mirror of https://github.com/docker/cli.git
Service cap-add/cap-drop: add special "RESET" value
This implements a special "RESET" value that can be used to reset the list of capabilities to add/drop when updating a service. Given the following service; | CapDrop | CapAdd | | -------------- | ------------- | | CAP_SOME_CAP | | When updating the service, and applying `--cap-drop RESET`, the "drop" list is reset to its default: | CapDrop | CapAdd | | -------------- | ------------- | | | | When updating the service, and applying `--cap-drop RESET`, combined with `--cap-add CAP_SOME_CAP` and `--cap-drop CAP_SOME_OTHER_CAP`: | CapDrop | CapAdd | | -------------- | ------------- | | CAP_FOO_CAP | CAP_SOME_CAP | Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
60abe967b5
commit
23660be600
|
@ -1409,9 +1409,17 @@ func updateCapabilities(flags *pflag.FlagSet, containerSpec *swarm.ContainerSpec
|
||||||
)
|
)
|
||||||
if flags.Changed(flagCapAdd) {
|
if flags.Changed(flagCapAdd) {
|
||||||
toAdd = opts.CapabilitiesMap(flags.Lookup(flagCapAdd).Value.(*opts.ListOpts).GetAll())
|
toAdd = opts.CapabilitiesMap(flags.Lookup(flagCapAdd).Value.(*opts.ListOpts).GetAll())
|
||||||
|
if toAdd[opts.ResetCapabilities] {
|
||||||
|
capAdd = make(map[string]bool)
|
||||||
|
delete(toAdd, opts.ResetCapabilities)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if flags.Changed(flagCapDrop) {
|
if flags.Changed(flagCapDrop) {
|
||||||
toDrop = opts.CapabilitiesMap(flags.Lookup(flagCapDrop).Value.(*opts.ListOpts).GetAll())
|
toDrop = opts.CapabilitiesMap(flags.Lookup(flagCapDrop).Value.(*opts.ListOpts).GetAll())
|
||||||
|
if toDrop[opts.ResetCapabilities] {
|
||||||
|
capDrop = make(map[string]bool)
|
||||||
|
delete(toDrop, opts.ResetCapabilities)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// First remove the capabilities to "drop" from the service's exiting
|
// First remove the capabilities to "drop" from the service's exiting
|
||||||
|
|
|
@ -1522,6 +1522,50 @@ func TestUpdateCaps(t *testing.T) {
|
||||||
expectedAdd: []string{"CAP_AAA", "CAP_BBB", "CAP_CCC", "CAP_DDD"},
|
expectedAdd: []string{"CAP_AAA", "CAP_BBB", "CAP_CCC", "CAP_DDD"},
|
||||||
expectedDrop: []string{"CAP_WWW", "CAP_XXX", "CAP_YYY", "CAP_ZZZ"},
|
expectedDrop: []string{"CAP_WWW", "CAP_XXX", "CAP_YYY", "CAP_ZZZ"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Reset capabilities",
|
||||||
|
flagAdd: []string{"RESET"},
|
||||||
|
flagDrop: []string{"RESET"},
|
||||||
|
spec: &swarm.ContainerSpec{
|
||||||
|
CapabilityAdd: []string{"CAP_AAA", "CAP_BBB", "CAP_CCC", "CAP_DDD"},
|
||||||
|
CapabilityDrop: []string{"CAP_WWW", "CAP_XXX", "CAP_YYY", "CAP_ZZZ"},
|
||||||
|
},
|
||||||
|
expectedAdd: nil,
|
||||||
|
expectedDrop: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Reset capabilities, and update after",
|
||||||
|
flagAdd: []string{"RESET", "CAP_ADD_ONE", "CAP_FOO"},
|
||||||
|
flagDrop: []string{"RESET", "CAP_DROP_ONE", "CAP_FOO"},
|
||||||
|
spec: &swarm.ContainerSpec{
|
||||||
|
CapabilityAdd: []string{"CAP_AAA", "CAP_BBB", "CAP_CCC", "CAP_DDD"},
|
||||||
|
CapabilityDrop: []string{"CAP_WWW", "CAP_XXX", "CAP_YYY", "CAP_ZZZ"},
|
||||||
|
},
|
||||||
|
expectedAdd: []string{"CAP_ADD_ONE", "CAP_FOO"},
|
||||||
|
expectedDrop: []string{"CAP_DROP_ONE"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Reset capabilities, and add ALL",
|
||||||
|
flagAdd: []string{"RESET", "ALL"},
|
||||||
|
flagDrop: []string{"RESET", "ALL"},
|
||||||
|
spec: &swarm.ContainerSpec{
|
||||||
|
CapabilityAdd: []string{"CAP_AAA", "CAP_BBB", "CAP_CCC", "CAP_DDD"},
|
||||||
|
CapabilityDrop: []string{"CAP_WWW", "CAP_XXX", "CAP_YYY", "CAP_ZZZ"},
|
||||||
|
},
|
||||||
|
expectedAdd: []string{"ALL"},
|
||||||
|
expectedDrop: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Add ALL and RESET",
|
||||||
|
flagAdd: []string{"ALL", "RESET"},
|
||||||
|
flagDrop: []string{"ALL", "RESET"},
|
||||||
|
spec: &swarm.ContainerSpec{
|
||||||
|
CapabilityAdd: []string{"CAP_AAA", "CAP_BBB", "CAP_CCC", "CAP_DDD"},
|
||||||
|
CapabilityDrop: []string{"CAP_WWW", "CAP_XXX", "CAP_YYY", "CAP_ZZZ"},
|
||||||
|
},
|
||||||
|
expectedAdd: []string{"ALL"},
|
||||||
|
expectedDrop: nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
|
|
@ -857,6 +857,7 @@ __docker_complete_capabilities_addable() {
|
||||||
CAP_SYS_TIME
|
CAP_SYS_TIME
|
||||||
CAP_SYS_TTY_CONFIG
|
CAP_SYS_TTY_CONFIG
|
||||||
CAP_WAKE_ALARM
|
CAP_WAKE_ALARM
|
||||||
|
RESET
|
||||||
)
|
)
|
||||||
COMPREPLY=( $( compgen -W "${capabilities[*]} ${capabilities[*]#CAP_}" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "${capabilities[*]} ${capabilities[*]#CAP_}" -- "$cur" ) )
|
||||||
}
|
}
|
||||||
|
@ -881,6 +882,7 @@ __docker_complete_capabilities_droppable() {
|
||||||
CAP_SETPCAP
|
CAP_SETPCAP
|
||||||
CAP_SETUID
|
CAP_SETUID
|
||||||
CAP_SYS_CHROOT
|
CAP_SYS_CHROOT
|
||||||
|
RESET
|
||||||
)
|
)
|
||||||
COMPREPLY=( $( compgen -W "${capabilities[*]} ${capabilities[*]#CAP_}" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "${capabilities[*]} ${capabilities[*]#CAP_}" -- "$cur" ) )
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,10 @@ import (
|
||||||
const (
|
const (
|
||||||
// AllCapabilities is a special value to add or drop all capabilities
|
// AllCapabilities is a special value to add or drop all capabilities
|
||||||
AllCapabilities = "ALL"
|
AllCapabilities = "ALL"
|
||||||
|
|
||||||
|
// ResetCapabilities is a special value to reset capabilities when updating.
|
||||||
|
// This value should only be used when updating, not used on "create".
|
||||||
|
ResetCapabilities = "RESET"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NormalizeCapability normalizes a capability by upper-casing, trimming white space
|
// NormalizeCapability normalizes a capability by upper-casing, trimming white space
|
||||||
|
@ -19,7 +23,7 @@ const (
|
||||||
// handled by the daemon.
|
// handled by the daemon.
|
||||||
func NormalizeCapability(cap string) string {
|
func NormalizeCapability(cap string) string {
|
||||||
cap = strings.ToUpper(strings.TrimSpace(cap))
|
cap = strings.ToUpper(strings.TrimSpace(cap))
|
||||||
if cap == AllCapabilities {
|
if cap == AllCapabilities || cap == ResetCapabilities {
|
||||||
return cap
|
return cap
|
||||||
}
|
}
|
||||||
if !strings.HasPrefix(cap, "CAP_") {
|
if !strings.HasPrefix(cap, "CAP_") {
|
||||||
|
@ -44,6 +48,9 @@ func CapabilitiesMap(caps []string) map[string]bool {
|
||||||
// lists are removed from the list of capabilities to drop. The special "ALL"
|
// lists are removed from the list of capabilities to drop. The special "ALL"
|
||||||
// capability is also taken into account.
|
// capability is also taken into account.
|
||||||
//
|
//
|
||||||
|
// Note that the special "RESET" value is only used when updating an existing
|
||||||
|
// service, and will be ignored.
|
||||||
|
//
|
||||||
// Duplicates are removed, and the resulting lists are sorted.
|
// Duplicates are removed, and the resulting lists are sorted.
|
||||||
func EffectiveCapAddCapDrop(add, drop []string) (capAdd, capDrop []string) {
|
func EffectiveCapAddCapDrop(add, drop []string) (capAdd, capDrop []string) {
|
||||||
var (
|
var (
|
||||||
|
@ -64,12 +71,16 @@ func EffectiveCapAddCapDrop(add, drop []string) (capAdd, capDrop []string) {
|
||||||
// Adding a capability takes precedence, so skip dropping
|
// Adding a capability takes precedence, so skip dropping
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if c != ResetCapabilities {
|
||||||
capDrop = append(capDrop, c)
|
capDrop = append(capDrop, c)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for c := range addCaps {
|
for c := range addCaps {
|
||||||
|
if c != ResetCapabilities {
|
||||||
capAdd = append(capAdd, c)
|
capAdd = append(capAdd, c)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sort.Strings(capAdd)
|
sort.Strings(capAdd)
|
||||||
sort.Strings(capDrop)
|
sort.Strings(capDrop)
|
||||||
|
|
Loading…
Reference in New Issue