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) }
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) }
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 }
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 }
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) }
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 }
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 }
// 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 }
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) }
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 }
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") }
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") }
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") }
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) }
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) }
// 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) }
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 }
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"`) }() } }
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 }
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() } } }
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 }
// 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 ¶ms.Error{ Message: err.Error(), Code: code, } }
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) }
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) }
func isNotFoundOrUnauthorized(err error) bool { return errors.IsNotFoundError(err) || params.ErrCode(err) == params.CodeUnauthorized }