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