Initialize platform matchers for current platform
Signed-off-by: James Sturtevant <jsturtevant@gmail.com>
This commit is contained in:
		| @@ -22,7 +22,6 @@ import ( | |||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	imagespec "github.com/opencontainers/image-spec/specs-go/v1" |  | ||||||
| 	specs "github.com/opencontainers/image-spec/specs-go/v1" | 	specs "github.com/opencontainers/image-spec/specs-go/v1" | ||||||
| 	"golang.org/x/sys/windows" | 	"golang.org/x/sys/windows" | ||||||
| ) | ) | ||||||
| @@ -39,25 +38,28 @@ func DefaultSpec() specs.Platform { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| type matchComparer struct { | type windowsmatcher struct { | ||||||
| 	defaults        Matcher | 	specs.Platform | ||||||
| 	osVersionPrefix string | 	osVersionPrefix string | ||||||
|  | 	defaultMatcher  Matcher | ||||||
| } | } | ||||||
|  |  | ||||||
| // Match matches platform with the same windows major, minor | // Match matches platform with the same windows major, minor | ||||||
| // and build version. | // and build version. | ||||||
| func (m matchComparer) Match(p imagespec.Platform) bool { | func (m windowsmatcher) Match(p specs.Platform) bool { | ||||||
| 	if m.defaults.Match(p) { | 	match := m.defaultMatcher.Match(p) | ||||||
| 		// TODO(windows): Figure out whether OSVersion is deprecated. |  | ||||||
| 		return strings.HasPrefix(p.OSVersion, m.osVersionPrefix) | 	if match && m.OS == "windows" { | ||||||
|  | 		return strings.HasPrefix(p.OSVersion, m.osVersionPrefix) && m.defaultMatcher.Match(p) | ||||||
| 	} | 	} | ||||||
| 	return false |  | ||||||
|  | 	return match | ||||||
| } | } | ||||||
|  |  | ||||||
| // Less sorts matched platforms in front of other platforms. | // Less sorts matched platforms in front of other platforms. | ||||||
| // For matched platforms, it puts platforms with larger revision | // For matched platforms, it puts platforms with larger revision | ||||||
| // number in front. | // number in front. | ||||||
| func (m matchComparer) Less(p1, p2 imagespec.Platform) bool { | func (m windowsmatcher) Less(p1, p2 specs.Platform) bool { | ||||||
| 	m1, m2 := m.Match(p1), m.Match(p2) | 	m1, m2 := m.Match(p1), m.Match(p2) | ||||||
| 	if m1 && m2 { | 	if m1 && m2 { | ||||||
| 		r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion) | 		r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion) | ||||||
| @@ -78,14 +80,15 @@ func revision(v string) int { | |||||||
| 	return r | 	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. | // Default returns the current platform's default platform specification. | ||||||
| func Default() MatchComparer { | func Default() MatchComparer { | ||||||
| 	major, minor, build := windows.RtlGetNtVersionNumbers() | 	return Only(DefaultSpec()) | ||||||
| 	return matchComparer{ |  | ||||||
| 		defaults: Ordered(DefaultSpec(), specs.Platform{ |  | ||||||
| 			OS:           "linux", |  | ||||||
| 			Architecture: runtime.GOARCH, |  | ||||||
| 		}), |  | ||||||
| 		osVersionPrefix: fmt.Sprintf("%d.%d.%d", major, minor, build), |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -47,15 +47,39 @@ func TestDefault(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestMatchComparerMatch(t *testing.T) { | func TestDefaultMatchComparer(t *testing.T) { | ||||||
|  | 	defaultMatcher := Default() | ||||||
|  |  | ||||||
|  | 	for _, test := range []struct { | ||||||
|  | 		platform imagespec.Platform | ||||||
|  | 		match    bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			platform: DefaultSpec(), | ||||||
|  | 			match:    true, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			platform: imagespec.Platform{ | ||||||
|  | 				OS:           "linux", | ||||||
|  | 				Architecture: runtime.GOARCH, | ||||||
|  | 			}, | ||||||
|  | 			match: false, | ||||||
|  | 		}, | ||||||
|  | 	} { | ||||||
|  | 		assert.Equal(t, test.match, defaultMatcher.Match(test.platform)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestMatchComparerMatch_WCOW(t *testing.T) { | ||||||
| 	major, minor, build := windows.RtlGetNtVersionNumbers() | 	major, minor, build := windows.RtlGetNtVersionNumbers() | ||||||
| 	buildStr := fmt.Sprintf("%d.%d.%d", major, minor, build) | 	buildStr := fmt.Sprintf("%d.%d.%d", major, minor, build) | ||||||
| 	m := matchComparer{ | 	m := windowsmatcher{ | ||||||
| 		defaults: Only(imagespec.Platform{ | 		Platform:        DefaultSpec(), | ||||||
| 			Architecture: "amd64", |  | ||||||
| 			OS:           "windows", |  | ||||||
| 		}), |  | ||||||
| 		osVersionPrefix: buildStr, | 		osVersionPrefix: buildStr, | ||||||
|  | 		defaultMatcher: &matcher{ | ||||||
|  | 			Platform: Normalize(DefaultSpec()), | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| 	for _, test := range []struct { | 	for _, test := range []struct { | ||||||
| 		platform imagespec.Platform | 		platform imagespec.Platform | ||||||
| @@ -106,18 +130,86 @@ func TestMatchComparerMatch(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 			match: false, | 			match: false, | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			platform: imagespec.Platform{ | ||||||
|  | 				Architecture: "amd64", | ||||||
|  | 				OS:           "linux", | ||||||
|  | 			}, | ||||||
|  | 			match: false, | ||||||
|  | 		}, | ||||||
| 	} { | 	} { | ||||||
| 		assert.Equal(t, test.match, m.Match(test.platform)) | 		assert.Equal(t, test.match, m.Match(test.platform), "should match: %t, %s to %s", test.match, m.Platform, test.platform) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestMatchComparerMatch_LCOW(t *testing.T) { | ||||||
|  | 	major, minor, build := windows.RtlGetNtVersionNumbers() | ||||||
|  | 	buildStr := fmt.Sprintf("%d.%d.%d", major, minor, build) | ||||||
|  | 	m := windowsmatcher{ | ||||||
|  | 		Platform: imagespec.Platform{ | ||||||
|  | 			OS:           "linux", | ||||||
|  | 			Architecture: "amd64", | ||||||
|  | 		}, | ||||||
|  | 		osVersionPrefix: "", | ||||||
|  | 		defaultMatcher: &matcher{ | ||||||
|  | 			Platform: Normalize(imagespec.Platform{ | ||||||
|  | 				OS:           "linux", | ||||||
|  | 				Architecture: "amd64", | ||||||
|  | 			}, | ||||||
|  | 			), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	for _, test := range []struct { | ||||||
|  | 		platform imagespec.Platform | ||||||
|  | 		match    bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			platform: DefaultSpec(), | ||||||
|  | 			match:    false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			platform: imagespec.Platform{ | ||||||
|  | 				Architecture: "amd64", | ||||||
|  | 				OS:           "windows", | ||||||
|  | 			}, | ||||||
|  | 			match: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			platform: imagespec.Platform{ | ||||||
|  | 				Architecture: "amd64", | ||||||
|  | 				OS:           "windows", | ||||||
|  | 				OSVersion:    buildStr + ".2", | ||||||
|  | 			}, | ||||||
|  | 			match: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			platform: imagespec.Platform{ | ||||||
|  | 				Architecture: "amd64", | ||||||
|  | 				OS:           "windows", | ||||||
|  | 				// Use an nonexistent Windows build so we don't get a match. Ws2019's build is 17763/ | ||||||
|  | 				OSVersion: "10.0.17762.1", | ||||||
|  | 			}, | ||||||
|  | 			match: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			platform: imagespec.Platform{ | ||||||
|  | 				Architecture: "amd64", | ||||||
|  | 				OS:           "linux", | ||||||
|  | 			}, | ||||||
|  | 			match: true, | ||||||
|  | 		}, | ||||||
|  | 	} { | ||||||
|  | 		assert.Equal(t, test.match, m.Match(test.platform), "should match %b, %s to %s", test.match, m.Platform, test.platform) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestMatchComparerLess(t *testing.T) { | func TestMatchComparerLess(t *testing.T) { | ||||||
| 	m := matchComparer{ | 	m := windowsmatcher{ | ||||||
| 		defaults: Only(imagespec.Platform{ | 		Platform:        DefaultSpec(), | ||||||
| 			Architecture: "amd64", |  | ||||||
| 			OS:           "windows", |  | ||||||
| 		}), |  | ||||||
| 		osVersionPrefix: "10.0.17763", | 		osVersionPrefix: "10.0.17763", | ||||||
|  | 		defaultMatcher: &matcher{ | ||||||
|  | 			Platform: Normalize(DefaultSpec()), | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| 	platforms := []imagespec.Platform{ | 	platforms := []imagespec.Platform{ | ||||||
| 		{ | 		{ | ||||||
|   | |||||||
| @@ -136,9 +136,7 @@ type Matcher interface { | |||||||
| // | // | ||||||
| // Applications should opt to use `Match` over directly parsing specifiers. | // Applications should opt to use `Match` over directly parsing specifiers. | ||||||
| func NewMatcher(platform specs.Platform) Matcher { | func NewMatcher(platform specs.Platform) Matcher { | ||||||
| 	return &matcher{ | 	return newDefaultMatcher(platform) | ||||||
| 		Platform: Normalize(platform), |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| type matcher struct { | type matcher struct { | ||||||
| @@ -257,5 +255,6 @@ func Format(platform specs.Platform) string { | |||||||
| func Normalize(platform specs.Platform) specs.Platform { | func Normalize(platform specs.Platform) specs.Platform { | ||||||
| 	platform.OS = normalizeOS(platform.OS) | 	platform.OS = normalizeOS(platform.OS) | ||||||
| 	platform.Architecture, platform.Variant = normalizeArch(platform.Architecture, platform.Variant) | 	platform.Architecture, platform.Variant = normalizeArch(platform.Architecture, platform.Variant) | ||||||
|  |  | ||||||
| 	return platform | 	return platform | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								platforms/platforms_other.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								platforms/platforms_other.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | //go:build !windows | ||||||
|  | // +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), | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								platforms/platforms_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								platforms/platforms_windows.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | /* | ||||||
|  |    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), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 James Sturtevant
					James Sturtevant