github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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 "github.com/juju/juju/testing" 15 ) 16 17 type StatusUnitAgentSuite struct { 18 ConnSuite 19 unit *state.Unit 20 agent *state.UnitAgent 21 } 22 23 var _ = gc.Suite(&StatusUnitAgentSuite{}) 24 25 func (s *StatusUnitAgentSuite) SetUpTest(c *gc.C) { 26 s.ConnSuite.SetUpTest(c) 27 s.unit = s.Factory.MakeUnit(c, nil) 28 s.agent = s.unit.Agent() 29 } 30 31 func (s *StatusUnitAgentSuite) TestInitialStatus(c *gc.C) { 32 s.checkInitialStatus(c) 33 } 34 35 func (s *StatusUnitAgentSuite) checkInitialStatus(c *gc.C) { 36 statusInfo, err := s.agent.Status() 37 c.Check(err, jc.ErrorIsNil) 38 checkInitialUnitAgentStatus(c, statusInfo) 39 } 40 41 func (s *StatusUnitAgentSuite) TestSetUnknownStatus(c *gc.C) { 42 now := testing.ZeroTime() 43 sInfo := status.StatusInfo{ 44 Status: status.Status("vliegkat"), 45 Message: "orville", 46 Since: &now, 47 } 48 err := s.agent.SetStatus(sInfo) 49 c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) 50 51 s.checkInitialStatus(c) 52 } 53 54 func (s *StatusUnitAgentSuite) TestSetErrorStatusWithoutInfo(c *gc.C) { 55 now := testing.ZeroTime() 56 sInfo := status.StatusInfo{ 57 Status: status.Error, 58 Message: "", 59 Since: &now, 60 } 61 err := s.agent.SetStatus(sInfo) 62 c.Check(err, gc.ErrorMatches, `cannot set status "error" without info`) 63 64 s.checkInitialStatus(c) 65 } 66 67 func (s *StatusUnitAgentSuite) TestSetOverwritesData(c *gc.C) { 68 now := testing.ZeroTime() 69 sInfo := status.StatusInfo{ 70 Status: status.Idle, 71 Message: "something", 72 Data: map[string]interface{}{ 73 "pew.pew": "zap", 74 }, 75 Since: &now, 76 } 77 err := s.agent.SetStatus(sInfo) 78 c.Check(err, jc.ErrorIsNil) 79 80 s.checkGetSetStatus(c) 81 } 82 83 func (s *StatusUnitAgentSuite) TestGetSetStatusAlive(c *gc.C) { 84 s.checkGetSetStatus(c) 85 } 86 87 func (s *StatusUnitAgentSuite) checkGetSetStatus(c *gc.C) { 88 now := testing.ZeroTime() 89 sInfo := status.StatusInfo{ 90 Status: status.Idle, 91 Message: "something", 92 Data: map[string]interface{}{ 93 "$foo": "bar", 94 "baz.qux": "ping", 95 "pong": map[string]interface{}{ 96 "$unset": "txn-revno", 97 }, 98 }, 99 Since: &now, 100 } 101 err := s.agent.SetStatus(sInfo) 102 c.Check(err, jc.ErrorIsNil) 103 104 unit, err := s.State.Unit(s.unit.Name()) 105 c.Assert(err, jc.ErrorIsNil) 106 agent := unit.Agent() 107 108 statusInfo, err := agent.Status() 109 c.Check(err, jc.ErrorIsNil) 110 c.Check(statusInfo.Status, gc.Equals, status.Idle) 111 c.Check(statusInfo.Message, gc.Equals, "something") 112 c.Check(statusInfo.Data, jc.DeepEquals, map[string]interface{}{ 113 "$foo": "bar", 114 "baz.qux": "ping", 115 "pong": map[string]interface{}{ 116 "$unset": "txn-revno", 117 }, 118 }) 119 c.Check(statusInfo.Since, gc.NotNil) 120 } 121 122 func (s *StatusUnitAgentSuite) TestGetSetStatusDying(c *gc.C) { 123 preventUnitDestroyRemove(c, s.unit) 124 err := s.unit.Destroy() 125 c.Assert(err, jc.ErrorIsNil) 126 127 s.checkGetSetStatus(c) 128 } 129 130 func (s *StatusUnitAgentSuite) TestGetSetStatusDead(c *gc.C) { 131 preventUnitDestroyRemove(c, s.unit) 132 err := s.unit.Destroy() 133 c.Assert(err, jc.ErrorIsNil) 134 err = s.unit.EnsureDead() 135 c.Assert(err, jc.ErrorIsNil) 136 137 // NOTE: it would be more technically correct to reject status updates 138 // while Dead, but it's easier and clearer, not to mention more efficient, 139 // to just depend on status doc existence. 140 s.checkGetSetStatus(c) 141 } 142 143 func (s *StatusUnitAgentSuite) TestGetSetStatusGone(c *gc.C) { 144 err := s.unit.Destroy() 145 c.Assert(err, jc.ErrorIsNil) 146 147 now := testing.ZeroTime() 148 sInfo := status.StatusInfo{ 149 Status: status.Idle, 150 Message: "not really", 151 Since: &now, 152 } 153 err = s.agent.SetStatus(sInfo) 154 c.Check(err, gc.ErrorMatches, `cannot set status: agent not found`) 155 156 statusInfo, err := s.agent.Status() 157 c.Check(err, gc.ErrorMatches, `cannot get status: agent not found`) 158 c.Check(statusInfo, gc.DeepEquals, status.StatusInfo{}) 159 } 160 161 func (s *StatusUnitAgentSuite) TestGetSetErrorStatus(c *gc.C) { 162 now := testing.ZeroTime() 163 sInfo := status.StatusInfo{ 164 Status: status.Error, 165 Message: "test-hook failed", 166 Data: map[string]interface{}{ 167 "foo": "bar", 168 }, 169 Since: &now, 170 } 171 err := s.agent.SetStatus(sInfo) 172 c.Assert(err, jc.ErrorIsNil) 173 174 // Agent error is reported as unit error. 175 statusInfo, err := s.unit.Status() 176 c.Check(err, jc.ErrorIsNil) 177 c.Check(statusInfo.Status, gc.Equals, status.Error) 178 c.Check(statusInfo.Message, gc.Equals, "test-hook failed") 179 c.Check(statusInfo.Data, gc.DeepEquals, map[string]interface{}{ 180 "foo": "bar", 181 }) 182 183 // For agents, error is reported as idle. 184 statusInfo, err = s.agent.Status() 185 c.Check(err, jc.ErrorIsNil) 186 c.Check(statusInfo.Status, gc.Equals, status.Idle) 187 c.Check(statusInfo.Message, gc.Equals, "") 188 c.Check(statusInfo.Data, gc.HasLen, 0) 189 } 190 191 func timeBeforeOrEqual(timeBefore, timeOther time.Time) bool { 192 return timeBefore.Before(timeOther) || timeBefore.Equal(timeOther) 193 } 194 195 func (s *StatusUnitAgentSuite) TestSetAgentStatusSince(c *gc.C) { 196 now := testing.ZeroTime() 197 sInfo := status.StatusInfo{ 198 Status: status.Idle, 199 Message: "", 200 Since: &now, 201 } 202 err := s.agent.SetStatus(sInfo) 203 c.Assert(err, jc.ErrorIsNil) 204 statusInfo, err := s.agent.Status() 205 c.Assert(err, jc.ErrorIsNil) 206 firstTime := statusInfo.Since 207 c.Assert(firstTime, gc.NotNil) 208 c.Assert(timeBeforeOrEqual(now, *firstTime), jc.IsTrue) 209 210 // Setting the same status a second time also updates the timestamp. 211 now = now.Add(1 * time.Second) 212 sInfo = status.StatusInfo{ 213 Status: status.Idle, 214 Message: "", 215 Since: &now, 216 } 217 err = s.agent.SetStatus(sInfo) 218 c.Assert(err, jc.ErrorIsNil) 219 statusInfo, err = s.agent.Status() 220 c.Assert(err, jc.ErrorIsNil) 221 c.Assert(timeBeforeOrEqual(*firstTime, *statusInfo.Since), jc.IsTrue) 222 } 223 224 func (s *StatusUnitAgentSuite) TestStatusHistoryInitial(c *gc.C) { 225 history, err := s.agent.StatusHistory(status.StatusHistoryFilter{Size: 1}) 226 c.Check(err, jc.ErrorIsNil) 227 c.Assert(history, gc.HasLen, 1) 228 229 checkInitialUnitAgentStatus(c, history[0]) 230 } 231 232 func (s *StatusUnitAgentSuite) TestStatusHistoryShort(c *gc.C) { 233 primeUnitAgentStatusHistory(c, s.agent, 5, 0) 234 235 history, err := s.agent.StatusHistory(status.StatusHistoryFilter{Size: 10}) 236 c.Check(err, jc.ErrorIsNil) 237 c.Assert(history, gc.HasLen, 6) 238 239 checkInitialUnitAgentStatus(c, history[5]) 240 history = history[:5] 241 for i, statusInfo := range history { 242 checkPrimedUnitAgentStatus(c, statusInfo, 4-i, 0) 243 } 244 } 245 246 func (s *StatusUnitAgentSuite) TestStatusHistoryLong(c *gc.C) { 247 primeUnitAgentStatusHistory(c, s.agent, 25, 0) 248 249 history, err := s.agent.StatusHistory(status.StatusHistoryFilter{Size: 15}) 250 c.Check(err, jc.ErrorIsNil) 251 c.Check(history, gc.HasLen, 15) 252 for i, statusInfo := range history { 253 checkPrimedUnitAgentStatus(c, statusInfo, 24-i, 0) 254 } 255 }