]> ruderich.org/simon Gitweb - safcm/safcm.git/blobdiff - cmd/safcm/config/groups.go
Improve and add comments
[safcm/safcm.git] / cmd / safcm / config / groups.go
index 7f7cb3f635c346663808e69e990aac020040b345..a1dd83a0164267a0f24a351a74966fd108300323 100644 (file)
@@ -34,7 +34,7 @@ const (
        GroupRemoveSuffix     = GroupSpecialSeparator + "remove"
 )
 
-// Keep in sync with sync_info.go:infoGroupDetectedRegexp
+// Keep in sync with cmd/safcm/sync_info.go:infoGroupDetectedRegexp
 var groupNameRegexp = regexp.MustCompile(`^[a-z0-9_-]+$`)
 
 func LoadGroups(cfg *Config, hosts *Hosts) (map[string][]string, error) {
@@ -60,7 +60,9 @@ func LoadGroups(cfg *Config, hosts *Hosts) (map[string][]string, error) {
                                "%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)
@@ -84,6 +86,8 @@ func LoadGroups(cfg *Config, hosts *Hosts) (map[string][]string, error) {
                        if x == GroupAll {
                                continue
                        }
+                       // Don't validate against groupNameRegexp because
+                       // hosts have less strict restrictions.
                        if strings.Contains(x, GroupSpecialSeparator) {
                                return nil, fmt.Errorf(
                                        "%s member %q must not contain %q",
@@ -95,14 +99,14 @@ func LoadGroups(cfg *Config, hosts *Hosts) (map[string][]string, error) {
                        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)
                }
        }
 
        // Sanity check for global configuration
-       for _, x := range cfg.GroupOrder {
-               const errPrefix = "config.yaml: group_order:"
+       for _, x := range cfg.GroupPriority {
+               const errPrefix = "config.yaml: group_priority:"
 
                if x == GroupAll {
                        continue
@@ -186,3 +190,42 @@ func ResolveHostGroups(host string,
        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
+}