| package cache // import "github.com/docker/docker/image/cache" | |
| import ( | |
| "github.com/docker/docker/api/types/container" | |
| ) | |
| // 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 { | |
| return false | |
| } | |
| 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.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.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 | |
| } | |
| } | |
| for k := range a.ExposedPorts { | |
| if _, exists := b.ExposedPorts[k]; !exists { | |
| 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.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 | |
| } |