Beispiel #1
0
func (s *deployerSuite) TestUnitRemove(c *gc.C) {
	unit, err := s.st.Unit(s.principal.Tag())
	c.Assert(err, gc.IsNil)

	// It fails because the entity is still alive.
	// And EnsureDead will fail because there is a subordinate.
	err = unit.Remove()
	c.Assert(err, gc.ErrorMatches, `cannot remove entity "unit-mysql-0": still alive`)
	c.Assert(params.ErrCode(err), gc.Equals, "")

	// With the subordinate it also fails due to it being alive.
	unit, err = s.st.Unit(s.subordinate.Tag())
	c.Assert(err, gc.IsNil)
	err = unit.Remove()
	c.Assert(err, gc.ErrorMatches, `cannot remove entity "unit-logging-0": still alive`)
	c.Assert(params.ErrCode(err), gc.Equals, "")

	// Make it dead first and try again.
	err = s.subordinate.EnsureDead()
	c.Assert(err, gc.IsNil)
	err = unit.Remove()
	c.Assert(err, gc.IsNil)

	// Verify it's gone.
	err = unit.Refresh()
	s.assertUnauthorized(c, err)
	unit, err = s.st.Unit(s.subordinate.Tag())
	s.assertUnauthorized(c, err)
	c.Assert(unit, gc.IsNil)
}
Beispiel #2
0
func (s *uniterSuite) TestEnsureDead(c *gc.C) {
	c.Assert(s.unit.Life(), gc.Equals, state.Alive)

	unit, err := s.uniter.Unit("unit-wordpress-0")
	c.Assert(err, gc.IsNil)

	err = unit.EnsureDead()
	c.Assert(err, gc.IsNil)

	err = s.unit.Refresh()
	c.Assert(err, gc.IsNil)
	c.Assert(s.unit.Life(), gc.Equals, state.Dead)

	err = unit.EnsureDead()
	c.Assert(err, gc.IsNil)
	err = s.unit.Refresh()
	c.Assert(err, gc.IsNil)
	c.Assert(s.unit.Life(), gc.Equals, state.Dead)

	err = s.unit.Remove()
	c.Assert(err, gc.IsNil)
	err = s.unit.Refresh()
	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)

	err = unit.EnsureDead()
	c.Assert(err, gc.ErrorMatches, `unit "wordpress/0" not found`)
	c.Assert(params.ErrCode(err), gc.Equals, params.CodeNotFound)
}
Beispiel #3
0
func opClientDestroyRelation(c *C, st *api.State, mst *state.State) (func(), error) {
	err := st.Client().DestroyRelation("nosuch1", "nosuch2")
	if params.ErrCode(err) == params.CodeNotFound {
		err = nil
	}
	return func() {}, err
}
Beispiel #4
0
func opClientServiceSetCharm(c *C, st *api.State, mst *state.State) (func(), error) {
	err := st.Client().ServiceSetCharm("nosuch", "local:series/wordpress", false)
	if params.ErrCode(err) == params.CodeNotFound {
		err = nil
	}
	return func() {}, err
}
Beispiel #5
0
func (s *upgraderSuite) TestSetToolsWrongMachine(c *C) {
	err := s.st.SetTools("42", &tools.Tools{
		Version: version.Current,
	})
	c.Assert(err, ErrorMatches, "permission denied")
	c.Assert(params.ErrCode(err), Equals, params.CodeUnauthorized)
}
Beispiel #6
0
func opClientAddServiceUnits(c *C, st *api.State, mst *state.State) (func(), error) {
	_, err := st.Client().AddServiceUnits("nosuch", 1)
	if params.ErrCode(err) == params.CodeNotFound {
		err = nil
	}
	return func() {}, err
}
Beispiel #7
0
func opClientServiceDestroy(c *C, st *api.State, mst *state.State) (func(), error) {
	err := st.Client().ServiceDestroy("non-existent")
	if params.ErrCode(err) == params.CodeNotFound {
		err = nil
	}
	return func() {}, err
}
Beispiel #8
0
// OpenAPI tries to open the state using the given Conf.  If it
// returns a non-empty newPassword, the password used to connect
// to the state should be changed accordingly - the caller should write the
// configuration with StateInfo.Password set to newPassword, then
// set the entity's password accordingly.
func (c *Conf) OpenAPI(dialOpts api.DialOpts) (st *api.State, newPassword string, err error) {
	info := *c.APIInfo
	info.Nonce = c.MachineNonce
	if info.Password != "" {
		st, err := api.Open(&info, dialOpts)
		if err == nil {
			return st, "", nil
		}
		if params.ErrCode(err) != params.CodeUnauthorized {
			return nil, "", err
		}
		// Access isn't authorized even though we have a password
		// This can happen if we crash after saving the
		// password but before changing it, so we'll try again
		// with the old password.
	}
	info.Password = c.OldPassword
	st, err = api.Open(&info, dialOpts)
	if err != nil {
		return nil, "", err
	}
	// We've succeeded in connecting with the old password, so
	// we can now change it to something more private.
	password, err := utils.RandomPassword()
	if err != nil {
		st.Close()
		return nil, "", err
	}
	return st, password, nil
}
Beispiel #9
0
func (s *machinerSuite) TestEnsureDead(c *C) {
	c.Assert(s.machine.Life(), Equals, state.Alive)

	machine, err := s.st.Machiner().Machine("machine-0")
	c.Assert(err, IsNil)

	err = machine.EnsureDead()
	c.Assert(err, IsNil)

	err = s.machine.Refresh()
	c.Assert(err, IsNil)
	c.Assert(s.machine.Life(), Equals, state.Dead)

	err = machine.EnsureDead()
	c.Assert(err, IsNil)
	err = s.machine.Refresh()
	c.Assert(err, IsNil)
	c.Assert(s.machine.Life(), Equals, state.Dead)

	err = s.machine.Remove()
	c.Assert(err, IsNil)
	err = s.machine.Refresh()
	c.Assert(err, checkers.Satisfies, errors.IsNotFoundError)

	err = machine.EnsureDead()
	c.Assert(err, ErrorMatches, "machine 0 not found")
	c.Assert(params.ErrCode(err), Equals, params.CodeNotFound)
}
Beispiel #10
0
func isFatal(err error) bool {
	isTerminate := err == worker.ErrTerminateAgent
	notProvisioned := params.ErrCode(err) == params.CodeNotProvisioned
	if isTerminate || notProvisioned || isUpgraded(err) {
		return true
	}
	_, ok := err.(*fatalError)
	return ok
}
Beispiel #11
0
func (s *machinerSuite) TestMachineAndMachineTag(c *gc.C) {
	machine, err := s.machiner.Machine("machine-42")
	c.Assert(err, gc.ErrorMatches, "permission denied")
	c.Assert(params.ErrCode(err), gc.Equals, params.CodeUnauthorized)
	c.Assert(machine, gc.IsNil)

	machine, err = s.machiner.Machine("machine-0")
	c.Assert(err, gc.IsNil)
	c.Assert(machine.Tag(), gc.Equals, "machine-0")
}
Beispiel #12
0
func (s *machinerSuite) TestMachineAndMachineId(c *C) {
	machine, err := s.st.Machiner().Machine("machine-42")
	c.Assert(err, ErrorMatches, "permission denied")
	c.Assert(params.ErrCode(err), Equals, params.CodeUnauthorized)
	c.Assert(machine, IsNil)

	machine, err = s.st.Machiner().Machine("machine-0")
	c.Assert(err, IsNil)
	c.Assert(machine.Tag(), Equals, "machine-0")
}
Beispiel #13
0
func (s *uniterSuite) TestUnitAndUnitTag(c *gc.C) {
	unit, err := s.uniter.Unit("unit-foo-42")
	c.Assert(err, gc.ErrorMatches, "permission denied")
	c.Assert(params.ErrCode(err), gc.Equals, params.CodeUnauthorized)
	c.Assert(unit, gc.IsNil)

	unit, err = s.uniter.Unit("unit-wordpress-0")
	c.Assert(err, gc.IsNil)
	c.Assert(unit.Tag(), gc.Equals, "unit-wordpress-0")
}
Beispiel #14
0
func (s *suite) TestMachine(c *C) {
	m, err := s.st.MachineAgent().Machine("42")
	c.Assert(err, ErrorMatches, "permission denied")
	c.Assert(params.ErrCode(err), Equals, params.CodeUnauthorized)
	c.Assert(m, IsNil)

	m, err = s.st.MachineAgent().Machine(s.machine.Tag())
	c.Assert(err, IsNil)
	c.Assert(m.Tag(), Equals, s.machine.Tag())
	c.Assert(m.Life(), Equals, params.Alive)
	c.Assert(m.Jobs(), DeepEquals, []params.MachineJob{params.JobHostUnits})

	err = s.machine.EnsureDead()
	c.Assert(err, IsNil)
	err = s.machine.Remove()
	c.Assert(err, IsNil)

	m, err = s.st.MachineAgent().Machine(s.machine.Tag())
	c.Assert(err, ErrorMatches, fmt.Sprintf("machine %s not found", s.machine.Id()))
	c.Assert(params.ErrCode(err), Equals, params.CodeNotFound)
	c.Assert(m, IsNil)
}
Beispiel #15
0
func (s *unitSuite) TestUnitEntity(c *gc.C) {
	m, err := s.st.Agent().Entity("wordpress/1")
	c.Assert(err, gc.ErrorMatches, "permission denied")
	c.Assert(params.ErrCode(err), gc.Equals, params.CodeUnauthorized)
	c.Assert(m, gc.IsNil)

	m, err = s.st.Agent().Entity(s.unit.Tag())
	c.Assert(err, gc.IsNil)
	c.Assert(m.Tag(), gc.Equals, s.unit.Tag())
	c.Assert(m.Life(), gc.Equals, params.Alive)
	c.Assert(m.Jobs(), gc.HasLen, 0)

	err = s.unit.EnsureDead()
	c.Assert(err, gc.IsNil)
	err = s.unit.Remove()
	c.Assert(err, gc.IsNil)

	m, err = s.st.Agent().Entity(s.unit.Tag())
	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("unit %q not found", s.unit.Name()))
	c.Assert(params.ErrCode(err), gc.Equals, params.CodeNotFound)
	c.Assert(m, gc.IsNil)
}
Beispiel #16
0
// commonLoop implements the loop structure common to the client
// watchers. It should be started in a separate goroutine by any
// watcher that embeds commonWatcher. It kills the commonWatcher's
// tomb when an error occurs.
func (w *commonWatcher) commonLoop() {
	defer close(w.in)
	w.wg.Add(1)
	go func() {
		// When the watcher has been stopped, we send a Stop request
		// to the server, which will remove the watcher and return a
		// CodeStopped error to any currently outstanding call to
		// Next. If a call to Next happens just after the watcher has
		// been stopped, we'll get a CodeNotFound error; Either way
		// we'll return, wait for the stop request to complete, and
		// the watcher will die with all resources cleaned up.
		defer w.wg.Done()
		<-w.tomb.Dying()
		if err := w.call("Stop", nil); err != nil {
			log.Errorf("state/api: error trying to stop watcher %v", err)
		}
	}()
	w.wg.Add(1)
	go func() {
		// Because Next blocks until there are changes, we need to
		// call it in a separate goroutine, so the watcher can be
		// stopped normally.
		defer w.wg.Done()
		for {
			result := w.newResult()
			err := w.call("Next", &result)
			if err != nil {
				if code := params.ErrCode(err); code == params.CodeStopped || code == params.CodeNotFound {
					if w.tomb.Err() != tomb.ErrStillAlive {
						// The watcher has been stopped at the client end, so we're
						// expecting one of the above two kinds of error.
						// We might see the same errors if the server itself
						// has been shut down, in which case we leave them
						// untouched.
						err = tomb.ErrDying
					}
				}
				// Something went wrong, just report the error and bail out.
				w.tomb.Kill(err)
				return
			}
			select {
			case <-w.tomb.Dying():
				return
			case w.in <- result:
				// Report back the result we just got.
			}
		}
	}()
	w.wg.Wait()
}
func (s *upgraderSuite) TestSetToolsWrongMachine(c *C) {
	cur := version.Current
	err := s.st.SetTools(params.AgentTools{
		Tag:    "42",
		Arch:   cur.Arch,
		Series: cur.Series,
		Major:  cur.Major,
		Minor:  cur.Minor,
		Patch:  cur.Patch,
		Build:  cur.Build,
	})
	c.Assert(err, ErrorMatches, "permission denied")
	c.Assert(params.ErrCode(err), Equals, params.CodeUnauthorized)
}
Beispiel #18
0
func opClientServiceUpdate(c *C, st *api.State, mst *state.State) (func(), error) {
	args := params.ServiceUpdate{
		ServiceName:     "no-such-charm",
		CharmUrl:        "cs:series/wordpress-42",
		ForceCharmUrl:   true,
		SettingsStrings: map[string]string{"blog-title": "foo"},
		SettingsYAML:    `"wordpress": {"blog-title": "foo"}`,
	}
	err := st.Client().ServiceUpdate(args)
	if params.ErrCode(err) == params.CodeNotFound {
		err = nil
	}
	return func() {}, err
}
Beispiel #19
0
func (s *loginSuite) TestBadLogin(c *C) {
	// Start our own server so we can control when the first login
	// happens. Otherwise in JujuConnSuite.SetUpTest api.Open is
	// called with user-admin permissions automatically.
	srv, err := apiserver.NewServer(
		s.State,
		"localhost:0",
		[]byte(coretesting.ServerCert),
		[]byte(coretesting.ServerKey),
	)
	c.Assert(err, IsNil)
	defer func() {
		err := srv.Stop()
		c.Assert(err, IsNil)
	}()

	info := &api.Info{
		Tag:      "",
		Password: "",
		Addrs:    []string{srv.Addr()},
		CACert:   []byte(coretesting.CACert),
	}
	for i, t := range badLoginTests {
		c.Logf("test %d; entity %q; password %q", i, t.tag, t.password)
		// Note that Open does not log in if the tag and password
		// are empty. This allows us to test operations on the connection
		// before calling Login, which we could not do if Open
		// always logged in.
		info.Tag = ""
		info.Password = ""
		func() {
			st, err := api.Open(info, fastDialOpts)
			c.Assert(err, IsNil)
			defer st.Close()

			_, err = st.Machiner().Machine("0")
			c.Assert(err, ErrorMatches, `unknown object type "Machiner"`)

			// Since these are user login tests, the nonce is empty.
			err = st.Login(t.tag, t.password, "")
			c.Assert(err, ErrorMatches, t.err)
			c.Assert(params.ErrCode(err), Equals, t.code)

			_, err = st.Machiner().Machine("0")
			c.Assert(err, ErrorMatches, `unknown object type "Machiner"`)
		}()
	}
}
Beispiel #20
0
func opClientResolved(c *C, st *api.State, _ *state.State) (func(), error) {
	err := st.Client().Resolved("wordpress/0", false)
	// There are several scenarios in which this test is called, one is
	// that the user is not authorized.  In that case we want to exit now,
	// letting the error percolate out so the caller knows that the
	// permission error was correctly generated.
	if err != nil && params.ErrCode(err) == params.CodeUnauthorized {
		return func() {}, err
	}
	// Otherwise, the user was authorized, but we expect an error anyway
	// because the unit is not in an error state when we tried to resolve
	// the error.  Therefore, since it is complaining it means that the
	// call to Resolved worked, so we're happy.
	c.Assert(err, NotNil)
	c.Assert(err.Error(), Equals, `unit "wordpress/0" is not in an error state`)
	return func() {}, nil
}
Beispiel #21
0
func (s *permSuite) TestOperationPerm(c *C) {
	entities := s.setUpScenario(c)
	for i, t := range operationPermTests {
		allow := allowed(entities, t.allow, t.deny)
		for _, e := range entities {
			c.Logf("test %d; %s; entity %q", i, t.about, e)
			st := s.openAs(c, e)
			reset, err := t.op(c, st, s.State)
			if allow[e] {
				c.Check(err, IsNil)
			} else {
				c.Check(err, ErrorMatches, "permission denied")
				c.Check(params.ErrCode(err), Equals, params.CodeUnauthorized)
			}
			reset()
			st.Close()
		}
	}
}
Beispiel #22
0
func openAPIState(c *agent.Conf, a Agent) (*api.State, AgentAPIState, error) {
	// We let the API dial fail immediately because the
	// runner's loop outside the caller of openAPIState will
	// keep on retrying. If we block for ages here,
	// then the worker that's calling this cannot
	// be interrupted.
	st, newPassword, err := c.OpenAPI(api.DialOpts{})
	if err != nil {
		return nil, nil, err
	}
	entity, err := a.APIEntity(st)
	if params.ErrCode(err) == params.CodeNotFound || err == nil && entity.Life() == params.Dead {
		err = worker.ErrTerminateAgent
	}
	if err != nil {
		st.Close()
		return nil, nil, err
	}
	if newPassword == "" {
		return st, entity, nil
	}
	// Make a copy of the configuration so that if we fail
	// to write the configuration file, the configuration will
	// still be valid.
	c1 := *c
	stateInfo := *c.StateInfo
	c1.StateInfo = &stateInfo
	apiInfo := *c.APIInfo
	c1.APIInfo = &apiInfo

	c1.StateInfo.Password = newPassword
	c1.APIInfo.Password = newPassword
	if err := c1.Write(); err != nil {
		return nil, nil, err
	}
	*c = c1
	if err := entity.SetPassword(newPassword); err != nil {
		return nil, nil, err
	}
	return st, entity, nil

}
Beispiel #23
0
// ServerError returns an error suitable for returning to an API
// client, with an error code suitable for various kinds of errors
// generated in packages outside the API.
func ServerError(err error) *params.Error {
	if err == nil {
		return nil
	}
	code := singletonErrorCodes[err]
	switch {
	case code != "":
	case errors.IsUnauthorizedError(err):
		code = params.CodeUnauthorized
	case errors.IsNotFoundError(err):
		code = params.CodeNotFound
	case state.IsNotAssigned(err):
		code = params.CodeNotAssigned
	case state.IsHasAssignedUnitsError(err):
		code = params.CodeHasAssignedUnits
	default:
		code = params.ErrCode(err)
	}
	return &params.Error{
		Message: err.Error(),
		Code:    code,
	}
}
Beispiel #24
0
func (s *deployerSuite) assertUnauthorized(c *gc.C, err error) {
	c.Assert(err, gc.ErrorMatches, "permission denied")
	c.Assert(params.ErrCode(err), gc.Equals, params.CodeUnauthorized)
}
Beispiel #25
0
func (s *upgraderSuite) TestToolsWrongMachine(c *C) {
	tools, err := s.st.Tools("42")
	c.Assert(err, ErrorMatches, "permission denied")
	c.Assert(params.ErrCode(err), Equals, params.CodeUnauthorized)
	c.Assert(tools, IsNil)
}
Beispiel #26
0
func isNotFoundOrUnauthorized(err error) bool {
	return errors.IsNotFoundError(err) || params.ErrCode(err) == params.CodeUnauthorized
}