github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/client/modelmanager/modelmanager_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package modelmanager_test
     5  
     6  import (
     7  	"regexp"
     8  	"time"
     9  
    10  	"github.com/juju/errors"
    11  	"github.com/juju/names/v5"
    12  	jc "github.com/juju/testing/checkers"
    13  	"go.uber.org/mock/gomock"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/api/base"
    17  	basemocks "github.com/juju/juju/api/base/mocks"
    18  	"github.com/juju/juju/api/client/modelmanager"
    19  	"github.com/juju/juju/api/common"
    20  	apiservererrors "github.com/juju/juju/apiserver/errors"
    21  	"github.com/juju/juju/core/life"
    22  	"github.com/juju/juju/core/model"
    23  	"github.com/juju/juju/core/status"
    24  	"github.com/juju/juju/environs/config"
    25  	"github.com/juju/juju/rpc/params"
    26  	coretesting "github.com/juju/juju/testing"
    27  )
    28  
    29  type modelmanagerSuite struct {
    30  }
    31  
    32  var _ = gc.Suite(&modelmanagerSuite{})
    33  
    34  func (s *modelmanagerSuite) TestCreateModelBadUser(c *gc.C) {
    35  	ctrl := gomock.NewController(c)
    36  	defer ctrl.Finish()
    37  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
    38  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
    39  	_, err := client.CreateModel("mymodel", "not a user", "", "", names.CloudCredentialTag{}, nil)
    40  	c.Assert(err, gc.ErrorMatches, `invalid owner name "not a user"`)
    41  }
    42  
    43  func (s *modelmanagerSuite) TestCreateModelBadCloud(c *gc.C) {
    44  	ctrl := gomock.NewController(c)
    45  	defer ctrl.Finish()
    46  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
    47  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
    48  	_, err := client.CreateModel("mymodel", "bob", "123!", "", names.CloudCredentialTag{}, nil)
    49  	c.Assert(err, gc.ErrorMatches, `invalid cloud name "123!"`)
    50  }
    51  
    52  func (s *modelmanagerSuite) TestCreateModel(c *gc.C) {
    53  	ctrl := gomock.NewController(c)
    54  	defer ctrl.Finish()
    55  
    56  	args := params.ModelCreateArgs{
    57  		Name:        "new-model",
    58  		OwnerTag:    "user-bob",
    59  		Config:      map[string]interface{}{"abc": 123},
    60  		CloudTag:    "cloud-nimbus",
    61  		CloudRegion: "catbus",
    62  	}
    63  
    64  	result := new(params.ModelInfo)
    65  	ress := params.ModelInfo{}
    66  	ress.Name = "dowhatimean"
    67  	ress.Type = "iaas"
    68  	ress.UUID = "youyoueyedee"
    69  	ress.ControllerUUID = "youyoueyedeetoo"
    70  	ress.ProviderType = "C-123"
    71  	ress.DefaultSeries = "M*A*S*H"
    72  	ress.CloudTag = "cloud-nimbus"
    73  	ress.CloudRegion = "catbus"
    74  	ress.OwnerTag = "user-fnord"
    75  	ress.Life = "alive"
    76  
    77  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
    78  	mockFacadeCaller.EXPECT().FacadeCall("CreateModel", args, result).SetArg(2, ress).Return(nil)
    79  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
    80  
    81  	newModel, err := client.CreateModel(
    82  		"new-model",
    83  		"bob",
    84  		"nimbus",
    85  		"catbus",
    86  		names.CloudCredentialTag{},
    87  		map[string]interface{}{"abc": 123},
    88  	)
    89  	c.Assert(err, jc.ErrorIsNil)
    90  
    91  	c.Assert(newModel, jc.DeepEquals, base.ModelInfo{
    92  		Name:           "dowhatimean",
    93  		Type:           model.IAAS,
    94  		UUID:           "youyoueyedee",
    95  		ControllerUUID: "youyoueyedeetoo",
    96  		ProviderType:   "C-123",
    97  		DefaultSeries:  "M*A*S*H",
    98  		Cloud:          "nimbus",
    99  		CloudRegion:    "catbus",
   100  		Owner:          "fnord",
   101  		Life:           "alive",
   102  		Status: base.Status{
   103  			Data: make(map[string]interface{}),
   104  		},
   105  		Users:    []base.UserInfo{},
   106  		Machines: []base.Machine{},
   107  	})
   108  }
   109  
   110  func (s *modelmanagerSuite) TestListModelsBadUser(c *gc.C) {
   111  	ctrl := gomock.NewController(c)
   112  	defer ctrl.Finish()
   113  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   114  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   115  	_, err := client.ListModels("not a user")
   116  	c.Assert(err, gc.ErrorMatches, `invalid user name "not a user"`)
   117  }
   118  
   119  func (s *modelmanagerSuite) TestListModels(c *gc.C) {
   120  	ctrl := gomock.NewController(c)
   121  	defer ctrl.Finish()
   122  
   123  	lastConnection := time.Now()
   124  	args := params.Entity{"user-user@remote"}
   125  
   126  	result := new(params.UserModelList)
   127  	ress := params.UserModelList{
   128  		UserModels: []params.UserModel{{
   129  			Model: params.Model{
   130  				Name:     "yo",
   131  				UUID:     "wei",
   132  				Type:     "caas",
   133  				OwnerTag: "user-user@remote",
   134  			},
   135  			LastConnection: &lastConnection,
   136  		}, {
   137  			Model: params.Model{
   138  				Name:     "sup",
   139  				UUID:     "hazzagarn",
   140  				Type:     "iaas",
   141  				OwnerTag: "user-phyllis@thrace",
   142  			},
   143  		}},
   144  	}
   145  
   146  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   147  	mockFacadeCaller.EXPECT().FacadeCall("ListModels", args, result).SetArg(2, ress).Return(nil)
   148  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   149  
   150  	models, err := client.ListModels("user@remote")
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	c.Assert(models, jc.DeepEquals, []base.UserModel{{
   153  		Name:           "yo",
   154  		UUID:           "wei",
   155  		Type:           model.CAAS,
   156  		Owner:          "user@remote",
   157  		LastConnection: &lastConnection,
   158  	}, {
   159  		Name:  "sup",
   160  		UUID:  "hazzagarn",
   161  		Type:  model.IAAS,
   162  		Owner: "phyllis@thrace",
   163  	}})
   164  }
   165  
   166  func (s *modelmanagerSuite) testDestroyModel(c *gc.C, destroyStorage, force *bool, maxWait *time.Duration, timeout time.Duration) {
   167  	ctrl := gomock.NewController(c)
   168  	defer ctrl.Finish()
   169  
   170  	args := params.DestroyModelsParams{
   171  		Models: []params.DestroyModelParams{{
   172  			ModelTag:       coretesting.ModelTag.String(),
   173  			DestroyStorage: destroyStorage,
   174  			Force:          force,
   175  			MaxWait:        maxWait,
   176  			Timeout:        &timeout,
   177  		}},
   178  	}
   179  
   180  	result := new(params.ErrorResults)
   181  	ress := params.ErrorResults{
   182  		Results: []params.ErrorResult{{}},
   183  	}
   184  
   185  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   186  	mockFacadeCaller.EXPECT().FacadeCall("DestroyModels", args, result).SetArg(2, ress).Return(nil)
   187  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   188  
   189  	err := client.DestroyModel(coretesting.ModelTag, destroyStorage, force, maxWait, &timeout)
   190  	c.Assert(err, jc.ErrorIsNil)
   191  }
   192  
   193  func (s *modelmanagerSuite) TestDestroyModel(c *gc.C) {
   194  	true_ := true
   195  	false_ := false
   196  	defaultMin := 1 * time.Minute
   197  	s.testDestroyModel(c, nil, nil, nil, time.Minute)
   198  	s.testDestroyModel(c, nil, &true_, nil, time.Minute)
   199  	s.testDestroyModel(c, nil, &true_, &defaultMin, time.Minute)
   200  	s.testDestroyModel(c, nil, &false_, nil, time.Minute)
   201  	s.testDestroyModel(c, &true_, nil, nil, time.Minute)
   202  	s.testDestroyModel(c, &true_, &false_, nil, time.Minute)
   203  	s.testDestroyModel(c, &true_, &true_, &defaultMin, time.Minute)
   204  	s.testDestroyModel(c, &false_, nil, nil, time.Minute)
   205  	s.testDestroyModel(c, &false_, &false_, nil, time.Minute)
   206  	s.testDestroyModel(c, &false_, &true_, &defaultMin, time.Minute)
   207  }
   208  
   209  func (s *modelmanagerSuite) TestModelDefaults(c *gc.C) {
   210  	ctrl := gomock.NewController(c)
   211  	defer ctrl.Finish()
   212  
   213  	args := params.Entities{
   214  		Entities: []params.Entity{{Tag: names.NewCloudTag("aws").String()}},
   215  	}
   216  
   217  	res := new(params.ModelDefaultsResults)
   218  	ress := params.ModelDefaultsResults{
   219  		Results: []params.ModelDefaultsResult{{Config: map[string]params.ModelDefaults{
   220  			"foo": {"bar", "model", []params.RegionDefaults{{
   221  				"dummy-region",
   222  				"dummy-value"}}},
   223  		}}},
   224  	}
   225  
   226  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   227  	mockFacadeCaller.EXPECT().FacadeCall("ModelDefaultsForClouds", args, res).SetArg(2, ress).Return(nil)
   228  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   229  
   230  	result, err := client.ModelDefaults("aws")
   231  	c.Assert(err, jc.ErrorIsNil)
   232  
   233  	c.Assert(result, jc.DeepEquals, config.ModelDefaultAttributes{
   234  		"foo": {"bar", "model", []config.RegionDefaultValue{{
   235  			"dummy-region",
   236  			"dummy-value"}}},
   237  	})
   238  }
   239  
   240  func (s *modelmanagerSuite) TestSetModelDefaults(c *gc.C) {
   241  	ctrl := gomock.NewController(c)
   242  	defer ctrl.Finish()
   243  
   244  	args := params.SetModelDefaults{
   245  		Config: []params.ModelDefaultValues{{
   246  			CloudTag:    "cloud-mycloud",
   247  			CloudRegion: "region",
   248  			Config: map[string]interface{}{
   249  				"some-name":  "value",
   250  				"other-name": true,
   251  			},
   252  		}}}
   253  
   254  	res := new(params.ErrorResults)
   255  	ress := params.ErrorResults{
   256  		Results: []params.ErrorResult{{Error: nil}},
   257  	}
   258  
   259  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   260  	mockFacadeCaller.EXPECT().FacadeCall("SetModelDefaults", args, res).SetArg(2, ress).Return(nil)
   261  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   262  
   263  	err := client.SetModelDefaults("mycloud", "region", map[string]interface{}{
   264  		"some-name":  "value",
   265  		"other-name": true,
   266  	})
   267  	c.Assert(err, jc.ErrorIsNil)
   268  }
   269  
   270  func (s *modelmanagerSuite) TestUnsetModelDefaults(c *gc.C) {
   271  	ctrl := gomock.NewController(c)
   272  	defer ctrl.Finish()
   273  
   274  	args := params.UnsetModelDefaults{
   275  		Keys: []params.ModelUnsetKeys{{
   276  			CloudTag:    "cloud-mycloud",
   277  			CloudRegion: "region",
   278  			Keys:        []string{"foo", "bar"},
   279  		}}}
   280  
   281  	res := new(params.ErrorResults)
   282  	ress := params.ErrorResults{
   283  		Results: []params.ErrorResult{{Error: nil}},
   284  	}
   285  
   286  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   287  	mockFacadeCaller.EXPECT().FacadeCall("UnsetModelDefaults", args, res).SetArg(2, ress).Return(nil)
   288  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   289  
   290  	err := client.UnsetModelDefaults("mycloud", "region", "foo", "bar")
   291  	c.Assert(err, jc.ErrorIsNil)
   292  }
   293  
   294  func (s *modelmanagerSuite) TestModelStatus(c *gc.C) {
   295  	ctrl := gomock.NewController(c)
   296  	defer ctrl.Finish()
   297  
   298  	args := params.Entities{
   299  		Entities: []params.Entity{
   300  			{Tag: coretesting.ModelTag.String()},
   301  			{Tag: coretesting.ModelTag.String()},
   302  		},
   303  	}
   304  
   305  	res := new(params.ModelStatusResults)
   306  	ress := params.ModelStatusResults{
   307  		Results: []params.ModelStatus{
   308  			{
   309  				ModelTag:           coretesting.ModelTag.String(),
   310  				OwnerTag:           "user-glenda",
   311  				ApplicationCount:   3,
   312  				HostedMachineCount: 2,
   313  				Life:               "alive",
   314  				Machines: []params.ModelMachineInfo{{
   315  					Id:         "0",
   316  					InstanceId: "inst-ance",
   317  					Status:     "pending",
   318  				}},
   319  			},
   320  			{
   321  				Error: apiservererrors.ServerError(errors.New("model error")),
   322  			},
   323  		},
   324  	}
   325  
   326  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   327  	mockFacadeCaller.EXPECT().FacadeCall("ModelStatus", args, res).SetArg(2, ress).Return(nil)
   328  	client := common.NewModelStatusAPI(mockFacadeCaller)
   329  
   330  	results, err := client.ModelStatus(coretesting.ModelTag, coretesting.ModelTag)
   331  	c.Assert(err, jc.ErrorIsNil)
   332  	c.Assert(results[0], jc.DeepEquals, base.ModelStatus{
   333  		UUID:               coretesting.ModelTag.Id(),
   334  		TotalMachineCount:  1,
   335  		HostedMachineCount: 2,
   336  		ApplicationCount:   3,
   337  		Owner:              "glenda",
   338  		Life:               life.Alive,
   339  		Machines:           []base.Machine{{Id: "0", InstanceId: "inst-ance", Status: "pending"}},
   340  	})
   341  	c.Assert(results[1].Error, gc.ErrorMatches, "model error")
   342  }
   343  
   344  func (s *modelmanagerSuite) TestModelStatusEmpty(c *gc.C) {
   345  	ctrl := gomock.NewController(c)
   346  	defer ctrl.Finish()
   347  
   348  	args := params.Entities{
   349  		Entities: []params.Entity{},
   350  	}
   351  
   352  	res := new(params.ModelStatusResults)
   353  	ress := params.ModelStatusResults{}
   354  
   355  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   356  	mockFacadeCaller.EXPECT().FacadeCall("ModelStatus", args, res).SetArg(2, ress).Return(nil)
   357  	client := common.NewModelStatusAPI(mockFacadeCaller)
   358  
   359  	results, err := client.ModelStatus()
   360  	c.Assert(err, jc.ErrorIsNil)
   361  	c.Assert(results, jc.DeepEquals, []base.ModelStatus{})
   362  }
   363  
   364  func (s *modelmanagerSuite) TestModelStatusError(c *gc.C) {
   365  	ctrl := gomock.NewController(c)
   366  	defer ctrl.Finish()
   367  
   368  	args := params.Entities{
   369  		Entities: []params.Entity{
   370  			{Tag: coretesting.ModelTag.String()},
   371  			{Tag: coretesting.ModelTag.String()},
   372  		},
   373  	}
   374  
   375  	res := new(params.ModelStatusResults)
   376  
   377  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   378  	mockFacadeCaller.EXPECT().FacadeCall("ModelStatus", args, res).Return(errors.New("model error"))
   379  	client := common.NewModelStatusAPI(mockFacadeCaller)
   380  	out, err := client.ModelStatus(coretesting.ModelTag, coretesting.ModelTag)
   381  	c.Assert(err, gc.ErrorMatches, "model error")
   382  	c.Assert(out, gc.IsNil)
   383  }
   384  
   385  func createModelSummary() *params.ModelSummary {
   386  	return &params.ModelSummary{
   387  		Name:               "name",
   388  		UUID:               "uuid",
   389  		Type:               "iaas",
   390  		ControllerUUID:     "controllerUUID",
   391  		ProviderType:       "aws",
   392  		DefaultSeries:      "xenial",
   393  		CloudTag:           "cloud-aws",
   394  		CloudRegion:        "us-east-1",
   395  		CloudCredentialTag: "cloudcred-foo_bob_one",
   396  		OwnerTag:           "user-admin",
   397  		Life:               life.Alive,
   398  		Status:             params.EntityStatus{Status: status.Status("active")},
   399  		UserAccess:         params.ModelAdminAccess,
   400  		Counts:             []params.ModelEntityCount{},
   401  	}
   402  }
   403  
   404  func (s *modelmanagerSuite) TestListModelSummaries(c *gc.C) {
   405  	ctrl := gomock.NewController(c)
   406  	defer ctrl.Finish()
   407  
   408  	userTag := names.NewUserTag("commander")
   409  	testModelInfo := createModelSummary()
   410  
   411  	args := params.ModelSummariesRequest{
   412  		UserTag: userTag.String(),
   413  		All:     true,
   414  	}
   415  
   416  	res := new(params.ModelSummaryResults)
   417  	ress := params.ModelSummaryResults{
   418  		Results: []params.ModelSummaryResult{
   419  			{Result: testModelInfo},
   420  			{Error: apiservererrors.ServerError(errors.New("model error"))},
   421  		},
   422  	}
   423  
   424  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   425  	mockFacadeCaller.EXPECT().FacadeCall("ListModelSummaries", args, res).SetArg(2, ress).Return(nil)
   426  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   427  
   428  	results, err := client.ListModelSummaries(userTag.Id(), true)
   429  	c.Assert(err, jc.ErrorIsNil)
   430  
   431  	c.Assert(results, gc.HasLen, 2)
   432  	c.Assert(results[0], jc.DeepEquals, base.UserModelSummary{Name: testModelInfo.Name,
   433  		UUID:            testModelInfo.UUID,
   434  		Type:            model.IAAS,
   435  		ControllerUUID:  testModelInfo.ControllerUUID,
   436  		ProviderType:    testModelInfo.ProviderType,
   437  		DefaultSeries:   testModelInfo.DefaultSeries,
   438  		Cloud:           "aws",
   439  		CloudRegion:     "us-east-1",
   440  		CloudCredential: "foo/bob/one",
   441  		Owner:           "admin",
   442  		Life:            "alive",
   443  		Status: base.Status{
   444  			Status: status.Active,
   445  			Data:   map[string]interface{}{},
   446  		},
   447  		ModelUserAccess: "admin",
   448  		Counts:          []base.EntityCount{},
   449  	})
   450  	c.Assert(errors.Cause(results[1].Error), gc.ErrorMatches, "model error")
   451  }
   452  
   453  func (s *modelmanagerSuite) TestListModelSummariesParsingErrors(c *gc.C) {
   454  	ctrl := gomock.NewController(c)
   455  	defer ctrl.Finish()
   456  
   457  	badOwnerInfo := createModelSummary()
   458  	badOwnerInfo.OwnerTag = "owner-user"
   459  
   460  	badCloudInfo := createModelSummary()
   461  	badCloudInfo.CloudTag = "not-cloud"
   462  
   463  	badCredentialsInfo := createModelSummary()
   464  	badCredentialsInfo.CloudCredentialTag = "not-credential"
   465  
   466  	args := params.ModelSummariesRequest{
   467  		UserTag: "user-commander",
   468  		All:     true,
   469  	}
   470  
   471  	res := new(params.ModelSummaryResults)
   472  	ress := params.ModelSummaryResults{
   473  		Results: []params.ModelSummaryResult{
   474  			{Result: badOwnerInfo},
   475  			{Result: badCloudInfo},
   476  			{Result: badCredentialsInfo},
   477  		},
   478  	}
   479  
   480  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   481  	mockFacadeCaller.EXPECT().FacadeCall("ListModelSummaries", args, res).SetArg(2, ress).Return(nil)
   482  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   483  	results, err := client.ListModelSummaries("commander", true)
   484  	c.Assert(err, jc.ErrorIsNil)
   485  	c.Assert(results, gc.HasLen, 3)
   486  	c.Assert(results[0].Error, gc.ErrorMatches, `while parsing model owner tag: "owner-user" is not a valid tag`)
   487  	c.Assert(results[1].Error, gc.ErrorMatches, `while parsing model cloud tag: "not-cloud" is not a valid tag`)
   488  	c.Assert(results[2].Error, gc.ErrorMatches, `while parsing model cloud credential tag: "not-credential" is not a valid tag`)
   489  }
   490  
   491  func (s *modelmanagerSuite) TestListModelSummariesInvalidUserIn(c *gc.C) {
   492  	ctrl := gomock.NewController(c)
   493  	defer ctrl.Finish()
   494  
   495  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   496  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   497  	out, err := client.ListModelSummaries("++)captain", false)
   498  	c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta(`invalid user name "++)captain"`))
   499  	c.Assert(out, gc.IsNil)
   500  }
   501  
   502  func (s *modelmanagerSuite) TestListModelSummariesServerError(c *gc.C) {
   503  	ctrl := gomock.NewController(c)
   504  	defer ctrl.Finish()
   505  
   506  	args := params.ModelSummariesRequest{
   507  		UserTag: "user-captain",
   508  		All:     false,
   509  	}
   510  
   511  	res := new(params.ModelSummaryResults)
   512  
   513  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   514  	mockFacadeCaller.EXPECT().FacadeCall("ListModelSummaries", args, res).Return(errors.New("captain, error"))
   515  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   516  	out, err := client.ListModelSummaries("captain", false)
   517  	c.Assert(err, gc.ErrorMatches, "captain, error")
   518  	c.Assert(out, gc.IsNil)
   519  }
   520  
   521  func (s *modelmanagerSuite) TestChangeModelCredential(c *gc.C) {
   522  	ctrl := gomock.NewController(c)
   523  	defer ctrl.Finish()
   524  
   525  	credentialTag := names.NewCloudCredentialTag("foo/bob/bar")
   526  	args := params.ChangeModelCredentialsParams{
   527  		Models: []params.ChangeModelCredentialParams{
   528  			{ModelTag: coretesting.ModelTag.String(), CloudCredentialTag: credentialTag.String()},
   529  		},
   530  	}
   531  
   532  	res := new(params.ErrorResults)
   533  	ress := params.ErrorResults{
   534  		Results: []params.ErrorResult{{}},
   535  	}
   536  
   537  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   538  	mockFacadeCaller.EXPECT().FacadeCall("ChangeModelCredential", args, res).SetArg(2, ress).Return(nil)
   539  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   540  
   541  	err := client.ChangeModelCredential(coretesting.ModelTag, credentialTag)
   542  	c.Assert(err, jc.ErrorIsNil)
   543  }
   544  
   545  func (s *modelmanagerSuite) TestChangeModelCredentialManyResults(c *gc.C) {
   546  	ctrl := gomock.NewController(c)
   547  	defer ctrl.Finish()
   548  
   549  	credentialTag := names.NewCloudCredentialTag("foo/bob/bar")
   550  
   551  	args := params.ChangeModelCredentialsParams{
   552  		Models: []params.ChangeModelCredentialParams{
   553  			{ModelTag: coretesting.ModelTag.String(), CloudCredentialTag: credentialTag.String()},
   554  		},
   555  	}
   556  
   557  	res := new(params.ErrorResults)
   558  	ress := params.ErrorResults{
   559  		Results: []params.ErrorResult{{}, {}},
   560  	}
   561  
   562  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   563  	mockFacadeCaller.EXPECT().FacadeCall("ChangeModelCredential", args, res).SetArg(2, ress).Return(nil)
   564  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   565  
   566  	err := client.ChangeModelCredential(coretesting.ModelTag, credentialTag)
   567  	c.Assert(err, gc.ErrorMatches, `expected 1 result, got 2`)
   568  }
   569  
   570  func (s *modelmanagerSuite) TestChangeModelCredentialCallFailed(c *gc.C) {
   571  	ctrl := gomock.NewController(c)
   572  	defer ctrl.Finish()
   573  
   574  	credentialTag := names.NewCloudCredentialTag("foo/bob/bar")
   575  	args := params.ChangeModelCredentialsParams{
   576  		Models: []params.ChangeModelCredentialParams{
   577  			{ModelTag: coretesting.ModelTag.String(), CloudCredentialTag: credentialTag.String()},
   578  		},
   579  	}
   580  
   581  	res := new(params.ErrorResults)
   582  
   583  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   584  	mockFacadeCaller.EXPECT().FacadeCall("ChangeModelCredential", args, res).Return(errors.New("failed call"))
   585  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   586  	err := client.ChangeModelCredential(coretesting.ModelTag, credentialTag)
   587  	c.Assert(err, gc.ErrorMatches, `failed call`)
   588  }
   589  
   590  func (s *modelmanagerSuite) TestChangeModelCredentialUpdateFailed(c *gc.C) {
   591  	ctrl := gomock.NewController(c)
   592  	defer ctrl.Finish()
   593  
   594  	credentialTag := names.NewCloudCredentialTag("foo/bob/bar")
   595  	args := params.ChangeModelCredentialsParams{
   596  		Models: []params.ChangeModelCredentialParams{
   597  			{ModelTag: coretesting.ModelTag.String(), CloudCredentialTag: credentialTag.String()},
   598  		},
   599  	}
   600  
   601  	res := new(params.ErrorResults)
   602  	ress := params.ErrorResults{
   603  		Results: []params.ErrorResult{{Error: apiservererrors.ServerError(errors.New("update error"))}},
   604  	}
   605  
   606  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   607  	mockFacadeCaller.EXPECT().FacadeCall("ChangeModelCredential", args, res).SetArg(2, ress).Return(nil)
   608  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   609  
   610  	err := client.ChangeModelCredential(coretesting.ModelTag, credentialTag)
   611  	c.Assert(err, gc.ErrorMatches, `update error`)
   612  }
   613  
   614  type dumpModelSuite struct {
   615  	coretesting.BaseSuite
   616  }
   617  
   618  var _ = gc.Suite(&dumpModelSuite{})
   619  
   620  func (s *dumpModelSuite) TestDumpModelDB(c *gc.C) {
   621  	ctrl := gomock.NewController(c)
   622  	defer ctrl.Finish()
   623  
   624  	expected := map[string]interface{}{
   625  		"models": []map[string]interface{}{{
   626  			"name": "admin",
   627  			"uuid": "some-uuid",
   628  		}},
   629  		"machines": []map[string]interface{}{{
   630  			"id":   "0",
   631  			"life": 0,
   632  		}},
   633  	}
   634  	args := params.Entities{[]params.Entity{{coretesting.ModelTag.String()}}}
   635  
   636  	res := new(params.MapResults)
   637  	ress := params.MapResults{Results: []params.MapResult{{
   638  		Result: expected,
   639  	}}}
   640  
   641  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   642  	mockFacadeCaller.EXPECT().FacadeCall("DumpModelsDB", args, res).SetArg(2, ress).Return(nil)
   643  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   644  
   645  	out, err := client.DumpModelDB(coretesting.ModelTag)
   646  	c.Assert(err, jc.ErrorIsNil)
   647  	c.Assert(out, jc.DeepEquals, expected)
   648  }
   649  
   650  func (s *dumpModelSuite) TestDumpModelDBError(c *gc.C) {
   651  	ctrl := gomock.NewController(c)
   652  	defer ctrl.Finish()
   653  
   654  	args := params.Entities{[]params.Entity{{coretesting.ModelTag.String()}}}
   655  
   656  	res := new(params.MapResults)
   657  	ress := params.MapResults{Results: []params.MapResult{{
   658  		Error: &params.Error{Message: "fake error"},
   659  	}}}
   660  
   661  	mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl)
   662  	mockFacadeCaller.EXPECT().FacadeCall("DumpModelsDB", args, res).SetArg(2, ress).Return(nil)
   663  	client := modelmanager.NewClientFromCaller(mockFacadeCaller)
   664  
   665  	out, err := client.DumpModelDB(coretesting.ModelTag)
   666  	c.Assert(err, gc.ErrorMatches, "fake error")
   667  	c.Assert(out, gc.IsNil)
   668  }