浏览代码

Pull image regardless of whether it exists locally if `tag=latest`

... and pull policy is `missing` or `if_not_present`

Signed-off-by: Laura Brehm <[email protected]>
Laura Brehm 3 年之前
父节点
当前提交
235734823e

+ 14 - 1
pkg/compose/pull.go

@@ -88,7 +88,7 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
 			})
 			continue
 		case types.PullPolicyMissing, types.PullPolicyIfNotPresent:
-			if _, ok := images[service.Image]; ok {
+			if imageAlreadyPresent(service.Image, images) {
 				w.Event(progress.Event{
 					ID:     service.Name,
 					Status: progress.Done,
@@ -133,6 +133,19 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
 	return err
 }
 
+func imageAlreadyPresent(serviceImage string, localImages map[string]string) bool {
+	normalizedImage, err := reference.ParseDockerRef(serviceImage)
+	if err != nil {
+		return false
+	}
+	tagged, ok := normalizedImage.(reference.NamedTagged)
+	if !ok {
+		return false
+	}
+	_, ok = localImages[serviceImage]
+	return ok && tagged.Tag() != "latest"
+}
+
 func (s *composeService) pullServiceImage(ctx context.Context, service types.ServiceConfig, info moby.Info, configFile driver.Auth, w progress.Writer, quietPull bool) (string, error) {
 	w.Event(progress.Event{
 		ID:     service.Name,

+ 0 - 55
pkg/e2e/compose_test.go

@@ -119,61 +119,6 @@ func TestLocalComposeUp(t *testing.T) {
 	})
 }
 
-func TestComposePull(t *testing.T) {
-	c := NewParallelCLI(t)
-
-	t.Run("Verify image pulled", func(t *testing.T) {
-		// cleanup existing images
-		c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/simple", "down", "--rmi", "all")
-
-		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/simple", "pull")
-		output := res.Combined()
-
-		assert.Assert(t, strings.Contains(output, "simple Pulled"))
-		assert.Assert(t, strings.Contains(output, "another Pulled"))
-
-		// verify default policy is 'always' for pull command
-		res = c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/simple", "pull")
-		output = res.Combined()
-
-		assert.Assert(t, strings.Contains(output, "simple Pulled"))
-		assert.Assert(t, strings.Contains(output, "another Pulled"))
-	})
-
-	t.Run("Verify a image is pulled once", func(t *testing.T) {
-		// cleanup existing images
-		c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/duplicate-images", "down", "--rmi", "all")
-
-		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/duplicate-images", "pull")
-		output := res.Combined()
-
-		if strings.Contains(output, "another Pulled") {
-			assert.Assert(t, strings.Contains(output, "another Pulled"))
-			assert.Assert(t, strings.Contains(output, "Skipped - Image is already being pulled by another"))
-		} else {
-			assert.Assert(t, strings.Contains(output, "simple Pulled"))
-			assert.Assert(t, strings.Contains(output, "Skipped - Image is already being pulled by simple"))
-		}
-	})
-
-	t.Run("Verify skipped pull if image is already present locally", func(t *testing.T) {
-		// make sure the required image is present
-		c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/image-present-locally", "pull")
-
-		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/image-present-locally", "pull")
-		output := res.Combined()
-
-		assert.Assert(t, strings.Contains(output, "Skipped - Image is already present locally"))
-	})
-
-	t.Run("Verify skipped no image to be pulled", func(t *testing.T) {
-		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/no-image-name-given", "pull")
-		output := res.Combined()
-
-		assert.Assert(t, strings.Contains(output, "Skipped - No image to be pulled"))
-	})
-}
-
 func TestDownComposefileInParentFolder(t *testing.T) {
 	c := NewParallelCLI(t)
 

+ 4 - 0
pkg/e2e/fixtures/compose-pull/image-present-locally/docker-compose.yaml

@@ -3,3 +3,7 @@ services:
     image: alpine:3.13.12
     pull_policy: missing
     command: top
+  latest:
+    image: alpine:latest
+    pull_policy: missing
+    command: top

+ 81 - 0
pkg/e2e/pull_test.go

@@ -0,0 +1,81 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package e2e
+
+import (
+	"strings"
+	"testing"
+
+	"gotest.tools/v3/assert"
+)
+
+func TestComposePull(t *testing.T) {
+	c := NewParallelCLI(t)
+
+	t.Run("Verify image pulled", func(t *testing.T) {
+		// cleanup existing images
+		c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/simple", "down", "--rmi", "all")
+
+		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/simple", "pull")
+		output := res.Combined()
+
+		assert.Assert(t, strings.Contains(output, "simple Pulled"))
+		assert.Assert(t, strings.Contains(output, "another Pulled"))
+
+		// verify default policy is 'always' for pull command
+		res = c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/simple", "pull")
+		output = res.Combined()
+
+		assert.Assert(t, strings.Contains(output, "simple Pulled"))
+		assert.Assert(t, strings.Contains(output, "another Pulled"))
+	})
+
+	t.Run("Verify a image is pulled once", func(t *testing.T) {
+		// cleanup existing images
+		c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/duplicate-images", "down", "--rmi", "all")
+
+		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/duplicate-images", "pull")
+		output := res.Combined()
+
+		if strings.Contains(output, "another Pulled") {
+			assert.Assert(t, strings.Contains(output, "another Pulled"))
+			assert.Assert(t, strings.Contains(output, "Skipped - Image is already being pulled by another"))
+		} else {
+			assert.Assert(t, strings.Contains(output, "simple Pulled"))
+			assert.Assert(t, strings.Contains(output, "Skipped - Image is already being pulled by simple"))
+		}
+	})
+
+	t.Run("Verify skipped pull if image is already present locally", func(t *testing.T) {
+		// make sure the required image is present
+		c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/image-present-locally", "pull")
+
+		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/image-present-locally", "pull")
+		output := res.Combined()
+
+		assert.Assert(t, strings.Contains(output, "simple Skipped - Image is already present locally"))
+		// image with :latest tag gets pulled regardless if pull_policy: missing or if_not_present
+		assert.Assert(t, strings.Contains(output, "latest Pulled"))
+	})
+
+	t.Run("Verify skipped no image to be pulled", func(t *testing.T) {
+		res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/no-image-name-given", "pull")
+		output := res.Combined()
+
+		assert.Assert(t, strings.Contains(output, "Skipped - No image to be pulled"))
+	})
+}