github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/agent/leadership/leadership_test.go (about) 1 // Copyright 2014-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package leadership_test 5 6 // Test that the service is translating incoming parameters to the 7 // manager layer correctly, and also translates the results back into 8 // network parameters. 9 10 import ( 11 "context" 12 "time" 13 14 "github.com/juju/errors" 15 "github.com/juju/testing" 16 jc "github.com/juju/testing/checkers" 17 gc "gopkg.in/check.v1" 18 "gopkg.in/juju/names.v2" 19 20 "github.com/juju/juju/apiserver/facade" 21 "github.com/juju/juju/apiserver/facades/agent/leadership" 22 "github.com/juju/juju/apiserver/params" 23 coreleadership "github.com/juju/juju/core/leadership" 24 ) 25 26 type leadershipSuite struct { 27 testing.IsolationSuite 28 } 29 30 var _ = gc.Suite(&leadershipSuite{}) 31 32 const ( 33 StubAppNm = "stub-application" 34 StubUnitNm = "stub-application/0" 35 ) 36 37 type stubClaimer struct { 38 ClaimLeadershipFn func(sid, uid string, duration time.Duration) error 39 BlockUntilLeadershipReleasedFn func(serviceId string, cancel <-chan struct{}) error 40 } 41 42 func (m *stubClaimer) ClaimLeadership(sid, uid string, duration time.Duration) error { 43 if m.ClaimLeadershipFn != nil { 44 return m.ClaimLeadershipFn(sid, uid, duration) 45 } 46 return nil 47 } 48 49 func (m *stubClaimer) BlockUntilLeadershipReleased(serviceId string, cancel <-chan struct{}) error { 50 if m.BlockUntilLeadershipReleasedFn != nil { 51 return m.BlockUntilLeadershipReleasedFn(serviceId, cancel) 52 } 53 return nil 54 } 55 56 type stubAuthorizer struct { 57 facade.Authorizer 58 tag names.Tag 59 } 60 61 func (m stubAuthorizer) AuthUnitAgent() bool { 62 _, ok := m.tag.(names.UnitTag) 63 return ok 64 } 65 66 func (m stubAuthorizer) AuthApplicationAgent() bool { 67 _, ok := m.tag.(names.ApplicationTag) 68 return ok 69 } 70 71 func (m stubAuthorizer) AuthOwner(tag names.Tag) bool { 72 return tag == m.tag 73 } 74 75 func (m stubAuthorizer) GetAuthTag() names.Tag { 76 return m.tag 77 } 78 79 func checkDurationEquals(c *gc.C, actual, expect time.Duration) { 80 delta := actual - expect 81 if delta < 0 { 82 delta = -delta 83 } 84 c.Check(delta, jc.LessThan, time.Microsecond) 85 } 86 87 func newLeadershipService( 88 c *gc.C, claimer coreleadership.Claimer, authorizer facade.Authorizer, 89 ) leadership.LeadershipService { 90 if authorizer == nil { 91 authorizer = stubAuthorizer{tag: names.NewUnitTag(StubUnitNm)} 92 } 93 result, err := leadership.NewLeadershipService(claimer, authorizer) 94 c.Assert(err, jc.ErrorIsNil) 95 return result 96 } 97 98 func (s *leadershipSuite) TestClaimLeadershipTranslation(c *gc.C) { 99 claimer := &stubClaimer{ 100 ClaimLeadershipFn: func(sid, uid string, duration time.Duration) error { 101 c.Check(sid, gc.Equals, StubAppNm) 102 c.Check(uid, gc.Equals, StubUnitNm) 103 expectDuration := time.Duration(299.9 * float64(time.Second)) 104 checkDurationEquals(c, duration, expectDuration) 105 return nil 106 }, 107 } 108 109 ldrSvc := newLeadershipService(c, claimer, nil) 110 results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ 111 Params: []params.ClaimLeadershipParams{ 112 { 113 ApplicationTag: names.NewApplicationTag(StubAppNm).String(), 114 UnitTag: names.NewUnitTag(StubUnitNm).String(), 115 DurationSeconds: 299.9, 116 }, 117 }, 118 }) 119 120 c.Check(err, jc.ErrorIsNil) 121 c.Assert(results.Results, gc.HasLen, 1) 122 c.Check(results.Results[0].Error, gc.IsNil) 123 } 124 125 func (s *leadershipSuite) TestClaimLeadershipApplicationAgent(c *gc.C) { 126 claimer := &stubClaimer{ 127 ClaimLeadershipFn: func(sid, uid string, duration time.Duration) error { 128 c.Check(sid, gc.Equals, StubAppNm) 129 c.Check(uid, gc.Equals, StubUnitNm) 130 expectDuration := time.Duration(299.9 * float64(time.Second)) 131 checkDurationEquals(c, duration, expectDuration) 132 return nil 133 }, 134 } 135 136 authorizer := &stubAuthorizer{ 137 tag: names.NewApplicationTag(StubAppNm), 138 } 139 ldrSvc := newLeadershipService(c, claimer, authorizer) 140 results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ 141 Params: []params.ClaimLeadershipParams{ 142 { 143 ApplicationTag: names.NewApplicationTag(StubAppNm).String(), 144 UnitTag: names.NewUnitTag(StubUnitNm).String(), 145 DurationSeconds: 299.9, 146 }, 147 }, 148 }) 149 150 c.Check(err, jc.ErrorIsNil) 151 c.Assert(results.Results, gc.HasLen, 1) 152 c.Check(results.Results[0].Error, gc.IsNil) 153 } 154 155 func (s *leadershipSuite) TestClaimLeadershipDeniedError(c *gc.C) { 156 claimer := &stubClaimer{ 157 ClaimLeadershipFn: func(sid, uid string, duration time.Duration) error { 158 c.Check(sid, gc.Equals, StubAppNm) 159 c.Check(uid, gc.Equals, StubUnitNm) 160 expectDuration := time.Duration(5.001 * float64(time.Second)) 161 checkDurationEquals(c, duration, expectDuration) 162 return errors.Annotatef(coreleadership.ErrClaimDenied, "obfuscated") 163 }, 164 } 165 166 ldrSvc := newLeadershipService(c, claimer, nil) 167 results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ 168 Params: []params.ClaimLeadershipParams{ 169 { 170 ApplicationTag: names.NewApplicationTag(StubAppNm).String(), 171 UnitTag: names.NewUnitTag(StubUnitNm).String(), 172 DurationSeconds: 5.001, 173 }, 174 }, 175 }) 176 177 c.Check(err, jc.ErrorIsNil) 178 c.Assert(results.Results, gc.HasLen, 1) 179 c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeLeadershipClaimDenied) 180 } 181 182 func (s *leadershipSuite) TestClaimLeadershipBadService(c *gc.C) { 183 ldrSvc := newLeadershipService(c, nil, nil) 184 185 results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ 186 Params: []params.ClaimLeadershipParams{ 187 { 188 ApplicationTag: "application-bad/0", 189 UnitTag: names.NewUnitTag(StubUnitNm).String(), 190 DurationSeconds: 123.45, 191 }, 192 }, 193 }) 194 c.Check(err, jc.ErrorIsNil) 195 c.Assert(results.Results, gc.HasLen, 1) 196 c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 197 } 198 199 func (s *leadershipSuite) TestClaimLeadershipBadUnit(c *gc.C) { 200 ldrSvc := newLeadershipService(c, nil, nil) 201 202 results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ 203 Params: []params.ClaimLeadershipParams{ 204 { 205 ApplicationTag: names.NewApplicationTag(StubAppNm).String(), 206 UnitTag: "unit-bad", 207 DurationSeconds: 123.45, 208 }, 209 }, 210 }) 211 c.Check(err, jc.ErrorIsNil) 212 c.Assert(results.Results, gc.HasLen, 1) 213 c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 214 } 215 216 func (s *leadershipSuite) TestClaimLeadershipDurationTooShort(c *gc.C) { 217 ldrSvc := newLeadershipService(c, nil, nil) 218 219 results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ 220 Params: []params.ClaimLeadershipParams{ 221 { 222 ApplicationTag: names.NewApplicationTag(StubAppNm).String(), 223 UnitTag: names.NewUnitTag(StubUnitNm).String(), 224 DurationSeconds: 4.99, 225 }, 226 }, 227 }) 228 c.Check(err, jc.ErrorIsNil) 229 c.Assert(results.Results, gc.HasLen, 1) 230 c.Check(results.Results[0].Error, gc.ErrorMatches, "invalid duration") 231 } 232 233 func (s *leadershipSuite) TestClaimLeadershipDurationTooLong(c *gc.C) { 234 ldrSvc := newLeadershipService(c, nil, nil) 235 236 results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ 237 Params: []params.ClaimLeadershipParams{ 238 { 239 ApplicationTag: names.NewApplicationTag(StubAppNm).String(), 240 UnitTag: names.NewUnitTag(StubUnitNm).String(), 241 DurationSeconds: 300.1, 242 }, 243 }, 244 }) 245 c.Check(err, jc.ErrorIsNil) 246 c.Assert(results.Results, gc.HasLen, 1) 247 c.Check(results.Results[0].Error, gc.ErrorMatches, "invalid duration") 248 } 249 250 func (s *leadershipSuite) TestBlockUntilLeadershipReleasedTranslation(c *gc.C) { 251 claimer := &stubClaimer{ 252 BlockUntilLeadershipReleasedFn: func(sid string, cancel <-chan struct{}) error { 253 c.Check(sid, gc.Equals, StubAppNm) 254 return nil 255 }, 256 } 257 258 ldrSvc := newLeadershipService(c, claimer, nil) 259 result, err := ldrSvc.BlockUntilLeadershipReleased( 260 context.Background(), 261 names.NewApplicationTag(StubAppNm), 262 ) 263 264 c.Check(err, jc.ErrorIsNil) 265 c.Check(result.Error, gc.IsNil) 266 } 267 268 func (s *leadershipSuite) TestBlockUntilLeadershipReleasedContext(c *gc.C) { 269 ctx, cancel := context.WithCancel(context.Background()) 270 cancel() 271 claimer := &stubClaimer{ 272 BlockUntilLeadershipReleasedFn: func(sid string, cancel <-chan struct{}) error { 273 c.Check(sid, gc.Equals, StubAppNm) 274 c.Check(cancel, gc.Equals, ctx.Done()) 275 return coreleadership.ErrBlockCancelled 276 }, 277 } 278 279 ldrSvc := newLeadershipService(c, claimer, nil) 280 result, err := ldrSvc.BlockUntilLeadershipReleased( 281 ctx, 282 names.NewApplicationTag(StubAppNm), 283 ) 284 285 c.Check(err, jc.ErrorIsNil) 286 c.Check(result.Error, gc.ErrorMatches, "waiting for leadership cancelled by client") 287 } 288 289 func (s *leadershipSuite) TestClaimLeadershipFailBadUnit(c *gc.C) { 290 authorizer := &stubAuthorizer{ 291 tag: names.NewUnitTag("lol-different/123"), 292 } 293 294 ldrSvc := newLeadershipService(c, nil, authorizer) 295 results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ 296 Params: []params.ClaimLeadershipParams{ 297 { 298 ApplicationTag: names.NewApplicationTag(StubAppNm).String(), 299 UnitTag: names.NewUnitTag(StubUnitNm).String(), 300 DurationSeconds: 123.45, 301 }, 302 }, 303 }) 304 305 c.Check(err, jc.ErrorIsNil) 306 c.Assert(results.Results, gc.HasLen, 1) 307 c.Check(results.Results[0].Error, gc.ErrorMatches, "permission denied") 308 c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 309 } 310 311 func (s *leadershipSuite) TestClaimLeadershipFailBadService(c *gc.C) { 312 ldrSvc := newLeadershipService(c, nil, nil) 313 results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ 314 Params: []params.ClaimLeadershipParams{ 315 { 316 ApplicationTag: names.NewApplicationTag("lol-different").String(), 317 UnitTag: names.NewUnitTag(StubUnitNm).String(), 318 DurationSeconds: 123.45, 319 }, 320 }, 321 }) 322 323 c.Check(err, jc.ErrorIsNil) 324 c.Assert(results.Results, gc.HasLen, 1) 325 c.Check(results.Results[0].Error, gc.ErrorMatches, "permission denied") 326 c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) 327 } 328 329 func (s *leadershipSuite) TestCreateUnauthorized(c *gc.C) { 330 authorizer := &stubAuthorizer{ 331 tag: names.NewMachineTag("123"), 332 } 333 334 ldrSvc, err := leadership.NewLeadershipService(nil, authorizer) 335 c.Check(ldrSvc, gc.IsNil) 336 c.Check(err, gc.ErrorMatches, "permission denied") 337 c.Check(err, jc.Satisfies, errors.IsUnauthorized) 338 }