diff --git a/go.mod b/go.mod index 139eb56a4..0dd61619d 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/containerd/log v0.1.0 github.com/containerd/nri v0.8.0 github.com/containerd/otelttrpc v0.1.0 - github.com/containerd/platforms v1.0.0-rc.0 + github.com/containerd/platforms v1.0.0-rc.1 github.com/containerd/plugin v1.0.0 github.com/containerd/ttrpc v1.2.7 github.com/containerd/typeurl/v2 v2.2.3 diff --git a/go.sum b/go.sum index e666d381d..7e86fad33 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/containerd/nri v0.8.0 h1:n1S753B9lX8RFrHYeSgwVvS1yaUcHjxbB+f+xzEncRI= github.com/containerd/nri v0.8.0/go.mod h1:uSkgBrCdEtAiEz4vnrq8gmAC4EnVAM5Klt0OuK5rZYQ= github.com/containerd/otelttrpc v0.1.0 h1:UOX68eVTE8H/T45JveIg+I22Ev2aFj4qPITCmXsskjw= github.com/containerd/otelttrpc v0.1.0/go.mod h1:XhoA2VvaGPW1clB2ULwrBZfXVuEWuyOd2NUD1IM0yTg= -github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= -github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= +github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E= +github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= diff --git a/vendor/github.com/containerd/platforms/compare.go b/vendor/github.com/containerd/platforms/compare.go index 0abe54140..24403f3b3 100644 --- a/vendor/github.com/containerd/platforms/compare.go +++ b/vendor/github.com/containerd/platforms/compare.go @@ -31,6 +31,34 @@ type MatchComparer interface { Less(specs.Platform, specs.Platform) bool } +type platformVersions struct { + major []int + minor []int +} + +var arm64variantToVersion = map[string]platformVersions{ + "v8": {[]int{8}, []int{0}}, + "v8.0": {[]int{8}, []int{0}}, + "v8.1": {[]int{8}, []int{1}}, + "v8.2": {[]int{8}, []int{2}}, + "v8.3": {[]int{8}, []int{3}}, + "v8.4": {[]int{8}, []int{4}}, + "v8.5": {[]int{8}, []int{5}}, + "v8.6": {[]int{8}, []int{6}}, + "v8.7": {[]int{8}, []int{7}}, + "v8.8": {[]int{8}, []int{8}}, + "v8.9": {[]int{8}, []int{9}}, + "v9": {[]int{9, 8}, []int{0, 5}}, + "v9.0": {[]int{9, 8}, []int{0, 5}}, + "v9.1": {[]int{9, 8}, []int{1, 6}}, + "v9.2": {[]int{9, 8}, []int{2, 7}}, + "v9.3": {[]int{9, 8}, []int{3, 8}}, + "v9.4": {[]int{9, 8}, []int{4, 9}}, + "v9.5": {[]int{9, 8}, []int{5, 9}}, + "v9.6": {[]int{9, 8}, []int{6, 9}}, + "v9.7": {[]int{9, 8}, []int{7, 9}}, +} + // platformVector returns an (ordered) vector of appropriate specs.Platform // objects to try matching for the given platform object (see platforms.Only). func platformVector(platform specs.Platform) []specs.Platform { @@ -73,52 +101,19 @@ func platformVector(platform specs.Platform) []specs.Platform { variant = "v8" } - majorVariant, minorVariant, hasMinor := strings.Cut(variant, ".") - if armMajor, err := strconv.Atoi(strings.TrimPrefix(majorVariant, "v")); err == nil && armMajor >= 8 { - armMinor := 0 - if len(variant) == 4 { - if minor, err := strconv.Atoi(minorVariant); err == nil && hasMinor { - armMinor = minor - } - } - - if armMajor == 9 { - for minor := armMinor - 1; minor >= 0; minor-- { - arm64Variant := "v" + strconv.Itoa(armMajor) + "." + strconv.Itoa(minor) - if minor == 0 { - arm64Variant = "v" + strconv.Itoa(armMajor) - } - vector = append(vector, specs.Platform{ - Architecture: platform.Architecture, - OS: platform.OS, - OSVersion: platform.OSVersion, - OSFeatures: platform.OSFeatures, - Variant: arm64Variant, - }) - } - - // v9.0 diverged from v8.5, meaning that v9.x is compatible with v8.{x+5} until v9.4/v8.9 - armMinor = armMinor + 5 - if armMinor > 9 { - armMinor = 9 - } - armMajor = 8 - vector = append(vector, specs.Platform{ - Architecture: platform.Architecture, - OS: platform.OS, - OSVersion: platform.OSVersion, - OSFeatures: platform.OSFeatures, - Variant: "v8." + strconv.Itoa(armMinor), - }) - } - - for minor := armMinor - 1; minor >= 0; minor-- { - arm64Variant := "v" + strconv.Itoa(armMajor) + "." + strconv.Itoa(minor) + vector = []specs.Platform{} // Reset vector, the first variant will be added in loop. + arm64Versions, ok := arm64variantToVersion[variant] + if !ok { + break + } + for i, major := range arm64Versions.major { + for minor := arm64Versions.minor[i]; minor >= 0; minor-- { + arm64Variant := "v" + strconv.Itoa(major) + "." + strconv.Itoa(minor) if minor == 0 { - arm64Variant = "v" + strconv.Itoa(armMajor) + arm64Variant = "v" + strconv.Itoa(major) } vector = append(vector, specs.Platform{ - Architecture: platform.Architecture, + Architecture: "arm64", OS: platform.OS, OSVersion: platform.OSVersion, OSFeatures: platform.OSFeatures, @@ -129,7 +124,7 @@ func platformVector(platform specs.Platform) []specs.Platform { // All arm64/v8.x and arm64/v9.x are compatible with arm/v8 (32-bits) and below. // There's no arm64 v9 variant, so it's normalized to v8. - if strings.HasPrefix(variant, "v8.") || strings.HasPrefix(variant, "v9.") { + if strings.HasPrefix(variant, "v8") || strings.HasPrefix(variant, "v9") { variant = "v8" } vector = append(vector, platformVector(specs.Platform{ diff --git a/vendor/github.com/containerd/platforms/database.go b/vendor/github.com/containerd/platforms/database.go index 4c7c66960..7a6f0d98c 100644 --- a/vendor/github.com/containerd/platforms/database.go +++ b/vendor/github.com/containerd/platforms/database.go @@ -86,22 +86,11 @@ func normalizeArch(arch, variant string) (string, string) { } case "aarch64", "arm64": arch = "arm64" - majorVariant, minorVariant, hasMinor := strings.Cut(variant, ".") - majorVariant = strings.TrimPrefix(majorVariant, "v") - if minorVariant == "0" { - minorVariant = "" - hasMinor = false - } - - if (majorVariant == "" || majorVariant == "8") && !hasMinor { - // normalize v8 to empty string + switch variant { + case "8", "v8", "v8.0": variant = "" - } else { - // otherwise to v8.x or v9 or v9.x - variant = "v" + majorVariant - if hasMinor { - variant = variant + "." + minorVariant - } + case "9", "9.0", "v9.0": + variant = "v9" } case "armhf": arch = "arm" diff --git a/vendor/github.com/containerd/platforms/defaults_windows.go b/vendor/github.com/containerd/platforms/defaults_windows.go index 8bae4eb00..0165adea7 100644 --- a/vendor/github.com/containerd/platforms/defaults_windows.go +++ b/vendor/github.com/containerd/platforms/defaults_windows.go @@ -19,8 +19,6 @@ package platforms import ( "fmt" "runtime" - "strconv" - "strings" specs "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sys/windows" @@ -38,80 +36,6 @@ func DefaultSpec() specs.Platform { } } -type windowsmatcher struct { - specs.Platform - osVersionPrefix string - defaultMatcher Matcher -} - -// Match matches platform with the same windows major, minor -// and build version. -func (m windowsmatcher) Match(p specs.Platform) bool { - match := m.defaultMatcher.Match(p) - - if match && m.OS == "windows" { - // HPC containers do not have OS version filled - if m.OSVersion == "" || p.OSVersion == "" { - return true - } - - hostOsVersion := getOSVersion(m.osVersionPrefix) - ctrOsVersion := getOSVersion(p.OSVersion) - return checkHostAndContainerCompat(hostOsVersion, ctrOsVersion) - } - - return match -} - -func getOSVersion(osVersionPrefix string) osVersion { - parts := strings.Split(osVersionPrefix, ".") - if len(parts) < 3 { - return osVersion{} - } - - majorVersion, _ := strconv.ParseUint(parts[0], 10, 8) - minorVersion, _ := strconv.ParseUint(parts[1], 10, 8) - buildNumber, _ := strconv.ParseUint(parts[2], 10, 16) - - return osVersion{ - MajorVersion: uint8(majorVersion), - MinorVersion: uint8(minorVersion), - Build: uint16(buildNumber), - } -} - -// Less sorts matched platforms in front of other platforms. -// For matched platforms, it puts platforms with larger revision -// number in front. -func (m windowsmatcher) Less(p1, p2 specs.Platform) bool { - m1, m2 := m.Match(p1), m.Match(p2) - if m1 && m2 { - r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion) - return r1 > r2 - } - return m1 && !m2 -} - -func revision(v string) int { - parts := strings.Split(v, ".") - if len(parts) < 4 { - return 0 - } - r, err := strconv.Atoi(parts[3]) - if err != nil { - return 0 - } - return r -} - -func prefix(v string) string { - parts := strings.Split(v, ".") - if len(parts) < 4 { - return v - } - return strings.Join(parts[0:3], ".") -} - // Default returns the current platform's default platform specification. func Default() MatchComparer { return Only(DefaultSpec()) diff --git a/vendor/github.com/containerd/platforms/platform_compat_windows.go b/vendor/github.com/containerd/platforms/platform_windows_compat.go similarity index 58% rename from vendor/github.com/containerd/platforms/platform_compat_windows.go rename to vendor/github.com/containerd/platforms/platform_windows_compat.go index 89e66f0c0..7f3d9966b 100644 --- a/vendor/github.com/containerd/platforms/platform_compat_windows.go +++ b/vendor/github.com/containerd/platforms/platform_windows_compat.go @@ -16,9 +16,16 @@ package platforms -// osVersion is a wrapper for Windows version information +import ( + "strconv" + "strings" + + specs "github.com/opencontainers/image-spec/specs-go/v1" +) + +// windowsOSVersion is a wrapper for Windows version information // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx -type osVersion struct { +type windowsOSVersion struct { Version uint32 MajorVersion uint8 MinorVersion uint8 @@ -55,7 +62,7 @@ var compatLTSCReleases = []uint16{ // Every release after WS 2022 will support the previous ltsc // container image. Stable ABI is in preview mode for windows 11 client. // Refer: https://learn.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-2022%2Cwindows-10#windows-server-host-os-compatibility -func checkHostAndContainerCompat(host, ctr osVersion) bool { +func checkWindowsHostAndContainerCompat(host, ctr windowsOSVersion) bool { // check major minor versions of host and guest if host.MajorVersion != ctr.MajorVersion || host.MinorVersion != ctr.MinorVersion { @@ -76,3 +83,74 @@ func checkHostAndContainerCompat(host, ctr osVersion) bool { } return ctr.Build >= supportedLtscRelease && ctr.Build <= host.Build } + +func getWindowsOSVersion(osVersionPrefix string) windowsOSVersion { + if strings.Count(osVersionPrefix, ".") < 2 { + return windowsOSVersion{} + } + + major, extra, _ := strings.Cut(osVersionPrefix, ".") + minor, extra, _ := strings.Cut(extra, ".") + build, _, _ := strings.Cut(extra, ".") + + majorVersion, err := strconv.ParseUint(major, 10, 8) + if err != nil { + return windowsOSVersion{} + } + + minorVersion, err := strconv.ParseUint(minor, 10, 8) + if err != nil { + return windowsOSVersion{} + } + buildNumber, err := strconv.ParseUint(build, 10, 16) + if err != nil { + return windowsOSVersion{} + } + + return windowsOSVersion{ + MajorVersion: uint8(majorVersion), + MinorVersion: uint8(minorVersion), + Build: uint16(buildNumber), + } +} + +func winRevision(v string) int { + parts := strings.Split(v, ".") + if len(parts) < 4 { + return 0 + } + r, err := strconv.Atoi(parts[3]) + if err != nil { + return 0 + } + return r +} + +type windowsVersionMatcher struct { + windowsOSVersion +} + +func (m windowsVersionMatcher) Match(v string) bool { + if m.isEmpty() || v == "" { + return true + } + osv := getWindowsOSVersion(v) + return checkWindowsHostAndContainerCompat(m.windowsOSVersion, osv) +} + +func (m windowsVersionMatcher) isEmpty() bool { + return m.MajorVersion == 0 && m.MinorVersion == 0 && m.Build == 0 +} + +type windowsMatchComparer struct { + Matcher +} + +func (c *windowsMatchComparer) Less(p1, p2 specs.Platform) bool { + m1, m2 := c.Match(p1), c.Match(p2) + if m1 && m2 { + r1, r2 := winRevision(p1.OSVersion), winRevision(p2.OSVersion) + return r1 > r2 + } + return m1 && !m2 +} diff --git a/vendor/github.com/containerd/platforms/platforms.go b/vendor/github.com/containerd/platforms/platforms.go index 7a84449c0..14d65abd4 100644 --- a/vendor/github.com/containerd/platforms/platforms.go +++ b/vendor/github.com/containerd/platforms/platforms.go @@ -144,18 +144,51 @@ type Matcher interface { // // Applications should opt to use `Match` over directly parsing specifiers. func NewMatcher(platform specs.Platform) Matcher { - return newDefaultMatcher(platform) + m := &matcher{ + Platform: Normalize(platform), + } + + if platform.OS == "windows" { + m.osvM = &windowsVersionMatcher{ + windowsOSVersion: getWindowsOSVersion(platform.OSVersion), + } + // In prior versions, on windows, the returned matcher implements a + // MatchComprarer interface. + // This preserves that behavior for backwards compatibility. + // + // TODO: This isn't actually used in this package, except for a test case, + // which may have been an unintended side of some refactor. + // It was likely intended to be used in `Ordered` but it is not since + // `Less` that is implemented here ends up getting masked due to wrapping. + if runtime.GOOS == "windows" { + return &windowsMatchComparer{m} + } + } + return m +} + +type osVerMatcher interface { + Match(string) bool } type matcher struct { specs.Platform + osvM osVerMatcher } func (m *matcher) Match(platform specs.Platform) bool { normalized := Normalize(platform) return m.OS == normalized.OS && m.Architecture == normalized.Architecture && - m.Variant == normalized.Variant + m.Variant == normalized.Variant && + m.matchOSVersion(platform) +} + +func (m *matcher) matchOSVersion(platform specs.Platform) bool { + if m.osvM != nil { + return m.osvM.Match(platform.OSVersion) + } + return true } func (m *matcher) String() string { diff --git a/vendor/github.com/containerd/platforms/platforms_other.go b/vendor/github.com/containerd/platforms/platforms_other.go deleted file mode 100644 index 03f4dcd99..000000000 --- a/vendor/github.com/containerd/platforms/platforms_other.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build !windows - -/* - Copyright The containerd 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 platforms - -import ( - specs "github.com/opencontainers/image-spec/specs-go/v1" -) - -// NewMatcher returns the default Matcher for containerd -func newDefaultMatcher(platform specs.Platform) Matcher { - return &matcher{ - Platform: Normalize(platform), - } -} diff --git a/vendor/github.com/containerd/platforms/platforms_windows.go b/vendor/github.com/containerd/platforms/platforms_windows.go deleted file mode 100644 index 950e2a2dd..000000000 --- a/vendor/github.com/containerd/platforms/platforms_windows.go +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright The containerd 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 platforms - -import ( - specs "github.com/opencontainers/image-spec/specs-go/v1" -) - -// NewMatcher returns a Windows matcher that will match on osVersionPrefix if -// the platform is Windows otherwise use the default matcher -func newDefaultMatcher(platform specs.Platform) Matcher { - prefix := prefix(platform.OSVersion) - return windowsmatcher{ - Platform: platform, - osVersionPrefix: prefix, - defaultMatcher: &matcher{ - Platform: Normalize(platform), - }, - } -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 0c4a04535..4fb8bb609 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -183,7 +183,7 @@ github.com/containerd/nri/types/v1 ## explicit; go 1.21 github.com/containerd/otelttrpc github.com/containerd/otelttrpc/internal -# github.com/containerd/platforms v1.0.0-rc.0 +# github.com/containerd/platforms v1.0.0-rc.1 ## explicit; go 1.20 github.com/containerd/platforms # github.com/containerd/plugin v1.0.0