2018-02-05 21:05:59 +00:00
|
|
|
package cache // import "github.com/docker/docker/image/cache"
|
2014-02-12 04:04:39 +00:00
|
|
|
|
2017-04-21 19:08:11 +00:00
|
|
|
import (
|
2024-02-05 16:38:00 +00:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/containerd/containerd/platforms"
|
2017-04-21 19:08:11 +00:00
|
|
|
"github.com/docker/docker/api/types/container"
|
2024-02-05 16:38:00 +00:00
|
|
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
2017-04-21 19:08:11 +00:00
|
|
|
)
|
2015-12-18 18:36:17 +00:00
|
|
|
|
2024-02-05 16:38:00 +00:00
|
|
|
func comparePlatform(builderPlatform, imagePlatform ocispec.Platform) bool {
|
|
|
|
// On Windows, only check the Major and Minor versions.
|
|
|
|
// The Build and Revision compatibility depends on whether `process` or
|
|
|
|
// `hyperv` isolation used.
|
|
|
|
//
|
|
|
|
// Fixes https://github.com/moby/moby/issues/47307
|
|
|
|
if builderPlatform.OS == "windows" && imagePlatform.OS == builderPlatform.OS {
|
|
|
|
// OSVersion format is:
|
|
|
|
// Major.Minor.Build.Revision
|
|
|
|
builderParts := strings.Split(builderPlatform.OSVersion, ".")
|
|
|
|
imageParts := strings.Split(imagePlatform.OSVersion, ".")
|
|
|
|
|
|
|
|
if len(builderParts) >= 3 && len(imageParts) >= 3 {
|
|
|
|
// Keep only Major & Minor.
|
|
|
|
builderParts[0] = imageParts[0]
|
|
|
|
builderParts[1] = imageParts[1]
|
|
|
|
imagePlatform.OSVersion = strings.Join(builderParts, ".")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return platforms.Only(builderPlatform).Match(imagePlatform)
|
|
|
|
}
|
|
|
|
|
2023-12-01 09:24:23 +00:00
|
|
|
// compare two Config struct. Do not container-specific fields:
|
|
|
|
// - Image
|
|
|
|
// - Hostname
|
|
|
|
// - Domainname
|
|
|
|
// - MacAddress
|
2017-01-03 18:19:27 +00:00
|
|
|
func compare(a, b *container.Config) bool {
|
2023-12-01 09:24:23 +00:00
|
|
|
if a == nil || b == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(a.Env) != len(b.Env) {
|
2014-02-12 04:04:39 +00:00
|
|
|
return false
|
|
|
|
}
|
2023-12-01 09:24:23 +00:00
|
|
|
if len(a.Cmd) != len(b.Cmd) {
|
2014-02-12 04:04:39 +00:00
|
|
|
return false
|
|
|
|
}
|
2023-12-01 09:24:23 +00:00
|
|
|
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) {
|
2014-02-12 04:04:39 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-12-01 09:24:23 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2016-02-29 11:28:37 +00:00
|
|
|
for i := 0; i < len(a.Cmd); i++ {
|
|
|
|
if a.Cmd[i] != b.Cmd[i] {
|
2014-02-12 04:04:39 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2023-12-01 09:24:23 +00:00
|
|
|
for i := 0; i < len(a.Entrypoint); i++ {
|
|
|
|
if a.Entrypoint[i] != b.Entrypoint[i] {
|
2014-02-12 04:04:39 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2023-12-01 09:24:23 +00:00
|
|
|
for i := 0; i < len(a.Shell); i++ {
|
|
|
|
if a.Shell[i] != b.Shell[i] {
|
2015-03-20 12:14:31 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2014-02-12 04:04:39 +00:00
|
|
|
for k := range a.ExposedPorts {
|
|
|
|
if _, exists := b.ExposedPorts[k]; !exists {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2023-12-01 09:24:23 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2015-04-11 00:05:21 +00:00
|
|
|
|
2023-12-01 09:24:23 +00:00
|
|
|
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 {
|
2014-02-12 04:04:39 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2023-12-01 09:24:23 +00:00
|
|
|
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 {
|
2014-02-12 04:04:39 +00:00
|
|
|
return false
|
|
|
|
}
|
2023-12-01 09:24:23 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2014-02-12 04:04:39 +00:00
|
|
|
}
|
2023-12-01 09:24:23 +00:00
|
|
|
|
2014-02-12 04:04:39 +00:00
|
|
|
return true
|
|
|
|
}
|