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 }