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, 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", }) expectHW := instance.MustParseHardware("mem=2048M") mcfg := agentbootstrap.BootstrapMachineConfig{ BootstrapConstraints: constraints.MustParse("mem=1024M"), Jobs: []multiwatcher.MachineJob{multiwatcher.JobManageModel}, InstanceId: "i-bootstrap", Characteristics: expectHW, } envAttrs := dummy.SampleConfig().Delete("admin-secret").Merge(testing.Attrs{ "agent-version": jujuversion.Current.String(), }) envCfg, err := config.New(config.NoDefaults, envAttrs) c.Assert(err, jc.ErrorIsNil) hostedModelConfigAttrs := map[string]interface{}{ "name": "hosted", "uuid": utils.MustNewUUID().String(), } adminUser := names.NewLocalUserTag("agent-admin") st, _, err := agentbootstrap.InitializeState( adminUser, cfg, envCfg, hostedModelConfigAttrs, mcfg, mongo.DefaultDialOpts(), state.Policy(nil), ) c.Assert(err, jc.ErrorIsNil) st.Close() st, _, err = agentbootstrap.InitializeState(adminUser, cfg, envCfg, nil, mcfg, mongo.DefaultDialOpts(), environs.NewStatePolicy()) if err == nil { st.Close() } c.Assert(err, gc.ErrorMatches, "failed to initialize mongo admin user: cannot set admin password: not authorized .*") }
func (s *bootstrapSuite) TestInitializeStateWithStateServingInfoNotAvailable(c *gc.C) { configParams := agent.AgentConfigParams{ Paths: agent.Paths{DataDir: c.MkDir()}, Tag: names.NewMachineTag("0"), UpgradedToVersion: jujuversion.Current, StateAddresses: []string{s.mgoInst.Addr()}, CACert: testing.CACert, Password: "******", Model: testing.ModelTag, } cfg, err := agent.NewAgentConfig(configParams) c.Assert(err, jc.ErrorIsNil) _, available := cfg.StateServingInfo() c.Assert(available, jc.IsFalse) adminUser := names.NewLocalUserTag("agent-admin") _, _, err = agentbootstrap.InitializeState(adminUser, cfg, nil, nil, agentbootstrap.BootstrapMachineConfig{}, mongo.DefaultDialOpts(), environs.NewStatePolicy()) // InitializeState will fail attempting to get the api port information c.Assert(err, gc.ErrorMatches, "state serving information not available") }
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) s.PatchValue(&network.InterfaceByNameAddrs, func(name string) ([]net.Addr, error) { c.Assert(name, gc.Equals, "foobar") return []net.Addr{ &net.IPAddr{IP: net.IPv4(10, 0, 3, 1)}, &net.IPAddr{IP: net.IPv4(10, 0, 3, 4)}, }, 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, 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 ) mcfg := agentbootstrap.BootstrapMachineConfig{ Addresses: initialAddrs, BootstrapConstraints: expectBootstrapConstraints, ModelConstraints: expectModelConstraints, Jobs: []multiwatcher.MachineJob{multiwatcher.JobManageModel}, InstanceId: "i-bootstrap", Characteristics: expectHW, SharedSecret: "abc123", } filteredAddrs := network.NewAddresses( "zeroonetwothree", "0.1.2.3", "10.0.3.3", ) // Prepare bootstrap config, so we can use it in the state policy. provider, err := environs.Provider("dummy") c.Assert(err, jc.ErrorIsNil) envAttrs := dummy.SampleConfig().Delete("admin-secret").Merge(testing.Attrs{ "agent-version": jujuversion.Current.String(), "not-for-hosted": "foo", }) envCfg, err := config.New(config.NoDefaults, envAttrs) c.Assert(err, jc.ErrorIsNil) envCfg, err = provider.BootstrapConfig(environs.BootstrapConfigParams{Config: envCfg}) c.Assert(err, jc.ErrorIsNil) defer dummy.Reset(c) hostedModelUUID := utils.MustNewUUID().String() hostedModelConfigAttrs := map[string]interface{}{ "name": "hosted", "uuid": hostedModelUUID, } adminUser := names.NewLocalUserTag("agent-admin") st, m, err := agentbootstrap.InitializeState( adminUser, cfg, envCfg, hostedModelConfigAttrs, mcfg, mongo.DefaultDialOpts(), environs.NewStatePolicy(), ) c.Assert(err, jc.ErrorIsNil) defer st.Close() err = cfg.Write() c.Assert(err, jc.ErrorIsNil) // Check that the environment has been set up. env, err := st.Model() c.Assert(err, jc.ErrorIsNil) c.Assert(env.UUID(), gc.Equals, envCfg.UUID()) // Check that initial admin user has been set up correctly. modelTag := env.Tag().(names.ModelTag) s.assertCanLogInAsAdmin(c, modelTag, testing.DefaultMongoPassword) user, err := st.User(env.Owner()) c.Assert(err, jc.ErrorIsNil) c.Assert(user.PasswordValid(testing.DefaultMongoPassword), jc.IsTrue) // Check that controller model configuration has been added, and // model constraints set. newEnvCfg, err := st.ModelConfig() c.Assert(err, jc.ErrorIsNil) c.Assert(newEnvCfg.AllAttrs(), gc.DeepEquals, envCfg.AllAttrs()) gotModelConstraints, err := st.ModelConstraints() c.Assert(err, jc.ErrorIsNil) c.Assert(gotModelConstraints, gc.DeepEquals, expectModelConstraints) // Check that the hosted model has been added, and model constraints // set. 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") hostedCfg, err := hostedModelSt.ModelConfig() c.Assert(err, jc.ErrorIsNil) _, hasUnexpected := hostedCfg.AllAttrs()["not-for-hosted"] c.Assert(hasUnexpected, jc.IsFalse) // 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(), info, mongo.DefaultDialOpts(), environs.NewStatePolicy()) c.Assert(err, jc.ErrorIsNil) defer st1.Close() }
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 .*") }