github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/provider/gce/config_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package gce_test 5 6 import ( 7 jc "github.com/juju/testing/checkers" 8 gc "gopkg.in/check.v1" 9 10 "github.com/juju/juju/environs" 11 "github.com/juju/juju/environs/config" 12 "github.com/juju/juju/provider/gce" 13 "github.com/juju/juju/testing" 14 ) 15 16 type ConfigSuite struct { 17 gce.BaseSuite 18 19 config *config.Config 20 } 21 22 var _ = gc.Suite(&ConfigSuite{}) 23 24 func (s *ConfigSuite) SetUpTest(c *gc.C) { 25 s.BaseSuite.SetUpTest(c) 26 27 cfg, err := testing.ModelConfig(c).Apply(gce.ConfigAttrs) 28 c.Assert(err, jc.ErrorIsNil) 29 s.config = cfg 30 } 31 32 // TODO(ericsnow) Each test only deals with a single field, so having 33 // multiple values in insert and remove (in configTestSpec) is a little 34 // misleading and unecessary. 35 36 // configTestSpec defines a subtest to run in a table driven test. 37 type configTestSpec struct { 38 // info describes the subtest. 39 info string 40 // insert holds attrs that should be merged into the config. 41 insert testing.Attrs 42 // remove has the names of attrs that should be removed. 43 remove []string 44 // expect defines the expected attributes in a success case. 45 expect testing.Attrs 46 // err is the error message to expect in a failure case. 47 err string 48 } 49 50 func (ts configTestSpec) checkSuccess(c *gc.C, value interface{}, err error) { 51 if !c.Check(err, jc.ErrorIsNil) { 52 return 53 } 54 55 var cfg *config.Config 56 switch typed := value.(type) { 57 case *config.Config: 58 cfg = typed 59 case environs.Environ: 60 cfg = typed.Config() 61 } 62 63 attrs := cfg.AllAttrs() 64 for field, value := range ts.expect { 65 c.Check(attrs[field], gc.Equals, value) 66 } 67 } 68 69 func (ts configTestSpec) checkFailure(c *gc.C, err error, msg string) { 70 c.Check(err, gc.ErrorMatches, msg+": "+ts.err) 71 } 72 73 func (ts configTestSpec) checkAttrs(c *gc.C, attrs map[string]interface{}, cfg *config.Config) { 74 for field, expected := range cfg.UnknownAttrs() { 75 value := attrs[field] 76 c.Check(value, gc.Equals, expected) 77 } 78 } 79 80 func (ts configTestSpec) attrs() testing.Attrs { 81 return gce.ConfigAttrs.Merge(ts.insert).Delete(ts.remove...) 82 } 83 84 func (ts configTestSpec) newConfig(c *gc.C) *config.Config { 85 attrs := ts.attrs() 86 cfg, err := testing.ModelConfig(c).Apply(attrs) 87 c.Assert(err, jc.ErrorIsNil) 88 return cfg 89 } 90 91 func (ts configTestSpec) fixCfg(c *gc.C, cfg *config.Config) *config.Config { 92 newCfg, err := cfg.Apply(ts.insert) 93 c.Assert(err, jc.ErrorIsNil) 94 return newCfg 95 } 96 97 func updateAttrs(attrs, updates testing.Attrs) testing.Attrs { 98 updated := make(testing.Attrs, len(attrs)) 99 for k, v := range attrs { 100 updated[k] = v 101 } 102 for k, v := range updates { 103 updated[k] = v 104 } 105 return updated 106 } 107 108 var newConfigTests = []configTestSpec{{ 109 info: "client-id is required", 110 remove: []string{"client-id"}, 111 err: "client-id: expected string, got nothing", 112 }, { 113 info: "client-id cannot be empty", 114 insert: testing.Attrs{"client-id": ""}, 115 err: "client-id: must not be empty", 116 }, { 117 info: "private-key is required", 118 remove: []string{"private-key"}, 119 err: "private-key: expected string, got nothing", 120 }, { 121 info: "private-key cannot be empty", 122 insert: testing.Attrs{"private-key": ""}, 123 err: "private-key: must not be empty", 124 }, { 125 info: "client-email is required", 126 remove: []string{"client-email"}, 127 err: "client-email: expected string, got nothing", 128 }, { 129 info: "client-email cannot be empty", 130 insert: testing.Attrs{"client-email": ""}, 131 err: "client-email: must not be empty", 132 }, { 133 info: "region is optional", 134 remove: []string{"region"}, 135 expect: testing.Attrs{"region": "us-central1"}, 136 }, { 137 info: "region cannot be empty", 138 insert: testing.Attrs{"region": ""}, 139 err: "region: must not be empty", 140 }, { 141 info: "project-id is required", 142 remove: []string{"project-id"}, 143 err: "project-id: expected string, got nothing", 144 }, { 145 info: "project-id cannot be empty", 146 insert: testing.Attrs{"project-id": ""}, 147 err: "project-id: must not be empty", 148 }, { 149 info: "image-endpoint is inserted if missing", 150 remove: []string{"image-endpoint"}, 151 expect: testing.Attrs{"image-endpoint": "https://www.googleapis.com"}, 152 }, { 153 info: "image-endpoint cannot be empty", 154 insert: testing.Attrs{"image-endpoint": ""}, 155 err: "image-endpoint: must not be empty", 156 }, { 157 info: "unknown field is not touched", 158 insert: testing.Attrs{"unknown-field": 12345}, 159 expect: testing.Attrs{"unknown-field": 12345}, 160 }} 161 162 func (s *ConfigSuite) TestNewModelConfig(c *gc.C) { 163 for i, test := range newConfigTests { 164 c.Logf("test %d: %s", i, test.info) 165 166 testConfig := test.newConfig(c) 167 environ, err := environs.New(testConfig) 168 169 // Check the result 170 if test.err != "" { 171 test.checkFailure(c, err, "invalid config") 172 } else { 173 test.checkSuccess(c, environ, err) 174 } 175 } 176 } 177 178 // TODO(wwitzel3) refactor to provider_test file 179 func (s *ConfigSuite) TestValidateNewConfig(c *gc.C) { 180 for i, test := range newConfigTests { 181 c.Logf("test %d: %s", i, test.info) 182 183 testConfig := test.newConfig(c) 184 validatedConfig, err := gce.Provider.Validate(testConfig, nil) 185 186 // Check the result 187 if test.err != "" { 188 test.checkFailure(c, err, "invalid config") 189 } else { 190 c.Check(validatedConfig, gc.NotNil) 191 test.checkSuccess(c, validatedConfig, err) 192 } 193 } 194 } 195 196 // TODO(wwitzel3) refactor to the provider_test file 197 func (s *ConfigSuite) TestValidateOldConfig(c *gc.C) { 198 for i, test := range newConfigTests { 199 c.Logf("test %d: %s", i, test.info) 200 201 oldcfg := test.newConfig(c) 202 newcfg := test.fixCfg(c, s.config) 203 expected := updateAttrs(gce.ConfigAttrs, test.insert) 204 205 // Validate the new config (relative to the old one) using the 206 // provider. 207 validatedConfig, err := gce.Provider.Validate(newcfg, oldcfg) 208 209 // Check the result. 210 if test.err != "" { 211 test.checkFailure(c, err, "invalid base config") 212 } else { 213 if test.insert == nil && test.remove != nil { 214 // No defaults are set on the old config. 215 c.Check(err, gc.ErrorMatches, "invalid base config: .*") 216 continue 217 } 218 219 if !c.Check(err, jc.ErrorIsNil) { 220 continue 221 } 222 // We verify that Validate filled in the defaults 223 // appropriately. 224 c.Check(validatedConfig, gc.NotNil) 225 test.checkAttrs(c, expected, validatedConfig) 226 } 227 } 228 } 229 230 var changeConfigTests = []configTestSpec{{ 231 info: "no change, no error", 232 expect: gce.ConfigAttrs, 233 }, { 234 info: "cannot change private-key", 235 insert: testing.Attrs{"private-key": "okkult"}, 236 err: "private-key: cannot change from " + gce.PrivateKey + " to okkult", 237 }, { 238 info: "cannot change client-id", 239 insert: testing.Attrs{"client-id": "mutant"}, 240 err: "client-id: cannot change from " + gce.ClientID + " to mutant", 241 }, { 242 info: "cannot change client-email", 243 insert: testing.Attrs{"client-email": "spam@eggs.com"}, 244 err: "client-email: cannot change from " + gce.ClientEmail + " to spam@eggs.com", 245 }, { 246 info: "cannot change region", 247 insert: testing.Attrs{"region": "not home"}, 248 err: "region: cannot change from home to not home", 249 }, { 250 info: "cannot change project-id", 251 insert: testing.Attrs{"project-id": "your-juju"}, 252 err: "project-id: cannot change from my-juju to your-juju", 253 }, { 254 info: "can insert unknown field", 255 insert: testing.Attrs{"unknown": "ignoti"}, 256 expect: testing.Attrs{"unknown": "ignoti"}, 257 }} 258 259 // TODO(wwitzel3) refactor this to the provider_test file. 260 func (s *ConfigSuite) TestValidateChange(c *gc.C) { 261 for i, test := range changeConfigTests { 262 c.Logf("test %d: %s", i, test.info) 263 264 testConfig := test.newConfig(c) 265 validatedConfig, err := gce.Provider.Validate(testConfig, s.config) 266 267 // Check the result. 268 if test.err != "" { 269 test.checkFailure(c, err, "invalid config change") 270 } else { 271 test.checkSuccess(c, validatedConfig, err) 272 } 273 } 274 } 275 276 func (s *ConfigSuite) TestSetConfig(c *gc.C) { 277 for i, test := range changeConfigTests { 278 c.Logf("test %d: %s", i, test.info) 279 280 environ, err := environs.New(s.config) 281 c.Assert(err, jc.ErrorIsNil) 282 283 testConfig := test.newConfig(c) 284 err = environ.SetConfig(testConfig) 285 286 // Check the result. 287 if test.err != "" { 288 test.checkFailure(c, err, "invalid config change") 289 test.checkAttrs(c, environ.Config().AllAttrs(), s.config) 290 } else { 291 test.checkSuccess(c, environ.Config(), err) 292 } 293 } 294 }