func (*NewAPIConnSuite) TestNewConn(c *gc.C) { cfg, err := config.New(config.NoDefaults, dummy.SampleConfig()) c.Assert(err, gc.IsNil) ctx := coretesting.Context(c) env, err := environs.Prepare(cfg, ctx, configstore.NewMem()) c.Assert(err, gc.IsNil) envtesting.UploadFakeTools(c, env.Storage()) err = bootstrap.Bootstrap(ctx, env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) cfg = env.Config() cfg, err = cfg.Apply(map[string]interface{}{ "secret": "fnord", }) c.Assert(err, gc.IsNil) err = env.SetConfig(cfg) c.Assert(err, gc.IsNil) conn, err := juju.NewAPIConn(env, api.DefaultDialOpts()) c.Assert(err, gc.IsNil) c.Assert(conn.Environ, gc.Equals, env) c.Assert(conn.State, gc.NotNil) // the secrets will not be updated, as they already exist attrs, err := conn.State.Client().EnvironmentGet() c.Assert(attrs["secret"], gc.Equals, "pork") c.Assert(conn.Close(), gc.IsNil) }
func (t *localServerSuite) TestAddresses(c *gc.C) { env := t.Prepare(c) envtesting.UploadFakeTools(c, env.Storage()) err := bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) inst, _ := testing.AssertStartInstance(c, env, "1") c.Assert(err, gc.IsNil) addrs, err := inst.Addresses() c.Assert(err, gc.IsNil) // Expected values use Address type but really contain a regexp for // the value rather than a valid ip or hostname. expected := []instance.Address{{ Value: "*.testing.invalid", Type: instance.HostName, NetworkScope: instance.NetworkPublic, }, { Value: "*.internal.invalid", Type: instance.HostName, NetworkScope: instance.NetworkCloudLocal, }, { Value: "8.0.0.*", Type: instance.Ipv4Address, NetworkScope: instance.NetworkPublic, }, { Value: "127.0.0.*", Type: instance.Ipv4Address, NetworkScope: instance.NetworkCloudLocal, }} c.Assert(addrs, gc.HasLen, len(expected)) for i, addr := range addrs { c.Check(addr.Value, gc.Matches, expected[i].Value) c.Check(addr.Type, gc.Equals, expected[i].Type) c.Check(addr.NetworkScope, gc.Equals, expected[i].NetworkScope) } }
func (s *LiveTests) assertStartInstanceDefaultSecurityGroup(c *gc.C, useDefault bool) { attrs := s.TestConfig.Merge(coretesting.Attrs{ "name": "sample-" + randomName(), "control-bucket": "juju-test-" + randomName(), "use-default-secgroup": useDefault, }) cfg, err := config.New(config.NoDefaults, attrs) c.Assert(err, gc.IsNil) // Set up a test environment. env, err := environs.New(cfg) c.Assert(err, gc.IsNil) c.Assert(env, gc.NotNil) defer env.Destroy() // Bootstrap and start an instance. err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) inst, _ := jujutesting.AssertStartInstance(c, env, "100") // Check whether the instance has the default security group assigned. novaClient := openstack.GetNovaClient(env) groups, err := novaClient.GetServerSecurityGroups(string(inst.Id())) c.Assert(err, gc.IsNil) defaultGroupFound := false for _, group := range groups { if group.Name == "default" { defaultGroupFound = true break } } c.Assert(defaultGroupFound, gc.Equals, useDefault) }
func (suite *environSuite) TestBootstrapFailsIfNoNodes(c *gc.C) { suite.setupFakeTools(c) env := suite.makeEnviron() err := bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) // Since there are no nodes, the attempt to allocate one returns a // 409: Conflict. c.Check(err, gc.ErrorMatches, ".*409.*") }
func (t *localServerSuite) TestInstanceStatus(c *gc.C) { env := t.Prepare(c) envtesting.UploadFakeTools(c, env.Storage()) err := bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) t.srv.ec2srv.SetInitialInstanceState(ec2test.Terminated) inst, _ := testing.AssertStartInstance(c, env, "1") c.Assert(err, gc.IsNil) c.Assert(inst.Status(), gc.Equals, "terminated") }
func (suite *environSuite) TestBootstrapSucceeds(c *gc.C) { suite.setupFakeTools(c) env := suite.makeEnviron() suite.testMAASObject.TestServer.NewNode(`{"system_id": "thenode", "hostname": "host"}`) lshwXML, err := suite.generateHWTemplate(map[string]string{"aa:bb:cc:dd:ee:f0": "eth0"}) c.Assert(err, gc.IsNil) suite.testMAASObject.TestServer.AddNodeDetails("thenode", lshwXML) err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) }
func (t *localServerSuite) TestStartInstanceHardwareCharacteristics(c *gc.C) { env := t.Prepare(c) envtesting.UploadFakeTools(c, env.Storage()) err := bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) _, hc := testing.AssertStartInstance(c, env, "1") c.Check(*hc.Arch, gc.Equals, "amd64") c.Check(*hc.Mem, gc.Equals, uint64(1740)) c.Check(*hc.CpuCores, gc.Equals, uint64(1)) c.Assert(*hc.CpuPower, gc.Equals, uint64(100)) }
func (t *Tests) TestBootstrap(c *gc.C) { e := t.Prepare(c) t.UploadFakeTools(c, e.Storage()) err := bootstrap.EnsureNotBootstrapped(e) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), e, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) info, apiInfo, err := e.StateInfo() c.Check(info.Addrs, gc.Not(gc.HasLen), 0) c.Check(apiInfo.Addrs, gc.Not(gc.HasLen), 0) err = bootstrap.EnsureNotBootstrapped(e) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") e2 := t.Open(c) t.UploadFakeTools(c, e2.Storage()) err = bootstrap.EnsureNotBootstrapped(e2) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") info2, apiInfo2, err := e2.StateInfo() c.Check(info2, gc.DeepEquals, info) c.Check(apiInfo2, gc.DeepEquals, apiInfo) err = environs.Destroy(e2, t.ConfigStore) c.Assert(err, gc.IsNil) // Prepare again because Destroy invalidates old environments. e3 := t.Prepare(c) t.UploadFakeTools(c, e3.Storage()) err = bootstrap.EnsureNotBootstrapped(e3) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), e3, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) err = bootstrap.EnsureNotBootstrapped(e3) c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped") }
func (suite *environSuite) TestBootstrapFailsIfNoTools(c *gc.C) { suite.setupFakeTools(c) env := suite.makeEnviron() // Can't RemoveAllTools, no public storage. envtesting.RemoveTools(c, env.Storage()) // Disable auto-uploading by setting the agent version. cfg, err := env.Config().Apply(map[string]interface{}{ "agent-version": version.Current.Number.String(), }) c.Assert(err, gc.IsNil) err = env.SetConfig(cfg) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) stripped := strings.Replace(err.Error(), "\n", "", -1) c.Check(stripped, gc.Matches, "cannot upload bootstrap tools: Juju cannot bootstrap because no tools are available for your environment.*") }
func (t *LiveTests) BootstrapOnce(c *gc.C) { if t.bootstrapped { return } t.PrepareOnce(c) // We only build and upload tools if there will be a state agent that // we could connect to (actual live tests, rather than local-only) cons := constraints.MustParse("mem=2G") if t.CanOpenState { _, err := sync.Upload(t.Env.Storage(), nil, coretesting.FakeDefaultSeries) c.Assert(err, gc.IsNil) } t.UploadFakeTools(c, t.Env.Storage()) err := bootstrap.EnsureNotBootstrapped(t.Env) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), t.Env, environs.BootstrapParams{Constraints: cons}) c.Assert(err, gc.IsNil) t.bootstrapped = true }
func (s *APIEndpointForEnvSuite) TestAPIEndpointNotCached(c *gc.C) { coretesting.WriteEnvironments(c, coretesting.MultipleEnvConfig) store, err := configstore.Default() c.Assert(err, gc.IsNil) ctx := coretesting.Context(c) env, err := environs.PrepareFromName("erewhemos", ctx, store) c.Assert(err, gc.IsNil) defer dummy.Reset() envtesting.UploadFakeTools(c, env.Storage()) err = bootstrap.Bootstrap(ctx, env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) // Note: if we get Bootstrap to start caching the API endpoint // immediately, we'll still want to have this test for compatibility. // We can just write blank info instead of reading and checking it is empty. savedInfo, err := store.ReadInfo("erewhemos") c.Assert(err, gc.IsNil) // Ensure that the data isn't cached c.Check(savedInfo.APIEndpoint().Addresses, gc.HasLen, 0) called := 0 expectState := &mockAPIState{ apiHostPorts: [][]instance.HostPort{ instance.AddressesWithPort([]instance.Address{instance.NewAddress("0.1.2.3", instance.NetworkUnknown)}, 1234), }, } apiOpen := func(apiInfo *api.Info, opts api.DialOpts) (juju.APIState, error) { c.Check(apiInfo.Tag, gc.Equals, "user-admin") c.Check(string(apiInfo.CACert), gc.Equals, coretesting.CACert) c.Check(apiInfo.Password, gc.Equals, coretesting.DefaultMongoPassword) c.Check(opts, gc.DeepEquals, api.DefaultDialOpts()) called++ return expectState, nil } endpoint, err := juju.APIEndpointInStore("erewhemos", false, store, apiOpen) c.Assert(err, gc.IsNil) c.Assert(called, gc.Equals, 1) c.Check(endpoint.Addresses, gc.DeepEquals, []string{"0.1.2.3:1234"}) }
func (t *localServerSuite) TestBootstrapInstanceUserDataAndState(c *gc.C) { env := t.Prepare(c) envtesting.UploadFakeTools(c, env.Storage()) err := bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) // check that the state holds the id of the bootstrap machine. bootstrapState, err := bootstrap.LoadState(env.Storage()) c.Assert(err, gc.IsNil) c.Assert(bootstrapState.StateInstances, gc.HasLen, 1) insts, err := env.AllInstances() c.Assert(err, gc.IsNil) c.Assert(insts, gc.HasLen, 1) c.Check(insts[0].Id(), gc.Equals, bootstrapState.StateInstances[0]) // check that the user data is configured to start zookeeper // and the machine and provisioning agents. // check that the user data is configured to only configure // authorized SSH keys and set the log output; everything // else happens after the machine is brought up. inst := t.srv.ec2srv.Instance(string(insts[0].Id())) c.Assert(inst, gc.NotNil) bootstrapDNS, err := insts[0].DNSName() c.Assert(err, gc.IsNil) c.Assert(bootstrapDNS, gc.Not(gc.Equals), "") userData, err := utils.Gunzip(inst.UserData) c.Assert(err, gc.IsNil) c.Logf("first instance: UserData: %q", userData) var userDataMap map[interface{}]interface{} err = goyaml.Unmarshal(userData, &userDataMap) c.Assert(err, gc.IsNil) c.Assert(userDataMap, jc.DeepEquals, map[interface{}]interface{}{ "output": map[interface{}]interface{}{ "all": "| tee -a /var/log/cloud-init-output.log", }, "ssh_authorized_keys": splitAuthKeys(env.Config().AuthorizedKeys()), "runcmd": []interface{}{ "set -xe", "install -D -m 644 /dev/null '/var/lib/juju/nonce.txt'", "printf '%s\\n' 'user-admin:bootstrap' > '/var/lib/juju/nonce.txt'", }, }) // check that a new instance will be started with a machine agent inst1, hc := testing.AssertStartInstance(c, env, "1") c.Check(*hc.Arch, gc.Equals, "amd64") c.Check(*hc.Mem, gc.Equals, uint64(1740)) c.Check(*hc.CpuCores, gc.Equals, uint64(1)) c.Assert(*hc.CpuPower, gc.Equals, uint64(100)) inst = t.srv.ec2srv.Instance(string(inst1.Id())) c.Assert(inst, gc.NotNil) userData, err = utils.Gunzip(inst.UserData) c.Assert(err, gc.IsNil) c.Logf("second instance: UserData: %q", userData) userDataMap = nil err = goyaml.Unmarshal(userData, &userDataMap) c.Assert(err, gc.IsNil) CheckPackage(c, userDataMap, "git", true) CheckPackage(c, userDataMap, "mongodb-server", false) CheckScripts(c, userDataMap, "jujud bootstrap-state", false) CheckScripts(c, userDataMap, "/var/lib/juju/agents/machine-1/agent.conf", true) // TODO check for provisioning agent err = env.Destroy() c.Assert(err, gc.IsNil) _, err = bootstrap.LoadState(env.Storage()) c.Assert(err, gc.NotNil) }
func (t *LiveTests) TestBootstrapWithDefaultSeries(c *gc.C) { if !t.HasProvisioner { c.Skip("HasProvisioner is false; cannot test deployment") } current := version.Current other := current other.Series = "quantal" if current == other { other.Series = "precise" } dummyCfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(coretesting.Attrs{ "state-server": false, "name": "dummy storage", })) dummyenv, err := environs.Prepare(dummyCfg, coretesting.Context(c), configstore.NewMem()) c.Assert(err, gc.IsNil) defer dummyenv.Destroy() t.Destroy(c) attrs := t.TestConfig.Merge(coretesting.Attrs{"default-series": other.Series}) cfg, err := config.New(config.NoDefaults, attrs) c.Assert(err, gc.IsNil) env, err := environs.Prepare(cfg, coretesting.Context(c), t.ConfigStore) c.Assert(err, gc.IsNil) defer environs.Destroy(env, t.ConfigStore) currentName := envtools.StorageName(current) otherName := envtools.StorageName(other) envStorage := env.Storage() dummyStorage := dummyenv.Storage() defer envStorage.Remove(otherName) _, err = sync.Upload(dummyStorage, ¤t.Number) c.Assert(err, gc.IsNil) // This will only work while cross-compiling across releases is safe, // which depends on external elements. Tends to be safe for the last // few releases, but we may have to refactor some day. err = storageCopy(dummyStorage, currentName, envStorage, otherName) c.Assert(err, gc.IsNil) err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) conn, err := juju.NewConn(env) c.Assert(err, gc.IsNil) defer conn.Close() // Wait for machine agent to come up on the bootstrap // machine and ensure it deployed the proper series. m0, err := conn.State.Machine("0") c.Assert(err, gc.IsNil) mw0 := newMachineToolWaiter(m0) defer mw0.Stop() waitAgentTools(c, mw0, other) }
func (suite *environSuite) TestStartInstanceStartsInstance(c *gc.C) { suite.setupFakeTools(c) env := suite.makeEnviron() // Create node 0: it will be used as the bootstrap node. suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0", "hostname": "host0"}`) lshwXML, err := suite.generateHWTemplate(map[string]string{"aa:bb:cc:dd:ee:f0": "eth0"}) c.Assert(err, gc.IsNil) suite.testMAASObject.TestServer.AddNodeDetails("node0", lshwXML) err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) // The bootstrap node has been acquired and started. operations := suite.testMAASObject.TestServer.NodeOperations() actions, found := operations["node0"] c.Check(found, gc.Equals, true) c.Check(actions, gc.DeepEquals, []string{"acquire", "start"}) // Test the instance id is correctly recorded for the bootstrap node. // Check that the state holds the id of the bootstrap machine. stateData, err := bootstrap.LoadState(env.Storage()) c.Assert(err, gc.IsNil) c.Assert(stateData.StateInstances, gc.HasLen, 1) insts, err := env.AllInstances() c.Assert(err, gc.IsNil) c.Assert(insts, gc.HasLen, 1) c.Check(insts[0].Id(), gc.Equals, stateData.StateInstances[0]) // Create node 1: it will be used as instance number 1. suite.testMAASObject.TestServer.NewNode(`{"system_id": "node1", "hostname": "host1"}`) lshwXML, err = suite.generateHWTemplate(map[string]string{"aa:bb:cc:dd:ee:f1": "eth0"}) c.Assert(err, gc.IsNil) suite.testMAASObject.TestServer.AddNodeDetails("node1", lshwXML) // TODO(wallyworld) - test instance metadata instance, _ := testing.AssertStartInstance(c, env, "1") c.Assert(err, gc.IsNil) c.Check(instance, gc.NotNil) // The instance number 1 has been acquired and started. actions, found = operations["node1"] c.Assert(found, gc.Equals, true) c.Check(actions, gc.DeepEquals, []string{"acquire", "start"}) // The value of the "user data" parameter used when starting the node // contains the run cmd used to write the machine information onto // the node's filesystem. requestValues := suite.testMAASObject.TestServer.NodeOperationRequestValues() nodeRequestValues, found := requestValues["node1"] c.Assert(found, gc.Equals, true) c.Assert(len(nodeRequestValues), gc.Equals, 2) userData := nodeRequestValues[1].Get("user_data") decodedUserData, err := decodeUserData(userData) c.Assert(err, gc.IsNil) info := machineInfo{"host1"} cloudinitRunCmd, err := info.cloudinitRunCmd() c.Assert(err, gc.IsNil) data, err := goyaml.Marshal(cloudinitRunCmd) c.Assert(err, gc.IsNil) c.Check(string(decodedUserData), gc.Matches, "(.|\n)*"+string(data)+"(\n|.)*") // Trash the tools and try to start another instance. envtesting.RemoveTools(c, env.Storage()) instance, _, _, err = testing.StartInstance(env, "2") c.Check(instance, gc.IsNil) c.Check(err, jc.Satisfies, errors.IsNotFound) }
func (b bootstrapFuncs) Bootstrap(ctx environs.BootstrapContext, env environs.Environ, args environs.BootstrapParams) error { return bootstrap.Bootstrap(ctx, env, args) }