"%s conflict with pre-defined group %q",
errPrefix, name)
}
- if hosts.Map[name] != nil {
+ if hosts.Map[name] != nil ||
+ hosts.Map[strings.TrimSuffix(name,
+ GroupRemoveSuffix)] != nil {
return nil, fmt.Errorf(
"%s conflict with existing host",
errPrefix)
if hosts.Map[x] != nil || groups[x] != nil {
continue
}
- return nil, fmt.Errorf("%s group %q not found",
+ return nil, fmt.Errorf("%s member %q not found",
errPrefix, x)
}
}
sort.Strings(res)
return res, nil
}
+
+// TransitivelyDetectedGroups returns all groups which depend on "detected"
+// groups, either directly or by depending on groups which transitively depend
+// on "detected" groups.
+func TransitivelyDetectedGroups(groups map[string][]string) []string {
+ work := make(map[string][]string)
+ for k, v := range groups {
+ work[k] = v
+ }
+
+ // Mark all groups which contain "detected" groups as long as new
+ // (transitive) "detected" groups are found.
+ detected := make(map[string]bool)
+ for {
+ change := false
+ for group, members := range work {
+ for _, x := range members {
+ if !detected[x] && !strings.HasPrefix(x,
+ GroupDetectedPrefix) {
+ continue
+ }
+ detected[strings.TrimSuffix(group,
+ GroupRemoveSuffix)] = true
+ delete(work, group)
+ change = true
+ }
+ }
+ if !change {
+ break
+ }
+ }
+
+ var res []string
+ for x := range detected {
+ res = append(res, x)
+ }
+ sort.Strings(res)
+ return res
+}