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