mirror of https://github.com/k3s-io/k3s
dockertools: add image ref to ImageService interfaces
parent
37fc81be0e
commit
fcbf39ea54
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue