func (*volumesSuite) testVolumeParams(c *gc.C, volumeParams *state.VolumeParams, info *state.VolumeInfo) { tag := names.NewVolumeTag("100") p, err := storagecommon.VolumeParams( &fakeVolume{tag: tag, params: volumeParams, info: info}, nil, // StorageInstance testing.ModelTag.Id(), testing.ControllerTag.Id(), testing.CustomModelConfig(c, testing.Attrs{ "resource-tags": "a=b c=", }), &fakePoolManager{}, provider.CommonStorageProviders(), ) c.Assert(err, jc.ErrorIsNil) c.Assert(p, jc.DeepEquals, params.VolumeParams{ VolumeTag: "volume-100", Provider: "loop", Size: 1024, Tags: map[string]string{ tags.JujuController: testing.ControllerTag.Id(), tags.JujuModel: testing.ModelTag.Id(), "a": "b", "c": "", }, }) }
func (config MachineManifoldConfig) newWorker(a agent.Agent, apiCaller base.APICaller) (worker.Worker, error) { if config.Clock == nil { return nil, dependency.ErrMissing } cfg := a.CurrentConfig() api, err := storageprovisioner.NewState(apiCaller, cfg.Tag()) if err != nil { return nil, errors.Trace(err) } tag, ok := cfg.Tag().(names.MachineTag) if !ok { return nil, errors.Errorf("this manifold may only be used inside a machine agent") } storageDir := filepath.Join(cfg.DataDir(), "storage") w, err := NewStorageProvisioner(Config{ Scope: tag, StorageDir: storageDir, Volumes: api, Filesystems: api, Life: api, Registry: provider.CommonStorageProviders(), Machines: api, Status: api, Clock: config.Clock, }) if err != nil { return nil, errors.Trace(err) } return w, nil }
func StorageProviders() storage.ProviderRegistry { return storage.ChainedProviderRegistry{ storage.StaticProviderRegistry{ map[storage.ProviderType]storage.Provider{ "static": &dummystorage.StorageProvider{IsDynamic: false}, "environscoped": &dummystorage.StorageProvider{ StorageScope: storage.ScopeEnviron, IsDynamic: true, }, "environscoped-block": &dummystorage.StorageProvider{ StorageScope: storage.ScopeEnviron, IsDynamic: true, SupportsFunc: func(k storage.StorageKind) bool { return k == storage.StorageKindBlock }, }, "machinescoped": &dummystorage.StorageProvider{ StorageScope: storage.ScopeMachine, IsDynamic: true, }, }, }, provider.CommonStorageProviders(), } }
func (*volumesSuite) TestVolumeParamsStorageTags(c *gc.C) { volumeTag := names.NewVolumeTag("100") storageTag := names.NewStorageTag("mystore/0") unitTag := names.NewUnitTag("mysql/123") p, err := storagecommon.VolumeParams( &fakeVolume{tag: volumeTag, params: &state.VolumeParams{ Pool: "loop", Size: 1024, }}, &fakeStorageInstance{tag: storageTag, owner: unitTag}, testing.ModelTag.Id(), testing.ControllerTag.Id(), testing.CustomModelConfig(c, nil), &fakePoolManager{}, provider.CommonStorageProviders(), ) c.Assert(err, jc.ErrorIsNil) c.Assert(p, jc.DeepEquals, params.VolumeParams{ VolumeTag: "volume-100", Provider: "loop", Size: 1024, Tags: map[string]string{ tags.JujuController: testing.ControllerTag.Id(), tags.JujuModel: testing.ModelTag.Id(), tags.JujuStorageInstance: "mystore/0", tags.JujuStorageOwner: "mysql/123", }, }) }
func (s *poolSuite) registerProviders(c *gc.C) { common := provider.CommonStorageProviders() for _, providerType := range common.StorageProviderTypes() { p, err := common.StorageProvider(providerType) c.Assert(err, jc.ErrorIsNil) s.registry.Providers[providerType] = p } }
func (s *assignCleanSuite) SetUpTest(c *gc.C) { c.Logf("assignment policy for this test: %q", s.policy) s.ConnSuite.SetUpTest(c) wordpress := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) s.wordpress = wordpress pm := poolmanager.New(state.NewStateSettings(s.State), provider.CommonStorageProviders()) _, err := pm.Create("loop-pool", provider.LoopProviderType, map[string]interface{}{}) c.Assert(err, jc.ErrorIsNil) }
func (s *factorySuite) SetUpTest(c *gc.C) { s.NewPolicy = func(*state.State) state.Policy { return &statetesting.MockPolicy{ GetStorageProviderRegistry: func() (storage.ProviderRegistry, error) { return provider.CommonStorageProviders(), nil }, } } s.StateSuite.SetUpTest(c) s.Factory = factory.NewFactory(s.State) }
func (s *MigrationImportSuite) TestStoragePools(c *gc.C) { pm := poolmanager.New(state.NewStateSettings(s.State), provider.CommonStorageProviders()) _, err := pm.Create("test-pool", provider.LoopProviderType, map[string]interface{}{ "value": 42, }) c.Assert(err, jc.ErrorIsNil) _, newSt := s.importModel(c) pm = poolmanager.New(state.NewStateSettings(newSt), provider.CommonStorageProviders()) pools, err := pm.List() c.Assert(err, jc.ErrorIsNil) c.Assert(pools, gc.HasLen, 1) pool := pools[0] c.Assert(pool.Name(), gc.Equals, "test-pool") c.Assert(pool.Provider(), gc.Equals, provider.LoopProviderType) c.Assert(pool.Attrs(), jc.DeepEquals, map[string]interface{}{ "value": 42, }) }
func (s *providerCommonSuite) TestCommonProvidersExported(c *gc.C) { registry := provider.CommonStorageProviders() var common []storage.ProviderType for _, pType := range registry.StorageProviderTypes() { common = append(common, pType) p, err := registry.StorageProvider(pType) c.Assert(err, jc.ErrorIsNil) c.Assert(p, gc.NotNil) } c.Assert(common, jc.SameContents, []storage.ProviderType{ provider.LoopProviderType, provider.RootfsProviderType, provider.TmpfsProviderType, }) }
func (s *internalStateSuite) SetUpTest(c *gc.C) { s.MgoSuite.SetUpTest(c) s.BaseSuite.SetUpTest(c) s.owner = names.NewLocalUserTag("test-admin") // Copied from NewMongoInfo (due to import loops). info := &mongo.MongoInfo{ Info: mongo.Info{ Addrs: []string{jujutesting.MgoServer.Addr()}, CACert: testing.CACert, }, } modelCfg := testing.ModelConfig(c) controllerCfg := testing.FakeControllerConfig() st, err := Initialize(InitializeParams{ Clock: clock.WallClock, ControllerConfig: controllerCfg, ControllerModelArgs: ModelArgs{ CloudName: "dummy", CloudRegion: "dummy-region", Owner: s.owner, Config: modelCfg, StorageProviderRegistry: provider.CommonStorageProviders(), }, CloudName: "dummy", Cloud: cloud.Cloud{ Type: "dummy", AuthTypes: []cloud.AuthType{cloud.EmptyAuthType}, Regions: []cloud.Region{ cloud.Region{ Name: "dummy-region", }, }, }, MongoInfo: info, MongoDialOpts: mongotest.DialOpts(), NewPolicy: func(*State) Policy { return internalStatePolicy{} }, }) c.Assert(err, jc.ErrorIsNil) s.state = st s.AddCleanup(func(*gc.C) { s.state.Close() }) }
// MakeModel creates an model with specified params, // filling in sane defaults for missing values. If params is nil, // defaults are used for all values. // // By default the new model shares the same owner as the calling // Factory's model. func (factory *Factory) MakeModel(c *gc.C, params *ModelParams) *state.State { if params == nil { params = new(ModelParams) } if params.Name == "" { params.Name = uniqueString("testenv") } if params.CloudName == "" { params.CloudName = "dummy" } if params.CloudRegion == "" { params.CloudRegion = "dummy-region" } if params.Owner == nil { origEnv, err := factory.st.Model() c.Assert(err, jc.ErrorIsNil) params.Owner = origEnv.Owner() } if params.StorageProviderRegistry == nil { params.StorageProviderRegistry = provider.CommonStorageProviders() } // It only makes sense to make an model with the same provider // as the initial model, or things will break elsewhere. currentCfg, err := factory.st.ModelConfig() c.Assert(err, jc.ErrorIsNil) uuid, err := utils.NewUUID() c.Assert(err, jc.ErrorIsNil) cfg := testing.CustomModelConfig(c, testing.Attrs{ "name": params.Name, "uuid": uuid.String(), "type": currentCfg.Type(), }.Merge(params.ConfigAttrs)) _, st, err := factory.st.NewModel(state.ModelArgs{ CloudName: params.CloudName, CloudRegion: params.CloudRegion, CloudCredential: params.CloudCredential, Config: cfg, Owner: params.Owner.(names.UserTag), StorageProviderRegistry: params.StorageProviderRegistry, }) c.Assert(err, jc.ErrorIsNil) return st }
func (internalStatePolicy) StorageProviderRegistry() (storage.ProviderRegistry, error) { return provider.CommonStorageProviders(), nil }
// NewStorageProviderRegistry returns a storage.ProviderRegistry that chains // the provided Environ with the common storage providers. func NewStorageProviderRegistry(env environs.Environ) storage.ProviderRegistry { return storage.ChainedProviderRegistry{env, provider.CommonStorageProviders()} }
func (s *provisionerSuite) TestSetInstanceInfo(c *gc.C) { pm := poolmanager.New(state.NewStateSettings(s.State), provider.CommonStorageProviders()) _, err := pm.Create("loop-pool", provider.LoopProviderType, map[string]interface{}{"foo": "bar"}) c.Assert(err, jc.ErrorIsNil) // Create a fresh machine, since machine 0 is already provisioned. template := state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, Volumes: []state.MachineVolumeParams{{ Volume: state.VolumeParams{ Pool: "loop-pool", Size: 123, }}, }, } notProvisionedMachine, err := s.State.AddOneMachine(template) c.Assert(err, jc.ErrorIsNil) apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag().(names.MachineTag)) c.Assert(err, jc.ErrorIsNil) instanceId, err := apiMachine.InstanceId() c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned) c.Assert(err, gc.ErrorMatches, "machine 1 not provisioned") c.Assert(instanceId, gc.Equals, instance.Id("")) hwChars := instance.MustParseHardware("cores=123", "mem=4G") volumes := []params.Volume{{ VolumeTag: "volume-1-0", Info: params.VolumeInfo{ VolumeId: "vol-123", Size: 124, }, }} volumeAttachments := map[string]params.VolumeAttachmentInfo{ "volume-1-0": { DeviceName: "xvdf1", }, } err = apiMachine.SetInstanceInfo( "i-will", "fake_nonce", &hwChars, nil, volumes, volumeAttachments, ) c.Assert(err, jc.ErrorIsNil) instanceId, err = apiMachine.InstanceId() c.Assert(err, jc.ErrorIsNil) c.Assert(instanceId, gc.Equals, instance.Id("i-will")) // Try it again - should fail. err = apiMachine.SetInstanceInfo("i-wont", "fake", nil, nil, nil, nil) c.Assert(err, gc.ErrorMatches, `cannot record provisioning info for "i-wont": cannot set instance data for machine "1": already set`) // Now try to get machine 0's instance id. apiMachine, err = s.provisioner.Machine(s.machine.Tag().(names.MachineTag)) c.Assert(err, jc.ErrorIsNil) instanceId, err = apiMachine.InstanceId() c.Assert(err, jc.ErrorIsNil) c.Assert(instanceId, gc.Equals, instance.Id("i-manager")) // Now check volumes and volume attachments. volume, err := s.State.Volume(names.NewVolumeTag("1/0")) c.Assert(err, jc.ErrorIsNil) volumeInfo, err := volume.Info() c.Assert(err, jc.ErrorIsNil) c.Assert(volumeInfo, gc.Equals, state.VolumeInfo{ VolumeId: "vol-123", Pool: "loop-pool", Size: 124, }) stateVolumeAttachments, err := s.State.MachineVolumeAttachments(names.NewMachineTag("1")) c.Assert(err, jc.ErrorIsNil) c.Assert(stateVolumeAttachments, gc.HasLen, 1) volumeAttachmentInfo, err := stateVolumeAttachments[0].Info() c.Assert(err, jc.ErrorIsNil) c.Assert(volumeAttachmentInfo, gc.Equals, state.VolumeAttachmentInfo{ DeviceName: "xvdf1", }) }
func (s *bootstrapSuite) TestInitializeState(c *gc.C) { dataDir := c.MkDir() lxcFakeNetConfig := filepath.Join(c.MkDir(), "lxc-net") netConf := []byte(` # comments ignored LXC_BR= ignored LXC_ADDR = "fooo" LXC_BRIDGE="foobar" # detected anything else ignored LXC_BRIDGE="ignored"`[1:]) err := ioutil.WriteFile(lxcFakeNetConfig, netConf, 0644) c.Assert(err, jc.ErrorIsNil) c.Assert(err, jc.ErrorIsNil) s.PatchValue(&network.InterfaceByNameAddrs, func(name string) ([]net.Addr, error) { if name == "foobar" { // The addresses on the LXC bridge return []net.Addr{ &net.IPAddr{IP: net.IPv4(10, 0, 3, 1)}, &net.IPAddr{IP: net.IPv4(10, 0, 3, 4)}, }, nil } else if name == network.DefaultLXDBridge { // The addresses on the LXD bridge return []net.Addr{ &net.IPAddr{IP: net.IPv4(10, 0, 4, 1)}, &net.IPAddr{IP: net.IPv4(10, 0, 4, 4)}, }, nil } c.Fatalf("unknown bridge in testing: %v", name) return nil, nil }) s.PatchValue(&network.LXCNetDefaultConfig, lxcFakeNetConfig) configParams := agent.AgentConfigParams{ Paths: agent.Paths{DataDir: dataDir}, Tag: names.NewMachineTag("0"), UpgradedToVersion: jujuversion.Current, StateAddresses: []string{s.mgoInst.Addr()}, CACert: testing.CACert, Password: testing.DefaultMongoPassword, Controller: testing.ControllerTag, Model: testing.ModelTag, } servingInfo := params.StateServingInfo{ Cert: testing.ServerCert, PrivateKey: testing.ServerKey, CAPrivateKey: testing.CAKey, APIPort: 1234, StatePort: s.mgoInst.Port(), SystemIdentity: "def456", } cfg, err := agent.NewStateMachineConfig(configParams, servingInfo) c.Assert(err, jc.ErrorIsNil) _, available := cfg.StateServingInfo() c.Assert(available, jc.IsTrue) expectBootstrapConstraints := constraints.MustParse("mem=1024M") expectModelConstraints := constraints.MustParse("mem=512M") expectHW := instance.MustParseHardware("mem=2048M") initialAddrs := network.NewAddresses( "zeroonetwothree", "0.1.2.3", "10.0.3.1", // lxc bridge address filtered. "10.0.3.4", // lxc bridge address filtered (-"-). "10.0.3.3", // not a lxc bridge address "10.0.4.1", // lxd bridge address filtered. "10.0.4.4", // lxd bridge address filtered. "10.0.4.5", // not an lxd bridge address ) filteredAddrs := network.NewAddresses( "zeroonetwothree", "0.1.2.3", "10.0.3.3", "10.0.4.5", ) modelAttrs := testing.FakeConfig().Merge(testing.Attrs{ "agent-version": jujuversion.Current.String(), "not-for-hosted": "foo", }) modelCfg, err := config.New(config.NoDefaults, modelAttrs) c.Assert(err, jc.ErrorIsNil) controllerCfg := testing.FakeControllerConfig() hostedModelUUID := utils.MustNewUUID().String() hostedModelConfigAttrs := map[string]interface{}{ "name": "hosted", "uuid": hostedModelUUID, } controllerInheritedConfig := map[string]interface{}{ "apt-mirror": "http://mirror", "no-proxy": "value", } regionConfig := cloud.RegionConfig{ "some-region": cloud.Attrs{ "no-proxy": "a-value", }, } var envProvider fakeProvider args := agentbootstrap.InitializeStateParams{ StateInitializationParams: instancecfg.StateInitializationParams{ BootstrapMachineConstraints: expectBootstrapConstraints, BootstrapMachineInstanceId: "i-bootstrap", BootstrapMachineHardwareCharacteristics: &expectHW, ControllerCloud: cloud.Cloud{ Type: "dummy", AuthTypes: []cloud.AuthType{cloud.EmptyAuthType}, Regions: []cloud.Region{{Name: "dummy-region"}}, RegionConfig: regionConfig, }, ControllerCloudName: "dummy", ControllerCloudRegion: "dummy-region", ControllerConfig: controllerCfg, ControllerModelConfig: modelCfg, ModelConstraints: expectModelConstraints, ControllerInheritedConfig: controllerInheritedConfig, HostedModelConfig: hostedModelConfigAttrs, }, BootstrapMachineAddresses: initialAddrs, BootstrapMachineJobs: []multiwatcher.MachineJob{multiwatcher.JobManageModel}, SharedSecret: "abc123", Provider: func(t string) (environs.EnvironProvider, error) { c.Assert(t, gc.Equals, "dummy") return &envProvider, nil }, StorageProviderRegistry: provider.CommonStorageProviders(), } adminUser := names.NewLocalUserTag("agent-admin") st, m, err := agentbootstrap.InitializeState( adminUser, cfg, args, mongotest.DialOpts(), state.NewPolicyFunc(nil), ) c.Assert(err, jc.ErrorIsNil) defer st.Close() err = cfg.Write() c.Assert(err, jc.ErrorIsNil) // Check that the environment has been set up. model, err := st.Model() c.Assert(err, jc.ErrorIsNil) c.Assert(model.UUID(), gc.Equals, modelCfg.UUID()) // Check that initial admin user has been set up correctly. modelTag := model.Tag().(names.ModelTag) controllerTag := names.NewControllerTag(controllerCfg.ControllerUUID()) s.assertCanLogInAsAdmin(c, modelTag, controllerTag, testing.DefaultMongoPassword) user, err := st.User(model.Owner()) c.Assert(err, jc.ErrorIsNil) c.Assert(user.PasswordValid(testing.DefaultMongoPassword), jc.IsTrue) // Check controller config controllerCfg, err = st.ControllerConfig() c.Assert(err, jc.ErrorIsNil) c.Assert(controllerCfg, jc.DeepEquals, controller.Config{ "controller-uuid": testing.ControllerTag.Id(), "ca-cert": testing.CACert, "state-port": 1234, "api-port": 17777, "set-numa-control-policy": false, }) // Check that controller model configuration has been added, and // model constraints set. newModelCfg, err := st.ModelConfig() c.Assert(err, jc.ErrorIsNil) // Add in the cloud attributes. expectedCfg, err := config.New(config.UseDefaults, modelAttrs) c.Assert(err, jc.ErrorIsNil) expectedAttrs := expectedCfg.AllAttrs() expectedAttrs["apt-mirror"] = "http://mirror" expectedAttrs["no-proxy"] = "value" c.Assert(newModelCfg.AllAttrs(), jc.DeepEquals, expectedAttrs) gotModelConstraints, err := st.ModelConstraints() c.Assert(err, jc.ErrorIsNil) c.Assert(gotModelConstraints, gc.DeepEquals, expectModelConstraints) // Check that the hosted model has been added, model constraints // set, and its config contains the same authorized-keys as the // controller model. hostedModelSt, err := st.ForModel(names.NewModelTag(hostedModelUUID)) c.Assert(err, jc.ErrorIsNil) defer hostedModelSt.Close() gotModelConstraints, err = hostedModelSt.ModelConstraints() c.Assert(err, jc.ErrorIsNil) c.Assert(gotModelConstraints, gc.DeepEquals, expectModelConstraints) hostedModel, err := hostedModelSt.Model() c.Assert(err, jc.ErrorIsNil) c.Assert(hostedModel.Name(), gc.Equals, "hosted") c.Assert(hostedModel.CloudRegion(), gc.Equals, "dummy-region") hostedCfg, err := hostedModelSt.ModelConfig() c.Assert(err, jc.ErrorIsNil) _, hasUnexpected := hostedCfg.AllAttrs()["not-for-hosted"] c.Assert(hasUnexpected, jc.IsFalse) c.Assert(hostedCfg.AuthorizedKeys(), gc.Equals, newModelCfg.AuthorizedKeys()) // Check that the bootstrap machine looks correct. c.Assert(m.Id(), gc.Equals, "0") c.Assert(m.Jobs(), gc.DeepEquals, []state.MachineJob{state.JobManageModel}) c.Assert(m.Series(), gc.Equals, series.HostSeries()) c.Assert(m.CheckProvisioned(agent.BootstrapNonce), jc.IsTrue) c.Assert(m.Addresses(), jc.DeepEquals, filteredAddrs) gotBootstrapConstraints, err := m.Constraints() c.Assert(err, jc.ErrorIsNil) c.Assert(gotBootstrapConstraints, gc.DeepEquals, expectBootstrapConstraints) c.Assert(err, jc.ErrorIsNil) gotHW, err := m.HardwareCharacteristics() c.Assert(err, jc.ErrorIsNil) c.Assert(*gotHW, gc.DeepEquals, expectHW) // Check that the API host ports are initialised correctly. apiHostPorts, err := st.APIHostPorts() c.Assert(err, jc.ErrorIsNil) c.Assert(apiHostPorts, jc.DeepEquals, [][]network.HostPort{ network.AddressesWithPort(filteredAddrs, 1234), }) // Check that the state serving info is initialised correctly. stateServingInfo, err := st.StateServingInfo() c.Assert(err, jc.ErrorIsNil) c.Assert(stateServingInfo, jc.DeepEquals, state.StateServingInfo{ APIPort: 1234, StatePort: s.mgoInst.Port(), Cert: testing.ServerCert, PrivateKey: testing.ServerKey, CAPrivateKey: testing.CAKey, SharedSecret: "abc123", SystemIdentity: "def456", }) // Check that the machine agent's config has been written // and that we can use it to connect to the state. machine0 := names.NewMachineTag("0") newCfg, err := agent.ReadConfig(agent.ConfigPath(dataDir, machine0)) c.Assert(err, jc.ErrorIsNil) c.Assert(newCfg.Tag(), gc.Equals, machine0) info, ok := cfg.MongoInfo() c.Assert(ok, jc.IsTrue) c.Assert(info.Password, gc.Not(gc.Equals), testing.DefaultMongoPassword) st1, err := state.Open(newCfg.Model(), newCfg.Controller(), info, mongotest.DialOpts(), nil) c.Assert(err, jc.ErrorIsNil) defer st1.Close() // Make sure that the hosted model Environ's Create method is called. envProvider.CheckCallNames(c, "PrepareConfig", "Validate", "Open", "Create", ) envProvider.CheckCall(c, 2, "Open", environs.OpenParams{ Cloud: environs.CloudSpec{ Type: "dummy", Name: "dummy", Region: "dummy-region", }, Config: hostedCfg, }) envProvider.CheckCall(c, 3, "Create", environs.CreateParams{ ControllerUUID: controllerCfg.ControllerUUID(), }) }
func (s *bootstrapSuite) TestInitializeStateFailsSecondTime(c *gc.C) { dataDir := c.MkDir() configParams := agent.AgentConfigParams{ Paths: agent.Paths{DataDir: dataDir}, Tag: names.NewMachineTag("0"), UpgradedToVersion: jujuversion.Current, StateAddresses: []string{s.mgoInst.Addr()}, CACert: testing.CACert, Password: testing.DefaultMongoPassword, Controller: testing.ControllerTag, Model: testing.ModelTag, } cfg, err := agent.NewAgentConfig(configParams) c.Assert(err, jc.ErrorIsNil) cfg.SetStateServingInfo(params.StateServingInfo{ APIPort: 5555, StatePort: s.mgoInst.Port(), Cert: "foo", PrivateKey: "bar", SharedSecret: "baz", SystemIdentity: "qux", }) modelAttrs := dummy.SampleConfig().Delete("admin-secret").Merge(testing.Attrs{ "agent-version": jujuversion.Current.String(), }) modelCfg, err := config.New(config.NoDefaults, modelAttrs) c.Assert(err, jc.ErrorIsNil) hostedModelConfigAttrs := map[string]interface{}{ "name": "hosted", "uuid": utils.MustNewUUID().String(), } args := agentbootstrap.InitializeStateParams{ StateInitializationParams: instancecfg.StateInitializationParams{ BootstrapMachineInstanceId: "i-bootstrap", ControllerCloud: cloud.Cloud{ Type: "dummy", AuthTypes: []cloud.AuthType{cloud.EmptyAuthType}, }, ControllerCloudName: "dummy", ControllerConfig: testing.FakeControllerConfig(), ControllerModelConfig: modelCfg, HostedModelConfig: hostedModelConfigAttrs, }, BootstrapMachineJobs: []multiwatcher.MachineJob{multiwatcher.JobManageModel}, SharedSecret: "abc123", Provider: func(t string) (environs.EnvironProvider, error) { return &fakeProvider{}, nil }, StorageProviderRegistry: provider.CommonStorageProviders(), } adminUser := names.NewLocalUserTag("agent-admin") st, _, err := agentbootstrap.InitializeState( adminUser, cfg, args, mongotest.DialOpts(), state.NewPolicyFunc(nil), ) c.Assert(err, jc.ErrorIsNil) st.Close() st, _, err = agentbootstrap.InitializeState( adminUser, cfg, args, mongotest.DialOpts(), state.NewPolicyFunc(nil), ) if err == nil { st.Close() } c.Assert(err, gc.ErrorMatches, "failed to initialize mongo admin user: cannot set admin password: not authorized .*") }