github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/controller/config_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package controller_test
     5  
     6  import (
     7  	stdtesting "testing"
     8  	"time"
     9  
    10  	"github.com/juju/collections/set"
    11  	"github.com/juju/loggo"
    12  	"github.com/juju/romulus"
    13  	gitjujutesting "github.com/juju/testing"
    14  	jc "github.com/juju/testing/checkers"
    15  	utilscert "github.com/juju/utils/cert"
    16  	gc "gopkg.in/check.v1"
    17  	"gopkg.in/juju/charmrepo.v3/csclient"
    18  
    19  	"github.com/juju/juju/cert"
    20  	"github.com/juju/juju/controller"
    21  	"github.com/juju/juju/testing"
    22  )
    23  
    24  func Test(t *stdtesting.T) {
    25  	gc.TestingT(t)
    26  }
    27  
    28  type ConfigSuite struct {
    29  	testing.FakeJujuXDGDataHomeSuite
    30  	home string
    31  }
    32  
    33  var _ = gc.Suite(&ConfigSuite{})
    34  
    35  func (s *ConfigSuite) SetUpTest(c *gc.C) {
    36  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    37  	// Make sure that the defaults are used, which
    38  	// is <root>=WARNING
    39  	loggo.DefaultContext().ResetLoggerLevels()
    40  }
    41  
    42  func (s *ConfigSuite) TestGenerateControllerCertAndKey(c *gc.C) {
    43  	// Add a cert.
    44  	s.FakeHomeSuite.Home.AddFiles(c, gitjujutesting.TestFile{Name: ".ssh/id_rsa.pub", Data: "rsa\n"})
    45  
    46  	for _, test := range []struct {
    47  		caCert    string
    48  		caKey     string
    49  		sanValues []string
    50  	}{{
    51  		caCert: testing.CACert,
    52  		caKey:  testing.CAKey,
    53  	}, {
    54  		caCert:    testing.CACert,
    55  		caKey:     testing.CAKey,
    56  		sanValues: []string{"10.0.0.1", "192.168.1.1"},
    57  	}} {
    58  		certPEM, keyPEM, err := controller.GenerateControllerCertAndKey(test.caCert, test.caKey, test.sanValues)
    59  		c.Assert(err, jc.ErrorIsNil)
    60  
    61  		_, _, err = utilscert.ParseCertAndKey(certPEM, keyPEM)
    62  		c.Check(err, jc.ErrorIsNil)
    63  
    64  		err = cert.Verify(certPEM, testing.CACert, time.Now())
    65  		c.Assert(err, jc.ErrorIsNil)
    66  		err = cert.Verify(certPEM, testing.CACert, time.Now().AddDate(9, 0, 0))
    67  		c.Assert(err, jc.ErrorIsNil)
    68  		err = cert.Verify(certPEM, testing.CACert, time.Now().AddDate(10, 0, 1))
    69  		c.Assert(err, gc.NotNil)
    70  		srvCert, err := utilscert.ParseCert(certPEM)
    71  		c.Assert(err, jc.ErrorIsNil)
    72  		sanIPs := make([]string, len(srvCert.IPAddresses))
    73  		for i, ip := range srvCert.IPAddresses {
    74  			sanIPs[i] = ip.String()
    75  		}
    76  		c.Assert(sanIPs, jc.SameContents, test.sanValues)
    77  	}
    78  }
    79  
    80  var validateTests = []struct {
    81  	about       string
    82  	config      controller.Config
    83  	expectError string
    84  }{{
    85  	about:       "missing CA cert",
    86  	expectError: `missing CA certificate`,
    87  }, {
    88  	about: "bad CA cert",
    89  	config: controller.Config{
    90  		controller.CACertKey: "xxx",
    91  	},
    92  	expectError: `bad CA certificate in configuration: no certificates found`,
    93  }, {
    94  	about: "bad controller UUID",
    95  	config: controller.Config{
    96  		controller.ControllerUUIDKey: "xxx",
    97  		controller.CACertKey:         testing.CACert,
    98  	},
    99  	expectError: `controller-uuid: expected UUID, got string\("xxx"\)`,
   100  }, {
   101  	about: "HTTPS identity URL OK",
   102  	config: controller.Config{
   103  		controller.IdentityURL: "https://0.1.2.3/foo",
   104  		controller.CACertKey:   testing.CACert,
   105  	},
   106  }, {
   107  	about: "HTTP identity URL requires public key",
   108  	config: controller.Config{
   109  		controller.IdentityURL: "http://0.1.2.3/foo",
   110  		controller.CACertKey:   testing.CACert,
   111  	},
   112  	expectError: `URL needs to be https when identity-public-key not provided`,
   113  }, {
   114  	about: "HTTP identity URL OK if public key is provided",
   115  	config: controller.Config{
   116  		controller.IdentityPublicKey: `o/yOqSNWncMo1GURWuez/dGR30TscmmuIxgjztpoHEY=`,
   117  		controller.IdentityURL:       "http://0.1.2.3/foo",
   118  		controller.CACertKey:         testing.CACert,
   119  	},
   120  }, {
   121  	about: "invalid identity public key",
   122  	config: controller.Config{
   123  		controller.IdentityPublicKey: `xxxx`,
   124  		controller.CACertKey:         testing.CACert,
   125  	},
   126  	expectError: `invalid identity public key: wrong length for base64 key, got 3 want 32`,
   127  }, {
   128  	about: "invalid management space name - whitespace",
   129  	config: controller.Config{
   130  		controller.CACertKey:           testing.CACert,
   131  		controller.JujuManagementSpace: " ",
   132  	},
   133  	expectError: `juju mgmt space name " " not valid`,
   134  }, {
   135  	about: "invalid management space name - caps",
   136  	config: controller.Config{
   137  		controller.CACertKey:           testing.CACert,
   138  		controller.JujuManagementSpace: "CAPS",
   139  	},
   140  	expectError: `juju mgmt space name "CAPS" not valid`,
   141  }, {
   142  	about: "invalid management space name - carriage return",
   143  	config: controller.Config{
   144  		controller.CACertKey:           testing.CACert,
   145  		controller.JujuManagementSpace: "\n",
   146  	},
   147  	expectError: `juju mgmt space name "\\n" not valid`,
   148  }, {
   149  	about: "invalid HA space name - number",
   150  	config: controller.Config{
   151  		controller.CACertKey:   testing.CACert,
   152  		controller.JujuHASpace: 666,
   153  	},
   154  	expectError: `type for juju HA space name 666 not valid`,
   155  }, {
   156  	about: "invalid HA space name - bool",
   157  	config: controller.Config{
   158  		controller.CACertKey:   testing.CACert,
   159  		controller.JujuHASpace: true,
   160  	},
   161  	expectError: `type for juju HA space name true not valid`,
   162  }, {
   163  	about: "invalid audit log max size",
   164  	config: controller.Config{
   165  		controller.CACertKey:       testing.CACert,
   166  		controller.AuditLogMaxSize: "abcd",
   167  	},
   168  	expectError: `invalid audit log max size in configuration: expected a non-negative number, got "abcd"`,
   169  }, {
   170  	about: "zero audit log max size",
   171  	config: controller.Config{
   172  		controller.CACertKey:       testing.CACert,
   173  		controller.AuditingEnabled: true,
   174  		controller.AuditLogMaxSize: "0M",
   175  	},
   176  	expectError: `invalid audit log max size: can't be 0 if auditing is enabled`,
   177  }, {
   178  	about: "invalid audit log max backups",
   179  	config: controller.Config{
   180  		controller.CACertKey:          testing.CACert,
   181  		controller.AuditLogMaxBackups: -10,
   182  	},
   183  	expectError: `invalid audit log max backups: should be a number of files \(or 0 to keep all\), got -10`,
   184  }, {
   185  	about: "invalid audit log exclude",
   186  	config: controller.Config{
   187  		controller.CACertKey:              testing.CACert,
   188  		controller.AuditLogExcludeMethods: []interface{}{"Dap.Kings", "ReadOnlyMethods", "Sharon Jones"},
   189  	},
   190  	expectError: `invalid audit log exclude methods: should be a list of "Facade.Method" names \(or "ReadOnlyMethods"\), got "Sharon Jones" at position 3`,
   191  }, {
   192  	about: "invalid CAAS operator docker image path",
   193  	config: controller.Config{
   194  		controller.CACertKey:             testing.CACert,
   195  		controller.CAASOperatorImagePath: "foo?bar",
   196  	},
   197  	expectError: `docker image path "foo\?bar" not valid`,
   198  }, {
   199  	about: "invalid CAAS operator docker image path - leading colon",
   200  	config: controller.Config{
   201  		controller.CACertKey:             testing.CACert,
   202  		controller.CAASOperatorImagePath: ":foo",
   203  	},
   204  	expectError: `docker image path ":foo" not valid`,
   205  }, {
   206  	about: "invalid CAAS operator docker image path - trailing colon",
   207  	config: controller.Config{
   208  		controller.CACertKey:             testing.CACert,
   209  		controller.CAASOperatorImagePath: "foo:",
   210  	},
   211  	expectError: `docker image path "foo:" not valid`,
   212  }, {
   213  	about: "invalid CAAS operator docker image path - extra colon",
   214  	config: controller.Config{
   215  		controller.CACertKey:             testing.CACert,
   216  		controller.CAASOperatorImagePath: "foo::bar",
   217  	},
   218  	expectError: `docker image path "foo::bar" not valid`,
   219  }, {
   220  	about: "invalid CAAS operator docker image path - leading /",
   221  	config: controller.Config{
   222  		controller.CACertKey:             testing.CACert,
   223  		controller.CAASOperatorImagePath: "/foo",
   224  	},
   225  	expectError: `docker image path "/foo" not valid`,
   226  }, {
   227  	about: "invalid CAAS operator docker image path - extra /",
   228  	config: controller.Config{
   229  		controller.CACertKey:             testing.CACert,
   230  		controller.CAASOperatorImagePath: "foo//bar",
   231  	},
   232  	expectError: `docker image path "foo//bar" not valid`,
   233  }, {
   234  	about: "negative controller-api-port",
   235  	config: controller.Config{
   236  		controller.CACertKey:         testing.CACert,
   237  		controller.ControllerAPIPort: -5,
   238  	},
   239  	expectError: `non-positive integer for controller-api-port not valid`,
   240  }, {
   241  	about: "controller-api-port matching api-port",
   242  	config: controller.Config{
   243  		controller.APIPort:           12345,
   244  		controller.CACertKey:         testing.CACert,
   245  		controller.ControllerAPIPort: 12345,
   246  	},
   247  	expectError: `controller-api-port matching api-port not valid`,
   248  }, {
   249  	about: "controller-api-port matching state-port",
   250  	config: controller.Config{
   251  		controller.APIPort:           12345,
   252  		controller.StatePort:         54321,
   253  		controller.CACertKey:         testing.CACert,
   254  		controller.ControllerAPIPort: 54321,
   255  	},
   256  	expectError: `controller-api-port matching state-port not valid`,
   257  }, {
   258  	about: "api-port-open-delay not a duration",
   259  	config: controller.Config{
   260  		controller.CACertKey:        testing.CACert,
   261  		controller.APIPortOpenDelay: "15",
   262  	},
   263  	expectError: `api-port-open-delay value "15" must be a valid duration`,
   264  }, {
   265  	about: "txn-prune-sleep-time not a duration",
   266  	config: controller.Config{
   267  		controller.CACertKey:         testing.CACert,
   268  		controller.PruneTxnSleepTime: "15",
   269  	},
   270  	expectError: `prune-txn-sleep-time must be a valid duration \(eg "10ms"\): time: missing unit in duration 15`,
   271  }}
   272  
   273  func (s *ConfigSuite) TestValidate(c *gc.C) {
   274  	for i, test := range validateTests {
   275  		c.Logf("test %d: %v", i, test.about)
   276  		err := test.config.Validate()
   277  		if test.expectError != "" {
   278  			c.Check(err, gc.ErrorMatches, test.expectError)
   279  		} else {
   280  			c.Check(err, jc.ErrorIsNil)
   281  		}
   282  	}
   283  }
   284  
   285  func (s *ConfigSuite) TestAPIPortDefaults(c *gc.C) {
   286  	cfg, err := controller.NewConfig(testing.ControllerTag.Id(), testing.CACert, nil)
   287  	c.Assert(err, jc.ErrorIsNil)
   288  	c.Assert(cfg.APIPortOpenDelay(), gc.Equals, 2*time.Second)
   289  }
   290  
   291  func (s *ConfigSuite) TestLogConfigDefaults(c *gc.C) {
   292  	cfg, err := controller.NewConfig(testing.ControllerTag.Id(), testing.CACert, nil)
   293  	c.Assert(err, jc.ErrorIsNil)
   294  	c.Assert(cfg.MaxLogsAge(), gc.Equals, 72*time.Hour)
   295  	c.Assert(cfg.MaxLogSizeMB(), gc.Equals, 4096)
   296  }
   297  
   298  func (s *ConfigSuite) TestLogConfigValues(c *gc.C) {
   299  	c.Assert(controller.AllowedUpdateConfigAttributes.Contains(controller.MaxLogsAge), jc.IsTrue)
   300  	c.Assert(controller.AllowedUpdateConfigAttributes.Contains(controller.MaxLogsSize), jc.IsTrue)
   301  
   302  	cfg, err := controller.NewConfig(
   303  		testing.ControllerTag.Id(),
   304  		testing.CACert,
   305  		map[string]interface{}{
   306  			"max-logs-size": "8G",
   307  			"max-logs-age":  "96h",
   308  		},
   309  	)
   310  	c.Assert(err, jc.ErrorIsNil)
   311  	c.Assert(cfg.MaxLogsAge(), gc.Equals, 96*time.Hour)
   312  	c.Assert(cfg.MaxLogSizeMB(), gc.Equals, 8192)
   313  }
   314  
   315  func (s *ConfigSuite) TestTxnLogConfigDefault(c *gc.C) {
   316  	cfg, err := controller.NewConfig(testing.ControllerTag.Id(), testing.CACert, nil)
   317  	c.Assert(err, jc.ErrorIsNil)
   318  	c.Assert(cfg.MaxTxnLogSizeMB(), gc.Equals, 10)
   319  }
   320  
   321  func (s *ConfigSuite) TestTxnLogConfigValue(c *gc.C) {
   322  	cfg, err := controller.NewConfig(
   323  		testing.ControllerTag.Id(),
   324  		testing.CACert,
   325  		map[string]interface{}{
   326  			"max-txn-log-size": "8G",
   327  		},
   328  	)
   329  	c.Assert(err, jc.ErrorIsNil)
   330  	c.Assert(cfg.MaxTxnLogSizeMB(), gc.Equals, 8192)
   331  }
   332  
   333  func (s *ConfigSuite) TestMaxPruneTxnConfigDefault(c *gc.C) {
   334  	cfg, err := controller.NewConfig(testing.ControllerTag.Id(), testing.CACert, nil)
   335  	c.Assert(err, jc.ErrorIsNil)
   336  	c.Check(cfg.MaxPruneTxnBatchSize(), gc.Equals, 1*1000*1000)
   337  	c.Check(cfg.MaxPruneTxnPasses(), gc.Equals, 100)
   338  }
   339  
   340  func (s *ConfigSuite) TestMaxPruneTxnConfigValue(c *gc.C) {
   341  	cfg, err := controller.NewConfig(
   342  		testing.ControllerTag.Id(),
   343  		testing.CACert,
   344  		map[string]interface{}{
   345  			"max-prune-txn-batch-size": "12345678",
   346  			"max-prune-txn-passes":     "10",
   347  		},
   348  	)
   349  	c.Assert(err, jc.ErrorIsNil)
   350  	c.Check(cfg.MaxPruneTxnBatchSize(), gc.Equals, 12345678)
   351  	c.Check(cfg.MaxPruneTxnPasses(), gc.Equals, 10)
   352  }
   353  
   354  func (s *ConfigSuite) TestPruneTxnQueryCount(c *gc.C) {
   355  	cfg, err := controller.NewConfig(
   356  		testing.ControllerTag.Id(),
   357  		testing.CACert,
   358  		map[string]interface{}{
   359  			"prune-txn-query-count": "500",
   360  			"prune-txn-sleep-time":  "5ms",
   361  		},
   362  	)
   363  	c.Assert(err, jc.ErrorIsNil)
   364  	c.Check(cfg.PruneTxnQueryCount(), gc.Equals, 500)
   365  	c.Check(cfg.PruneTxnSleepTime(), gc.Equals, 5*time.Millisecond)
   366  }
   367  
   368  func (s *ConfigSuite) TestNetworkSpaceConfigValues(c *gc.C) {
   369  	haSpace := "space1"
   370  	managementSpace := "space2"
   371  
   372  	cfg, err := controller.NewConfig(
   373  		testing.ControllerTag.Id(),
   374  		testing.CACert,
   375  		map[string]interface{}{
   376  			controller.JujuHASpace:         haSpace,
   377  			controller.JujuManagementSpace: managementSpace,
   378  		},
   379  	)
   380  	c.Assert(err, jc.ErrorIsNil)
   381  	c.Assert(cfg.JujuHASpace(), gc.Equals, haSpace)
   382  	c.Assert(cfg.JujuManagementSpace(), gc.Equals, managementSpace)
   383  }
   384  
   385  func (s *ConfigSuite) TestNetworkSpaceConfigDefaults(c *gc.C) {
   386  	cfg, err := controller.NewConfig(
   387  		testing.ControllerTag.Id(),
   388  		testing.CACert,
   389  		map[string]interface{}{},
   390  	)
   391  	c.Assert(err, jc.ErrorIsNil)
   392  	c.Assert(cfg.JujuHASpace(), gc.Equals, "")
   393  	c.Assert(cfg.JujuManagementSpace(), gc.Equals, "")
   394  }
   395  
   396  func (s *ConfigSuite) TestAuditLogDefaults(c *gc.C) {
   397  	cfg, err := controller.NewConfig(testing.ControllerTag.Id(), testing.CACert, nil)
   398  	c.Assert(err, jc.ErrorIsNil)
   399  	c.Assert(cfg.AuditingEnabled(), gc.Equals, true)
   400  	c.Assert(cfg.AuditLogCaptureArgs(), gc.Equals, false)
   401  	c.Assert(cfg.AuditLogMaxSizeMB(), gc.Equals, 300)
   402  	c.Assert(cfg.AuditLogMaxBackups(), gc.Equals, 10)
   403  	c.Assert(cfg.AuditLogExcludeMethods(), gc.DeepEquals,
   404  		set.NewStrings(controller.DefaultAuditLogExcludeMethods...))
   405  }
   406  
   407  func (s *ConfigSuite) TestAuditLogValues(c *gc.C) {
   408  	cfg, err := controller.NewConfig(
   409  		testing.ControllerTag.Id(),
   410  		testing.CACert,
   411  		map[string]interface{}{
   412  			"auditing-enabled":          false,
   413  			"audit-log-capture-args":    true,
   414  			"audit-log-max-size":        "100M",
   415  			"audit-log-max-backups":     10.0,
   416  			"audit-log-exclude-methods": []string{"Fleet.Foxes", "King.Gizzard", "ReadOnlyMethods"},
   417  		},
   418  	)
   419  	c.Assert(err, jc.ErrorIsNil)
   420  	c.Assert(cfg.AuditingEnabled(), gc.Equals, false)
   421  	c.Assert(cfg.AuditLogCaptureArgs(), gc.Equals, true)
   422  	c.Assert(cfg.AuditLogMaxSizeMB(), gc.Equals, 100)
   423  	c.Assert(cfg.AuditLogMaxBackups(), gc.Equals, 10)
   424  	c.Assert(cfg.AuditLogExcludeMethods(), gc.DeepEquals, set.NewStrings(
   425  		"Fleet.Foxes",
   426  		"King.Gizzard",
   427  		"ReadOnlyMethods",
   428  	))
   429  }
   430  
   431  func (s *ConfigSuite) TestAuditLogExcludeMethodsType(c *gc.C) {
   432  	_, err := controller.NewConfig(
   433  		testing.ControllerTag.Id(),
   434  		testing.CACert,
   435  		map[string]interface{}{
   436  			"audit-log-exclude-methods": []int{2, 3, 4},
   437  		},
   438  	)
   439  	c.Assert(err, gc.ErrorMatches, `audit-log-exclude-methods\[0\]: expected string, got int\(2\)`)
   440  }
   441  
   442  func (s *ConfigSuite) TestAuditLogFloatBackupsLoadedDirectly(c *gc.C) {
   443  	// We still need to be able to handle floats in data loaded from the DB.
   444  	cfg := controller.Config{
   445  		controller.AuditLogMaxBackups: 10.0,
   446  	}
   447  	c.Assert(cfg.AuditLogMaxBackups(), gc.Equals, 10)
   448  }
   449  
   450  func (s *ConfigSuite) TestConfigManagementSpaceAsConstraint(c *gc.C) {
   451  	managementSpace := "management-space"
   452  	cfg, err := controller.NewConfig(
   453  		testing.ControllerTag.Id(),
   454  		testing.CACert,
   455  		map[string]interface{}{controller.JujuHASpace: managementSpace},
   456  	)
   457  	c.Assert(err, jc.ErrorIsNil)
   458  	c.Check(*cfg.AsSpaceConstraints(nil), gc.DeepEquals, []string{managementSpace})
   459  }
   460  
   461  func (s *ConfigSuite) TestConfigHASpaceAsConstraint(c *gc.C) {
   462  	haSpace := "ha-space"
   463  	cfg, err := controller.NewConfig(
   464  		testing.ControllerTag.Id(),
   465  		testing.CACert,
   466  		map[string]interface{}{controller.JujuHASpace: haSpace},
   467  	)
   468  	c.Assert(err, jc.ErrorIsNil)
   469  	c.Check(*cfg.AsSpaceConstraints(nil), gc.DeepEquals, []string{haSpace})
   470  }
   471  
   472  func (s *ConfigSuite) TestConfigAllSpacesAsMergedConstraints(c *gc.C) {
   473  	haSpace := "ha-space"
   474  	managementSpace := "management-space"
   475  	constraintSpace := "constraint-space"
   476  
   477  	cfg, err := controller.NewConfig(
   478  		testing.ControllerTag.Id(),
   479  		testing.CACert,
   480  		map[string]interface{}{
   481  			controller.JujuHASpace:         haSpace,
   482  			controller.JujuManagementSpace: managementSpace,
   483  		},
   484  	)
   485  	c.Assert(err, jc.ErrorIsNil)
   486  
   487  	got := *cfg.AsSpaceConstraints(&[]string{constraintSpace})
   488  	c.Check(got, gc.DeepEquals, []string{constraintSpace, haSpace, managementSpace})
   489  }
   490  
   491  func (s *ConfigSuite) TestConfigNoSpacesNilSpaceConfigPreserved(c *gc.C) {
   492  	cfg, err := controller.NewConfig(
   493  		testing.ControllerTag.Id(),
   494  		testing.CACert,
   495  		map[string]interface{}{},
   496  	)
   497  	c.Assert(err, jc.ErrorIsNil)
   498  	c.Check(cfg.AsSpaceConstraints(nil), gc.IsNil)
   499  }
   500  
   501  func (s *ConfigSuite) TestCAASOperatorImagePath(c *gc.C) {
   502  	for _, imagePath := range []string{
   503  		"juju-operator-image",
   504  		"registry.foo.com/juju-operator-image",
   505  		"registry.foo.com/me/juju-operator-image",
   506  		"juju-operator-image:latest",
   507  		"juju-operator-image:2.4-beta1",
   508  		"registry.foo.com/juju-operator-image:2.4-beta1",
   509  		"registry.foo.com/me/juju-operator-image:2.4-beta1",
   510  	} {
   511  		cfg, err := controller.NewConfig(
   512  			testing.ControllerTag.Id(),
   513  			testing.CACert,
   514  			map[string]interface{}{
   515  				controller.CAASOperatorImagePath: imagePath,
   516  			},
   517  		)
   518  		c.Assert(err, jc.ErrorIsNil)
   519  		c.Assert(cfg.CAASOperatorImagePath(), gc.Equals, imagePath)
   520  	}
   521  }
   522  
   523  func (s *ConfigSuite) TestCharmstoreURLDefault(c *gc.C) {
   524  	cfg, err := controller.NewConfig(
   525  		testing.ControllerTag.Id(),
   526  		testing.CACert,
   527  		map[string]interface{}{},
   528  	)
   529  	c.Assert(err, jc.ErrorIsNil)
   530  	c.Check(cfg.CharmStoreURL(), gc.Equals, csclient.ServerURL)
   531  }
   532  
   533  func (s *ConfigSuite) TestCharmstoreURLSettingValue(c *gc.C) {
   534  	csURL := "http://homestarrunner.com/charmstore"
   535  	cfg, err := controller.NewConfig(
   536  		testing.ControllerTag.Id(),
   537  		testing.CACert,
   538  		map[string]interface{}{
   539  			controller.CharmStoreURL: csURL,
   540  		},
   541  	)
   542  	c.Assert(err, jc.ErrorIsNil)
   543  	c.Assert(cfg.CharmStoreURL(), gc.Equals, csURL)
   544  }
   545  
   546  func (s *ConfigSuite) TestMeteringURLDefault(c *gc.C) {
   547  	cfg, err := controller.NewConfig(
   548  		testing.ControllerTag.Id(),
   549  		testing.CACert,
   550  		map[string]interface{}{},
   551  	)
   552  	c.Assert(err, jc.ErrorIsNil)
   553  	c.Check(cfg.MeteringURL(), gc.Equals, romulus.DefaultAPIRoot)
   554  }
   555  
   556  func (s *ConfigSuite) TestMeteringURLSettingValue(c *gc.C) {
   557  	mURL := "http://homestarrunner.com/metering"
   558  	cfg, err := controller.NewConfig(
   559  		testing.ControllerTag.Id(),
   560  		testing.CACert,
   561  		map[string]interface{}{
   562  			controller.MeteringURL: mURL,
   563  		},
   564  	)
   565  	c.Assert(err, jc.ErrorIsNil)
   566  	c.Assert(cfg.MeteringURL(), gc.Equals, mURL)
   567  }