github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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 "os" 9 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 "github.com/juju/utils/ssh" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/cloud" 16 "github.com/juju/juju/environs" 17 "github.com/juju/juju/environs/config" 18 jp "github.com/juju/juju/provider/joyent" 19 coretesting "github.com/juju/juju/testing" 20 ) 21 22 func newConfig(c *gc.C, attrs coretesting.Attrs) *config.Config { 23 attrs = coretesting.FakeConfig().Merge(attrs) 24 cfg, err := config.New(config.UseDefaults, attrs) 25 c.Assert(err, jc.ErrorIsNil) 26 return cfg 27 } 28 29 func validAttrs() coretesting.Attrs { 30 return coretesting.FakeConfig().Merge(coretesting.Attrs{ 31 "type": "joyent", 32 "sdc-user": "test", 33 "sdc-key-id": "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff", 34 "sdc-url": "test://test.api.joyentcloud.com", 35 "private-key": testPrivateKey, 36 "algorithm": "rsa-sha256", 37 }) 38 } 39 40 type ConfigSuite struct { 41 coretesting.FakeJujuXDGDataHomeSuite 42 originalValues map[string]testing.Restorer 43 privateKeyData string 44 } 45 46 var _ = gc.Suite(&ConfigSuite{}) 47 48 func (s *ConfigSuite) SetUpSuite(c *gc.C) { 49 s.FakeJujuXDGDataHomeSuite.SetUpSuite(c) 50 restoreSdcAccount := testing.PatchEnvironment(jp.SdcAccount, "tester") 51 s.AddCleanup(func(*gc.C) { restoreSdcAccount() }) 52 restoreSdcKeyId := testing.PatchEnvironment(jp.SdcKeyId, "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00") 53 s.AddCleanup(func(*gc.C) { restoreSdcKeyId() }) 54 s.privateKeyData = generatePrivateKey(c) 55 jp.RegisterMachinesEndpoint() 56 s.AddCleanup(func(*gc.C) { jp.UnregisterMachinesEndpoint() }) 57 } 58 59 func generatePrivateKey(c *gc.C) string { 60 oldBits := ssh.KeyBits 61 defer func() { 62 ssh.KeyBits = oldBits 63 }() 64 ssh.KeyBits = 32 65 private, _, err := ssh.GenerateKey("test-client") 66 c.Assert(err, jc.ErrorIsNil) 67 return private 68 } 69 70 func (s *ConfigSuite) SetUpTest(c *gc.C) { 71 s.FakeJujuXDGDataHomeSuite.SetUpTest(c) 72 for _, envVar := range jp.EnvironmentVariables { 73 s.PatchEnvironment(envVar, "") 74 } 75 } 76 77 type configtest struct { 78 info string 79 insert coretesting.Attrs 80 remove []string 81 envVars map[string]string 82 expect coretesting.Attrs 83 err string 84 } 85 86 var newConfigTests = []configtest{{ 87 info: "sdc-user is required", 88 remove: []string{"sdc-user"}, 89 err: ".* cannot get sdc-user value from environment variable .*", 90 }, { 91 info: "sdc-user cannot be empty", 92 insert: coretesting.Attrs{"sdc-user": ""}, 93 err: ".* cannot get sdc-user value from environment variable .*", 94 }, { 95 info: "can get sdc-user from environment variable", 96 insert: coretesting.Attrs{"sdc-user": ""}, 97 expect: coretesting.Attrs{"sdc-user": "tester"}, 98 envVars: map[string]string{ 99 "SDC_ACCOUNT": "tester", 100 }, 101 }, { 102 info: "can get sdc-user from environment variable, missing from config", 103 remove: []string{"sdc-user"}, 104 expect: coretesting.Attrs{"sdc-user": "tester"}, 105 envVars: map[string]string{ 106 "SDC_ACCOUNT": "tester", 107 }, 108 }, { 109 info: "sdc-key-id is required", 110 remove: []string{"sdc-key-id"}, 111 err: ".* cannot get sdc-key-id value from environment variable .*", 112 }, { 113 info: "sdc-key-id cannot be empty", 114 insert: coretesting.Attrs{"sdc-key-id": ""}, 115 err: ".* cannot get sdc-key-id value from environment variable .*", 116 }, { 117 info: "can get sdc-key-id from environment variable", 118 insert: coretesting.Attrs{"sdc-key-id": ""}, 119 expect: coretesting.Attrs{"sdc-key-id": "key"}, 120 envVars: map[string]string{ 121 "SDC_KEY_ID": "key", 122 }, 123 }, { 124 info: "can get sdc-key-id from environment variable, missing from config", 125 remove: []string{"sdc-key-id"}, 126 expect: coretesting.Attrs{"sdc-key-id": "key"}, 127 envVars: map[string]string{ 128 "SDC_KEY_ID": "key", 129 }, 130 }, { 131 info: "sdc-url is inserted if missing", 132 expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 133 }, { 134 info: "sdc-url cannot be empty", 135 insert: coretesting.Attrs{"sdc-url": ""}, 136 err: ".* cannot get sdc-url value from environment variable .*", 137 }, { 138 info: "sdc-url is untouched if present", 139 insert: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 140 expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 141 }, { 142 info: "algorithm is inserted if missing", 143 expect: coretesting.Attrs{"algorithm": "rsa-sha256"}, 144 }, { 145 info: "algorithm cannot be empty", 146 insert: coretesting.Attrs{"algorithm": ""}, 147 err: ".* algorithm: must not be empty", 148 }, { 149 info: "unknown field is not touched", 150 insert: coretesting.Attrs{"unknown-field": 12345}, 151 expect: coretesting.Attrs{"unknown-field": 12345}, 152 }} 153 154 func (s *ConfigSuite) TestNewModelConfig(c *gc.C) { 155 for i, test := range newConfigTests { 156 doTest(s, i, test, c) 157 } 158 } 159 160 func doTest(s *ConfigSuite, i int, test configtest, c *gc.C) { 161 c.Logf("test %d: %s", i, test.info) 162 for k, v := range test.envVars { 163 os.Setenv(k, v) 164 defer os.Setenv(k, "") 165 } 166 attrs := validAttrs().Merge(test.insert).Delete(test.remove...) 167 attrs["private-key"] = s.privateKeyData 168 testConfig := newConfig(c, attrs) 169 environ, err := environs.New(testConfig) 170 if test.err == "" { 171 c.Check(err, jc.ErrorIsNil) 172 if err != nil { 173 return 174 } 175 attrs := environ.Config().AllAttrs() 176 for field, value := range test.expect { 177 c.Check(attrs[field], gc.Equals, value) 178 } 179 } else { 180 c.Check(environ, gc.IsNil) 181 c.Check(err, gc.ErrorMatches, test.err) 182 } 183 } 184 185 var changeConfigTests = []struct { 186 info string 187 insert coretesting.Attrs 188 remove []string 189 expect coretesting.Attrs 190 err string 191 }{{ 192 info: "no change, no error", 193 expect: validAttrs(), 194 }, { 195 info: "can change sdc-user", 196 insert: coretesting.Attrs{"sdc-user": "joyent_user"}, 197 expect: coretesting.Attrs{"sdc-user": "joyent_user"}, 198 }, { 199 info: "can change sdc-key-id", 200 insert: coretesting.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, 201 expect: coretesting.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"}, 202 }, { 203 info: "can change sdc-url", 204 insert: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 205 expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"}, 206 }, { 207 info: "can insert unknown field", 208 insert: coretesting.Attrs{"unknown": "ignoti"}, 209 expect: coretesting.Attrs{"unknown": "ignoti"}, 210 }} 211 212 func (s *ConfigSuite) TestValidateChange(c *gc.C) { 213 attrs := validAttrs() 214 baseConfig := newConfig(c, attrs) 215 for i, test := range changeConfigTests { 216 c.Logf("test %d: %s", i, test.info) 217 attrs := validAttrs().Merge(test.insert).Delete(test.remove...) 218 testConfig := newConfig(c, attrs) 219 validatedConfig, err := jp.Provider.Validate(testConfig, baseConfig) 220 if test.err == "" { 221 c.Check(err, jc.ErrorIsNil) 222 if err != nil { 223 continue 224 } 225 attrs := validatedConfig.AllAttrs() 226 for field, value := range test.expect { 227 c.Check(attrs[field], gc.Equals, value) 228 } 229 } else { 230 c.Check(validatedConfig, gc.IsNil) 231 c.Check(err, gc.ErrorMatches, "invalid config change: "+test.err) 232 } 233 } 234 } 235 236 func (s *ConfigSuite) TestSetConfig(c *gc.C) { 237 baseConfig := newConfig(c, validAttrs()) 238 for i, test := range changeConfigTests { 239 c.Logf("test %d: %s", i, test.info) 240 environ, err := environs.New(baseConfig) 241 c.Assert(err, jc.ErrorIsNil) 242 attrs := validAttrs().Merge(test.insert).Delete(test.remove...) 243 testConfig := newConfig(c, attrs) 244 err = environ.SetConfig(testConfig) 245 newAttrs := environ.Config().AllAttrs() 246 if test.err == "" { 247 c.Check(err, jc.ErrorIsNil) 248 for field, value := range test.expect { 249 c.Check(newAttrs[field], gc.Equals, value) 250 } 251 } else { 252 c.Check(err, gc.ErrorMatches, test.err) 253 for field, value := range baseConfig.UnknownAttrs() { 254 c.Check(newAttrs[field], gc.Equals, value) 255 } 256 } 257 } 258 } 259 260 // TODO(wallyworld) - add tests for cloud endpoint passed in via bootstrap args 261 var bootstrapConfigTests = []struct { 262 info string 263 insert coretesting.Attrs 264 remove []string 265 expect coretesting.Attrs 266 err string 267 }{{ 268 info: "All value provided, nothing to do", 269 expect: validAttrs(), 270 }} 271 272 func (s *ConfigSuite) TestBootstrapConfig(c *gc.C) { 273 for i, test := range bootstrapConfigTests { 274 c.Logf("test %d: %s", i, test.info) 275 attrs := validAttrs().Merge(test.insert).Delete(test.remove...) 276 credentialAttrs := make(map[string]string, len(attrs)) 277 for k, v := range attrs.Delete("type") { 278 credentialAttrs[k] = fmt.Sprintf("%v", v) 279 } 280 testConfig := newConfig(c, attrs) 281 preparedConfig, err := jp.Provider.BootstrapConfig(environs.BootstrapConfigParams{ 282 Config: testConfig, 283 Credentials: cloud.NewCredential( 284 cloud.UserPassAuthType, 285 credentialAttrs, 286 ), 287 }) 288 if test.err == "" { 289 c.Check(err, jc.ErrorIsNil) 290 attrs := preparedConfig.AllAttrs() 291 for field, value := range test.expect { 292 c.Check(attrs[field], gc.Equals, value) 293 } 294 } else { 295 c.Check(preparedConfig, gc.IsNil) 296 c.Check(err, gc.ErrorMatches, test.err) 297 } 298 } 299 }