github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/model/show_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for info.
     3  
     4  package model_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/cmd"
    10  	"github.com/juju/cmd/cmdtesting"
    11  	"github.com/juju/errors"
    12  	gitjujutesting "github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	"github.com/juju/version"
    15  	gc "gopkg.in/check.v1"
    16  	"gopkg.in/juju/names.v2"
    17  
    18  	"github.com/juju/juju/apiserver/params"
    19  	"github.com/juju/juju/cmd/juju/model"
    20  	coremodel "github.com/juju/juju/core/model"
    21  	"github.com/juju/juju/core/status"
    22  	"github.com/juju/juju/jujuclient"
    23  	"github.com/juju/juju/testing"
    24  )
    25  
    26  var _ = gc.Suite(&ShowCommandSuite{})
    27  var _ = gc.Suite(&showSLACommandSuite{})
    28  
    29  type ShowCommandSuite struct {
    30  	testing.FakeJujuXDGDataHomeSuite
    31  	fake            fakeModelShowClient
    32  	store           *jujuclient.MemStore
    33  	expectedOutput  attrs
    34  	expectedDisplay string
    35  }
    36  
    37  func (s *ShowCommandSuite) SetUpTest(c *gc.C) {
    38  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    39  	lastConnection := time.Date(2015, 3, 20, 0, 0, 0, 0, time.UTC)
    40  	statusSince := time.Date(2016, 4, 5, 0, 0, 0, 0, time.UTC)
    41  	migrationStart := time.Date(2016, 4, 6, 0, 10, 0, 0, time.UTC)
    42  	migrationEnd := time.Date(2016, 4, 7, 0, 0, 15, 0, time.UTC)
    43  
    44  	users := []params.ModelUserInfo{{
    45  		UserName:       "admin",
    46  		LastConnection: &lastConnection,
    47  		Access:         "write",
    48  	}, {
    49  		UserName:    "bob",
    50  		DisplayName: "Bob",
    51  		Access:      "read",
    52  	}}
    53  
    54  	s.fake = fakeModelShowClient{
    55  		info: params.ModelInfo{
    56  			Name:           "mymodel",
    57  			UUID:           testing.ModelTag.Id(),
    58  			Type:           "iaas",
    59  			ControllerUUID: "1ca2293b-fdb9-4299-97d6-55583bb39364",
    60  			IsController:   false,
    61  			OwnerTag:       "user-admin",
    62  			CloudTag:       "cloud-some-cloud",
    63  			CloudRegion:    "some-region",
    64  			ProviderType:   "openstack",
    65  			Life:           params.Alive,
    66  			Status: params.EntityStatus{
    67  				Status: status.Active,
    68  				Since:  &statusSince,
    69  			},
    70  			Users: users,
    71  			Migration: &params.ModelMigrationStatus{
    72  				Status: "obfuscating Quigley matrix",
    73  				Start:  &migrationStart,
    74  				End:    &migrationEnd,
    75  			},
    76  		},
    77  	}
    78  
    79  	s.expectedOutput = attrs{
    80  		"mymodel": attrs{
    81  			"name":            "admin/mymodel",
    82  			"short-name":      "mymodel",
    83  			"model-uuid":      "deadbeef-0bad-400d-8000-4b1d0d06f00d",
    84  			"model-type":      "iaas",
    85  			"controller-uuid": "1ca2293b-fdb9-4299-97d6-55583bb39364",
    86  			"controller-name": "testing",
    87  			"is-controller":   false,
    88  			"owner":           "admin",
    89  			"cloud":           "some-cloud",
    90  			"region":          "some-region",
    91  			"type":            "openstack",
    92  			"life":            "alive",
    93  			"status": attrs{
    94  				"current":         "active",
    95  				"since":           "2016-04-05",
    96  				"migration":       "obfuscating Quigley matrix",
    97  				"migration-start": "2016-04-06",
    98  				"migration-end":   "2016-04-07",
    99  			},
   100  			"users": attrs{
   101  				"admin": attrs{
   102  					"access":          "write",
   103  					"last-connection": "2015-03-20",
   104  				},
   105  				"bob": attrs{
   106  					"display-name":    "Bob",
   107  					"access":          "read",
   108  					"last-connection": "never connected",
   109  				},
   110  			},
   111  		},
   112  	}
   113  
   114  	s.store = jujuclient.NewMemStore()
   115  	s.store.CurrentControllerName = "testing"
   116  	s.store.Controllers["testing"] = jujuclient.ControllerDetails{}
   117  	s.store.Accounts["testing"] = jujuclient.AccountDetails{
   118  		User: "admin",
   119  	}
   120  	err := s.store.UpdateModel("testing", "admin/mymodel", jujuclient.ModelDetails{
   121  		ModelUUID: testing.ModelTag.Id(),
   122  		ModelType: coremodel.IAAS,
   123  	})
   124  	c.Assert(err, jc.ErrorIsNil)
   125  	s.store.Models["testing"].CurrentModel = "admin/mymodel"
   126  }
   127  
   128  func (s *ShowCommandSuite) TestShow(c *gc.C) {
   129  	_, err := cmdtesting.RunCommand(c, s.newShowCommand())
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	s.fake.CheckCalls(c, []gitjujutesting.StubCall{
   132  		{"ModelInfo", []interface{}{[]names.ModelTag{testing.ModelTag}}},
   133  		{"Close", nil},
   134  	})
   135  }
   136  
   137  func (s *ShowCommandSuite) TestShowUnknownCallsRefresh(c *gc.C) {
   138  	called := false
   139  	refresh := func(jujuclient.ClientStore, string) error {
   140  		called = true
   141  		return nil
   142  	}
   143  	_, err := cmdtesting.RunCommand(c, model.NewShowCommandForTest(&s.fake, refresh, s.store), "unknown")
   144  	c.Check(called, jc.IsTrue)
   145  	c.Check(err, jc.Satisfies, errors.IsNotFound)
   146  }
   147  
   148  func (s *ShowCommandSuite) TestShowFormatYaml(c *gc.C) {
   149  	ctx, err := cmdtesting.RunCommand(c, s.newShowCommand(), "--format", "yaml")
   150  	c.Assert(err, jc.ErrorIsNil)
   151  	c.Assert(cmdtesting.Stdout(ctx), jc.YAMLEquals, s.expectedOutput)
   152  }
   153  
   154  func (s *ShowCommandSuite) addCredentialToTestData() {
   155  	s.fake.info.CloudCredentialTag = "cloudcred-some-cloud_some-owner_some-credential"
   156  
   157  	modelOutput := s.expectedOutput["mymodel"].(attrs)
   158  	modelOutput["credential"] = attrs{
   159  		"name":  "some-credential",
   160  		"owner": "some-owner",
   161  		"cloud": "some-cloud",
   162  	}
   163  }
   164  
   165  func (s *ShowCommandSuite) TestShowWithCredentialFormatYaml(c *gc.C) {
   166  	s.addCredentialToTestData()
   167  	ctx, err := cmdtesting.RunCommand(c, s.newShowCommand(), "--format", "yaml")
   168  	c.Assert(err, jc.ErrorIsNil)
   169  	c.Assert(cmdtesting.Stdout(ctx), jc.YAMLEquals, s.expectedOutput)
   170  }
   171  
   172  func (s *ShowCommandSuite) TestShowFormatJson(c *gc.C) {
   173  	ctx, err := cmdtesting.RunCommand(c, s.newShowCommand(), "--format", "json")
   174  	c.Assert(err, jc.ErrorIsNil)
   175  	c.Assert(cmdtesting.Stdout(ctx), jc.JSONEquals, s.expectedOutput)
   176  }
   177  
   178  func (s *ShowCommandSuite) TestShowWithCredentialFormatJson(c *gc.C) {
   179  	s.addCredentialToTestData()
   180  	ctx, err := cmdtesting.RunCommand(c, s.newShowCommand(), "--format", "json")
   181  	c.Assert(err, jc.ErrorIsNil)
   182  	c.Assert(cmdtesting.Stdout(ctx), jc.JSONEquals, s.expectedOutput)
   183  }
   184  
   185  func (s *ShowCommandSuite) TestUnrecognizedArg(c *gc.C) {
   186  	_, err := cmdtesting.RunCommand(c, s.newShowCommand(), "admin", "whoops")
   187  	c.Assert(err, gc.ErrorMatches, `unrecognized args: \["whoops"\]`)
   188  }
   189  
   190  func (s *ShowCommandSuite) TestShowBasicIncompleteModelsYaml(c *gc.C) {
   191  	s.fake.infos = []params.ModelInfoResult{
   192  		{Result: createBasicModelInfo()},
   193  	}
   194  	s.expectedDisplay = `
   195  basic-model:
   196    name: owner/basic-model
   197    short-name: basic-model
   198    model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d
   199    model-type: iaas
   200    controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d
   201    controller-name: testing
   202    is-controller: false
   203    owner: owner
   204    cloud: altostratus
   205    region: mid-level
   206    life: dead
   207  `[1:]
   208  	s.assertShowOutput(c, "yaml")
   209  }
   210  
   211  func (s *ShowCommandSuite) TestShowBasicIncompleteModelsJson(c *gc.C) {
   212  	s.fake.infos = []params.ModelInfoResult{
   213  		{Result: createBasicModelInfo()},
   214  	}
   215  	s.expectedDisplay = "{\"basic-model\":" +
   216  		"{\"name\":\"owner/basic-model\"," +
   217  		"\"short-name\":\"basic-model\"," +
   218  		"\"model-uuid\":\"deadbeef-0bad-400d-8000-4b1d0d06f00d\"," +
   219  		"\"model-type\":\"iaas\"," +
   220  		"\"controller-uuid\":\"deadbeef-1bad-500d-9000-4b1d0d06f00d\"," +
   221  		"\"controller-name\":\"testing\"," +
   222  		"\"is-controller\":false," +
   223  		"\"owner\":\"owner\"," +
   224  		"\"cloud\":\"altostratus\"," +
   225  		"\"region\":\"mid-level\"," +
   226  		"\"life\":\"dead\"}}\n"
   227  	s.assertShowOutput(c, "json")
   228  }
   229  
   230  func (s *ShowCommandSuite) TestShowBasicWithStatusIncompleteModelsYaml(c *gc.C) {
   231  	s.fake.infos = []params.ModelInfoResult{
   232  		{Result: createBasicModelInfoWithStatus()},
   233  	}
   234  	s.expectedDisplay = `
   235  basic-model:
   236    name: owner/basic-model
   237    short-name: basic-model
   238    model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d
   239    model-type: iaas
   240    controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d
   241    controller-name: testing
   242    is-controller: false
   243    owner: owner
   244    cloud: altostratus
   245    region: mid-level
   246    life: dead
   247    status:
   248      current: busy
   249  `[1:]
   250  	s.assertShowOutput(c, "yaml")
   251  }
   252  
   253  func (s *ShowCommandSuite) TestShowBasicWithStatusIncompleteModelsJson(c *gc.C) {
   254  	s.fake.infos = []params.ModelInfoResult{
   255  		{Result: createBasicModelInfoWithStatus()},
   256  	}
   257  	s.expectedDisplay = "{\"basic-model\":" +
   258  		"{\"name\":\"owner/basic-model\"," +
   259  		"\"short-name\":\"basic-model\"," +
   260  		"\"model-uuid\":\"deadbeef-0bad-400d-8000-4b1d0d06f00d\"," +
   261  		"\"model-type\":\"iaas\"," +
   262  		"\"controller-uuid\":\"deadbeef-1bad-500d-9000-4b1d0d06f00d\"," +
   263  		"\"controller-name\":\"testing\"," +
   264  		"\"is-controller\":false," +
   265  		"\"owner\":\"owner\"," +
   266  		"\"cloud\":\"altostratus\"," +
   267  		"\"region\":\"mid-level\"," +
   268  		"\"life\":\"dead\"," +
   269  		"\"status\":{\"current\":\"busy\"}}}\n"
   270  
   271  	s.assertShowOutput(c, "json")
   272  }
   273  
   274  func (s *ShowCommandSuite) TestShowBasicWithMigrationIncompleteModelsYaml(c *gc.C) {
   275  	basicAndMigrationStatusInfo := createBasicModelInfo()
   276  	addMigrationStatusStatus(basicAndMigrationStatusInfo)
   277  	s.fake.infos = []params.ModelInfoResult{
   278  		{Result: basicAndMigrationStatusInfo},
   279  	}
   280  	s.expectedDisplay = `
   281  basic-model:
   282    name: owner/basic-model
   283    short-name: basic-model
   284    model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d
   285    model-type: iaas
   286    controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d
   287    controller-name: testing
   288    is-controller: false
   289    owner: owner
   290    cloud: altostratus
   291    region: mid-level
   292    life: dead
   293    status:
   294      migration: importing
   295      migration-start: just now
   296  `[1:]
   297  	s.assertShowOutput(c, "yaml")
   298  }
   299  
   300  func (s *ShowCommandSuite) TestShowBasicWithMigrationIncompleteModelsJson(c *gc.C) {
   301  	basicAndMigrationStatusInfo := createBasicModelInfo()
   302  	addMigrationStatusStatus(basicAndMigrationStatusInfo)
   303  	s.fake.infos = []params.ModelInfoResult{
   304  		{Result: basicAndMigrationStatusInfo},
   305  	}
   306  	s.expectedDisplay = "{\"basic-model\":" +
   307  		"{\"name\":\"owner/basic-model\"," +
   308  		"\"short-name\":\"basic-model\"," +
   309  		"\"model-uuid\":\"deadbeef-0bad-400d-8000-4b1d0d06f00d\"," +
   310  		"\"model-type\":\"iaas\"," +
   311  		"\"controller-uuid\":\"deadbeef-1bad-500d-9000-4b1d0d06f00d\"," +
   312  		"\"controller-name\":\"testing\"," +
   313  		"\"is-controller\":false," +
   314  		"\"owner\":\"owner\"," +
   315  		"\"cloud\":\"altostratus\"," +
   316  		"\"region\":\"mid-level\"," +
   317  		"\"life\":\"dead\"," +
   318  		"\"status\":{\"migration\":\"importing\",\"migration-start\":\"just now\"}}}\n"
   319  	s.assertShowOutput(c, "json")
   320  }
   321  
   322  func (s *ShowCommandSuite) TestShowBasicWithStatusAndMigrationIncompleteModelsYaml(c *gc.C) {
   323  	basicAndStatusAndMigrationInfo := createBasicModelInfoWithStatus()
   324  	addMigrationStatusStatus(basicAndStatusAndMigrationInfo)
   325  	s.fake.infos = []params.ModelInfoResult{
   326  		{Result: basicAndStatusAndMigrationInfo},
   327  	}
   328  	s.expectedDisplay = `
   329  basic-model:
   330    name: owner/basic-model
   331    short-name: basic-model
   332    model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d
   333    model-type: iaas
   334    controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d
   335    controller-name: testing
   336    is-controller: false
   337    owner: owner
   338    cloud: altostratus
   339    region: mid-level
   340    life: dead
   341    status:
   342      current: busy
   343      migration: importing
   344      migration-start: just now
   345  `[1:]
   346  	s.assertShowOutput(c, "yaml")
   347  }
   348  
   349  func (s *ShowCommandSuite) TestShowBasicWithStatusAndMigrationIncompleteModelsJson(c *gc.C) {
   350  	basicAndStatusAndMigrationInfo := createBasicModelInfoWithStatus()
   351  	addMigrationStatusStatus(basicAndStatusAndMigrationInfo)
   352  	s.fake.infos = []params.ModelInfoResult{
   353  		{Result: basicAndStatusAndMigrationInfo},
   354  	}
   355  	s.expectedDisplay = "{\"basic-model\":" +
   356  		"{\"name\":\"owner/basic-model\"," +
   357  		"\"short-name\":\"basic-model\"," +
   358  		"\"model-uuid\":\"deadbeef-0bad-400d-8000-4b1d0d06f00d\"," +
   359  		"\"model-type\":\"iaas\"," +
   360  		"\"controller-uuid\":\"deadbeef-1bad-500d-9000-4b1d0d06f00d\"," +
   361  		"\"controller-name\":\"testing\"," +
   362  		"\"is-controller\":false," +
   363  		"\"owner\":\"owner\"," +
   364  		"\"cloud\":\"altostratus\"," +
   365  		"\"region\":\"mid-level\"," +
   366  		"\"life\":\"dead\"," +
   367  		"\"status\":{\"current\":\"busy\",\"migration\":\"importing\",\"migration-start\":\"just now\"}}}\n"
   368  
   369  	s.assertShowOutput(c, "json")
   370  }
   371  
   372  func (s *ShowCommandSuite) TestShowBasicWithProviderIncompleteModelsYaml(c *gc.C) {
   373  	basicAndProviderTypeInfo := createBasicModelInfo()
   374  	basicAndProviderTypeInfo.ProviderType = "aws"
   375  	s.fake.infos = []params.ModelInfoResult{
   376  		{Result: basicAndProviderTypeInfo},
   377  	}
   378  	s.expectedDisplay = `
   379  basic-model:
   380    name: owner/basic-model
   381    short-name: basic-model
   382    model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d
   383    model-type: iaas
   384    controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d
   385    controller-name: testing
   386    is-controller: false
   387    owner: owner
   388    cloud: altostratus
   389    region: mid-level
   390    type: aws
   391    life: dead
   392  `[1:]
   393  	s.assertShowOutput(c, "yaml")
   394  }
   395  
   396  func (s *ShowCommandSuite) TestShowBasicWithProviderIncompleteModelsJson(c *gc.C) {
   397  	basicAndProviderTypeInfo := createBasicModelInfo()
   398  	basicAndProviderTypeInfo.ProviderType = "aws"
   399  	s.fake.infos = []params.ModelInfoResult{
   400  		{Result: basicAndProviderTypeInfo},
   401  	}
   402  	s.expectedDisplay = "{\"basic-model\":" +
   403  		"{\"name\":\"owner/basic-model\"," +
   404  		"\"short-name\":\"basic-model\"," +
   405  		"\"model-uuid\":\"deadbeef-0bad-400d-8000-4b1d0d06f00d\"," +
   406  		"\"model-type\":\"iaas\"," +
   407  		"\"controller-uuid\":\"deadbeef-1bad-500d-9000-4b1d0d06f00d\"," +
   408  		"\"controller-name\":\"testing\"," +
   409  		"\"is-controller\":false," +
   410  		"\"owner\":\"owner\"," +
   411  		"\"cloud\":\"altostratus\"," +
   412  		"\"region\":\"mid-level\"," +
   413  		"\"type\":\"aws\"," +
   414  		"\"life\":\"dead\"}}\n"
   415  	s.assertShowOutput(c, "json")
   416  }
   417  
   418  func (s *ShowCommandSuite) TestShowBasicWithUsersIncompleteModelsYaml(c *gc.C) {
   419  	basicAndUsersInfo := createBasicModelInfo()
   420  	basicAndUsersInfo.Users = []params.ModelUserInfo{
   421  		{"admin", "display name", nil, params.UserAccessPermission("admin")},
   422  	}
   423  	s.fake.infos = []params.ModelInfoResult{
   424  		{Result: basicAndUsersInfo},
   425  	}
   426  	s.expectedDisplay = `
   427  basic-model:
   428    name: owner/basic-model
   429    short-name: basic-model
   430    model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d
   431    model-type: iaas
   432    controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d
   433    controller-name: testing
   434    is-controller: false
   435    owner: owner
   436    cloud: altostratus
   437    region: mid-level
   438    life: dead
   439    users:
   440      admin:
   441        display-name: display name
   442        access: admin
   443        last-connection: never connected
   444  `[1:]
   445  	s.assertShowOutput(c, "yaml")
   446  }
   447  
   448  func (s *ShowCommandSuite) TestShowBasicWithUsersIncompleteModelsJson(c *gc.C) {
   449  	basicAndUsersInfo := createBasicModelInfo()
   450  	basicAndUsersInfo.Users = []params.ModelUserInfo{
   451  		{"admin", "display name", nil, params.UserAccessPermission("admin")},
   452  	}
   453  
   454  	s.fake.infos = []params.ModelInfoResult{
   455  		{Result: basicAndUsersInfo},
   456  	}
   457  	s.expectedDisplay = "{\"basic-model\":" +
   458  		"{\"name\":\"owner/basic-model\"," +
   459  		"\"short-name\":\"basic-model\"," +
   460  		"\"model-uuid\":\"deadbeef-0bad-400d-8000-4b1d0d06f00d\"," +
   461  		"\"model-type\":\"iaas\"," +
   462  		"\"controller-uuid\":\"deadbeef-1bad-500d-9000-4b1d0d06f00d\"," +
   463  		"\"controller-name\":\"testing\"," +
   464  		"\"is-controller\":false," +
   465  		"\"owner\":\"owner\"," +
   466  		"\"cloud\":\"altostratus\"," +
   467  		"\"region\":\"mid-level\"," +
   468  		"\"life\":\"dead\"," +
   469  		"\"users\":{\"admin\":{\"display-name\":\"display name\",\"access\":\"admin\",\"last-connection\":\"never connected\"}}}}\n"
   470  	s.assertShowOutput(c, "json")
   471  }
   472  
   473  func (s *ShowCommandSuite) TestShowBasicWithMachinesIncompleteModelsYaml(c *gc.C) {
   474  	basicAndMachinesInfo := createBasicModelInfo()
   475  	basicAndMachinesInfo.Machines = []params.ModelMachineInfo{
   476  		{Id: "2"}, {Id: "12"},
   477  	}
   478  	s.fake.infos = []params.ModelInfoResult{
   479  		{Result: basicAndMachinesInfo},
   480  	}
   481  	s.expectedDisplay = `
   482  basic-model:
   483    name: owner/basic-model
   484    short-name: basic-model
   485    model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d
   486    model-type: iaas
   487    controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d
   488    controller-name: testing
   489    is-controller: false
   490    owner: owner
   491    cloud: altostratus
   492    region: mid-level
   493    life: dead
   494    machines:
   495      "2":
   496        cores: 0
   497      "12":
   498        cores: 0
   499  `[1:]
   500  	s.assertShowOutput(c, "yaml")
   501  }
   502  
   503  func (s *ShowCommandSuite) TestShowBasicWithMachinesIncompleteModelsJson(c *gc.C) {
   504  	basicAndMachinesInfo := createBasicModelInfo()
   505  	basicAndMachinesInfo.Machines = []params.ModelMachineInfo{
   506  		{Id: "2"}, {Id: "12"},
   507  	}
   508  	s.fake.infos = []params.ModelInfoResult{
   509  		{Result: basicAndMachinesInfo},
   510  	}
   511  	s.expectedDisplay = "{\"basic-model\":" +
   512  		"{\"name\":\"owner/basic-model\"," +
   513  		"\"short-name\":\"basic-model\"," +
   514  		"\"model-uuid\":\"deadbeef-0bad-400d-8000-4b1d0d06f00d\"," +
   515  		"\"model-type\":\"iaas\"," +
   516  		"\"controller-uuid\":\"deadbeef-1bad-500d-9000-4b1d0d06f00d\"," +
   517  		"\"controller-name\":\"testing\"," +
   518  		"\"is-controller\":false," +
   519  		"\"owner\":\"owner\"," +
   520  		"\"cloud\":\"altostratus\"," +
   521  		"\"region\":\"mid-level\"," +
   522  		"\"life\":\"dead\"," +
   523  		"\"machines\":{\"12\":{\"cores\":0},\"2\":{\"cores\":0}}}}\n"
   524  	s.assertShowOutput(c, "json")
   525  }
   526  
   527  func (s *ShowCommandSuite) TestShowBasicWithSLAIncompleteModelsYaml(c *gc.C) {
   528  	basicAndSLAInfo := createBasicModelInfo()
   529  	basicAndSLAInfo.SLA = &params.ModelSLAInfo{
   530  		Owner: "owner",
   531  		Level: "level",
   532  	}
   533  	s.fake.infos = []params.ModelInfoResult{
   534  		{Result: basicAndSLAInfo},
   535  	}
   536  	s.expectedDisplay = `
   537  basic-model:
   538    name: owner/basic-model
   539    short-name: basic-model
   540    model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d
   541    model-type: iaas
   542    controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d
   543    controller-name: testing
   544    is-controller: false
   545    owner: owner
   546    cloud: altostratus
   547    region: mid-level
   548    life: dead
   549    sla: level
   550    sla-owner: owner
   551  `[1:]
   552  	s.assertShowOutput(c, "yaml")
   553  }
   554  
   555  func (s *ShowCommandSuite) TestShowBasicWithSLAIncompleteModelsJson(c *gc.C) {
   556  	basicAndSLAInfo := createBasicModelInfo()
   557  	basicAndSLAInfo.SLA = &params.ModelSLAInfo{
   558  		Owner: "owner",
   559  		Level: "level",
   560  	}
   561  	s.fake.infos = []params.ModelInfoResult{
   562  		{Result: basicAndSLAInfo},
   563  	}
   564  	s.expectedDisplay = "{\"basic-model\":" +
   565  		"{\"name\":\"owner/basic-model\"," +
   566  		"\"short-name\":\"basic-model\"," +
   567  		"\"model-uuid\":\"deadbeef-0bad-400d-8000-4b1d0d06f00d\"," +
   568  		"\"model-type\":\"iaas\"," +
   569  		"\"controller-uuid\":\"deadbeef-1bad-500d-9000-4b1d0d06f00d\"," +
   570  		"\"controller-name\":\"testing\"," +
   571  		"\"is-controller\":false," +
   572  		"\"owner\":\"owner\"," +
   573  		"\"cloud\":\"altostratus\"," +
   574  		"\"region\":\"mid-level\"," +
   575  		"\"life\":\"dead\"," +
   576  		"\"sla\":\"level\"," +
   577  		"\"sla-owner\":\"owner\"}}\n"
   578  	s.assertShowOutput(c, "json")
   579  }
   580  
   581  func (s *ShowCommandSuite) TestShowModelWithAgentVersionInJson(c *gc.C) {
   582  	s.expectedDisplay = "{\"basic-model\":" +
   583  		"{\"name\":\"owner/basic-model\"," +
   584  		"\"short-name\":\"basic-model\"," +
   585  		"\"model-uuid\":\"deadbeef-0bad-400d-8000-4b1d0d06f00d\"," +
   586  		"\"model-type\":\"iaas\"," +
   587  		"\"controller-uuid\":\"deadbeef-1bad-500d-9000-4b1d0d06f00d\"," +
   588  		"\"controller-name\":\"testing\"," +
   589  		"\"is-controller\":false," +
   590  		"\"owner\":\"owner\"," +
   591  		"\"cloud\":\"altostratus\"," +
   592  		"\"region\":\"mid-level\"," +
   593  		"\"life\":\"dead\"," +
   594  		"\"agent-version\":\"2.55.5\"}}\n"
   595  	s.assertShowModelWithAgent(c, "json")
   596  }
   597  
   598  func (s *ShowCommandSuite) TestShowModelWithAgentVersionInYaml(c *gc.C) {
   599  	s.expectedDisplay = `
   600  basic-model:
   601    name: owner/basic-model
   602    short-name: basic-model
   603    model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d
   604    model-type: iaas
   605    controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d
   606    controller-name: testing
   607    is-controller: false
   608    owner: owner
   609    cloud: altostratus
   610    region: mid-level
   611    life: dead
   612    agent-version: 2.55.5
   613  `[1:]
   614  	s.assertShowModelWithAgent(c, "yaml")
   615  }
   616  
   617  func (s *ShowCommandSuite) assertShowModelWithAgent(c *gc.C, format string) {
   618  	// Since most of the tests in this suite already test model infos without
   619  	// agent version, all we need to do here is to test one with it.
   620  	agentVersion, err := version.Parse("2.55.5")
   621  	c.Assert(err, jc.ErrorIsNil)
   622  	basicTestInfo := createBasicModelInfo()
   623  	basicTestInfo.AgentVersion = &agentVersion
   624  	s.fake.infos = []params.ModelInfoResult{
   625  		{Result: basicTestInfo},
   626  	}
   627  	s.assertShowOutput(c, format)
   628  }
   629  
   630  func (s *ShowCommandSuite) newShowCommand() cmd.Command {
   631  	return model.NewShowCommandForTest(&s.fake, noOpRefresh, s.store)
   632  }
   633  
   634  func (s *ShowCommandSuite) assertShowOutput(c *gc.C, format string) {
   635  	ctx, err := cmdtesting.RunCommand(c, s.newShowCommand(), "--format", format)
   636  	c.Assert(err, jc.ErrorIsNil)
   637  	c.Assert(cmdtesting.Stdout(ctx), gc.Equals, s.expectedDisplay)
   638  }
   639  
   640  func createBasicModelInfo() *params.ModelInfo {
   641  	return &params.ModelInfo{
   642  		Name:           "basic-model",
   643  		UUID:           testing.ModelTag.Id(),
   644  		ControllerUUID: testing.ControllerTag.Id(),
   645  		IsController:   false,
   646  		Type:           "iaas",
   647  		OwnerTag:       names.NewUserTag("owner").String(),
   648  		Life:           params.Dead,
   649  		CloudTag:       names.NewCloudTag("altostratus").String(),
   650  		CloudRegion:    "mid-level",
   651  	}
   652  }
   653  
   654  func createBasicModelInfoWithStatus() *params.ModelInfo {
   655  	basicAndStatusInfo := createBasicModelInfo()
   656  	basicAndStatusInfo.Status = params.EntityStatus{
   657  		Status: status.Busy,
   658  	}
   659  	return basicAndStatusInfo
   660  }
   661  
   662  func addMigrationStatusStatus(existingInfo *params.ModelInfo) {
   663  	now := time.Now()
   664  	existingInfo.Migration = &params.ModelMigrationStatus{
   665  		Status: "importing",
   666  		Start:  &now,
   667  	}
   668  }
   669  
   670  type showSLACommandSuite struct {
   671  	ShowCommandSuite
   672  }
   673  
   674  func (s *showSLACommandSuite) SetUpTest(c *gc.C) {
   675  	s.ShowCommandSuite.SetUpTest(c)
   676  
   677  	s.fake.info.SLA = &params.ModelSLAInfo{
   678  		Level: "next",
   679  		Owner: "user",
   680  	}
   681  	slaOutput := s.expectedOutput["mymodel"].(attrs)
   682  	slaOutput["sla"] = "next"
   683  	slaOutput["sla-owner"] = "user"
   684  }
   685  
   686  func noOpRefresh(_ jujuclient.ClientStore, _ string) error {
   687  	return nil
   688  }
   689  
   690  type attrs map[string]interface{}
   691  
   692  type fakeModelShowClient struct {
   693  	gitjujutesting.Stub
   694  	info  params.ModelInfo
   695  	err   *params.Error
   696  	infos []params.ModelInfoResult
   697  }
   698  
   699  func (f *fakeModelShowClient) Close() error {
   700  	f.MethodCall(f, "Close")
   701  	return f.NextErr()
   702  }
   703  
   704  func (f *fakeModelShowClient) ModelInfo(tags []names.ModelTag) ([]params.ModelInfoResult, error) {
   705  	f.MethodCall(f, "ModelInfo", tags)
   706  	if f.infos != nil {
   707  		return f.infos, nil
   708  	}
   709  	if len(tags) != 1 {
   710  		return nil, errors.Errorf("expected 1 tag, got %d", len(tags))
   711  	}
   712  	if tags[0] != testing.ModelTag {
   713  		return nil, errors.Errorf("expected %s, got %s", testing.ModelTag.Id(), tags[0].Id())
   714  	}
   715  	return []params.ModelInfoResult{{Result: &f.info, Error: f.err}}, f.NextErr()
   716  }