dockertools: add image ref to ImageService interfaces

pull/6/head
Pengfei Ni 2016-12-29 15:26:03 +08:00
parent 37fc81be0e
commit fcbf39ea54
4 changed files with 60 additions and 26 deletions

View File

@ -94,7 +94,7 @@ func SetContainerNamePrefix(prefix string) {
// DockerPuller is an abstract interface for testability. It abstracts image pull operations.
type DockerPuller interface {
Pull(image string, secrets []v1.Secret) error
IsImagePresent(image string) (bool, error)
IsImagePresent(image string) (string, error)
}
// dockerPuller is the default implementation of DockerPuller.
@ -241,11 +241,11 @@ func (p dockerPuller) Pull(image string, secrets []v1.Secret) error {
err := p.client.PullImage(image, dockertypes.AuthConfig{}, opts)
if err == nil {
// Sometimes PullImage failed with no error returned.
exist, ierr := p.IsImagePresent(image)
imageRef, ierr := p.IsImagePresent(image)
if ierr != nil {
glog.Warningf("Failed to inspect image %s: %v", image, ierr)
}
if !exist {
if imageRef == "" {
return fmt.Errorf("image pull failed for unknown error")
}
return nil
@ -277,15 +277,23 @@ func (p dockerPuller) Pull(image string, secrets []v1.Secret) error {
return utilerrors.NewAggregate(pullErrs)
}
func (p dockerPuller) IsImagePresent(image string) (bool, error) {
_, err := p.client.InspectImageByRef(image)
func (p dockerPuller) IsImagePresent(image string) (string, error) {
resp, err := p.client.InspectImageByRef(image)
if err == nil {
return true, nil
if resp == nil {
return "", nil
}
imageRef := resp.ID
if len(resp.RepoDigests) > 0 {
imageRef = resp.RepoDigests[0]
}
return imageRef, nil
}
if _, ok := err.(imageNotFoundError); ok {
return false, nil
return "", nil
}
return false, err
return "", err
}
// Creates a name which can be reversed to identify both full pod name and container name.

View File

@ -590,6 +590,7 @@ func (dm *DockerManager) runContainer(
container *v1.Container,
opts *kubecontainer.RunContainerOptions,
ref *v1.ObjectReference,
imageRef string,
netMode string,
ipcMode string,
utsMode string,
@ -765,7 +766,7 @@ func (dm *DockerManager) runContainer(
Name: containerName,
Config: &dockercontainer.Config{
Env: makeEnvList(opts.Envs),
Image: container.Image,
Image: imageRef,
WorkingDir: container.WorkingDir,
Labels: labels,
// Interactive containers:
@ -958,13 +959,37 @@ func (dm *DockerManager) ListImages() ([]kubecontainer.Image, error) {
return images, nil
}
// GetImageRef returns the image digest if exists, or else returns the image ID.
// It is exported for reusing in dockershim.
func GetImageRef(client DockerInterface, image string) (string, error) {
img, err := client.InspectImageByRef(image)
if err != nil {
return "", err
}
if img == nil {
return "", fmt.Errorf("unable to inspect image %s", image)
}
// Returns the digest if it exist.
if len(img.RepoDigests) > 0 {
return img.RepoDigests[0], nil
}
return img.ID, nil
}
// PullImage pulls an image from network to local storage.
func (dm *DockerManager) PullImage(image kubecontainer.ImageSpec, secrets []v1.Secret) error {
return dm.dockerPuller.Pull(image.Image, secrets)
func (dm *DockerManager) PullImage(image kubecontainer.ImageSpec, secrets []v1.Secret) (string, error) {
err := dm.dockerPuller.Pull(image.Image, secrets)
if err != nil {
return "", err
}
return GetImageRef(dm.client, image.Image)
}
// IsImagePresent checks whether the container image is already in the local storage.
func (dm *DockerManager) IsImagePresent(image kubecontainer.ImageSpec) (bool, error) {
func (dm *DockerManager) IsImagePresent(image kubecontainer.ImageSpec) (string, error) {
return dm.dockerPuller.IsImagePresent(image.Image)
}
@ -1683,7 +1708,7 @@ func (dm *DockerManager) applyOOMScoreAdj(pod *v1.Pod, container *v1.Container,
// Run a single container from a pod. Returns the docker container ID
// If do not need to pass labels, just pass nil.
func (dm *DockerManager) runContainerInPod(pod *v1.Pod, container *v1.Container, netMode, ipcMode, pidMode, podIP string, restartCount int) (kubecontainer.ContainerID, error) {
func (dm *DockerManager) runContainerInPod(pod *v1.Pod, container *v1.Container, netMode, ipcMode, pidMode, podIP, imageRef string, restartCount int) (kubecontainer.ContainerID, error) {
start := time.Now()
defer func() {
metrics.ContainerManagerLatency.WithLabelValues("runContainerInPod").Observe(metrics.SinceInMicroseconds(start))
@ -1708,7 +1733,7 @@ func (dm *DockerManager) runContainerInPod(pod *v1.Pod, container *v1.Container,
oomScoreAdj := dm.calculateOomScoreAdj(pod, container)
id, err := dm.runContainer(pod, container, opts, ref, netMode, ipcMode, utsMode, pidMode, restartCount, oomScoreAdj)
id, err := dm.runContainer(pod, container, opts, ref, imageRef, netMode, ipcMode, utsMode, pidMode, restartCount, oomScoreAdj)
if err != nil {
return kubecontainer.ContainerID{}, fmt.Errorf("runContainer: %v", err)
}
@ -1888,12 +1913,13 @@ func (dm *DockerManager) createPodInfraContainer(pod *v1.Pod) (kubecontainer.Doc
// No pod secrets for the infra container.
// The message isn't needed for the Infra container
if err, msg := dm.imagePuller.EnsureImageExists(pod, container, nil); err != nil {
imageRef, msg, err := dm.imagePuller.EnsureImageExists(pod, container, nil)
if err != nil {
return "", err, msg
}
// Currently we don't care about restart count of infra container, just set it to 0.
id, err := dm.runContainerInPod(pod, container, netNamespace, getIPCMode(pod), getPidMode(pod), "", 0)
id, err := dm.runContainerInPod(pod, container, netNamespace, getIPCMode(pod), getPidMode(pod), "", imageRef, 0)
if err != nil {
return "", kubecontainer.ErrRunContainer, err.Error()
}
@ -2305,7 +2331,7 @@ func (dm *DockerManager) SyncPod(pod *v1.Pod, _ v1.PodStatus, podStatus *kubecon
// tryContainerStart attempts to pull and start the container, returning an error and a reason string if the start
// was not successful.
func (dm *DockerManager) tryContainerStart(container *v1.Container, pod *v1.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, namespaceMode, pidMode, podIP string) (err error, reason string) {
err, msg := dm.imagePuller.EnsureImageExists(pod, container, pullSecrets)
imageRef, msg, err := dm.imagePuller.EnsureImageExists(pod, container, pullSecrets)
if err != nil {
return err, msg
}
@ -2331,7 +2357,7 @@ func (dm *DockerManager) tryContainerStart(container *v1.Container, pod *v1.Pod,
netMode = namespaceMode
}
_, err = dm.runContainerInPod(pod, container, netMode, namespaceMode, pidMode, podIP, restartCount)
_, err = dm.runContainerInPod(pod, container, netMode, namespaceMode, pidMode, podIP, imageRef, restartCount)
if err != nil {
// TODO(bburns) : Perhaps blacklist a container after N failures?
return kubecontainer.ErrRunContainer, err.Error()

View File

@ -112,8 +112,8 @@ func newFakeImageManager() images.ImageManager {
return &fakeImageManager{}
}
func (m *fakeImageManager) EnsureImageExists(pod *v1.Pod, container *v1.Container, pullSecrets []v1.Secret) (error, string) {
return nil, ""
func (m *fakeImageManager) EnsureImageExists(pod *v1.Pod, container *v1.Container, pullSecrets []v1.Secret) (string, string, error) {
return container.Image, "", nil
}
func createTestDockerManager(fakeHTTPClient *fakeHTTP, fakeDocker *FakeDockerClient) (*DockerManager, *FakeDockerClient) {
@ -647,9 +647,9 @@ func TestSyncPodCreatesNetAndContainerPullsImage(t *testing.T) {
verifyCalls(t, fakeDocker, []string{
// Create pod infra container.
"create", "start", "inspect_container", "inspect_container",
"inspect_image", "create", "start", "inspect_container", "inspect_container",
// Create container.
"create", "start", "inspect_container",
"inspect_image", "create", "start", "inspect_container",
})
fakeDocker.Lock()

View File

@ -592,18 +592,18 @@ func (f *FakeDockerPuller) Pull(image string, secrets []v1.Secret) (err error) {
return err
}
func (f *FakeDockerPuller) IsImagePresent(name string) (bool, error) {
func (f *FakeDockerPuller) IsImagePresent(name string) (string, error) {
f.Lock()
defer f.Unlock()
if f.HasImages == nil {
return true, nil
return name, nil
}
for _, s := range f.HasImages {
if s == name {
return true, nil
return s, nil
}
}
return false, nil
return "", nil
}
func (f *FakeDockerClient) ImageHistory(id string) ([]dockertypes.ImageHistory, error) {
f.Lock()