github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/base/supportedseries_test.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package base 5 6 import ( 7 "os" 8 "time" 9 10 "github.com/juju/collections/transform" 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/core/os/ostype" 16 ) 17 18 const distroInfoContents = `version,codename,series,created,release,eol,eol-server 19 10.04,Firefox,firefox,2009-10-13,2010-04-26,2016-04-26 20 12.04 LTS,Precise Pangolin,precise,2011-10-13,2012-04-26,2017-04-26 21 99.04,Focal,focal,2020-04-25,2020-10-17,2365-07-17 22 ` 23 24 type SupportedSeriesSuite struct { 25 testing.IsolationSuite 26 } 27 28 var _ = gc.Suite(&SupportedSeriesSuite{}) 29 30 func (s *SupportedSeriesSuite) TestSupportedInfoForType(c *gc.C) { 31 tmpFile, close := makeTempFile(c, distroInfoContents) 32 defer close() 33 34 now := time.Date(2020, 3, 16, 0, 0, 0, 0, time.UTC) 35 36 info, err := supportedInfoForType(tmpFile.Name(), now, Base{}, "") 37 c.Assert(err, jc.ErrorIsNil) 38 39 ctrlBases := info.controllerBases() 40 c.Assert(ctrlBases, jc.DeepEquals, transform.Slice([]string{"ubuntu@20.04", "ubuntu@22.04", "ubuntu@24.04"}, MustParseBaseFromString)) 41 42 workloadBases := info.workloadBases(false) 43 c.Assert(workloadBases, jc.DeepEquals, transform.Slice([]string{ 44 "centos@7", "centos@9", "genericlinux@genericlinux", "kubernetes@kubernetes", 45 "ubuntu@20.04", "ubuntu@22.04", "ubuntu@24.04", 46 }, MustParseBaseFromString)) 47 } 48 49 func (s *SupportedSeriesSuite) TestSupportedInfoForTypeUsingImageStream(c *gc.C) { 50 tmpFile, close := makeTempFile(c, distroInfoContents) 51 defer close() 52 53 now := time.Date(2020, 3, 16, 0, 0, 0, 0, time.UTC) 54 55 info, err := supportedInfoForType(tmpFile.Name(), now, MustParseBaseFromString("ubuntu@20.04"), "daily") 56 c.Assert(err, jc.ErrorIsNil) 57 58 ctrlBases := info.controllerBases() 59 c.Assert(ctrlBases, jc.DeepEquals, transform.Slice([]string{"ubuntu@20.04", "ubuntu@22.04", "ubuntu@24.04"}, MustParseBaseFromString)) 60 61 workloadBases := info.workloadBases(false) 62 c.Assert(workloadBases, jc.DeepEquals, transform.Slice([]string{ 63 "centos@7", "centos@9", "genericlinux@genericlinux", "kubernetes@kubernetes", 64 "ubuntu@20.04", "ubuntu@22.04", "ubuntu@24.04", 65 }, MustParseBaseFromString)) 66 } 67 68 func (s *SupportedSeriesSuite) TestSupportedInfoForTypeUsingInvalidImageStream(c *gc.C) { 69 tmpFile, close := makeTempFile(c, distroInfoContents) 70 defer close() 71 72 now := time.Date(2020, 3, 16, 0, 0, 0, 0, time.UTC) 73 74 info, err := supportedInfoForType(tmpFile.Name(), now, MustParseBaseFromString("ubuntu@20.04"), "turtle") 75 c.Assert(err, jc.ErrorIsNil) 76 77 ctrlBases := info.controllerBases() 78 c.Assert(ctrlBases, jc.DeepEquals, transform.Slice([]string{"ubuntu@20.04", "ubuntu@22.04", "ubuntu@24.04"}, MustParseBaseFromString)) 79 80 workloadBases := info.workloadBases(false) 81 c.Assert(workloadBases, jc.DeepEquals, transform.Slice([]string{ 82 "centos@7", "centos@9", "genericlinux@genericlinux", "kubernetes@kubernetes", 83 "ubuntu@20.04", "ubuntu@22.04", "ubuntu@24.04", 84 }, MustParseBaseFromString)) 85 } 86 87 func (s *SupportedSeriesSuite) TestSupportedInfoForTypeUsingInvalidSeries(c *gc.C) { 88 tmpFile, close := makeTempFile(c, distroInfoContents) 89 defer close() 90 91 now := time.Date(2020, 3, 16, 0, 0, 0, 0, time.UTC) 92 93 info, err := supportedInfoForType(tmpFile.Name(), now, MustParseBaseFromString("ubuntu@10.04"), "daily") 94 c.Assert(err, jc.ErrorIsNil) 95 96 ctrlBases := info.controllerBases() 97 c.Assert(ctrlBases, jc.DeepEquals, transform.Slice([]string{"ubuntu@20.04", "ubuntu@22.04", "ubuntu@24.04"}, MustParseBaseFromString)) 98 99 workloadBases := info.workloadBases(false) 100 c.Assert(workloadBases, jc.DeepEquals, transform.Slice([]string{ 101 "centos@7", "centos@9", "genericlinux@genericlinux", "kubernetes@kubernetes", 102 "ubuntu@20.04", "ubuntu@22.04", "ubuntu@24.04", 103 }, MustParseBaseFromString)) 104 } 105 106 var getOSFromSeriesTests = []struct { 107 series string 108 want ostype.OSType 109 err string 110 }{{ 111 series: "precise", 112 want: ostype.Ubuntu, 113 }, { 114 series: "centos7", 115 want: ostype.CentOS, 116 }, { 117 series: "kubernetes", 118 want: ostype.Kubernetes, 119 }, { 120 series: "genericlinux", 121 want: ostype.GenericLinux, 122 }, { 123 series: "", 124 err: "series \"\" not valid", 125 }, 126 } 127 128 func (s *SupportedSeriesSuite) TestGetOSFromSeries(c *gc.C) { 129 for _, t := range getOSFromSeriesTests { 130 got, err := GetOSFromSeries(t.series) 131 if t.err != "" { 132 c.Assert(err, gc.ErrorMatches, t.err) 133 } else { 134 c.Check(err, jc.ErrorIsNil) 135 c.Assert(got, gc.Equals, t.want) 136 } 137 } 138 } 139 140 func (s *SupportedSeriesSuite) TestUnknownOSFromSeries(c *gc.C) { 141 _, err := GetOSFromSeries("Xuanhuaceratops") 142 c.Assert(err, jc.Satisfies, IsUnknownOSForSeriesError) 143 c.Assert(err, gc.ErrorMatches, `unknown OS for series: "Xuanhuaceratops"`) 144 } 145 146 func (s *SupportedSeriesSuite) TestSeriesVersionEmpty(c *gc.C) { 147 _, err := SeriesVersion("") 148 c.Assert(err, gc.ErrorMatches, `.*unknown version for series: "".*`) 149 } 150 151 func boolPtr(b bool) *bool { 152 return &b 153 } 154 155 func (s *SupportedSeriesSuite) TestGetBaseFromSeries(c *gc.C) { 156 vers, err := GetBaseFromSeries("jammy") 157 c.Assert(err, jc.ErrorIsNil) 158 c.Assert(vers, jc.DeepEquals, MakeDefaultBase("ubuntu", "22.04")) 159 _, err = GetBaseFromSeries("unknown") 160 c.Assert(err, gc.ErrorMatches, `series "unknown" not valid`) 161 vers, err = GetBaseFromSeries("centos7") 162 c.Assert(err, jc.ErrorIsNil) 163 c.Assert(vers, jc.DeepEquals, MakeDefaultBase("centos", "7")) 164 } 165 166 func (s *SupportedSeriesSuite) TestGetSeriesFromOSVersion(c *gc.C) { 167 series, err := GetSeriesFromChannel("ubuntu", "22.04") 168 c.Assert(err, jc.ErrorIsNil) 169 c.Assert(series, gc.Equals, "jammy") 170 _, err = GetSeriesFromChannel("bad", "22.04") 171 c.Assert(err, gc.ErrorMatches, `os "bad" version "22.04" not found`) 172 series, err = GetSeriesFromChannel("centos", "7/stable") 173 c.Assert(err, jc.ErrorIsNil) 174 c.Assert(series, gc.Equals, "centos7") 175 } 176 177 func (s *SupportedSeriesSuite) TestUbuntuVersions(c *gc.C) { 178 ubuntuSeries := map[SeriesName]seriesVersion{ 179 Precise: { 180 WorkloadType: ControllerWorkloadType, 181 OS: UbuntuOS, 182 Version: "12.04", 183 }, 184 Quantal: { 185 WorkloadType: ControllerWorkloadType, 186 OS: UbuntuOS, 187 Version: "12.10", 188 }, 189 Raring: { 190 WorkloadType: ControllerWorkloadType, 191 OS: UbuntuOS, 192 Version: "13.04", 193 }, 194 Saucy: { 195 WorkloadType: ControllerWorkloadType, 196 OS: UbuntuOS, 197 Version: "13.10", 198 }, 199 Trusty: { 200 WorkloadType: ControllerWorkloadType, 201 OS: UbuntuOS, 202 Version: "14.04", 203 LTS: true, 204 ESMSupported: true, 205 }, 206 Utopic: { 207 WorkloadType: ControllerWorkloadType, 208 OS: UbuntuOS, 209 Version: "14.10", 210 }, 211 Vivid: { 212 WorkloadType: ControllerWorkloadType, 213 OS: UbuntuOS, 214 Version: "15.04", 215 }, 216 Wily: { 217 WorkloadType: ControllerWorkloadType, 218 OS: UbuntuOS, 219 Version: "15.10", 220 }, 221 Xenial: { 222 WorkloadType: ControllerWorkloadType, 223 OS: UbuntuOS, 224 Version: "16.04", 225 LTS: true, 226 ESMSupported: true, 227 }, 228 Yakkety: { 229 WorkloadType: ControllerWorkloadType, 230 OS: UbuntuOS, 231 Version: "16.10", 232 }, 233 Zesty: { 234 WorkloadType: ControllerWorkloadType, 235 OS: UbuntuOS, 236 Version: "17.04", 237 }, 238 Artful: { 239 WorkloadType: ControllerWorkloadType, 240 OS: UbuntuOS, 241 Version: "17.10", 242 }, 243 Bionic: { 244 WorkloadType: ControllerWorkloadType, 245 OS: UbuntuOS, 246 Version: "18.04", 247 LTS: true, 248 ESMSupported: true, 249 }, 250 Cosmic: { 251 WorkloadType: ControllerWorkloadType, 252 OS: UbuntuOS, 253 Version: "18.10", 254 }, 255 Disco: { 256 WorkloadType: ControllerWorkloadType, 257 OS: UbuntuOS, 258 Version: "19.04", 259 }, 260 Eoan: { 261 WorkloadType: ControllerWorkloadType, 262 OS: UbuntuOS, 263 Version: "19.10", 264 }, 265 Focal: { 266 WorkloadType: ControllerWorkloadType, 267 OS: UbuntuOS, 268 Version: "20.04", 269 LTS: true, 270 Supported: true, 271 ESMSupported: true, 272 }, 273 Groovy: { 274 WorkloadType: ControllerWorkloadType, 275 OS: UbuntuOS, 276 Version: "20.10", 277 }, 278 Hirsute: { 279 WorkloadType: ControllerWorkloadType, 280 OS: UbuntuOS, 281 Version: "21.04", 282 }, 283 Impish: { 284 WorkloadType: ControllerWorkloadType, 285 OS: UbuntuOS, 286 Version: "21.10", 287 }, 288 Jammy: { 289 WorkloadType: ControllerWorkloadType, 290 OS: UbuntuOS, 291 Version: "22.04", 292 LTS: true, 293 Supported: true, 294 ESMSupported: true, 295 }, 296 Kinetic: { 297 WorkloadType: ControllerWorkloadType, 298 OS: UbuntuOS, 299 Version: "22.10", 300 }, 301 Lunar: { 302 WorkloadType: ControllerWorkloadType, 303 OS: UbuntuOS, 304 Version: "23.04", 305 }, 306 Mantic: { 307 WorkloadType: ControllerWorkloadType, 308 OS: UbuntuOS, 309 Version: "23.10", 310 }, 311 Noble: { 312 WorkloadType: ControllerWorkloadType, 313 OS: UbuntuOS, 314 Version: "24.04", 315 LTS: true, 316 ESMSupported: true, 317 }, 318 } 319 320 result := ubuntuVersions(nil, nil, ubuntuSeries) 321 c.Check(result, gc.DeepEquals, map[string]string{"artful": "17.10", "bionic": "18.04", "cosmic": "18.10", "disco": "19.04", "eoan": "19.10", "focal": "20.04", "groovy": "20.10", "hirsute": "21.04", "impish": "21.10", "jammy": "22.04", "kinetic": "22.10", "lunar": "23.04", "mantic": "23.10", "noble": "24.04", "precise": "12.04", "quantal": "12.10", "raring": "13.04", "saucy": "13.10", "trusty": "14.04", "utopic": "14.10", "vivid": "15.04", "wily": "15.10", "xenial": "16.04", "yakkety": "16.10", "zesty": "17.04"}) 322 323 result = ubuntuVersions(boolPtr(true), boolPtr(true), ubuntuSeries) 324 c.Check(result, gc.DeepEquals, map[string]string{"focal": "20.04", "jammy": "22.04"}) 325 326 result = ubuntuVersions(boolPtr(false), boolPtr(false), ubuntuSeries) 327 c.Check(result, gc.DeepEquals, map[string]string{"artful": "17.10", "cosmic": "18.10", "disco": "19.04", "eoan": "19.10", "groovy": "20.10", "hirsute": "21.04", "impish": "21.10", "kinetic": "22.10", "lunar": "23.04", "mantic": "23.10", "precise": "12.04", "quantal": "12.10", "raring": "13.04", "saucy": "13.10", "utopic": "14.10", "vivid": "15.04", "wily": "15.10", "yakkety": "16.10", "zesty": "17.04"}) 328 329 result = ubuntuVersions(boolPtr(true), boolPtr(false), ubuntuSeries) 330 c.Check(result, gc.DeepEquals, map[string]string{}) 331 332 result = ubuntuVersions(boolPtr(false), boolPtr(true), ubuntuSeries) 333 c.Check(result, gc.DeepEquals, map[string]string{"bionic": "18.04", "noble": "24.04", "trusty": "14.04", "xenial": "16.04"}) 334 335 result = ubuntuVersions(boolPtr(true), nil, ubuntuSeries) 336 c.Check(result, gc.DeepEquals, map[string]string{"focal": "20.04", "jammy": "22.04"}) 337 338 result = ubuntuVersions(boolPtr(false), nil, ubuntuSeries) 339 c.Check(result, gc.DeepEquals, map[string]string{"artful": "17.10", "bionic": "18.04", "cosmic": "18.10", "disco": "19.04", "eoan": "19.10", "groovy": "20.10", "hirsute": "21.04", "impish": "21.10", "kinetic": "22.10", "lunar": "23.04", "mantic": "23.10", "noble": "24.04", "precise": "12.04", "quantal": "12.10", "raring": "13.04", "saucy": "13.10", "trusty": "14.04", "utopic": "14.10", "vivid": "15.04", "wily": "15.10", "xenial": "16.04", "yakkety": "16.10", "zesty": "17.04"}) 340 341 result = ubuntuVersions(nil, boolPtr(true), ubuntuSeries) 342 c.Check(result, gc.DeepEquals, map[string]string{"bionic": "18.04", "focal": "20.04", "jammy": "22.04", "noble": "24.04", "trusty": "14.04", "xenial": "16.04"}) 343 344 result = ubuntuVersions(nil, boolPtr(false), ubuntuSeries) 345 c.Check(result, gc.DeepEquals, map[string]string{"artful": "17.10", "cosmic": "18.10", "disco": "19.04", "eoan": "19.10", "groovy": "20.10", "hirsute": "21.04", "impish": "21.10", "kinetic": "22.10", "lunar": "23.04", "mantic": "23.10", "precise": "12.04", "quantal": "12.10", "raring": "13.04", "saucy": "13.10", "utopic": "14.10", "vivid": "15.04", "wily": "15.10", "yakkety": "16.10", "zesty": "17.04"}) 346 } 347 348 func makeTempFile(c *gc.C, content string) (*os.File, func()) { 349 tmpfile, err := os.CreateTemp("", "distroinfo") 350 if err != nil { 351 c.Assert(err, jc.ErrorIsNil) 352 } 353 354 _, err = tmpfile.Write([]byte(content)) 355 c.Assert(err, jc.ErrorIsNil) 356 357 // Reset the file for reading. 358 _, err = tmpfile.Seek(0, 0) 359 c.Assert(err, jc.ErrorIsNil) 360 361 return tmpfile, func() { 362 err := os.Remove(tmpfile.Name()) 363 c.Assert(err, jc.ErrorIsNil) 364 } 365 }