func (s *machineConfigSuite) TestSecureConnectionDisallowed(c *gc.C) { // StateServingInfo without CAPrivateKey will not allow secure connections. servingInfo := state.StateServingInfo{ PrivateKey: jujutesting.ServerKey, Cert: jujutesting.ServerCert, SharedSecret: "really, really secret", APIPort: 4321, StatePort: 1234, } s.State.SetStateServingInfo(servingInfo) hc := instance.MustParseHardware("mem=4G arch=amd64") apiParams := params.AddMachineParams{ Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, InstanceId: instance.Id("1234"), Nonce: "foo", HardwareCharacteristics: hc, } machines, err := s.APIState.Client().AddMachines([]params.AddMachineParams{apiParams}) c.Assert(err, jc.ErrorIsNil) c.Assert(len(machines), gc.Equals, 1) machineId := machines[0].Machine instanceConfig, err := client.InstanceConfig(s.State, machineId, apiParams.Nonce, "") c.Assert(err, jc.ErrorIsNil) c.Assert(instanceConfig.AgentEnvironment[agent.AllowsSecureConnection], gc.Equals, "false") }
func (s *assignCleanSuite) TestAssignUsingConstraintsToMachine(c *gc.C) { for i, t := range assignUsingConstraintsTests { c.Logf("test %d", i) cons := constraints.MustParse(t.unitConstraints) err := s.State.SetModelConstraints(cons) c.Assert(err, jc.ErrorIsNil) unit, err := s.wordpress.AddUnit() c.Assert(err, jc.ErrorIsNil) m, err := s.State.AddMachine("quantal", state.JobHostUnits) c.Assert(err, jc.ErrorIsNil) if t.hardwareCharacteristics != "none" { hc := instance.MustParseHardware(t.hardwareCharacteristics) err = m.SetProvisioned("inst-id", "fake_nonce", &hc) c.Assert(err, jc.ErrorIsNil) } um, err := s.assignUnit(unit) if t.assignOk { c.Assert(err, jc.ErrorIsNil) c.Assert(um.Id(), gc.Equals, m.Id()) } else { c.Assert(um, gc.IsNil) c.Assert(err, gc.ErrorMatches, eligibleMachinesInUse) // Destroy the machine so it can't be used for the next test. err = m.Destroy() c.Assert(err, jc.ErrorIsNil) } } }
func (s *BootstrapSuite) TestKeepBrokenDoesNoStop(c *gc.C) { innerStorage := newStorage(s, c) stor := &mockStorage{Storage: innerStorage} checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, mcfg *cloudinit.MachineConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { stor.putErr = fmt.Errorf("suddenly a wild blah") return &mockInstance{id: "i-blah"}, &checkHardware, nil, nil } stopInstances := func(instances []instance.Id) error { c.Errorf("unexpected call to StopInstances") return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, stopInstances: stopInstances, config: configGetter(c), } ctx := coretesting.Context(c) _, _, _, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ KeepBroken: true, AvailableTools: tools.List{&tools.Tools{Version: version.Current}}, }) c.Assert(err, gc.ErrorMatches, "cannot save state: suddenly a wild blah") }
func (s *machineConfigSuite) TestMachineConfig(c *gc.C) { addrs := network.NewAddresses("1.2.3.4") hc := instance.MustParseHardware("mem=4G arch=amd64") apiParams := params.AddMachineParams{ Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, InstanceId: instance.Id("1234"), Nonce: "foo", HardwareCharacteristics: hc, Addrs: params.FromNetworkAddresses(addrs), } machines, err := s.APIState.Client().AddMachines([]params.AddMachineParams{apiParams}) c.Assert(err, jc.ErrorIsNil) c.Assert(len(machines), gc.Equals, 1) machineId := machines[0].Machine instanceConfig, err := client.InstanceConfig(s.State, machineId, apiParams.Nonce, "") c.Assert(err, jc.ErrorIsNil) envConfig, err := s.State.EnvironConfig() c.Assert(err, jc.ErrorIsNil) mongoAddrs := s.State.MongoConnectionInfo().Addrs apiAddrs := []string{net.JoinHostPort("localhost", strconv.Itoa(envConfig.APIPort()))} c.Check(instanceConfig.MongoInfo.Addrs, gc.DeepEquals, mongoAddrs) c.Check(instanceConfig.APIInfo.Addrs, gc.DeepEquals, apiAddrs) toolsURL := fmt.Sprintf("https://%s/environment/%s/tools/%s", apiAddrs[0], jujutesting.EnvironmentTag.Id(), instanceConfig.Tools.Version) c.Assert(instanceConfig.Tools.URL, gc.Equals, toolsURL) c.Assert(instanceConfig.AgentEnvironment[agent.AllowsSecureConnection], gc.Equals, "true") }
func (s *machineConfigSuite) TestMachineConfig(c *gc.C) { addrs := network.NewAddresses("1.2.3.4") hc := instance.MustParseHardware("mem=4G arch=amd64") apiParams := params.AddMachineParams{ Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, InstanceId: instance.Id("1234"), Nonce: "foo", HardwareCharacteristics: hc, Addrs: params.FromNetworkAddresses(addrs...), } machines, err := s.APIState.Client().AddMachines([]params.AddMachineParams{apiParams}) c.Assert(err, jc.ErrorIsNil) c.Assert(len(machines), gc.Equals, 1) machineId := machines[0].Machine instanceConfig, err := client.InstanceConfig(s.State, machineId, apiParams.Nonce, "") c.Assert(err, jc.ErrorIsNil) cfg, err := s.State.ControllerConfig() c.Assert(err, jc.ErrorIsNil) apiAddrs := []string{net.JoinHostPort("localhost", strconv.Itoa(cfg.APIPort()))} c.Check(instanceConfig.APIInfo.Addrs, gc.DeepEquals, apiAddrs) toolsURL := fmt.Sprintf("https://%s/model/%s/tools/%s", apiAddrs[0], jujutesting.ModelTag.Id(), instanceConfig.AgentVersion()) c.Assert(instanceConfig.ToolsList().URLs(), jc.DeepEquals, map[version.Binary][]string{ instanceConfig.AgentVersion(): []string{toolsURL}, }) }
func (s *machineConfigSuite) TestMachineConfig(c *gc.C) { addrs := []network.Address{network.NewAddress("1.2.3.4", network.ScopeUnknown)} hc := instance.MustParseHardware("mem=4G arch=amd64") apiParams := params.AddMachineParams{ Jobs: []params.MachineJob{params.JobHostUnits}, InstanceId: instance.Id("1234"), Nonce: "foo", HardwareCharacteristics: hc, Addrs: addrs, } machines, err := s.APIState.Client().AddMachines([]params.AddMachineParams{apiParams}) c.Assert(err, gc.IsNil) c.Assert(len(machines), gc.Equals, 1) machineId := machines[0].Machine machineConfig, err := client.MachineConfig(s.State, machineId, apiParams.Nonce, "") c.Assert(err, gc.IsNil) envConfig, err := s.State.EnvironConfig() c.Assert(err, gc.IsNil) env, err := environs.New(envConfig) c.Assert(err, gc.IsNil) stateInfo, apiInfo, err := env.StateInfo() c.Assert(err, gc.IsNil) c.Check(machineConfig.StateInfo.Addrs, gc.DeepEquals, stateInfo.Addrs) c.Check(machineConfig.APIInfo.Addrs, gc.DeepEquals, apiInfo.Addrs) c.Assert(machineConfig.Tools.URL, gc.Not(gc.Equals), "") }
func (s *machineConfigSuite) TestMachineConfig(c *gc.C) { addrs := []network.Address{network.NewAddress("1.2.3.4", network.ScopeUnknown)} hc := instance.MustParseHardware("mem=4G arch=amd64") apiParams := params.AddMachineParams{ Jobs: []params.MachineJob{params.JobHostUnits}, InstanceId: instance.Id("1234"), Nonce: "foo", HardwareCharacteristics: hc, Addrs: addrs, } machines, err := s.APIState.Client().AddMachines([]params.AddMachineParams{apiParams}) c.Assert(err, gc.IsNil) c.Assert(len(machines), gc.Equals, 1) machineId := machines[0].Machine machineConfig, err := client.MachineConfig(s.State, machineId, apiParams.Nonce, "") c.Assert(err, gc.IsNil) envConfig, err := s.State.EnvironConfig() c.Assert(err, gc.IsNil) mongoAddrs := s.State.MongoConnectionInfo().Addrs apiAddrs := []string{net.JoinHostPort("localhost", strconv.Itoa(envConfig.APIPort()))} c.Check(machineConfig.MongoInfo.Addrs, gc.DeepEquals, mongoAddrs) c.Check(machineConfig.APIInfo.Addrs, gc.DeepEquals, apiAddrs) toolsURL := fmt.Sprintf("https://%s/environment/90168e4c-2f10-4e9c-83c2-feedfacee5a9/tools/%s", apiAddrs[0], machineConfig.Tools.Version) c.Assert(machineConfig.Tools.URL, gc.Equals, toolsURL) }
func (s *BootstrapSuite) TestInitializeEnvironmentToolsNotFound(c *gc.C) { // bootstrap with 1.99.1 but there will be no tools so version will be reset. envcfg, err := s.envcfg.Apply(map[string]interface{}{ "agent-version": "1.99.1", }) c.Assert(err, jc.ErrorIsNil) b64yamlControllerModelConfig := b64yaml(envcfg.AllAttrs()).encode() hw := instance.MustParseHardware("arch=amd64 mem=8G") _, cmd, err := s.initBootstrapCommand( c, nil, "--model-config", b64yamlControllerModelConfig, "--hosted-model-config", s.b64yamlHostedModelConfig, "--instance-id", string(s.instanceId), "--hardware", hw.String(), ) c.Assert(err, jc.ErrorIsNil) err = cmd.Run(nil) c.Assert(err, jc.ErrorIsNil) st, err := state.Open(testing.ModelTag, &mongo.MongoInfo{ Info: mongo.Info{ Addrs: []string{gitjujutesting.MgoServer.Addr()}, CACert: testing.CACert, }, Password: testPassword, }, mongotest.DialOpts(), environs.NewStatePolicy()) c.Assert(err, jc.ErrorIsNil) defer st.Close() cfg, err := st.ModelConfig() c.Assert(err, jc.ErrorIsNil) vers, ok := cfg.AgentVersion() c.Assert(ok, jc.IsTrue) c.Assert(vers.String(), gc.Equals, "1.99.0") }
func (s *withoutStateServerSuite) TestInstanceId(c *gc.C) { // Provision 2 machines first. err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil) c.Assert(err, gc.IsNil) hwChars := instance.MustParseHardware("arch=i386", "mem=4G") err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars) c.Assert(err, gc.IsNil) args := params.Entities{Entities: []params.Entity{ {Tag: s.machines[0].Tag()}, {Tag: s.machines[1].Tag()}, {Tag: s.machines[2].Tag()}, {Tag: "machine-42"}, {Tag: "unit-foo-0"}, {Tag: "service-bar"}, }} result, err := s.provisioner.InstanceId(args) c.Assert(err, gc.IsNil) c.Assert(result, gc.DeepEquals, params.StringResults{ Results: []params.StringResult{ {Result: "i-am"}, {Result: "i-am-not"}, {Error: apiservertesting.NotProvisionedError("2")}, {Error: apiservertesting.NotFoundError("machine 42")}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) }
func (s *withoutStateServerSuite) TestMachinesWithTransientErrors(c *gc.C) { err := s.machines[0].SetStatus(params.StatusStarted, "blah", nil) c.Assert(err, gc.IsNil) err = s.machines[1].SetStatus(params.StatusError, "transient error", params.StatusData{"transient": true, "foo": "bar"}) c.Assert(err, gc.IsNil) err = s.machines[2].SetStatus(params.StatusError, "error", params.StatusData{"transient": false}) c.Assert(err, gc.IsNil) err = s.machines[3].SetStatus(params.StatusError, "error", nil) c.Assert(err, gc.IsNil) // Machine 4 is provisioned but error not reset yet. err = s.machines[4].SetStatus(params.StatusError, "transient error", params.StatusData{"transient": true, "foo": "bar"}) c.Assert(err, gc.IsNil) hwChars := instance.MustParseHardware("arch=i386", "mem=4G") err = s.machines[4].SetProvisioned("i-am", "fake_nonce", &hwChars) c.Assert(err, gc.IsNil) result, err := s.provisioner.MachinesWithTransientErrors() c.Assert(err, gc.IsNil) c.Assert(result, gc.DeepEquals, params.StatusResults{ Results: []params.StatusResult{ {Id: "1", Life: "alive", Status: "error", Info: "transient error", Data: params.StatusData{"transient": true, "foo": "bar"}}, }, }) }
func (s *clientSuite) TestClientAddMachinesWithInstanceIdSomeErrors(c *gc.C) { apiParams := make([]params.AddMachineParams, 3) addrs := network.NewAddresses("1.2.3.4") hc := instance.MustParseHardware("mem=4G") for i := 0; i < 3; i++ { apiParams[i] = params.AddMachineParams{ Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, InstanceId: instance.Id(fmt.Sprintf("1234-%d", i)), Nonce: "foo", HardwareCharacteristics: hc, Addrs: params.FromNetworkAddresses(addrs...), } } // This will cause the last add-machine to fail. apiParams[2].Nonce = "" machines, err := s.APIState.Client().AddMachines(apiParams) c.Assert(err, jc.ErrorIsNil) c.Assert(len(machines), gc.Equals, 3) for i, machineResult := range machines { if i == 2 { c.Assert(machineResult.Error, gc.NotNil) c.Assert(machineResult.Error, gc.ErrorMatches, "cannot add a new machine: cannot add a machine with an instance id and no nonce") } else { c.Assert(machineResult.Machine, gc.DeepEquals, strconv.Itoa(i)) s.checkMachine(c, machineResult.Machine, series.LatestLts(), apiParams[i].Constraints.String()) instanceId := fmt.Sprintf("1234-%d", i) s.checkInstance(c, machineResult.Machine, instanceId, "foo", hc, addrs) } } }
// Create a machine to use. func (s *networkerSuite) setUpMachine(c *gc.C) { var err error s.machine, err = s.State.AddMachine("quantal", state.JobHostUnits) c.Assert(err, gc.IsNil) hwChars := instance.MustParseHardware("arch=i386", "mem=4G") s.machineIfaces = []state.NetworkInterfaceInfo{{ MACAddress: "aa:bb:cc:dd:ee:f0", InterfaceName: "eth0", NetworkName: "net1", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", InterfaceName: "eth1", NetworkName: "net1", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", InterfaceName: "eth1.42", NetworkName: "vlan42", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f0", InterfaceName: "eth0.69", NetworkName: "vlan69", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f2", InterfaceName: "eth2", NetworkName: "net2", IsVirtual: false, Disabled: true, }} err = s.machine.SetInstanceInfo("i-am", "fake_nonce", &hwChars, s.networks, s.machineIfaces) c.Assert(err, gc.IsNil) }
func (s *BootstrapSuite) TestInitializeEnvironmentInvalidOplogSize(c *gc.C) { s.mongoOplogSize = "NaN" hw := instance.MustParseHardware("arch=amd64 mem=8G") _, cmd, err := s.initBootstrapCommand(c, nil, "--env-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId), "--hardware", hw.String()) c.Assert(err, jc.ErrorIsNil) err = cmd.Run(nil) c.Assert(err, gc.ErrorMatches, `invalid oplog size: "NaN"`) }
func (s *BootstrapSuite) TestInitializeEnvironment(c *gc.C) { hw := instance.MustParseHardware("arch=amd64 mem=8G") machConf, cmd, err := s.initBootstrapCommand(c, nil, "--env-config", s.envcfg, "--instance-id", string(s.instanceId), "--hardware", hw.String()) c.Assert(err, gc.IsNil) err = cmd.Run(nil) c.Assert(err, gc.IsNil) c.Assert(s.fakeEnsureMongo.dataDir, gc.Equals, s.dataDir) c.Assert(s.fakeEnsureMongo.initiateCount, gc.Equals, 1) c.Assert(s.fakeEnsureMongo.ensureCount, gc.Equals, 1) c.Assert(s.fakeEnsureMongo.dataDir, gc.Equals, s.dataDir) c.Assert(s.fakeEnsureMongo.oplogSize, gc.Equals, 1234) expectInfo, exists := machConf.StateServingInfo() c.Assert(exists, jc.IsTrue) c.Assert(expectInfo.SharedSecret, gc.Equals, "") servingInfo := s.fakeEnsureMongo.info c.Assert(len(servingInfo.SharedSecret), gc.Not(gc.Equals), 0) servingInfo.SharedSecret = "" c.Assert(servingInfo, jc.DeepEquals, expectInfo) expectDialAddrs := []string{fmt.Sprintf("127.0.0.1:%d", expectInfo.StatePort)} gotDialAddrs := s.fakeEnsureMongo.initiateParams.DialInfo.Addrs c.Assert(gotDialAddrs, gc.DeepEquals, expectDialAddrs) memberHost := fmt.Sprintf("%s:%d", s.bootstrapName, expectInfo.StatePort) c.Assert(s.fakeEnsureMongo.initiateParams.MemberHostPort, gc.Equals, memberHost) c.Assert(s.fakeEnsureMongo.initiateParams.User, gc.Equals, "") c.Assert(s.fakeEnsureMongo.initiateParams.Password, gc.Equals, "") st, err := state.Open(&authentication.MongoInfo{ Info: mongo.Info{ Addrs: []string{gitjujutesting.MgoServer.Addr()}, CACert: testing.CACert, }, Password: testPasswordHash(), }, mongo.DefaultDialOpts(), environs.NewStatePolicy()) c.Assert(err, gc.IsNil) defer st.Close() machines, err := st.AllMachines() c.Assert(err, gc.IsNil) c.Assert(machines, gc.HasLen, 1) instid, err := machines[0].InstanceId() c.Assert(err, gc.IsNil) c.Assert(instid, gc.Equals, instance.Id(string(s.instanceId))) stateHw, err := machines[0].HardwareCharacteristics() c.Assert(err, gc.IsNil) c.Assert(stateHw, gc.NotNil) c.Assert(*stateHw, gc.DeepEquals, hw) cons, err := st.EnvironConstraints() c.Assert(err, gc.IsNil) c.Assert(&cons, jc.Satisfies, constraints.IsEmpty) }
func (s *withoutControllerSuite) TestMachinesWithTransientErrors(c *gc.C) { now := time.Now() sInfo := status.StatusInfo{ Status: status.Started, Message: "blah", Since: &now, } err := s.machines[0].SetStatus(sInfo) c.Assert(err, jc.ErrorIsNil) sInfo = status.StatusInfo{ Status: status.Error, Message: "transient error", Data: map[string]interface{}{"transient": true, "foo": "bar"}, Since: &now, } err = s.machines[1].SetStatus(sInfo) c.Assert(err, jc.ErrorIsNil) sInfo = status.StatusInfo{ Status: status.Error, Message: "error", Data: map[string]interface{}{"transient": false}, Since: &now, } err = s.machines[2].SetStatus(sInfo) c.Assert(err, jc.ErrorIsNil) sInfo = status.StatusInfo{ Status: status.Error, Message: "error", Since: &now, } err = s.machines[3].SetStatus(sInfo) c.Assert(err, jc.ErrorIsNil) // Machine 4 is provisioned but error not reset yet. sInfo = status.StatusInfo{ Status: status.Error, Message: "transient error", Data: map[string]interface{}{"transient": true, "foo": "bar"}, Since: &now, } err = s.machines[4].SetStatus(sInfo) c.Assert(err, jc.ErrorIsNil) hwChars := instance.MustParseHardware("arch=i386", "mem=4G") err = s.machines[4].SetProvisioned("i-am", "fake_nonce", &hwChars) c.Assert(err, jc.ErrorIsNil) result, err := s.provisioner.MachinesWithTransientErrors() c.Assert(err, jc.ErrorIsNil) c.Assert(result, gc.DeepEquals, params.StatusResults{ Results: []params.StatusResult{ {Id: "1", Life: "alive", Status: "error", Info: "transient error", Data: map[string]interface{}{"transient": true, "foo": "bar"}}, }, }) }
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) TestSuccess(c *gc.C) { s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber) stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, icfg *instancecfg.InstanceConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error, ) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var getConfigCalled int getConfig := func() *config.Config { getConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } inner := coretesting.Context(c) ctx := modelcmd.BootstrapContext(inner) result, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ ControllerConfig: coretesting.FakeControllerConfig(), AvailableTools: tools.List{ &tools.Tools{ Version: version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: series.HostSeries(), }, }, }}) c.Assert(err, jc.ErrorIsNil) c.Assert(result.Arch, gc.Equals, "ppc64el") // based on hardware characteristics c.Assert(result.Series, gc.Equals, config.PreferredSeries(mocksConfig)) output := inner.Stderr.(*bytes.Buffer) lines := strings.Split(output.String(), "\n") c.Assert(len(lines), jc.GreaterThan, 1) c.Assert(lines[0], gc.Equals, "Some message") }
func (s *bootstrapSuite) TestInitializeStateFailsSecondTime(c *gc.C) { dataDir := c.MkDir() pwHash := utils.UserPasswordHash(testing.DefaultMongoPassword, utils.CompatSalt) configParams := agent.AgentConfigParams{ DataDir: dataDir, Tag: "machine-0", UpgradedToVersion: version.Current.Number, StateAddresses: []string{gitjujutesting.MgoServer.Addr()}, CACert: testing.CACert, Password: pwHash, } cfg, err := agent.NewAgentConfig(configParams) c.Assert(err, gc.IsNil) cfg.SetStateServingInfo(params.StateServingInfo{ APIPort: 5555, StatePort: gitjujutesting.MgoServer.Port(), Cert: "foo", PrivateKey: "bar", SharedSecret: "baz", SystemIdentity: "qux", }) expectConstraints := constraints.MustParse("mem=1024M") expectHW := instance.MustParseHardware("mem=2048M") mcfg := agent.BootstrapMachineConfig{ Constraints: expectConstraints, Jobs: []params.MachineJob{params.JobHostUnits}, InstanceId: "i-bootstrap", Characteristics: expectHW, } envAttrs := dummy.SampleConfig().Delete("admin-secret").Merge(testing.Attrs{ "agent-version": version.Current.Number.String(), "state-id": "1", // needed so policy can Open config }) envCfg, err := config.New(config.NoDefaults, envAttrs) c.Assert(err, gc.IsNil) st, _, err := agent.InitializeState(cfg, envCfg, mcfg, mongo.DialOpts{}, environs.NewStatePolicy()) c.Assert(err, gc.IsNil) err = st.SetAdminMongoPassword("") c.Check(err, gc.IsNil) st.Close() st, _, err = agent.InitializeState(cfg, envCfg, mcfg, mongo.DialOpts{}, environs.NewStatePolicy()) if err == nil { st.Close() } c.Assert(err, gc.ErrorMatches, "failed to initialize state: cannot create log collection: unauthorized mongo access: unauthorized") }
func (s *bootstrapSuite) TestInitializeStateFailsSecondTime(c *gc.C) { dataDir := c.MkDir() pwHash := utils.UserPasswordHash(testing.DefaultMongoPassword, utils.CompatSalt) configParams := agent.AgentConfigParams{ Paths: agent.Paths{DataDir: dataDir}, Tag: names.NewMachineTag("0"), UpgradedToVersion: version.Current.Number, StateAddresses: []string{s.mgoInst.Addr()}, CACert: testing.CACert, Password: pwHash, Environment: testing.EnvironmentTag, } 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", }) expectConstraints := constraints.MustParse("mem=1024M") expectHW := instance.MustParseHardware("mem=2048M") mcfg := agent.BootstrapMachineConfig{ Constraints: expectConstraints, Jobs: []multiwatcher.MachineJob{multiwatcher.JobManageEnviron}, InstanceId: "i-bootstrap", Characteristics: expectHW, } envAttrs := dummy.SampleConfig().Delete("admin-secret").Merge(testing.Attrs{ "agent-version": version.Current.Number.String(), "state-id": "1", // needed so policy can Open config }) envCfg, err := config.New(config.NoDefaults, envAttrs) c.Assert(err, jc.ErrorIsNil) adminUser := names.NewLocalUserTag("agent-admin") st, _, err := agent.InitializeState(adminUser, cfg, envCfg, mcfg, mongo.DefaultDialOpts(), environs.NewStatePolicy()) c.Assert(err, jc.ErrorIsNil) st.Close() st, _, err = agent.InitializeState(adminUser, cfg, envCfg, 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) TestBootstrapSeries(c *gc.C) { s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber) s.PatchValue(&series.HostSeries, func() string { return "precise" }) stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func(_ string, _ constraints.Value, _ []string, _ tools.List, icfg *instancecfg.InstanceConfig) (instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var numGetConfigCalled int getConfig := func() *config.Config { numGetConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } ctx := envtesting.BootstrapContext(c) bootstrapSeries := "utopic" result, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ ControllerConfig: coretesting.FakeControllerConfig(), BootstrapSeries: bootstrapSeries, AvailableTools: tools.List{ &tools.Tools{ Version: version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: bootstrapSeries, }, }, }}) c.Assert(err, jc.ErrorIsNil) c.Check(result.Arch, gc.Equals, "ppc64el") // based on hardware characteristics c.Check(result.Series, gc.Equals, bootstrapSeries) }
func (s *machineConfigSuite) TestMachineConfigNoTools(c *gc.C) { s.PatchValue(&envtools.DefaultBaseURL, "") addrs := network.NewAddresses("1.2.3.4") hc := instance.MustParseHardware("mem=4G arch=amd64") apiParams := params.AddMachineParams{ Series: "quantal", Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, InstanceId: instance.Id("1234"), Nonce: "foo", HardwareCharacteristics: hc, Addrs: params.FromNetworkAddresses(addrs), } machines, err := s.APIState.Client().AddMachines([]params.AddMachineParams{apiParams}) c.Assert(err, jc.ErrorIsNil) _, err = client.InstanceConfig(s.State, machines[0].Machine, apiParams.Nonce, "") c.Assert(err, gc.ErrorMatches, coretools.ErrNoMatches.Error()) }
func (s *withoutStateServerSuite) TestSetProvisioned(c *gc.C) { // Provision machine 0 first. hwChars := instance.MustParseHardware("arch=i386", "mem=4G") err := s.machines[0].SetProvisioned("i-am", "fake_nonce", &hwChars) c.Assert(err, gc.IsNil) args := params.SetProvisioned{Machines: []params.MachineSetProvisioned{ {Tag: s.machines[0].Tag(), InstanceId: "i-was", Nonce: "fake_nonce", Characteristics: nil}, {Tag: s.machines[1].Tag(), InstanceId: "i-will", Nonce: "fake_nonce", Characteristics: &hwChars}, {Tag: s.machines[2].Tag(), InstanceId: "i-am-too", Nonce: "fake", Characteristics: nil}, {Tag: "machine-42", InstanceId: "", Nonce: "", Characteristics: nil}, {Tag: "unit-foo-0", InstanceId: "", Nonce: "", Characteristics: nil}, {Tag: "service-bar", InstanceId: "", Nonce: "", Characteristics: nil}, }} result, err := s.provisioner.SetProvisioned(args) c.Assert(err, gc.IsNil) c.Assert(result, gc.DeepEquals, params.ErrorResults{ Results: []params.ErrorResult{ {¶ms.Error{ Message: `cannot set instance data for machine "0": already set`, }}, {nil}, {nil}, {apiservertesting.NotFoundError("machine 42")}, {apiservertesting.ErrUnauthorized}, {apiservertesting.ErrUnauthorized}, }, }) // Verify machine 1 and 2 were provisioned. c.Assert(s.machines[1].Refresh(), gc.IsNil) c.Assert(s.machines[2].Refresh(), gc.IsNil) instanceId, err := s.machines[1].InstanceId() c.Assert(err, gc.IsNil) c.Check(instanceId, gc.Equals, instance.Id("i-will")) instanceId, err = s.machines[2].InstanceId() c.Assert(err, gc.IsNil) c.Check(instanceId, gc.Equals, instance.Id("i-am-too")) c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue) c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue) gotHardware, err := s.machines[1].HardwareCharacteristics() c.Assert(err, gc.IsNil) c.Check(gotHardware, gc.DeepEquals, &hwChars) }
func (s *VolumeStateSuite) TestSetVolumeInfoNoStorageAssigned(c *gc.C) { oneJob := []state.MachineJob{state.JobHostUnits} cons := constraints.MustParse("mem=4G") hc := instance.MustParseHardware("mem=2G") volumeParams := state.VolumeParams{ Pool: "loop-pool", Size: 123, } machineTemplate := state.MachineTemplate{ Series: "precise", Constraints: cons, HardwareCharacteristics: hc, InstanceId: "inst-id", Nonce: "nonce", Jobs: oneJob, Volumes: []state.MachineVolumeParams{{ Volume: volumeParams, }}, } machines, err := s.State.AddMachines(machineTemplate) c.Assert(err, jc.ErrorIsNil) c.Assert(machines, gc.HasLen, 1) m, err := s.State.Machine(machines[0].Id()) c.Assert(err, jc.ErrorIsNil) volumeAttachments, err := s.State.MachineVolumeAttachments(m.MachineTag()) c.Assert(err, jc.ErrorIsNil) c.Assert(volumeAttachments, gc.HasLen, 1) volumeTag := volumeAttachments[0].Volume() volume := s.volume(c, volumeTag) _, err = volume.StorageInstance() c.Assert(err, jc.Satisfies, errors.IsNotAssigned) s.assertVolumeUnprovisioned(c, volumeTag) volumeInfoSet := state.VolumeInfo{Size: 123, VolumeId: "vol-ume"} err = s.State.SetVolumeInfo(volume.VolumeTag(), volumeInfoSet) c.Assert(err, jc.ErrorIsNil) volumeInfoSet.Pool = "loop-pool" // taken from params s.assertVolumeInfo(c, volumeTag, volumeInfoSet) }
func (s *BootstrapSuite) TestSuccess(c *gc.C) { stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, mcfg *cloudinit.MachineConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var getConfigCalled int getConfig := func() *config.Config { getConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } restore := envtesting.DisableFinishBootstrap() defer restore() env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } originalAuthKeys := env.Config().AuthorizedKeys() ctx := coretesting.Context(c) err := common.Bootstrap(ctx, env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) authKeys := env.Config().AuthorizedKeys() c.Assert(authKeys, gc.Not(gc.Equals), originalAuthKeys) c.Assert(authKeys, jc.HasSuffix, "juju-system-key\n") }
// Create a machine and login to it. func (s *networkerSuite) setUpMachine(c *gc.C) { var err error s.machine, err = s.State.AddMachine("quantal", state.JobHostUnits) c.Assert(err, jc.ErrorIsNil) password, err := utils.RandomPassword() c.Assert(err, jc.ErrorIsNil) err = s.machine.SetPassword(password) c.Assert(err, jc.ErrorIsNil) hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G") s.machineIfaces = []state.NetworkInterfaceInfo{{ MACAddress: "aa:bb:cc:dd:ee:f0", InterfaceName: "eth0", NetworkName: "net1", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", InterfaceName: "eth1", NetworkName: "net1", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", InterfaceName: "eth1.42", NetworkName: "vlan42", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f0", InterfaceName: "eth0.69", NetworkName: "vlan69", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f2", InterfaceName: "eth2", NetworkName: "net2", IsVirtual: false, Disabled: true, }} err = s.machine.SetInstanceInfo("i-am", "fake_nonce", &hwChars, s.networks, s.machineIfaces, nil, nil) c.Assert(err, jc.ErrorIsNil) s.st = s.OpenAPIAsMachine(c, s.machine.Tag(), password, "fake_nonce") c.Assert(s.st, gc.NotNil) }
// Create and provision a container and a nested container. func (s *networkerSuite) setUpContainers(c *gc.C) { template := state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, } var err error s.container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) c.Assert(err, jc.ErrorIsNil) s.containerIfaces = []state.NetworkInterfaceInfo{{ MACAddress: "aa:bb:cc:dd:ee:e0", InterfaceName: "eth0", NetworkName: "net1", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:e1", InterfaceName: "eth1", NetworkName: "net1", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:e1", InterfaceName: "eth1.42", NetworkName: "vlan42", IsVirtual: true, }} hwChars := instance.MustParseHardware("arch=i386", "mem=4G") err = s.container.SetInstanceInfo("i-container", "fake_nonce", &hwChars, s.networks[:2], s.containerIfaces, nil, nil) c.Assert(err, jc.ErrorIsNil) s.nestedContainer, err = s.State.AddMachineInsideMachine(template, s.container.Id(), instance.LXC) c.Assert(err, jc.ErrorIsNil) s.nestedContainerIfaces = []state.NetworkInterfaceInfo{{ MACAddress: "aa:bb:cc:dd:ee:d0", InterfaceName: "eth0", NetworkName: "net1", IsVirtual: false, }} err = s.nestedContainer.SetInstanceInfo("i-too", "fake_nonce", &hwChars, s.networks[:1], s.nestedContainerIfaces, nil, nil) c.Assert(err, jc.ErrorIsNil) }
func (s *clientSuite) TestProvisioningScript(c *gc.C) { // Inject a machine and then call the ProvisioningScript API. // The result should be the same as when calling MachineConfig, // converting it to a cloudinit.MachineConfig, and disabling // apt_upgrade. apiParams := params.AddMachineParams{ Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, InstanceId: instance.Id("1234"), Nonce: "foo", HardwareCharacteristics: instance.MustParseHardware("arch=amd64"), } machines, err := s.APIState.Client().AddMachines([]params.AddMachineParams{apiParams}) c.Assert(err, jc.ErrorIsNil) c.Assert(len(machines), gc.Equals, 1) machineId := machines[0].Machine // Call ProvisioningScript. Normally ProvisioningScript and // MachineConfig are mutually exclusive; both of them will // allocate a api password for the machine agent. script, err := s.APIState.Client().ProvisioningScript(params.ProvisioningScriptParams{ MachineId: machineId, Nonce: apiParams.Nonce, }) c.Assert(err, jc.ErrorIsNil) icfg, err := client.InstanceConfig(s.State, machineId, apiParams.Nonce, "") c.Assert(err, jc.ErrorIsNil) provisioningScript, err := manual.ProvisioningScript(icfg) c.Assert(err, jc.ErrorIsNil) // ProvisioningScript internally calls MachineConfig, // which allocates a new, random password. Everything // about the scripts should be the same other than // the line containing "oldpassword" from agent.conf. scriptLines := strings.Split(script, "\n") provisioningScriptLines := strings.Split(provisioningScript, "\n") c.Assert(scriptLines, gc.HasLen, len(provisioningScriptLines)) for i, line := range scriptLines { if strings.Contains(line, "oldpassword") { continue } c.Assert(line, gc.Equals, provisioningScriptLines[i]) } }
func (s *BootstrapSuite) TestSuccess(c *gc.C) { s.PatchValue(&version.Current.Number, coretesting.FakeVersionNumber) stor := newStorage(s, c) checkInstanceId := "i-success" checkHardware := instance.MustParseHardware("arch=ppc64el mem=2T") startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, icfg *instancecfg.InstanceConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error, ) { return &mockInstance{id: checkInstanceId}, &checkHardware, nil, nil } var mocksConfig = minimalConfig(c) var getConfigCalled int getConfig := func() *config.Config { getConfigCalled++ return mocksConfig } setConfig := func(c *config.Config) error { mocksConfig = c return nil } env := &mockEnviron{ storage: stor, startInstance: startInstance, config: getConfig, setConfig: setConfig, } ctx := envtesting.BootstrapContext(c) arch, series, _, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ AvailableTools: tools.List{&tools.Tools{Version: version.Current}}, }) c.Assert(err, jc.ErrorIsNil) c.Assert(arch, gc.Equals, "ppc64el") // based on hardware characteristics c.Assert(series, gc.Equals, config.PreferredSeries(mocksConfig)) }
func (s *firewallerBaseSuite) testInstanceId( c *gc.C, facade interface { InstanceId(args params.Entities) (params.StringResults, error) }, ) { // Provision 2 machines first. err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil) c.Assert(err, jc.ErrorIsNil) hwChars := instance.MustParseHardware("arch=i386", "mem=4G") err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars) c.Assert(err, jc.ErrorIsNil) args := addFakeEntities(params.Entities{Entities: []params.Entity{ {Tag: s.machines[0].Tag().String()}, {Tag: s.machines[1].Tag().String()}, {Tag: s.machines[2].Tag().String()}, {Tag: s.service.Tag().String()}, {Tag: s.units[2].Tag().String()}, }}) result, err := facade.InstanceId(args) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.StringResults{ Results: []params.StringResult{ {Result: "i-am"}, {Result: "i-am-not"}, {Error: apiservertesting.NotProvisionedError("2")}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.NotFoundError("machine 42")}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) }
func (s *provisionerSuite) TestSetInstanceInfo(c *gc.C) { // Create a fresh machine, since machine 0 is already provisioned. notProvisionedMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) c.Assert(err, gc.IsNil) apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag().(names.MachineTag)) c.Assert(err, gc.IsNil) instanceId, err := apiMachine.InstanceId() c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned) c.Assert(err, gc.ErrorMatches, "machine 1 is not provisioned") c.Assert(instanceId, gc.Equals, instance.Id("")) hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G") _, err = s.State.Network("net1") c.Assert(err, jc.Satisfies, errors.IsNotFound) _, err = s.State.Network("vlan42") c.Assert(err, jc.Satisfies, errors.IsNotFound) ifacesMachine, err := notProvisionedMachine.NetworkInterfaces() c.Assert(err, gc.IsNil) c.Assert(ifacesMachine, gc.HasLen, 0) networks := []params.Network{{ Tag: "network-net1", ProviderId: "net1", CIDR: "0.1.2.0/24", VLANTag: 0, }, { Tag: "network-vlan42", ProviderId: "vlan42", CIDR: "0.2.2.0/24", VLANTag: 42, }, { Tag: "network-vlan69", ProviderId: "vlan69", CIDR: "0.3.2.0/24", VLANTag: 69, }, { Tag: "network-vlan42", // duplicated; ignored ProviderId: "vlan42", CIDR: "0.2.2.0/24", VLANTag: 42, }} ifaces := []params.NetworkInterface{{ MACAddress: "aa:bb:cc:dd:ee:f0", NetworkTag: "network-net1", InterfaceName: "eth0", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", NetworkTag: "network-net1", InterfaceName: "eth1", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", NetworkTag: "network-vlan42", InterfaceName: "eth1.42", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f1", NetworkTag: "network-vlan69", InterfaceName: "eth1.69", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f1", // duplicated mac+net; ignored NetworkTag: "network-vlan42", InterfaceName: "eth2", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f4", NetworkTag: "network-net1", InterfaceName: "eth1", // duplicated name+machine id; ignored IsVirtual: false, }} err = apiMachine.SetInstanceInfo("i-will", "fake_nonce", &hwChars, networks, ifaces) c.Assert(err, gc.IsNil) instanceId, err = apiMachine.InstanceId() c.Assert(err, gc.IsNil) c.Assert(instanceId, gc.Equals, instance.Id("i-will")) // Try it again - should fail. err = apiMachine.SetInstanceInfo("i-wont", "fake", nil, nil, nil) c.Assert(err, gc.ErrorMatches, `aborted instance "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, gc.IsNil) instanceId, err = apiMachine.InstanceId() c.Assert(err, gc.IsNil) c.Assert(instanceId, gc.Equals, instance.Id("i-manager")) // Check the networks are created. for i, _ := range networks { if i == 3 { // Last one was ignored, so skip it. break } tag, err := names.ParseNetworkTag(networks[i].Tag) c.Assert(err, gc.IsNil) networkName := tag.Id() network, err := s.State.Network(networkName) c.Assert(err, gc.IsNil) c.Check(network.Name(), gc.Equals, networkName) c.Check(network.ProviderId(), gc.Equals, networks[i].ProviderId) c.Check(network.Tag().String(), gc.Equals, networks[i].Tag) c.Check(network.VLANTag(), gc.Equals, networks[i].VLANTag) c.Check(network.CIDR(), gc.Equals, networks[i].CIDR) } // And the network interfaces as well. ifacesMachine, err = notProvisionedMachine.NetworkInterfaces() c.Assert(err, gc.IsNil) c.Assert(ifacesMachine, gc.HasLen, 4) actual := make([]params.NetworkInterface, len(ifacesMachine)) for i, iface := range ifacesMachine { actual[i].InterfaceName = iface.InterfaceName() actual[i].NetworkTag = iface.NetworkTag().String() actual[i].MACAddress = iface.MACAddress() actual[i].IsVirtual = iface.IsVirtual() c.Check(iface.MachineTag(), gc.Equals, notProvisionedMachine.Tag()) c.Check(iface.MachineId(), gc.Equals, notProvisionedMachine.Id()) } c.Assert(actual, jc.SameContents, ifaces[:4]) // skip the rest as they are ignored. }