Skip to content

Commit

Permalink
Replace service "Capabilities" w/ add/drop API
Browse files Browse the repository at this point in the history
After dicussing with maintainers, it was decided putting the burden of
providing the full cap list on the client is not a good design.
Instead we decided to follow along with the container API and use cap
add/drop.

This brings in the changes already merged into swarmkit.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
  • Loading branch information
cpuguy83 committed Jul 27, 2020
1 parent baa3212 commit 24f173a
Show file tree
Hide file tree
Showing 15 changed files with 86 additions and 230 deletions.
3 changes: 0 additions & 3 deletions api/server/router/container/container_routes.go
Expand Up @@ -489,9 +489,6 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
// Ignore KernelMemoryTCP because it was added in API 1.40.
hostConfig.KernelMemoryTCP = 0

// Ignore Capabilities because it was added in API 1.40.
hostConfig.Capabilities = nil

// Older clients (API < 1.40) expects the default to be shareable, make them happy
if hostConfig.IpcMode.IsEmpty() {
hostConfig.IpcMode = container.IpcMode("shareable")
Expand Down
3 changes: 2 additions & 1 deletion api/server/router/swarm/helpers.go
Expand Up @@ -99,7 +99,8 @@ func adjustForAPIVersion(cliVersion string, service *swarm.ServiceSpec) {
if service.TaskTemplate.ContainerSpec != nil {
// Capabilities for docker swarm services weren't
// supported before API version 1.41
service.TaskTemplate.ContainerSpec.Capabilities = nil
service.TaskTemplate.ContainerSpec.CapabilityAdd = nil
service.TaskTemplate.ContainerSpec.CapabilityDrop = nil
}
if service.TaskTemplate.Resources != nil && service.TaskTemplate.Resources.Limits != nil {
// Limits.Pids not supported before API version 1.41
Expand Down
24 changes: 12 additions & 12 deletions api/swagger.yaml
Expand Up @@ -906,15 +906,6 @@ definitions:
$ref: "#/definitions/Mount"

# Applicable to UNIX platforms
Capabilities:
type: "array"
description: |
A list of kernel capabilities to be available for container (this
overrides the default set).
Conflicts with options 'CapAdd' and 'CapDrop'"
items:
type: "string"
CapAdd:
type: "array"
description: |
Expand Down Expand Up @@ -3276,18 +3267,27 @@ definitions:
additionalProperties:
type: "string"
# This option is not used by Windows containers
Capabilities:
CapabilityAdd:
type: "array"
description: |
A list of kernel capabilities to be available for container (this
overrides the default set).
A list of kernel capabilities to add to the default set
for the container.
items:
type: "string"
example:
- "CAP_NET_RAW"
- "CAP_SYS_ADMIN"
- "CAP_SYS_CHROOT"
- "CAP_SYSLOG"
CapabilityDrop:
type: "array"
description: |
A list of kernel capabilities to drop from the default set
for the container.
items:
type: "string"
example:
- "CAP_NET_RAW"
NetworkAttachmentSpec:
description: |
Read-only spec type for non-swarm containers attached to swarm overlay
Expand Down
1 change: 0 additions & 1 deletion api/types/container/host_config.go
Expand Up @@ -403,7 +403,6 @@ type HostConfig struct {
// Applicable to UNIX platforms
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container
Capabilities []string `json:"Capabilities"` // List of kernel capabilities to be available for container (this overrides the default set)
CgroupnsMode CgroupnsMode // Cgroup namespace mode to use for the container
DNS []string `json:"Dns"` // List of DNS server to lookup
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
Expand Down
15 changes: 8 additions & 7 deletions api/types/swarm/container.go
Expand Up @@ -67,11 +67,12 @@ type ContainerSpec struct {
// The format of extra hosts on swarmkit is specified in:
// http://man7.org/linux/man-pages/man5/hosts.5.html
// IP_address canonical_hostname [aliases...]
Hosts []string `json:",omitempty"`
DNSConfig *DNSConfig `json:",omitempty"`
Secrets []*SecretReference `json:",omitempty"`
Configs []*ConfigReference `json:",omitempty"`
Isolation container.Isolation `json:",omitempty"`
Sysctls map[string]string `json:",omitempty"`
Capabilities []string `json:",omitempty"`
Hosts []string `json:",omitempty"`
DNSConfig *DNSConfig `json:",omitempty"`
Secrets []*SecretReference `json:",omitempty"`
Configs []*ConfigReference `json:",omitempty"`
Isolation container.Isolation `json:",omitempty"`
Sysctls map[string]string `json:",omitempty"`
CapabilityAdd []string `json:",omitempty"`
CapabilityDrop []string `json:",omitempty"`
}
80 changes: 41 additions & 39 deletions daemon/cluster/convert/container.go
Expand Up @@ -18,26 +18,27 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) *types.ContainerSpec {
return nil
}
containerSpec := &types.ContainerSpec{
Image: c.Image,
Labels: c.Labels,
Command: c.Command,
Args: c.Args,
Hostname: c.Hostname,
Env: c.Env,
Dir: c.Dir,
User: c.User,
Groups: c.Groups,
StopSignal: c.StopSignal,
TTY: c.TTY,
OpenStdin: c.OpenStdin,
ReadOnly: c.ReadOnly,
Hosts: c.Hosts,
Secrets: secretReferencesFromGRPC(c.Secrets),
Configs: configReferencesFromGRPC(c.Configs),
Isolation: IsolationFromGRPC(c.Isolation),
Init: initFromGRPC(c.Init),
Sysctls: c.Sysctls,
Capabilities: c.Capabilities,
Image: c.Image,
Labels: c.Labels,
Command: c.Command,
Args: c.Args,
Hostname: c.Hostname,
Env: c.Env,
Dir: c.Dir,
User: c.User,
Groups: c.Groups,
StopSignal: c.StopSignal,
TTY: c.TTY,
OpenStdin: c.OpenStdin,
ReadOnly: c.ReadOnly,
Hosts: c.Hosts,
Secrets: secretReferencesFromGRPC(c.Secrets),
Configs: configReferencesFromGRPC(c.Configs),
Isolation: IsolationFromGRPC(c.Isolation),
Init: initFromGRPC(c.Init),
Sysctls: c.Sysctls,
CapabilityAdd: c.CapabilityAdd,
CapabilityDrop: c.CapabilityDrop,
}

if c.DNSConfig != nil {
Expand Down Expand Up @@ -246,25 +247,26 @@ func configReferencesFromGRPC(sr []*swarmapi.ConfigReference) []*types.ConfigRef

func containerToGRPC(c *types.ContainerSpec) (*swarmapi.ContainerSpec, error) {
containerSpec := &swarmapi.ContainerSpec{
Image: c.Image,
Labels: c.Labels,
Command: c.Command,
Args: c.Args,
Hostname: c.Hostname,
Env: c.Env,
Dir: c.Dir,
User: c.User,
Groups: c.Groups,
StopSignal: c.StopSignal,
TTY: c.TTY,
OpenStdin: c.OpenStdin,
ReadOnly: c.ReadOnly,
Hosts: c.Hosts,
Secrets: secretReferencesToGRPC(c.Secrets),
Isolation: isolationToGRPC(c.Isolation),
Init: initToGRPC(c.Init),
Sysctls: c.Sysctls,
Capabilities: c.Capabilities,
Image: c.Image,
Labels: c.Labels,
Command: c.Command,
Args: c.Args,
Hostname: c.Hostname,
Env: c.Env,
Dir: c.Dir,
User: c.User,
Groups: c.Groups,
StopSignal: c.StopSignal,
TTY: c.TTY,
OpenStdin: c.OpenStdin,
ReadOnly: c.ReadOnly,
Hosts: c.Hosts,
Secrets: secretReferencesToGRPC(c.Secrets),
Isolation: isolationToGRPC(c.Isolation),
Init: initToGRPC(c.Init),
Sysctls: c.Sysctls,
CapabilityAdd: c.CapabilityAdd,
CapabilityDrop: c.CapabilityDrop,
}

if c.DNSConfig != nil {
Expand Down
3 changes: 2 additions & 1 deletion daemon/cluster/executor/container/container.go
Expand Up @@ -360,7 +360,8 @@ func (c *containerConfig) hostConfig() *enginecontainer.HostConfig {
Isolation: c.isolation(),
Init: c.init(),
Sysctls: c.spec().Sysctls,
Capabilities: c.spec().Capabilities,
CapAdd: c.spec().CapabilityAdd,
CapDrop: c.spec().CapabilityDrop,
}

if c.spec().DNSConfig != nil {
Expand Down
9 changes: 0 additions & 9 deletions daemon/container.go
Expand Up @@ -305,21 +305,12 @@ func validateHostConfig(hostConfig *containertypes.HostConfig, platform string)
}

func validateCapabilities(hostConfig *containertypes.HostConfig) error {
if len(hostConfig.CapAdd) > 0 && hostConfig.Capabilities != nil {
return errdefs.InvalidParameter(errors.Errorf("conflicting options: Capabilities and CapAdd"))
}
if len(hostConfig.CapDrop) > 0 && hostConfig.Capabilities != nil {
return errdefs.InvalidParameter(errors.Errorf("conflicting options: Capabilities and CapDrop"))
}
if _, err := caps.NormalizeLegacyCapabilities(hostConfig.CapAdd); err != nil {
return errors.Wrap(err, "invalid CapAdd")
}
if _, err := caps.NormalizeLegacyCapabilities(hostConfig.CapDrop); err != nil {
return errors.Wrap(err, "invalid CapDrop")
}
if err := caps.ValidateCapabilities(hostConfig.Capabilities); err != nil {
return errors.Wrap(err, "invalid Capabilities")
}
// TODO consider returning warnings if "Privileged" is combined with Capabilities, CapAdd and/or CapDrop
return nil
}
Expand Down
1 change: 0 additions & 1 deletion daemon/oci_linux.go
Expand Up @@ -162,7 +162,6 @@ func WithCapabilities(c *container.Container) coci.SpecOpts {
caps.DefaultCapabilities(),
c.HostConfig.CapAdd,
c.HostConfig.CapDrop,
c.HostConfig.Capabilities,
c.HostConfig.Privileged,
)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion daemon/oci_windows.go
Expand Up @@ -390,7 +390,7 @@ func (daemon *Daemon) createSpecLinuxFields(c *container.Container, s *specs.Spe
// Note these are against the UVM.
setResourcesInSpec(c, s, true) // LCOW is Hyper-V only

capabilities, err := caps.TweakCapabilities(caps.DefaultCapabilities(), c.HostConfig.CapAdd, c.HostConfig.CapDrop, c.HostConfig.Capabilities, c.HostConfig.Privileged)
capabilities, err := caps.TweakCapabilities(caps.DefaultCapabilities(), c.HostConfig.CapAdd, c.HostConfig.CapDrop, c.HostConfig.Privileged)
if err != nil {
return fmt.Errorf("linux spec capabilities: %v", err)
}
Expand Down
17 changes: 6 additions & 11 deletions docs/api/version-history.md
Expand Up @@ -28,12 +28,12 @@ keywords: "API, Docker, rcli, REST, documentation"
* The `filter` (singular) query parameter, which was deprecated in favor of the
`filters` option in Docker 1.13, has now been removed from the `GET /images/json`
endpoint. The parameter remains available when using API version 1.40 or below.
* `GET /services` now returns `Capabilities` as part of the `ContainerSpec`.
* `GET /services/{id}` now returns `Capabilities` as part of the `ContainerSpec`.
* `POST /services/create` now accepts `Capabilities` as part of the `ContainerSpec`.
* `POST /services/{id}/update` now accepts `Capabilities` as part of the `ContainerSpec`.
* `GET /tasks` now returns `Capabilities` as part of the `ContainerSpec`.
* `GET /tasks/{id}` now returns `Capabilities` as part of the `ContainerSpec`.
* `GET /services` now returns `CappAdd` and `CapDrop` as part of the `ContainerSpec`.
* `GET /services/{id}` now returns `CapAdd` and `CapDrop` as part of the `ContainerSpec`.
* `POST /services/create` now accepts `CapAdd` and `CapDrop` as part of the `ContainerSpec`.
* `POST /services/{id}/update` now accepts `CapAdd` and `CapDrop` as part of the `ContainerSpec`.
* `GET /tasks` now returns `CapAdd` and `CapDrop` as part of the `ContainerSpec`.
* `GET /tasks/{id}` now returns `CapAdd` and `CapDrop` as part of the `ContainerSpec`.
* `GET /services` now returns `Pids` in `TaskTemplate.Resources.Limits`.
* `GET /services/{id}` now returns `Pids` in `TaskTemplate.Resources.Limits`.
* `POST /services/create` now accepts `Pids` in `TaskTemplate.Resources.Limits`.
Expand Down Expand Up @@ -135,11 +135,6 @@ keywords: "API, Docker, rcli, REST, documentation"
* `GET /service/{id}` now returns `MaxReplicas` as part of the `Placement`.
* `POST /service/create` and `POST /services/(id or name)/update` now take the field `MaxReplicas`
as part of the service `Placement`, allowing to specify maximum replicas per node for the service.
* `GET /containers` now returns `Capabilities` field as part of the `HostConfig`.
* `GET /containers/{id}/json` now returns a `Capabilities` field as part of the `HostConfig`.
* `POST /containers/create` now takes a `Capabilities` field to set the list of
kernel capabilities to be available for the container (this overrides the default
set).
* `POST /containers/create` on Linux now creates a container with `HostConfig.IpcMode=private`
by default, if IpcMode is not explicitly specified. The per-daemon default can be changed
back to `shareable` by using `DefaultIpcMode` daemon configuration parameter.
Expand Down

0 comments on commit 24f173a

Please sign in to comment.