github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/common/unitstatus_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common_test 5 6 import ( 7 "errors" 8 9 "github.com/juju/names/v5" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/apiserver/common" 15 "github.com/juju/juju/core/status" 16 "github.com/juju/juju/state" 17 ) 18 19 type UnitStatusSuite struct { 20 testing.IsolationSuite 21 ctx common.ModelPresenceContext 22 unit *fakeStatusUnit 23 } 24 25 var _ = gc.Suite(&UnitStatusSuite{}) 26 27 func (s *UnitStatusSuite) SetUpTest(c *gc.C) { 28 s.unit = &fakeStatusUnit{ 29 app: "foo", 30 agentStatus: status.StatusInfo{ 31 Status: status.Started, 32 Message: "agent ok", 33 }, 34 status: status.StatusInfo{ 35 Status: status.Idle, 36 Message: "unit ok", 37 }, 38 presence: true, 39 shouldBeAssigned: true, 40 } 41 s.ctx = common.ModelPresenceContext{ 42 Presence: agentAlive(names.NewUnitTag(s.unit.Name()).String()), 43 } 44 } 45 46 func (s *UnitStatusSuite) checkUntouched(c *gc.C) { 47 agent, workload := s.ctx.UnitStatus(s.unit) 48 c.Check(agent.Status, jc.DeepEquals, s.unit.agentStatus) 49 c.Check(agent.Err, jc.ErrorIsNil) 50 c.Check(workload.Status, jc.DeepEquals, s.unit.status) 51 c.Check(workload.Err, jc.ErrorIsNil) 52 } 53 54 func (s *UnitStatusSuite) checkLost(c *gc.C) { 55 agent, workload := s.ctx.UnitStatus(s.unit) 56 c.Check(agent.Status, jc.DeepEquals, status.StatusInfo{ 57 Status: status.Lost, 58 Message: "agent is not communicating with the server", 59 }) 60 c.Check(agent.Err, jc.ErrorIsNil) 61 c.Check(workload.Status, jc.DeepEquals, status.StatusInfo{ 62 Status: status.Unknown, 63 Message: "agent lost, see 'juju show-status-log foo/2'", 64 }) 65 c.Check(workload.Err, jc.ErrorIsNil) 66 } 67 68 func (s *UnitStatusSuite) TestNormal(c *gc.C) { 69 s.checkUntouched(c) 70 } 71 72 func (s *UnitStatusSuite) TestCAASNormal(c *gc.C) { 73 s.unit.shouldBeAssigned = false 74 s.ctx.Presence = agentAlive(names.NewApplicationTag(s.unit.app).String()) 75 s.checkUntouched(c) 76 } 77 78 func (s *UnitStatusSuite) TestErrors(c *gc.C) { 79 s.unit.agentStatusErr = errors.New("agent status error") 80 s.unit.statusErr = errors.New("status error") 81 82 agent, workload := s.ctx.UnitStatus(s.unit) 83 c.Check(agent.Err, gc.ErrorMatches, "agent status error") 84 c.Check(workload.Err, gc.ErrorMatches, "status error") 85 } 86 87 func (s *UnitStatusSuite) TestLost(c *gc.C) { 88 s.ctx.Presence = agentDown(s.unit.Tag().String()) 89 s.checkLost(c) 90 } 91 92 func (s *UnitStatusSuite) TestCAASLost(c *gc.C) { 93 s.unit.shouldBeAssigned = false 94 s.ctx.Presence = agentDown(names.NewApplicationTag(s.unit.app).String()) 95 s.checkLost(c) 96 } 97 98 func (s *UnitStatusSuite) TestLostTerminated(c *gc.C) { 99 s.unit.status.Status = status.Terminated 100 s.unit.status.Message = "" 101 102 s.ctx.Presence = agentDown(s.unit.Tag().String()) 103 104 agent, workload := s.ctx.UnitStatus(s.unit) 105 c.Check(agent.Status, jc.DeepEquals, status.StatusInfo{ 106 Status: status.Lost, 107 Message: "agent is not communicating with the server", 108 }) 109 c.Check(agent.Err, jc.ErrorIsNil) 110 c.Check(workload.Status, jc.DeepEquals, status.StatusInfo{ 111 Status: status.Terminated, 112 Message: "", 113 }) 114 c.Check(workload.Err, jc.ErrorIsNil) 115 } 116 117 func (s *UnitStatusSuite) TestCAASLostTerminated(c *gc.C) { 118 s.unit.shouldBeAssigned = false 119 s.unit.status.Status = status.Terminated 120 s.unit.status.Message = "" 121 122 s.ctx.Presence = agentDown(names.NewApplicationTag(s.unit.app).String()) 123 124 agent, workload := s.ctx.UnitStatus(s.unit) 125 c.Check(agent.Status, jc.DeepEquals, status.StatusInfo{ 126 Status: status.Lost, 127 Message: "agent is not communicating with the server", 128 }) 129 c.Check(agent.Err, jc.ErrorIsNil) 130 c.Check(workload.Status, jc.DeepEquals, status.StatusInfo{ 131 Status: status.Terminated, 132 Message: "", 133 }) 134 c.Check(workload.Err, jc.ErrorIsNil) 135 } 136 func (s *UnitStatusSuite) TestLostAndDead(c *gc.C) { 137 s.ctx.Presence = agentDown(s.unit.Tag().String()) 138 s.unit.life = state.Dead 139 // Status is untouched if unit is Dead. 140 s.checkUntouched(c) 141 } 142 143 func (s *UnitStatusSuite) TestPresenceError(c *gc.C) { 144 s.ctx.Presence = presenceError(s.unit.Tag().String()) 145 // Presence error gets ignored, so no output is unchanged. 146 s.checkUntouched(c) 147 } 148 149 func (s *UnitStatusSuite) TestNotLostIfAllocating(c *gc.C) { 150 s.ctx.Presence = agentDown(s.unit.Tag().String()) 151 s.unit.agentStatus.Status = status.Allocating 152 s.checkUntouched(c) 153 } 154 155 func (s *UnitStatusSuite) TestCantBeLostDuringInstall(c *gc.C) { 156 s.ctx.Presence = agentDown(s.unit.Tag().String()) 157 s.unit.agentStatus.Status = status.Executing 158 s.unit.agentStatus.Message = "running install hook" 159 s.checkUntouched(c) 160 } 161 162 func (s *UnitStatusSuite) TestCantBeLostDuringWorkloadInstall(c *gc.C) { 163 s.ctx.Presence = agentDown(s.unit.Tag().String()) 164 s.unit.status.Status = status.Maintenance 165 s.unit.status.Message = "installing charm software" 166 s.checkUntouched(c) 167 } 168 169 type fakeStatusUnit struct { 170 app string 171 agentStatus status.StatusInfo 172 agentStatusErr error 173 status status.StatusInfo 174 statusErr error 175 presence bool 176 life state.Life 177 shouldBeAssigned bool 178 } 179 180 func (u *fakeStatusUnit) Name() string { 181 return u.app + "/2" 182 } 183 184 func (u *fakeStatusUnit) Tag() names.Tag { 185 return names.NewUnitTag(u.Name()) 186 } 187 188 func (u *fakeStatusUnit) AgentStatus() (status.StatusInfo, error) { 189 return u.agentStatus, u.agentStatusErr 190 } 191 192 func (u *fakeStatusUnit) Status() (status.StatusInfo, error) { 193 return u.status, u.statusErr 194 } 195 196 func (u *fakeStatusUnit) Life() state.Life { 197 return u.life 198 } 199 200 func (u *fakeStatusUnit) ShouldBeAssigned() bool { 201 return u.shouldBeAssigned 202 } 203 204 func (u *fakeStatusUnit) IsSidecar() (bool, error) { 205 return false, nil 206 }