Refactor CreateContainer.

This commit is contained in:
Random-Liu 2016-04-14 10:36:13 -07:00
parent da07fa9dd5
commit ba4a5ed39e
11 changed files with 111 additions and 126 deletions

View File

@ -60,7 +60,7 @@ const (
type DockerInterface interface { type DockerInterface interface {
ListContainers(options dockertypes.ContainerListOptions) ([]dockertypes.Container, error) ListContainers(options dockertypes.ContainerListOptions) ([]dockertypes.Container, error)
InspectContainer(id string) (*dockertypes.ContainerJSON, error) InspectContainer(id string) (*dockertypes.ContainerJSON, error)
CreateContainer(docker.CreateContainerOptions) (*docker.Container, error) CreateContainer(dockertypes.ContainerCreateConfig) (*dockertypes.ContainerCreateResponse, error)
StartContainer(id string, hostConfig *docker.HostConfig) error StartContainer(id string, hostConfig *docker.HostConfig) error
StopContainer(id string, timeout uint) error StopContainer(id string, timeout uint) error
RemoveContainer(opts docker.RemoveContainerOptions) error RemoveContainer(opts docker.RemoveContainerOptions) error

View File

@ -28,6 +28,7 @@ import (
"github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/pkg/jsonmessage"
dockertypes "github.com/docker/engine-api/types" dockertypes "github.com/docker/engine-api/types"
dockernat "github.com/docker/go-connections/nat"
docker "github.com/fsouza/go-dockerclient" docker "github.com/fsouza/go-dockerclient"
cadvisorapi "github.com/google/cadvisor/info/v1" cadvisorapi "github.com/google/cadvisor/info/v1"
"k8s.io/kubernetes/cmd/kubelet/app/options" "k8s.io/kubernetes/cmd/kubelet/app/options"
@ -744,37 +745,37 @@ func TestMakePortsAndBindings(t *testing.T) {
} }
// Construct expected bindings // Construct expected bindings
expectPortBindings := map[string][]docker.PortBinding{ expectPortBindings := map[string][]dockernat.PortBinding{
"80/tcp": { "80/tcp": {
docker.PortBinding{ dockernat.PortBinding{
HostPort: "8080", HostPort: "8080",
HostIP: "127.0.0.1", HostIP: "127.0.0.1",
}, },
}, },
"443/tcp": { "443/tcp": {
docker.PortBinding{ dockernat.PortBinding{
HostPort: "443", HostPort: "443",
HostIP: "", HostIP: "",
}, },
docker.PortBinding{ dockernat.PortBinding{
HostPort: "446", HostPort: "446",
HostIP: "", HostIP: "",
}, },
}, },
"443/udp": { "443/udp": {
docker.PortBinding{ dockernat.PortBinding{
HostPort: "446", HostPort: "446",
HostIP: "", HostIP: "",
}, },
}, },
"444/udp": { "444/udp": {
docker.PortBinding{ dockernat.PortBinding{
HostPort: "444", HostPort: "444",
HostIP: "", HostIP: "",
}, },
}, },
"445/tcp": { "445/tcp": {
docker.PortBinding{ dockernat.PortBinding{
HostPort: "445", HostPort: "445",
HostIP: "", HostIP: "",
}, },

View File

@ -305,7 +305,7 @@ func (f *FakeDockerClient) normalSleep(mean, stdDev, cutOffMillis int) {
// CreateContainer is a test-spy implementation of DockerInterface.CreateContainer. // CreateContainer is a test-spy implementation of DockerInterface.CreateContainer.
// It adds an entry "create" to the internal method call record. // It adds an entry "create" to the internal method call record.
func (f *FakeDockerClient) CreateContainer(c docker.CreateContainerOptions) (*docker.Container, error) { func (f *FakeDockerClient) CreateContainer(c dockertypes.ContainerCreateConfig) (*dockertypes.ContainerCreateResponse, error) {
f.Lock() f.Lock()
defer f.Unlock() defer f.Unlock()
f.called = append(f.called, "create") f.called = append(f.called, "create")
@ -315,28 +315,21 @@ func (f *FakeDockerClient) CreateContainer(c docker.CreateContainerOptions) (*do
// This is not a very good fake. We'll just add this container's name to the list. // This is not a very good fake. We'll just add this container's name to the list.
// Docker likes to add a '/', so copy that behavior. // Docker likes to add a '/', so copy that behavior.
name := "/" + c.Name name := "/" + c.Name
id := name
f.Created = append(f.Created, name) f.Created = append(f.Created, name)
// The newest container should be in front, because we assume so in GetPodStatus() // The newest container should be in front, because we assume so in GetPodStatus()
f.RunningContainerList = append([]dockertypes.Container{ f.RunningContainerList = append([]dockertypes.Container{
{ID: name, Names: []string{name}, Image: c.Config.Image, Labels: c.Config.Labels}, {ID: name, Names: []string{name}, Image: c.Config.Image, Labels: c.Config.Labels},
}, f.RunningContainerList...) }, f.RunningContainerList...)
// TODO(random-liu): Remove this convertion when we refactor CreateContainer f.ContainerMap[name] = convertFakeContainer(&FakeContainer{ID: id, Name: name, Config: c.Config, HostConfig: c.HostConfig})
config := &dockercontainer.Config{}
convertType(c.Config, config)
hostConfig := &dockercontainer.HostConfig{}
convertType(c.HostConfig, hostConfig)
container := convertFakeContainer(&FakeContainer{ID: name, Name: name, Config: config, HostConfig: hostConfig})
containerCopy := *container
f.ContainerMap[name] = &containerCopy
f.normalSleep(100, 25, 25) f.normalSleep(100, 25, 25)
// TODO(random-liu): This will be refactored soon, we could do this because only the returned id is used. return &dockertypes.ContainerCreateResponse{ID: id}, nil
return &docker.Container{ID: container.ID}, nil
} }
// StartContainer is a test-spy implementation of DockerInterface.StartContainer. // StartContainer is a test-spy implementation of DockerInterface.StartContainer.
// It adds an entry "start" to the internal method call record. // It adds an entry "start" to the internal method call record.
// The HostConfig at StartContainer will be deprecated from docker 1.10. Now in // The HostConfig at StartContainer will be deprecated from docker 1.10. Now in
// docker manager the HostConfig is set when CreateContainer(). // docker manager the HostConfig is set when ContainerCreate().
// TODO(random-liu): Remove the HostConfig here when it is completely removed in // TODO(random-liu): Remove the HostConfig here when it is completely removed in
// docker 1.12. // docker 1.12.
func (f *FakeDockerClient) StartContainer(id string, _ *docker.HostConfig) error { func (f *FakeDockerClient) StartContainer(id string, _ *docker.HostConfig) error {
@ -543,3 +536,8 @@ func (f *FakeDockerPuller) IsImagePresent(name string) (bool, error) {
} }
return false, nil return false, nil
} }
// dockerTimestampToString converts the timestamp to string
func dockerTimestampToString(t time.Time) string {
return t.Format(time.RFC3339Nano)
}

View File

@ -67,7 +67,7 @@ func (in instrumentedDockerInterface) InspectContainer(id string) (*dockertypes.
return out, err return out, err
} }
func (in instrumentedDockerInterface) CreateContainer(opts docker.CreateContainerOptions) (*docker.Container, error) { func (in instrumentedDockerInterface) CreateContainer(opts dockertypes.ContainerCreateConfig) (*dockertypes.ContainerCreateResponse, error) {
const operation = "create_container" const operation = "create_container"
defer recordOperation(operation, time.Now()) defer recordOperation(operation, time.Now())

View File

@ -29,7 +29,6 @@ import (
"github.com/docker/docker/pkg/stdcopy" "github.com/docker/docker/pkg/stdcopy"
dockerapi "github.com/docker/engine-api/client" dockerapi "github.com/docker/engine-api/client"
dockertypes "github.com/docker/engine-api/types" dockertypes "github.com/docker/engine-api/types"
dockercontainer "github.com/docker/engine-api/types/container"
dockerfilters "github.com/docker/engine-api/types/filters" dockerfilters "github.com/docker/engine-api/types/filters"
docker "github.com/fsouza/go-dockerclient" docker "github.com/fsouza/go-dockerclient"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -125,24 +124,12 @@ func (d *kubeDockerClient) InspectContainer(id string) (*dockertypes.ContainerJS
return &containerJSON, nil return &containerJSON, nil
} }
func (d *kubeDockerClient) CreateContainer(opts docker.CreateContainerOptions) (*docker.Container, error) { func (d *kubeDockerClient) CreateContainer(opts dockertypes.ContainerCreateConfig) (*dockertypes.ContainerCreateResponse, error) {
config := &dockercontainer.Config{} createResp, err := d.client.ContainerCreate(getDefaultContext(), opts.Config, opts.HostConfig, opts.NetworkingConfig, opts.Name)
if err := convertType(opts.Config, config); err != nil {
return nil, err
}
hostConfig := &dockercontainer.HostConfig{}
if err := convertType(opts.HostConfig, hostConfig); err != nil {
return nil, err
}
resp, err := d.client.ContainerCreate(getDefaultContext(), config, hostConfig, nil, opts.Name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
container := &docker.Container{} return &createResp, nil
if err := convertType(&resp, container); err != nil {
return nil, err
}
return container, nil
} }
// TODO(random-liu): The HostConfig at container start is deprecated, will remove this in the following refactoring. // TODO(random-liu): The HostConfig at container start is deprecated, will remove this in the following refactoring.
@ -384,11 +371,6 @@ func parseDockerTimestamp(s string) (time.Time, error) {
return time.Parse(time.RFC3339Nano, s) return time.Parse(time.RFC3339Nano, s)
} }
// dockerTimestampToString converts the timestamp to string
func dockerTimestampToString(t time.Time) string {
return t.Format(time.RFC3339Nano)
}
// containerNotFoundError is the error returned by InspectContainer when container not found. We // containerNotFoundError is the error returned by InspectContainer when container not found. We
// add this error type for testability. We don't use the original error returned by engine-api // add this error type for testability. We don't use the original error returned by engine-api
// because dockertypes.containerNotFoundError is private, we can't create and inject it in our test. // because dockertypes.containerNotFoundError is private, we can't create and inject it in our test.

View File

@ -33,6 +33,9 @@ import (
"github.com/coreos/go-semver/semver" "github.com/coreos/go-semver/semver"
dockertypes "github.com/docker/engine-api/types" dockertypes "github.com/docker/engine-api/types"
dockercontainer "github.com/docker/engine-api/types/container"
dockerstrslice "github.com/docker/engine-api/types/strslice"
dockernat "github.com/docker/go-connections/nat"
docker "github.com/fsouza/go-dockerclient" docker "github.com/fsouza/go-dockerclient"
"github.com/golang/glog" "github.com/golang/glog"
cadvisorapi "github.com/google/cadvisor/info/v1" cadvisorapi "github.com/google/cadvisor/info/v1"
@ -477,9 +480,9 @@ func makeMountBindings(mounts []kubecontainer.Mount, podHasSELinuxLabel bool) (r
return return
} }
func makePortsAndBindings(portMappings []kubecontainer.PortMapping) (map[docker.Port]struct{}, map[docker.Port][]docker.PortBinding) { func makePortsAndBindings(portMappings []kubecontainer.PortMapping) (map[dockernat.Port]struct{}, map[dockernat.Port][]dockernat.PortBinding) {
exposedPorts := map[docker.Port]struct{}{} exposedPorts := map[dockernat.Port]struct{}{}
portBindings := map[docker.Port][]docker.PortBinding{} portBindings := map[dockernat.Port][]dockernat.PortBinding{}
for _, port := range portMappings { for _, port := range portMappings {
exteriorPort := port.HostPort exteriorPort := port.HostPort
if exteriorPort == 0 { if exteriorPort == 0 {
@ -500,10 +503,10 @@ func makePortsAndBindings(portMappings []kubecontainer.PortMapping) (map[docker.
protocol = "/tcp" protocol = "/tcp"
} }
dockerPort := docker.Port(strconv.Itoa(interiorPort) + protocol) dockerPort := dockernat.Port(strconv.Itoa(interiorPort) + protocol)
exposedPorts[dockerPort] = struct{}{} exposedPorts[dockerPort] = struct{}{}
hostBinding := docker.PortBinding{ hostBinding := dockernat.PortBinding{
HostPort: strconv.Itoa(exteriorPort), HostPort: strconv.Itoa(exteriorPort),
HostIP: port.HostIP, HostIP: port.HostIP,
} }
@ -514,7 +517,7 @@ func makePortsAndBindings(portMappings []kubecontainer.PortMapping) (map[docker.
portBindings[dockerPort] = append(existedBindings, hostBinding) portBindings[dockerPort] = append(existedBindings, hostBinding)
} else { } else {
// Otherwise, it's fresh new port binding // Otherwise, it's fresh new port binding
portBindings[dockerPort] = []docker.PortBinding{ portBindings[dockerPort] = []dockernat.PortBinding{
hostBinding, hostBinding,
} }
} }
@ -599,17 +602,18 @@ func (dm *DockerManager) runContainer(
} }
} }
hc := &docker.HostConfig{ hc := &dockercontainer.HostConfig{
Binds: binds, Binds: binds,
NetworkMode: netMode, NetworkMode: dockercontainer.NetworkMode(netMode),
IpcMode: ipcMode, IpcMode: dockercontainer.IpcMode(ipcMode),
UTSMode: utsMode, UTSMode: dockercontainer.UTSMode(utsMode),
PidMode: pidMode, PidMode: dockercontainer.PidMode(pidMode),
ReadonlyRootfs: readOnlyRootFilesystem(container), ReadonlyRootfs: readOnlyRootFilesystem(container),
// Memory and CPU are set here for newer versions of Docker (1.6+). Resources: dockercontainer.Resources{
Memory: memoryLimit, Memory: memoryLimit,
MemorySwap: -1, MemorySwap: -1,
CPUShares: cpuShares, CPUShares: cpuShares,
},
SecurityOpt: securityOpts, SecurityOpt: securityOpts,
} }
@ -633,15 +637,11 @@ func (dm *DockerManager) runContainer(
hc.CgroupParent = opts.CgroupParent hc.CgroupParent = opts.CgroupParent
} }
dockerOpts := docker.CreateContainerOptions{ dockerOpts := dockertypes.ContainerCreateConfig{
Name: containerName, Name: containerName,
Config: &docker.Config{ Config: &dockercontainer.Config{
Env: makeEnvList(opts.Envs), Env: makeEnvList(opts.Envs),
Image: container.Image, Image: container.Image,
// Memory and CPU are set here for older versions of Docker (pre-1.6).
Memory: memoryLimit,
MemorySwap: -1,
CPUShares: cpuShares,
WorkingDir: container.WorkingDir, WorkingDir: container.WorkingDir,
Labels: labels, Labels: labels,
// Interactive containers: // Interactive containers:
@ -657,36 +657,39 @@ func (dm *DockerManager) runContainer(
setInfraContainerNetworkConfig(pod, netMode, opts, dockerOpts) setInfraContainerNetworkConfig(pod, netMode, opts, dockerOpts)
} }
setEntrypointAndCommand(container, opts, &dockerOpts) setEntrypointAndCommand(container, opts, dockerOpts)
glog.V(3).Infof("Container %v/%v/%v: setting entrypoint \"%v\" and command \"%v\"", pod.Namespace, pod.Name, container.Name, dockerOpts.Config.Entrypoint, dockerOpts.Config.Cmd) glog.V(3).Infof("Container %v/%v/%v: setting entrypoint \"%v\" and command \"%v\"", pod.Namespace, pod.Name, container.Name, dockerOpts.Config.Entrypoint, dockerOpts.Config.Cmd)
securityContextProvider := securitycontext.NewSimpleSecurityContextProvider() securityContextProvider := securitycontext.NewSimpleSecurityContextProvider()
securityContextProvider.ModifyContainerConfig(pod, container, dockerOpts.Config) securityContextProvider.ModifyContainerConfig(pod, container, dockerOpts.Config)
securityContextProvider.ModifyHostConfig(pod, container, dockerOpts.HostConfig) securityContextProvider.ModifyHostConfig(pod, container, dockerOpts.HostConfig)
dockerContainer, err := dm.client.CreateContainer(dockerOpts) createResp, err := dm.client.CreateContainer(dockerOpts)
if err != nil { if err != nil {
dm.recorder.Eventf(ref, api.EventTypeWarning, kubecontainer.FailedToCreateContainer, "Failed to create docker container with error: %v", err) dm.recorder.Eventf(ref, api.EventTypeWarning, kubecontainer.FailedToCreateContainer, "Failed to create docker container with error: %v", err)
return kubecontainer.ContainerID{}, err return kubecontainer.ContainerID{}, err
} }
dm.recorder.Eventf(ref, api.EventTypeNormal, kubecontainer.CreatedContainer, "Created container with docker id %v", utilstrings.ShortenString(dockerContainer.ID, 12)) if len(createResp.Warnings) != 0 {
glog.V(2).Infof("Container %q of pod %q created with warnings: %v", container.Name, format.Pod(pod), createResp.Warnings)
}
dm.recorder.Eventf(ref, api.EventTypeNormal, kubecontainer.CreatedContainer, "Created container with docker id %v", utilstrings.ShortenString(createResp.ID, 12))
if err = dm.client.StartContainer(dockerContainer.ID, nil); err != nil { if err = dm.client.StartContainer(createResp.ID, nil); err != nil {
dm.recorder.Eventf(ref, api.EventTypeWarning, kubecontainer.FailedToStartContainer, dm.recorder.Eventf(ref, api.EventTypeWarning, kubecontainer.FailedToStartContainer,
"Failed to start container with docker id %v with error: %v", utilstrings.ShortenString(dockerContainer.ID, 12), err) "Failed to start container with docker id %v with error: %v", utilstrings.ShortenString(createResp.ID, 12), err)
return kubecontainer.ContainerID{}, err return kubecontainer.ContainerID{}, err
} }
dm.recorder.Eventf(ref, api.EventTypeNormal, kubecontainer.StartedContainer, "Started container with docker id %v", utilstrings.ShortenString(dockerContainer.ID, 12)) dm.recorder.Eventf(ref, api.EventTypeNormal, kubecontainer.StartedContainer, "Started container with docker id %v", utilstrings.ShortenString(createResp.ID, 12))
return kubecontainer.DockerID(dockerContainer.ID).ContainerID(), nil return kubecontainer.DockerID(createResp.ID).ContainerID(), nil
} }
// setInfraContainerNetworkConfig sets the network configuration for the infra-container. We only set network configuration for infra-container, all // setInfraContainerNetworkConfig sets the network configuration for the infra-container. We only set network configuration for infra-container, all
// the user containers will share the same network namespace with infra-container. // the user containers will share the same network namespace with infra-container.
func setInfraContainerNetworkConfig(pod *api.Pod, netMode string, opts *kubecontainer.RunContainerOptions, dockerOpts docker.CreateContainerOptions) { func setInfraContainerNetworkConfig(pod *api.Pod, netMode string, opts *kubecontainer.RunContainerOptions, dockerOpts dockertypes.ContainerCreateConfig) {
exposedPorts, portBindings := makePortsAndBindings(opts.PortMappings) exposedPorts, portBindings := makePortsAndBindings(opts.PortMappings)
dockerOpts.Config.ExposedPorts = exposedPorts dockerOpts.Config.ExposedPorts = exposedPorts
dockerOpts.HostConfig.PortBindings = portBindings dockerOpts.HostConfig.PortBindings = dockernat.PortMap(portBindings)
if netMode != namespaceModeHost { if netMode != namespaceModeHost {
dockerOpts.Config.Hostname = opts.Hostname dockerOpts.Config.Hostname = opts.Hostname
@ -699,11 +702,11 @@ func setInfraContainerNetworkConfig(pod *api.Pod, netMode string, opts *kubecont
} }
} }
func setEntrypointAndCommand(container *api.Container, opts *kubecontainer.RunContainerOptions, dockerOpts *docker.CreateContainerOptions) { func setEntrypointAndCommand(container *api.Container, opts *kubecontainer.RunContainerOptions, dockerOpts dockertypes.ContainerCreateConfig) {
command, args := kubecontainer.ExpandContainerCommandAndArgs(container, opts.Envs) command, args := kubecontainer.ExpandContainerCommandAndArgs(container, opts.Envs)
dockerOpts.Config.Entrypoint = command dockerOpts.Config.Entrypoint = dockerstrslice.StrSlice(command)
dockerOpts.Config.Cmd = args dockerOpts.Config.Cmd = dockerstrslice.StrSlice(args)
} }
// A helper function to get the KubeletContainerName and hash from a docker // A helper function to get the KubeletContainerName and hash from a docker

View File

@ -31,6 +31,7 @@ import (
dockertypes "github.com/docker/engine-api/types" dockertypes "github.com/docker/engine-api/types"
dockercontainer "github.com/docker/engine-api/types/container" dockercontainer "github.com/docker/engine-api/types/container"
dockerstrslice "github.com/docker/engine-api/types/strslice"
docker "github.com/fsouza/go-dockerclient" docker "github.com/fsouza/go-dockerclient"
cadvisorapi "github.com/google/cadvisor/info/v1" cadvisorapi "github.com/google/cadvisor/info/v1"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -164,13 +165,13 @@ func TestSetEntrypointAndCommand(t *testing.T) {
name string name string
container *api.Container container *api.Container
envs []kubecontainer.EnvVar envs []kubecontainer.EnvVar
expected *docker.CreateContainerOptions expected *dockertypes.ContainerCreateConfig
}{ }{
{ {
name: "none", name: "none",
container: &api.Container{}, container: &api.Container{},
expected: &docker.CreateContainerOptions{ expected: &dockertypes.ContainerCreateConfig{
Config: &docker.Config{}, Config: &dockercontainer.Config{},
}, },
}, },
{ {
@ -178,9 +179,9 @@ func TestSetEntrypointAndCommand(t *testing.T) {
container: &api.Container{ container: &api.Container{
Command: []string{"foo", "bar"}, Command: []string{"foo", "bar"},
}, },
expected: &docker.CreateContainerOptions{ expected: &dockertypes.ContainerCreateConfig{
Config: &docker.Config{ Config: &dockercontainer.Config{
Entrypoint: []string{"foo", "bar"}, Entrypoint: dockerstrslice.StrSlice([]string{"foo", "bar"}),
}, },
}, },
}, },
@ -199,9 +200,9 @@ func TestSetEntrypointAndCommand(t *testing.T) {
Value: "boo", Value: "boo",
}, },
}, },
expected: &docker.CreateContainerOptions{ expected: &dockertypes.ContainerCreateConfig{
Config: &docker.Config{ Config: &dockercontainer.Config{
Entrypoint: []string{"foo", "zoo", "boo"}, Entrypoint: dockerstrslice.StrSlice([]string{"foo", "zoo", "boo"}),
}, },
}, },
}, },
@ -210,8 +211,8 @@ func TestSetEntrypointAndCommand(t *testing.T) {
container: &api.Container{ container: &api.Container{
Args: []string{"foo", "bar"}, Args: []string{"foo", "bar"},
}, },
expected: &docker.CreateContainerOptions{ expected: &dockertypes.ContainerCreateConfig{
Config: &docker.Config{ Config: &dockercontainer.Config{
Cmd: []string{"foo", "bar"}, Cmd: []string{"foo", "bar"},
}, },
}, },
@ -231,9 +232,9 @@ func TestSetEntrypointAndCommand(t *testing.T) {
Value: "trap", Value: "trap",
}, },
}, },
expected: &docker.CreateContainerOptions{ expected: &dockertypes.ContainerCreateConfig{
Config: &docker.Config{ Config: &dockercontainer.Config{
Cmd: []string{"zap", "hap", "trap"}, Cmd: dockerstrslice.StrSlice([]string{"zap", "hap", "trap"}),
}, },
}, },
}, },
@ -243,10 +244,10 @@ func TestSetEntrypointAndCommand(t *testing.T) {
Command: []string{"foo"}, Command: []string{"foo"},
Args: []string{"bar", "baz"}, Args: []string{"bar", "baz"},
}, },
expected: &docker.CreateContainerOptions{ expected: &dockertypes.ContainerCreateConfig{
Config: &docker.Config{ Config: &dockercontainer.Config{
Entrypoint: []string{"foo"}, Entrypoint: dockerstrslice.StrSlice([]string{"foo"}),
Cmd: []string{"bar", "baz"}, Cmd: dockerstrslice.StrSlice([]string{"bar", "baz"}),
}, },
}, },
}, },
@ -270,10 +271,10 @@ func TestSetEntrypointAndCommand(t *testing.T) {
Value: "roo", Value: "roo",
}, },
}, },
expected: &docker.CreateContainerOptions{ expected: &dockertypes.ContainerCreateConfig{
Config: &docker.Config{ Config: &dockercontainer.Config{
Entrypoint: []string{"boo--zoo", "foo", "roo"}, Entrypoint: dockerstrslice.StrSlice([]string{"boo--zoo", "foo", "roo"}),
Cmd: []string{"foo", "zoo", "boo"}, Cmd: dockerstrslice.StrSlice([]string{"foo", "zoo", "boo"}),
}, },
}, },
}, },
@ -284,8 +285,8 @@ func TestSetEntrypointAndCommand(t *testing.T) {
Envs: tc.envs, Envs: tc.envs,
} }
actualOpts := &docker.CreateContainerOptions{ actualOpts := dockertypes.ContainerCreateConfig{
Config: &docker.Config{}, Config: &dockercontainer.Config{},
} }
setEntrypointAndCommand(tc.container, opts, actualOpts) setEntrypointAndCommand(tc.container, opts, actualOpts)

View File

@ -19,7 +19,7 @@ package securitycontext
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
docker "github.com/fsouza/go-dockerclient" dockercontainer "github.com/docker/engine-api/types/container"
) )
// ValidSecurityContextWithContainerDefaults creates a valid security context provider based on // ValidSecurityContextWithContainerDefaults creates a valid security context provider based on
@ -39,7 +39,7 @@ func NewFakeSecurityContextProvider() SecurityContextProvider {
type FakeSecurityContextProvider struct{} type FakeSecurityContextProvider struct{}
func (p FakeSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, container *api.Container, config *docker.Config) { func (p FakeSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, container *api.Container, config *dockercontainer.Config) {
} }
func (p FakeSecurityContextProvider) ModifyHostConfig(pod *api.Pod, container *api.Container, hostConfig *docker.HostConfig) { func (p FakeSecurityContextProvider) ModifyHostConfig(pod *api.Pod, container *api.Container, hostConfig *dockercontainer.HostConfig) {
} }

View File

@ -23,7 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/kubelet/leaky" "k8s.io/kubernetes/pkg/kubelet/leaky"
docker "github.com/fsouza/go-dockerclient" dockercontainer "github.com/docker/engine-api/types/container"
) )
// NewSimpleSecurityContextProvider creates a new SimpleSecurityContextProvider. // NewSimpleSecurityContextProvider creates a new SimpleSecurityContextProvider.
@ -37,7 +37,7 @@ type SimpleSecurityContextProvider struct{}
// ModifyContainerConfig is called before the Docker createContainer call. // ModifyContainerConfig is called before the Docker createContainer call.
// The security context provider can make changes to the Config with which // The security context provider can make changes to the Config with which
// the container is created. // the container is created.
func (p SimpleSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, container *api.Container, config *docker.Config) { func (p SimpleSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, container *api.Container, config *dockercontainer.Config) {
effectiveSC := DetermineEffectiveSecurityContext(pod, container) effectiveSC := DetermineEffectiveSecurityContext(pod, container)
if effectiveSC == nil { if effectiveSC == nil {
return return
@ -50,7 +50,7 @@ func (p SimpleSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, conta
// ModifyHostConfig is called before the Docker runContainer call. // ModifyHostConfig is called before the Docker runContainer call.
// The security context provider can make changes to the HostConfig, affecting // The security context provider can make changes to the HostConfig, affecting
// security options, whether the container is privileged, volume binds, etc. // security options, whether the container is privileged, volume binds, etc.
func (p SimpleSecurityContextProvider) ModifyHostConfig(pod *api.Pod, container *api.Container, hostConfig *docker.HostConfig) { func (p SimpleSecurityContextProvider) ModifyHostConfig(pod *api.Pod, container *api.Container, hostConfig *dockercontainer.HostConfig) {
// Apply pod security context // Apply pod security context
if container.Name != leaky.PodInfraContainerName && pod.Spec.SecurityContext != nil { if container.Name != leaky.PodInfraContainerName && pod.Spec.SecurityContext != nil {
// TODO: We skip application of supplemental groups to the // TODO: We skip application of supplemental groups to the

View File

@ -22,7 +22,7 @@ import (
"strconv" "strconv"
"testing" "testing"
docker "github.com/fsouza/go-dockerclient" dockercontainer "github.com/docker/engine-api/types/container"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
apitesting "k8s.io/kubernetes/pkg/api/testing" apitesting "k8s.io/kubernetes/pkg/api/testing"
) )
@ -35,28 +35,28 @@ func TestModifyContainerConfig(t *testing.T) {
name string name string
podSc *api.PodSecurityContext podSc *api.PodSecurityContext
sc *api.SecurityContext sc *api.SecurityContext
expected *docker.Config expected *dockercontainer.Config
}{ }{
{ {
name: "container.SecurityContext.RunAsUser set", name: "container.SecurityContext.RunAsUser set",
sc: &api.SecurityContext{ sc: &api.SecurityContext{
RunAsUser: &uid, RunAsUser: &uid,
}, },
expected: &docker.Config{ expected: &dockercontainer.Config{
User: strconv.FormatInt(uid, 10), User: strconv.FormatInt(uid, 10),
}, },
}, },
{ {
name: "no RunAsUser value set", name: "no RunAsUser value set",
sc: &api.SecurityContext{}, sc: &api.SecurityContext{},
expected: &docker.Config{}, expected: &dockercontainer.Config{},
}, },
{ {
name: "pod.Spec.SecurityContext.RunAsUser set", name: "pod.Spec.SecurityContext.RunAsUser set",
podSc: &api.PodSecurityContext{ podSc: &api.PodSecurityContext{
RunAsUser: &uid, RunAsUser: &uid,
}, },
expected: &docker.Config{ expected: &dockercontainer.Config{
User: strconv.FormatInt(uid, 10), User: strconv.FormatInt(uid, 10),
}, },
}, },
@ -68,7 +68,7 @@ func TestModifyContainerConfig(t *testing.T) {
sc: &api.SecurityContext{ sc: &api.SecurityContext{
RunAsUser: &overrideUid, RunAsUser: &overrideUid,
}, },
expected: &docker.Config{ expected: &dockercontainer.Config{
User: strconv.FormatInt(overrideUid, 10), User: strconv.FormatInt(overrideUid, 10),
}, },
}, },
@ -79,7 +79,7 @@ func TestModifyContainerConfig(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
pod := &api.Pod{Spec: api.PodSpec{SecurityContext: tc.podSc}} pod := &api.Pod{Spec: api.PodSpec{SecurityContext: tc.podSc}}
dummyContainer.SecurityContext = tc.sc dummyContainer.SecurityContext = tc.sc
dockerCfg := &docker.Config{} dockerCfg := &dockercontainer.Config{}
provider.ModifyContainerConfig(pod, dummyContainer, dockerCfg) provider.ModifyContainerConfig(pod, dummyContainer, dockerCfg)
@ -93,16 +93,16 @@ func TestModifyHostConfig(t *testing.T) {
priv := true priv := true
setPrivSC := &api.SecurityContext{} setPrivSC := &api.SecurityContext{}
setPrivSC.Privileged = &priv setPrivSC.Privileged = &priv
setPrivHC := &docker.HostConfig{ setPrivHC := &dockercontainer.HostConfig{
Privileged: true, Privileged: true,
} }
setCapsHC := &docker.HostConfig{ setCapsHC := &dockercontainer.HostConfig{
CapAdd: []string{"addCapA", "addCapB"}, CapAdd: []string{"addCapA", "addCapB"},
CapDrop: []string{"dropCapA", "dropCapB"}, CapDrop: []string{"dropCapA", "dropCapB"},
} }
setSELinuxHC := &docker.HostConfig{} setSELinuxHC := &dockercontainer.HostConfig{}
setSELinuxHC.SecurityOpt = []string{ setSELinuxHC.SecurityOpt = []string{
fmt.Sprintf("%s:%s", dockerLabelUser, "user"), fmt.Sprintf("%s:%s", dockerLabelUser, "user"),
fmt.Sprintf("%s:%s", dockerLabelRole, "role"), fmt.Sprintf("%s:%s", dockerLabelRole, "role"),
@ -117,7 +117,7 @@ func TestModifyHostConfig(t *testing.T) {
name string name string
podSc *api.PodSecurityContext podSc *api.PodSecurityContext
sc *api.SecurityContext sc *api.SecurityContext
expected *docker.HostConfig expected *dockercontainer.HostConfig
}{ }{
{ {
name: "fully set container.SecurityContext", name: "fully set container.SecurityContext",
@ -164,7 +164,7 @@ func TestModifyHostConfig(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
pod := &api.Pod{Spec: api.PodSpec{SecurityContext: tc.podSc}} pod := &api.Pod{Spec: api.PodSpec{SecurityContext: tc.podSc}}
dummyContainer.SecurityContext = tc.sc dummyContainer.SecurityContext = tc.sc
dockerCfg := &docker.HostConfig{} dockerCfg := &dockercontainer.HostConfig{}
provider.ModifyHostConfig(pod, dummyContainer, dockerCfg) provider.ModifyHostConfig(pod, dummyContainer, dockerCfg)
@ -187,7 +187,7 @@ func TestModifyHostConfigPodSecurityContext(t *testing.T) {
testCases := map[string]struct { testCases := map[string]struct {
securityContext *api.PodSecurityContext securityContext *api.PodSecurityContext
expected *docker.HostConfig expected *dockercontainer.HostConfig
}{ }{
"nil": { "nil": {
securityContext: nil, securityContext: nil,
@ -219,7 +219,7 @@ func TestModifyHostConfigPodSecurityContext(t *testing.T) {
for k, v := range testCases { for k, v := range testCases {
dummyPod.Spec.SecurityContext = v.securityContext dummyPod.Spec.SecurityContext = v.securityContext
dockerCfg := &docker.HostConfig{} dockerCfg := &dockercontainer.HostConfig{}
provider.ModifyHostConfig(dummyPod, dummyContainer, dockerCfg) provider.ModifyHostConfig(dummyPod, dummyContainer, dockerCfg)
if !reflect.DeepEqual(v.expected, dockerCfg) { if !reflect.DeepEqual(v.expected, dockerCfg) {
t.Errorf("unexpected modification of host config for %s. Expected: %#v Got: %#v", k, v.expected, dockerCfg) t.Errorf("unexpected modification of host config for %s. Expected: %#v Got: %#v", k, v.expected, dockerCfg)
@ -301,8 +301,8 @@ func inputSELinuxOptions() *api.SELinuxOptions {
} }
} }
func fullValidHostConfig() *docker.HostConfig { func fullValidHostConfig() *dockercontainer.HostConfig {
return &docker.HostConfig{ return &dockercontainer.HostConfig{
Privileged: true, Privileged: true,
CapAdd: []string{"addCapA", "addCapB"}, CapAdd: []string{"addCapA", "addCapB"},
CapDrop: []string{"dropCapA", "dropCapB"}, CapDrop: []string{"dropCapA", "dropCapB"},

View File

@ -19,21 +19,21 @@ package securitycontext
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
docker "github.com/fsouza/go-dockerclient" dockercontainer "github.com/docker/engine-api/types/container"
) )
type SecurityContextProvider interface { type SecurityContextProvider interface {
// ModifyContainerConfig is called before the Docker createContainer call. // ModifyContainerConfig is called before the Docker createContainer call.
// The security context provider can make changes to the Config with which // The security context provider can make changes to the Config with which
// the container is created. // the container is created.
ModifyContainerConfig(pod *api.Pod, container *api.Container, config *docker.Config) ModifyContainerConfig(pod *api.Pod, container *api.Container, config *dockercontainer.Config)
// ModifyHostConfig is called before the Docker createContainer call. // ModifyHostConfig is called before the Docker createContainer call.
// The security context provider can make changes to the HostConfig, affecting // The security context provider can make changes to the HostConfig, affecting
// security options, whether the container is privileged, volume binds, etc. // security options, whether the container is privileged, volume binds, etc.
// An error is returned if it's not possible to secure the container as requested // An error is returned if it's not possible to secure the container as requested
// with a security context. // with a security context.
ModifyHostConfig(pod *api.Pod, container *api.Container, hostConfig *docker.HostConfig) ModifyHostConfig(pod *api.Pod, container *api.Container, hostConfig *dockercontainer.HostConfig)
} }
const ( const (