From bbcf564745afe1bb341e8eecd27b22bf34f33ad5 Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Wed, 4 Sep 2019 23:22:25 -0700 Subject: [PATCH] Add windows image platform comparer Signed-off-by: Lantao Liu --- cri.go | 2 + pkg/containerd/platforms/default_unix.go | 28 ++++ pkg/containerd/platforms/default_windows.go | 77 +++++++++ .../platforms/default_windows_test.go | 150 ++++++++++++++++++ 4 files changed, 257 insertions(+) create mode 100644 pkg/containerd/platforms/default_unix.go create mode 100644 pkg/containerd/platforms/default_windows.go create mode 100644 pkg/containerd/platforms/default_windows_test.go diff --git a/cri.go b/cri.go index d477c1efb..6953ef252 100644 --- a/cri.go +++ b/cri.go @@ -40,6 +40,7 @@ import ( criconfig "github.com/containerd/cri/pkg/config" "github.com/containerd/cri/pkg/constants" + criplatforms "github.com/containerd/cri/pkg/containerd/platforms" "github.com/containerd/cri/pkg/server" ) @@ -89,6 +90,7 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) { client, err := containerd.New( "", containerd.WithDefaultNamespace(constants.K8sContainerdNamespace), + containerd.WithDefaultPlatform(criplatforms.Default()), containerd.WithServices(servicesOpts...), ) if err != nil { diff --git a/pkg/containerd/platforms/default_unix.go b/pkg/containerd/platforms/default_unix.go new file mode 100644 index 000000000..f71aa60a4 --- /dev/null +++ b/pkg/containerd/platforms/default_unix.go @@ -0,0 +1,28 @@ +// +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 ( + "github.com/containerd/containerd/platforms" +) + +// Default returns the current platform's default platform specification. +func Default() platforms.MatchComparer { + return platforms.Default() +} diff --git a/pkg/containerd/platforms/default_windows.go b/pkg/containerd/platforms/default_windows.go new file mode 100644 index 000000000..29e7f61bd --- /dev/null +++ b/pkg/containerd/platforms/default_windows.go @@ -0,0 +1,77 @@ +// +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 ( + "fmt" + "strconv" + "strings" + + "github.com/containerd/containerd/platforms" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" + "golang.org/x/sys/windows" +) + +type matchComparer struct { + defaults platforms.Matcher + osVersionPrefix string +} + +// Match matches platform with the same windows major, minor +// and build version. +func (m matchComparer) Match(p imagespec.Platform) bool { + if m.defaults.Match(p) { + // TODO(windows): Figure out whether OSVersion is deprecated. + return strings.HasPrefix(p.OSVersion, m.osVersionPrefix) + } + return false +} + +// Less sorts matched platforms in front of other platforms. +// For matched platforms, it puts platforms with larger revision +// number in front. +func (m matchComparer) Less(p1, p2 imagespec.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 +} + +// Default returns the current platform's default platform specification. +func Default() platforms.MatchComparer { + major, minor, build := windows.RtlGetNtVersionNumbers() + return matchComparer{ + defaults: platforms.Only(platforms.DefaultSpec()), + osVersionPrefix: fmt.Sprintf("%d.%d.%d", major, minor, build), + } +} diff --git a/pkg/containerd/platforms/default_windows_test.go b/pkg/containerd/platforms/default_windows_test.go new file mode 100644 index 000000000..b66d95353 --- /dev/null +++ b/pkg/containerd/platforms/default_windows_test.go @@ -0,0 +1,150 @@ +// +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 ( + "sort" + "testing" + + "github.com/containerd/containerd/platforms" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/stretchr/testify/assert" +) + +func TestMatchComparerMatch(t *testing.T) { + m := matchComparer{ + defaults: platforms.Only(imagespec.Platform{ + Architecture: "amd64", + OS: "windows", + }), + osVersionPrefix: "10.0.17763", + } + for _, test := range []struct { + platform imagespec.Platform + match bool + }{ + { + platform: imagespec.Platform{ + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17763.1", + }, + match: true, + }, + { + platform: imagespec.Platform{ + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17763.2", + }, + match: true, + }, + { + platform: imagespec.Platform{ + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17762.1", + }, + match: false, + }, + { + platform: imagespec.Platform{ + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17764.1", + }, + match: false, + }, + { + platform: imagespec.Platform{ + Architecture: "amd64", + OS: "windows", + }, + match: false, + }, + } { + assert.Equal(t, test.match, m.Match(test.platform)) + } +} + +func TestMatchComparerLess(t *testing.T) { + m := matchComparer{ + defaults: platforms.Only(imagespec.Platform{ + Architecture: "amd64", + OS: "windows", + }), + osVersionPrefix: "10.0.17763", + } + platforms := []imagespec.Platform{ + { + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17764.1", + }, + { + Architecture: "amd64", + OS: "windows", + }, + { + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17763.1", + }, + { + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17763.2", + }, + { + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17762.1", + }, + } + expected := []imagespec.Platform{ + { + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17763.2", + }, + { + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17763.1", + }, + { + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17764.1", + }, + { + Architecture: "amd64", + OS: "windows", + }, + { + Architecture: "amd64", + OS: "windows", + OSVersion: "10.0.17762.1", + }, + } + sort.SliceStable(platforms, func(i, j int) bool { + return m.Less(platforms[i], platforms[j]) + }) + assert.Equal(t, expected, platforms) +}