github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/unitagent.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/juju/names.v2" 9 10 "github.com/juju/juju/status" 11 ) 12 13 // UnitAgent represents the state of a service's unit agent. 14 type UnitAgent struct { 15 st *State 16 tag names.Tag 17 name string 18 status.StatusHistoryGetter 19 } 20 21 func newUnitAgent(st *State, tag names.Tag, name string) *UnitAgent { 22 unitAgent := &UnitAgent{ 23 st: st, 24 tag: tag, 25 name: name, 26 } 27 28 return unitAgent 29 } 30 31 // String returns the unit agent as string. 32 func (u *UnitAgent) String() string { 33 return u.name 34 } 35 36 // Status returns the status of the unit agent. 37 func (u *UnitAgent) Status() (status.StatusInfo, error) { 38 info, err := getStatus(u.st, u.globalKey(), "agent") 39 if err != nil { 40 return status.StatusInfo{}, errors.Trace(err) 41 } 42 // The current health spec says when a hook error occurs, the workload should 43 // be in error state, but the state model more correctly records the agent 44 // itself as being in error. So we'll do that model translation here. 45 // TODO(fwereade): this should absolutely not be happpening in the model. 46 if info.Status == status.Error { 47 return status.StatusInfo{ 48 Status: status.Idle, 49 Message: "", 50 Data: map[string]interface{}{}, 51 Since: info.Since, 52 }, nil 53 } 54 return info, nil 55 } 56 57 // SetStatus sets the status of the unit agent. The optional values 58 // allow to pass additional helpful status data. 59 func (u *UnitAgent) SetStatus(unitAgentStatus status.StatusInfo) (err error) { 60 switch unitAgentStatus.Status { 61 case status.Idle, status.Executing, status.Rebooting, status.Failed: 62 case status.Error: 63 if unitAgentStatus.Message == "" { 64 return errors.Errorf("cannot set status %q without info", unitAgentStatus.Status) 65 } 66 case status.Allocating, status.Lost: 67 return errors.Errorf("cannot set status %q", unitAgentStatus.Status) 68 default: 69 return errors.Errorf("cannot set invalid status %q", unitAgentStatus.Status) 70 } 71 return setStatus(u.st, setStatusParams{ 72 badge: "agent", 73 globalKey: u.globalKey(), 74 status: unitAgentStatus.Status, 75 message: unitAgentStatus.Message, 76 rawData: unitAgentStatus.Data, 77 updated: unitAgentStatus.Since, 78 }) 79 } 80 81 // StatusHistory returns a slice of at most filter.Size StatusInfo items 82 // or items as old as filter.Date or items newer than now - filter.Delta time 83 // representing past statuses for this agent. 84 func (u *UnitAgent) StatusHistory(filter status.StatusHistoryFilter) ([]status.StatusInfo, error) { 85 args := &statusHistoryArgs{ 86 st: u.st, 87 globalKey: u.globalKey(), 88 filter: filter, 89 } 90 return statusHistory(args) 91 } 92 93 // unitAgentGlobalKey returns the global database key for the named unit. 94 func unitAgentGlobalKey(name string) string { 95 return "u#" + name 96 } 97 98 // globalKey returns the global database key for the unit. 99 func (u *UnitAgent) globalKey() string { 100 return unitAgentGlobalKey(u.name) 101 } 102 103 // Tag returns a names.Tag identifying this agent's unit. 104 func (u *UnitAgent) Tag() names.Tag { 105 return u.tag 106 }