diff --git a/workflow/datastore.go b/workflow/datastore.go index c9a1487b..8a4cf613 100644 --- a/workflow/datastore.go +++ b/workflow/datastore.go @@ -3,25 +3,30 @@ package workflow import ( "database/sql" "fmt" + "strings" "time" kitlog "github.com/go-kit/kit/log" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" // postgres driver - "github.com/micromdm/micromdm/profile" "github.com/pkg/errors" ) // ErrExists is returned if a workflow already exists var ErrExists = errors.New("workflow already exists. each workflow must have a unique name") +// Profile is configuration profile in a workflow +type Profile struct { + UUID string +} + // Workflow describes a workflow that a device will execute // A workflow contains a list of configuration profiles, // Applications and included workflows type Workflow struct { - UUID string `json:"uuid" db:"workflow_uuid"` - Name string `json:"name" db:"name"` - Profiles []profile.Profile `json:"profiles"` + UUID string `json:"uuid" db:"workflow_uuid"` + Name string `json:"name" db:"name"` + Profiles []Profile `json:"profiles"` // Applications []application // IncludedWorkflows []Workflow } @@ -46,11 +51,64 @@ func (store pgStore) Create(wf *Workflow) (*Workflow, error) { if err != nil { return nil, errors.Wrap(err, "pgStore create workflow") } + + profiles := wf.Profiles + if err := store.addProfiles(wf.UUID, profiles...); err != nil { + return nil, err + } + return wf, nil } +func (store pgStore) addProfiles(wfUUID string, profiles ...Profile) error { + if len(profiles) == 0 { + return nil + } + + for _, prf := range profiles { + if err := store.addProfile(wfUUID, prf.UUID); err != nil { + return err + } + } + return nil +} + +func (store pgStore) addProfile(wfUUID, pfUUID string) error { + addProfileStmt := `INSERT INTO workflow_profile (workflow_uuid, profile_uuid) VALUES ($1, $2) + ON CONFLICT ON CONSTRAINT workflow_profile_pkey DO NOTHING;` + + _, err := store.Exec(addProfileStmt, wfUUID, pfUUID) + if err != nil { + return errors.Wrap(err, "pgStore add profile to workflow") + } + return nil +} + func (store pgStore) Workflows(params ...interface{}) ([]Workflow, error) { - panic("not implemented") + stmt := selectWorkflowsStmt + var where []string + for _, param := range params { + if f, ok := param.(whereer); ok { + where = append(where, f.where()) + } + } + + if len(where) != 0 { + whereFilter := strings.Join(where, ",") + stmt = fmt.Sprintf("%s WHERE %s", selectWorkflowsStmt, whereFilter) + } + + var workflows []Workflow + err := store.Select(&workflows, stmt) + if err != nil { + return nil, errors.Wrap(err, "pgStore Workflows") + } + return workflows, nil +} + +// whereer is for building args passed into Profiles() +type whereer interface { + where() string } // sql statements @@ -58,7 +116,7 @@ var ( createWorkflowStmt = `INSERT INTO workflows (name) VALUES ($1) ON CONFLICT ON CONSTRAINT workflows_name_key DO NOTHING RETURNING workflow_uuid;` - // selectProfilesStmt = `SELECT profile_uuid, identifier FROM profiles` + selectWorkflowsStmt = `SELECT workflow_uuid, name FROM profiles` ) //NewDB creates a Datastore diff --git a/workflow/datastore_test.go b/workflow/datastore_test.go index ea4bc446..587f7de9 100644 --- a/workflow/datastore_test.go +++ b/workflow/datastore_test.go @@ -1,14 +1,40 @@ package workflow import ( + "math/rand" "os" + "reflect" "testing" + "time" "github.com/go-kit/kit/log" "github.com/jmoiron/sqlx" - "github.com/micromdm/micromdm/profile" ) +func TestDatastoreWorkflows(t *testing.T) { + // ds := datastore(t) + defer teardown() +} + +func (wf Workflow) Generate(rand *rand.Rand, size int) reflect.Value { + name := randomString(16) + randomWorkflow := Workflow{ + Name: name, + } + + return reflect.ValueOf(randomWorkflow) +} + +func randomString(strlen int) string { + rand.Seed(time.Now().UTC().UnixNano()) + const chars = "abcdefghijklmnopqrstuvwxyz0123456789" + result := make([]byte, strlen) + for i := 0; i < strlen; i++ { + result[i] = chars[rand.Intn(len(chars))] + } + return string(result) +} + func TestNewDB(t *testing.T) { _ = datastore(t) defer teardown() @@ -49,18 +75,16 @@ func TestDatastoreCreate(t *testing.T) { { in: &Workflow{ Name: "exampleWorkflowWithProfiles", - Profiles: []profile.Profile{ - profile.Profile{ - PayloadIdentifier: "com.example.workflow.profile", - }, + Profiles: []Profile{ + Profile{UUID: "c7616875-df2d-4fe5-9c1e-0cb36c1ede8a"}, }, }, - shouldErr: false, + shouldErr: true, }, } for _, tt := range createTests { - wf, err := ds.Create(tt.in) + _, err := ds.Create(tt.in) if !tt.shouldErr { checkErr(err) } @@ -69,15 +93,7 @@ func TestDatastoreCreate(t *testing.T) { t.Fatal("expected", tt.testErr, "got", err) } } - profiles := tt.in.Profiles // check profiles - // this test should not pass... - if len(profiles) != 0 { - if len(profiles) != len(wf.Profiles) { - t.Log("checking profile count") - t.Fatal("expected", len(profiles), "got", len(wf.Profiles)) - } - } } }