@@ -43,6 +43,17 @@ const (
4343 MergeNumericIDOnly
4444)
4545
46+ //SkipMethod is the third argument for EntityDefinition.Merge().
47+ type SkipMethod uint
48+
49+ const (
50+ //SkipDisabled does not skip any fields during merging.
51+ SkipDisabled SkipMethod = iota
52+ //SkipEnabled skips fields where one of the definitions instructs us to do so
53+ //(causing the other side's attribute to win).
54+ SkipEnabled
55+ )
56+
4657//EntityDefinition contains data from a definition file that describes an entity
4758//(a user account or group). Definitions can also be obtained by scanning the
4859//user/group databases.
@@ -76,7 +87,7 @@ type EntityDefinition interface {
7687 //
7788 //The merge `method` tells which attributes may be merged. Possible values
7889 //are MergeWhereCompatible, MergeEmptyOnly and MergeNumericIDOnly.
79- Merge (other EntityDefinition , method MergeMethod ) (EntityDefinition , []error )
90+ Merge (other EntityDefinition , mMethod MergeMethod , sMethod SkipMethod ) (EntityDefinition , []error )
8091 //Apply provisions this entity. The argument indicates the currently
8192 //provisioned state. The argument's concrete type must match the callee.
8293 Apply (provisioned EntityDefinition ) error
@@ -116,14 +127,15 @@ type GroupDefinition struct {
116127
117128//UserDefinition represents a UNIX user account (as registered in /etc/passwd).
118129type UserDefinition struct {
119- Name string `toml:"name"` //the user name (the first field in /etc/passwd)
120- Comment string `toml:"comment,omitempty"` //the full name (sometimes also called "comment"; the fifth field in /etc/passwd)
121- UID * int `toml:"uid,omitzero"` //the user ID (the third field in /etc/passwd), or nil if no specific UID is enforced
122- System bool `toml:"system,omitempty"` //whether the group is a system group (this influences the GID selection if gid = 0)
123- Home string `toml:"home,omitempty"` //path to the user's home directory (or empty to use the default)
124- Group string `toml:"group,omitempty"` //the name of the user's initial login group (or empty to use the default)
125- Groups []string `toml:"groups,omitempty"` //the names of supplementary groups which the user is also a member of
126- Shell string `toml:"shell,omitempty"` //path to the user's login shell (or empty to use the default)
130+ Name string `toml:"name"` //the user name (the first field in /etc/passwd)
131+ Comment string `toml:"comment,omitempty"` //the full name (sometimes also called "comment"; the fifth field in /etc/passwd)
132+ UID * int `toml:"uid,omitzero"` //the user ID (the third field in /etc/passwd), or nil if no specific UID is enforced
133+ System bool `toml:"system,omitempty"` //whether the group is a system group (this influences the GID selection if gid = 0)
134+ Home string `toml:"home,omitempty"` //path to the user's home directory (or empty to use the default)
135+ Group string `toml:"group,omitempty"` //the name of the user's initial login group (or empty to use the default)
136+ Groups []string `toml:"groups,omitempty"` //the names of supplementary groups which the user is also a member of
137+ Shell string `toml:"shell,omitempty"` //path to the user's login shell (or empty to use the default)
138+ SkipBaseGroups bool `toml:"skipBaseGroups,omitempty"` //whether to consider supplementary groups in the base image during merging
127139}
128140
129141//TypeName implements the EntityDefinition interface.
@@ -172,7 +184,11 @@ func (u *UserDefinition) Attributes() string {
172184 attrs = append (attrs , "login group: " + u .Group )
173185 }
174186 if len (u .Groups ) > 0 {
175- attrs = append (attrs , "groups: " + strings .Join (u .Groups , "," ))
187+ if u .SkipBaseGroups {
188+ attrs = append (attrs , "exact groups: " + strings .Join (u .Groups , "," ))
189+ } else {
190+ attrs = append (attrs , "groups: " + strings .Join (u .Groups , "," ))
191+ }
176192 }
177193 if u .Shell != "" {
178194 attrs = append (attrs , "login shell: " + u .Shell )
@@ -194,9 +210,12 @@ func (g *GroupDefinition) WithSerializableState(callback func(EntityDefinition))
194210
195211//WithSerializableState implements the EntityDefinition interface.
196212func (u * UserDefinition ) WithSerializableState (callback func (EntityDefinition )) {
197- //we don't want to serialize the `system` attribute in diffs etc.
213+ //we don't want to serialize the `system` and `skipBaseGroups` attributes in diffs etc.
198214 system := u .System
215+ skipBaseGroups := u .SkipBaseGroups
199216 u .System = false
217+ u .SkipBaseGroups = false
200218 callback (u )
201219 u .System = system
220+ u .SkipBaseGroups = skipBaseGroups
202221}
0 commit comments