github.com/lalkh/containerd@v1.4.3/platforms/compare.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package platforms 18 19 import specs "github.com/opencontainers/image-spec/specs-go/v1" 20 21 // MatchComparer is able to match and compare platforms to 22 // filter and sort platforms. 23 type MatchComparer interface { 24 Matcher 25 26 Less(specs.Platform, specs.Platform) bool 27 } 28 29 // Only returns a match comparer for a single platform 30 // using default resolution logic for the platform. 31 // 32 // For ARMv8, will also match ARMv7, ARMv6 and ARMv5 (for 32bit runtimes) 33 // For ARMv7, will also match ARMv6 and ARMv5 34 // For ARMv6, will also match ARMv5 35 func Only(platform specs.Platform) MatchComparer { 36 platform = Normalize(platform) 37 if platform.Architecture == "arm" { 38 if platform.Variant == "v8" { 39 return orderedPlatformComparer{ 40 matchers: []Matcher{ 41 &matcher{ 42 Platform: platform, 43 }, 44 &matcher{ 45 Platform: specs.Platform{ 46 Architecture: platform.Architecture, 47 OS: platform.OS, 48 OSVersion: platform.OSVersion, 49 OSFeatures: platform.OSFeatures, 50 Variant: "v7", 51 }, 52 }, 53 &matcher{ 54 Platform: specs.Platform{ 55 Architecture: platform.Architecture, 56 OS: platform.OS, 57 OSVersion: platform.OSVersion, 58 OSFeatures: platform.OSFeatures, 59 Variant: "v6", 60 }, 61 }, 62 &matcher{ 63 Platform: specs.Platform{ 64 Architecture: platform.Architecture, 65 OS: platform.OS, 66 OSVersion: platform.OSVersion, 67 OSFeatures: platform.OSFeatures, 68 Variant: "v5", 69 }, 70 }, 71 }, 72 } 73 } 74 if platform.Variant == "v7" { 75 return orderedPlatformComparer{ 76 matchers: []Matcher{ 77 &matcher{ 78 Platform: platform, 79 }, 80 &matcher{ 81 Platform: specs.Platform{ 82 Architecture: platform.Architecture, 83 OS: platform.OS, 84 OSVersion: platform.OSVersion, 85 OSFeatures: platform.OSFeatures, 86 Variant: "v6", 87 }, 88 }, 89 &matcher{ 90 Platform: specs.Platform{ 91 Architecture: platform.Architecture, 92 OS: platform.OS, 93 OSVersion: platform.OSVersion, 94 OSFeatures: platform.OSFeatures, 95 Variant: "v5", 96 }, 97 }, 98 }, 99 } 100 } 101 if platform.Variant == "v6" { 102 return orderedPlatformComparer{ 103 matchers: []Matcher{ 104 &matcher{ 105 Platform: platform, 106 }, 107 &matcher{ 108 Platform: specs.Platform{ 109 Architecture: platform.Architecture, 110 OS: platform.OS, 111 OSVersion: platform.OSVersion, 112 OSFeatures: platform.OSFeatures, 113 Variant: "v5", 114 }, 115 }, 116 }, 117 } 118 } 119 } 120 121 return singlePlatformComparer{ 122 Matcher: &matcher{ 123 Platform: platform, 124 }, 125 } 126 } 127 128 // Ordered returns a platform MatchComparer which matches any of the platforms 129 // but orders them in order they are provided. 130 func Ordered(platforms ...specs.Platform) MatchComparer { 131 matchers := make([]Matcher, len(platforms)) 132 for i := range platforms { 133 matchers[i] = NewMatcher(platforms[i]) 134 } 135 return orderedPlatformComparer{ 136 matchers: matchers, 137 } 138 } 139 140 // Any returns a platform MatchComparer which matches any of the platforms 141 // with no preference for ordering. 142 func Any(platforms ...specs.Platform) MatchComparer { 143 matchers := make([]Matcher, len(platforms)) 144 for i := range platforms { 145 matchers[i] = NewMatcher(platforms[i]) 146 } 147 return anyPlatformComparer{ 148 matchers: matchers, 149 } 150 } 151 152 // All is a platform MatchComparer which matches all platforms 153 // with preference for ordering. 154 var All MatchComparer = allPlatformComparer{} 155 156 type singlePlatformComparer struct { 157 Matcher 158 } 159 160 func (c singlePlatformComparer) Less(p1, p2 specs.Platform) bool { 161 return c.Match(p1) && !c.Match(p2) 162 } 163 164 type orderedPlatformComparer struct { 165 matchers []Matcher 166 } 167 168 func (c orderedPlatformComparer) Match(platform specs.Platform) bool { 169 for _, m := range c.matchers { 170 if m.Match(platform) { 171 return true 172 } 173 } 174 return false 175 } 176 177 func (c orderedPlatformComparer) Less(p1 specs.Platform, p2 specs.Platform) bool { 178 for _, m := range c.matchers { 179 p1m := m.Match(p1) 180 p2m := m.Match(p2) 181 if p1m && !p2m { 182 return true 183 } 184 if p1m || p2m { 185 return false 186 } 187 } 188 return false 189 } 190 191 type anyPlatformComparer struct { 192 matchers []Matcher 193 } 194 195 func (c anyPlatformComparer) Match(platform specs.Platform) bool { 196 for _, m := range c.matchers { 197 if m.Match(platform) { 198 return true 199 } 200 } 201 return false 202 } 203 204 func (c anyPlatformComparer) Less(p1, p2 specs.Platform) bool { 205 var p1m, p2m bool 206 for _, m := range c.matchers { 207 if !p1m && m.Match(p1) { 208 p1m = true 209 } 210 if !p2m && m.Match(p2) { 211 p2m = true 212 } 213 if p1m && p2m { 214 return false 215 } 216 } 217 // If one matches, and the other does, sort match first 218 return p1m && !p2m 219 } 220 221 type allPlatformComparer struct{} 222 223 func (allPlatformComparer) Match(specs.Platform) bool { 224 return true 225 } 226 227 func (allPlatformComparer) Less(specs.Platform, specs.Platform) bool { 228 return false 229 }