github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/cmd/juju/commands/switch_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package commands
     5  
     6  import (
     7  	"errors"
     8  	"os"
     9  
    10  	"github.com/juju/cmd/v3"
    11  	"github.com/juju/cmd/v3/cmdtesting"
    12  	"github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/cmd/juju/common"
    17  	"github.com/juju/juju/cmd/modelcmd"
    18  	_ "github.com/juju/juju/juju"
    19  	"github.com/juju/juju/jujuclient"
    20  	"github.com/juju/juju/jujuclient/jujuclienttesting"
    21  	coretesting "github.com/juju/juju/testing"
    22  )
    23  
    24  type SwitchSimpleSuite struct {
    25  	coretesting.FakeJujuXDGDataHomeSuite
    26  	testing.Stub
    27  	store     *jujuclient.MemStore
    28  	stubStore *jujuclienttesting.StubStore
    29  	onRefresh func()
    30  }
    31  
    32  var _ = gc.Suite(&SwitchSimpleSuite{})
    33  
    34  func (s *SwitchSimpleSuite) SetUpTest(c *gc.C) {
    35  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    36  	s.Stub.ResetCalls()
    37  	s.store = jujuclient.NewMemStore()
    38  	s.stubStore = jujuclienttesting.WrapClientStore(s.store)
    39  	s.onRefresh = nil
    40  }
    41  
    42  func (s *SwitchSimpleSuite) refreshModels(store jujuclient.ClientStore, controllerName string) error {
    43  	s.MethodCall(s, "RefreshModels", store, controllerName)
    44  	if s.onRefresh != nil {
    45  		s.onRefresh()
    46  	}
    47  	return s.NextErr()
    48  }
    49  
    50  func (s *SwitchSimpleSuite) run(c *gc.C, args ...string) (*cmd.Context, error) {
    51  	cmd := &switchCommand{
    52  		Store:         s.stubStore,
    53  		RefreshModels: s.refreshModels,
    54  	}
    55  	return cmdtesting.RunCommand(c, modelcmd.WrapBase(cmd), args...)
    56  }
    57  
    58  func (s *SwitchSimpleSuite) TestNoArgs(c *gc.C) {
    59  	_, err := s.run(c)
    60  	c.Assert(err, gc.ErrorMatches, common.MissingModelNameError("switch").Error())
    61  }
    62  
    63  func (s *SwitchSimpleSuite) TestNoArgsCurrentController(c *gc.C) {
    64  	s.addController(c, "a-controller")
    65  	s.store.CurrentControllerName = "a-controller"
    66  	ctx, err := s.run(c)
    67  	c.Assert(err, jc.ErrorIsNil)
    68  	c.Assert(cmdtesting.Stdout(ctx), gc.Equals, "a-controller\n")
    69  }
    70  
    71  func (s *SwitchSimpleSuite) TestUnknownControllerNameReturnsError(c *gc.C) {
    72  	s.addController(c, "a-controller")
    73  	s.store.CurrentControllerName = "a-controller"
    74  	_, err := s.run(c, "another-controller:modela")
    75  	c.Assert(err, gc.ErrorMatches, "controller another-controller not found")
    76  }
    77  
    78  func (s *SwitchSimpleSuite) TestNoArgsCurrentModel(c *gc.C) {
    79  	s.addController(c, "a-controller")
    80  	s.store.CurrentControllerName = "a-controller"
    81  	s.store.Models["a-controller"] = &jujuclient.ControllerModels{
    82  		Models:       map[string]jujuclient.ModelDetails{"admin/mymodel": {}},
    83  		CurrentModel: "admin/mymodel",
    84  	}
    85  	ctx, err := s.run(c)
    86  	c.Assert(err, jc.ErrorIsNil)
    87  	c.Assert(cmdtesting.Stdout(ctx), gc.Equals, "a-controller:admin/mymodel\n")
    88  }
    89  
    90  func (s *SwitchSimpleSuite) TestSwitchWritesCurrentController(c *gc.C) {
    91  	s.addController(c, "a-controller")
    92  	context, err := s.run(c, "a-controller")
    93  	c.Assert(err, jc.ErrorIsNil)
    94  	c.Assert(cmdtesting.Stderr(context), gc.Equals, " -> a-controller (controller)\n")
    95  	s.stubStore.CheckCalls(c, []testing.StubCall{
    96  		{"CurrentController", nil},
    97  		{"ControllerByName", []interface{}{"a-controller"}},
    98  		{"CurrentModel", []interface{}{"a-controller"}},
    99  		{"SetCurrentController", []interface{}{"a-controller"}},
   100  	})
   101  }
   102  
   103  func (s *SwitchSimpleSuite) TestSwitchWithCurrentController(c *gc.C) {
   104  	s.store.CurrentControllerName = "old"
   105  	s.addController(c, "old")
   106  	s.addController(c, "new")
   107  	context, err := s.run(c, "new")
   108  	c.Assert(err, jc.ErrorIsNil)
   109  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "old (controller) -> new (controller)\n")
   110  }
   111  
   112  func (s *SwitchSimpleSuite) TestSwitchLocalControllerWithCurrent(c *gc.C) {
   113  	s.store.CurrentControllerName = "old"
   114  	s.addController(c, "old")
   115  	s.addController(c, "new")
   116  	context, err := s.run(c, "new")
   117  	c.Assert(err, jc.ErrorIsNil)
   118  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "old (controller) -> new (controller)\n")
   119  }
   120  
   121  func (s *SwitchSimpleSuite) TestSwitchLocalControllerWithCurrentExplicit(c *gc.C) {
   122  	s.store.CurrentControllerName = "old"
   123  	s.addController(c, "old")
   124  	s.addController(c, "new")
   125  	context, err := s.run(c, "new:")
   126  	c.Assert(err, jc.ErrorIsNil)
   127  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "old (controller) -> new (controller)\n")
   128  }
   129  
   130  func (s *SwitchSimpleSuite) TestSwitchSameController(c *gc.C) {
   131  	s.store.CurrentControllerName = "same"
   132  	s.addController(c, "same")
   133  	context, err := s.run(c, "same")
   134  	c.Assert(err, jc.ErrorIsNil)
   135  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "same (controller) (no change)\n")
   136  	s.stubStore.CheckCalls(c, []testing.StubCall{
   137  		{"CurrentController", nil},
   138  		{"ControllerByName", []interface{}{"same"}},
   139  		{"CurrentModel", []interface{}{"same"}},
   140  		{"ControllerByName", []interface{}{"same"}},
   141  	})
   142  }
   143  
   144  func (s *SwitchSimpleSuite) TestSwitchControllerToModel(c *gc.C) {
   145  	s.store.CurrentControllerName = "ctrl"
   146  	s.addController(c, "ctrl")
   147  	s.store.Models["ctrl"] = &jujuclient.ControllerModels{
   148  		Models: map[string]jujuclient.ModelDetails{"admin/mymodel": {}},
   149  	}
   150  	context, err := s.run(c, "mymodel")
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "ctrl (controller) -> ctrl:admin/mymodel\n")
   153  	s.stubStore.CheckCalls(c, []testing.StubCall{
   154  		{"CurrentController", nil},
   155  		{"ControllerByName", []interface{}{"ctrl"}},
   156  		{"CurrentModel", []interface{}{"ctrl"}},
   157  		{"ControllerByName", []interface{}{"mymodel"}},
   158  		{"AccountDetails", []interface{}{"ctrl"}},
   159  		{"SetCurrentModel", []interface{}{"ctrl", "admin/mymodel"}},
   160  	})
   161  	c.Assert(s.store.Models["ctrl"].CurrentModel, gc.Equals, "admin/mymodel")
   162  }
   163  
   164  func (s *SwitchSimpleSuite) TestSwitchControllerToModelDifferentController(c *gc.C) {
   165  	s.store.CurrentControllerName = "old"
   166  	s.addController(c, "old")
   167  	s.addController(c, "new")
   168  	s.store.Models["new"] = &jujuclient.ControllerModels{
   169  		Models: map[string]jujuclient.ModelDetails{"admin/mymodel": {}},
   170  	}
   171  	context, err := s.run(c, "new:mymodel")
   172  	c.Assert(err, jc.ErrorIsNil)
   173  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "old (controller) -> new:admin/mymodel\n")
   174  	s.stubStore.CheckCalls(c, []testing.StubCall{
   175  		{"CurrentController", nil},
   176  		{"ControllerByName", []interface{}{"old"}},
   177  		{"CurrentModel", []interface{}{"old"}},
   178  		{"ControllerByName", []interface{}{"new:mymodel"}},
   179  		{"ControllerByName", []interface{}{"new"}},
   180  		{"AccountDetails", []interface{}{"new"}},
   181  		{"SetCurrentModel", []interface{}{"new", "admin/mymodel"}},
   182  		{"SetCurrentController", []interface{}{"new"}},
   183  	})
   184  	c.Assert(s.store.Models["new"].CurrentModel, gc.Equals, "admin/mymodel")
   185  }
   186  
   187  func (s *SwitchSimpleSuite) TestSwitchControllerSameNameAsModel(c *gc.C) {
   188  	s.store.CurrentControllerName = "old"
   189  	s.addController(c, "new")
   190  	s.addController(c, "old")
   191  	s.store.Models["new"] = &jujuclient.ControllerModels{
   192  		Models: map[string]jujuclient.ModelDetails{"admin/mymodel": {}, "admin/old": {}},
   193  	}
   194  	s.store.Models["old"] = &jujuclient.ControllerModels{
   195  		Models: map[string]jujuclient.ModelDetails{"admin/somemodel": {}},
   196  	}
   197  	_, err := s.run(c, "new:mymodel")
   198  	c.Assert(err, jc.ErrorIsNil)
   199  	context, err := s.run(c, "old")
   200  	c.Assert(err, jc.ErrorIsNil)
   201  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "new:admin/mymodel -> old (controller)\n")
   202  }
   203  
   204  func (s *SwitchSimpleSuite) TestSwitchControllerSameNameAsModelExplicitModel(c *gc.C) {
   205  	s.store.CurrentControllerName = "old"
   206  	s.addController(c, "new")
   207  	s.addController(c, "old")
   208  	s.store.Models["new"] = &jujuclient.ControllerModels{
   209  		Models: map[string]jujuclient.ModelDetails{"admin/mymodel": {}, "admin/old": {}},
   210  	}
   211  	s.store.Models["old"] = &jujuclient.ControllerModels{
   212  		Models: map[string]jujuclient.ModelDetails{"admin/somemodel": {}},
   213  	}
   214  	_, err := s.run(c, "new:mymodel")
   215  	c.Assert(err, jc.ErrorIsNil)
   216  	context, err := s.run(c, ":old")
   217  	c.Assert(err, jc.ErrorIsNil)
   218  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "new:admin/mymodel -> new:admin/old\n")
   219  }
   220  
   221  func (s *SwitchSimpleSuite) TestSwitchLocalControllerToModelDifferentController(c *gc.C) {
   222  	s.store.CurrentControllerName = "old"
   223  	s.addController(c, "old")
   224  	s.addController(c, "new")
   225  	s.store.Models["new"] = &jujuclient.ControllerModels{
   226  		Models: map[string]jujuclient.ModelDetails{"admin/mymodel": {}},
   227  	}
   228  	context, err := s.run(c, "new:mymodel")
   229  	c.Assert(err, jc.ErrorIsNil)
   230  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "old (controller) -> new:admin/mymodel\n")
   231  	s.stubStore.CheckCalls(c, []testing.StubCall{
   232  		{"CurrentController", nil},
   233  		{"ControllerByName", []interface{}{"old"}},
   234  		{"CurrentModel", []interface{}{"old"}},
   235  		{"ControllerByName", []interface{}{"new:mymodel"}},
   236  		{"ControllerByName", []interface{}{"new"}},
   237  		{"AccountDetails", []interface{}{"new"}},
   238  		{"SetCurrentModel", []interface{}{"new", "admin/mymodel"}},
   239  		{"SetCurrentController", []interface{}{"new"}},
   240  	})
   241  	c.Assert(s.store.Models["new"].CurrentModel, gc.Equals, "admin/mymodel")
   242  }
   243  
   244  func (s *SwitchSimpleSuite) TestSwitchControllerToDifferentControllerCurrentModel(c *gc.C) {
   245  	s.store.CurrentControllerName = "old"
   246  	s.addController(c, "old")
   247  	s.addController(c, "new")
   248  	s.store.Models["new"] = &jujuclient.ControllerModels{
   249  		Models:       map[string]jujuclient.ModelDetails{"admin/mymodel": {}},
   250  		CurrentModel: "admin/mymodel",
   251  	}
   252  	context, err := s.run(c, "new:mymodel")
   253  	c.Assert(err, jc.ErrorIsNil)
   254  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "old (controller) -> new:admin/mymodel\n")
   255  	s.stubStore.CheckCalls(c, []testing.StubCall{
   256  		{"CurrentController", nil},
   257  		{"ControllerByName", []interface{}{"old"}},
   258  		{"CurrentModel", []interface{}{"old"}},
   259  		{"ControllerByName", []interface{}{"new:mymodel"}},
   260  		{"ControllerByName", []interface{}{"new"}},
   261  		{"AccountDetails", []interface{}{"new"}},
   262  		{"SetCurrentModel", []interface{}{"new", "admin/mymodel"}},
   263  		{"SetCurrentController", []interface{}{"new"}},
   264  	})
   265  }
   266  
   267  func (s *SwitchSimpleSuite) TestSwitchToModelDifferentOwner(c *gc.C) {
   268  	s.store.CurrentControllerName = "same"
   269  	s.addController(c, "same")
   270  	s.store.Models["same"] = &jujuclient.ControllerModels{
   271  		Models: map[string]jujuclient.ModelDetails{
   272  			"admin/mymodel":  {},
   273  			"bianca/mymodel": {},
   274  		},
   275  		CurrentModel: "admin/mymodel",
   276  	}
   277  	context, err := s.run(c, "bianca/mymodel")
   278  	c.Assert(err, jc.ErrorIsNil)
   279  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "same:admin/mymodel -> same:bianca/mymodel\n")
   280  	c.Assert(s.store.Models["same"].CurrentModel, gc.Equals, "bianca/mymodel")
   281  }
   282  
   283  func (s *SwitchSimpleSuite) TestSwitchUnknownNoCurrentController(c *gc.C) {
   284  	_, err := s.run(c, "unknown")
   285  	c.Assert(err, gc.ErrorMatches, `"unknown" is not the name of a model or controller`)
   286  	s.stubStore.CheckCalls(c, []testing.StubCall{
   287  		{"CurrentController", nil},
   288  		{"ControllerByName", []interface{}{"unknown"}},
   289  	})
   290  }
   291  
   292  func (s *SwitchSimpleSuite) TestSwitchUnknownCurrentControllerRefreshModels(c *gc.C) {
   293  	s.store.CurrentControllerName = "ctrl"
   294  	s.addController(c, "ctrl")
   295  	s.onRefresh = func() {
   296  		s.store.Models["ctrl"] = &jujuclient.ControllerModels{
   297  			Models: map[string]jujuclient.ModelDetails{"admin/unknown": {}},
   298  		}
   299  	}
   300  	ctx, err := s.run(c, "unknown")
   301  	c.Assert(err, jc.ErrorIsNil)
   302  	c.Assert(cmdtesting.Stderr(ctx), gc.Equals, "ctrl (controller) -> ctrl:admin/unknown\n")
   303  	s.CheckCallNames(c, "RefreshModels")
   304  }
   305  
   306  func (s *SwitchSimpleSuite) TestSwitchUnknownCurrentControllerRefreshModelsStillUnknown(c *gc.C) {
   307  	s.store.CurrentControllerName = "ctrl"
   308  	s.addController(c, "ctrl")
   309  	_, err := s.run(c, "unknown")
   310  	c.Assert(err, gc.ErrorMatches, `"unknown" is not the name of a model or controller`)
   311  	s.CheckCallNames(c, "RefreshModels")
   312  }
   313  
   314  func (s *SwitchSimpleSuite) TestSwitchUnknownCurrentControllerRefreshModelsFails(c *gc.C) {
   315  	s.store.CurrentControllerName = "ctrl"
   316  	s.addController(c, "ctrl")
   317  	s.SetErrors(errors.New("not very refreshing"))
   318  	_, err := s.run(c, "unknown")
   319  	c.Assert(err, gc.ErrorMatches, "refreshing models cache: not very refreshing")
   320  	s.CheckCallNames(c, "RefreshModels")
   321  }
   322  
   323  func (s *SwitchSimpleSuite) TestSettingWhenModelEnvVarSet(c *gc.C) {
   324  	os.Setenv("JUJU_MODEL", "using-model")
   325  	_, err := s.run(c, "erewhemos-2")
   326  	c.Assert(err, gc.ErrorMatches, `cannot switch when JUJU_MODEL is overriding the model \(set to "using-model"\)`)
   327  }
   328  
   329  func (s *SwitchSimpleSuite) TestSettingWhenControllerEnvVarSet(c *gc.C) {
   330  	os.Setenv("JUJU_CONTROLLER", "using-controller")
   331  	_, err := s.run(c, "erewhemos-2")
   332  	c.Assert(err, gc.ErrorMatches, `cannot switch when JUJU_CONTROLLER is overriding the controller \(set to "using-controller"\)`)
   333  }
   334  
   335  func (s *SwitchSimpleSuite) TestTooManyParams(c *gc.C) {
   336  	_, err := s.run(c, "foo", "bar")
   337  	c.Assert(err, gc.ErrorMatches, `unrecognized args: ."bar".`)
   338  }
   339  
   340  func (s *SwitchSimpleSuite) addController(c *gc.C, name string) {
   341  	s.store.Controllers[name] = jujuclient.ControllerDetails{}
   342  	s.store.Accounts[name] = jujuclient.AccountDetails{
   343  		User: "admin",
   344  	}
   345  }
   346  
   347  func (s *SwitchSimpleSuite) TestSwitchCurrentModelInStore(c *gc.C) {
   348  	s.store.CurrentControllerName = "same"
   349  	s.addController(c, "same")
   350  	s.store.Models["same"] = &jujuclient.ControllerModels{
   351  		Models: map[string]jujuclient.ModelDetails{
   352  			"admin/mymodel": {},
   353  		},
   354  		CurrentModel: "admin/mymodel",
   355  	}
   356  	context, err := s.run(c, "mymodel")
   357  	c.Assert(err, jc.ErrorIsNil)
   358  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "same:admin/mymodel (no change)\n")
   359  	s.stubStore.CheckCalls(c, []testing.StubCall{
   360  		{"CurrentController", nil},
   361  		{"ControllerByName", []interface{}{"same"}},
   362  		{"CurrentModel", []interface{}{"same"}},
   363  		{"ControllerByName", []interface{}{"mymodel"}},
   364  		{"AccountDetails", []interface{}{"same"}},
   365  		{"SetCurrentModel", []interface{}{"same", "admin/mymodel"}},
   366  	})
   367  }
   368  
   369  func (s *SwitchSimpleSuite) TestSwitchCurrentModelNoLongerInStore(c *gc.C) {
   370  	s.store.CurrentControllerName = "same"
   371  	s.addController(c, "same")
   372  	s.store.Models["same"] = &jujuclient.ControllerModels{CurrentModel: "admin/mymodel"}
   373  	_, err := s.run(c, "mymodel")
   374  	c.Assert(err, gc.ErrorMatches, `"mymodel" is not the name of a model or controller`)
   375  }