예제 #1
0
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)
}
예제 #2
0
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, &current.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)
}
예제 #3
0
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
}
예제 #4
0
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)
}
예제 #5
0
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()
}
예제 #6
0
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)
}
예제 #7
0
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
}
예제 #8
0
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()}
}
예제 #9
0
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()
}
예제 #10
0
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)
}
예제 #11
0
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")
}
예제 #12
0
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)
}
예제 #13
0
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, &current.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)
}
예제 #14
0
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)
}
예제 #15
0
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)
}