func (m *model) validateStorage(allMachineIDs, allApplications, allUnits set.Strings) error { appsAndUnits := allApplications.Union(allUnits) allStorage := set.NewStrings() for i, storage := range m.Storages_.Storages_ { if err := storage.Validate(); err != nil { return errors.Annotatef(err, "storage[%d]", i) } allStorage.Add(storage.Tag().Id()) owner, err := storage.Owner() if err != nil { return errors.Wrap(err, errors.NotValidf("storage[%d] owner (%s)", i, owner)) } ownerID := owner.Id() if !appsAndUnits.Contains(ownerID) { return errors.NotValidf("storage[%d] owner (%s)", i, ownerID) } for _, unit := range storage.Attachments() { if !allUnits.Contains(unit.Id()) { return errors.NotValidf("storage[%d] attachment referencing unknown unit %q", i, unit) } } } allVolumes := set.NewStrings() for i, volume := range m.Volumes_.Volumes_ { if err := volume.Validate(); err != nil { return errors.Annotatef(err, "volume[%d]", i) } allVolumes.Add(volume.Tag().Id()) if storeID := volume.Storage().Id(); storeID != "" && !allStorage.Contains(storeID) { return errors.NotValidf("volume[%d] referencing unknown storage %q", i, storeID) } for j, attachment := range volume.Attachments() { if machineID := attachment.Machine().Id(); !allMachineIDs.Contains(machineID) { return errors.NotValidf("volume[%d].attachment[%d] referencing unknown machine %q", i, j, machineID) } } } for i, filesystem := range m.Filesystems_.Filesystems_ { if err := filesystem.Validate(); err != nil { return errors.Annotatef(err, "filesystem[%d]", i) } if storeID := filesystem.Storage().Id(); storeID != "" && !allStorage.Contains(storeID) { return errors.NotValidf("filesystem[%d] referencing unknown storage %q", i, storeID) } if volID := filesystem.Volume().Id(); volID != "" && !allVolumes.Contains(volID) { return errors.NotValidf("filesystem[%d] referencing unknown volume %q", i, volID) } for j, attachment := range filesystem.Attachments() { if machineID := attachment.Machine().Id(); !allMachineIDs.Contains(machineID) { return errors.NotValidf("filesystem[%d].attachment[%d] referencing unknown machine %q", i, j, machineID) } } } return nil }
func (stringSetSuite) TestUninitialized(c *gc.C) { var uninitialized set.Strings c.Assert(uninitialized.Size(), gc.Equals, 0) c.Assert(uninitialized.IsEmpty(), gc.Equals, true) // You can get values and sorted values from an unitialized set. AssertValues(c, uninitialized) // All contains checks are false c.Assert(uninitialized.Contains("foo"), gc.Equals, false) // Remove works on an uninitialized Strings uninitialized.Remove("foo") var other set.Strings // Union returns a new set that is empty but initialized. c.Assert(uninitialized.Union(other), gc.DeepEquals, set.NewStrings()) c.Assert(uninitialized.Intersection(other), gc.DeepEquals, set.NewStrings()) c.Assert(uninitialized.Difference(other), gc.DeepEquals, set.NewStrings()) other = set.NewStrings("foo", "bar") c.Assert(uninitialized.Union(other), gc.DeepEquals, other) c.Assert(uninitialized.Intersection(other), gc.DeepEquals, set.NewStrings()) c.Assert(uninitialized.Difference(other), gc.DeepEquals, set.NewStrings()) c.Assert(other.Union(uninitialized), gc.DeepEquals, other) c.Assert(other.Intersection(uninitialized), gc.DeepEquals, set.NewStrings()) c.Assert(other.Difference(uninitialized), gc.DeepEquals, other) // Once something is added, the set becomes initialized. uninitialized.Add("foo") AssertValues(c, uninitialized, "foo") }
// JaccardSets measure Jaccard distance of two sets func JaccardSets(a, b set.Strings) float64 { return float64(a.Intersection(b).Size()) / float64(a.Union(b).Size()) }