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>
This commit is contained in:
parent
c7b3cb101b
commit
537348763f
2 changed files with 130 additions and 89 deletions
|
@ -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(), backend.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
|
||||
}
|
||||
|
|
158
image/cache/compare.go
vendored
158
image/cache/compare.go
vendored
|
@ -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 {
|
||||
return false
|
||||
}
|
||||
if a.AttachStdout != b.AttachStdout ||
|
||||
a.AttachStderr != b.AttachStderr ||
|
||||
a.User != b.User ||
|
||||
a.OpenStdin != b.OpenStdin ||
|
||||
a.Tty != b.Tty {
|
||||
if a == nil || b == nil {
|
||||
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.Env) != len(b.Env) {
|
||||
return false
|
||||
}
|
||||
if len(a.Cmd) != len(b.Cmd) {
|
||||
return false
|
||||
}
|
||||
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.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] {
|
||||
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.Entrypoint); i++ {
|
||||
if a.Entrypoint[i] != b.Entrypoint[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
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 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
|
||||
}
|
||||
}
|
||||
for k, v := range a.Labels {
|
||||
if v != b.Labels[k] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue