github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/facades/client/modelupgrader/upgrader_test.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package modelupgrader_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names/v5" 9 "github.com/juju/replicaset/v3" 10 jujutesting "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 "github.com/juju/utils/v3" 13 "github.com/juju/version/v2" 14 "go.uber.org/mock/gomock" 15 gc "gopkg.in/check.v1" 16 17 "github.com/juju/juju/apiserver/common" 18 "github.com/juju/juju/apiserver/facades/client/modelupgrader" 19 "github.com/juju/juju/apiserver/facades/client/modelupgrader/mocks" 20 apiservertesting "github.com/juju/juju/apiserver/testing" 21 "github.com/juju/juju/controller" 22 coreos "github.com/juju/juju/core/os" 23 "github.com/juju/juju/core/os/ostype" 24 "github.com/juju/juju/docker" 25 "github.com/juju/juju/docker/registry" 26 "github.com/juju/juju/docker/registry/image" 27 registrymocks "github.com/juju/juju/docker/registry/mocks" 28 "github.com/juju/juju/environs" 29 environscloudspec "github.com/juju/juju/environs/cloudspec" 30 "github.com/juju/juju/environs/context" 31 envtools "github.com/juju/juju/environs/tools" 32 "github.com/juju/juju/provider/lxd" 33 "github.com/juju/juju/rpc/params" 34 "github.com/juju/juju/state" 35 coretesting "github.com/juju/juju/testing" 36 coretools "github.com/juju/juju/tools" 37 "github.com/juju/juju/upgrades/upgradevalidation" 38 upgradevalidationmocks "github.com/juju/juju/upgrades/upgradevalidation/mocks" 39 ) 40 41 var winVersions = []string{ 42 "win2008r2", "win2012", "win2012hv", "win2012hvr2", "win2012r2", "win2012r2", 43 "win2016", "win2016hv", "win2019", "win7", "win8", "win81", "win10", 44 } 45 46 var ubuntuVersions = []string{ 47 "12.04", 48 "12.10", 49 "13.04", 50 "13.10", 51 "14.04", 52 "14.10", 53 "15.04", 54 "15.10", 55 "16.04", 56 "16.10", 57 "17.04", 58 "17.10", 59 "18.04", 60 "18.10", 61 "19.04", 62 "19.10", 63 "20.10", 64 "21.04", 65 "21.10", 66 "22.10", 67 "23.04", 68 "23.10", 69 "24.04", 70 } 71 72 var controllerCfg = controller.Config{ 73 controller.ControllerUUIDKey: coretesting.ControllerTag.Id(), 74 controller.CAASImageRepo: ` 75 { 76 "serveraddress": "quay.io", 77 "auth": "xxxxx==", 78 "repository": "test-account" 79 } 80 `[1:], 81 } 82 83 func makeBases(os string, vers []string) []state.Base { 84 bases := make([]state.Base, len(vers)) 85 for i, vers := range vers { 86 bases[i] = state.Base{OS: os, Channel: vers} 87 } 88 return bases 89 } 90 91 type modelUpgradeSuite struct { 92 jujutesting.IsolationSuite 93 94 adminUser names.UserTag 95 authoriser apiservertesting.FakeAuthorizer 96 callContext context.ProviderCallContext 97 98 statePool *mocks.MockStatePool 99 toolsFinder *mocks.MockToolsFinder 100 bootstrapEnviron *mocks.MockBootstrapEnviron 101 blockChecker *mocks.MockBlockCheckerInterface 102 registryProvider *registrymocks.MockRegistry 103 cloudSpec lxd.CloudSpec 104 } 105 106 var _ = gc.Suite(&modelUpgradeSuite{}) 107 108 func (s *modelUpgradeSuite) SetUpTest(c *gc.C) { 109 s.IsolationSuite.SetUpTest(c) 110 111 adminUser := "admin" 112 s.adminUser = names.NewUserTag(adminUser) 113 114 s.authoriser = apiservertesting.FakeAuthorizer{ 115 Tag: s.adminUser, 116 } 117 118 s.callContext = context.NewEmptyCloudCallContext() 119 s.cloudSpec = lxd.CloudSpec{CloudSpec: environscloudspec.CloudSpec{Type: "lxd"}} 120 } 121 122 func (s *modelUpgradeSuite) getModelUpgraderAPI(c *gc.C) (*gomock.Controller, *modelupgrader.ModelUpgraderAPI) { 123 ctrl := gomock.NewController(c) 124 s.statePool = mocks.NewMockStatePool(ctrl) 125 s.toolsFinder = mocks.NewMockToolsFinder(ctrl) 126 s.bootstrapEnviron = mocks.NewMockBootstrapEnviron(ctrl) 127 s.blockChecker = mocks.NewMockBlockCheckerInterface(ctrl) 128 s.registryProvider = registrymocks.NewMockRegistry(ctrl) 129 130 api, err := modelupgrader.NewModelUpgraderAPI( 131 coretesting.ControllerTag, 132 s.statePool, 133 s.toolsFinder, 134 func() (environs.BootstrapEnviron, error) { 135 return s.bootstrapEnviron, nil 136 }, 137 s.blockChecker, s.authoriser, s.callContext, 138 func(docker.ImageRepoDetails) (registry.Registry, error) { 139 return s.registryProvider, nil 140 }, 141 func(names.ModelTag) (environscloudspec.CloudSpec, error) { 142 return s.cloudSpec.CloudSpec, nil 143 }, 144 ) 145 c.Assert(err, jc.ErrorIsNil) 146 return ctrl, api 147 } 148 149 func (s *modelUpgradeSuite) TestUpgradeModelWithInvalidModelTag(c *gc.C) { 150 ctrl, api := s.getModelUpgraderAPI(c) 151 defer ctrl.Finish() 152 153 _, err := api.UpgradeModel(params.UpgradeModelParams{ModelTag: "!!!"}) 154 c.Assert(err, gc.ErrorMatches, `"!!!" is not a valid tag`) 155 } 156 157 func (s *modelUpgradeSuite) TestUpgradeModelWithModelWithNoPermission(c *gc.C) { 158 s.authoriser = apiservertesting.FakeAuthorizer{ 159 Tag: names.NewUserTag("user"), 160 } 161 ctrl, api := s.getModelUpgraderAPI(c) 162 defer ctrl.Finish() 163 164 _, err := api.UpgradeModel( 165 params.UpgradeModelParams{ 166 ModelTag: coretesting.ModelTag.String(), 167 TargetVersion: version.MustParse("3.0.0"), 168 }, 169 ) 170 c.Assert(err, gc.ErrorMatches, `permission denied`) 171 } 172 173 func (s *modelUpgradeSuite) TestUpgradeModelWithChangeNotAllowed(c *gc.C) { 174 ctrl, api := s.getModelUpgraderAPI(c) 175 defer ctrl.Finish() 176 177 s.blockChecker.EXPECT().ChangeAllowed().Return(errors.Errorf("the operation has been blocked")) 178 179 _, err := api.UpgradeModel( 180 params.UpgradeModelParams{ 181 ModelTag: coretesting.ModelTag.String(), 182 TargetVersion: version.MustParse("3.0.0"), 183 }, 184 ) 185 c.Assert(err, gc.ErrorMatches, `the operation has been blocked`) 186 } 187 188 func (s *modelUpgradeSuite) assertUpgradeModelForControllerModelJuju3(c *gc.C, dryRun bool) { 189 ctrl, api := s.getModelUpgraderAPI(c) 190 defer ctrl.Finish() 191 192 s.PatchValue(&upgradevalidation.MinAgentVersions, map[int]version.Number{ 193 3: version.MustParse("2.9.1"), 194 }) 195 196 server := upgradevalidationmocks.NewMockServer(ctrl) 197 serverFactory := upgradevalidationmocks.NewMockServerFactory(ctrl) 198 s.PatchValue(&upgradevalidation.NewServerFactory, 199 func(_ lxd.NewHTTPClientFunc) lxd.ServerFactory { 200 return serverFactory 201 }, 202 ) 203 204 ctrlModelTag := coretesting.ModelTag 205 model1ModelUUID, err := utils.NewUUID() 206 c.Assert(err, jc.ErrorIsNil) 207 ctrlModel := mocks.NewMockModel(ctrl) 208 model1 := mocks.NewMockModel(ctrl) 209 ctrlModel.EXPECT().IsControllerModel().Return(true).AnyTimes() 210 211 ctrlState := mocks.NewMockState(ctrl) 212 state1 := mocks.NewMockState(ctrl) 213 ctrlState.EXPECT().Release().AnyTimes() 214 ctrlState.EXPECT().Model().Return(ctrlModel, nil) 215 state1.EXPECT().Release() 216 217 s.statePool.EXPECT().Get(ctrlModelTag.Id()).Return(ctrlState, nil) 218 s.blockChecker.EXPECT().ChangeAllowed().Return(nil) 219 220 // Decide/validate target version. 221 ctrlState.EXPECT().ControllerConfig().Return(controllerCfg, nil) 222 ctrlModel.EXPECT().Life().Return(state.Alive) 223 ctrlModel.EXPECT().AgentVersion().Return(version.MustParse("3.9.1"), nil) 224 ctrlModel.EXPECT().Type().Return(state.ModelTypeIAAS) 225 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 226 Number: version.MustParse("3.9.99"), 227 ControllerCfg: controllerCfg, ModelType: state.ModelTypeIAAS}).Return( 228 []*coretools.Tools{ 229 {Version: version.MustParseBinary("3.9.99-ubuntu-amd64")}, 230 }, nil, 231 ) 232 233 // 1. Check controller model. 234 // - check agent version; 235 ctrlModel.EXPECT().AgentVersion().Return(version.MustParse("3.9.1"), nil) 236 // - check mongo status; 237 ctrlState.EXPECT().MongoCurrentStatus().Return(&replicaset.Status{ 238 Members: []replicaset.MemberStatus{ 239 { 240 Id: 1, 241 Address: "1.1.1.1", 242 State: replicaset.PrimaryState, 243 }, 244 { 245 Id: 2, 246 Address: "2.2.2.2", 247 State: replicaset.SecondaryState, 248 }, 249 { 250 Id: 3, 251 Address: "3.3.3.3", 252 State: replicaset.SecondaryState, 253 }, 254 }, 255 }, nil) 256 // - check mongo version; 257 s.statePool.EXPECT().MongoVersion().Return("4.4", nil) 258 // - check if the model has win machines; 259 ctrlState.EXPECT().MachineCountForBase(makeBases("windows", winVersions)).Return(nil, nil) 260 // - check if the model has deprecated ubuntu machines; 261 ctrlState.EXPECT().MachineCountForBase(makeBases("ubuntu", ubuntuVersions)).Return(nil, nil) 262 // - check LXD version. 263 // - check if model has charm store charms; 264 ctrlState.EXPECT().AllCharmURLs().Return(nil, errors.NotFoundf("charms")) 265 serverFactory.EXPECT().RemoteServer(s.cloudSpec).Return(server, nil) 266 server.EXPECT().ServerVersion().Return("5.2") 267 268 ctrlState.EXPECT().AllModelUUIDs().Return([]string{ctrlModelTag.Id(), model1ModelUUID.String()}, nil) 269 270 // 2. Check other models. 271 s.statePool.EXPECT().Get(model1ModelUUID.String()).Return(state1, nil) 272 state1.EXPECT().Model().Return(model1, nil) 273 model1.EXPECT().Life().Return(state.Alive) 274 // - check agent version; 275 model1.EXPECT().AgentVersion().Return(version.MustParse("2.9.1"), nil) 276 // - check if model migration is ongoing; 277 model1.EXPECT().MigrationMode().Return(state.MigrationModeNone) 278 // - check if the model has win machines; 279 state1.EXPECT().MachineCountForBase(makeBases("windows", winVersions)).Return(nil, nil) 280 // - check if the model has deprecated ubuntu machines; 281 state1.EXPECT().MachineCountForBase(makeBases("ubuntu", ubuntuVersions)).Return(nil, nil) 282 // - check if model has charm store charms; 283 state1.EXPECT().AllCharmURLs().Return(nil, errors.NotFoundf("charms")) 284 // - check LXD version. 285 serverFactory.EXPECT().RemoteServer(s.cloudSpec).Return(server, nil) 286 server.EXPECT().ServerVersion().Return("5.2") 287 288 if !dryRun { 289 ctrlState.EXPECT().SetModelAgentVersion(version.MustParse("3.9.99"), nil, false).Return(nil) 290 } 291 292 result, err := api.UpgradeModel( 293 params.UpgradeModelParams{ 294 ModelTag: ctrlModelTag.String(), 295 TargetVersion: version.MustParse("3.9.99"), 296 AgentStream: "", 297 DryRun: dryRun, 298 }, 299 ) 300 c.Assert(err, jc.ErrorIsNil) 301 c.Assert(result, gc.DeepEquals, params.UpgradeModelResult{ 302 ChosenVersion: version.MustParse("3.9.99"), 303 }) 304 } 305 306 func (s *modelUpgradeSuite) TestUpgradeModelForControllerModelJuju3(c *gc.C) { 307 s.assertUpgradeModelForControllerModelJuju3(c, false) 308 } 309 310 func (s *modelUpgradeSuite) TestUpgradeModelForControllerModelJuju3DryRun(c *gc.C) { 311 s.assertUpgradeModelForControllerModelJuju3(c, true) 312 } 313 314 func (s *modelUpgradeSuite) TestUpgradeModelForControllerDyingHostedModelJuju3(c *gc.C) { 315 ctrl, api := s.getModelUpgraderAPI(c) 316 defer ctrl.Finish() 317 318 s.PatchValue(&upgradevalidation.MinAgentVersions, map[int]version.Number{ 319 3: version.MustParse("2.9.1"), 320 }) 321 322 server := upgradevalidationmocks.NewMockServer(ctrl) 323 serverFactory := upgradevalidationmocks.NewMockServerFactory(ctrl) 324 s.PatchValue(&upgradevalidation.NewServerFactory, 325 func(_ lxd.NewHTTPClientFunc) lxd.ServerFactory { 326 return serverFactory 327 }, 328 ) 329 330 ctrlModelTag := coretesting.ModelTag 331 model1ModelUUID, err := utils.NewUUID() 332 c.Assert(err, jc.ErrorIsNil) 333 ctrlModel := mocks.NewMockModel(ctrl) 334 model1 := mocks.NewMockModel(ctrl) 335 ctrlModel.EXPECT().IsControllerModel().Return(true).AnyTimes() 336 337 ctrlState := mocks.NewMockState(ctrl) 338 state1 := mocks.NewMockState(ctrl) 339 ctrlState.EXPECT().Release().AnyTimes() 340 ctrlState.EXPECT().Model().Return(ctrlModel, nil) 341 state1.EXPECT().Release() 342 343 s.statePool.EXPECT().Get(ctrlModelTag.Id()).Return(ctrlState, nil) 344 s.blockChecker.EXPECT().ChangeAllowed().Return(nil) 345 346 // Decide/validate target version. 347 ctrlState.EXPECT().ControllerConfig().Return(controllerCfg, nil) 348 ctrlModel.EXPECT().Life().Return(state.Alive) 349 ctrlModel.EXPECT().AgentVersion().Return(version.MustParse("3.9.1"), nil) 350 ctrlModel.EXPECT().Type().Return(state.ModelTypeIAAS) 351 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 352 Number: version.MustParse("3.9.99"), 353 ControllerCfg: controllerCfg, ModelType: state.ModelTypeIAAS}).Return( 354 []*coretools.Tools{ 355 {Version: version.MustParseBinary("3.9.99-ubuntu-amd64")}, 356 }, nil, 357 ) 358 359 // 1. Check controller model. 360 // - check agent version; 361 ctrlModel.EXPECT().AgentVersion().Return(version.MustParse("3.9.1"), nil) 362 // - check mongo status; 363 ctrlState.EXPECT().MongoCurrentStatus().Return(&replicaset.Status{ 364 Members: []replicaset.MemberStatus{ 365 { 366 Id: 1, 367 Address: "1.1.1.1", 368 State: replicaset.PrimaryState, 369 }, 370 { 371 Id: 2, 372 Address: "2.2.2.2", 373 State: replicaset.SecondaryState, 374 }, 375 { 376 Id: 3, 377 Address: "3.3.3.3", 378 State: replicaset.SecondaryState, 379 }, 380 }, 381 }, nil) 382 // - check mongo version; 383 s.statePool.EXPECT().MongoVersion().Return("4.4", nil) 384 // - check if the model has win machines; 385 ctrlState.EXPECT().MachineCountForBase(makeBases("windows", winVersions)).Return(nil, nil) 386 // - check if the model has deprecated ubuntu machines; 387 ctrlState.EXPECT().MachineCountForBase(makeBases("ubuntu", ubuntuVersions)).Return(nil, nil) 388 // - check LXD version. 389 // - check if model has charm store charms; 390 ctrlState.EXPECT().AllCharmURLs().Return(nil, errors.NotFoundf("charms")) 391 serverFactory.EXPECT().RemoteServer(s.cloudSpec).Return(server, nil) 392 server.EXPECT().ServerVersion().Return("5.2") 393 394 ctrlState.EXPECT().AllModelUUIDs().Return([]string{ctrlModelTag.Id(), model1ModelUUID.String()}, nil) 395 396 // 2. Check other models. 397 s.statePool.EXPECT().Get(model1ModelUUID.String()).Return(state1, nil) 398 state1.EXPECT().Model().Return(model1, nil) 399 // Skip this dying model. 400 model1.EXPECT().Life().Return(state.Dying) 401 402 ctrlState.EXPECT().SetModelAgentVersion(version.MustParse("3.9.99"), nil, false).Return(nil) 403 404 result, err := api.UpgradeModel( 405 params.UpgradeModelParams{ 406 ModelTag: ctrlModelTag.String(), 407 TargetVersion: version.MustParse("3.9.99"), 408 AgentStream: "", 409 DryRun: false, 410 }, 411 ) 412 c.Assert(err, jc.ErrorIsNil) 413 c.Assert(result, gc.DeepEquals, params.UpgradeModelResult{ 414 ChosenVersion: version.MustParse("3.9.99"), 415 }) 416 } 417 418 func (s *modelUpgradeSuite) TestUpgradeModelForControllerModelJuju3Failed(c *gc.C) { 419 ctrl, api := s.getModelUpgraderAPI(c) 420 defer ctrl.Finish() 421 422 s.PatchValue(&upgradevalidation.MinAgentVersions, map[int]version.Number{ 423 3: version.MustParse("2.9.2"), 424 }) 425 426 server := upgradevalidationmocks.NewMockServer(ctrl) 427 serverFactory := upgradevalidationmocks.NewMockServerFactory(ctrl) 428 s.PatchValue(&upgradevalidation.NewServerFactory, 429 func(_ lxd.NewHTTPClientFunc) lxd.ServerFactory { 430 return serverFactory 431 }, 432 ) 433 434 ctrlModelTag := coretesting.ModelTag 435 model1ModelUUID, err := utils.NewUUID() 436 c.Assert(err, jc.ErrorIsNil) 437 ctrlModel := mocks.NewMockModel(ctrl) 438 model1 := mocks.NewMockModel(ctrl) 439 ctrlModel.EXPECT().IsControllerModel().Return(true).AnyTimes() 440 441 ctrlState := mocks.NewMockState(ctrl) 442 state1 := mocks.NewMockState(ctrl) 443 ctrlState.EXPECT().Release().AnyTimes() 444 ctrlState.EXPECT().Model().Return(ctrlModel, nil) 445 state1.EXPECT().Release() 446 447 s.statePool.EXPECT().Get(ctrlModelTag.Id()).Return(ctrlState, nil) 448 449 s.blockChecker.EXPECT().ChangeAllowed().Return(nil) 450 451 // Decide/validate target version. 452 ctrlState.EXPECT().ControllerConfig().Return(controllerCfg, nil) 453 ctrlModel.EXPECT().Life().Return(state.Alive) 454 ctrlModel.EXPECT().AgentVersion().Return(version.MustParse("2.9.1"), nil) 455 ctrlModel.EXPECT().Type().Return(state.ModelTypeIAAS) 456 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 457 Number: version.MustParse("3.9.99"), 458 ControllerCfg: controllerCfg, ModelType: state.ModelTypeIAAS}).Return( 459 []*coretools.Tools{ 460 {Version: version.MustParseBinary("3.9.99-ubuntu-amd64")}, 461 }, nil, 462 ) 463 464 // 1. Check controller model. 465 // - check agent version; 466 ctrlModel.EXPECT().AgentVersion().Return(version.MustParse("2.9.1"), nil) 467 // - check mongo status; 468 ctrlState.EXPECT().MongoCurrentStatus().Return(&replicaset.Status{ 469 Members: []replicaset.MemberStatus{ 470 { 471 Id: 1, 472 Address: "1.1.1.1", 473 State: replicaset.FatalState, 474 }, 475 { 476 Id: 2, 477 Address: "2.2.2.2", 478 State: replicaset.ArbiterState, 479 }, 480 { 481 Id: 3, 482 Address: "3.3.3.3", 483 State: replicaset.RecoveringState, 484 }, 485 }, 486 }, nil) 487 // - check mongo version; 488 s.statePool.EXPECT().MongoVersion().Return("4.3", nil) 489 // - check if the model has win machines; 490 ctrlState.EXPECT().MachineCountForBase(makeBases("windows", winVersions)).Return(map[string]int{"win10": 1, "win7": 2}, nil) 491 // - check if the model has deprecated ubuntu machines; 492 ctrlState.EXPECT().MachineCountForBase(makeBases("ubuntu", ubuntuVersions)).Return(map[string]int{"xenial": 2}, nil) 493 // - check if model has charm store charms; 494 ctrlState.EXPECT().AllCharmURLs().Return(nil, errors.NotFoundf("charms")) 495 // - check LXD version. 496 serverFactory.EXPECT().RemoteServer(s.cloudSpec).Return(server, nil) 497 server.EXPECT().ServerVersion().Return("4.0") 498 ctrlModel.EXPECT().Owner().Return(names.NewUserTag("admin")) 499 ctrlModel.EXPECT().Name().Return("controller") 500 501 ctrlState.EXPECT().AllModelUUIDs().Return([]string{ctrlModelTag.Id(), model1ModelUUID.String()}, nil) 502 // 2. Check other models. 503 s.statePool.EXPECT().Get(model1ModelUUID.String()).Return(state1, nil) 504 state1.EXPECT().Model().Return(model1, nil) 505 model1.EXPECT().Life().Return(state.Alive) 506 // - check agent version; 507 model1.EXPECT().AgentVersion().Return(version.MustParse("2.9.0"), nil) 508 // - check if model migration is ongoing; 509 model1.EXPECT().MigrationMode().Return(state.MigrationModeExporting) 510 // - check if the model has win machines; 511 state1.EXPECT().MachineCountForBase(makeBases("windows", winVersions)).Return(map[string]int{"win10": 1, "win7": 3}, nil) 512 // - check if the model has deprecated ubuntu machines; 513 state1.EXPECT().MachineCountForBase(makeBases("ubuntu", ubuntuVersions)).Return(map[string]int{ 514 "artful": 1, "cosmic": 2, "disco": 3, "eoan": 4, "groovy": 5, 515 "hirsute": 6, "impish": 7, "precise": 8, "quantal": 9, "raring": 10, 516 "saucy": 11, "trusty": 12, "utopic": 13, "vivid": 14, "wily": 15, 517 "xenial": 16, "yakkety": 17, "zesty": 18, 518 }, nil) 519 // - check if model has charm store charms; 520 state1.EXPECT().AllCharmURLs().Return(nil, errors.NotFoundf("charms")) 521 // - check LXD version. 522 serverFactory.EXPECT().RemoteServer(s.cloudSpec).Return(server, nil) 523 server.EXPECT().ServerVersion().Return("4.0") 524 model1.EXPECT().Owner().Return(names.NewUserTag("admin")) 525 model1.EXPECT().Name().Return("model-1") 526 527 result, err := api.UpgradeModel( 528 params.UpgradeModelParams{ 529 ModelTag: ctrlModelTag.String(), 530 TargetVersion: version.MustParse("3.9.99"), 531 }, 532 ) 533 c.Assert(err, jc.ErrorIsNil) 534 c.Assert(result.Error.Error(), gc.Equals, ` 535 cannot upgrade to "3.9.99" due to issues with these models: 536 "admin/controller": 537 - upgrading a controller to a newer major.minor version 3.9 not supported 538 - unable to upgrade, database node 1 (1.1.1.1) has state FATAL, node 2 (2.2.2.2) has state ARBITER, node 3 (3.3.3.3) has state RECOVERING 539 - mongo version has to be "4.4" at least, but current version is "4.3" 540 - the model hosts deprecated windows machine(s): win10(1) win7(2) 541 - the model hosts deprecated ubuntu machine(s): xenial(2) 542 - LXD version has to be at least "5.0.0", but current version is only "4.0.0" 543 "admin/model-1": 544 - current model ("2.9.0") has to be upgraded to "2.9.2" at least 545 - model is under "exporting" mode, upgrade blocked 546 - the model hosts deprecated windows machine(s): win10(1) win7(3) 547 - the model hosts deprecated ubuntu machine(s): artful(1) cosmic(2) disco(3) eoan(4) groovy(5) hirsute(6) impish(7) precise(8) quantal(9) raring(10) saucy(11) trusty(12) utopic(13) vivid(14) wily(15) xenial(16) yakkety(17) zesty(18) 548 - LXD version has to be at least "5.0.0", but current version is only "4.0.0"`[1:]) 549 } 550 551 func (s *modelUpgradeSuite) assertUpgradeModelJuju3(c *gc.C, ctrlModelVers string, dryRun bool) { 552 ctrl, api := s.getModelUpgraderAPI(c) 553 defer ctrl.Finish() 554 555 server := upgradevalidationmocks.NewMockServer(ctrl) 556 serverFactory := upgradevalidationmocks.NewMockServerFactory(ctrl) 557 s.PatchValue(&upgradevalidation.NewServerFactory, 558 func(_ lxd.NewHTTPClientFunc) lxd.ServerFactory { 559 return serverFactory 560 }, 561 ) 562 563 modelUUID := coretesting.ModelTag.Id() 564 model := mocks.NewMockModel(ctrl) 565 st := mocks.NewMockState(ctrl) 566 st.EXPECT().Release().AnyTimes() 567 568 s.statePool.EXPECT().Get(modelUUID).AnyTimes().Return(st, nil) 569 st.EXPECT().Model().AnyTimes().Return(model, nil) 570 ctrlModel := mocks.NewMockModel(ctrl) 571 572 var agentStream string 573 574 s.blockChecker.EXPECT().ChangeAllowed().Return(nil) 575 576 // Decide/validate target version. 577 st.EXPECT().ControllerConfig().Return(controllerCfg, nil) 578 model.EXPECT().Life().Return(state.Alive) 579 model.EXPECT().AgentVersion().Return(version.MustParse("2.9.1"), nil) 580 model.EXPECT().IsControllerModel().Return(false).AnyTimes() 581 s.statePool.EXPECT().ControllerModel().Return(ctrlModel, nil) 582 ctrlModel.EXPECT().AgentVersion().Return(version.MustParse(ctrlModelVers), nil) 583 if ctrlModelVers != "3.9.99" { 584 model.EXPECT().Type().Return(state.ModelTypeIAAS) 585 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 586 Number: version.MustParse("3.9.99"), 587 ControllerCfg: controllerCfg, ModelType: state.ModelTypeIAAS}).Return( 588 []*coretools.Tools{ 589 {Version: version.MustParseBinary("3.9.99-ubuntu-amd64")}, 590 }, nil, 591 ) 592 } 593 594 // - check no upgrade series in process. 595 st.EXPECT().HasUpgradeSeriesLocks().Return(false, nil) 596 // - check if model has charm store charms; 597 st.EXPECT().AllCharmURLs().Return(nil, errors.NotFoundf("charms")) 598 // - check if the model has win machines; 599 st.EXPECT().MachineCountForBase(makeBases("windows", winVersions)).Return(nil, nil) 600 // - check if the model has deprecated ubuntu machines; 601 st.EXPECT().MachineCountForBase(makeBases("ubuntu", ubuntuVersions)).Return(nil, nil) 602 // - check LXD version. 603 serverFactory.EXPECT().RemoteServer(s.cloudSpec).Return(server, nil) 604 server.EXPECT().ServerVersion().Return("5.2") 605 606 if !dryRun { 607 st.EXPECT().SetModelAgentVersion(version.MustParse("3.9.99"), nil, false).Return(nil) 608 } 609 610 result, err := api.UpgradeModel( 611 params.UpgradeModelParams{ 612 ModelTag: coretesting.ModelTag.String(), 613 TargetVersion: version.MustParse("3.9.99"), 614 AgentStream: agentStream, 615 DryRun: dryRun, 616 }, 617 ) 618 c.Assert(err, jc.ErrorIsNil) 619 c.Assert(result, gc.DeepEquals, params.UpgradeModelResult{ 620 ChosenVersion: version.MustParse("3.9.99"), 621 }) 622 } 623 624 func (s *modelUpgradeSuite) TestUpgradeModelJuju3(c *gc.C) { 625 s.assertUpgradeModelJuju3(c, "3.10.0", false) 626 } 627 628 func (s *modelUpgradeSuite) TestUpgradeModelJuju3SameAsController(c *gc.C) { 629 s.assertUpgradeModelJuju3(c, "3.9.99", false) 630 } 631 632 func (s *modelUpgradeSuite) TestUpgradeModelJuju3DryRun(c *gc.C) { 633 s.assertUpgradeModelJuju3(c, "3.10.0", true) 634 } 635 636 func (s *modelUpgradeSuite) TestUpgradeModelJuju3Failed(c *gc.C) { 637 ctrl, api := s.getModelUpgraderAPI(c) 638 defer ctrl.Finish() 639 640 server := upgradevalidationmocks.NewMockServer(ctrl) 641 serverFactory := upgradevalidationmocks.NewMockServerFactory(ctrl) 642 s.PatchValue(&upgradevalidation.NewServerFactory, 643 func(_ lxd.NewHTTPClientFunc) lxd.ServerFactory { 644 return serverFactory 645 }, 646 ) 647 648 modelUUID := coretesting.ModelTag.Id() 649 model := mocks.NewMockModel(ctrl) 650 st := mocks.NewMockState(ctrl) 651 st.EXPECT().Release() 652 653 s.statePool.EXPECT().Get(modelUUID).AnyTimes().Return(st, nil) 654 st.EXPECT().Model().AnyTimes().Return(model, nil) 655 656 ctrlModel := mocks.NewMockModel(ctrl) 657 658 s.blockChecker.EXPECT().ChangeAllowed().Return(nil) 659 660 // Decide/validate target version. 661 st.EXPECT().ControllerConfig().Return(controllerCfg, nil) 662 model.EXPECT().Life().Return(state.Alive) 663 model.EXPECT().AgentVersion().Return(version.MustParse("2.9.1"), nil) 664 model.EXPECT().Type().Return(state.ModelTypeIAAS) 665 model.EXPECT().IsControllerModel().Return(false).AnyTimes() 666 s.statePool.EXPECT().ControllerModel().Return(ctrlModel, nil) 667 ctrlModel.EXPECT().AgentVersion().Return(version.MustParse("3.10.0"), nil) 668 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 669 Number: version.MustParse("3.9.99"), 670 ControllerCfg: controllerCfg, ModelType: state.ModelTypeIAAS}).Return( 671 []*coretools.Tools{ 672 {Version: version.MustParseBinary("3.9.99-ubuntu-amd64")}, 673 }, nil, 674 ) 675 676 // - check no upgrade series in process. 677 st.EXPECT().HasUpgradeSeriesLocks().Return(true, nil) 678 679 // - check if the model has win machines; 680 st.EXPECT().MachineCountForBase(makeBases("windows", winVersions)).Return(map[string]int{"win10": 1, "win7": 3}, nil) 681 // - check if the model has deprecated ubuntu machines; 682 st.EXPECT().MachineCountForBase(makeBases("ubuntu", ubuntuVersions)).Return(map[string]int{ 683 "artful": 1, "cosmic": 2, "disco": 3, "eoan": 4, "groovy": 5, 684 "hirsute": 6, "impish": 7, "precise": 8, "quantal": 9, "raring": 10, 685 "saucy": 11, "trusty": 12, "utopic": 13, "vivid": 14, "wily": 15, 686 "xenial": 16, "yakkety": 17, "zesty": 18, 687 }, nil) 688 // - check if model has charm store charms; 689 st.EXPECT().AllCharmURLs().Return(nil, errors.NotFoundf("charms")) 690 // - check LXD version. 691 serverFactory.EXPECT().RemoteServer(s.cloudSpec).Return(server, nil) 692 server.EXPECT().ServerVersion().Return("4.0") 693 model.EXPECT().Owner().Return(names.NewUserTag("admin")) 694 model.EXPECT().Name().Return("model-1") 695 696 result, err := api.UpgradeModel( 697 params.UpgradeModelParams{ 698 ModelTag: coretesting.ModelTag.String(), 699 TargetVersion: version.MustParse("3.9.99"), 700 }, 701 ) 702 c.Assert(err, jc.ErrorIsNil) 703 c.Assert(result.Error.Error(), gc.Equals, ` 704 cannot upgrade to "3.9.99" due to issues with these models: 705 "admin/model-1": 706 - unexpected upgrade series lock found 707 - the model hosts deprecated windows machine(s): win10(1) win7(3) 708 - the model hosts deprecated ubuntu machine(s): artful(1) cosmic(2) disco(3) eoan(4) groovy(5) hirsute(6) impish(7) precise(8) quantal(9) raring(10) saucy(11) trusty(12) utopic(13) vivid(14) wily(15) xenial(16) yakkety(17) zesty(18) 709 - LXD version has to be at least "5.0.0", but current version is only "4.0.0"`[1:]) 710 } 711 712 func (s *modelUpgradeSuite) TestCannotUpgradePastControllerVersion(c *gc.C) { 713 ctrl, api := s.getModelUpgraderAPI(c) 714 defer ctrl.Finish() 715 716 modelUUID := coretesting.ModelTag.Id() 717 model := mocks.NewMockModel(ctrl) 718 st := mocks.NewMockState(ctrl) 719 st.EXPECT().Release().AnyTimes() 720 721 s.statePool.EXPECT().Get(modelUUID).AnyTimes().Return(st, nil) 722 st.EXPECT().Model().AnyTimes().Return(model, nil) 723 ctrlModel := mocks.NewMockModel(ctrl) 724 725 s.blockChecker.EXPECT().ChangeAllowed().Return(nil) 726 727 st.EXPECT().ControllerConfig().Return(controllerCfg, nil) 728 model.EXPECT().Life().Return(state.Alive) 729 model.EXPECT().AgentVersion().Return(version.MustParse("2.9.1"), nil) 730 model.EXPECT().IsControllerModel().Return(false) 731 s.statePool.EXPECT().ControllerModel().Return(ctrlModel, nil) 732 ctrlModel.EXPECT().AgentVersion().Return(version.MustParse("3.9.99"), nil) 733 734 _, err := api.UpgradeModel( 735 params.UpgradeModelParams{ 736 ModelTag: coretesting.ModelTag.String(), 737 TargetVersion: version.MustParse("3.12.0"), 738 }, 739 ) 740 c.Assert(err, gc.ErrorMatches, `cannot upgrade to a version "3.12.0" greater than that of the controller "3.9.99"`) 741 } 742 743 func (s *modelUpgradeSuite) TestAbortCurrentUpgrade(c *gc.C) { 744 ctrl, api := s.getModelUpgraderAPI(c) 745 defer ctrl.Finish() 746 747 modelUUID := coretesting.ModelTag.Id() 748 st := mocks.NewMockState(ctrl) 749 st.EXPECT().Release() 750 751 gomock.InOrder( 752 s.blockChecker.EXPECT().ChangeAllowed().Return(nil), 753 s.statePool.EXPECT().Get(modelUUID).Return(st, nil), 754 st.EXPECT().AbortCurrentUpgrade().Return(nil), 755 ) 756 err := api.AbortModelUpgrade(params.ModelParam{ModelTag: coretesting.ModelTag.String()}) 757 c.Assert(err, jc.ErrorIsNil) 758 } 759 760 func (s *modelUpgradeSuite) TestFindToolsIAAS(c *gc.C) { 761 ctrl, api := s.getModelUpgraderAPI(c) 762 defer ctrl.Finish() 763 764 simpleStreams := []*coretools.Tools{ 765 {Version: version.MustParseBinary("2.9.6-ubuntu-amd64")}, 766 } 767 768 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 769 MajorVersion: 2, ModelType: state.ModelTypeIAAS}).Return(simpleStreams, nil) 770 771 result, err := api.FindAgents(common.FindAgentsParams{MajorVersion: 2, ModelType: state.ModelTypeIAAS}) 772 c.Assert(err, jc.ErrorIsNil) 773 c.Assert(result, gc.DeepEquals, coretools.Versions{ 774 &coretools.Tools{Version: version.MustParseBinary("2.9.6-ubuntu-amd64")}, 775 }) 776 } 777 778 func (s *modelUpgradeSuite) TestFindToolsCAASReleased(c *gc.C) { 779 ctrl, api := s.getModelUpgraderAPI(c) 780 defer ctrl.Finish() 781 782 st := mocks.NewMockState(ctrl) 783 model := mocks.NewMockModel(ctrl) 784 st.EXPECT().Model().AnyTimes().Return(model, nil) 785 786 simpleStreams := []*coretools.Tools{ 787 {Version: version.MustParseBinary("2.9.9-ubuntu-amd64")}, 788 {Version: version.MustParseBinary("2.9.10-ubuntu-amd64")}, 789 {Version: version.MustParseBinary("2.9.11-ubuntu-amd64")}, 790 } 791 s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) 792 793 gomock.InOrder( 794 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 795 MajorVersion: 2, MinorVersion: 9, 796 ModelType: state.ModelTypeCAAS, 797 }).Return(simpleStreams, nil), 798 s.registryProvider.EXPECT().Tags("jujud-operator").Return(coretools.Versions{ 799 image.NewImageInfo(version.MustParse("2.9.8")), 800 image.NewImageInfo(version.MustParse("2.9.9")), 801 image.NewImageInfo(version.MustParse("2.9.10.1")), 802 image.NewImageInfo(version.MustParse("2.9.10")), 803 image.NewImageInfo(version.MustParse("2.9.11")), 804 image.NewImageInfo(version.MustParse("2.9.12")), // skip: it's not released in simplestream yet. 805 }, nil), 806 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.9").Return("amd64", nil), 807 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10.1").Return("amd64", nil), 808 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10").Return("amd64", nil), 809 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.11").Return("amd64", nil), 810 s.registryProvider.EXPECT().Close().Return(nil), 811 ) 812 813 result, err := api.FindAgents(common.FindAgentsParams{MajorVersion: 2, MinorVersion: 9, ModelType: state.ModelTypeCAAS}) 814 c.Assert(err, jc.ErrorIsNil) 815 c.Assert(result, gc.DeepEquals, coretools.Versions{ 816 &coretools.Tools{Version: version.MustParseBinary("2.9.9-ubuntu-amd64")}, 817 &coretools.Tools{Version: version.MustParseBinary("2.9.10.1-ubuntu-amd64")}, 818 &coretools.Tools{Version: version.MustParseBinary("2.9.10-ubuntu-amd64")}, 819 &coretools.Tools{Version: version.MustParseBinary("2.9.11-ubuntu-amd64")}, 820 }) 821 } 822 823 func (s *modelUpgradeSuite) TestFindToolsCAASReleasedExact(c *gc.C) { 824 ctrl, api := s.getModelUpgraderAPI(c) 825 defer ctrl.Finish() 826 827 st := mocks.NewMockState(ctrl) 828 model := mocks.NewMockModel(ctrl) 829 st.EXPECT().Model().AnyTimes().Return(model, nil) 830 831 simpleStreams := []*coretools.Tools{ 832 {Version: version.MustParseBinary("2.9.10-ubuntu-amd64")}, 833 } 834 s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) 835 836 gomock.InOrder( 837 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 838 Number: version.MustParse("2.9.10"), 839 ModelType: state.ModelTypeCAAS, 840 }).Return(simpleStreams, nil), 841 s.registryProvider.EXPECT().Tags("jujud-operator").Return(coretools.Versions{ 842 image.NewImageInfo(version.MustParse("2.9.8")), 843 image.NewImageInfo(version.MustParse("2.9.9")), 844 image.NewImageInfo(version.MustParse("2.9.10.1")), 845 image.NewImageInfo(version.MustParse("2.9.10")), 846 image.NewImageInfo(version.MustParse("2.9.11")), 847 image.NewImageInfo(version.MustParse("2.9.12")), 848 }, nil), 849 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10").Return("amd64", nil), 850 s.registryProvider.EXPECT().Close().Return(nil), 851 ) 852 853 result, err := api.FindAgents(common.FindAgentsParams{ 854 Number: version.MustParse("2.9.10"), ModelType: state.ModelTypeCAAS}) 855 c.Assert(err, jc.ErrorIsNil) 856 c.Assert(result, gc.DeepEquals, coretools.Versions{ 857 &coretools.Tools{Version: version.MustParseBinary("2.9.10-ubuntu-amd64")}, 858 }) 859 } 860 861 func (s *modelUpgradeSuite) TestFindToolsCAASNonReleased(c *gc.C) { 862 ctrl, api := s.getModelUpgraderAPI(c) 863 defer ctrl.Finish() 864 865 st := mocks.NewMockState(ctrl) 866 model := mocks.NewMockModel(ctrl) 867 st.EXPECT().Model().AnyTimes().Return(model, nil) 868 869 simpleStreams := []*coretools.Tools{ 870 {Version: version.MustParseBinary("2.9.9-ubuntu-amd64")}, 871 {Version: version.MustParseBinary("2.9.10-ubuntu-amd64")}, 872 {Version: version.MustParseBinary("2.9.11-ubuntu-amd64")}, 873 {Version: version.MustParseBinary("2.9.12-ubuntu-amd64")}, 874 } 875 s.PatchValue(&coreos.HostOS, func() ostype.OSType { return ostype.Ubuntu }) 876 877 gomock.InOrder( 878 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 879 MajorVersion: 2, MinorVersion: 9, AgentStream: envtools.DevelStream, 880 ModelType: state.ModelTypeCAAS, 881 }).Return(simpleStreams, nil), 882 s.registryProvider.EXPECT().Tags("jujud-operator").Return(coretools.Versions{ 883 image.NewImageInfo(version.MustParse("2.9.8")), // skip: it's not released in simplestream yet. 884 image.NewImageInfo(version.MustParse("2.9.9")), 885 image.NewImageInfo(version.MustParse("2.9.10.1")), 886 image.NewImageInfo(version.MustParse("2.9.10")), 887 image.NewImageInfo(version.MustParse("2.9.11")), 888 image.NewImageInfo(version.MustParse("2.9.12")), 889 image.NewImageInfo(version.MustParse("2.9.13")), // skip: it's not released in simplestream yet. 890 }, nil), 891 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.9").Return("amd64", nil), 892 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10.1").Return("amd64", nil), 893 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10").Return("amd64", nil), 894 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.11").Return("amd64", nil), 895 s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.12").Return("", errors.NotFoundf("2.9.12")), // This can only happen on a non-official registry account. 896 s.registryProvider.EXPECT().Close().Return(nil), 897 ) 898 899 result, err := api.FindAgents(common.FindAgentsParams{ 900 MajorVersion: 2, MinorVersion: 9, AgentStream: envtools.DevelStream, 901 ModelType: state.ModelTypeCAAS, 902 }) 903 c.Assert(err, jc.ErrorIsNil) 904 c.Assert(result, gc.DeepEquals, coretools.Versions{ 905 &coretools.Tools{Version: version.MustParseBinary("2.9.9-ubuntu-amd64")}, 906 &coretools.Tools{Version: version.MustParseBinary("2.9.10.1-ubuntu-amd64")}, 907 &coretools.Tools{Version: version.MustParseBinary("2.9.10-ubuntu-amd64")}, 908 &coretools.Tools{Version: version.MustParseBinary("2.9.11-ubuntu-amd64")}, 909 }) 910 } 911 912 func (s *modelUpgradeSuite) TestDecideVersionFindToolUseAgentVersionMajorMinor(c *gc.C) { 913 ctrl, api := s.getModelUpgraderAPI(c) 914 defer ctrl.Finish() 915 916 st := mocks.NewMockState(ctrl) 917 model := mocks.NewMockModel(ctrl) 918 st.EXPECT().Model().AnyTimes().Return(model, nil) 919 920 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 921 MajorVersion: 3, MinorVersion: 666, 922 ModelType: state.ModelTypeIAAS, 923 }).Return(nil, errors.New(`fail to exit early`)) 924 925 targetVersion, err := api.DecideVersion( 926 version.MustParse("3.9.99"), common.FindAgentsParams{ 927 MajorVersion: 3, MinorVersion: 666, ModelType: state.ModelTypeIAAS}, 928 ) 929 c.Assert(err, gc.ErrorMatches, `cannot find agents from simple streams: fail to exit early`) 930 c.Assert(targetVersion, gc.DeepEquals, version.Zero) 931 } 932 933 func (s *modelUpgradeSuite) TestDecideVersionFindToolUseTargetMajor(c *gc.C) { 934 ctrl, api := s.getModelUpgraderAPI(c) 935 defer ctrl.Finish() 936 937 st := mocks.NewMockState(ctrl) 938 model := mocks.NewMockModel(ctrl) 939 st.EXPECT().Model().AnyTimes().Return(model, nil) 940 941 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 942 Number: version.MustParse("4.9.99"), 943 ModelType: state.ModelTypeIAAS, 944 }).Return(nil, errors.New(`fail to exit early`)) 945 946 targetVersion, err := api.DecideVersion( 947 version.MustParse("3.9.99"), 948 common.FindAgentsParams{Number: version.MustParse("4.9.99"), ModelType: state.ModelTypeIAAS}, 949 ) 950 c.Assert(err, gc.ErrorMatches, `cannot find agents from simple streams: fail to exit early`) 951 c.Assert(targetVersion, gc.DeepEquals, version.Zero) 952 } 953 954 func (s *modelUpgradeSuite) TestDecideVersionValidateAndUseTargetVersion(c *gc.C) { 955 ctrl, api := s.getModelUpgraderAPI(c) 956 defer ctrl.Finish() 957 958 st := mocks.NewMockState(ctrl) 959 model := mocks.NewMockModel(ctrl) 960 st.EXPECT().Model().AnyTimes().Return(model, nil) 961 962 simpleStreams := []*coretools.Tools{ 963 {Version: version.MustParseBinary("3.9.98-ubuntu-amd64")}, 964 } 965 966 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 967 Number: version.MustParse("3.9.98"), ModelType: state.ModelTypeIAAS, 968 }).Return(simpleStreams, nil) 969 970 targetVersion, err := api.DecideVersion( 971 version.MustParse("2.9.99"), 972 common.FindAgentsParams{ 973 Number: version.MustParse("3.9.98"), ModelType: state.ModelTypeIAAS}, 974 ) 975 c.Assert(err, jc.ErrorIsNil) 976 c.Assert(targetVersion, gc.DeepEquals, version.MustParse("3.9.98")) 977 } 978 979 func (s *modelUpgradeSuite) TestDecideVersionNewestMinor(c *gc.C) { 980 ctrl, api := s.getModelUpgraderAPI(c) 981 defer ctrl.Finish() 982 983 st := mocks.NewMockState(ctrl) 984 model := mocks.NewMockModel(ctrl) 985 st.EXPECT().Model().AnyTimes().Return(model, nil) 986 987 simpleStreams := []*coretools.Tools{ 988 {Version: version.MustParseBinary("2.9.100-ubuntu-amd64")}, 989 {Version: version.MustParseBinary("2.10.99-ubuntu-amd64")}, 990 {Version: version.MustParseBinary("2.11.99-ubuntu-amd64")}, 991 {Version: version.MustParseBinary("3.666.0-ubuntu-amd64")}, 992 } 993 994 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 995 MajorVersion: 2, 996 ModelType: state.ModelTypeIAAS, 997 }).Return(simpleStreams, nil) 998 999 targetVersion, err := api.DecideVersion( 1000 version.MustParse("2.9.99"), 1001 common.FindAgentsParams{ 1002 MajorVersion: 2, MinorVersion: 0, 1003 ModelType: state.ModelTypeIAAS}, 1004 ) 1005 c.Assert(err, jc.ErrorIsNil) 1006 c.Assert(targetVersion, gc.DeepEquals, version.MustParse("2.9.100")) 1007 } 1008 1009 func (s *modelUpgradeSuite) TestDecideVersionIgnoresNewerMajor(c *gc.C) { 1010 ctrl, api := s.getModelUpgraderAPI(c) 1011 defer ctrl.Finish() 1012 1013 st := mocks.NewMockState(ctrl) 1014 model := mocks.NewMockModel(ctrl) 1015 st.EXPECT().Model().AnyTimes().Return(model, nil) 1016 1017 simpleStreams := []*coretools.Tools{ 1018 {Version: version.MustParseBinary("2.9.100-ubuntu-amd64")}, 1019 {Version: version.MustParseBinary("3.666.0-ubuntu-amd64")}, 1020 } 1021 1022 s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{ 1023 MajorVersion: 2, 1024 ModelType: state.ModelTypeIAAS, 1025 }).Return(simpleStreams, nil) 1026 1027 targetVersion, err := api.DecideVersion( 1028 version.MustParse("2.9.99"), 1029 common.FindAgentsParams{ 1030 MajorVersion: 2, 1031 ModelType: state.ModelTypeIAAS}, 1032 ) 1033 c.Assert(err, jc.ErrorIsNil) 1034 c.Assert(targetVersion, gc.DeepEquals, version.MustParse("2.9.100")) 1035 }