diff --git a/pkg/kubelet/container/kuberuntime.go b/pkg/kubelet/container/kuberuntime.go index 41b660f8ae1..1e031681718 100644 --- a/pkg/kubelet/container/kuberuntime.go +++ b/pkg/kubelet/container/kuberuntime.go @@ -22,9 +22,8 @@ import ( runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" ) -// RuntimeService interface defines the interfaces that should be implemented -// by a container runtime. -// Thread safety is required from implementations of this interface. +// RuntimeService interface should be implemented by a container runtime. +// The methods should be thread-safe. type RuntimeService interface { // Version returns the runtime name, runtime version and runtime API version Version(apiVersion string) (*runtimeApi.VersionResponse, error) @@ -33,40 +32,39 @@ type RuntimeService interface { CreatePodSandbox(config *runtimeApi.PodSandboxConfig) (string, error) // StopPodSandbox stops the sandbox. If there are any running containers in the // sandbox, they should be force terminated. - StopPodSandbox(podSandBoxID string) error - // DeletePodSandbox deletes the sandbox. If there are any running containers in the - // sandbox, they should be force deleted. - DeletePodSandbox(podSandBoxID string) error + StopPodSandbox(podSandboxID string) error + // DeletePodSandbox deletes the sandbox. If there are running containers in the + // sandbox, they should be forcibly deleted. + DeletePodSandbox(podSandboxID string) error // PodSandboxStatus returns the Status of the PodSandbox. - PodSandboxStatus(podSandBoxID string) (*runtimeApi.PodSandboxStatus, error) - // ListPodSandbox returns a list of SandBox. + PodSandboxStatus(podSandboxID string) (*runtimeApi.PodSandboxStatus, error) + // ListPodSandbox returns a list of Sandbox. ListPodSandbox(filter *runtimeApi.PodSandboxFilter) ([]*runtimeApi.PodSandbox, error) - // CreateContainer creates a new container in specified PodSandbox - CreateContainer(podSandBoxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) + // CreateContainer creates a new container in specified PodSandbox. + CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) // StartContainer starts the container. StartContainer(rawContainerID string) error // StopContainer stops a running container with a grace period (i.e., timeout). StopContainer(rawContainerID string, timeout int64) error - // RemoveContainer removes the container. If the container is running, the container - // should be force removed. + // RemoveContainer removes the container. RemoveContainer(rawContainerID string) error // ListContainers lists all containers by filters. ListContainers(filter *runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) - // ContainerStatus returns the container status. + // ContainerStatus returns the status of the container. ContainerStatus(rawContainerID string) (*runtimeApi.ContainerStatus, error) - // Exec execute a command in the container. + // Exec executes a command in the container. Exec(rawContainerID string, cmd []string, tty bool, stdin io.Reader, stdout, stderr io.WriteCloser) error } -// ImageManagerService interface defines the interfaces that should be implemented -// by a container image manager. -// Thread safety is required from implementations of this interface. +// ImageManagerService interface should be implemented by a container image +// manager. +// The methods should be thread-safe. type ImageManagerService interface { - // ListImages lists existing images. + // ListImages lists the existing images. ListImages(filter *runtimeApi.ImageFilter) ([]*runtimeApi.Image, error) // ImageStatus returns the status of the image. ImageStatus(image *runtimeApi.ImageSpec) (*runtimeApi.Image, error) - // PullImage pulls a image with authentication config. + // PullImage pulls an image with the authentication config. PullImage(image *runtimeApi.ImageSpec, auth *runtimeApi.AuthConfig) error // RemoveImage removes the image. RemoveImage(image *runtimeApi.ImageSpec) error diff --git a/pkg/kubelet/dockershim/convert.go b/pkg/kubelet/dockershim/convert.go new file mode 100644 index 00000000000..156171bcb93 --- /dev/null +++ b/pkg/kubelet/dockershim/convert.go @@ -0,0 +1,91 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockershim + +import ( + "fmt" + "strings" + + dockertypes "github.com/docker/engine-api/types" + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" +) + +// This file contains helper functions to convert docker API types to runtime +// API types, or vice versa. + +const ( + // Status of a container returned by docker ListContainers + statusRunningPrefix = "Up" + statusCreatedPrefix = "Created" + statusExitedPrefix = "Exited" +) + +func toRuntimeAPIImage(image *dockertypes.Image) (*runtimeApi.Image, error) { + if image == nil { + return nil, fmt.Errorf("unable to convert a nil pointer to a runtime API image") + } + + size := uint64(image.VirtualSize) + return &runtimeApi.Image{ + Id: &image.ID, + RepoTags: image.RepoTags, + RepoDigests: image.RepoDigests, + Size_: &size, + }, nil +} + +func toRuntimeAPIContainer(c *dockertypes.Container) *runtimeApi.Container { + state := toRuntimeAPIContainerState(c.Status) + return &runtimeApi.Container{ + Id: &c.ID, + Name: &c.Names[0], + Image: &runtimeApi.ImageSpec{Image: &c.Image}, + ImageRef: &c.ImageID, + State: &state, + Labels: c.Labels, + } +} + +func toDockerContainerStatus(state runtimeApi.ContainerState) string { + switch state { + case runtimeApi.ContainerState_CREATED: + return "created" + case runtimeApi.ContainerState_RUNNING: + return "running" + case runtimeApi.ContainerState_EXITED: + return "exited" + case runtimeApi.ContainerState_UNKNOWN: + fallthrough + default: + return "unknown" + } +} + +func toRuntimeAPIContainerState(state string) runtimeApi.ContainerState { + // Parse the state string in dockertypes.Container. This could break when + // we upgrade docker. + switch { + case strings.HasPrefix(state, statusRunningPrefix): + return runtimeApi.ContainerState_RUNNING + case strings.HasPrefix(state, statusExitedPrefix): + return runtimeApi.ContainerState_EXITED + case strings.HasPrefix(state, statusCreatedPrefix): + return runtimeApi.ContainerState_CREATED + default: + return runtimeApi.ContainerState_UNKNOWN + } +} diff --git a/pkg/kubelet/dockershim/convert_test.go b/pkg/kubelet/dockershim/convert_test.go new file mode 100644 index 00000000000..57f614bec0b --- /dev/null +++ b/pkg/kubelet/dockershim/convert_test.go @@ -0,0 +1,41 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockershim + +import ( + "testing" + + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" +) + +func TestConvertDockerStatusToRuntimeAPIState(t *testing.T) { + testCases := []struct { + input string + expected runtimeApi.ContainerState + }{ + {input: "Up 5 hours", expected: runtimeApi.ContainerState_RUNNING}, + {input: "Exited (0) 2 hours ago", expected: runtimeApi.ContainerState_EXITED}, + {input: "Created", expected: runtimeApi.ContainerState_CREATED}, + {input: "Random string", expected: runtimeApi.ContainerState_UNKNOWN}, + } + + for i, test := range testCases { + if actual := toRuntimeAPIContainerState(test.input); actual != test.expected { + t.Errorf("Test[%d]: expected %q, got %q", i, test.expected, actual) + } + } +} diff --git a/pkg/kubelet/dockershim/doc.go b/pkg/kubelet/dockershim/doc.go new file mode 100644 index 00000000000..619271d3467 --- /dev/null +++ b/pkg/kubelet/dockershim/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Docker integration using pkg/kubelet/api/v1alpha1/runtime/api.pb.go. +package dockershim diff --git a/pkg/kubelet/dockershim/docker_container.go b/pkg/kubelet/dockershim/docker_container.go new file mode 100644 index 00000000000..d7ca149d2b6 --- /dev/null +++ b/pkg/kubelet/dockershim/docker_container.go @@ -0,0 +1,203 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockershim + +import ( + "fmt" + "io" + + dockertypes "github.com/docker/engine-api/types" + dockercontainer "github.com/docker/engine-api/types/container" + dockerfilters "github.com/docker/engine-api/types/filters" + dockerstrslice "github.com/docker/engine-api/types/strslice" + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" +) + +// ListContainers lists all containers matching the filter. +func (ds *dockerService) ListContainers(filter *runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) { + opts := dockertypes.ContainerListOptions{All: true} + + opts.Filter = dockerfilters.NewArgs() + if filter != nil { + if filter.Name != nil { + opts.Filter.Add("name", filter.GetName()) + } + if filter.Id != nil { + opts.Filter.Add("id", filter.GetId()) + } + if filter.State != nil { + opts.Filter.Add("status", toDockerContainerStatus(filter.GetState())) + } + if filter.PodSandboxId != nil { + // TODO: implement this after sandbox functions are implemented. + } + + if filter.LabelSelector != nil { + for k, v := range filter.LabelSelector { + opts.Filter.Add("label", fmt.Sprintf("%s=%s", k, v)) + } + } + } + containers, err := ds.client.ListContainers(opts) + if err != nil { + return nil, err + } + // Convert docker to runtime api containers. + result := []*runtimeApi.Container{} + for _, c := range containers { + result = append(result, toRuntimeAPIContainer(&c)) + } + return result, nil +} + +// CreateContainer creates a new container in the given PodSandbox +// Note: docker doesn't use LogPath yet. +// TODO: check if the default values returned by the runtime API are ok. +func (ds *dockerService) CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) { + if config == nil { + return "", fmt.Errorf("container config is nil") + } + if sandboxConfig == nil { + return "", fmt.Errorf("sandbox config is nil for container %q", config.GetName()) + } + + // Merge annotations and labels because docker supports only labels. + // TODO: add a prefix to annotations so that we can distinguish labels and + // annotations when reading back them from the docker container. + // TODO: should we apply docker-specific labels? + labels := config.GetLabels() + for k, v := range config.GetAnnotations() { + if _, ok := labels[k]; !ok { + // Only write to labels if the key doesn't exist. + labels[k] = v + } + } + + image := "" + if iSpec := config.GetImage(); iSpec != nil { + image = iSpec.GetImage() + } + createConfig := dockertypes.ContainerCreateConfig{ + Name: config.GetName(), + Config: &dockercontainer.Config{ + // TODO: set User. + Hostname: sandboxConfig.GetHostname(), + Entrypoint: dockerstrslice.StrSlice(config.GetCommand()), + Cmd: dockerstrslice.StrSlice(config.GetArgs()), + Env: generateEnvList(config.GetEnvs()), + Image: image, + WorkingDir: config.GetWorkingDir(), + Labels: labels, + // Interactive containers: + OpenStdin: config.GetStdin(), + StdinOnce: config.GetStdinOnce(), + Tty: config.GetTty(), + }, + } + + // Fill the HostConfig. + hc := &dockercontainer.HostConfig{ + Binds: generateMountBindings(config.GetMounts()), + ReadonlyRootfs: config.GetReadonlyRootfs(), + Privileged: config.GetPrivileged(), + } + + // Apply options derived from the sandbox config. + if lc := sandboxConfig.GetLinux(); lc != nil { + // Apply Cgroup options. + // TODO: Check if this works with per-pod cgroups. + hc.CgroupParent = lc.GetCgroupParent() + + // Apply namespace options. + sandboxNSMode := fmt.Sprintf("container:%v", podSandboxID) + hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode) + hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode) + hc.UTSMode = "" + hc.PidMode = "" + + nsOpts := lc.GetNamespaceOptions() + if nsOpts != nil { + if nsOpts.GetHostNetwork() { + hc.UTSMode = namespaceModeHost + } + if nsOpts.GetHostPid() { + hc.PidMode = namespaceModeHost + } + } + } + + // Apply Linux-specific options if applicable. + if lc := config.GetLinux(); lc != nil { + // Apply resource options. + // TODO: Check if the units are correct. + // TODO: Can we assume the defaults are sane? + rOpts := lc.GetResources() + if rOpts != nil { + hc.Resources = dockercontainer.Resources{ + Memory: rOpts.GetMemoryLimitInBytes(), + MemorySwap: -1, // Always disable memory swap. + CPUShares: rOpts.GetCpuShares(), + CPUQuota: rOpts.GetCpuQuota(), + CPUPeriod: rOpts.GetCpuPeriod(), + // TODO: Need to set devices. + } + hc.OomScoreAdj = int(rOpts.GetOomScoreAdj()) + } + // Note: ShmSize is handled in kube_docker_client.go + } + + // TODO: Seccomp support. Need to figure out how to pass seccomp options + // through the runtime API (annotations?).See dockerManager.getSecurityOpts() + // for the details. Always set the default seccomp profile for now. + hc.SecurityOpt = []string{fmt.Sprintf("%s=%s", "seccomp", defaultSeccompProfile)} + // TODO: Add or drop capabilities. + + createConfig.HostConfig = hc + createResp, err := ds.client.CreateContainer(createConfig) + if createResp != nil { + return createResp.ID, err + } + return "", err +} + +// StartContainer starts the container. +func (ds *dockerService) StartContainer(rawContainerID string) error { + return ds.client.StartContainer(rawContainerID) +} + +// StopContainer stops a running container with a grace period (i.e., timeout). +func (ds *dockerService) StopContainer(rawContainerID string, timeout int64) error { + return ds.client.StopContainer(rawContainerID, int(timeout)) +} + +// RemoveContainer removes the container. +// TODO: If a container is still running, should we forcibly remove it? +func (ds *dockerService) RemoveContainer(rawContainerID string) error { + return ds.client.RemoveContainer(rawContainerID, dockertypes.ContainerRemoveOptions{RemoveVolumes: true}) +} + +// ContainerStatus returns the container status. +// TODO: Implement the function. +func (ds *dockerService) ContainerStatus(rawContainerID string) (*runtimeApi.ContainerStatus, error) { + return nil, fmt.Errorf("not implemented") +} + +// Exec execute a command in the container. +// TODO: Implement the function. +func (ds *dockerService) Exec(rawContainerID string, cmd []string, tty bool, stdin io.Reader, stdout, stderr io.WriteCloser) error { + return fmt.Errorf("not implemented") +} diff --git a/pkg/kubelet/dockershim/docker_image.go b/pkg/kubelet/dockershim/docker_image.go new file mode 100644 index 00000000000..395b54870bc --- /dev/null +++ b/pkg/kubelet/dockershim/docker_image.go @@ -0,0 +1,85 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockershim + +import ( + "fmt" + + dockertypes "github.com/docker/engine-api/types" + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" +) + +// This file implements methods in ImageManagerService. + +// ListImages lists existing images. +func (ds *dockerService) ListImages(filter *runtimeApi.ImageFilter) ([]*runtimeApi.Image, error) { + opts := dockertypes.ImageListOptions{} + if filter != nil { + if imgSpec := filter.GetImage(); imgSpec != nil { + opts.MatchName = imgSpec.GetImage() + } + } + + images, err := ds.client.ListImages(opts) + if err != nil { + return nil, err + } + + result := []*runtimeApi.Image{} + for _, i := range images { + apiImage, err := toRuntimeAPIImage(&i) + if err != nil { + // TODO: log an error message? + continue + } + result = append(result, apiImage) + } + return result, nil +} + +// ImageStatus returns the status of the image. +func (ds *dockerService) ImageStatus(image *runtimeApi.ImageSpec) (*runtimeApi.Image, error) { + images, err := ds.ListImages(&runtimeApi.ImageFilter{Image: image}) + if err != nil { + return nil, err + } + if len(images) != 1 { + return nil, fmt.Errorf("ImageStatus returned more than one image: %+v", images) + } + return images[0], nil +} + +// PullImage pulls a image with authentication config. +func (ds *dockerService) PullImage(image *runtimeApi.ImageSpec, auth *runtimeApi.AuthConfig) error { + // TODO: add default tags for images or should this be done by kubelet? + return ds.client.PullImage(image.GetImage(), + dockertypes.AuthConfig{ + Username: auth.GetUsername(), + Password: auth.GetPassword(), + ServerAddress: auth.GetServerAddress(), + IdentityToken: auth.GetIdentityToken(), + RegistryToken: auth.GetRegistryToken(), + }, + dockertypes.ImagePullOptions{}, + ) +} + +// RemoveImage removes the image. +func (ds *dockerService) RemoveImage(image *runtimeApi.ImageSpec) error { + _, err := ds.client.RemoveImage(image.GetImage(), dockertypes.ImageRemoveOptions{PruneChildren: true}) + return err +} diff --git a/pkg/kubelet/dockershim/docker_sandbox.go b/pkg/kubelet/dockershim/docker_sandbox.go new file mode 100644 index 00000000000..7825a9909a8 --- /dev/null +++ b/pkg/kubelet/dockershim/docker_sandbox.go @@ -0,0 +1,51 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockershim + +import ( + "fmt" + + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" +) + +// CreatePodSandbox creates a pod-level sandbox. +// The definition of PodSandbox is at https://github.com/kubernetes/kubernetes/pull/25899 +func (ds *dockerService) CreatePodSandbox(config *runtimeApi.PodSandboxConfig) (string, error) { + return "", fmt.Errorf("Not implemented") +} + +// StopPodSandbox stops the sandbox. If there are any running containers in the +// sandbox, they should be force terminated. +func (ds *dockerService) StopPodSandbox(podSandboxID string) error { + return fmt.Errorf("Not implemented") +} + +// DeletePodSandbox deletes the sandbox. If there are running containers in the +// sandbox, they should be forcibly deleted. +func (ds *dockerService) DeletePodSandbox(podSandboxID string) error { + return fmt.Errorf("Not implemented") +} + +// PodSandboxStatus returns the Status of the PodSandbox. +func (ds *dockerService) PodSandboxStatus(podSandboxID string) (*runtimeApi.PodSandboxStatus, error) { + return nil, fmt.Errorf("Not implemented") +} + +// ListPodSandbox returns a list of Sandbox. +func (ds *dockerService) ListPodSandbox(filter *runtimeApi.PodSandboxFilter) ([]*runtimeApi.PodSandbox, error) { + return nil, fmt.Errorf("Not implemented") +} diff --git a/pkg/kubelet/dockershim/docker_service.go b/pkg/kubelet/dockershim/docker_service.go new file mode 100644 index 00000000000..2371560654b --- /dev/null +++ b/pkg/kubelet/dockershim/docker_service.go @@ -0,0 +1,78 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockershim + +import ( + "fmt" + "io" + + "k8s.io/kubernetes/pkg/api" + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" + kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" + "k8s.io/kubernetes/pkg/kubelet/dockertools" +) + +const ( + dockerRuntimeName = "docker" + kubeAPIVersion = "0.1.0" + + // String used to detect docker host mode for various namespaces (e.g. + // networking). Must match the value returned by docker inspect -f + // '{{.HostConfig.NetworkMode}}'. + namespaceModeHost = "host" + + defaultSeccompProfile = "unconfined" +) + +func NewDockerSevice(client dockertools.DockerInterface) DockerLegacyService { + return &dockerService{ + client: dockertools.NewInstrumentedDockerInterface(client), + } +} + +// DockerLegacyService is an interface that embeds both the new +// RuntimeService and ImageService interfaces, while including legacy methods +// for backward compatibility. +type DockerLegacyService interface { + kubecontainer.RuntimeService + kubecontainer.ImageManagerService + + // Supporting legacy methods for docker. + GetContainerLogs(pod *api.Pod, containerID kubecontainer.ContainerID, logOptions *api.PodLogOptions, stdout, stderr io.Writer) (err error) + kubecontainer.ContainerAttacher + PortForward(pod *kubecontainer.Pod, port uint16, stream io.ReadWriteCloser) error +} + +type dockerService struct { + client dockertools.DockerInterface +} + +// Version returns the runtime name, runtime version and runtime API version +func (ds *dockerService) Version(apiVersion string) (*runtimeApi.VersionResponse, error) { + v, err := ds.client.Version() + if err != nil { + return nil, fmt.Errorf("docker: failed to get docker version: %v", err) + } + runtimeAPIVersion := kubeAPIVersion + name := dockerRuntimeName + return &runtimeApi.VersionResponse{ + Version: &runtimeAPIVersion, + RuntimeName: &name, + RuntimeVersion: &v.Version, + RuntimeApiVersion: &v.APIVersion, + }, nil +} diff --git a/pkg/kubelet/dockershim/helpers.go b/pkg/kubelet/dockershim/helpers.go new file mode 100644 index 00000000000..eb438216c64 --- /dev/null +++ b/pkg/kubelet/dockershim/helpers.go @@ -0,0 +1,78 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockershim + +import ( + "fmt" + + dockerapiversion "github.com/docker/engine-api/types/versions" + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" +) + +// apiVersion implements kubecontainer.Version interface by implementing +// Compare() and String(). It uses the compare function of engine-api to +// compare docker apiversions. +type apiVersion string + +func (v apiVersion) String() string { + return string(v) +} + +func (v apiVersion) Compare(other string) (int, error) { + if dockerapiversion.LessThan(string(v), other) { + return -1, nil + } else if dockerapiversion.GreaterThan(string(v), other) { + return 1, nil + } + return 0, nil +} + +// generateEnvList converts KeyValue list to a list of strings, in the form of +// '=', which can be understood by docker. +func generateEnvList(envs []*runtimeApi.KeyValue) (result []string) { + for _, env := range envs { + result = append(result, fmt.Sprintf("%s=%s", env.GetKey(), env.GetValue())) + } + return +} + +// generateMountBindings converts the mount list to a list of strings that +// can be understood by docker. +// Each element in the string is in the form of: +// ':', or +// '::ro', if the path is read only, or +// '::Z', if the volume requires SELinux +// relabeling and the pod provides an SELinux label +func generateMountBindings(mounts []*runtimeApi.Mount) (result []string) { + // TODO: resolve podHasSELinuxLabel + for _, m := range mounts { + bind := fmt.Sprintf("%s:%s", m.GetHostPath(), m.GetContainerPath()) + readOnly := m.GetReadonly() + if readOnly { + bind += ":ro" + } + if m.GetSelinuxRelabel() { + if readOnly { + bind += ",Z" + } else { + bind += ":Z" + } + } + result = append(result, bind) + } + return +} diff --git a/pkg/kubelet/dockershim/legacy.go b/pkg/kubelet/dockershim/legacy.go new file mode 100644 index 00000000000..5f1bbc46fae --- /dev/null +++ b/pkg/kubelet/dockershim/legacy.go @@ -0,0 +1,43 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dockershim + +import ( + "fmt" + "io" + + "k8s.io/kubernetes/pkg/api" + kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" + "k8s.io/kubernetes/pkg/util/term" +) + +// This file implements the functions that are needed for backward +// compatibility. Therefore, it imports various kubernetes packages +// directly. + +// TODO: implement the methods in this file. +func (ds *dockerService) AttachContainer(id kubecontainer.ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) (err error) { + return fmt.Errorf("not implemented") +} + +func (ds *dockerService) GetContainerLogs(pod *api.Pod, containerID kubecontainer.ContainerID, logOptions *api.PodLogOptions, stdout, stderr io.Writer) (err error) { + return fmt.Errorf("not implemented") +} + +func (ds *dockerService) PortForward(pod *kubecontainer.Pod, port uint16, stream io.ReadWriteCloser) error { + return fmt.Errorf("not implemented") +} diff --git a/pkg/kubelet/dockertools/docker_manager.go b/pkg/kubelet/dockertools/docker_manager.go index 3a183895d55..bff3e8891b6 100644 --- a/pkg/kubelet/dockertools/docker_manager.go +++ b/pkg/kubelet/dockertools/docker_manager.go @@ -225,7 +225,7 @@ func NewDockerManager( seccompProfileRoot string, options ...kubecontainer.Option) *DockerManager { // Wrap the docker client with instrumentedDockerInterface - client = newInstrumentedDockerInterface(client) + client = NewInstrumentedDockerInterface(client) // Work out the location of the Docker runtime, defaulting to /var/lib/docker // if there are any problems. diff --git a/pkg/kubelet/dockertools/instrumented_docker.go b/pkg/kubelet/dockertools/instrumented_docker.go index 8503fe2d303..eb15226498a 100644 --- a/pkg/kubelet/dockertools/instrumented_docker.go +++ b/pkg/kubelet/dockertools/instrumented_docker.go @@ -30,7 +30,7 @@ type instrumentedDockerInterface struct { } // Creates an instrumented DockerInterface from an existing DockerInterface. -func newInstrumentedDockerInterface(dockerClient DockerInterface) DockerInterface { +func NewInstrumentedDockerInterface(dockerClient DockerInterface) DockerInterface { return instrumentedDockerInterface{ client: dockerClient, }