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