github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/status_unitagent_test.go (about) 1 // Copyright 2012-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "time" 8 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/state" 13 "github.com/juju/juju/status" 14 ) 15 16 type StatusUnitAgentSuite struct { 17 ConnSuite 18 unit *state.Unit 19 agent *state.UnitAgent 20 } 21 22 var _ = gc.Suite(&StatusUnitAgentSuite{}) 23 24 func (s *StatusUnitAgentSuite) SetUpTest(c *gc.C) { 25 s.ConnSuite.SetUpTest(c) 26 s.unit = s.Factory.MakeUnit(c, nil) 27 s.agent = s.unit.Agent() 28 } 29 30 func (s *StatusUnitAgentSuite) TestInitialStatus(c *gc.C) { 31 s.checkInitialStatus(c) 32 } 33 34 func (s *StatusUnitAgentSuite) checkInitialStatus(c *gc.C) { 35 statusInfo, err := s.agent.Status() 36 c.Check(err, jc.ErrorIsNil) 37 checkInitialUnitAgentStatus(c, statusInfo) 38 } 39 40 func (s *StatusUnitAgentSuite) TestSetUnknownStatus(c *gc.C) { 41 err := s.agent.SetStatus(status.Status("vliegkat"), "orville", nil) 42 c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) 43 44 s.checkInitialStatus(c) 45 } 46 47 func (s *StatusUnitAgentSuite) TestSetErrorStatusWithoutInfo(c *gc.C) { 48 err := s.agent.SetStatus(status.StatusError, "", nil) 49 c.Check(err, gc.ErrorMatches, `cannot set status "error" without info`) 50 51 s.checkInitialStatus(c) 52 } 53 54 func (s *StatusUnitAgentSuite) TestSetOverwritesData(c *gc.C) { 55 err := s.agent.SetStatus(status.StatusIdle, "something", map[string]interface{}{ 56 "pew.pew": "zap", 57 }) 58 c.Check(err, jc.ErrorIsNil) 59 60 s.checkGetSetStatus(c) 61 } 62 63 func (s *StatusUnitAgentSuite) TestGetSetStatusAlive(c *gc.C) { 64 s.checkGetSetStatus(c) 65 } 66 67 func (s *StatusUnitAgentSuite) checkGetSetStatus(c *gc.C) { 68 err := s.agent.SetStatus(status.StatusIdle, "something", map[string]interface{}{ 69 "$foo": "bar", 70 "baz.qux": "ping", 71 "pong": map[string]interface{}{ 72 "$unset": "txn-revno", 73 }, 74 }) 75 c.Check(err, jc.ErrorIsNil) 76 77 unit, err := s.State.Unit(s.unit.Name()) 78 c.Assert(err, jc.ErrorIsNil) 79 agent := unit.Agent() 80 81 statusInfo, err := agent.Status() 82 c.Check(err, jc.ErrorIsNil) 83 c.Check(statusInfo.Status, gc.Equals, status.StatusIdle) 84 c.Check(statusInfo.Message, gc.Equals, "something") 85 c.Check(statusInfo.Data, jc.DeepEquals, map[string]interface{}{ 86 "$foo": "bar", 87 "baz.qux": "ping", 88 "pong": map[string]interface{}{ 89 "$unset": "txn-revno", 90 }, 91 }) 92 c.Check(statusInfo.Since, gc.NotNil) 93 } 94 95 func (s *StatusUnitAgentSuite) TestGetSetStatusDying(c *gc.C) { 96 preventUnitDestroyRemove(c, s.unit) 97 err := s.unit.Destroy() 98 c.Assert(err, jc.ErrorIsNil) 99 100 s.checkGetSetStatus(c) 101 } 102 103 func (s *StatusUnitAgentSuite) TestGetSetStatusDead(c *gc.C) { 104 preventUnitDestroyRemove(c, s.unit) 105 err := s.unit.Destroy() 106 c.Assert(err, jc.ErrorIsNil) 107 err = s.unit.EnsureDead() 108 c.Assert(err, jc.ErrorIsNil) 109 110 // NOTE: it would be more technically correct to reject status updates 111 // while Dead, but it's easier and clearer, not to mention more efficient, 112 // to just depend on status doc existence. 113 s.checkGetSetStatus(c) 114 } 115 116 func (s *StatusUnitAgentSuite) TestGetSetStatusGone(c *gc.C) { 117 err := s.unit.Destroy() 118 c.Assert(err, jc.ErrorIsNil) 119 120 err = s.agent.SetStatus(status.StatusIdle, "not really", nil) 121 c.Check(err, gc.ErrorMatches, `cannot set status: agent not found`) 122 123 statusInfo, err := s.agent.Status() 124 c.Check(err, gc.ErrorMatches, `cannot get status: agent not found`) 125 c.Check(statusInfo, gc.DeepEquals, status.StatusInfo{}) 126 } 127 128 func (s *StatusUnitAgentSuite) TestGetSetErrorStatus(c *gc.C) { 129 err := s.agent.SetStatus(status.StatusError, "test-hook failed", map[string]interface{}{ 130 "foo": "bar", 131 }) 132 c.Assert(err, jc.ErrorIsNil) 133 134 // Agent error is reported as unit error. 135 statusInfo, err := s.unit.Status() 136 c.Check(err, jc.ErrorIsNil) 137 c.Check(statusInfo.Status, gc.Equals, status.StatusError) 138 c.Check(statusInfo.Message, gc.Equals, "test-hook failed") 139 c.Check(statusInfo.Data, gc.DeepEquals, map[string]interface{}{ 140 "foo": "bar", 141 }) 142 143 // For agents, error is reported as idle. 144 statusInfo, err = s.agent.Status() 145 c.Check(err, jc.ErrorIsNil) 146 c.Check(statusInfo.Status, gc.Equals, status.StatusIdle) 147 c.Check(statusInfo.Message, gc.Equals, "") 148 c.Check(statusInfo.Data, gc.HasLen, 0) 149 } 150 151 func timeBeforeOrEqual(timeBefore, timeOther time.Time) bool { 152 return timeBefore.Before(timeOther) || timeBefore.Equal(timeOther) 153 } 154 155 func (s *StatusUnitAgentSuite) TestSetAgentStatusSince(c *gc.C) { 156 now := time.Now() 157 err := s.agent.SetStatus(status.StatusIdle, "", nil) 158 c.Assert(err, jc.ErrorIsNil) 159 statusInfo, err := s.agent.Status() 160 c.Assert(err, jc.ErrorIsNil) 161 firstTime := statusInfo.Since 162 c.Assert(firstTime, gc.NotNil) 163 c.Assert(timeBeforeOrEqual(now, *firstTime), jc.IsTrue) 164 165 // Setting the same status a second time also updates the timestamp. 166 err = s.agent.SetStatus(status.StatusIdle, "", nil) 167 c.Assert(err, jc.ErrorIsNil) 168 statusInfo, err = s.agent.Status() 169 c.Assert(err, jc.ErrorIsNil) 170 c.Assert(timeBeforeOrEqual(*firstTime, *statusInfo.Since), jc.IsTrue) 171 } 172 173 func (s *StatusUnitAgentSuite) TestStatusHistoryInitial(c *gc.C) { 174 history, err := s.agent.StatusHistory(1) 175 c.Check(err, jc.ErrorIsNil) 176 c.Assert(history, gc.HasLen, 1) 177 178 checkInitialUnitAgentStatus(c, history[0]) 179 } 180 181 func (s *StatusUnitAgentSuite) TestStatusHistoryShort(c *gc.C) { 182 primeUnitAgentStatusHistory(c, s.agent, 5) 183 184 history, err := s.agent.StatusHistory(10) 185 c.Check(err, jc.ErrorIsNil) 186 c.Assert(history, gc.HasLen, 6) 187 188 checkInitialUnitAgentStatus(c, history[5]) 189 history = history[:5] 190 for i, statusInfo := range history { 191 checkPrimedUnitAgentStatus(c, statusInfo, 4-i) 192 } 193 } 194 195 func (s *StatusUnitAgentSuite) TestStatusHistoryLong(c *gc.C) { 196 primeUnitAgentStatusHistory(c, s.agent, 25) 197 198 history, err := s.agent.StatusHistory(15) 199 c.Check(err, jc.ErrorIsNil) 200 c.Check(history, gc.HasLen, 15) 201 for i, statusInfo := range history { 202 checkPrimedUnitAgentStatus(c, statusInfo, 24-i) 203 } 204 }