Ver código fonte

image/cache: Compare all config fields

Add checks for some image config fields that were missing.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 537348763faeb7adc515305e87910e11bdb14b00)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Paweł Gronowski 1 ano atrás
pai
commit
6d05b9b65b
2 arquivos alterados com 124 adições e 83 exclusões
  1. 2 59
      daemon/containerd/cache.go
  2. 122 24
      image/cache/compare.go

+ 2 - 59
daemon/containerd/cache.go

@@ -11,6 +11,7 @@ import (
 	"github.com/docker/docker/builder"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/image"
+	"github.com/docker/docker/image/cache"
 	"github.com/opencontainers/go-digest"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 )
@@ -98,7 +99,7 @@ func (ic *localCache) GetCache(parentID string, cfg *container.Config) (imageID
 			return "", err
 		}
 
-		if isMatch(&cc, cfg) {
+		if cache.CompareConfig(&cc, cfg) {
 			childImage, err := ic.imageService.GetImage(ctx, child.String(), imagetype.GetImageOpts{})
 			if err != nil {
 				return "", err
@@ -206,61 +207,3 @@ func (ic *imageCache) isParent(ctx context.Context, img *image.Image, parentID i
 	}
 	return ic.isParent(ctx, p, parentID)
 }
-
-// compare two Config struct. Do not compare the "Image" nor "Hostname" fields
-// If OpenStdin is set, then it differs
-func isMatch(a, b *container.Config) bool {
-	if a == nil || b == nil ||
-		a.OpenStdin || b.OpenStdin {
-		return false
-	}
-	if a.AttachStdout != b.AttachStdout ||
-		a.AttachStderr != b.AttachStderr ||
-		a.User != b.User ||
-		a.OpenStdin != b.OpenStdin ||
-		a.Tty != b.Tty {
-		return false
-	}
-
-	if len(a.Cmd) != len(b.Cmd) ||
-		len(a.Env) != len(b.Env) ||
-		len(a.Labels) != len(b.Labels) ||
-		len(a.ExposedPorts) != len(b.ExposedPorts) ||
-		len(a.Entrypoint) != len(b.Entrypoint) ||
-		len(a.Volumes) != len(b.Volumes) {
-		return false
-	}
-
-	for i := 0; i < len(a.Cmd); i++ {
-		if a.Cmd[i] != b.Cmd[i] {
-			return false
-		}
-	}
-	for i := 0; i < len(a.Env); i++ {
-		if a.Env[i] != b.Env[i] {
-			return false
-		}
-	}
-	for k, v := range a.Labels {
-		if v != b.Labels[k] {
-			return false
-		}
-	}
-	for k := range a.ExposedPorts {
-		if _, exists := b.ExposedPorts[k]; !exists {
-			return false
-		}
-	}
-
-	for i := 0; i < len(a.Entrypoint); i++ {
-		if a.Entrypoint[i] != b.Entrypoint[i] {
-			return false
-		}
-	}
-	for key := range a.Volumes {
-		if _, exists := b.Volumes[key]; !exists {
-			return false
-		}
-	}
-	return true
-}

+ 122 - 24
image/cache/compare.go

@@ -4,42 +4,69 @@ import (
 	"github.com/docker/docker/api/types/container"
 )
 
-// compare two Config struct. Do not compare the "Image" nor "Hostname" fields
-// If OpenStdin is set, then it differs
+// TODO: Remove once containerd image service directly uses the ImageCache and
+// LocalImageCache structs.
+func CompareConfig(a, b *container.Config) bool {
+	return compare(a, b)
+}
+
+// compare two Config struct. Do not container-specific fields:
+// - Image
+// - Hostname
+// - Domainname
+// - MacAddress
 func compare(a, b *container.Config) bool {
-	if a == nil || b == nil ||
-		a.OpenStdin || b.OpenStdin {
+	if a == nil || b == nil {
+		return false
+	}
+
+	if len(a.Env) != len(b.Env) {
 		return false
 	}
-	if a.AttachStdout != b.AttachStdout ||
-		a.AttachStderr != b.AttachStderr ||
-		a.User != b.User ||
-		a.OpenStdin != b.OpenStdin ||
-		a.Tty != b.Tty {
+	if len(a.Cmd) != len(b.Cmd) {
 		return false
 	}
-
-	if len(a.Cmd) != len(b.Cmd) ||
-		len(a.Env) != len(b.Env) ||
-		len(a.Labels) != len(b.Labels) ||
-		len(a.ExposedPorts) != len(b.ExposedPorts) ||
-		len(a.Entrypoint) != len(b.Entrypoint) ||
-		len(a.Volumes) != len(b.Volumes) {
+	if len(a.Entrypoint) != len(b.Entrypoint) {
+		return false
+	}
+	if len(a.Shell) != len(b.Shell) {
+		return false
+	}
+	if len(a.ExposedPorts) != len(b.ExposedPorts) {
+		return false
+	}
+	if len(a.Volumes) != len(b.Volumes) {
+		return false
+	}
+	if len(a.Labels) != len(b.Labels) {
+		return false
+	}
+	if len(a.OnBuild) != len(b.OnBuild) {
 		return false
 	}
 
+	for i := 0; i < len(a.Env); i++ {
+		if a.Env[i] != b.Env[i] {
+			return false
+		}
+	}
+	for i := 0; i < len(a.OnBuild); i++ {
+		if a.OnBuild[i] != b.OnBuild[i] {
+			return false
+		}
+	}
 	for i := 0; i < len(a.Cmd); i++ {
 		if a.Cmd[i] != b.Cmd[i] {
 			return false
 		}
 	}
-	for i := 0; i < len(a.Env); i++ {
-		if a.Env[i] != b.Env[i] {
+	for i := 0; i < len(a.Entrypoint); i++ {
+		if a.Entrypoint[i] != b.Entrypoint[i] {
 			return false
 		}
 	}
-	for k, v := range a.Labels {
-		if v != b.Labels[k] {
+	for i := 0; i < len(a.Shell); i++ {
+		if a.Shell[i] != b.Shell[i] {
 			return false
 		}
 	}
@@ -48,16 +75,87 @@ func compare(a, b *container.Config) bool {
 			return false
 		}
 	}
+	for key := range a.Volumes {
+		if _, exists := b.Volumes[key]; !exists {
+			return false
+		}
+	}
+	for k, v := range a.Labels {
+		if v != b.Labels[k] {
+			return false
+		}
+	}
 
-	for i := 0; i < len(a.Entrypoint); i++ {
-		if a.Entrypoint[i] != b.Entrypoint[i] {
+	if a.AttachStdin != b.AttachStdin {
+		return false
+	}
+	if a.AttachStdout != b.AttachStdout {
+		return false
+	}
+	if a.AttachStderr != b.AttachStderr {
+		return false
+	}
+	if a.NetworkDisabled != b.NetworkDisabled {
+		return false
+	}
+	if a.Tty != b.Tty {
+		return false
+	}
+	if a.OpenStdin != b.OpenStdin {
+		return false
+	}
+	if a.StdinOnce != b.StdinOnce {
+		return false
+	}
+	if a.ArgsEscaped != b.ArgsEscaped {
+		return false
+	}
+	if a.User != b.User {
+		return false
+	}
+	if a.WorkingDir != b.WorkingDir {
+		return false
+	}
+	if a.StopSignal != b.StopSignal {
+		return false
+	}
+
+	if (a.StopTimeout == nil) != (b.StopTimeout == nil) {
+		return false
+	}
+	if a.StopTimeout != nil && b.StopTimeout != nil {
+		if *a.StopTimeout != *b.StopTimeout {
 			return false
 		}
 	}
-	for key := range a.Volumes {
-		if _, exists := b.Volumes[key]; !exists {
+	if (a.Healthcheck == nil) != (b.Healthcheck == nil) {
+		return false
+	}
+	if a.Healthcheck != nil && b.Healthcheck != nil {
+		if a.Healthcheck.Interval != b.Healthcheck.Interval {
+			return false
+		}
+		if a.Healthcheck.StartInterval != b.Healthcheck.StartInterval {
 			return false
 		}
+		if a.Healthcheck.StartPeriod != b.Healthcheck.StartPeriod {
+			return false
+		}
+		if a.Healthcheck.Timeout != b.Healthcheck.Timeout {
+			return false
+		}
+		if a.Healthcheck.Retries != b.Healthcheck.Retries {
+			return false
+		}
+		if len(a.Healthcheck.Test) != len(b.Healthcheck.Test) {
+			return false
+		}
+		for i := 0; i < len(a.Healthcheck.Test); i++ {
+			if a.Healthcheck.Test[i] != b.Healthcheck.Test[i] {
+				return false
+			}
+		}
 	}
+
 	return true
 }