diff --git a/platform/blueprint/builtin/db.go b/platform/blueprint/builtin/db.go index 16833282..05884cab 100644 --- a/platform/blueprint/builtin/db.go +++ b/platform/blueprint/builtin/db.go @@ -47,17 +47,6 @@ func NewDB( return datastore, nil } -func (db *DB) Create(bp *blueprint.Blueprint) error { - _, err := db.BlueprintByName(bp.Name) - if err != nil && isNotFound(err) { - return errors.New("blueprint must have a unique name") - } else if err != nil { - return errors.Wrap(err, "creating blueprint") - } - - return db.Save(bp) -} - func (db *DB) List() ([]blueprint.Blueprint, error) { // TODO add filter/limit with ForEach var blueprints []blueprint.Blueprint @@ -109,22 +98,16 @@ func (db *DB) Save(bp *blueprint.Blueprint) error { if err != nil { return errors.Wrap(err, "marshalling blueprint") } - indexes := []string{bp.UUID, bp.Name} idxBucket := tx.Bucket([]byte(blueprintIndexBucket)) if idxBucket == nil { return fmt.Errorf("bucket %v not found!", idxBucket) } - for _, idx := range indexes { - if idx == "" { - continue - } - key := []byte(idx) - if err := idxBucket.Put(key, []byte(bp.UUID)); err != nil { - return errors.Wrap(err, "put blueprint idx to boltdb") - } + key := []byte(bp.Name) + if err := idxBucket.Put(key, []byte(bp.UUID)); err != nil { + return errors.Wrap(err, "put blueprint idx to boltdb") } - key := []byte(bp.UUID) + key = []byte(bp.UUID) if err := bkt.Put(key, bpproto); err != nil { return errors.Wrap(err, "put blueprint to boltdb") } @@ -192,10 +175,6 @@ func (db *DB) Delete(name string) error { if err != nil { return err } - err = i.Delete([]byte(bp.UUID)) - if err != nil { - return err - } err = b.Delete([]byte(bp.UUID)) if err != nil { return err diff --git a/platform/blueprint/builtin/db_test.go b/platform/blueprint/builtin/db_test.go new file mode 100644 index 00000000..3d15eab8 --- /dev/null +++ b/platform/blueprint/builtin/db_test.go @@ -0,0 +1,141 @@ +package builtin + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/boltdb/bolt" + "github.com/micromdm/micromdm/platform/blueprint" + profile "github.com/micromdm/micromdm/platform/profile/builtin" + user "github.com/micromdm/micromdm/platform/user/builtin" +) + +func TestSave(t *testing.T) { + db := setupDB(t) + bp := &blueprint.Blueprint{} + bp.ApplyAt = []string{"Enroll"} + + if err := db.Save(bp); err == nil { + t.Fatal("blueprints are required to have an UUID and Name") + } + + bp.UUID = "" + bp.Name = "blueprint" + if err := db.Save(bp); err == nil { + t.Fatal("blueprints are required to have an UUID") + } + + bp.UUID = "a-b-c-d" + bp.Name = "" + if err := db.Save(bp); err == nil { + t.Fatal("blueprints are required to have a Name") + } + + bp.UUID = "a-b-c-d" + bp.Name = "blueprint" + if err := db.Save(bp); err != nil { + t.Fatalf("saving blueprint in datastore: %s", err) + } + + bp.UUID = "e-f-g-h" + bp.Name = "blueprint" + if err := db.Save(bp); err == nil { + t.Fatal("blueprint names must be unique") + } + + bp.UUID = "e-f-g-h" + bp.Name = "blueprint2" + if err := db.Save(bp); err != nil { + t.Fatalf("saving blueprint2 in datastore: %s", err) + } + + byName, err := db.BlueprintByName("blueprint") + if err != nil { + t.Fatalf("getting blueprint by Name: %s", err) + } + if byName == nil || byName.UUID != "a-b-c-d" { + t.Fatalf("have %s, want %s", byName.UUID, "a-b-c-d") + } + + byApplyAt, err := db.BlueprintsByApplyAt("Enroll") + if err != nil { + t.Fatalf("getting blueprint by ApplyAt: %s", err) + } + if len(byApplyAt) != 2 { + t.Fatalf("multiple blueprints not saved correctly") + } +} + +func TestList(t *testing.T) { + db := setupDB(t) + bp1 := &blueprint.Blueprint{ + UUID: "a-b-c-d", + Name: "blueprint-1", + } + bp2 := &blueprint.Blueprint{ + UUID: "e-f-g-h", + Name: "blueprint-2", + } + + if err := db.Save(bp1); err != nil { + t.Fatalf("saving blueprint-1 to datastore: %s", err) + } + + if err := db.Save(bp2); err != nil { + t.Fatalf("saving blueprint-2 to datastore: %s", err) + } + + bps, err := db.List() + if err != nil { + t.Fatalf("listing blueprints: %s", err) + } + if len(bps) != 2 { + t.Fatalf("expected %d, found %d", 2, len(bps)) + } +} + +func TestDelete(t *testing.T) { + db := setupDB(t) + bp1 := &blueprint.Blueprint{ + UUID: "a-b-c-d", + Name: "blueprint", + } + + if err := db.Save(bp1); err != nil { + t.Fatalf("saving blueprint to datastore: %s", err) + } + + if err := db.Delete("blueprint"); err != nil { + t.Fatalf("deleting blueprint in datastore: %s", err) + } + + _, err := db.BlueprintByName("blueprint") + if err == nil { + t.Fatalf("expected blueprint to be deleted: %s", err) + } +} + +func setupDB(t *testing.T) *DB { + f, _ := ioutil.TempFile("", "bolt-") + f.Close() + os.Remove(f.Name()) + + db, err := bolt.Open(f.Name(), 0777, nil) + if err != nil { + t.Fatalf("couldn't open bolt, err %s\n", err) + } + profileDB, err := profile.NewDB(db) + if err != nil { + t.Fatalf("couldn't create profile DB, err %s\n", err) + } + userDB, err := user.NewDB(db) + if err != nil { + t.Fatalf("couldn't create user DB, err %s\n", err) + } + blueprintDB, err := NewDB(db, profileDB, userDB) + if err != nil { + t.Fatalf("couldn't create blueprint DB, err %s\n", err) + } + return blueprintDB +}