github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/status_service_test.go (about) 1 // Copyright 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 ServiceStatusSuite struct { 17 ConnSuite 18 service *state.Service 19 } 20 21 var _ = gc.Suite(&ServiceStatusSuite{}) 22 23 func (s *ServiceStatusSuite) SetUpTest(c *gc.C) { 24 s.ConnSuite.SetUpTest(c) 25 s.service = s.Factory.MakeService(c, nil) 26 } 27 28 func (s *ServiceStatusSuite) TestInitialStatus(c *gc.C) { 29 s.checkInitialStatus(c) 30 } 31 32 func (s *ServiceStatusSuite) checkInitialStatus(c *gc.C) { 33 statusInfo, err := s.service.Status() 34 c.Check(err, jc.ErrorIsNil) 35 checkInitialWorkloadStatus(c, statusInfo) 36 } 37 38 func (s *ServiceStatusSuite) TestSetUnknownStatus(c *gc.C) { 39 err := s.service.SetStatus(status.Status("vliegkat"), "orville", nil) 40 c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) 41 42 s.checkInitialStatus(c) 43 } 44 45 func (s *ServiceStatusSuite) TestSetOverwritesData(c *gc.C) { 46 err := s.service.SetStatus(status.StatusActive, "healthy", map[string]interface{}{ 47 "pew.pew": "zap", 48 }) 49 c.Check(err, jc.ErrorIsNil) 50 51 s.checkGetSetStatus(c) 52 } 53 54 func (s *ServiceStatusSuite) TestGetSetStatusAlive(c *gc.C) { 55 s.checkGetSetStatus(c) 56 } 57 58 func (s *ServiceStatusSuite) checkGetSetStatus(c *gc.C) { 59 err := s.service.SetStatus(status.StatusActive, "healthy", map[string]interface{}{ 60 "$ping": map[string]interface{}{ 61 "foo.bar": 123, 62 }, 63 }) 64 c.Check(err, jc.ErrorIsNil) 65 66 service, err := s.State.Service(s.service.Name()) 67 c.Assert(err, jc.ErrorIsNil) 68 69 statusInfo, err := service.Status() 70 c.Check(err, jc.ErrorIsNil) 71 c.Check(statusInfo.Status, gc.Equals, status.StatusActive) 72 c.Check(statusInfo.Message, gc.Equals, "healthy") 73 c.Check(statusInfo.Data, jc.DeepEquals, map[string]interface{}{ 74 "$ping": map[string]interface{}{ 75 "foo.bar": 123, 76 }, 77 }) 78 c.Check(statusInfo.Since, gc.NotNil) 79 } 80 81 func (s *ServiceStatusSuite) TestGetSetStatusDying(c *gc.C) { 82 _, err := s.service.AddUnit() 83 c.Assert(err, jc.ErrorIsNil) 84 err = s.service.Destroy() 85 c.Assert(err, jc.ErrorIsNil) 86 87 s.checkGetSetStatus(c) 88 } 89 90 func (s *ServiceStatusSuite) TestGetSetStatusGone(c *gc.C) { 91 err := s.service.Destroy() 92 c.Assert(err, jc.ErrorIsNil) 93 94 err = s.service.SetStatus(status.StatusActive, "not really", nil) 95 c.Check(err, gc.ErrorMatches, `cannot set status: service not found`) 96 97 statusInfo, err := s.service.Status() 98 c.Check(err, gc.ErrorMatches, `cannot get status: service not found`) 99 c.Check(statusInfo, gc.DeepEquals, status.StatusInfo{}) 100 } 101 102 func (s *ServiceStatusSuite) TestSetStatusSince(c *gc.C) { 103 now := time.Now() 104 105 err := s.service.SetStatus(status.StatusMaintenance, "", nil) 106 c.Assert(err, jc.ErrorIsNil) 107 statusInfo, err := s.service.Status() 108 c.Assert(err, jc.ErrorIsNil) 109 firstTime := statusInfo.Since 110 c.Assert(firstTime, gc.NotNil) 111 c.Assert(timeBeforeOrEqual(now, *firstTime), jc.IsTrue) 112 113 // Setting the same status a second time also updates the timestamp. 114 err = s.service.SetStatus(status.StatusMaintenance, "", nil) 115 c.Assert(err, jc.ErrorIsNil) 116 statusInfo, err = s.service.Status() 117 c.Assert(err, jc.ErrorIsNil) 118 c.Assert(timeBeforeOrEqual(*firstTime, *statusInfo.Since), jc.IsTrue) 119 } 120 121 func (s *ServiceStatusSuite) TestDeriveStatus(c *gc.C) { 122 // NOTE(fwereade): as detailed in the code, this implementation is not sane. 123 // The specified behaviour is arguably sane, but the code is in the wrong 124 // place. 125 126 // Create a unit with each possible status. 127 addUnit := func(status status.Status) *state.Unit { 128 unit, err := s.service.AddUnit() 129 c.Assert(err, gc.IsNil) 130 err = unit.SetStatus(status, "blam", nil) 131 c.Assert(err, gc.IsNil) 132 return unit 133 } 134 blockedUnit := addUnit(status.StatusBlocked) 135 waitingUnit := addUnit(status.StatusWaiting) 136 maintenanceUnit := addUnit(status.StatusMaintenance) 137 terminatedUnit := addUnit(status.StatusTerminated) 138 activeUnit := addUnit(status.StatusActive) 139 unknownUnit := addUnit(status.StatusUnknown) 140 141 // ...and create one with error status by setting it on the agent :-/. 142 errorUnit, err := s.service.AddUnit() 143 c.Assert(err, gc.IsNil) 144 err = errorUnit.Agent().SetStatus(status.StatusError, "blam", nil) 145 c.Assert(err, gc.IsNil) 146 147 // For each status, in order of severity, check the service status is 148 // derived from that unit status; then remove that unit and proceed to 149 // the next severity. 150 checkAndRemove := func(unit *state.Unit, status status.Status) { 151 info, err := s.service.Status() 152 c.Check(err, jc.ErrorIsNil) 153 c.Check(info.Status, gc.Equals, status) 154 155 err = unit.Destroy() 156 c.Assert(err, jc.ErrorIsNil) 157 err = unit.EnsureDead() 158 c.Assert(err, jc.ErrorIsNil) 159 err = unit.Remove() 160 c.Assert(err, jc.ErrorIsNil) 161 } 162 checkAndRemove(errorUnit, status.StatusError) 163 checkAndRemove(blockedUnit, status.StatusBlocked) 164 checkAndRemove(waitingUnit, status.StatusWaiting) 165 checkAndRemove(maintenanceUnit, status.StatusMaintenance) 166 checkAndRemove(terminatedUnit, status.StatusTerminated) 167 checkAndRemove(activeUnit, status.StatusActive) 168 checkAndRemove(unknownUnit, status.StatusUnknown) 169 } 170 171 func (s *ServiceStatusSuite) TestServiceStatusOverridesDerivedStatus(c *gc.C) { 172 unit, err := s.service.AddUnit() 173 c.Assert(err, gc.IsNil) 174 err = unit.SetStatus(status.StatusBlocked, "pow", nil) 175 c.Assert(err, gc.IsNil) 176 err = s.service.SetStatus(status.StatusMaintenance, "zot", nil) 177 c.Assert(err, gc.IsNil) 178 179 info, err := s.service.Status() 180 c.Check(err, jc.ErrorIsNil) 181 c.Check(info.Status, gc.Equals, status.StatusMaintenance) 182 }