Merge pull request #4298 from justenwalker/docker-driver-digest-tags
driver/docker: pull image with digest
This commit is contained in:
commit
d95698e2c5
|
@ -1500,10 +1500,7 @@ func (d *DockerDriver) Periodic() (bool, time.Duration) {
|
||||||
// loading it from the file system
|
// loading it from the file system
|
||||||
func (d *DockerDriver) createImage(driverConfig *DockerDriverConfig, client *docker.Client, taskDir *allocdir.TaskDir) (string, error) {
|
func (d *DockerDriver) createImage(driverConfig *DockerDriverConfig, client *docker.Client, taskDir *allocdir.TaskDir) (string, error) {
|
||||||
image := driverConfig.ImageName
|
image := driverConfig.ImageName
|
||||||
repo, tag := docker.ParseRepositoryTag(image)
|
repo, tag := parseDockerImage(image)
|
||||||
if tag == "" {
|
|
||||||
tag = "latest"
|
|
||||||
}
|
|
||||||
|
|
||||||
coordinator, callerID := d.getDockerCoordinator(client)
|
coordinator, callerID := d.getDockerCoordinator(client)
|
||||||
|
|
||||||
|
@ -1511,7 +1508,7 @@ func (d *DockerDriver) createImage(driverConfig *DockerDriverConfig, client *doc
|
||||||
// is "latest", or ForcePull is set, we have to check for a new version every time so we don't
|
// is "latest", or ForcePull is set, we have to check for a new version every time so we don't
|
||||||
// bother to check and cache the id here. We'll download first, then cache.
|
// bother to check and cache the id here. We'll download first, then cache.
|
||||||
if driverConfig.ForcePull {
|
if driverConfig.ForcePull {
|
||||||
d.logger.Printf("[DEBUG] driver.docker: force pull image '%s:%s' instead of inspecting local", repo, tag)
|
d.logger.Printf("[DEBUG] driver.docker: force pull image '%s' instead of inspecting local", dockerImageRef(repo, tag))
|
||||||
} else if tag != "latest" {
|
} else if tag != "latest" {
|
||||||
if dockerImage, _ := client.InspectImage(image); dockerImage != nil {
|
if dockerImage, _ := client.InspectImage(image); dockerImage != nil {
|
||||||
// Image exists so just increment its reference count
|
// Image exists so just increment its reference count
|
||||||
|
@ -1544,7 +1541,7 @@ func (d *DockerDriver) pullImage(driverConfig *DockerDriverConfig, client *docke
|
||||||
d.logger.Printf("[DEBUG] driver.docker: did not find docker auth for repo %q", repo)
|
d.logger.Printf("[DEBUG] driver.docker: did not find docker auth for repo %q", repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.emitEvent("Downloading image %s:%s", repo, tag)
|
d.emitEvent("Downloading image %s", dockerImageRef(repo, tag))
|
||||||
coordinator, callerID := d.getDockerCoordinator(client)
|
coordinator, callerID := d.getDockerCoordinator(client)
|
||||||
|
|
||||||
return coordinator.PullImage(driverConfig.ImageName, authOptions, callerID, d.emitEvent)
|
return coordinator.PullImage(driverConfig.ImageName, authOptions, callerID, d.emitEvent)
|
||||||
|
@ -2185,3 +2182,25 @@ type createContainerClient interface {
|
||||||
ListContainers(docker.ListContainersOptions) ([]docker.APIContainers, error)
|
ListContainers(docker.ListContainersOptions) ([]docker.APIContainers, error)
|
||||||
RemoveContainer(opts docker.RemoveContainerOptions) error
|
RemoveContainer(opts docker.RemoveContainerOptions) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseDockerImage(image string) (repo, tag string) {
|
||||||
|
repo, tag = docker.ParseRepositoryTag(image)
|
||||||
|
if tag != "" {
|
||||||
|
return repo, tag
|
||||||
|
}
|
||||||
|
if i := strings.IndexRune(image, '@'); i > -1 { // Has digest (@sha256:...)
|
||||||
|
// when pulling images with a digest, the repository contains the sha hash, and the tag is empty
|
||||||
|
// see: https://github.com/fsouza/go-dockerclient/blob/master/image_test.go#L471
|
||||||
|
repo = image
|
||||||
|
} else {
|
||||||
|
tag = "latest"
|
||||||
|
}
|
||||||
|
return repo, tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func dockerImageRef(repo string, tag string) string {
|
||||||
|
if tag == "" {
|
||||||
|
return repo
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s:%s", repo, tag)
|
||||||
|
}
|
||||||
|
|
|
@ -178,10 +178,7 @@ func (d *dockerCoordinator) PullImage(image string, authOptions *docker.AuthConf
|
||||||
func (d *dockerCoordinator) pullImageImpl(image string, authOptions *docker.AuthConfiguration, future *pullFuture) {
|
func (d *dockerCoordinator) pullImageImpl(image string, authOptions *docker.AuthConfiguration, future *pullFuture) {
|
||||||
defer d.clearPullLogger(image)
|
defer d.clearPullLogger(image)
|
||||||
// Parse the repo and tag
|
// Parse the repo and tag
|
||||||
repo, tag := docker.ParseRepositoryTag(image)
|
repo, tag := parseDockerImage(image)
|
||||||
if tag == "" {
|
|
||||||
tag = "latest"
|
|
||||||
}
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -206,18 +203,18 @@ func (d *dockerCoordinator) pullImageImpl(image string, authOptions *docker.Auth
|
||||||
err := d.client.PullImage(pullOptions, auth)
|
err := d.client.PullImage(pullOptions, auth)
|
||||||
|
|
||||||
if ctxErr := ctx.Err(); ctxErr == context.DeadlineExceeded {
|
if ctxErr := ctx.Err(); ctxErr == context.DeadlineExceeded {
|
||||||
d.logger.Printf("[ERR] driver.docker: timeout pulling container %s:%s", repo, tag)
|
d.logger.Printf("[ERR] driver.docker: timeout pulling container %s", dockerImageRef(repo, tag))
|
||||||
future.set("", recoverablePullError(ctxErr, image))
|
future.set("", recoverablePullError(ctxErr, image))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.logger.Printf("[ERR] driver.docker: failed pulling container %s:%s: %s", repo, tag, err)
|
d.logger.Printf("[ERR] driver.docker: failed pulling container %s: %s", dockerImageRef(repo, tag), err)
|
||||||
future.set("", recoverablePullError(err, image))
|
future.set("", recoverablePullError(err, image))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d.logger.Printf("[DEBUG] driver.docker: docker pull %s:%s succeeded", repo, tag)
|
d.logger.Printf("[DEBUG] driver.docker: docker pull %s succeeded", dockerImageRef(repo, tag))
|
||||||
|
|
||||||
dockerImage, err := d.client.InspectImage(image)
|
dockerImage, err := d.client.InspectImage(image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1092,6 +1092,30 @@ func TestDockerDriver_ForcePull(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDockerDriver_ForcePull_RepoDigest(t *testing.T) {
|
||||||
|
if !tu.IsTravis() {
|
||||||
|
t.Parallel()
|
||||||
|
}
|
||||||
|
if !testutil.DockerIsConnected(t) {
|
||||||
|
t.Skip("Docker not connected")
|
||||||
|
}
|
||||||
|
|
||||||
|
task, _, _ := dockerTask(t)
|
||||||
|
task.Config["load"] = ""
|
||||||
|
task.Config["image"] = "library/busybox@sha256:58ac43b2cc92c687a32c8be6278e50a063579655fe3090125dcb2af0ff9e1a64"
|
||||||
|
localDigest := "sha256:8ac48589692a53a9b8c2d1ceaa6b402665aa7fe667ba51ccc03002300856d8c7"
|
||||||
|
task.Config["force_pull"] = "true"
|
||||||
|
|
||||||
|
client, handle, cleanup := dockerSetup(t, task)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
waitForExist(t, client, handle)
|
||||||
|
|
||||||
|
container, err := client.InspectContainer(handle.ContainerID())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, localDigest, container.Image)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDockerDriver_SecurityOpt(t *testing.T) {
|
func TestDockerDriver_SecurityOpt(t *testing.T) {
|
||||||
if !tu.IsTravis() {
|
if !tu.IsTravis() {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
@ -2458,3 +2482,41 @@ func TestDockerDriver_AdvertiseIPv6Address(t *testing.T) {
|
||||||
t.Fatalf("Got GlobalIPv6address %s want GlobalIPv6address with prefix %s", expectedPrefix, container.NetworkSettings.GlobalIPv6Address)
|
t.Fatalf("Got GlobalIPv6address %s want GlobalIPv6address with prefix %s", expectedPrefix, container.NetworkSettings.GlobalIPv6Address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseDockerImage(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Image string
|
||||||
|
Repo string
|
||||||
|
Tag string
|
||||||
|
}{
|
||||||
|
{"library/hello-world:1.0", "library/hello-world", "1.0"},
|
||||||
|
{"library/hello-world", "library/hello-world", "latest"},
|
||||||
|
{"library/hello-world:latest", "library/hello-world", "latest"},
|
||||||
|
{"library/hello-world@sha256:f5233545e43561214ca4891fd1157e1c3c563316ed8e237750d59bde73361e77", "library/hello-world@sha256:f5233545e43561214ca4891fd1157e1c3c563316ed8e237750d59bde73361e77", ""},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.Image, func(t *testing.T) {
|
||||||
|
repo, tag := parseDockerImage(test.Image)
|
||||||
|
require.Equal(t, test.Repo, repo)
|
||||||
|
require.Equal(t, test.Tag, tag)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDockerImageRef(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Image string
|
||||||
|
Repo string
|
||||||
|
Tag string
|
||||||
|
}{
|
||||||
|
{"library/hello-world:1.0", "library/hello-world", "1.0"},
|
||||||
|
{"library/hello-world:latest", "library/hello-world", "latest"},
|
||||||
|
{"library/hello-world@sha256:f5233545e43561214ca4891fd1157e1c3c563316ed8e237750d59bde73361e77", "library/hello-world@sha256:f5233545e43561214ca4891fd1157e1c3c563316ed8e237750d59bde73361e77", ""},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.Image, func(t *testing.T) {
|
||||||
|
image := dockerImageRef(test.Repo, test.Tag)
|
||||||
|
require.Equal(t, test.Image, image)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue