mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 12:15:52 +00:00
Merge pull request #7578 from yujuhong/docker_manager
Add image-related methods to DockerManager
This commit is contained in:
commit
441a4e6f30
@ -54,18 +54,18 @@ type Runtime interface {
|
||||
KillContainerInPod(api.Container, *api.Pod) error
|
||||
// GetPodStatus retrieves the status of the pod, including the information of
|
||||
// all containers in the pod.
|
||||
GetPodStatus(*api.Pod) (api.PodStatus, error)
|
||||
GetPodStatus(*api.Pod) (*api.PodStatus, error)
|
||||
// TODO(vmarmol): Merge RunInContainer and ExecInContainer.
|
||||
// Runs the command in the container of the specified pod using nsinit.
|
||||
// TODO(yifan): Use strong type for containerID.
|
||||
RunInContainer(containerID string, cmd []string) error
|
||||
RunInContainer(containerID string, cmd []string) ([]byte, error)
|
||||
// Runs the command in the container of the specified pod using nsenter.
|
||||
// Attaches the processes stdin, stdout, and stderr. Optionally uses a
|
||||
// tty.
|
||||
// TODO(yifan): Use strong type for containerID.
|
||||
ExecInContainer(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error
|
||||
// Forward the specified port from the specified pod to the stream.
|
||||
PortForward(pod Pod, port uint16, stream io.ReadWriteCloser) error
|
||||
PortForward(pod *Pod, port uint16, stream io.ReadWriteCloser) error
|
||||
// PullImage pulls an image from the network to local storage.
|
||||
PullImage(image string) error
|
||||
// IsImagePresent checks whether the container image is already in the local storage.
|
||||
|
60
pkg/kubelet/dockertools/convert.go
Normal file
60
pkg/kubelet/dockertools/convert.go
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2015 Google Inc. All rights reserved.
|
||||
|
||||
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 dockertools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
kubecontainer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/container"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
)
|
||||
|
||||
// This file contains helper functions to convert docker API types to runtime
|
||||
// (kubecontainer) types.
|
||||
|
||||
// Converts docker.APIContainers to kubecontainer.Container.
|
||||
func toRuntimeContainer(c *docker.APIContainers) (*kubecontainer.Container, error) {
|
||||
if c == nil {
|
||||
return nil, fmt.Errorf("unable to convert a nil pointer to a runtime container")
|
||||
}
|
||||
|
||||
dockerName, hash, err := getDockerContainerNameInfo(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &kubecontainer.Container{
|
||||
ID: types.UID(c.ID),
|
||||
Name: dockerName.ContainerName,
|
||||
Image: c.Image,
|
||||
Hash: hash,
|
||||
Created: c.Created,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Converts docker.APIImages to kubecontainer.Image.
|
||||
func toRuntimeImage(image *docker.APIImages) (*kubecontainer.Image, error) {
|
||||
if image == nil {
|
||||
return nil, fmt.Errorf("unable to convert a nil pointer to a runtime image")
|
||||
}
|
||||
|
||||
return &kubecontainer.Image{
|
||||
ID: image.ID,
|
||||
Tags: image.RepoTags,
|
||||
Size: image.Size,
|
||||
}, nil
|
||||
}
|
71
pkg/kubelet/dockertools/convert_test.go
Normal file
71
pkg/kubelet/dockertools/convert_test.go
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright 2015 Google Inc. All rights reserved.
|
||||
|
||||
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 dockertools
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
kubecontainer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/container"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
)
|
||||
|
||||
func TestToRuntimeContainer(t *testing.T) {
|
||||
original := &docker.APIContainers{
|
||||
ID: "ab2cdf",
|
||||
Image: "bar_image",
|
||||
Created: 12345,
|
||||
Names: []string{"/k8s_bar.5678_foo_ns_1234_42"},
|
||||
}
|
||||
expected := &kubecontainer.Container{
|
||||
ID: types.UID("ab2cdf"),
|
||||
Name: "bar",
|
||||
Image: "bar_image",
|
||||
Hash: 0x5678,
|
||||
Created: 12345,
|
||||
}
|
||||
|
||||
actual, err := toRuntimeContainer(original)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("expected %#v, got %#v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToRuntimeImage(t *testing.T) {
|
||||
original := &docker.APIImages{
|
||||
ID: "aeeea",
|
||||
RepoTags: []string{"abc", "def"},
|
||||
Size: 1234,
|
||||
}
|
||||
expected := &kubecontainer.Image{
|
||||
ID: "aeeea",
|
||||
Tags: []string{"abc", "def"},
|
||||
Size: 1234,
|
||||
}
|
||||
|
||||
actual, err := toRuntimeImage(original)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("expected %#v, got %#v", expected, actual)
|
||||
}
|
||||
}
|
@ -53,8 +53,8 @@ const (
|
||||
maxReasonCacheEntries = 200
|
||||
)
|
||||
|
||||
// TODO: Eventually DockerManager should implement kubecontainer.Runtime
|
||||
// interface.
|
||||
// TODO(yjhong): DockerManager should implement the Runtime interface.
|
||||
|
||||
type DockerManager struct {
|
||||
client DockerInterface
|
||||
recorder record.EventRecorder
|
||||
@ -640,21 +640,6 @@ func getDockerContainerNameInfo(c *docker.APIContainers) (*KubeletContainerName,
|
||||
return dockerName, hash, nil
|
||||
}
|
||||
|
||||
// Converts docker.APIContainers to kubecontainer.Container.
|
||||
func convertDockerToRuntimeContainer(c *docker.APIContainers) (*kubecontainer.Container, error) {
|
||||
dockerName, hash, err := getDockerContainerNameInfo(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &kubecontainer.Container{
|
||||
ID: types.UID(c.ID),
|
||||
Name: dockerName.ContainerName,
|
||||
Image: c.Image,
|
||||
Hash: hash,
|
||||
Created: c.Created,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Get pod UID, name, and namespace by examining the container names.
|
||||
func getPodInfoFromContainer(c *docker.APIContainers) (types.UID, string, string, error) {
|
||||
dockerName, _, err := getDockerContainerNameInfo(c)
|
||||
@ -678,7 +663,7 @@ func (dm *DockerManager) GetContainers(all bool) ([]*kubecontainer.Container, er
|
||||
// Convert DockerContainers to []*kubecontainer.Container
|
||||
result := make([]*kubecontainer.Container, 0, len(containers))
|
||||
for _, c := range containers {
|
||||
converted, err := convertDockerToRuntimeContainer(c)
|
||||
converted, err := toRuntimeContainer(c)
|
||||
if err != nil {
|
||||
glog.Errorf("Error examining the container: %v", err)
|
||||
continue
|
||||
@ -699,7 +684,7 @@ func (dm *DockerManager) GetPods(all bool) ([]*kubecontainer.Pod, error) {
|
||||
|
||||
// Group containers by pod.
|
||||
for _, c := range containers {
|
||||
converted, err := convertDockerToRuntimeContainer(c)
|
||||
converted, err := toRuntimeContainer(c)
|
||||
if err != nil {
|
||||
glog.Errorf("Error examining the container: %v", err)
|
||||
continue
|
||||
@ -730,14 +715,40 @@ func (dm *DockerManager) GetPods(all bool) ([]*kubecontainer.Pod, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (dm *DockerManager) Pull(image string) error {
|
||||
// List all images in the local storage.
|
||||
func (dm *DockerManager) ListImages() ([]kubecontainer.Image, error) {
|
||||
var images []kubecontainer.Image
|
||||
|
||||
dockerImages, err := dm.client.ListImages(docker.ListImagesOptions{})
|
||||
if err != nil {
|
||||
return images, err
|
||||
}
|
||||
|
||||
for _, di := range dockerImages {
|
||||
image, err := toRuntimeImage(&di)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
images = append(images, *image)
|
||||
}
|
||||
return images, nil
|
||||
}
|
||||
|
||||
// PullImage pulls an image from network to local storage.
|
||||
func (dm *DockerManager) PullImage(image string) error {
|
||||
return dm.Puller.Pull(image)
|
||||
}
|
||||
|
||||
// IsImagePresent checks whether the container image is already in the local storage.
|
||||
func (dm *DockerManager) IsImagePresent(image string) (bool, error) {
|
||||
return dm.Puller.IsImagePresent(image)
|
||||
}
|
||||
|
||||
// Removes the specified image.
|
||||
func (dm *DockerManager) RemoveImage(image string) error {
|
||||
return dm.client.RemoveImage(image)
|
||||
}
|
||||
|
||||
// podInfraContainerChanged returns true if the pod infra container has changed.
|
||||
func (dm *DockerManager) podInfraContainerChanged(pod *api.Pod, podInfraContainer *kubecontainer.Container) (bool, error) {
|
||||
networkMode := ""
|
||||
@ -1128,7 +1139,7 @@ func (dm *DockerManager) CreatePodInfraContainer(pod *api.Pod, generator kubecon
|
||||
return "", err
|
||||
}
|
||||
if !ok {
|
||||
if err := dm.Pull(container.Image); err != nil {
|
||||
if err := dm.PullImage(container.Image); err != nil {
|
||||
if ref != nil {
|
||||
dm.recorder.Eventf(ref, "failed", "Failed to pull image %q: %v", container.Image, err)
|
||||
}
|
||||
|
@ -116,30 +116,6 @@ func TestSetEntrypointAndCommand(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertDockerToRuntimeContainer(t *testing.T) {
|
||||
dockerContainer := &docker.APIContainers{
|
||||
ID: "ab2cdf",
|
||||
Image: "bar_image",
|
||||
Created: 12345,
|
||||
Names: []string{"/k8s_bar.5678_foo_ns_1234_42"},
|
||||
}
|
||||
expected := &kubecontainer.Container{
|
||||
ID: types.UID("ab2cdf"),
|
||||
Name: "bar",
|
||||
Image: "bar_image",
|
||||
Hash: 0x5678,
|
||||
Created: 12345,
|
||||
}
|
||||
|
||||
actual, err := convertDockerToRuntimeContainer(dockerContainer)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("expected %#v, got %#v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// verifyPods returns true if the two pod slices are equal.
|
||||
func verifyPods(a, b []*kubecontainer.Pod) bool {
|
||||
if len(a) != len(b) {
|
||||
@ -179,11 +155,10 @@ func TestGetPods(t *testing.T) {
|
||||
}
|
||||
|
||||
// Convert the docker containers. This does not affect the test coverage
|
||||
// because the conversion is tested separately in
|
||||
// TestConvertDockerToRuntimeContainer.
|
||||
// because the conversion is tested separately in convert_test.go
|
||||
containers := make([]*kubecontainer.Container, len(dockerContainers))
|
||||
for i := range containers {
|
||||
c, err := convertDockerToRuntimeContainer(&dockerContainers[i])
|
||||
c, err := toRuntimeContainer(&dockerContainers[i])
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
@ -214,3 +189,24 @@ func TestGetPods(t *testing.T) {
|
||||
t.Errorf("expected %#v, got %#v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListImages(t *testing.T) {
|
||||
manager, fakeDocker := NewFakeDockerManager()
|
||||
dockerImages := []docker.APIImages{{ID: "1111"}, {ID: "2222"}, {ID: "3333"}}
|
||||
expected := util.NewStringSet([]string{"1111", "2222", "3333"}...)
|
||||
|
||||
fakeDocker.Images = dockerImages
|
||||
actualImages, err := manager.ListImages()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
actual := util.NewStringSet()
|
||||
for _, i := range actualImages {
|
||||
actual.Insert(i.ID)
|
||||
}
|
||||
// We can compare the two sets directly because util.StringSet.List()
|
||||
// returns a "sorted" list.
|
||||
if !reflect.DeepEqual(expected.List(), actual.List()) {
|
||||
t.Errorf("expected %#v, got %#v", expected.List(), actual.List())
|
||||
}
|
||||
}
|
||||
|
@ -883,7 +883,7 @@ func (kl *Kubelet) pullImage(pod *api.Pod, container *api.Container) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = kl.containerManager.Pull(container.Image)
|
||||
err = kl.containerManager.PullImage(container.Image)
|
||||
kl.runtimeHooks.ReportImagePull(pod, container, err)
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user