github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/provider/joyent/config_test.go (about) 1 // Copyright 2013 Joyent Inc. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package joyent_test 5 6 import ( 7 "fmt" 8 "io/ioutil" 9 "os" 10 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/environs" 17 "github.com/juju/juju/environs/config" 18 envtesting "github.com/juju/juju/environs/testing" 19 jp "github.com/juju/juju/provider/joyent" 20 coretesting "github.com/juju/juju/testing" 21 "github.com/juju/juju/utils/ssh" 22 ) 23 24 func newConfig(c *gc.C, attrs coretesting.Attrs) *config.Config { 25 attrs = coretesting.FakeConfig().Merge(attrs) 26 cfg, err := config.New(config.UseDefaults, attrs) 27 c.Assert(err, jc.ErrorIsNil) 28 return cfg 29 } 30 31 func validAttrs() coretesting.Attrs { 32 return coretesting.FakeConfig().Merge(coretesting.Attrs{ 33 "type": "joyent", 34 "sdc-user": "test", 35 "sdc-key-id": "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff", 36 "sdc-url": "test://test.api.joyentcloud.com", 37 "manta-user": "test", 38 "manta-key-id": "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff", 39 "manta-url": "test://test.manta.joyent.com", 40 "private-key-path": "~/.ssh/provider_id_rsa", 41 "algorithm": "rsa-sha256", 42 "control-dir": "juju-test", 43 }) 44 } 45 46 type ConfigSuite struct { 47 coretesting.FakeJujuHomeSuite 48 originalValues map[string]testing.Restorer 49 privateKeyData string 50 } 51 52 var _ = gc.Suite(&ConfigSuite{}) 53 54 func (s *ConfigSuite) SetUpSuite(c *gc.C) { 55 s.FakeJujuHomeSuite.SetUpSuite(c) 56 restoreSdcAccount := testing.PatchEnvironment(jp.SdcAccount, "tester") 57 s.AddSuiteCleanup(func(*gc.C) { restoreSdcAccount() }) 58 restoreSdcKeyId := testing.PatchEnvironment(jp.SdcKeyId, "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00") 59 s.AddSuiteCleanup(func(*gc.C) { restoreSdcKeyId() }) 60 restoreMantaUser := testing.PatchEnvironment(jp.MantaUser, "tester") 61 s.AddSuiteCleanup(func(*gc.C) { restoreMantaUser() }) 62 restoreMantaKeyId := testing.PatchEnvironment(jp.MantaKeyId, "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00") 63 s.AddSuiteCleanup(func(*gc.C) { restoreMantaKeyId() }) 64 s.privateKeyData = generatePrivateKey(c) 65 jp.RegisterMachinesEndpoint() 66 s.AddSuiteCleanup(func(*gc.C) { jp.UnregisterMachinesEndpoint() }) 67 } 68 69 func generatePrivateKey(c *gc.C) string { 70 oldBits := ssh.KeyBits 71 defer func() { 72 ssh.KeyBits = oldBits 73 }() 74 ssh.KeyBits = 32 75 private, _, err := ssh.GenerateKey("test-client") 76 c.Assert(err, jc.ErrorIsNil) 77 return private 78 } 79 80 func (s *ConfigSuite) SetUpTest(c *gc.C) { 81 s.FakeJujuHomeSuite.SetUpTest(c) 82 s.AddCleanup(CreateTestKey(c)) 83 for _, envVar := range jp.EnvironmentVariables { 84 s.PatchEnvironment(envVar, "") 85 } 86 } 87 88 var newConfigTests = []struct { 89 info string 90 insert coretesting.Attrs 91 remove []string 92 envVars map[string]string 93 expect coretesting.Attrs 94 err string 95 }{{ 96 info: "sdc-user is required", 97 remove: []string{"sdc-user"}, 98 err: ".* cannot get sdc-user value from environment variable .*", 99 }, { 100 info: "sdc-user cannot be empty", 101 insert: coretesting.Attrs{"sdc-user": ""}, 102 err: ".* cannot get sdc-user value from environment variable .*", 103 }, { 104 info: "can get sdc-user from env variable", 105 insert: coretesting.Attrs{"sdc-user": ""}, 106 expect: coretesting.Attrs{"sdc-user": "tester"}, 107 envVars: map[string]string{ 108 "SDC_ACCOUNT": "tester", 109 }, 110 }, { 111 info: "can get sdc-user from env variable, missing from config", 112 remove: []string{"sdc-user"}, 113 expect: coretesting.Attrs{"sdc-user": "tester"}, 114 envVars: map[string]string{ 115 "SDC_ACCOUNT": "tester", 116 }, 117 }, { 118 info: "sdc-key-id is required", 119 remove: []string{"sdc-key-id"}, 120 err: ".* cannot get sdc-key-id value from environment variable .*", 121 }, { 122 info: "sdc-key-id cannot be empty", 123 insert: coretesting.Attrs{"sdc-key-id": ""}, 124 err: ".* cannot get sdc-key-id value from environment variable .*", 125 }, { 126 info: "can get sdc-key-id from env variable", 127 insert: coretesting.Attrs{"sdc-key-id": ""}, 128 expect: coretesting.Attrs{"sdc-key-id": "key"}, 129 envVars: map[string]string{ 130 "SDC_KEY_ID": "key", 131 }, 132 }, { 133 info: "can get sdc-key-id from env variable, missing from config", 134 remove: []string{"sdc-key-id"}, 135 expect: coretesting.Attrs{"sdc-key-id": "key"}, 136 envVars: map[string]string{ 137 "SDC_KEY_ID": "key", 138 }, 139 }, { 140 info: "sdc-url is inserted if missing", 141 expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 142 }, { 143 info: "sdc-url cannot be empty", 144 insert: coretesting.Attrs{"sdc-url": ""}, 145 err: ".* cannot get sdc-url value from environment variable .*", 146 }, { 147 info: "sdc-url is untouched if present", 148 insert: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 149 expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 150 }, { 151 info: "manta-user is required", 152 remove: []string{"manta-user"}, 153 err: ".* cannot get manta-user value from environment variable .*", 154 }, { 155 info: "manta-user cannot be empty", 156 insert: coretesting.Attrs{"manta-user": ""}, 157 err: ".* cannot get manta-user value from environment variable .*", 158 }, { 159 info: "can get manta-user from env variable", 160 insert: coretesting.Attrs{"manta-user": ""}, 161 expect: coretesting.Attrs{"manta-user": "tester"}, 162 envVars: map[string]string{ 163 "MANTA_USER": "tester", 164 }, 165 }, { 166 info: "can get manta-user from env variable, missing from config", 167 remove: []string{"manta-user"}, 168 expect: coretesting.Attrs{"manta-user": "tester"}, 169 envVars: map[string]string{ 170 "MANTA_USER": "tester", 171 }, 172 }, { 173 info: "manta-key-id is required", 174 remove: []string{"manta-key-id"}, 175 err: ".* cannot get manta-key-id value from environment variable .*", 176 }, { 177 info: "manta-key-id cannot be empty", 178 insert: coretesting.Attrs{"manta-key-id": ""}, 179 err: ".* cannot get manta-key-id value from environment variable .*", 180 }, { 181 info: "can get manta-key-id from env variable", 182 insert: coretesting.Attrs{"manta-key-id": ""}, 183 expect: coretesting.Attrs{"manta-key-id": "key"}, 184 envVars: map[string]string{ 185 "MANTA_KEY_ID": "key", 186 }, 187 }, { 188 info: "can get manta-key-id from env variable, missing from config", 189 remove: []string{"manta-key-id"}, 190 expect: coretesting.Attrs{"manta-key-id": "key"}, 191 envVars: map[string]string{ 192 "MANTA_KEY_ID": "key", 193 }, 194 }, { 195 info: "manta-url is inserted if missing", 196 expect: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"}, 197 }, { 198 info: "manta-url cannot be empty", 199 insert: coretesting.Attrs{"manta-url": ""}, 200 err: ".* cannot get manta-url value from environment variable .*", 201 }, { 202 info: "manta-url is untouched if present", 203 insert: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"}, 204 expect: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"}, 205 }, { 206 info: "private-key-path is inserted if missing", 207 remove: []string{"private-key-path"}, 208 expect: coretesting.Attrs{"private-key-path": "~/.ssh/id_rsa"}, 209 }, { 210 info: "can get private-key-path from env variable", 211 insert: coretesting.Attrs{"private-key-path": ""}, 212 expect: coretesting.Attrs{"private-key-path": "some-file"}, 213 envVars: map[string]string{ 214 "MANTA_PRIVATE_KEY_FILE": "some-file", 215 }, 216 }, { 217 info: "can get private-key-path from env variable, missing from config", 218 remove: []string{"private-key-path"}, 219 expect: coretesting.Attrs{"private-key-path": "some-file"}, 220 envVars: map[string]string{ 221 "MANTA_PRIVATE_KEY_FILE": "some-file", 222 }, 223 }, { 224 info: "algorithm is inserted if missing", 225 expect: coretesting.Attrs{"algorithm": "rsa-sha256"}, 226 }, { 227 info: "algorithm cannot be empty", 228 insert: coretesting.Attrs{"algorithm": ""}, 229 err: ".* algorithm: must not be empty", 230 }, { 231 info: "unknown field is not touched", 232 insert: coretesting.Attrs{"unknown-field": 12345}, 233 expect: coretesting.Attrs{"unknown-field": 12345}, 234 }} 235 236 func (s *ConfigSuite) TestNewEnvironConfig(c *gc.C) { 237 for i, test := range newConfigTests { 238 c.Logf("test %d: %s", i, test.info) 239 for k, v := range test.envVars { 240 os.Setenv(k, v) 241 } 242 attrs := validAttrs().Merge(test.insert).Delete(test.remove...) 243 attrs["private-key"] = s.privateKeyData 244 testConfig := newConfig(c, attrs) 245 environ, err := environs.New(testConfig) 246 if test.err == "" { 247 c.Check(err, jc.ErrorIsNil) 248 if err != nil { 249 continue 250 } 251 attrs := environ.Config().AllAttrs() 252 for field, value := range test.expect { 253 c.Check(attrs[field], gc.Equals, value) 254 } 255 } else { 256 c.Check(environ, gc.IsNil) 257 c.Check(err, gc.ErrorMatches, test.err) 258 } 259 } 260 } 261 262 var changeConfigTests = []struct { 263 info string 264 insert coretesting.Attrs 265 remove []string 266 expect coretesting.Attrs 267 err string 268 }{{ 269 info: "no change, no error", 270 expect: validAttrs(), 271 }, { 272 info: "can change sdc-user", 273 insert: coretesting.Attrs{"sdc-user": "joyent_user"}, 274 expect: coretesting.Attrs{"sdc-user": "joyent_user"}, 275 }, { 276 info: "can change sdc-key-id", 277 insert: coretesting.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, 278 expect: coretesting.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, 279 }, { 280 info: "can change sdc-url", 281 insert: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 282 expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 283 }, { 284 info: "can change manta-user", 285 insert: coretesting.Attrs{"manta-user": "manta_user"}, 286 expect: coretesting.Attrs{"manta-user": "manta_user"}, 287 }, { 288 info: "can change manta-key-id", 289 insert: coretesting.Attrs{"manta-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, 290 expect: coretesting.Attrs{"manta-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, 291 }, { 292 info: "can change manta-url", 293 insert: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"}, 294 expect: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"}, 295 }, { 296 info: "can insert unknown field", 297 insert: coretesting.Attrs{"unknown": "ignoti"}, 298 expect: coretesting.Attrs{"unknown": "ignoti"}, 299 }} 300 301 func (s *ConfigSuite) TestValidateChange(c *gc.C) { 302 attrs := validAttrs() 303 attrs["private-key"] = s.privateKeyData 304 baseConfig := newConfig(c, attrs) 305 for i, test := range changeConfigTests { 306 c.Logf("test %d: %s", i, test.info) 307 attrs := validAttrs().Merge(test.insert).Delete(test.remove...) 308 attrs["private-key"] = s.privateKeyData 309 testConfig := newConfig(c, attrs) 310 validatedConfig, err := jp.Provider.Validate(testConfig, baseConfig) 311 if test.err == "" { 312 c.Check(err, jc.ErrorIsNil) 313 if err != nil { 314 continue 315 } 316 attrs := validatedConfig.AllAttrs() 317 for field, value := range test.expect { 318 c.Check(attrs[field], gc.Equals, value) 319 } 320 } else { 321 c.Check(validatedConfig, gc.IsNil) 322 c.Check(err, gc.ErrorMatches, "invalid config change: "+test.err) 323 } 324 } 325 } 326 327 func (s *ConfigSuite) TestSetConfig(c *gc.C) { 328 baseConfig := newConfig(c, validAttrs()) 329 for i, test := range changeConfigTests { 330 c.Logf("test %d: %s", i, test.info) 331 environ, err := environs.New(baseConfig) 332 c.Assert(err, jc.ErrorIsNil) 333 attrs := validAttrs().Merge(test.insert).Delete(test.remove...) 334 testConfig := newConfig(c, attrs) 335 err = environ.SetConfig(testConfig) 336 newAttrs := environ.Config().AllAttrs() 337 if test.err == "" { 338 c.Check(err, jc.ErrorIsNil) 339 for field, value := range test.expect { 340 c.Check(newAttrs[field], gc.Equals, value) 341 } 342 } else { 343 c.Check(err, gc.ErrorMatches, test.err) 344 for field, value := range baseConfig.UnknownAttrs() { 345 c.Check(newAttrs[field], gc.Equals, value) 346 } 347 } 348 } 349 } 350 351 func validPrepareAttrs() coretesting.Attrs { 352 return validAttrs().Delete("private-key") 353 } 354 355 var prepareConfigTests = []struct { 356 info string 357 insert coretesting.Attrs 358 remove []string 359 expect coretesting.Attrs 360 err string 361 }{{ 362 info: "All value provided, nothig to do", 363 expect: validPrepareAttrs(), 364 }, { 365 info: "private key is loaded from key file", 366 insert: coretesting.Attrs{"private-key-path": fmt.Sprintf("~/.ssh/%s", testKeyFileName)}, 367 expect: coretesting.Attrs{"private-key": testPrivateKey}, 368 }, { 369 info: "bad private-key-path errors, not panics", 370 insert: coretesting.Attrs{"private-key-path": "~/.ssh/no-such-file"}, 371 err: "invalid Joyent provider config: open .*: " + utils.NoSuchFileErrRegexp, 372 }} 373 374 func (s *ConfigSuite) TestPrepareForBootstrap(c *gc.C) { 375 ctx := envtesting.BootstrapContext(c) 376 for i, test := range prepareConfigTests { 377 c.Logf("test %d: %s", i, test.info) 378 attrs := validPrepareAttrs().Merge(test.insert).Delete(test.remove...) 379 testConfig := newConfig(c, attrs) 380 preparedConfig, err := jp.Provider.PrepareForBootstrap(ctx, testConfig) 381 if test.err == "" { 382 c.Check(err, jc.ErrorIsNil) 383 attrs := preparedConfig.Config().AllAttrs() 384 for field, value := range test.expect { 385 c.Check(attrs[field], gc.Equals, value) 386 } 387 } else { 388 c.Check(preparedConfig, gc.IsNil) 389 c.Check(err, gc.ErrorMatches, test.err) 390 } 391 } 392 } 393 394 func (s *ConfigSuite) TestPrepareWithDefaultKeyFile(c *gc.C) { 395 ctx := envtesting.BootstrapContext(c) 396 // By default "private-key-path isn't set until after validateConfig has been called. 397 attrs := validAttrs().Delete("private-key-path", "private-key") 398 keyFilePath, err := utils.NormalizePath(jp.DefaultPrivateKey) 399 c.Assert(err, jc.ErrorIsNil) 400 err = ioutil.WriteFile(keyFilePath, []byte(testPrivateKey), 400) 401 c.Assert(err, jc.ErrorIsNil) 402 defer os.Remove(keyFilePath) 403 testConfig := newConfig(c, attrs) 404 preparedConfig, err := jp.Provider.PrepareForBootstrap(ctx, testConfig) 405 c.Assert(err, jc.ErrorIsNil) 406 attrs = preparedConfig.Config().AllAttrs() 407 c.Check(attrs["private-key-path"], gc.Equals, jp.DefaultPrivateKey) 408 c.Check(attrs["private-key"], gc.Equals, testPrivateKey) 409 }