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  }