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

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package controller_test
     5  
     6  import (
     7  	"regexp"
     8  
     9  	"github.com/juju/cmd"
    10  	"github.com/juju/cmd/cmdtesting"
    11  	"github.com/juju/errors"
    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  	"github.com/juju/juju/cmd/juju/controller"
    18  	"github.com/juju/juju/core/model"
    19  	"github.com/juju/juju/jujuclient"
    20  	"github.com/juju/juju/jujuclient/jujuclienttesting"
    21  	"github.com/juju/juju/permission"
    22  )
    23  
    24  type ShowControllerSuite struct {
    25  	baseControllerSuite
    26  	fakeController *fakeController
    27  	api            func(string) controller.ControllerAccessAPI
    28  	setAccess      func(permission.Access)
    29  }
    30  
    31  var _ = gc.Suite(&ShowControllerSuite{})
    32  
    33  func (s *ShowControllerSuite) SetUpTest(c *gc.C) {
    34  	s.baseControllerSuite.SetUpTest(c)
    35  	s.fakeController = &fakeController{
    36  		machines: map[string][]base.Machine{
    37  			"ghi": {
    38  				{Id: "0", InstanceId: "id-0", HasVote: false, WantsVote: true, Status: "active"},
    39  				{Id: "1", InstanceId: "id-1", HasVote: false, WantsVote: true, Status: "down"},
    40  				{Id: "2", InstanceId: "id-2", HasVote: true, WantsVote: true, Status: "active"},
    41  				{Id: "3", InstanceId: "id-3", HasVote: false, WantsVote: false, Status: "active"},
    42  			},
    43  		},
    44  		access:         permission.SuperuserAccess,
    45  		bestAPIVersion: 8,
    46  	}
    47  	s.api = func(controllerName string) controller.ControllerAccessAPI {
    48  		s.fakeController.controllerName = controllerName
    49  		return s.fakeController
    50  	}
    51  	s.setAccess = func(access permission.Access) {
    52  		s.fakeController.access = access
    53  	}
    54  }
    55  
    56  func (s *ShowControllerSuite) TestShowOneControllerOneInStore(c *gc.C) {
    57  	s.controllersYaml = `controllers:
    58    mallards:
    59      uuid: this-is-another-uuid
    60      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
    61      ca-cert: this-is-another-ca-cert
    62      cloud: mallards
    63      agent-version: 999.99.99
    64      mongo-version: 3.5.12
    65  `
    66  	s.createTestClientStore(c)
    67  
    68  	s.expectedOutput = `
    69  mallards:
    70    details:
    71      uuid: this-is-another-uuid
    72      controller-uuid: this-is-another-uuid
    73      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
    74      ca-cert: this-is-another-ca-cert
    75      cloud: mallards
    76      agent-version: 999.99.99
    77      mongo-version: 3.5.12
    78    models:
    79      controller:
    80        uuid: abc
    81        model-uuid: abc
    82        machine-count: 2
    83        core-count: 4
    84      my-model:
    85        uuid: def
    86        model-uuid: def
    87        machine-count: 2
    88        core-count: 4
    89    current-model: admin/my-model
    90    account:
    91      user: admin
    92      access: superuser
    93  `[1:]
    94  
    95  	s.assertShowController(c, "mallards")
    96  }
    97  
    98  func (s *ShowControllerSuite) TestShowControllerWithPasswords(c *gc.C) {
    99  	s.controllersYaml = `controllers:
   100    mallards:
   101      uuid: this-is-another-uuid
   102      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
   103      ca-cert: this-is-another-ca-cert
   104      cloud: mallards
   105      agent-version: 999.99.99
   106      mongo-version: 3.5.12
   107  `
   108  	s.createTestClientStore(c)
   109  
   110  	s.expectedOutput = `
   111  mallards:
   112    details:
   113      uuid: this-is-another-uuid
   114      controller-uuid: this-is-another-uuid
   115      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
   116      ca-cert: this-is-another-ca-cert
   117      cloud: mallards
   118      agent-version: 999.99.99
   119      mongo-version: 3.5.12
   120    models:
   121      controller:
   122        uuid: abc
   123        model-uuid: abc
   124        machine-count: 2
   125        core-count: 4
   126      my-model:
   127        uuid: def
   128        model-uuid: def
   129        machine-count: 2
   130        core-count: 4
   131    current-model: admin/my-model
   132    account:
   133      user: admin
   134      access: superuser
   135      password: hunter2
   136  `[1:]
   137  
   138  	s.assertShowController(c, "mallards", "--show-password")
   139  }
   140  
   141  func (s *ShowControllerSuite) TestShowControllerWithBootstrapConfig(c *gc.C) {
   142  	s.controllersYaml = `controllers:
   143    mallards:
   144      uuid: this-is-another-uuid
   145      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
   146      ca-cert: this-is-another-ca-cert
   147      cloud: mallards
   148      region: mallards1
   149      agent-version: 999.99.99
   150      mongo-version: 3.5.12
   151  `
   152  	store := s.createTestClientStore(c)
   153  	store.BootstrapConfig["mallards"] = jujuclient.BootstrapConfig{
   154  		Config: map[string]interface{}{
   155  			"name":  "controller",
   156  			"type":  "maas",
   157  			"extra": "value",
   158  		},
   159  		Credential:    "my-credential",
   160  		CloudType:     "maas",
   161  		Cloud:         "mallards",
   162  		CloudRegion:   "mallards1",
   163  		CloudEndpoint: "http://mallards.local/MAAS",
   164  	}
   165  
   166  	s.expectedOutput = `
   167  mallards:
   168    details:
   169      uuid: this-is-another-uuid
   170      controller-uuid: this-is-another-uuid
   171      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
   172      ca-cert: this-is-another-ca-cert
   173      cloud: mallards
   174      region: mallards1
   175      agent-version: 999.99.99
   176      mongo-version: 3.5.12
   177    models:
   178      controller:
   179        uuid: abc
   180        model-uuid: abc
   181        machine-count: 2
   182        core-count: 4
   183      my-model:
   184        uuid: def
   185        model-uuid: def
   186        machine-count: 2
   187        core-count: 4
   188    current-model: admin/my-model
   189    account:
   190      user: admin
   191      access: superuser
   192  `[1:]
   193  
   194  	s.assertShowController(c, "mallards")
   195  }
   196  
   197  func (s *ShowControllerSuite) TestShowOneControllerManyInStore(c *gc.C) {
   198  	s.createTestClientStore(c)
   199  
   200  	s.expectedOutput = `
   201  aws-test:
   202    details:
   203      uuid: this-is-the-aws-test-uuid
   204      controller-uuid: this-is-the-aws-test-uuid
   205      api-endpoints: [this-is-aws-test-of-many-api-endpoints]
   206      ca-cert: this-is-aws-test-ca-cert
   207      cloud: aws
   208      region: us-east-1
   209      agent-version: 999.99.99
   210      mongo-version: 3.5.12
   211    controller-machines:
   212      "0":
   213        instance-id: id-0
   214        ha-status: ha-pending
   215      "1":
   216        instance-id: id-1
   217        ha-status: down, lost connection
   218      "2":
   219        instance-id: id-2
   220        ha-status: ha-enabled
   221    models:
   222      controller:
   223        uuid: ghi
   224        model-uuid: ghi
   225        machine-count: 2
   226        core-count: 4
   227    current-model: admin/controller
   228    account:
   229      user: admin
   230      access: superuser
   231  `[1:]
   232  	s.assertShowController(c, "aws-test")
   233  }
   234  
   235  func (s *ShowControllerSuite) TestShowSomeControllerMoreInStore(c *gc.C) {
   236  	s.createTestClientStore(c)
   237  	s.expectedOutput = `
   238  aws-test:
   239    details:
   240      uuid: this-is-the-aws-test-uuid
   241      controller-uuid: this-is-the-aws-test-uuid
   242      api-endpoints: [this-is-aws-test-of-many-api-endpoints]
   243      ca-cert: this-is-aws-test-ca-cert
   244      cloud: aws
   245      region: us-east-1
   246      agent-version: 999.99.99
   247      mongo-version: 3.5.12
   248    controller-machines:
   249      "0":
   250        instance-id: id-0
   251        ha-status: ha-pending
   252      "1":
   253        instance-id: id-1
   254        ha-status: down, lost connection
   255      "2":
   256        instance-id: id-2
   257        ha-status: ha-enabled
   258    models:
   259      controller:
   260        uuid: ghi
   261        model-uuid: ghi
   262        machine-count: 2
   263        core-count: 4
   264    current-model: admin/controller
   265    account:
   266      user: admin
   267      access: superuser
   268  mark-test-prodstack:
   269    details:
   270      uuid: this-is-a-uuid
   271      controller-uuid: this-is-a-uuid
   272      api-endpoints: [this-is-one-of-many-api-endpoints]
   273      ca-cert: this-is-a-ca-cert
   274      cloud: prodstack
   275      agent-version: 999.99.99
   276      mongo-version: 3.5.12
   277    account:
   278      user: admin
   279      access: superuser
   280  `[1:]
   281  
   282  	s.assertShowController(c, "aws-test", "mark-test-prodstack")
   283  }
   284  
   285  func (s *ShowControllerSuite) TestShowOneControllerWithAPIVersionTooLow(c *gc.C) {
   286  	s.fakeController = &fakeController{
   287  		machines:       map[string][]base.Machine{},
   288  		access:         permission.SuperuserAccess,
   289  		bestAPIVersion: 1,
   290  	}
   291  
   292  	s.controllersYaml = `controllers:
   293    mallards:
   294      uuid: this-is-another-uuid
   295      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
   296      ca-cert: this-is-another-ca-cert
   297      cloud: mallards
   298      agent-version: 999.99.99
   299  `
   300  	s.createTestClientStore(c)
   301  
   302  	s.expectedOutput = `
   303  mallards:
   304    details:
   305      uuid: this-is-another-uuid
   306      controller-uuid: this-is-another-uuid
   307      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
   308      ca-cert: this-is-another-ca-cert
   309      cloud: mallards
   310      agent-version: 999.99.99
   311    models:
   312      controller:
   313        uuid: abc
   314        model-uuid: abc
   315        machine-count: 2
   316        core-count: 4
   317      my-model:
   318        uuid: def
   319        model-uuid: def
   320        machine-count: 2
   321        core-count: 4
   322    current-model: admin/my-model
   323    account:
   324      user: admin
   325      access: superuser
   326  `[1:]
   327  
   328  	s.assertShowController(c, "mallards")
   329  }
   330  
   331  func (s *ShowControllerSuite) TestShowControllerJsonOne(c *gc.C) {
   332  	s.createTestClientStore(c)
   333  
   334  	s.expectedOutput = `
   335  {"aws-test":{"details":{"uuid":"this-is-the-aws-test-uuid","api-endpoints":["this-is-aws-test-of-many-api-endpoints"],"ca-cert":"this-is-aws-test-ca-cert","cloud":"aws","region":"us-east-1","agent-version":"999.99.99","mongo-version":"3.5.12"},"controller-machines":{"0":{"instance-id":"id-0","ha-status":"ha-pending"},"1":{"instance-id":"id-1","ha-status":"down, lost connection"},"2":{"instance-id":"id-2","ha-status":"ha-enabled"}},"models":{"controller":{"uuid":"ghi","machine-count":2,"core-count":4}},"current-model":"admin/controller","account":{"user":"admin","access":"superuser"}}}
   336  `[1:]
   337  
   338  	s.assertShowController(c, "--format", "json", "aws-test")
   339  }
   340  
   341  func (s *ShowControllerSuite) TestShowControllerJsonMany(c *gc.C) {
   342  	s.createTestClientStore(c)
   343  	s.expectedOutput = `
   344  {"aws-test":{"details":{"uuid":"this-is-the-aws-test-uuid","api-endpoints":["this-is-aws-test-of-many-api-endpoints"],"ca-cert":"this-is-aws-test-ca-cert","cloud":"aws","region":"us-east-1","agent-version":"999.99.99","mongo-version":"3.5.12"},"controller-machines":{"0":{"instance-id":"id-0","ha-status":"ha-pending"},"1":{"instance-id":"id-1","ha-status":"down, lost connection"},"2":{"instance-id":"id-2","ha-status":"ha-enabled"}},"models":{"controller":{"uuid":"ghi","machine-count":2,"core-count":4}},"current-model":"admin/controller","account":{"user":"admin","access":"superuser"}},"mark-test-prodstack":{"details":{"uuid":"this-is-a-uuid","api-endpoints":["this-is-one-of-many-api-endpoints"],"ca-cert":"this-is-a-ca-cert","cloud":"prodstack","agent-version":"999.99.99","mongo-version":"3.5.12"},"account":{"user":"admin","access":"superuser"}}}
   345  `[1:]
   346  	s.assertShowController(c, "--format", "json", "aws-test", "mark-test-prodstack")
   347  }
   348  
   349  func (s *ShowControllerSuite) TestShowControllerReadFromStoreErr(c *gc.C) {
   350  	s.createTestClientStore(c)
   351  
   352  	msg := "fail getting controller"
   353  	errStore := jujuclienttesting.NewStubStore()
   354  	errStore.SetErrors(errors.New(msg))
   355  	s.store = errStore
   356  	s.expectedErr = msg
   357  
   358  	s.assertShowControllerFailed(c, "test1")
   359  	errStore.CheckCallNames(c, "ControllerByName")
   360  }
   361  
   362  func (s *ShowControllerSuite) TestShowControllerNoArgs(c *gc.C) {
   363  	store := s.createTestClientStore(c)
   364  	store.CurrentControllerName = "aws-test"
   365  
   366  	s.expectedOutput = `
   367  {"aws-test":{"details":{"uuid":"this-is-the-aws-test-uuid","api-endpoints":["this-is-aws-test-of-many-api-endpoints"],"ca-cert":"this-is-aws-test-ca-cert","cloud":"aws","region":"us-east-1","agent-version":"999.99.99","mongo-version":"3.5.12"},"controller-machines":{"0":{"instance-id":"id-0","ha-status":"ha-pending"},"1":{"instance-id":"id-1","ha-status":"down, lost connection"},"2":{"instance-id":"id-2","ha-status":"ha-enabled"}},"models":{"controller":{"uuid":"ghi","machine-count":2,"core-count":4}},"current-model":"admin/controller","account":{"user":"admin","access":"superuser"}}}
   368  `[1:]
   369  	s.assertShowController(c, "--format", "json")
   370  }
   371  
   372  func (s *ShowControllerSuite) TestShowControllerNoArgsNoCurrent(c *gc.C) {
   373  	store := s.createTestClientStore(c)
   374  	store.CurrentControllerName = ""
   375  	s.expectedErr = regexp.QuoteMeta(`there is no active controller`)
   376  	s.assertShowControllerFailed(c)
   377  }
   378  
   379  func (s *ShowControllerSuite) TestShowControllerNotFound(c *gc.C) {
   380  	s.createTestClientStore(c)
   381  
   382  	s.expectedErr = `controller whoops not found`
   383  	s.assertShowControllerFailed(c, "whoops")
   384  }
   385  
   386  func (s *ShowControllerSuite) TestShowControllerUnrecognizedFlag(c *gc.C) {
   387  	s.expectedErr = `option provided but not defined: -m`
   388  	s.assertShowControllerFailed(c, "-m", "my.world")
   389  }
   390  
   391  func (s *ShowControllerSuite) TestShowControllerUnrecognizedOptionFlag(c *gc.C) {
   392  	s.expectedErr = `option provided but not defined: --model`
   393  	s.assertShowControllerFailed(c, "--model", "still.my.world")
   394  }
   395  
   396  func (s *ShowControllerSuite) TestShowControllerRefreshesStore(c *gc.C) {
   397  	store := s.createTestClientStore(c)
   398  	_, err := s.runShowController(c, "aws-test")
   399  	c.Assert(err, jc.ErrorIsNil)
   400  	c.Check(store.Controllers["aws-test"].ActiveControllerMachineCount, gc.Equals, 1)
   401  	s.fakeController.machines["ghi"][0].HasVote = true
   402  	_, err = s.runShowController(c, "aws-test")
   403  	c.Assert(err, jc.ErrorIsNil)
   404  	c.Check(store.Controllers["aws-test"].ControllerMachineCount, gc.Equals, 3)
   405  	c.Check(store.Controllers["aws-test"].ActiveControllerMachineCount, gc.Equals, 2)
   406  }
   407  
   408  func (s *ShowControllerSuite) TestShowControllerRefreshesStoreModels(c *gc.C) {
   409  	store := s.createTestClientStore(c)
   410  	c.Assert(store.Models["mallards"], gc.DeepEquals, &jujuclient.ControllerModels{
   411  		CurrentModel: "admin/my-model",
   412  		Models: map[string]jujuclient.ModelDetails{
   413  			"model0":   {ModelUUID: "abc", ModelType: model.IAAS},
   414  			"my-model": {ModelUUID: "def", ModelType: model.IAAS},
   415  		},
   416  	})
   417  	_, err := s.runShowController(c, "mallards")
   418  	c.Assert(err, jc.ErrorIsNil)
   419  	c.Assert(store.Models["mallards"], gc.DeepEquals, &jujuclient.ControllerModels{
   420  		CurrentModel: "admin/my-model",
   421  		Models: map[string]jujuclient.ModelDetails{
   422  			"admin/controller": {ModelUUID: "abc", ModelType: model.IAAS},
   423  			"admin/my-model":   {ModelUUID: "def", ModelType: model.IAAS},
   424  		},
   425  	})
   426  }
   427  
   428  func (s *ShowControllerSuite) TestShowControllerForUserWithLoginAccess(c *gc.C) {
   429  	s.controllersYaml = `controllers:
   430    mallards:
   431      uuid: this-is-another-uuid
   432      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
   433      ca-cert: this-is-another-ca-cert
   434      cloud: mallards
   435      agent-version: 999.99.99
   436  `
   437  	s.expectedOutput = `
   438  mallards:
   439    details:
   440      uuid: this-is-another-uuid
   441      controller-uuid: this-is-another-uuid
   442      api-endpoints: [this-is-another-of-many-api-endpoints, this-is-one-more-of-many-api-endpoints]
   443      ca-cert: this-is-another-ca-cert
   444      cloud: mallards
   445      agent-version: 999.99.99
   446    current-model: admin/my-model
   447    account:
   448      user: admin
   449      access: login
   450  `[1:]
   451  
   452  	store := s.createTestClientStore(c)
   453  	c.Assert(store.Models["mallards"].Models, gc.HasLen, 2)
   454  	s.setAccess(permission.LoginAccess)
   455  	s.assertShowController(c, "mallards")
   456  }
   457  
   458  func (s *ShowControllerSuite) TestShowControllerWithIdentityProvider(c *gc.C) {
   459  	_ = s.createTestClientStore(c)
   460  	ctx, err := s.runShowController(c, "aws-test")
   461  	c.Assert(err, jc.ErrorIsNil)
   462  	c.Assert(cmdtesting.Stdout(ctx), gc.Not(jc.Contains), "identity-url")
   463  
   464  	expURL := "https://api.jujucharms.com/identity"
   465  	s.fakeController.identityURL = expURL
   466  	ctx, err = s.runShowController(c, "aws-test")
   467  	c.Assert(err, jc.ErrorIsNil)
   468  	c.Assert(cmdtesting.Stdout(ctx), jc.Contains, "identity-url: "+expURL)
   469  }
   470  
   471  func (s *ShowControllerSuite) runShowController(c *gc.C, args ...string) (*cmd.Context, error) {
   472  	return cmdtesting.RunCommand(c, controller.NewShowControllerCommandForTest(s.store, s.api), args...)
   473  }
   474  
   475  func (s *ShowControllerSuite) assertShowControllerFailed(c *gc.C, args ...string) {
   476  	_, err := s.runShowController(c, args...)
   477  	c.Assert(err, gc.ErrorMatches, s.expectedErr)
   478  }
   479  
   480  func (s *ShowControllerSuite) assertShowController(c *gc.C, args ...string) {
   481  	context, err := s.runShowController(c, args...)
   482  	c.Assert(err, jc.ErrorIsNil)
   483  	c.Assert(cmdtesting.Stdout(context), gc.Equals, s.expectedOutput)
   484  }
   485  
   486  type fakeController struct {
   487  	controllerName string
   488  	machines       map[string][]base.Machine
   489  	access         permission.Access
   490  	bestAPIVersion int
   491  	identityURL    string
   492  }
   493  
   494  func (c *fakeController) GetControllerAccess(user string) (permission.Access, error) {
   495  	return c.access, nil
   496  }
   497  
   498  func (*fakeController) ModelConfig() (map[string]interface{}, error) {
   499  	return map[string]interface{}{"agent-version": "999.99.99"}, nil
   500  }
   501  
   502  func (c *fakeController) ModelStatus(models ...names.ModelTag) (result []base.ModelStatus, _ error) {
   503  	for _, mtag := range models {
   504  		result = append(result, base.ModelStatus{
   505  			UUID:              mtag.Id(),
   506  			TotalMachineCount: 2,
   507  			CoreCount:         4,
   508  			Machines:          c.machines[mtag.Id()],
   509  		})
   510  	}
   511  	return result, nil
   512  }
   513  
   514  func (c *fakeController) MongoVersion() (string, error) {
   515  	if c.bestAPIVersion < 3 {
   516  		return "", errors.NotSupportedf("requires APIVersion >= 3")
   517  	}
   518  	return "3.5.12", nil
   519  }
   520  
   521  func (c *fakeController) AllModels() (result []base.UserModel, _ error) {
   522  	models := map[string][]base.UserModel{
   523  		"aws-test": {
   524  			{Name: "controller", UUID: "ghi", Owner: "admin", Type: model.IAAS},
   525  		},
   526  		"mallards": {
   527  			{Name: "controller", UUID: "abc", Owner: "admin", Type: model.IAAS},
   528  			{Name: "my-model", UUID: "def", Owner: "admin", Type: model.IAAS},
   529  		},
   530  	}
   531  	all, exists := models[c.controllerName]
   532  	if !exists {
   533  		return result, nil
   534  	}
   535  	return all, nil
   536  }
   537  
   538  func (c *fakeController) IdentityProviderURL() (string, error) {
   539  	return c.identityURL, nil
   540  }
   541  
   542  func (*fakeController) Close() error {
   543  	return nil
   544  }