github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/apiserver/common/setstatus_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 "gopkg.in/juju/names.v2" 13 14 "github.com/juju/juju/apiserver/common" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/state" 17 "github.com/juju/juju/status" 18 "github.com/juju/juju/testing/factory" 19 ) 20 21 type statusSetterSuite struct { 22 statusBaseSuite 23 setter *common.StatusSetter 24 } 25 26 var _ = gc.Suite(&statusSetterSuite{}) 27 28 func (s *statusSetterSuite) SetUpTest(c *gc.C) { 29 s.statusBaseSuite.SetUpTest(c) 30 31 s.setter = common.NewStatusSetter(s.State, func() (common.AuthFunc, error) { 32 return s.authFunc, nil 33 }) 34 } 35 36 func (s *statusSetterSuite) TestUnauthorized(c *gc.C) { 37 tag := names.NewMachineTag("42") 38 s.badTag = tag 39 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 40 Tag: tag.String(), 41 Status: status.Executing.String(), 42 }}}) 43 c.Assert(err, jc.ErrorIsNil) 44 c.Assert(result.Results, gc.HasLen, 1) 45 c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 46 } 47 48 func (s *statusSetterSuite) TestNotATag(c *gc.C) { 49 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 50 Tag: "not a tag", 51 Status: status.Executing.String(), 52 }}}) 53 c.Assert(err, jc.ErrorIsNil) 54 c.Assert(result.Results, gc.HasLen, 1) 55 c.Assert(result.Results[0].Error, gc.ErrorMatches, `"not a tag" is not a valid tag`) 56 } 57 58 func (s *statusSetterSuite) TestNotFound(c *gc.C) { 59 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 60 Tag: names.NewMachineTag("42").String(), 61 Status: status.Down.String(), 62 }}}) 63 c.Assert(err, jc.ErrorIsNil) 64 c.Assert(result.Results, gc.HasLen, 1) 65 c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeNotFound) 66 } 67 68 func (s *statusSetterSuite) TestSetMachineStatus(c *gc.C) { 69 machine := s.Factory.MakeMachine(c, nil) 70 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 71 Tag: machine.Tag().String(), 72 Status: status.Started.String(), 73 }}}) 74 c.Assert(err, jc.ErrorIsNil) 75 c.Assert(result.Results, gc.HasLen, 1) 76 c.Assert(result.Results[0].Error, gc.IsNil) 77 78 err = machine.Refresh() 79 c.Assert(err, jc.ErrorIsNil) 80 machineStatus, err := machine.Status() 81 c.Assert(err, jc.ErrorIsNil) 82 c.Assert(machineStatus.Status, gc.Equals, status.Started) 83 } 84 85 func (s *statusSetterSuite) TestSetUnitStatus(c *gc.C) { 86 // The status has to be a valid workload status, because get status 87 // on the unit returns the workload status not the agent status as it 88 // does on a machine. 89 unit := s.Factory.MakeUnit(c, &factory.UnitParams{Status: &status.StatusInfo{ 90 Status: status.Maintenance, 91 }}) 92 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 93 Tag: unit.Tag().String(), 94 Status: status.Active.String(), 95 }}}) 96 c.Assert(err, jc.ErrorIsNil) 97 c.Assert(result.Results, gc.HasLen, 1) 98 c.Assert(result.Results[0].Error, gc.IsNil) 99 100 err = unit.Refresh() 101 c.Assert(err, jc.ErrorIsNil) 102 unitStatus, err := unit.Status() 103 c.Assert(err, jc.ErrorIsNil) 104 c.Assert(unitStatus.Status, gc.Equals, status.Active) 105 } 106 107 func (s *statusSetterSuite) TestSetServiceStatus(c *gc.C) { 108 // Calls to set the status of a service should be going through the 109 // ServiceStatusSetter that checks for leadership, so permission denied 110 // here. 111 service := s.Factory.MakeApplication(c, &factory.ApplicationParams{Status: &status.StatusInfo{ 112 Status: status.Maintenance, 113 }}) 114 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 115 Tag: service.Tag().String(), 116 Status: status.Active.String(), 117 }}}) 118 c.Assert(err, jc.ErrorIsNil) 119 c.Assert(result.Results, gc.HasLen, 1) 120 c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 121 122 err = service.Refresh() 123 c.Assert(err, jc.ErrorIsNil) 124 serviceStatus, err := service.Status() 125 c.Assert(err, jc.ErrorIsNil) 126 c.Assert(serviceStatus.Status, gc.Equals, status.Maintenance) 127 } 128 129 func (s *statusSetterSuite) TestBulk(c *gc.C) { 130 s.badTag = names.NewMachineTag("42") 131 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 132 Tag: s.badTag.String(), 133 Status: status.Active.String(), 134 }, { 135 Tag: "bad-tag", 136 Status: status.Active.String(), 137 }}}) 138 c.Assert(err, jc.ErrorIsNil) 139 c.Assert(result.Results, gc.HasLen, 2) 140 c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 141 c.Assert(result.Results[1].Error, gc.ErrorMatches, `"bad-tag" is not a valid tag`) 142 } 143 144 type serviceStatusSetterSuite struct { 145 statusBaseSuite 146 setter *common.ServiceStatusSetter 147 } 148 149 var _ = gc.Suite(&serviceStatusSetterSuite{}) 150 151 func (s *serviceStatusSetterSuite) SetUpTest(c *gc.C) { 152 s.statusBaseSuite.SetUpTest(c) 153 154 s.setter = common.NewServiceStatusSetter(s.State, func() (common.AuthFunc, error) { 155 return s.authFunc, nil 156 }) 157 } 158 159 func (s *serviceStatusSetterSuite) TestUnauthorized(c *gc.C) { 160 // Machines are unauthorized since they are not units 161 tag := names.NewUnitTag("foo/0") 162 s.badTag = tag 163 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 164 Tag: tag.String(), 165 Status: status.Active.String(), 166 }}}) 167 c.Assert(err, jc.ErrorIsNil) 168 c.Assert(result.Results, gc.HasLen, 1) 169 c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 170 } 171 172 func (s *serviceStatusSetterSuite) TestNotATag(c *gc.C) { 173 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 174 Tag: "not a tag", 175 Status: status.Active.String(), 176 }}}) 177 c.Assert(err, jc.ErrorIsNil) 178 c.Assert(result.Results, gc.HasLen, 1) 179 c.Assert(result.Results[0].Error, gc.ErrorMatches, `"not a tag" is not a valid tag`) 180 } 181 182 func (s *serviceStatusSetterSuite) TestNotFound(c *gc.C) { 183 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 184 Tag: names.NewUnitTag("foo/0").String(), 185 Status: status.Active.String(), 186 }}}) 187 c.Assert(err, jc.ErrorIsNil) 188 c.Assert(result.Results, gc.HasLen, 1) 189 c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeNotFound) 190 } 191 192 func (s *serviceStatusSetterSuite) TestSetMachineStatus(c *gc.C) { 193 machine := s.Factory.MakeMachine(c, nil) 194 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 195 Tag: machine.Tag().String(), 196 Status: status.Active.String(), 197 }}}) 198 c.Assert(err, jc.ErrorIsNil) 199 c.Assert(result.Results, gc.HasLen, 1) 200 // Can't call set service status on a machine. 201 c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 202 } 203 204 func (s *serviceStatusSetterSuite) TestSetServiceStatus(c *gc.C) { 205 // TODO: the correct way to fix this is to have the authorizer on the 206 // simple status setter to check to see if the unit (authTag) is a leader 207 // and able to set the service status. However, that is for another day. 208 service := s.Factory.MakeApplication(c, &factory.ApplicationParams{Status: &status.StatusInfo{ 209 Status: status.Maintenance, 210 }}) 211 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 212 Tag: service.Tag().String(), 213 Status: status.Active.String(), 214 }}}) 215 c.Assert(err, jc.ErrorIsNil) 216 c.Assert(result.Results, gc.HasLen, 1) 217 // Can't call set service status on a service. Weird I know, but the only 218 // way is to go through the unit leader. 219 c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 220 } 221 222 func (s *serviceStatusSetterSuite) TestSetUnitStatusNotLeader(c *gc.C) { 223 // If the unit isn't the leader, it can't set it. 224 unit := s.Factory.MakeUnit(c, &factory.UnitParams{Status: &status.StatusInfo{ 225 Status: status.Maintenance, 226 }}) 227 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 228 Tag: unit.Tag().String(), 229 Status: status.Active.String(), 230 }}}) 231 c.Assert(err, jc.ErrorIsNil) 232 c.Assert(result.Results, gc.HasLen, 1) 233 status := result.Results[0] 234 c.Assert(status.Error, gc.ErrorMatches, ".* is not leader of .*") 235 } 236 237 func (s *serviceStatusSetterSuite) TestSetUnitStatusIsLeader(c *gc.C) { 238 service := s.Factory.MakeApplication(c, &factory.ApplicationParams{Status: &status.StatusInfo{ 239 Status: status.Maintenance, 240 }}) 241 unit := s.Factory.MakeUnit(c, &factory.UnitParams{ 242 Application: service, 243 Status: &status.StatusInfo{ 244 Status: status.Maintenance, 245 }}) 246 s.State.LeadershipClaimer().ClaimLeadership( 247 service.Name(), 248 unit.Name(), 249 time.Minute) 250 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 251 Tag: unit.Tag().String(), 252 Status: status.Active.String(), 253 }}}) 254 255 c.Assert(err, jc.ErrorIsNil) 256 c.Assert(result.Results, gc.HasLen, 1) 257 c.Assert(result.Results[0].Error, gc.IsNil) 258 259 err = service.Refresh() 260 c.Assert(err, jc.ErrorIsNil) 261 unitStatus, err := service.Status() 262 c.Assert(err, jc.ErrorIsNil) 263 c.Assert(unitStatus.Status, gc.Equals, status.Active) 264 } 265 266 func (s *serviceStatusSetterSuite) TestBulk(c *gc.C) { 267 s.badTag = names.NewMachineTag("42") 268 machine := s.Factory.MakeMachine(c, nil) 269 result, err := s.setter.SetStatus(params.SetStatus{[]params.EntityStatusArgs{{ 270 Tag: s.badTag.String(), 271 Status: status.Active.String(), 272 }, { 273 Tag: machine.Tag().String(), 274 Status: status.Active.String(), 275 }, { 276 Tag: "bad-tag", 277 Status: status.Active.String(), 278 }}}) 279 c.Assert(err, jc.ErrorIsNil) 280 c.Assert(result.Results, gc.HasLen, 3) 281 c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 282 c.Assert(result.Results[1].Error, jc.Satisfies, params.IsCodeUnauthorized) 283 c.Assert(result.Results[2].Error, gc.ErrorMatches, `"bad-tag" is not a valid tag`) 284 } 285 286 type unitAgentFinderSuite struct{} 287 288 var _ = gc.Suite(&unitAgentFinderSuite{}) 289 290 func (unitAgentFinderSuite) TestFindEntity(c *gc.C) { 291 f := fakeEntityFinder{ 292 unit: fakeUnit{ 293 agent: &state.UnitAgent{}, 294 }, 295 } 296 ua := &common.UnitAgentFinder{f} 297 entity, err := ua.FindEntity(names.NewUnitTag("unit/0")) 298 c.Assert(err, jc.ErrorIsNil) 299 c.Assert(entity, gc.DeepEquals, f.unit.agent) 300 } 301 302 func (unitAgentFinderSuite) TestFindEntityBadTag(c *gc.C) { 303 ua := &common.UnitAgentFinder{fakeEntityFinder{}} 304 _, err := ua.FindEntity(names.NewApplicationTag("foo")) 305 c.Assert(err, gc.ErrorMatches, "unsupported tag.*") 306 } 307 308 func (unitAgentFinderSuite) TestFindEntityErr(c *gc.C) { 309 f := fakeEntityFinder{err: errors.Errorf("boo")} 310 ua := &common.UnitAgentFinder{f} 311 _, err := ua.FindEntity(names.NewUnitTag("unit/0")) 312 c.Assert(errors.Cause(err), gc.Equals, f.err) 313 } 314 315 type fakeEntityFinder struct { 316 unit fakeUnit 317 err error 318 } 319 320 func (f fakeEntityFinder) FindEntity(tag names.Tag) (state.Entity, error) { 321 return f.unit, f.err 322 } 323 324 type fakeUnit struct { 325 state.Entity 326 agent *state.UnitAgent 327 } 328 329 func (f fakeUnit) Agent() *state.UnitAgent { 330 return f.agent 331 }