diff --git a/pkg/kubelet/dockershim/docker_image.go b/pkg/kubelet/dockershim/docker_image.go index e0239737fa9..15aa7d95410 100644 --- a/pkg/kubelet/dockershim/docker_image.go +++ b/pkg/kubelet/dockershim/docker_image.go @@ -63,8 +63,8 @@ func (ds *dockerService) ImageStatus(image *runtimeapi.ImageSpec) (*runtimeapi.I } // PullImage pulls an image with authentication config. -func (ds *dockerService) PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig) error { - return ds.client.PullImage(image.GetImage(), +func (ds *dockerService) PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig) (string, error) { + err := ds.client.PullImage(image.GetImage(), dockertypes.AuthConfig{ Username: auth.GetUsername(), Password: auth.GetPassword(), @@ -74,6 +74,11 @@ func (ds *dockerService) PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi }, dockertypes.ImagePullOptions{}, ) + if err != nil { + return "", err + } + + return dockertools.GetImageRef(ds.client, image.GetImage()) } // RemoveImage removes the image. diff --git a/pkg/kubelet/dockershim/remote/docker_service.go b/pkg/kubelet/dockershim/remote/docker_service.go index 15abc8399e2..8274d83315d 100644 --- a/pkg/kubelet/dockershim/remote/docker_service.go +++ b/pkg/kubelet/dockershim/remote/docker_service.go @@ -200,11 +200,11 @@ func (d *dockerService) ImageStatus(ctx context.Context, r *runtimeapi.ImageStat } func (d *dockerService) PullImage(ctx context.Context, r *runtimeapi.PullImageRequest) (*runtimeapi.PullImageResponse, error) { - err := d.imageService.PullImage(r.GetImage(), r.GetAuth()) + image, err := d.imageService.PullImage(r.GetImage(), r.GetAuth()) if err != nil { return nil, err } - return &runtimeapi.PullImageResponse{}, nil + return &runtimeapi.PullImageResponse{ImageRef: &image}, nil } func (d *dockerService) RemoveImage(ctx context.Context, r *runtimeapi.RemoveImageRequest) (*runtimeapi.RemoveImageResponse, error) { diff --git a/pkg/kubelet/kuberuntime/instrumented_services.go b/pkg/kubelet/kuberuntime/instrumented_services.go index 2ba2583f666..1a76b0a4d52 100644 --- a/pkg/kubelet/kuberuntime/instrumented_services.go +++ b/pkg/kubelet/kuberuntime/instrumented_services.go @@ -239,13 +239,13 @@ func (in instrumentedImageManagerService) ImageStatus(image *runtimeapi.ImageSpe return out, err } -func (in instrumentedImageManagerService) PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig) error { +func (in instrumentedImageManagerService) PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig) (string, error) { const operation = "pull_image" defer recordOperation(operation, time.Now()) - err := in.service.PullImage(image, auth) + imageRef, err := in.service.PullImage(image, auth) recordError(operation, err) - return err + return imageRef, err } func (in instrumentedImageManagerService) RemoveImage(image *runtimeapi.ImageSpec) error { diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container.go b/pkg/kubelet/kuberuntime/kuberuntime_container.go index 73070c113d0..7f9517a1ee7 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -51,7 +51,7 @@ import ( // * run the post start lifecycle hooks (if applicable) func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandboxConfig *runtimeapi.PodSandboxConfig, container *v1.Container, pod *v1.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, podIP string) (string, error) { // Step 1: pull the image. - err, msg := m.imagePuller.EnsureImageExists(pod, container, pullSecrets) + imageRef, msg, err := m.imagePuller.EnsureImageExists(pod, container, pullSecrets) if err != nil { return msg, err } @@ -70,7 +70,7 @@ func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandb restartCount = containerStatus.RestartCount + 1 } - containerConfig, err := m.generateContainerConfig(container, pod, restartCount, podIP) + containerConfig, err := m.generateContainerConfig(container, pod, restartCount, podIP, imageRef) if err != nil { m.recorder.Eventf(ref, v1.EventTypeWarning, events.FailedToCreateContainer, "Failed to create container with error: %v", err) return "Generate Container Config Failed", err @@ -129,7 +129,7 @@ func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandb } // generateContainerConfig generates container config for kubelet runtime v1. -func (m *kubeGenericRuntimeManager) generateContainerConfig(container *v1.Container, pod *v1.Pod, restartCount int, podIP string) (*runtimeapi.ContainerConfig, error) { +func (m *kubeGenericRuntimeManager) generateContainerConfig(container *v1.Container, pod *v1.Pod, restartCount int, podIP, imageRef string) (*runtimeapi.ContainerConfig, error) { opts, err := m.runtimeHelper.GenerateRunContainerOptions(pod, container, podIP) if err != nil { return nil, err @@ -156,7 +156,7 @@ func (m *kubeGenericRuntimeManager) generateContainerConfig(container *v1.Contai Name: &container.Name, Attempt: &restartCountUint32, }, - Image: &runtimeapi.ImageSpec{Image: &container.Image}, + Image: &runtimeapi.ImageSpec{Image: &imageRef}, Command: command, Args: args, WorkingDir: &container.WorkingDir, diff --git a/pkg/kubelet/kuberuntime/kuberuntime_image.go b/pkg/kubelet/kuberuntime/kuberuntime_image.go index 672ac108dc8..34b711170df 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_image.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_image.go @@ -28,16 +28,16 @@ import ( // PullImage pulls an image from the network to local storage using the supplied // secrets if necessary. -func (m *kubeGenericRuntimeManager) PullImage(image kubecontainer.ImageSpec, pullSecrets []v1.Secret) error { +func (m *kubeGenericRuntimeManager) PullImage(image kubecontainer.ImageSpec, pullSecrets []v1.Secret) (string, error) { img := image.Image repoToPull, _, _, err := parsers.ParseImageName(img) if err != nil { - return err + return "", err } keyring, err := credentialprovider.MakeDockerKeyring(pullSecrets, m.keyring) if err != nil { - return err + return "", err } imgSpec := &runtimeapi.ImageSpec{Image: &img} @@ -45,13 +45,13 @@ func (m *kubeGenericRuntimeManager) PullImage(image kubecontainer.ImageSpec, pul if !withCredentials { glog.V(3).Infof("Pulling image %q without credentials", img) - err = m.imageService.PullImage(imgSpec, nil) + imageRef, err := m.imageService.PullImage(imgSpec, nil) if err != nil { glog.Errorf("Pull image %q failed: %v", img, err) - return err + return "", err } - return nil + return imageRef, nil } var pullErrs []error @@ -66,26 +66,34 @@ func (m *kubeGenericRuntimeManager) PullImage(image kubecontainer.ImageSpec, pul RegistryToken: &authConfig.RegistryToken, } - err = m.imageService.PullImage(imgSpec, auth) + imageRef, err := m.imageService.PullImage(imgSpec, auth) // If there was no error, return success if err == nil { - return nil + return imageRef, nil } pullErrs = append(pullErrs, err) } - return utilerrors.NewAggregate(pullErrs) + return "", utilerrors.NewAggregate(pullErrs) } // IsImagePresent checks whether the container image is already in the local storage. -func (m *kubeGenericRuntimeManager) IsImagePresent(image kubecontainer.ImageSpec) (bool, error) { +func (m *kubeGenericRuntimeManager) IsImagePresent(image kubecontainer.ImageSpec) (string, error) { status, err := m.imageService.ImageStatus(&runtimeapi.ImageSpec{Image: &image.Image}) if err != nil { glog.Errorf("ImageStatus for image %q failed: %v", image, err) - return false, err + return "", err } - return status != nil, nil + if status == nil { + return "", nil + } + + imageRef := status.GetId() + if len(status.RepoDigests) > 0 { + imageRef = status.RepoDigests[0] + } + return imageRef, nil } // ListImages gets all images currently on the machine. diff --git a/pkg/kubelet/kuberuntime/kuberuntime_image_test.go b/pkg/kubelet/kuberuntime/kuberuntime_image_test.go index 9124de9cc9b..01e6129c6e5 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_image_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_image_test.go @@ -28,8 +28,9 @@ func TestPullImage(t *testing.T) { _, _, fakeManager, err := createTestRuntimeManager() assert.NoError(t, err) - err = fakeManager.PullImage(kubecontainer.ImageSpec{Image: "busybox"}, nil) + imageRef, err := fakeManager.PullImage(kubecontainer.ImageSpec{Image: "busybox"}, nil) assert.NoError(t, err) + assert.Equal(t, "busybox", imageRef) images, err := fakeManager.ListImages() assert.NoError(t, err) @@ -61,16 +62,16 @@ func TestIsImagePresent(t *testing.T) { image := "busybox" fakeImageService.SetFakeImages([]string{image}) - present, err := fakeManager.IsImagePresent(kubecontainer.ImageSpec{Image: image}) + imageRef, err := fakeManager.IsImagePresent(kubecontainer.ImageSpec{Image: image}) assert.NoError(t, err) - assert.Equal(t, true, present) + assert.Equal(t, image, imageRef) } func TestRemoveImage(t *testing.T) { _, fakeImageService, fakeManager, err := createTestRuntimeManager() assert.NoError(t, err) - err = fakeManager.PullImage(kubecontainer.ImageSpec{Image: "busybox"}, nil) + _, err = fakeManager.PullImage(kubecontainer.ImageSpec{Image: "busybox"}, nil) assert.NoError(t, err) assert.Equal(t, 1, len(fakeImageService.Images)) diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go index f5c6f75c224..a4837718054 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go @@ -145,7 +145,7 @@ func makeFakeContainer(t *testing.T, m *kubeGenericRuntimeManager, template cont sandboxConfig, err := m.generatePodSandboxConfig(template.pod, template.sandboxAttempt) assert.NoError(t, err, "generatePodSandboxConfig for container template %+v", template) - containerConfig, err := m.generateContainerConfig(template.container, template.pod, template.attempt, "") + containerConfig, err := m.generateContainerConfig(template.container, template.pod, template.attempt, "", template.container.Image) assert.NoError(t, err, "generateContainerConfig for container template %+v", template) podSandboxID := apitest.BuildSandboxName(sandboxConfig.Metadata) diff --git a/pkg/kubelet/remote/remote_image.go b/pkg/kubelet/remote/remote_image.go index b7667dc41bc..31faac8e1d8 100644 --- a/pkg/kubelet/remote/remote_image.go +++ b/pkg/kubelet/remote/remote_image.go @@ -79,20 +79,20 @@ func (r *RemoteImageService) ImageStatus(image *runtimeapi.ImageSpec) (*runtimea } // PullImage pulls an image with authentication config. -func (r *RemoteImageService) PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig) error { +func (r *RemoteImageService) PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig) (string, error) { ctx, cancel := getContextWithTimeout(r.timeout) defer cancel() - _, err := r.imageClient.PullImage(ctx, &runtimeapi.PullImageRequest{ + resp, err := r.imageClient.PullImage(ctx, &runtimeapi.PullImageRequest{ Image: image, Auth: auth, }) if err != nil { glog.Errorf("PullImage %q from image service failed: %v", image.GetImage(), err) - return err + return "", err } - return nil + return resp.GetImageRef(), nil } // RemoveImage removes the image.