// processUnitAndAgentStatus retrieves status information for both unit and unitAgents. func processUnitAndAgentStatus(unit *state.Unit, status *params.UnitStatus) { status.UnitAgent, status.Workload = processUnitStatus(unit) // Legacy fields required until Juju 2.0. // We only display pending, started, error, stopped. var ok bool legacyState, ok := state.TranslateToLegacyAgentState( state.Status(status.UnitAgent.Status), state.Status(status.Workload.Status), status.Workload.Info, ) if !ok { logger.Warningf( "translate to legacy status encounted unexpected workload status %q and agent status %q", status.Workload.Status, status.UnitAgent.Status) } status.AgentState = params.Status(legacyState) if status.AgentState == params.StatusError { status.AgentStateInfo = status.Workload.Info } status.AgentVersion = status.UnitAgent.Version status.Life = status.UnitAgent.Life status.Err = status.UnitAgent.Err processUnitLost(unit, status) return }
func (s *serviceSuite) TestSetServiceStatus(c *gc.C) { message := "a test message" stat, err := s.wordpressService.Status() c.Assert(stat.Status, gc.Not(gc.Equals), state.Status(params.StatusActive)) c.Assert(stat.Message, gc.Not(gc.Equals), message) err = s.apiService.SetStatus(s.wordpressUnit.Name(), params.StatusActive, message, map[string]interface{}{}) c.Assert(err, gc.ErrorMatches, "this unit is not the leader") s.claimLeadership(c, s.wordpressUnit, s.wordpressService) err = s.apiService.SetStatus(s.wordpressUnit.Name(), params.StatusActive, message, map[string]interface{}{}) c.Assert(err, jc.ErrorIsNil) stat, err = s.wordpressService.Status() c.Assert(err, jc.ErrorIsNil) c.Assert(stat.Status, gc.Equals, state.Status(params.StatusActive)) c.Assert(stat.Message, gc.Equals, message) }
func (s *StatusSetter) setEntityStatus(tag names.Tag, status params.Status, info string, data map[string]interface{}) error { entity, err := s.st.FindEntity(tag) if err != nil { return err } switch entity := entity.(type) { case state.StatusSetter: return entity.SetStatus(state.Status(status), info, data) default: return NotSupportedError(tag, fmt.Sprintf("setting status, %T", entity)) } }
func (s *StatusModelSuite) TestUnitAgentStatusDocValidation(c *gc.C) { unit := s.Factory.MakeUnit(c, nil) for i, test := range []struct { status state.Status info string err string }{{ status: state.StatusPending, err: `cannot set invalid status "pending"`, }, { status: state.StatusDown, err: `cannot set invalid status "down"`, }, { status: state.StatusStarted, err: `cannot set invalid status "started"`, }, { status: state.StatusStopped, err: `cannot set invalid status "stopped"`, }, { status: state.StatusAllocating, err: `cannot set status "allocating"`, }, { status: state.StatusAllocating, info: "any message", err: `cannot set status "allocating"`, }, { status: state.StatusLost, err: `cannot set status "lost"`, }, { status: state.StatusLost, info: "any message", err: `cannot set status "lost"`, }, { status: state.StatusError, err: `cannot set status "error" without info`, }, { status: state.StatusError, info: "some error info", }, { status: state.Status("bogus"), err: `cannot set invalid status "bogus"`, }} { c.Logf("test %d", i) err := unit.SetAgentStatus(test.status, test.info, nil) if test.err != "" { c.Check(err, gc.ErrorMatches, test.err) } else { c.Check(err, jc.ErrorIsNil) } } }
func matchAgentStatus(patterns []string, status state.Status) (bool, bool, error) { oneValidStatus := false for _, p := range patterns { // If the pattern isn't a known status, ignore it. ps := state.Status(p) if !ps.KnownAgentStatus() { continue } oneValidStatus = true if status.Matches(ps) { return true, true, nil } } return false, oneValidStatus, nil }
func matchWorkloadStatus(patterns []string, workloadStatus state.Status, agentStatus state.Status) (bool, bool, error) { oneValidStatus := false for _, p := range patterns { // If the pattern isn't a known status, ignore it. ps := state.Status(p) if !ps.KnownWorkloadStatus() { continue } oneValidStatus = true // To preserve current expected behaviour, we only report on workload status // if the agent itself is not in error. if agentStatus != state.StatusError && workloadStatus.WorkloadMatches(ps) { return true, true, nil } } return false, oneValidStatus, nil }
func (s *UnitAgentSuite) TestGetSetStatusWhileAlive(c *gc.C) { agent := s.unit.Agent().(*state.UnitAgent) err := agent.SetStatus(state.StatusError, "", nil) c.Assert(err, gc.ErrorMatches, `cannot set status "error" without info`) err = agent.SetStatus(state.Status("vliegkat"), "orville", nil) c.Assert(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) statusInfo, err := agent.Status() c.Assert(err, jc.ErrorIsNil) c.Assert(statusInfo.Status, gc.Equals, state.StatusAllocating) c.Assert(statusInfo.Message, gc.Equals, "") c.Assert(statusInfo.Data, gc.HasLen, 0) err = agent.SetStatus(state.StatusIdle, "", nil) c.Assert(err, jc.ErrorIsNil) statusInfo, err = agent.Status() c.Assert(err, jc.ErrorIsNil) c.Assert(statusInfo.Status, gc.Equals, state.StatusIdle) c.Assert(statusInfo.Message, gc.Equals, "") c.Assert(statusInfo.Data, gc.HasLen, 0) err = agent.SetStatus(state.StatusError, "test-hook failed", map[string]interface{}{ "foo": "bar", }) c.Assert(err, jc.ErrorIsNil) // Agent error is reported as unit error. statusInfo, err = s.unit.Status() c.Assert(err, jc.ErrorIsNil) c.Assert(statusInfo.Status, gc.Equals, state.StatusError) c.Assert(statusInfo.Message, gc.Equals, "test-hook failed") c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{ "foo": "bar", }) // For agents, error is reported as idle. statusInfo, err = agent.Status() c.Assert(err, jc.ErrorIsNil) c.Assert(statusInfo.Status, gc.Equals, state.StatusIdle) c.Assert(statusInfo.Message, gc.Equals, "") c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{}) }
func serviceSetStatus(s *ServiceStatusSetter, args params.SetStatus, getService serviceGetter, isLeaderCheck isLeaderFunc) (params.ErrorResults, error) { result := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.Entities)), } if len(args.Entities) == 0 { return result, nil } canModify, err := s.getCanModify() if err != nil { return params.ErrorResults{}, err } for i, arg := range args.Entities { leader, err := isLeaderCheck(s.st, arg.Tag) if err != nil { result.Results[i].Error = ServerError(err) continue } if !leader { result.Results[i].Error = ServerError(ErrIsNotLeader) continue } service, err := getService(s.st, arg.Tag) if err != nil { result.Results[i].Error = ServerError(err) continue } if !canModify(service.Tag()) { result.Results[i].Error = ServerError(ErrPerm) continue } if err := service.SetStatus(state.Status(arg.Status), arg.Info, arg.Data); err != nil { result.Results[i].Error = ServerError(err) } } return result, nil }
func (s *FilesystemStatusSuite) TestSetUnknownStatus(c *gc.C) { err := s.filesystem.SetStatus(state.Status("vliegkat"), "orville", nil) c.Assert(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) s.checkInitialStatus(c) }
func (s *StatusUnitAgentSuite) TestSetUnknownStatus(c *gc.C) { err := s.agent.SetStatus(state.Status("vliegkat"), "orville", nil) c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) s.checkInitialStatus(c) }
// SetStatus sets the status on the service given by the unit in args if the unit is the leader. func (s *ServiceStatusSetter) SetStatus(args params.SetStatus) (params.ErrorResults, error) { result := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.Entities)), } if len(args.Entities) == 0 { return result, nil } canModify, err := s.getCanModify() if err != nil { return params.ErrorResults{}, err } for i, arg := range args.Entities { // TODO(fwereade): the auth is basically nonsense, and basically only // works by coincidence. Read carefully. // We "know" that arg.Tag is either the calling unit or its service // (because getCanModify is authUnitOrService, and we'll fail out if // it isn't); and, in practice, it's always going to be the calling // unit (because, /sigh, we don't actually use service tags to refer // to services in this method). tag, err := names.ParseTag(arg.Tag) if err != nil { result.Results[i].Error = ServerError(err) continue } if !canModify(tag) { result.Results[i].Error = ServerError(ErrPerm) continue } unitTag, ok := tag.(names.UnitTag) if !ok { // No matter what the canModify says, if this entity is not // a unit, we say "NO". result.Results[i].Error = ServerError(ErrPerm) continue } unitId := unitTag.Id() // Now we have the unit, we can get the service that should have been // specified in the first place... serviceId, err := names.UnitService(unitId) if err != nil { result.Results[i].Error = ServerError(err) continue } service, err := s.st.Service(serviceId) if err != nil { result.Results[i].Error = ServerError(err) continue } // ...and set the status, conditional on the unit being (and remaining) // service leader. checker := s.st.LeadershipChecker() token := checker.LeadershipCheck(serviceId, unitId) // TODO(fwereade) pass token into SetStatus instead of checking here. if err := token.Check(nil); err != nil { // TODO(fwereade) this should probably be ErrPerm is certain cases, // but I don't think I implemented an exported ErrNotLeader. I // should have done, though. result.Results[i].Error = ServerError(err) continue } if err := service.SetStatus(state.Status(arg.Status), arg.Info, arg.Data); err != nil { result.Results[i].Error = ServerError(err) } } return result, nil }