github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/common/credentialcommon/modelcredential_test.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package credentialcommon_test 5 6 import ( 7 stdcontext "context" 8 9 "github.com/juju/errors" 10 "github.com/juju/names/v5" 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/apiserver/common/credentialcommon" 16 apiservererrors "github.com/juju/juju/apiserver/errors" 17 "github.com/juju/juju/caas" 18 "github.com/juju/juju/cloud" 19 "github.com/juju/juju/core/instance" 20 "github.com/juju/juju/environs" 21 "github.com/juju/juju/environs/config" 22 "github.com/juju/juju/environs/context" 23 "github.com/juju/juju/environs/instances" 24 "github.com/juju/juju/rpc/params" 25 "github.com/juju/juju/state" 26 statetesting "github.com/juju/juju/state/testing" 27 jujuesting "github.com/juju/juju/testing" 28 ) 29 30 var _ = gc.Suite(&CheckMachinesSuite{}) 31 var _ = gc.Suite(&ModelCredentialSuite{}) 32 33 type CheckMachinesSuite struct { 34 testing.IsolationSuite 35 36 provider *mockProvider 37 instance *mockInstance 38 callContext context.ProviderCallContext 39 40 backend *mockPersistedBackend 41 machine *mockMachine 42 } 43 44 func (s *CheckMachinesSuite) SetUpTest(c *gc.C) { 45 s.IsolationSuite.SetUpTest(c) 46 s.backend = createModelBackend() 47 48 // This is what the test gets from the state. 49 s.machine = createTestMachine("1", "wind-up") 50 s.backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 51 return []credentialcommon.Machine{s.machine}, nil 52 } 53 54 // This is what the test gets from the cloud. 55 s.instance = &mockInstance{id: "wind-up"} 56 s.provider = &mockProvider{ 57 Stub: &testing.Stub{}, 58 allInstancesFunc: func(ctx context.ProviderCallContext) ([]instances.Instance, error) { 59 return []instances.Instance{s.instance}, nil 60 }, 61 } 62 s.callContext = context.NewEmptyCloudCallContext() 63 } 64 65 func (s *CheckMachinesSuite) TestCheckMachinesSuccess(c *gc.C) { 66 results, err := credentialcommon.CheckMachineInstances(s.backend, false, []instances.Instance{s.instance}) 67 c.Assert(err, jc.ErrorIsNil) 68 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 69 } 70 71 func (s *CheckMachinesSuite) TestCheckMachinesInstancesMissing(c *gc.C) { 72 machine1 := createTestMachine("2", "birds") 73 s.backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 74 return []credentialcommon.Machine{s.machine, machine1}, nil 75 } 76 77 results, err := credentialcommon.CheckMachineInstances(s.backend, false, []instances.Instance{s.instance}) 78 c.Assert(err, jc.ErrorIsNil) 79 80 c.Assert(results.Results, gc.HasLen, 1) 81 c.Assert(results.Results[0].Error, gc.ErrorMatches, `couldn't find instance "birds" for machine 2`) 82 } 83 84 func (s *CheckMachinesSuite) TestCheckMachinesExtraInstances(c *gc.C) { 85 instance2 := &mockInstance{id: "analyse"} 86 results, err := credentialcommon.CheckMachineInstances(s.backend, false, []instances.Instance{s.instance, instance2}) 87 c.Assert(err, jc.ErrorIsNil) 88 c.Assert(results.Results, gc.IsNil) 89 } 90 91 func (s *CheckMachinesSuite) TestCheckMachinesExtraInstancesWhenMigrating(c *gc.C) { 92 instance2 := &mockInstance{id: "analyse"} 93 results, err := credentialcommon.CheckMachineInstances(s.backend, true, []instances.Instance{s.instance, instance2}) 94 c.Assert(err, jc.ErrorIsNil) 95 96 c.Assert(results.Results, gc.HasLen, 1) 97 c.Assert(results.Results[0].Error, gc.ErrorMatches, `no machine with instance "analyse"`) 98 } 99 100 func (s *CheckMachinesSuite) TestCheckMachinesErrorGettingMachines(c *gc.C) { 101 s.backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 102 return nil, errors.New("boom") 103 } 104 105 results, err := credentialcommon.CheckMachineInstances(s.backend, false, nil) 106 c.Assert(err, gc.ErrorMatches, "boom") 107 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 108 } 109 110 func (s *CheckMachinesSuite) TestCheckMachinesHandlesContainers(c *gc.C) { 111 machine1 := createTestMachine("1", "") 112 machine1.container = true 113 s.backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 114 return []credentialcommon.Machine{s.machine, machine1}, nil 115 } 116 117 results, err := credentialcommon.CheckMachineInstances(s.backend, false, []instances.Instance{s.instance}) 118 c.Assert(err, jc.ErrorIsNil) 119 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 120 } 121 122 func (s *CheckMachinesSuite) TestCheckMachinesHandlesManual(c *gc.C) { 123 machine1 := createTestMachine("2", "") 124 machine1.manualFunc = func() (bool, error) { return false, errors.New("manual retrieval failure") } 125 s.backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 126 return []credentialcommon.Machine{s.machine, machine1}, nil 127 } 128 129 results, err := credentialcommon.CheckMachineInstances(s.backend, false, []instances.Instance{s.instance}) 130 c.Assert(err, gc.ErrorMatches, "manual retrieval failure") 131 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 132 133 machine1.manualFunc = func() (bool, error) { return true, nil } 134 results, err = credentialcommon.CheckMachineInstances(s.backend, false, []instances.Instance{s.instance}) 135 c.Assert(err, jc.ErrorIsNil) 136 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 137 } 138 139 func (s *CheckMachinesSuite) TestCheckMachinesErrorGettingMachineInstanceId(c *gc.C) { 140 machine1 := createTestMachine("2", "") 141 machine1.instanceIdFunc = func() (instance.Id, error) { return "", errors.New("retrieval failure") } 142 s.backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 143 return []credentialcommon.Machine{s.machine, machine1}, nil 144 } 145 146 results, err := credentialcommon.CheckMachineInstances(s.backend, false, []instances.Instance{s.instance}) 147 c.Assert(err, jc.ErrorIsNil) 148 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 149 Results: []params.ErrorResult{ 150 {Error: apiservererrors.ServerError(errors.Errorf("getting instance id for machine 2: retrieval failure"))}, 151 }, 152 }) 153 } 154 155 func (s *CheckMachinesSuite) TestCheckMachinesErrorGettingMachineInstanceIdNonFatal(c *gc.C) { 156 machine1 := createTestMachine("2", "") 157 machine1.instanceIdFunc = func() (instance.Id, error) { return "", errors.New("retrieval failure") } 158 s.machine.instanceIdFunc = machine1.instanceIdFunc 159 s.backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 160 return []credentialcommon.Machine{s.machine, machine1}, nil 161 } 162 163 results, err := credentialcommon.CheckMachineInstances(s.backend, false, nil) 164 c.Assert(err, jc.ErrorIsNil) 165 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 166 Results: []params.ErrorResult{ 167 {Error: apiservererrors.ServerError(errors.New("getting instance id for machine 1: retrieval failure"))}, 168 {Error: apiservererrors.ServerError(errors.New("getting instance id for machine 2: retrieval failure"))}, 169 }, 170 }) 171 } 172 173 func (s *CheckMachinesSuite) TestCheckMachinesErrorGettingMachineInstanceIdNonFatalWhenMigrating(c *gc.C) { 174 machine1 := createTestMachine("2", "") 175 machine1.instanceIdFunc = func() (instance.Id, error) { return "", errors.New("retrieval failure") } 176 s.machine.instanceIdFunc = machine1.instanceIdFunc 177 s.backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 178 return []credentialcommon.Machine{s.machine, machine1}, nil 179 } 180 181 results, err := credentialcommon.CheckMachineInstances(s.backend, true, []instances.Instance{s.instance}) 182 c.Assert(err, jc.ErrorIsNil) 183 // There should be 3 errors here: 184 // * 2 of them because failing to get an instance id from one machine should not stop the processing the rest of the machines; 185 // * 1 because we no longer can link test instance (s.instance) to a test machine (s.machine). 186 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 187 Results: []params.ErrorResult{ 188 {Error: apiservererrors.ServerError(errors.New("getting instance id for machine 1: retrieval failure"))}, 189 {Error: apiservererrors.ServerError(errors.New("getting instance id for machine 2: retrieval failure"))}, 190 {Error: apiservererrors.ServerError(errors.New(`no machine with instance "wind-up"`))}, 191 }, 192 }) 193 } 194 195 func (s *CheckMachinesSuite) TestCheckMachinesNotProvisionedError(c *gc.C) { 196 machine2 := createTestMachine("2", "") 197 machine2.instanceIdFunc = func() (instance.Id, error) { return "", errors.NotProvisionedf("machine 2") } 198 s.backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 199 return []credentialcommon.Machine{s.machine, machine2}, nil 200 } 201 202 // We should ignore the unprovisioned machine - we wouldn't expect 203 // the cloud to know about it. 204 results, err := credentialcommon.CheckMachineInstances(s.backend, false, []instances.Instance{s.instance}) 205 c.Assert(err, jc.ErrorIsNil) 206 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 207 } 208 209 type ModelCredentialSuite struct { 210 testing.IsolationSuite 211 212 backend *mockPersistedBackend 213 callContext context.ProviderCallContext 214 } 215 216 func (s *ModelCredentialSuite) SetUpTest(c *gc.C) { 217 s.IsolationSuite.SetUpTest(c) 218 s.backend = createModelBackend() 219 s.callContext = context.NewEmptyCloudCallContext() 220 } 221 222 func (s *ModelCredentialSuite) TestValidateNewModelCredentialUnknownModelType(c *gc.C) { 223 unknownModel := createTestModel() 224 unknownModel.modelType = state.ModelType("unknown") 225 s.backend.modelFunc = func() (credentialcommon.Model, error) { 226 return unknownModel, nil 227 } 228 229 results, err := credentialcommon.ValidateNewModelCredential(s.backend, s.callContext, names.CloudCredentialTag{}, &testCredential, false, false) 230 c.Assert(err, gc.ErrorMatches, `model type "unknown" not supported`) 231 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 232 } 233 234 func (s *ModelCredentialSuite) TestBuildingOpenParamsErrorGettingModel(c *gc.C) { 235 s.backend.SetErrors(errors.New("get model error")) 236 results, err := credentialcommon.ValidateNewModelCredential(s.backend, s.callContext, names.CloudCredentialTag{}, nil, false, false) 237 c.Assert(err, gc.ErrorMatches, "get model error") 238 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 239 s.backend.CheckCallNames(c, "Model") 240 } 241 242 func (s *ModelCredentialSuite) TestBuildingOpenParamsErrorGettingCloud(c *gc.C) { 243 s.backend.SetErrors( 244 nil, // getting model 245 errors.New("get cloud error"), 246 ) 247 results, err := credentialcommon.ValidateNewModelCredential(s.backend, s.callContext, names.CloudCredentialTag{}, nil, false, false) 248 s.backend.CheckCallNames(c, "Model", "Cloud") 249 c.Assert(err, gc.ErrorMatches, "get cloud error") 250 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 251 } 252 253 func (s *ModelCredentialSuite) TestBuildingOpenParamsErrorGettingModelConfig(c *gc.C) { 254 model := createTestModel() 255 model.configFunc = func() (*config.Config, error) { 256 return nil, errors.New("get model config error") 257 } 258 259 s.backend.modelFunc = func() (credentialcommon.Model, error) { 260 return model, nil 261 } 262 263 results, err := credentialcommon.ValidateNewModelCredential(s.backend, s.callContext, names.CloudCredentialTag{}, &testCredential, false, false) 264 c.Assert(err, gc.ErrorMatches, "get model config error") 265 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 266 s.backend.CheckCallNames(c, "Model", "Cloud") 267 } 268 269 func (s *ModelCredentialSuite) TestBuildingOpenParamsErrorValidateCredentialForModelCloud(c *gc.C) { 270 model := createTestModel() 271 model.validateCredentialFunc = func(tag names.CloudCredentialTag, credential cloud.Credential) error { 272 return errors.New("credential not for model cloud error") 273 } 274 275 s.backend.modelFunc = func() (credentialcommon.Model, error) { 276 return model, nil 277 } 278 279 results, err := credentialcommon.ValidateNewModelCredential(s.backend, s.callContext, names.CloudCredentialTag{}, &testCredential, false, false) 280 c.Assert(err, gc.ErrorMatches, "credential not for model cloud error") 281 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 282 s.backend.CheckCallNames(c, "Model", "Cloud") 283 } 284 285 func (s *ModelCredentialSuite) TestValidateExistingModelCredentialErrorGettingModel(c *gc.C) { 286 s.backend.SetErrors(errors.New("get model error")) 287 results, err := credentialcommon.ValidateExistingModelCredential(s.backend, s.callContext, false, false) 288 c.Assert(err, gc.ErrorMatches, "get model error") 289 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 290 s.backend.CheckCallNames(c, "Model") 291 } 292 293 func (s *ModelCredentialSuite) TestValidateExistingModelCredentialUnsetCloudCredential(c *gc.C) { 294 model := createTestModel() 295 model.cloudCredentialTagFunc = func() (names.CloudCredentialTag, bool) { 296 return names.CloudCredentialTag{}, false 297 } 298 299 s.backend.modelFunc = func() (credentialcommon.Model, error) { 300 return model, nil 301 } 302 303 results, err := credentialcommon.ValidateExistingModelCredential(s.backend, s.callContext, false, false) 304 c.Assert(err, jc.ErrorIsNil) 305 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 306 s.backend.CheckCallNames(c, "Model") 307 } 308 309 func (s *ModelCredentialSuite) TestValidateExistingModelCredentialErrorGettingCredential(c *gc.C) { 310 s.backend.cloudCredentialFunc = func(tag names.CloudCredentialTag) (state.Credential, error) { 311 return state.Credential{}, errors.New("no nope niet") 312 } 313 314 results, err := credentialcommon.ValidateExistingModelCredential(s.backend, s.callContext, false, false) 315 c.Assert(err, gc.ErrorMatches, "no nope niet") 316 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 317 s.backend.CheckCallNames(c, "Model", "CloudCredential") 318 } 319 320 func (s *ModelCredentialSuite) TestValidateExistingModelCredentialInvalidCredential(c *gc.C) { 321 s.backend.cloudCredentialFunc = func(tag names.CloudCredentialTag) (state.Credential, error) { 322 cred := statetesting.NewEmptyCredential() 323 cred.Name = "cred" 324 cred.Invalid = true 325 return cred, nil 326 } 327 328 results, err := credentialcommon.ValidateExistingModelCredential(s.backend, s.callContext, false, false) 329 c.Assert(err, gc.ErrorMatches, `credential "cred" not valid`) 330 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 331 s.backend.CheckCallNames(c, "Model", "CloudCredential") 332 } 333 334 func (s *ModelCredentialSuite) TestOpeningProviderFails(c *gc.C) { 335 s.PatchValue(credentialcommon.NewEnv, func(stdcontext.Context, environs.OpenParams) (environs.Environ, error) { 336 return nil, errors.New("explosive") 337 }) 338 results, err := credentialcommon.CheckIAASModelCredential(environs.OpenParams{}, s.backend, s.callContext, false, false) 339 c.Assert(err, gc.ErrorMatches, "explosive") 340 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 341 } 342 343 func (s *ModelCredentialSuite) TestValidateNewModelCredentialForIAASModel(c *gc.C) { 344 s.ensureEnvForIAASModel(c) 345 results, err := credentialcommon.ValidateNewModelCredential(s.backend, s.callContext, names.CloudCredentialTag{}, &testCredential, false, false) 346 c.Assert(err, jc.ErrorIsNil) 347 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 348 } 349 350 func (s *ModelCredentialSuite) TestValidateExistingModelCredentialForIAASModel(c *gc.C) { 351 s.ensureEnvForIAASModel(c) 352 results, err := credentialcommon.ValidateExistingModelCredential(s.backend, s.callContext, false, false) 353 c.Assert(err, jc.ErrorIsNil) 354 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 355 } 356 357 func (s *ModelCredentialSuite) TestOpeningCAASBrokerFails(c *gc.C) { 358 s.PatchValue(credentialcommon.NewCAASBroker, func(stdcontext.Context, environs.OpenParams) (caas.Broker, error) { 359 return nil, errors.New("explosive") 360 }) 361 results, err := credentialcommon.CheckCAASModelCredential(environs.OpenParams{}) 362 c.Assert(err, gc.ErrorMatches, "explosive") 363 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 364 } 365 366 func (s *ModelCredentialSuite) TestCAASCredentialCheckFailed(c *gc.C) { 367 s.PatchValue(credentialcommon.NewCAASBroker, func(stdcontext.Context, environs.OpenParams) (caas.Broker, error) { 368 return &mockCaasBroker{ 369 namespacesFunc: func() ([]string, error) { return nil, errors.New("fail auth") }, 370 }, nil 371 }) 372 results, err := credentialcommon.CheckCAASModelCredential(environs.OpenParams{}) 373 c.Assert(err, gc.ErrorMatches, "fail auth") 374 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 375 } 376 377 func (s *ModelCredentialSuite) TestCAASCredentialCheckSucceeds(c *gc.C) { 378 s.PatchValue(credentialcommon.NewCAASBroker, func(stdcontext.Context, environs.OpenParams) (caas.Broker, error) { 379 return &mockCaasBroker{ 380 namespacesFunc: func() ([]string, error) { return []string{}, nil }, 381 }, nil 382 }) 383 results, err := credentialcommon.CheckCAASModelCredential(environs.OpenParams{}) 384 c.Assert(err, jc.ErrorIsNil) 385 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 386 } 387 388 func (s *ModelCredentialSuite) TestValidateNewModelCredentialForCAASModel(c *gc.C) { 389 s.ensureEnvForCAASModel(c) 390 results, err := credentialcommon.ValidateNewModelCredential(s.backend, s.callContext, names.CloudCredentialTag{}, &testCredential, false, false) 391 c.Assert(err, jc.ErrorIsNil) 392 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 393 } 394 395 func (s *ModelCredentialSuite) TestValidateExistingModelCredentialForCAASSuccess(c *gc.C) { 396 s.ensureEnvForCAASModel(c) 397 results, err := credentialcommon.ValidateExistingModelCredential(s.backend, s.callContext, false, false) 398 c.Assert(err, jc.ErrorIsNil) 399 c.Assert(results, gc.DeepEquals, params.ErrorResults{}) 400 } 401 402 func (s *ModelCredentialSuite) ensureEnvForCAASModel(c *gc.C) { 403 caasModel := createTestModel() 404 caasModel.modelType = state.ModelTypeCAAS 405 s.backend.modelFunc = func() (credentialcommon.Model, error) { 406 return caasModel, nil 407 } 408 s.PatchValue(credentialcommon.NewCAASBroker, func(stdcontext.Context, environs.OpenParams) (caas.Broker, error) { 409 return &mockCaasBroker{ 410 namespacesFunc: func() ([]string, error) { return []string{}, nil }, 411 }, nil 412 }) 413 } 414 415 func (s *ModelCredentialSuite) ensureEnvForIAASModel(c *gc.C) { 416 s.PatchValue(credentialcommon.NewEnv, func(stdcontext.Context, environs.OpenParams) (environs.Environ, error) { 417 return &mockEnviron{ 418 mockProvider: &mockProvider{ 419 Stub: &testing.Stub{}, 420 allInstancesFunc: func(ctx context.ProviderCallContext) ([]instances.Instance, error) { 421 return []instances.Instance{}, nil 422 }, 423 }, 424 }, nil 425 }) 426 } 427 428 func createModelBackend() *mockPersistedBackend { 429 backend := mockPersistedBackend{Stub: &testing.Stub{}} 430 backend.allMachinesFunc = func() ([]credentialcommon.Machine, error) { 431 return []credentialcommon.Machine{}, backend.NextErr() 432 } 433 backend.modelFunc = func() (credentialcommon.Model, error) { 434 return createTestModel(), backend.NextErr() 435 } 436 backend.controllerConfigFunc = func() (credentialcommon.ControllerConfig, error) { 437 return testControllerConfig, backend.NextErr() 438 } 439 440 backend.cloudFunc = func(name string) (cloud.Cloud, error) { 441 return cloud.Cloud{ 442 Name: "nuage", 443 Type: "dummy", 444 AuthTypes: []cloud.AuthType{cloud.EmptyAuthType, cloud.UserPassAuthType}, 445 Regions: []cloud.Region{{Name: "nine", Endpoint: "endpoint"}}, 446 }, backend.NextErr() 447 } 448 backend.cloudCredentialFunc = func(tag names.CloudCredentialTag) (state.Credential, error) { 449 return statetesting.NewEmptyCredential(), backend.NextErr() 450 } 451 return &backend 452 } 453 454 type mockProvider struct { 455 *testing.Stub 456 allInstancesFunc func(ctx context.ProviderCallContext) ([]instances.Instance, error) 457 } 458 459 func (m *mockProvider) AllInstances(ctx context.ProviderCallContext) ([]instances.Instance, error) { 460 m.MethodCall(m, "AllInstances", ctx) 461 return m.allInstancesFunc(ctx) 462 } 463 464 type mockInstance struct { 465 instances.Instance 466 id string 467 } 468 469 func (i *mockInstance) Id() instance.Id { 470 return instance.Id(i.id) 471 } 472 473 type mockMachine struct { 474 id string 475 container bool 476 manualFunc func() (bool, error) 477 instanceIdFunc func() (instance.Id, error) 478 } 479 480 func (m *mockMachine) IsManual() (bool, error) { 481 return m.manualFunc() 482 } 483 484 func (m *mockMachine) IsContainer() bool { 485 return m.container 486 } 487 488 func (m *mockMachine) InstanceId() (instance.Id, error) { 489 return m.instanceIdFunc() 490 } 491 492 func (m *mockMachine) InstanceNames() (instance.Id, string, error) { 493 instId, err := m.instanceIdFunc() 494 return instId, "", err 495 } 496 497 func (m *mockMachine) Id() string { 498 return m.id 499 } 500 501 func createTestMachine(id, instanceId string) *mockMachine { 502 return &mockMachine{ 503 id: id, 504 manualFunc: func() (bool, error) { return false, nil }, 505 instanceIdFunc: func() (instance.Id, error) { return instance.Id(instanceId), nil }, 506 } 507 } 508 509 type mockPersistedBackend struct { 510 *testing.Stub 511 allMachinesFunc func() ([]credentialcommon.Machine, error) 512 513 modelFunc func() (credentialcommon.Model, error) 514 controllerConfigFunc func() (credentialcommon.ControllerConfig, error) 515 cloudFunc func(name string) (cloud.Cloud, error) 516 cloudCredentialFunc func(tag names.CloudCredentialTag) (state.Credential, error) 517 } 518 519 func (m *mockPersistedBackend) AllMachines() ([]credentialcommon.Machine, error) { 520 m.MethodCall(m, "AllMachines") 521 return m.allMachinesFunc() 522 } 523 524 func (m *mockPersistedBackend) Model() (credentialcommon.Model, error) { 525 m.MethodCall(m, "Model") 526 return m.modelFunc() 527 } 528 529 func (m *mockPersistedBackend) ControllerConfig() (credentialcommon.ControllerConfig, error) { 530 m.MethodCall(m, "ControllerConfig") 531 return m.controllerConfigFunc() 532 } 533 534 func (m *mockPersistedBackend) Cloud(name string) (cloud.Cloud, error) { 535 m.MethodCall(m, "Cloud", name) 536 return m.cloudFunc(name) 537 } 538 539 func (m *mockPersistedBackend) CloudCredential(tag names.CloudCredentialTag) (state.Credential, error) { 540 m.MethodCall(m, "CloudCredential", tag) 541 return m.cloudCredentialFunc(tag) 542 } 543 544 type mockModel struct { 545 modelType state.ModelType 546 cloudNameFunc func() string 547 cloudRegionFunc func() string 548 configFunc func() (*config.Config, error) 549 validateCredentialFunc func(tag names.CloudCredentialTag, credential cloud.Credential) error 550 cloudCredentialTagFunc func() (names.CloudCredentialTag, bool) 551 } 552 553 func (m *mockModel) CloudName() string { 554 return m.cloudNameFunc() 555 } 556 557 func (m *mockModel) CloudRegion() string { 558 return m.cloudRegionFunc() 559 } 560 561 func (m *mockModel) Config() (*config.Config, error) { 562 return m.configFunc() 563 } 564 565 func (m *mockModel) Type() state.ModelType { 566 return m.modelType 567 } 568 569 func (m *mockModel) CloudCredentialTag() (names.CloudCredentialTag, bool) { 570 return m.cloudCredentialTagFunc() 571 } 572 573 func (m *mockModel) ValidateCloudCredential(tag names.CloudCredentialTag, credential cloud.Credential) error { 574 return m.validateCredentialFunc(tag, credential) 575 } 576 577 func createTestModel() *mockModel { 578 return &mockModel{ 579 modelType: state.ModelTypeIAAS, 580 cloudNameFunc: func() string { return "nuage" }, 581 cloudRegionFunc: func() string { return "nine" }, 582 configFunc: func() (*config.Config, error) { 583 return nil, nil 584 }, 585 validateCredentialFunc: func(tag names.CloudCredentialTag, credential cloud.Credential) error { 586 return nil 587 }, 588 cloudCredentialTagFunc: func() (names.CloudCredentialTag, bool) { 589 // return true here since, most of the time, we want to test when the cloud credential is set. 590 return names.CloudCredentialTag{}, true 591 }, 592 } 593 } 594 595 var ( 596 testCredential = cloud.NewCredential( 597 cloud.UserPassAuthType, 598 map[string]string{ 599 "username": "user", 600 "password": "password", 601 }, 602 ) 603 testControllerConfig = jujuesting.FakeControllerConfig() 604 ) 605 606 type mockEnviron struct { 607 environs.Environ 608 *mockProvider 609 } 610 611 func (m *mockEnviron) AllInstances(ctx context.ProviderCallContext) ([]instances.Instance, error) { 612 return m.mockProvider.AllInstances(ctx) 613 } 614 615 type mockCaasBroker struct { 616 caas.Broker 617 618 namespacesFunc func() ([]string, error) 619 } 620 621 func (m *mockCaasBroker) Namespaces() ([]string, error) { 622 return m.namespacesFunc() 623 } 624 625 func (m *mockCaasBroker) CheckCloudCredentials() error { 626 // The k8s provider implements this via a list namespaces call to the cluster 627 _, err := m.namespacesFunc() 628 return err 629 }