func (t *LiveTests) TestCheckEnvironmentOnConnectBadVerificationFile(c *C) { // When new connection is established to a bootstraped environment, // it is checked that we are running against a juju-core environment. // // If the verification file has unexpected content, it is not // a juju-core environment (likely to a Python juju environment). if !t.CanOpenState { c.Skip("CanOpenState is false; cannot open state connection") } t.BootstrapOnce(c) environ := t.Env storage := environ.Storage() // Finally, replace the content with an arbitrary string. badVerificationContent := "bootstrap storage verification" reader := strings.NewReader(badVerificationContent) err := storage.Put( "bootstrap-verify", reader, int64(len(badVerificationContent))) c.Assert(err, IsNil) defer restoreBootstrapVerificationFile(c, storage) // Running NewConn() should fail. _, err = juju.NewConn(t.Env) c.Assert(err, Equals, environs.InvalidEnvironmentError) }
func (t *LiveTests) TestBootstrapWithDefaultSeries(c *C) { if !t.HasProvisioner { c.Skip("HasProvisioner is false; cannot test deployment") } current := version.Current other := current other.Series = "precise" if current == other { other.Series = "quantal" } cfg := t.Env.Config() cfg, err := cfg.Apply(map[string]interface{}{"default-series": other.Series}) c.Assert(err, IsNil) env, err := environs.New(cfg) c.Assert(err, IsNil) dummyenv, err := environs.NewFromAttrs(map[string]interface{}{ "type": "dummy", "name": "dummy storage", "secret": "pizza", "state-server": false, }) c.Assert(err, IsNil) defer dummyenv.Destroy(nil) currentPath := environs.ToolsStoragePath(current) otherPath := environs.ToolsStoragePath(other) envStorage := env.Storage() dummyStorage := dummyenv.Storage() defer envStorage.Remove(otherPath) _, err = environs.PutTools(dummyStorage, ¤t.Number) c.Assert(err, 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, currentPath, envStorage, otherPath) c.Assert(err, IsNil) err = environs.Bootstrap(env, false, panicWrite) c.Assert(err, IsNil) defer env.Destroy(nil) conn, err := juju.NewConn(env) c.Assert(err, 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, IsNil) mw0 := newMachineToolWaiter(m0) defer mw0.Stop() waitAgentTools(c, mw0, other) }
func build() error { environ, err := environs.NewFromName("") if err != nil { return err } err = environs.Bootstrap(environ, true, nil) if err != nil { return err } conn, err := juju.NewConn(environ) if err != nil { return err } repo := &charm.LocalRepository{filepath.Dir(os.Args[0])} curl := charm.MustParseURL("local:precise/builddb") ch, err := conn.PutCharm(curl, repo, false) if err != nil { return err } service, err := conn.AddService("builddb", ch) if err != nil { return err } if err := service.SetExposed(); err != nil { return err } units, err := conn.AddUnits(service, 1) if err != nil { return err } log.Printf("builddb: Waiting for unit to reach %q status...", state.UnitStarted) unit := units[0] last, info, err := unit.Status() if err != nil { return err } logStatus(last, info) for last != state.UnitStarted { time.Sleep(2 * time.Second) if err := unit.Refresh(); err != nil { return err } status, info, err := unit.Status() if err != nil { return err } if status != last { logStatus(status, info) last = status } } addr, ok := unit.PublicAddress() if !ok { return fmt.Errorf("cannot retrieve files: build unit lacks a public-address") } log.Printf("builddb: Built files published at http://%s", addr) log.Printf("builddb: Remember to destroy the environment when you're done...") return nil }
func (cs *NewConnSuite) TestConnWithPassword(c *C) { env, err := environs.NewFromAttrs(map[string]interface{}{ "name": "erewhemos", "type": "dummy", "state-server": true, "authorized-keys": "i-am-a-key", "secret": "squirrel", "admin-secret": "nutkin", "ca-cert": coretesting.CACert, "ca-private-key": coretesting.CAKey, }) c.Assert(err, IsNil) err = environs.Bootstrap(env, constraints.Value{}) c.Assert(err, IsNil) // Check that Bootstrap has correctly used a hash // of the admin password. info, _, err := env.StateInfo() c.Assert(err, IsNil) info.Password = utils.PasswordHash("nutkin") st, err := state.Open(info, state.DefaultDialOpts()) c.Assert(err, IsNil) st.Close() // Check that we can connect with the original environment. conn, err := juju.NewConn(env) c.Assert(err, IsNil) conn.Close() // Check that the password has now been changed to the original // admin password. info.Password = "******" st1, err := state.Open(info, state.DefaultDialOpts()) c.Assert(err, IsNil) st1.Close() // Check that we can still connect with the original // environment. conn, err = juju.NewConn(env) c.Assert(err, IsNil) defer conn.Close() // Reset the admin password so the state db can be reused. err = conn.State.SetAdminMongoPassword("") c.Assert(err, IsNil) }
func (t *LiveTests) TestCheckEnvironmentOnConnect(c *C) { // When new connection is established to a bootstraped environment, // it is checked that we are running against a juju-core environment. if !t.CanOpenState { c.Skip("CanOpenState is false; cannot open state connection") } t.BootstrapOnce(c) conn, err := juju.NewConn(t.Env) c.Assert(err, IsNil) conn.Close() }
func (cs *NewConnSuite) TestConnStateDoesNotUpdateExistingSecrets(c *C) { attrs := map[string]interface{}{ "name": "erewhemos", "type": "dummy", "state-server": true, "authorized-keys": "i-am-a-key", "secret": "pork", "admin-secret": "some secret", "ca-cert": coretesting.CACert, "ca-private-key": coretesting.CAKey, } env, err := environs.NewFromAttrs(attrs) c.Assert(err, IsNil) err = environs.Bootstrap(env, constraints.Value{}) c.Assert(err, IsNil) // Make a new Conn, which will push the secrets. conn, err := juju.NewConn(env) c.Assert(err, IsNil) defer conn.Close() // Make another env with a different secret. attrs["secret"] = "squirrel" env1, err := environs.NewFromAttrs(attrs) c.Assert(err, IsNil) // Connect with the new env and check that the secret has not changed conn, err = juju.NewConn(env1) c.Assert(err, IsNil) defer conn.Close() cfg, err := conn.State.EnvironConfig() c.Assert(err, IsNil) c.Assert(cfg.UnknownAttrs()["secret"], Equals, "pork") // Reset the admin password so the state db can be reused. err = conn.State.SetAdminMongoPassword("") c.Assert(err, IsNil) }
func (s *JujuConnSuite) setUpConn(c *C) { if s.RootDir != "" { panic("JujuConnSuite.setUpConn without teardown") } s.RootDir = c.MkDir() s.oldHome = os.Getenv("HOME") home := filepath.Join(s.RootDir, "/home/ubuntu") err := os.MkdirAll(home, 0777) c.Assert(err, IsNil) os.Setenv("HOME", home) dataDir := filepath.Join(s.RootDir, "/var/lib/juju") err = os.MkdirAll(dataDir, 0777) c.Assert(err, IsNil) yaml := []byte(fmt.Sprintf(envConfig, version.Current.Number)) err = ioutil.WriteFile(config.JujuHomePath("environments.yaml"), yaml, 0600) c.Assert(err, IsNil) err = ioutil.WriteFile(config.JujuHomePath("dummyenv-cert.pem"), []byte(testing.CACert), 0666) c.Assert(err, IsNil) err = ioutil.WriteFile(config.JujuHomePath("dummyenv-private-key.pem"), []byte(testing.CAKey), 0600) c.Assert(err, IsNil) environ, err := environs.NewFromName("dummyenv") c.Assert(err, IsNil) // sanity check we've got the correct environment. c.Assert(environ.Name(), Equals, "dummyenv") c.Assert(environs.Bootstrap(environ, constraints.Value{}), IsNil) s.BackingState = environ.(GetStater).GetStateInAPIServer() conn, err := juju.NewConn(environ) c.Assert(err, IsNil) s.Conn = conn s.State = conn.State apiConn, err := juju.NewAPIConn(environ, api.DialOpts{}) c.Assert(err, IsNil) s.APIConn = apiConn s.APIState = apiConn.State s.environ = environ }
func (s *ConnSuite) SetUpTest(c *C) { s.LoggingSuite.SetUpTest(c) s.MgoSuite.SetUpTest(c) attrs := map[string]interface{}{ "name": "erewhemos", "type": "dummy", "state-server": true, "authorized-keys": "i-am-a-key", "admin-secret": "deploy-test-secret", "ca-cert": coretesting.CACert, "ca-private-key": coretesting.CAKey, } environ, err := environs.NewFromAttrs(attrs) c.Assert(err, IsNil) err = environs.Bootstrap(environ, constraints.Value{}) c.Assert(err, IsNil) s.conn, err = juju.NewConn(environ) c.Assert(err, IsNil) s.repo = &charm.LocalRepository{Path: c.MkDir()} }
func (t *LiveTests) TestCheckEnvironmentOnConnectNoVerificationFile(c *C) { // When new connection is established to a bootstraped environment, // it is checked that we are running against a juju-core environment. // // Absence of a verification file means it is a juju-core environment // with an older version, which is fine. if !t.CanOpenState { c.Skip("CanOpenState is false; cannot open state connection") } t.BootstrapOnce(c) environ := t.Env storage := environ.Storage() err := storage.Remove("bootstrap-verify") c.Assert(err, IsNil) defer restoreBootstrapVerificationFile(c, storage) conn, err := juju.NewConn(t.Env) c.Assert(err, IsNil) conn.Close() }
func (cs *NewConnSuite) TestConnStateSecretsSideEffect(c *C) { attrs := map[string]interface{}{ "name": "erewhemos", "type": "dummy", "state-server": true, "authorized-keys": "i-am-a-key", "secret": "pork", "admin-secret": "side-effect secret", "ca-cert": coretesting.CACert, "ca-private-key": coretesting.CAKey, } env, err := environs.NewFromAttrs(attrs) c.Assert(err, IsNil) err = environs.Bootstrap(env, constraints.Value{}) c.Assert(err, IsNil) info, _, err := env.StateInfo() c.Assert(err, IsNil) info.Password = utils.PasswordHash("side-effect secret") st, err := state.Open(info, state.DefaultDialOpts()) c.Assert(err, IsNil) // Verify we have no secret in the environ config cfg, err := st.EnvironConfig() c.Assert(err, IsNil) c.Assert(cfg.UnknownAttrs()["secret"], IsNil) // Make a new Conn, which will push the secrets. conn, err := juju.NewConn(env) c.Assert(err, IsNil) defer conn.Close() cfg, err = conn.State.EnvironConfig() c.Assert(err, IsNil) c.Assert(cfg.UnknownAttrs()["secret"], Equals, "pork") // Reset the admin password so the state db can be reused. err = conn.State.SetAdminMongoPassword("") c.Assert(err, IsNil) }
func (*NewConnSuite) TestNewConnWithoutAdminSecret(c *C) { attrs := map[string]interface{}{ "name": "erewhemos", "type": "dummy", "state-server": true, "authorized-keys": "i-am-a-key", "secret": "pork", "admin-secret": "really", "ca-cert": coretesting.CACert, "ca-private-key": coretesting.CAKey, } env, err := environs.NewFromAttrs(attrs) c.Assert(err, IsNil) err = environs.Bootstrap(env, constraints.Value{}) c.Assert(err, IsNil) delete(attrs, "admin-secret") env1, err := environs.NewFromAttrs(attrs) c.Assert(err, IsNil) conn, err := juju.NewConn(env1) c.Check(conn, IsNil) c.Assert(err, ErrorMatches, "cannot connect without admin-secret") }
func (*NewAPIConnSuite) TestNewConn(c *C) { attrs := map[string]interface{}{ "name": "erewhemos", "type": "dummy", "state-server": true, "authorized-keys": "i-am-a-key", "secret": "pork", "admin-secret": "really", "ca-cert": coretesting.CACert, "ca-private-key": coretesting.CAKey, } env, err := environs.NewFromAttrs(attrs) c.Assert(err, IsNil) err = environs.Bootstrap(env, constraints.Value{}) c.Assert(err, IsNil) conn, err := juju.NewConn(env) c.Assert(err, IsNil) c.Assert(conn.Environ, Equals, env) c.Assert(conn.State, NotNil) c.Assert(conn.Close(), IsNil) }
func (t *LiveTests) TestBootstrapWithDefaultSeries(c *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" } cfg := t.Env.Config() cfg, err := cfg.Apply(map[string]interface{}{"default-series": other.Series}) c.Assert(err, IsNil) env, err := environs.New(cfg) c.Assert(err, IsNil) dummyenv, err := environs.NewFromAttrs(map[string]interface{}{ "type": "dummy", "name": "dummy storage", "secret": "pizza", "state-server": false, "ca-cert": coretesting.CACert, "ca-private-key": coretesting.CAKey, }) c.Assert(err, IsNil) defer dummyenv.Destroy(nil) // BUG: We destroy the environment, then write to its storage. // This is bogus, strictly speaking, but it works on // existing providers for the time being and means // this test does not fail when the environment is // already bootstrapped. t.Destroy(c) currentName := tools.StorageName(current) otherName := tools.StorageName(other) envStorage := env.Storage() dummyStorage := dummyenv.Storage() defer envStorage.Remove(otherName) _, err = tools.Upload(dummyStorage, ¤t.Number) c.Assert(err, 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, IsNil) err = environs.Bootstrap(env, constraints.Value{}) c.Assert(err, IsNil) defer env.Destroy(nil) conn, err := juju.NewConn(env) c.Assert(err, 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, IsNil) mw0 := newMachineToolWaiter(m0) defer mw0.Stop() waitAgentTools(c, mw0, other) }
func (t *LiveTests) TestBootstrapAndDeploy(c *C) { if !t.CanOpenState || !t.HasProvisioner { c.Skip(fmt.Sprintf("skipping provisioner test, CanOpenState: %v, HasProvisioner: %v", t.CanOpenState, t.HasProvisioner)) } t.BootstrapOnce(c) // TODO(niemeyer): Stop growing this kitchen sink test and split it into proper parts. c.Logf("opening connection") conn, err := juju.NewConn(t.Env) c.Assert(err, IsNil) defer conn.Close() c.Logf("opening API connection") apiConn, err := juju.NewAPIConn(t.Env, api.DefaultDialOpts()) c.Assert(err, IsNil) defer conn.Close() // Check that the agent version has made it through the // bootstrap process (it's optional in the config.Config) cfg, err := conn.State.EnvironConfig() c.Assert(err, IsNil) agentVersion, ok := cfg.AgentVersion() c.Check(ok, Equals, true) c.Check(agentVersion, Equals, version.CurrentNumber()) // Check that the constraints have been set in the environment. cons, err := conn.State.EnvironConstraints() c.Assert(err, IsNil) c.Assert(cons.String(), Equals, "mem=2048M") // Wait for machine agent to come up on the bootstrap // machine and find the deployed series from that. m0, err := conn.State.Machine("0") c.Assert(err, IsNil) instId0, err := m0.InstanceId() c.Assert(err, IsNil) // Check that the API connection is working. status, err := apiConn.State.Client().Status() c.Assert(err, IsNil) c.Assert(status.Machines["0"].InstanceId, Equals, string(instId0)) mw0 := newMachineToolWaiter(m0) defer mw0.Stop() // If the series has not been specified, we expect the most recent Ubuntu LTS release to be used. expectedVersion := version.Current expectedVersion.Series = config.DefaultSeries mtools0 := waitAgentTools(c, mw0, expectedVersion) // Create a new service and deploy a unit of it. c.Logf("deploying service") repoDir := c.MkDir() url := coretesting.Charms.ClonedURL(repoDir, mtools0.Series, "dummy") sch, err := conn.PutCharm(url, &charm.LocalRepository{repoDir}, false) c.Assert(err, IsNil) svc, err := conn.State.AddService("dummy", sch) c.Assert(err, IsNil) units, err := conn.AddUnits(svc, 1, "") c.Assert(err, IsNil) unit := units[0] // Wait for the unit's machine and associated agent to come up // and announce itself. mid1, err := unit.AssignedMachineId() c.Assert(err, IsNil) m1, err := conn.State.Machine(mid1) c.Assert(err, IsNil) mw1 := newMachineToolWaiter(m1) defer mw1.Stop() waitAgentTools(c, mw1, mtools0.Binary) err = m1.Refresh() c.Assert(err, IsNil) instId1, err := m1.InstanceId() c.Assert(err, IsNil) uw := newUnitToolWaiter(unit) defer uw.Stop() utools := waitAgentTools(c, uw, expectedVersion) // Check that we can upgrade the environment. newVersion := utools.Binary newVersion.Patch++ t.checkUpgrade(c, conn, newVersion, mw0, mw1, uw) // BUG(niemeyer): Logic below is very much wrong. Must be: // // 1. EnsureDying on the unit and EnsureDying on the machine // 2. Unit dies by itself // 3. Machine removes dead unit // 4. Machine dies by itself // 5. Provisioner removes dead machine // // Now remove the unit and its assigned machine and // check that the PA removes it. c.Logf("removing unit") err = unit.Destroy() c.Assert(err, IsNil) // Wait until unit is dead uwatch := unit.Watch() defer uwatch.Stop() for unit.Life() != state.Dead { c.Logf("waiting for unit change") <-uwatch.Changes() err := unit.Refresh() c.Logf("refreshed; err %v", err) if errors.IsNotFoundError(err) { c.Logf("unit has been removed") break } c.Assert(err, IsNil) } for { c.Logf("destroying machine") err := m1.Destroy() if err == nil { break } c.Assert(err, FitsTypeOf, &state.HasAssignedUnitsError{}) time.Sleep(5 * time.Second) err = m1.Refresh() if errors.IsNotFoundError(err) { break } c.Assert(err, IsNil) } c.Logf("waiting for instance to be removed") t.assertStopInstance(c, conn.Environ, instId1) }
func (t *LiveTests) TestBootstrapAndDeploy(c *C) { if !t.CanOpenState || !t.HasProvisioner { c.Skip(fmt.Sprintf("skipping provisioner test, CanOpenState: %v, HasProvisioner: %v", t.CanOpenState, t.HasProvisioner)) } t.BootstrapOnce(c) // TODO(niemeyer): Stop growing this kitchen sink test and split it into proper parts. c.Logf("opening connection") conn, err := juju.NewConn(t.Env) c.Assert(err, IsNil) defer conn.Close() // Check that the agent version has made it through the // bootstrap process (it's optional in the config.Config) cfg, err := conn.State.EnvironConfig() c.Assert(err, IsNil) c.Check(cfg.AgentVersion(), Equals, version.Current.Number) // Wait for machine agent to come up on the bootstrap // machine and find the deployed series from that. m0, err := conn.State.Machine("0") c.Assert(err, IsNil) mw0 := newMachineToolWaiter(m0) defer mw0.Stop() mtools0 := waitAgentTools(c, mw0, version.Current) // Create a new service and deploy a unit of it. c.Logf("deploying service") repoDir := c.MkDir() url := coretesting.Charms.ClonedURL(repoDir, mtools0.Series, "dummy") sch, err := conn.PutCharm(url, &charm.LocalRepository{repoDir}, false) c.Assert(err, IsNil) svc, err := conn.AddService("", sch) c.Assert(err, IsNil) units, err := conn.AddUnits(svc, 1) c.Assert(err, IsNil) unit := units[0] // Wait for the unit's machine and associated agent to come up // and announce itself. mid1, err := unit.AssignedMachineId() c.Assert(err, IsNil) m1, err := conn.State.Machine(mid1) c.Assert(err, IsNil) mw1 := newMachineToolWaiter(m1) defer mw1.Stop() waitAgentTools(c, mw1, mtools0.Binary) err = m1.Refresh() c.Assert(err, IsNil) instId1, err := m1.InstanceId() c.Assert(err, IsNil) uw := newUnitToolWaiter(unit) defer uw.Stop() utools := waitAgentTools(c, uw, version.Current) // Check that we can upgrade the environment. newVersion := utools.Binary newVersion.Patch++ t.checkUpgrade(c, conn, newVersion, mw0, mw1, uw) // BUG(niemeyer): Logic below is very much wrong. Must be: // // 1. EnsureDying on the unit and EnsureDying on the machine // 2. Unit dies by itself // 3. Machine removes dead unit // 4. Machine dies by itself // 5. Provisioner removes dead machine // // Now remove the unit and its assigned machine and // check that the PA removes it. c.Logf("removing unit") err = unit.EnsureDead() c.Assert(err, IsNil) err = svc.RemoveUnit(unit) c.Assert(err, IsNil) err = m1.EnsureDead() c.Assert(err, IsNil) err = conn.State.RemoveMachine(mid1) c.Assert(err, IsNil) c.Logf("waiting for instance to be removed") t.assertStopInstance(c, conn.Environ, instId1) }