mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Check infra container image existence before pulling.
This commit is contained in:
		@@ -61,8 +61,9 @@ func (ds *dockerService) RunPodSandbox(config *runtimeapi.PodSandboxConfig) (str
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// NOTE: To use a custom sandbox image in a private repository, users need to configure the nodes with credentials properly.
 | 
						// NOTE: To use a custom sandbox image in a private repository, users need to configure the nodes with credentials properly.
 | 
				
			||||||
	// see: http://kubernetes.io/docs/user-guide/images/#configuring-nodes-to-authenticate-to-a-private-repository
 | 
						// see: http://kubernetes.io/docs/user-guide/images/#configuring-nodes-to-authenticate-to-a-private-repository
 | 
				
			||||||
	if err := ds.client.PullImage(image, dockertypes.AuthConfig{}, dockertypes.ImagePullOptions{}); err != nil {
 | 
						// Only pull sandbox image when it's not present - v1.PullIfNotPresent.
 | 
				
			||||||
		return "", fmt.Errorf("unable to pull image for the sandbox container: %v", err)
 | 
						if err := ensureSandboxImageExists(ds.client, image); err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Step 2: Create the sandbox container.
 | 
						// Step 2: Create the sandbox container.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -320,3 +320,19 @@ func getSecurityOptSeparator(v *semver.Version) rune {
 | 
				
			|||||||
		return dockertools.SecurityOptSeparatorNew
 | 
							return dockertools.SecurityOptSeparatorNew
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ensureSandboxImageExists pulls the sandbox image when it's not present.
 | 
				
			||||||
 | 
					func ensureSandboxImageExists(client dockertools.DockerInterface, image string) error {
 | 
				
			||||||
 | 
						_, err := client.InspectImageByRef(image)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !dockertools.IsImageNotFoundError(err) {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to inspect sandbox image %q: %v", image, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = client.PullImage(image, dockertypes.AuthConfig{}, dockertypes.ImagePullOptions{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("unable to pull sandbox image %q: %v", image, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@ limitations under the License.
 | 
				
			|||||||
package dockershim
 | 
					package dockershim
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/blang/semver"
 | 
						"github.com/blang/semver"
 | 
				
			||||||
@@ -25,6 +26,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api/v1"
 | 
						"k8s.io/kubernetes/pkg/api/v1"
 | 
				
			||||||
	runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
 | 
						runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/kubelet/dockertools"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/security/apparmor"
 | 
						"k8s.io/kubernetes/pkg/security/apparmor"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -261,3 +263,32 @@ func TestGetSecurityOptSeparator(t *testing.T) {
 | 
				
			|||||||
		assert.Equal(t, test.expected, actual, c)
 | 
							assert.Equal(t, test.expected, actual, c)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEnsureSandboxImageExists(t *testing.T) {
 | 
				
			||||||
 | 
						for desc, test := range map[string]struct {
 | 
				
			||||||
 | 
							inject error
 | 
				
			||||||
 | 
							calls  []string
 | 
				
			||||||
 | 
							err    bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							"should not pull image when it already exists": {
 | 
				
			||||||
 | 
								inject: nil,
 | 
				
			||||||
 | 
								calls:  []string{"inspect_image"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"should pull image when it doesn't exist": {
 | 
				
			||||||
 | 
								inject: dockertools.ImageNotFoundError{ID: "image_id"},
 | 
				
			||||||
 | 
								calls:  []string{"inspect_image", "pull"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"should return error when inspect image fails": {
 | 
				
			||||||
 | 
								inject: fmt.Errorf("arbitrary error"),
 | 
				
			||||||
 | 
								calls:  []string{"inspect_image"},
 | 
				
			||||||
 | 
								err:    true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						} {
 | 
				
			||||||
 | 
							t.Logf("TestCase: %q", desc)
 | 
				
			||||||
 | 
							_, fakeDocker, _ := newTestDockerService()
 | 
				
			||||||
 | 
							fakeDocker.InjectError("inspect_image", test.inject)
 | 
				
			||||||
 | 
							err := ensureSandboxImageExists(fakeDocker, "gcr.io/test/image")
 | 
				
			||||||
 | 
							assert.NoError(t, fakeDocker.AssertCalls(test.calls))
 | 
				
			||||||
 | 
							assert.Equal(t, test.err, err != nil)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -290,7 +290,7 @@ func (p dockerPuller) GetImageRef(image string) (string, error) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return imageRef, nil
 | 
							return imageRef, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if _, ok := err.(imageNotFoundError); ok {
 | 
						if IsImageNotFoundError(err) {
 | 
				
			||||||
		return "", nil
 | 
							return "", nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return "", err
 | 
						return "", err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -405,6 +405,7 @@ func (dm *DockerManager) inspectContainer(id string, podName, podNamespace strin
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// default to the image ID, but try and inspect for the RepoDigests
 | 
						// default to the image ID, but try and inspect for the RepoDigests
 | 
				
			||||||
	imageID := DockerPrefix + iResult.Image
 | 
						imageID := DockerPrefix + iResult.Image
 | 
				
			||||||
 | 
						imageName := iResult.Config.Image
 | 
				
			||||||
	imgInspectResult, err := dm.client.InspectImageByID(iResult.Image)
 | 
						imgInspectResult, err := dm.client.InspectImageByID(iResult.Image)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		utilruntime.HandleError(fmt.Errorf("unable to inspect docker image %q while inspecting docker container %q: %v", iResult.Image, containerName, err))
 | 
							utilruntime.HandleError(fmt.Errorf("unable to inspect docker image %q while inspecting docker container %q: %v", iResult.Image, containerName, err))
 | 
				
			||||||
@@ -416,12 +417,12 @@ func (dm *DockerManager) inspectContainer(id string, podName, podNamespace strin
 | 
				
			|||||||
		if len(imgInspectResult.RepoDigests) > 0 {
 | 
							if len(imgInspectResult.RepoDigests) > 0 {
 | 
				
			||||||
			imageID = DockerPullablePrefix + imgInspectResult.RepoDigests[0]
 | 
								imageID = DockerPullablePrefix + imgInspectResult.RepoDigests[0]
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	imageName := iResult.Config.Image
 | 
					 | 
				
			||||||
		if len(imgInspectResult.RepoTags) > 0 {
 | 
							if len(imgInspectResult.RepoTags) > 0 {
 | 
				
			||||||
			imageName = imgInspectResult.RepoTags[0]
 | 
								imageName = imgInspectResult.RepoTags[0]
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	status := kubecontainer.ContainerStatus{
 | 
						status := kubecontainer.ContainerStatus{
 | 
				
			||||||
		Name:         containerName,
 | 
							Name:         containerName,
 | 
				
			||||||
		RestartCount: containerInfo.RestartCount,
 | 
							RestartCount: containerInfo.RestartCount,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -187,7 +187,7 @@ func (d *kubeDockerClient) inspectImageRaw(ref string) (*dockertypes.ImageInspec
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if dockerapi.IsErrImageNotFound(err) {
 | 
							if dockerapi.IsErrImageNotFound(err) {
 | 
				
			||||||
			err = imageNotFoundError{ID: ref}
 | 
								err = ImageNotFoundError{ID: ref}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -202,7 +202,7 @@ func (d *kubeDockerClient) InspectImageByID(imageID string) (*dockertypes.ImageI
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !matchImageIDOnly(*resp, imageID) {
 | 
						if !matchImageIDOnly(*resp, imageID) {
 | 
				
			||||||
		return nil, imageNotFoundError{ID: imageID}
 | 
							return nil, ImageNotFoundError{ID: imageID}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return resp, nil
 | 
						return resp, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -214,7 +214,7 @@ func (d *kubeDockerClient) InspectImageByRef(imageRef string) (*dockertypes.Imag
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !matchImageTagOrSHA(*resp, imageRef) {
 | 
						if !matchImageTagOrSHA(*resp, imageRef) {
 | 
				
			||||||
		return nil, imageNotFoundError{ID: imageRef}
 | 
							return nil, ImageNotFoundError{ID: imageRef}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return resp, nil
 | 
						return resp, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -613,18 +613,19 @@ func IsContainerNotFoundError(err error) bool {
 | 
				
			|||||||
	return containerNotFoundErrorRegx.MatchString(err.Error())
 | 
						return containerNotFoundErrorRegx.MatchString(err.Error())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// imageNotFoundError is the error returned by InspectImage when image not found.
 | 
					// ImageNotFoundError is the error returned by InspectImage when image not found.
 | 
				
			||||||
type imageNotFoundError struct {
 | 
					// Expose this to inject error in dockershim for testing.
 | 
				
			||||||
 | 
					type ImageNotFoundError struct {
 | 
				
			||||||
	ID string
 | 
						ID string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e imageNotFoundError) Error() string {
 | 
					func (e ImageNotFoundError) Error() string {
 | 
				
			||||||
	return fmt.Sprintf("no such image: %q", e.ID)
 | 
						return fmt.Sprintf("no such image: %q", e.ID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsImageNotFoundError checks whether the error is image not found error. This is exposed
 | 
					// IsImageNotFoundError checks whether the error is image not found error. This is exposed
 | 
				
			||||||
// to share with dockershim.
 | 
					// to share with dockershim.
 | 
				
			||||||
func IsImageNotFoundError(err error) bool {
 | 
					func IsImageNotFoundError(err error) bool {
 | 
				
			||||||
	_, ok := err.(imageNotFoundError)
 | 
						_, ok := err.(ImageNotFoundError)
 | 
				
			||||||
	return ok
 | 
						return ok
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user