github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/cmd/juju/model/defaultscommand_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  package model_test
     4  
     5  import (
     6  	"strings"
     7  
     8  	"github.com/juju/cmd"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/apiserver/common"
    13  	"github.com/juju/juju/cmd/juju/model"
    14  	"github.com/juju/juju/environs/config"
    15  	"github.com/juju/juju/jujuclient"
    16  	"github.com/juju/juju/jujuclient/jujuclienttesting"
    17  	"github.com/juju/juju/testing"
    18  )
    19  
    20  type DefaultsCommandSuite struct {
    21  	fakeModelDefaultEnvSuite
    22  	store *jujuclienttesting.MemStore
    23  }
    24  
    25  var _ = gc.Suite(&DefaultsCommandSuite{})
    26  
    27  func (s *DefaultsCommandSuite) SetUpTest(c *gc.C) {
    28  	s.fakeModelDefaultEnvSuite.SetUpTest(c)
    29  	s.store = jujuclienttesting.NewMemStore()
    30  	s.store.CurrentControllerName = "controller"
    31  	s.store.Controllers["controller"] = jujuclient.ControllerDetails{}
    32  }
    33  
    34  func (s *DefaultsCommandSuite) run(c *gc.C, args ...string) (*cmd.Context, error) {
    35  	command := model.NewDefaultsCommandForTest(s.fakeAPIRoot, s.fakeDefaultsAPI, s.fakeCloudAPI, s.store)
    36  	return testing.RunCommand(c, command, args...)
    37  }
    38  
    39  func (s *DefaultsCommandSuite) TestDefaultsInit(c *gc.C) {
    40  	for i, test := range []struct {
    41  		description string
    42  		args        []string
    43  		errorMatch  string
    44  		nilErr      bool
    45  	}{
    46  		{
    47  			// Test set
    48  			description: "test set key specified more than once",
    49  			args:        []string{"special=extra", "special=other"},
    50  			errorMatch:  `key "special" specified more than once`,
    51  		}, {
    52  			description: "test cannot set agent-version",
    53  			args:        []string{"agent-version=2.0.0"},
    54  			errorMatch:  `"agent-version" must be set via "upgrade-juju"`,
    55  		}, {
    56  			description: "test set multiple keys",
    57  			args:        []string{"foo=bar", "baz=eggs"},
    58  			nilErr:      true,
    59  		}, {
    60  			// Test reset
    61  			description: "test empty args with reset fails",
    62  			args:        []string{"--reset"},
    63  			errorMatch:  "flag needs an argument: --reset",
    64  		}, {
    65  			description: "test reset with positional arg interpereted as invalid region",
    66  			args:        []string{"--reset", "something", "weird"},
    67  			errorMatch:  `invalid region specified: "weird"`,
    68  		},
    69  		{
    70  			description: "test reset with valid region and duplicate key set",
    71  			args:        []string{"--reset", "something", "dummy-region", "something=weird"},
    72  			errorMatch:  `key "something" cannot be both set and unset in the same command`,
    73  		},
    74  		{
    75  			description: "test reset with valid region and extra positional arg",
    76  			args:        []string{"--reset", "something", "dummy-region", "weird"},
    77  			errorMatch:  "cannot retrieve defaults for a region and reset attributes at the same time",
    78  		}, {
    79  			description: "test reset with valid region only",
    80  			args:        []string{"--reset", "foo", "dummy-region"},
    81  			nilErr:      true,
    82  		}, {
    83  			description: "test cannot reset agent version",
    84  			args:        []string{"--reset", "agent-version"},
    85  			errorMatch:  `"agent-version" cannot be reset`,
    86  		}, {
    87  			description: "test reset inits",
    88  			args:        []string{"--reset", "foo"},
    89  			nilErr:      true,
    90  		}, {
    91  			description: "test trailing reset fails",
    92  			args:        []string{"foo=bar", "--reset"},
    93  			errorMatch:  "flag needs an argument: --reset",
    94  		}, {
    95  			description: "test reset and get init",
    96  			args:        []string{"--reset", "agent-version,b", "foo=bar"},
    97  			errorMatch:  `"agent-version" cannot be reset`,
    98  		}, {
    99  			description: "test reset with key=val fails",
   100  			args:        []string{"--reset", "foo=bar"},
   101  			errorMatch:  `--reset accepts a comma delimited set of keys "a,b,c", received: "foo=bar"`,
   102  		}, {
   103  			description: "test reset multiple with key=val fails",
   104  			args:        []string{"--reset", "a,foo=bar,b"},
   105  			errorMatch:  `--reset accepts a comma delimited set of keys "a,b,c", received: "foo=bar"`,
   106  		}, {
   107  			description: "test reset with two positional args fails expecting a region",
   108  			args:        []string{"--reset", "a", "b", "c"},
   109  			errorMatch:  `invalid region specified: "b"`,
   110  		}, {
   111  			description: "test reset with two positional args fails expecting a region reordered",
   112  			args:        []string{"a", "--reset", "b", "c"},
   113  			errorMatch:  `invalid region specified: "a"`,
   114  		}, {
   115  			description: "test multiple reset inits",
   116  			args:        []string{"--reset", "a", "--reset", "b"},
   117  			nilErr:      true,
   118  		}, {
   119  			description: "test multiple reset and set inits",
   120  			args:        []string{"--reset", "a", "b=c", "--reset", "d"},
   121  			nilErr:      true,
   122  		}, {
   123  			description: "test multiple reset with valid region inits",
   124  			args:        []string{"dummy-region", "--reset", "a", "--reset", "b"},
   125  			nilErr:      true,
   126  		}, {
   127  			description: "test multiple reset with two positional args fails expecting a region reordered",
   128  			args:        []string{"a", "--reset", "b", "--reset", "c", "d"},
   129  			errorMatch:  `invalid region specified: "a"`,
   130  		}, {
   131  			description: "test reset multiple with key=val fails",
   132  			args:        []string{"--reset", "a", "--reset", "b,foo=bar,c"},
   133  			errorMatch:  `--reset accepts a comma delimited set of keys "a,b,c", received: "foo=bar"`,
   134  		}, {
   135  			// test get
   136  			description: "test no args inits",
   137  			args:        nil,
   138  			nilErr:      true,
   139  		}, {
   140  			description: "one key arg inits",
   141  			args:        []string{"one"},
   142  			nilErr:      true,
   143  		}, {
   144  			description: "test two key args fails",
   145  			args:        []string{"one", "two"},
   146  			errorMatch:  "can only retrieve defaults for one key or all",
   147  		}, {
   148  			description: "test multiple key args fails",
   149  			args:        []string{"one", "two", "three"},
   150  			errorMatch:  "can only retrieve defaults for one key or all",
   151  		}, {
   152  			description: "test valid region and one arg",
   153  			args:        []string{"dummy-region", "one"},
   154  			nilErr:      true,
   155  		}, {
   156  			description: "test valid region and no args",
   157  			args:        []string{"dummy-region"},
   158  			nilErr:      true,
   159  		}, {
   160  			// test cloud/region
   161  			description: "test invalid cloud fails",
   162  			args:        []string{"invalidCloud/invalidRegion", "one=two"},
   163  			errorMatch:  "Unknown cloud",
   164  		}, {
   165  			description: "test valid cloud with invalid region fails",
   166  			args:        []string{"dummy/invalidRegion", "one=two"},
   167  			errorMatch:  `invalid region specified: "dummy/invalidRegion"`,
   168  		}, {
   169  			description: "test no cloud with invalid region fails",
   170  			args:        []string{"invalidRegion", "one=two"},
   171  			errorMatch:  `invalid region specified: "invalidRegion"`,
   172  		}, {
   173  			description: "test valid region with set arg succeeds",
   174  			args:        []string{"dummy-region", "one=two"},
   175  			nilErr:      true,
   176  		}, {
   177  			description: "test valid region with set and reset succeeds",
   178  			args:        []string{"dummy-region", "one=two", "--reset", "three"},
   179  			nilErr:      true,
   180  		}, {
   181  			description: "test reset and set with extra key is interpereted as invalid region",
   182  			args:        []string{"--reset", "something,else", "invalidRegion", "is=weird"},
   183  			errorMatch:  `invalid region specified: "invalidRegion"`,
   184  		}, {
   185  			description: "test reset and set with valid region and extra key fails",
   186  			args:        []string{"--reset", "something,else", "dummy-region", "invalidkey", "is=weird"},
   187  			errorMatch:  "cannot set and retrieve default values simultaneously",
   188  		}, {
   189  			// test various invalid
   190  			description: "test too many positional args with reset",
   191  			args:        []string{"--reset", "a", "b", "c", "d"},
   192  			errorMatch:  "invalid input",
   193  		}, {
   194  			description: "test too many positional args with invalid region set",
   195  			args:        []string{"a", "a=b", "b", "c=d"},
   196  			errorMatch:  `invalid region specified: "a"`,
   197  		}, {
   198  			description: "test invalid positional args with set",
   199  			args:        []string{"a=b", "b", "c=d"},
   200  			errorMatch:  `expected "key=value", got "b"`,
   201  		}, {
   202  			description: "test invalid positional args with set and trailing key",
   203  			args:        []string{"a=b", "c=d", "e"},
   204  			errorMatch:  "cannot set and retrieve default values simultaneously",
   205  		}, {
   206  			description: "test invalid positional args with valid region, set, reset",
   207  			args:        []string{"dummy-region", "a=b", "--reset", "c,d,", "e=f", "g"},
   208  			errorMatch:  "cannot set and retrieve default values simultaneously",
   209  		}, {
   210  			// Test some random orderings
   211  			description: "test invalid positional args with set, reset with trailing comman and split key=values",
   212  			args:        []string{"dummy-region", "a=b", "--reset", "c,d,", "e=f"},
   213  			nilErr:      true,
   214  		}, {
   215  			description: "test leading comma with reset",
   216  			args:        []string{"--reset", ",a,b"},
   217  			nilErr:      true,
   218  		},
   219  	} {
   220  		c.Logf("test %d: %s", i, test.description)
   221  		cmd := model.NewDefaultsCommandForTest(s.fakeAPIRoot, s.fakeDefaultsAPI, s.fakeCloudAPI, s.store)
   222  		err := testing.InitCommand(cmd, test.args)
   223  		if test.nilErr {
   224  			c.Check(err, jc.ErrorIsNil)
   225  			continue
   226  		}
   227  		c.Check(err, gc.ErrorMatches, test.errorMatch)
   228  	}
   229  }
   230  
   231  func (s *DefaultsCommandSuite) TestResetUnknownValueLogs(c *gc.C) {
   232  	_, err := s.run(c, "--reset", "attr,weird")
   233  	c.Assert(err, jc.ErrorIsNil)
   234  	expected := `key "weird" is not defined in the known model configuration: possible misspelling`
   235  	c.Check(c.GetTestLog(), jc.Contains, expected)
   236  }
   237  
   238  func (s *DefaultsCommandSuite) TestResetAttr(c *gc.C) {
   239  	_, err := s.run(c, "--reset", "attr,unknown")
   240  	c.Assert(err, jc.ErrorIsNil)
   241  	c.Assert(s.fakeDefaultsAPI.defaults, jc.DeepEquals, config.ModelDefaultAttributes{
   242  		"attr2": {Controller: "bar", Default: nil, Regions: []config.RegionDefaultValue{{
   243  			Name:  "dummy-region",
   244  			Value: "dummy-value",
   245  		}, {
   246  			Name:  "another-region",
   247  			Value: "another-value",
   248  		}}},
   249  	})
   250  }
   251  
   252  func (s *DefaultsCommandSuite) TestResetBlockedError(c *gc.C) {
   253  	s.fakeDefaultsAPI.err = common.OperationBlockedError("TestBlockedError")
   254  	_, err := s.run(c, "--reset", "attr")
   255  	testing.AssertOperationWasBlocked(c, err, ".*TestBlockedError.*")
   256  }
   257  
   258  func (s *DefaultsCommandSuite) TestSetUnknownValueLogs(c *gc.C) {
   259  	_, err := s.run(c, "weird=foo")
   260  	c.Assert(err, jc.ErrorIsNil)
   261  	expected := `key "weird" is not defined in the known model configuration: possible misspelling`
   262  	c.Check(c.GetTestLog(), jc.Contains, expected)
   263  }
   264  
   265  func (s *DefaultsCommandSuite) TestSet(c *gc.C) {
   266  	_, err := s.run(c, "special=extra", "attr=baz")
   267  	c.Assert(err, jc.ErrorIsNil)
   268  	c.Assert(s.fakeDefaultsAPI.defaults, jc.DeepEquals, config.ModelDefaultAttributes{
   269  		"attr": {Controller: "baz", Default: nil, Regions: nil},
   270  		"attr2": {Controller: "bar", Default: nil, Regions: []config.RegionDefaultValue{{
   271  			Name:  "dummy-region",
   272  			Value: "dummy-value",
   273  		}, {
   274  			Name:  "another-region",
   275  			Value: "another-value",
   276  		}}},
   277  		"special": {Controller: "extra", Default: nil, Regions: nil},
   278  	})
   279  }
   280  
   281  func (s *DefaultsCommandSuite) TestSetConveysCloudRegion(c *gc.C) {
   282  	table := []struct {
   283  		input, cloud, region string
   284  	}{
   285  		{"", "", ""},
   286  		{"dummy-region", "dummy", "dummy-region"},
   287  		{"dummy/dummy-region", "dummy", "dummy-region"},
   288  		{"another-region", "dummy", "another-region"},
   289  	}
   290  	for i, test := range table {
   291  		c.Logf("test %d", i)
   292  		var err error
   293  		if test.input == "" {
   294  			_, err = s.run(c, "special=extra", "--reset", "attr")
   295  		} else {
   296  			_, err = s.run(c, test.input, "special=extra", "--reset", "attr")
   297  		}
   298  		c.Assert(err, jc.ErrorIsNil)
   299  		c.Assert(s.fakeDefaultsAPI.region, jc.DeepEquals, test.region)
   300  		c.Assert(s.fakeDefaultsAPI.cloud, jc.DeepEquals, test.cloud)
   301  	}
   302  }
   303  
   304  func (s *DefaultsCommandSuite) TestBlockedErrorOnSet(c *gc.C) {
   305  	s.fakeDefaultsAPI.err = common.OperationBlockedError("TestBlockedError")
   306  	_, err := s.run(c, "special=extra")
   307  	testing.AssertOperationWasBlocked(c, err, ".*TestBlockedError.*")
   308  }
   309  
   310  func (s *DefaultsCommandSuite) TestGetSingleValue(c *gc.C) {
   311  	context, err := s.run(c, "attr2")
   312  	c.Assert(err, jc.ErrorIsNil)
   313  
   314  	output := strings.TrimSpace(testing.Stdout(context))
   315  	expected := "" +
   316  		"Attribute         Default        Controller\n" +
   317  		"attr2             -              bar\n" +
   318  		"  dummy-region    dummy-value    -\n" +
   319  		"  another-region  another-value  -"
   320  	c.Assert(output, gc.Equals, expected)
   321  }
   322  
   323  func (s *DefaultsCommandSuite) TestGetSingleValueJSON(c *gc.C) {
   324  	context, err := s.run(c, "--format=json", "attr2")
   325  	c.Assert(err, jc.ErrorIsNil)
   326  
   327  	output := strings.TrimSpace(testing.Stdout(context))
   328  	c.Assert(output, gc.Equals,
   329  		`{"attr2":{"controller":"bar","regions":[{"name":"dummy-region","value":"dummy-value"},{"name":"another-region","value":"another-value"}]}}`)
   330  }
   331  
   332  func (s *DefaultsCommandSuite) TestGetAllValuesYAML(c *gc.C) {
   333  	context, err := s.run(c, "--format=yaml")
   334  	c.Assert(err, jc.ErrorIsNil)
   335  
   336  	output := strings.TrimSpace(testing.Stdout(context))
   337  	expected := "" +
   338  		"attr:\n" +
   339  		"  default: foo\n" +
   340  		"attr2:\n" +
   341  		"  controller: bar\n" +
   342  		"  regions:\n" +
   343  		"  - name: dummy-region\n" +
   344  		"    value: dummy-value\n" +
   345  		"  - name: another-region\n" +
   346  		"    value: another-value"
   347  	c.Assert(output, gc.Equals, expected)
   348  }
   349  
   350  func (s *DefaultsCommandSuite) TestGetAllValuesJSON(c *gc.C) {
   351  	context, err := s.run(c, "--format=json")
   352  	c.Assert(err, jc.ErrorIsNil)
   353  
   354  	output := strings.TrimSpace(testing.Stdout(context))
   355  	expected := `{"attr":{"default":"foo"},"attr2":{"controller":"bar","regions":[{"name":"dummy-region","value":"dummy-value"},{"name":"another-region","value":"another-value"}]}}`
   356  	c.Assert(output, gc.Equals, expected)
   357  }
   358  
   359  func (s *DefaultsCommandSuite) TestGetAllValuesTabular(c *gc.C) {
   360  	context, err := s.run(c)
   361  	c.Assert(err, jc.ErrorIsNil)
   362  
   363  	output := strings.TrimSpace(testing.Stdout(context))
   364  	expected := "" +
   365  		"Attribute         Default        Controller\n" +
   366  		"attr              foo            -\n" +
   367  		"attr2             -              bar\n" +
   368  		"  dummy-region    dummy-value    -\n" +
   369  		"  another-region  another-value  -"
   370  	c.Assert(output, gc.Equals, expected)
   371  }
   372  
   373  func (s *DefaultsCommandSuite) TestGetRegionValuesTabular(c *gc.C) {
   374  	context, err := s.run(c, "dummy-region")
   375  	c.Assert(err, jc.ErrorIsNil)
   376  
   377  	output := strings.TrimSpace(testing.Stdout(context))
   378  	expected := "" +
   379  		"Attribute       Default      Controller\n" +
   380  		"attr2           -            bar\n" +
   381  		"  dummy-region  dummy-value  -"
   382  	c.Assert(output, gc.Equals, expected)
   383  }