github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/initialize_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	gitjujutesting "github.com/juju/testing"
     8  	jc "github.com/juju/testing/checkers"
     9  	"github.com/juju/utils/clock"
    10  	gc "gopkg.in/check.v1"
    11  	"gopkg.in/juju/names.v2"
    12  
    13  	"github.com/juju/juju/cloud"
    14  	"github.com/juju/juju/constraints"
    15  	"github.com/juju/juju/controller"
    16  	"github.com/juju/juju/environs"
    17  	"github.com/juju/juju/environs/config"
    18  	"github.com/juju/juju/mongo/mongotest"
    19  	"github.com/juju/juju/state"
    20  	statetesting "github.com/juju/juju/state/testing"
    21  	"github.com/juju/juju/storage"
    22  	"github.com/juju/juju/testing"
    23  )
    24  
    25  type InitializeSuite struct {
    26  	gitjujutesting.MgoSuite
    27  	testing.BaseSuite
    28  	State *state.State
    29  }
    30  
    31  var _ = gc.Suite(&InitializeSuite{})
    32  
    33  func (s *InitializeSuite) SetUpSuite(c *gc.C) {
    34  	s.BaseSuite.SetUpSuite(c)
    35  	s.MgoSuite.SetUpSuite(c)
    36  }
    37  
    38  func (s *InitializeSuite) TearDownSuite(c *gc.C) {
    39  	s.MgoSuite.TearDownSuite(c)
    40  	s.BaseSuite.TearDownSuite(c)
    41  }
    42  
    43  func (s *InitializeSuite) SetUpTest(c *gc.C) {
    44  	s.BaseSuite.SetUpTest(c)
    45  	s.MgoSuite.SetUpTest(c)
    46  }
    47  
    48  func (s *InitializeSuite) openState(c *gc.C, modelTag names.ModelTag) {
    49  	st, err := state.Open(
    50  		modelTag,
    51  		testing.ControllerTag,
    52  		statetesting.NewMongoInfo(),
    53  		mongotest.DialOpts(),
    54  		state.NewPolicyFunc(nil),
    55  	)
    56  	c.Assert(err, jc.ErrorIsNil)
    57  	s.State = st
    58  }
    59  
    60  func (s *InitializeSuite) TearDownTest(c *gc.C) {
    61  	if s.State != nil {
    62  		err := s.State.Close()
    63  		c.Check(err, jc.ErrorIsNil)
    64  	}
    65  	s.MgoSuite.TearDownTest(c)
    66  	s.BaseSuite.TearDownTest(c)
    67  }
    68  
    69  func (s *InitializeSuite) TestInitialize(c *gc.C) {
    70  	cfg := testing.ModelConfig(c)
    71  	uuid := cfg.UUID()
    72  	owner := names.NewLocalUserTag("initialize-admin")
    73  
    74  	userPassCredentialTag := names.NewCloudCredentialTag(
    75  		"dummy/" + owner.Canonical() + "/some-credential",
    76  	)
    77  	emptyCredentialTag := names.NewCloudCredentialTag(
    78  		"dummy/" + owner.Canonical() + "/empty-credential",
    79  	)
    80  	userpassCredential := cloud.NewCredential(
    81  		cloud.UserPassAuthType,
    82  		map[string]string{
    83  			"username": "alice",
    84  			"password": "hunter2",
    85  		},
    86  	)
    87  	userpassCredential.Label = userPassCredentialTag.Name()
    88  	emptyCredential := cloud.NewEmptyCredential()
    89  	emptyCredential.Label = emptyCredentialTag.Name()
    90  	cloudCredentialsIn := map[names.CloudCredentialTag]cloud.Credential{
    91  		userPassCredentialTag: userpassCredential,
    92  		emptyCredentialTag:    emptyCredential,
    93  	}
    94  	controllerCfg := testing.FakeControllerConfig()
    95  
    96  	st, err := state.Initialize(state.InitializeParams{
    97  		Clock:            clock.WallClock,
    98  		ControllerConfig: controllerCfg,
    99  		ControllerModelArgs: state.ModelArgs{
   100  			Owner:                   owner,
   101  			Config:                  cfg,
   102  			CloudName:               "dummy",
   103  			CloudRegion:             "dummy-region",
   104  			CloudCredential:         userPassCredentialTag,
   105  			StorageProviderRegistry: storage.StaticProviderRegistry{},
   106  		},
   107  		CloudName: "dummy",
   108  		Cloud: cloud.Cloud{
   109  			Type: "dummy",
   110  			AuthTypes: []cloud.AuthType{
   111  				cloud.EmptyAuthType, cloud.UserPassAuthType,
   112  			},
   113  			Regions: []cloud.Region{{Name: "dummy-region"}},
   114  		},
   115  		CloudCredentials: cloudCredentialsIn,
   116  		MongoInfo:        statetesting.NewMongoInfo(),
   117  		MongoDialOpts:    mongotest.DialOpts(),
   118  	})
   119  	c.Assert(err, jc.ErrorIsNil)
   120  	c.Assert(st, gc.NotNil)
   121  	modelTag := st.ModelTag()
   122  	c.Assert(modelTag.Id(), gc.Equals, uuid)
   123  	err = st.Close()
   124  	c.Assert(err, jc.ErrorIsNil)
   125  
   126  	s.openState(c, modelTag)
   127  
   128  	cfg, err = s.State.ModelConfig()
   129  	c.Assert(err, jc.ErrorIsNil)
   130  	expected := cfg.AllAttrs()
   131  	for k, v := range config.ConfigDefaults() {
   132  		if _, ok := expected[k]; !ok {
   133  			expected[k] = v
   134  		}
   135  	}
   136  	c.Assert(cfg.AllAttrs(), jc.DeepEquals, expected)
   137  	// Check that the model has been created.
   138  	model, err := s.State.Model()
   139  	c.Assert(err, jc.ErrorIsNil)
   140  	c.Assert(model.Tag(), gc.Equals, modelTag)
   141  	c.Assert(model.CloudRegion(), gc.Equals, "dummy-region")
   142  	// Check that the owner has been created.
   143  	c.Assert(model.Owner(), gc.Equals, owner)
   144  	// Check that the owner can be retrieved by the tag.
   145  	entity, err := s.State.FindEntity(model.Owner())
   146  	c.Assert(err, jc.ErrorIsNil)
   147  	c.Assert(entity.Tag(), gc.Equals, owner)
   148  	// Check that the owner has an ModelUser created for the bootstrapped model.
   149  	modelUser, err := s.State.UserAccess(model.Owner(), model.Tag())
   150  	c.Assert(err, jc.ErrorIsNil)
   151  	c.Assert(modelUser.UserTag, gc.Equals, owner)
   152  	c.Assert(modelUser.Object, gc.Equals, model.Tag())
   153  
   154  	// Check that the model can be found through the tag.
   155  	entity, err = s.State.FindEntity(modelTag)
   156  	c.Assert(err, jc.ErrorIsNil)
   157  	cons, err := s.State.ModelConstraints()
   158  	c.Assert(err, jc.ErrorIsNil)
   159  	c.Assert(&cons, jc.Satisfies, constraints.IsEmpty)
   160  
   161  	addrs, err := s.State.APIHostPorts()
   162  	c.Assert(err, jc.ErrorIsNil)
   163  	c.Assert(addrs, gc.HasLen, 0)
   164  
   165  	info, err := s.State.ControllerInfo()
   166  	c.Assert(err, jc.ErrorIsNil)
   167  	c.Assert(info, jc.DeepEquals, &state.ControllerInfo{ModelTag: modelTag, CloudName: "dummy"})
   168  
   169  	// Check that the model's cloud and credential names are as
   170  	// expected, and the owner's cloud credentials are initialised.
   171  	c.Assert(model.Cloud(), gc.Equals, "dummy")
   172  	credentialTag, ok := model.CloudCredential()
   173  	c.Assert(ok, jc.IsTrue)
   174  	c.Assert(credentialTag, gc.Equals, userPassCredentialTag)
   175  	cloudCredentials, err := s.State.CloudCredentials(model.Owner(), "dummy")
   176  	c.Assert(err, jc.ErrorIsNil)
   177  	expectedCred := make(map[string]cloud.Credential, len(cloudCredentialsIn))
   178  	for tag, cred := range cloudCredentialsIn {
   179  		expectedCred[tag.Canonical()] = cred
   180  	}
   181  	c.Assert(cloudCredentials, jc.DeepEquals, expectedCred)
   182  }
   183  
   184  func (s *InitializeSuite) TestInitializeWithInvalidCredentialType(c *gc.C) {
   185  	owner := names.NewLocalUserTag("initialize-admin")
   186  	modelCfg := testing.ModelConfig(c)
   187  	controllerCfg := testing.FakeControllerConfig()
   188  	credentialTag := names.NewCloudCredentialTag("dummy/" + owner.Canonical() + "/borken")
   189  	_, err := state.Initialize(state.InitializeParams{
   190  		Clock:            clock.WallClock,
   191  		ControllerConfig: controllerCfg,
   192  		ControllerModelArgs: state.ModelArgs{
   193  			CloudName:               "dummy",
   194  			Owner:                   owner,
   195  			Config:                  modelCfg,
   196  			StorageProviderRegistry: storage.StaticProviderRegistry{},
   197  		},
   198  		CloudName: "dummy",
   199  		Cloud: cloud.Cloud{
   200  			Type: "dummy",
   201  			AuthTypes: []cloud.AuthType{
   202  				cloud.AccessKeyAuthType, cloud.OAuth1AuthType,
   203  			},
   204  		},
   205  		CloudCredentials: map[names.CloudCredentialTag]cloud.Credential{
   206  			credentialTag: cloud.NewCredential(cloud.UserPassAuthType, nil),
   207  		},
   208  		MongoInfo:     statetesting.NewMongoInfo(),
   209  		MongoDialOpts: mongotest.DialOpts(),
   210  	})
   211  	c.Assert(err, gc.ErrorMatches,
   212  		`validating initialization args: validating cloud credentials: credential "dummy/initialize-admin@local/borken" with auth-type "userpass" is not supported \(expected one of \["access-key" "oauth1"\]\)`,
   213  	)
   214  }
   215  
   216  func (s *InitializeSuite) TestInitializeWithControllerInheritedConfig(c *gc.C) {
   217  	cfg := testing.ModelConfig(c)
   218  	uuid := cfg.UUID()
   219  	initial := cfg.AllAttrs()
   220  	controllerInheritedConfigIn := map[string]interface{}{
   221  		"default-series": initial["default-series"],
   222  	}
   223  	owner := names.NewLocalUserTag("initialize-admin")
   224  	controllerCfg := testing.FakeControllerConfig()
   225  
   226  	st, err := state.Initialize(state.InitializeParams{
   227  		Clock:            clock.WallClock,
   228  		ControllerConfig: controllerCfg,
   229  		ControllerModelArgs: state.ModelArgs{
   230  			CloudName:               "dummy",
   231  			Owner:                   owner,
   232  			Config:                  cfg,
   233  			StorageProviderRegistry: storage.StaticProviderRegistry{},
   234  		},
   235  		CloudName: "dummy",
   236  		Cloud: cloud.Cloud{
   237  			Type:      "dummy",
   238  			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
   239  		},
   240  		ControllerInheritedConfig: controllerInheritedConfigIn,
   241  		MongoInfo:                 statetesting.NewMongoInfo(),
   242  		MongoDialOpts:             mongotest.DialOpts(),
   243  	})
   244  	c.Assert(err, jc.ErrorIsNil)
   245  	c.Assert(st, gc.NotNil)
   246  	modelTag := st.ModelTag()
   247  	c.Assert(modelTag.Id(), gc.Equals, uuid)
   248  	err = st.Close()
   249  	c.Assert(err, jc.ErrorIsNil)
   250  
   251  	s.openState(c, modelTag)
   252  
   253  	controllerInheritedConfig, err := state.ReadSettings(s.State, state.GlobalSettingsC, state.ControllerInheritedSettingsGlobalKey)
   254  	c.Assert(err, jc.ErrorIsNil)
   255  	c.Assert(controllerInheritedConfig.Map(), jc.DeepEquals, controllerInheritedConfigIn)
   256  
   257  	expected := cfg.AllAttrs()
   258  	for k, v := range config.ConfigDefaults() {
   259  		if _, ok := expected[k]; !ok {
   260  			expected[k] = v
   261  		}
   262  	}
   263  	// Config as read from state has resources tags coerced to a map.
   264  	expected["resource-tags"] = map[string]string{}
   265  	cfg, err = s.State.ModelConfig()
   266  	c.Assert(err, jc.ErrorIsNil)
   267  	c.Assert(cfg.AllAttrs(), jc.DeepEquals, expected)
   268  }
   269  
   270  func (s *InitializeSuite) TestDoubleInitializeConfig(c *gc.C) {
   271  	cfg := testing.ModelConfig(c)
   272  	owner := names.NewLocalUserTag("initialize-admin")
   273  
   274  	mgoInfo := statetesting.NewMongoInfo()
   275  	dialOpts := mongotest.DialOpts()
   276  	controllerCfg := testing.FakeControllerConfig()
   277  
   278  	args := state.InitializeParams{
   279  		Clock:            clock.WallClock,
   280  		ControllerConfig: controllerCfg,
   281  		ControllerModelArgs: state.ModelArgs{
   282  			CloudName:               "dummy",
   283  			Owner:                   owner,
   284  			Config:                  cfg,
   285  			StorageProviderRegistry: storage.StaticProviderRegistry{},
   286  		},
   287  		CloudName: "dummy",
   288  		Cloud: cloud.Cloud{
   289  			Type:      "dummy",
   290  			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
   291  		},
   292  		MongoInfo:     mgoInfo,
   293  		MongoDialOpts: dialOpts,
   294  	}
   295  	st, err := state.Initialize(args)
   296  	c.Assert(err, jc.ErrorIsNil)
   297  	err = st.Close()
   298  	c.Check(err, jc.ErrorIsNil)
   299  
   300  	st, err = state.Initialize(args)
   301  	c.Check(err, gc.ErrorMatches, "already initialized")
   302  	if !c.Check(st, gc.IsNil) {
   303  		err = st.Close()
   304  		c.Check(err, jc.ErrorIsNil)
   305  	}
   306  }
   307  
   308  func (s *InitializeSuite) TestModelConfigWithAdminSecret(c *gc.C) {
   309  	update := map[string]interface{}{"admin-secret": "foo"}
   310  	remove := []string{}
   311  	s.testBadModelConfig(c, update, remove, "admin-secret should never be written to the state")
   312  }
   313  
   314  func (s *InitializeSuite) TestModelConfigWithCAPrivateKey(c *gc.C) {
   315  	update := map[string]interface{}{"ca-private-key": "foo"}
   316  	remove := []string{}
   317  	s.testBadModelConfig(c, update, remove, "ca-private-key should never be written to the state")
   318  }
   319  
   320  func (s *InitializeSuite) TestModelConfigWithoutAgentVersion(c *gc.C) {
   321  	update := map[string]interface{}{}
   322  	remove := []string{"agent-version"}
   323  	s.testBadModelConfig(c, update, remove, "agent-version must always be set in state")
   324  }
   325  
   326  func (s *InitializeSuite) testBadModelConfig(c *gc.C, update map[string]interface{}, remove []string, expect string) {
   327  	good := testing.CustomModelConfig(c, testing.Attrs{"uuid": testing.ModelTag.Id()})
   328  	bad, err := good.Apply(update)
   329  	c.Assert(err, jc.ErrorIsNil)
   330  	bad, err = bad.Remove(remove)
   331  	c.Assert(err, jc.ErrorIsNil)
   332  
   333  	owner := names.NewLocalUserTag("initialize-admin")
   334  	controllerCfg := testing.FakeControllerConfig()
   335  
   336  	args := state.InitializeParams{
   337  		Clock:            clock.WallClock,
   338  		ControllerConfig: controllerCfg,
   339  		ControllerModelArgs: state.ModelArgs{
   340  			CloudName:               "dummy",
   341  			CloudRegion:             "dummy-region",
   342  			Owner:                   owner,
   343  			Config:                  bad,
   344  			StorageProviderRegistry: storage.StaticProviderRegistry{},
   345  		},
   346  		CloudName: "dummy",
   347  		Cloud: cloud.Cloud{
   348  			Type:      "dummy",
   349  			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
   350  			Regions:   []cloud.Region{{Name: "dummy-region"}},
   351  		},
   352  		MongoInfo:     statetesting.NewMongoInfo(),
   353  		MongoDialOpts: mongotest.DialOpts(),
   354  	}
   355  	_, err = state.Initialize(args)
   356  	c.Assert(err, gc.ErrorMatches, expect)
   357  
   358  	args.ControllerModelArgs.Config = good
   359  	st, err := state.Initialize(args)
   360  	c.Assert(err, jc.ErrorIsNil)
   361  	st.Close()
   362  
   363  	s.openState(c, st.ModelTag())
   364  	err = s.State.UpdateModelConfig(update, remove, nil)
   365  	c.Assert(err, gc.ErrorMatches, expect)
   366  
   367  	// ModelConfig remains inviolate.
   368  	cfg, err := s.State.ModelConfig()
   369  	c.Assert(err, jc.ErrorIsNil)
   370  	goodWithDefaults, err := config.New(config.UseDefaults, good.AllAttrs())
   371  	c.Assert(err, jc.ErrorIsNil)
   372  	c.Assert(cfg.AllAttrs(), jc.DeepEquals, goodWithDefaults.AllAttrs())
   373  }
   374  
   375  func (s *InitializeSuite) TestCloudConfigWithForbiddenValues(c *gc.C) {
   376  	badAttrNames := []string{
   377  		"admin-secret",
   378  		"ca-private-key",
   379  		config.AgentVersionKey,
   380  	}
   381  	for _, attr := range controller.ControllerOnlyConfigAttributes {
   382  		badAttrNames = append(badAttrNames, attr)
   383  	}
   384  
   385  	modelCfg := testing.ModelConfig(c)
   386  	controllerCfg := testing.FakeControllerConfig()
   387  	args := state.InitializeParams{
   388  		Clock:            clock.WallClock,
   389  		ControllerConfig: controllerCfg,
   390  		ControllerModelArgs: state.ModelArgs{
   391  			CloudName:               "dummy",
   392  			Owner:                   names.NewLocalUserTag("initialize-admin"),
   393  			Config:                  modelCfg,
   394  			StorageProviderRegistry: storage.StaticProviderRegistry{},
   395  		},
   396  		CloudName: "dummy",
   397  		Cloud: cloud.Cloud{
   398  			Type:      "dummy",
   399  			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
   400  		},
   401  		MongoInfo:     statetesting.NewMongoInfo(),
   402  		MongoDialOpts: mongotest.DialOpts(),
   403  	}
   404  
   405  	for _, badAttrName := range badAttrNames {
   406  		badAttrs := map[string]interface{}{badAttrName: "foo"}
   407  		args.ControllerInheritedConfig = badAttrs
   408  		_, err := state.Initialize(args)
   409  		c.Assert(err, gc.ErrorMatches, "local cloud config cannot contain .*")
   410  	}
   411  }
   412  
   413  func (s *InitializeSuite) TestInitializeWithCloudRegionConfig(c *gc.C) {
   414  	cfg := testing.ModelConfig(c)
   415  	uuid := cfg.UUID()
   416  
   417  	// Phony region-config
   418  	regionInheritedConfigIn := cloud.RegionConfig{
   419  		"a-region": cloud.Attrs{
   420  			"a-key": "a-value",
   421  		},
   422  		"b-region": cloud.Attrs{
   423  			"b-key": "b-value",
   424  		},
   425  	}
   426  	owner := names.NewLocalUserTag("initialize-admin")
   427  	controllerCfg := testing.FakeControllerConfig()
   428  
   429  	st, err := state.Initialize(state.InitializeParams{
   430  		Clock:            clock.WallClock,
   431  		ControllerConfig: controllerCfg,
   432  		ControllerModelArgs: state.ModelArgs{
   433  			CloudName:               "dummy",
   434  			Owner:                   owner,
   435  			Config:                  cfg,
   436  			StorageProviderRegistry: storage.StaticProviderRegistry{},
   437  		},
   438  		CloudName: "dummy",
   439  		Cloud: cloud.Cloud{
   440  			Type:         "dummy",
   441  			AuthTypes:    []cloud.AuthType{cloud.EmptyAuthType},
   442  			RegionConfig: regionInheritedConfigIn, // Init with phony region-config
   443  		},
   444  		MongoInfo:     statetesting.NewMongoInfo(),
   445  		MongoDialOpts: mongotest.DialOpts(),
   446  	})
   447  	c.Assert(err, jc.ErrorIsNil)
   448  	c.Assert(st, gc.NotNil)
   449  	modelTag := st.ModelTag()
   450  	c.Assert(modelTag.Id(), gc.Equals, uuid)
   451  	err = st.Close()
   452  	c.Assert(err, jc.ErrorIsNil)
   453  
   454  	s.openState(c, modelTag)
   455  
   456  	for k := range regionInheritedConfigIn {
   457  		// Query for config for each region
   458  		regionInheritedConfig, err := state.ReadSettings(
   459  			s.State, state.GlobalSettingsC,
   460  			"dummy#"+k)
   461  		c.Assert(err, jc.ErrorIsNil)
   462  		c.Assert(
   463  			cloud.Attrs(regionInheritedConfig.Map()),
   464  			jc.DeepEquals,
   465  			regionInheritedConfigIn[k])
   466  	}
   467  }
   468  
   469  func (s *InitializeSuite) TestInitializeWithCloudRegionMisses(c *gc.C) {
   470  	cfg := testing.ModelConfig(c)
   471  	uuid := cfg.UUID()
   472  	controllerInheritedConfigIn := map[string]interface{}{
   473  		"no-proxy": "local",
   474  	}
   475  	// Phony region-config
   476  	regionInheritedConfigIn := cloud.RegionConfig{
   477  		"a-region": cloud.Attrs{
   478  			"no-proxy": "a-value",
   479  		},
   480  		"b-region": cloud.Attrs{
   481  			"no-proxy": "b-value",
   482  		},
   483  	}
   484  	owner := names.NewLocalUserTag("initialize-admin")
   485  	controllerCfg := testing.FakeControllerConfig()
   486  
   487  	st, err := state.Initialize(state.InitializeParams{
   488  		Clock:            clock.WallClock,
   489  		ControllerConfig: controllerCfg,
   490  		ControllerModelArgs: state.ModelArgs{
   491  			CloudName:               "dummy",
   492  			Owner:                   owner,
   493  			Config:                  cfg,
   494  			StorageProviderRegistry: storage.StaticProviderRegistry{},
   495  		},
   496  		CloudName: "dummy",
   497  		Cloud: cloud.Cloud{
   498  			Type:         "dummy",
   499  			AuthTypes:    []cloud.AuthType{cloud.EmptyAuthType},
   500  			RegionConfig: regionInheritedConfigIn, // Init with phony region-config
   501  		},
   502  		ControllerInheritedConfig: controllerInheritedConfigIn,
   503  		MongoInfo:                 statetesting.NewMongoInfo(),
   504  		MongoDialOpts:             mongotest.DialOpts(),
   505  	})
   506  	c.Assert(err, jc.ErrorIsNil)
   507  	c.Assert(st, gc.NotNil)
   508  	modelTag := st.ModelTag()
   509  	c.Assert(modelTag.Id(), gc.Equals, uuid)
   510  	err = st.Close()
   511  	c.Assert(err, jc.ErrorIsNil)
   512  
   513  	s.openState(c, modelTag)
   514  
   515  	var attrs map[string]interface{}
   516  	rspec := &environs.RegionSpec{Cloud: "dummy", Region: "c-region"}
   517  	got, err := s.State.ComposeNewModelConfig(attrs, rspec)
   518  	c.Check(err, jc.ErrorIsNil)
   519  	c.Assert(got["no-proxy"], gc.Equals, "local")
   520  }
   521  
   522  func (s *InitializeSuite) TestInitializeWithCloudRegionHits(c *gc.C) {
   523  	cfg := testing.ModelConfig(c)
   524  	uuid := cfg.UUID()
   525  
   526  	controllerInheritedConfigIn := map[string]interface{}{
   527  		"no-proxy": "local",
   528  	}
   529  	// Phony region-config
   530  	regionInheritedConfigIn := cloud.RegionConfig{
   531  		"a-region": cloud.Attrs{
   532  			"no-proxy": "a-value",
   533  		},
   534  		"b-region": cloud.Attrs{
   535  			"no-proxy": "b-value",
   536  		},
   537  	}
   538  	owner := names.NewLocalUserTag("initialize-admin")
   539  	controllerCfg := testing.FakeControllerConfig()
   540  
   541  	st, err := state.Initialize(state.InitializeParams{
   542  		Clock:            clock.WallClock,
   543  		ControllerConfig: controllerCfg,
   544  		ControllerModelArgs: state.ModelArgs{
   545  			CloudName:               "dummy",
   546  			Owner:                   owner,
   547  			Config:                  cfg,
   548  			StorageProviderRegistry: storage.StaticProviderRegistry{},
   549  		},
   550  		CloudName: "dummy",
   551  		Cloud: cloud.Cloud{
   552  			Type:         "dummy",
   553  			AuthTypes:    []cloud.AuthType{cloud.EmptyAuthType},
   554  			RegionConfig: regionInheritedConfigIn, // Init with phony region-config
   555  		},
   556  		ControllerInheritedConfig: controllerInheritedConfigIn,
   557  		MongoInfo:                 statetesting.NewMongoInfo(),
   558  		MongoDialOpts:             mongotest.DialOpts(),
   559  	})
   560  	c.Assert(err, jc.ErrorIsNil)
   561  	c.Assert(st, gc.NotNil)
   562  	modelTag := st.ModelTag()
   563  	c.Assert(modelTag.Id(), gc.Equals, uuid)
   564  	err = st.Close()
   565  	c.Assert(err, jc.ErrorIsNil)
   566  
   567  	s.openState(c, modelTag)
   568  
   569  	var attrs map[string]interface{}
   570  	for r := range regionInheritedConfigIn {
   571  		rspec := &environs.RegionSpec{Cloud: "dummy", Region: r}
   572  		got, err := s.State.ComposeNewModelConfig(attrs, rspec)
   573  		c.Check(err, jc.ErrorIsNil)
   574  		c.Assert(got["no-proxy"], gc.Equals, regionInheritedConfigIn[r]["no-proxy"])
   575  	}
   576  }