github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/status_unit_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 UnitStatusSuite struct { 18 ConnSuite 19 unit *state.Unit 20 } 21 22 var _ = gc.Suite(&UnitStatusSuite{}) 23 24 func (s *UnitStatusSuite) SetUpTest(c *gc.C) { 25 s.ConnSuite.SetUpTest(c) 26 s.unit = s.Factory.MakeUnit(c, nil) 27 } 28 29 func (s *UnitStatusSuite) TestInitialStatus(c *gc.C) { 30 s.checkInitialStatus(c) 31 } 32 33 func (s *UnitStatusSuite) checkInitialStatus(c *gc.C) { 34 statusInfo, err := s.unit.Status() 35 c.Check(err, jc.ErrorIsNil) 36 checkInitialWorkloadStatus(c, statusInfo) 37 } 38 39 func (s *UnitStatusSuite) TestSetUnknownStatus(c *gc.C) { 40 now := testing.ZeroTime() 41 sInfo := status.StatusInfo{ 42 Status: status.Status("vliegkat"), 43 Message: "orville", 44 Since: &now, 45 } 46 err := s.unit.SetStatus(sInfo) 47 c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) 48 49 s.checkInitialStatus(c) 50 } 51 52 func (s *UnitStatusSuite) TestSetOverwritesData(c *gc.C) { 53 now := testing.ZeroTime() 54 sInfo := status.StatusInfo{ 55 Status: status.Active, 56 Message: "healthy", 57 Data: map[string]interface{}{ 58 "pew.pew": "zap", 59 }, 60 Since: &now, 61 } 62 err := s.unit.SetStatus(sInfo) 63 c.Check(err, jc.ErrorIsNil) 64 65 s.checkGetSetStatus(c) 66 } 67 68 func (s *UnitStatusSuite) TestGetSetStatusAlive(c *gc.C) { 69 s.checkGetSetStatus(c) 70 } 71 72 func (s *UnitStatusSuite) checkGetSetStatus(c *gc.C) { 73 now := testing.ZeroTime() 74 sInfo := status.StatusInfo{ 75 Status: status.Active, 76 Message: "healthy", 77 Data: map[string]interface{}{ 78 "$ping": map[string]interface{}{ 79 "foo.bar": 123, 80 }}, 81 Since: &now, 82 } 83 err := s.unit.SetStatus(sInfo) 84 c.Check(err, jc.ErrorIsNil) 85 86 unit, err := s.State.Unit(s.unit.Name()) 87 c.Assert(err, jc.ErrorIsNil) 88 89 statusInfo, err := unit.Status() 90 c.Check(err, jc.ErrorIsNil) 91 c.Check(statusInfo.Status, gc.Equals, status.Active) 92 c.Check(statusInfo.Message, gc.Equals, "healthy") 93 c.Check(statusInfo.Data, jc.DeepEquals, map[string]interface{}{ 94 "$ping": map[string]interface{}{ 95 "foo.bar": 123, 96 }, 97 }) 98 c.Check(statusInfo.Since, gc.NotNil) 99 } 100 101 func (s *UnitStatusSuite) TestGetSetStatusDying(c *gc.C) { 102 preventUnitDestroyRemove(c, s.unit) 103 err := s.unit.Destroy() 104 c.Assert(err, jc.ErrorIsNil) 105 106 s.checkGetSetStatus(c) 107 } 108 109 func (s *UnitStatusSuite) TestGetSetStatusDead(c *gc.C) { 110 preventUnitDestroyRemove(c, s.unit) 111 err := s.unit.Destroy() 112 c.Assert(err, jc.ErrorIsNil) 113 err = s.unit.EnsureDead() 114 c.Assert(err, jc.ErrorIsNil) 115 116 // NOTE: it would be more technically correct to reject status updates 117 // while Dead, but it's easier and clearer, not to mention more efficient, 118 // to just depend on status doc existence. 119 s.checkGetSetStatus(c) 120 } 121 122 func (s *UnitStatusSuite) TestGetSetStatusGone(c *gc.C) { 123 err := s.unit.Destroy() 124 c.Assert(err, jc.ErrorIsNil) 125 126 now := testing.ZeroTime() 127 sInfo := status.StatusInfo{ 128 Status: status.Active, 129 Message: "not really", 130 Since: &now, 131 } 132 err = s.unit.SetStatus(sInfo) 133 c.Check(err, gc.ErrorMatches, `cannot set status: unit not found`) 134 135 statusInfo, err := s.unit.Status() 136 c.Check(err, gc.ErrorMatches, `cannot get status: unit not found`) 137 c.Check(statusInfo, gc.DeepEquals, status.StatusInfo{}) 138 } 139 140 func (s *UnitStatusSuite) TestSetUnitStatusSince(c *gc.C) { 141 now := testing.ZeroTime() 142 sInfo := status.StatusInfo{ 143 Status: status.Maintenance, 144 Message: "", 145 Since: &now, 146 } 147 err := s.unit.SetStatus(sInfo) 148 c.Assert(err, jc.ErrorIsNil) 149 statusInfo, err := s.unit.Status() 150 c.Assert(err, jc.ErrorIsNil) 151 firstTime := statusInfo.Since 152 c.Assert(firstTime, gc.NotNil) 153 c.Assert(timeBeforeOrEqual(now, *firstTime), jc.IsTrue) 154 155 // Setting the same status a second time also updates the timestamp. 156 now = now.Add(1 * time.Second) 157 sInfo = status.StatusInfo{ 158 Status: status.Maintenance, 159 Message: "", 160 Since: &now, 161 } 162 err = s.unit.SetStatus(sInfo) 163 c.Assert(err, jc.ErrorIsNil) 164 statusInfo, err = s.unit.Status() 165 c.Assert(err, jc.ErrorIsNil) 166 c.Assert(timeBeforeOrEqual(*firstTime, *statusInfo.Since), jc.IsTrue) 167 } 168 169 func (s *UnitStatusSuite) TestStatusHistoryInitial(c *gc.C) { 170 history, err := s.unit.StatusHistory(status.StatusHistoryFilter{Size: 1}) 171 c.Check(err, jc.ErrorIsNil) 172 c.Assert(history, gc.HasLen, 1) 173 174 checkInitialWorkloadStatus(c, history[0]) 175 } 176 177 func (s *UnitStatusSuite) TestStatusHistoryShort(c *gc.C) { 178 primeUnitStatusHistory(c, s.unit, 5, 0) 179 180 history, err := s.unit.StatusHistory(status.StatusHistoryFilter{Size: 10}) 181 c.Check(err, jc.ErrorIsNil) 182 c.Assert(history, gc.HasLen, 6) 183 184 checkInitialWorkloadStatus(c, history[5]) 185 history = history[:5] 186 for i, statusInfo := range history { 187 checkPrimedUnitStatus(c, statusInfo, 4-i, 0) 188 } 189 } 190 191 func (s *UnitStatusSuite) TestStatusHistoryLong(c *gc.C) { 192 primeUnitStatusHistory(c, s.unit, 25, 0) 193 194 history, err := s.unit.StatusHistory(status.StatusHistoryFilter{Size: 15}) 195 c.Check(err, jc.ErrorIsNil) 196 c.Check(history, gc.HasLen, 15) 197 for i, statusInfo := range history { 198 checkPrimedUnitStatus(c, statusInfo, 24-i, 0) 199 } 200 }