github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/uniter/operation/runhook_test.go (about) 1 // Copyright 2014-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package operation_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/testing" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/juju/charm.v6-unstable/hooks" 12 13 "github.com/juju/juju/worker/uniter/hook" 14 "github.com/juju/juju/worker/uniter/operation" 15 "github.com/juju/juju/worker/uniter/runner/context" 16 "github.com/juju/juju/worker/uniter/runner/jujuc" 17 ) 18 19 type RunHookSuite struct { 20 testing.IsolationSuite 21 } 22 23 var _ = gc.Suite(&RunHookSuite{}) 24 25 type newHook func(operation.Factory, hook.Info) (operation.Operation, error) 26 27 func (s *RunHookSuite) testPrepareHookError( 28 c *gc.C, newHook newHook, expectClearResolvedFlag, expectSkip bool, 29 ) { 30 callbacks := &PrepareHookCallbacks{ 31 MockPrepareHook: &MockPrepareHook{err: errors.New("pow")}, 32 } 33 factory := operation.NewFactory(operation.FactoryParams{ 34 Callbacks: callbacks, 35 }) 36 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 37 c.Assert(err, jc.ErrorIsNil) 38 39 newState, err := op.Prepare(operation.State{}) 40 c.Check(newState, gc.IsNil) 41 if expectSkip { 42 c.Check(err, gc.Equals, operation.ErrSkipExecute) 43 c.Check(callbacks.MockPrepareHook.gotHook, gc.IsNil) 44 return 45 } 46 c.Check(err, gc.ErrorMatches, "pow") 47 c.Check(callbacks.MockPrepareHook.gotHook, gc.DeepEquals, &hook.Info{ 48 Kind: hooks.ConfigChanged, 49 }) 50 } 51 52 func (s *RunHookSuite) TestPrepareHookCtxCalled(c *gc.C) { 53 ctx := &MockContext{} 54 callbacks := &PrepareHookCallbacks{ 55 MockPrepareHook: &MockPrepareHook{}, 56 } 57 runnerFactory := &MockRunnerFactory{ 58 MockNewHookRunner: &MockNewHookRunner{ 59 runner: &MockRunner{ 60 context: ctx, 61 }, 62 }, 63 } 64 factory := operation.NewFactory(operation.FactoryParams{ 65 RunnerFactory: runnerFactory, 66 Callbacks: callbacks, 67 }) 68 69 op, err := factory.NewRunHook(hook.Info{Kind: hooks.ConfigChanged}) 70 c.Assert(err, jc.ErrorIsNil) 71 72 newState, err := op.Prepare(operation.State{}) 73 c.Check(newState, gc.NotNil) 74 c.Assert(err, jc.ErrorIsNil) 75 76 ctx.CheckCall(c, 0, "Prepare") 77 } 78 79 func (s *RunHookSuite) TestPrepareHookCtxError(c *gc.C) { 80 ctx := &MockContext{} 81 ctx.SetErrors(errors.New("ctx prepare error")) 82 callbacks := &PrepareHookCallbacks{ 83 MockPrepareHook: &MockPrepareHook{}, 84 } 85 runnerFactory := &MockRunnerFactory{ 86 MockNewHookRunner: &MockNewHookRunner{ 87 runner: &MockRunner{ 88 context: ctx, 89 }, 90 }, 91 } 92 factory := operation.NewFactory(operation.FactoryParams{ 93 RunnerFactory: runnerFactory, 94 Callbacks: callbacks, 95 }) 96 97 op, err := factory.NewRunHook(hook.Info{Kind: hooks.ConfigChanged}) 98 c.Assert(err, jc.ErrorIsNil) 99 100 newState, err := op.Prepare(operation.State{}) 101 c.Check(newState, gc.IsNil) 102 c.Assert(err, gc.ErrorMatches, `ctx prepare error`) 103 104 ctx.CheckCall(c, 0, "Prepare") 105 } 106 107 func (s *RunHookSuite) TestPrepareHookError_Run(c *gc.C) { 108 s.testPrepareHookError(c, (operation.Factory).NewRunHook, false, false) 109 } 110 111 func (s *RunHookSuite) TestPrepareHookError_Skip(c *gc.C) { 112 s.testPrepareHookError(c, (operation.Factory).NewSkipHook, true, true) 113 } 114 115 func (s *RunHookSuite) testPrepareRunnerError(c *gc.C, newHook newHook) { 116 callbacks := NewPrepareHookCallbacks() 117 runnerFactory := &MockRunnerFactory{ 118 MockNewHookRunner: &MockNewHookRunner{err: errors.New("splat")}, 119 } 120 factory := operation.NewFactory(operation.FactoryParams{ 121 RunnerFactory: runnerFactory, 122 Callbacks: callbacks, 123 }) 124 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 125 c.Assert(err, jc.ErrorIsNil) 126 127 newState, err := op.Prepare(operation.State{}) 128 c.Check(newState, gc.IsNil) 129 c.Check(err, gc.ErrorMatches, "splat") 130 c.Check(runnerFactory.MockNewHookRunner.gotHook, gc.DeepEquals, &hook.Info{ 131 Kind: hooks.ConfigChanged, 132 }) 133 } 134 135 func (s *RunHookSuite) TestPrepareRunnerError_Run(c *gc.C) { 136 s.testPrepareRunnerError(c, (operation.Factory).NewRunHook) 137 } 138 139 func (s *RunHookSuite) testPrepareSuccess( 140 c *gc.C, newHook newHook, before, after operation.State, 141 ) { 142 runnerFactory := NewRunHookRunnerFactory(errors.New("should not call")) 143 callbacks := NewPrepareHookCallbacks() 144 factory := operation.NewFactory(operation.FactoryParams{ 145 RunnerFactory: runnerFactory, 146 Callbacks: callbacks, 147 }) 148 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 149 c.Assert(err, jc.ErrorIsNil) 150 151 newState, err := op.Prepare(before) 152 c.Check(err, jc.ErrorIsNil) 153 c.Check(newState, gc.DeepEquals, &after) 154 } 155 156 func (s *RunHookSuite) TestPrepareSuccess_BlankSlate(c *gc.C) { 157 s.testPrepareSuccess(c, 158 (operation.Factory).NewRunHook, 159 operation.State{}, 160 operation.State{ 161 Kind: operation.RunHook, 162 Step: operation.Pending, 163 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 164 }, 165 ) 166 } 167 168 func (s *RunHookSuite) TestPrepareSuccess_Preserve(c *gc.C) { 169 s.testPrepareSuccess(c, 170 (operation.Factory).NewRunHook, 171 overwriteState, 172 operation.State{ 173 Started: true, 174 Kind: operation.RunHook, 175 Step: operation.Pending, 176 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 177 }, 178 ) 179 } 180 181 func (s *RunHookSuite) getExecuteRunnerTest(c *gc.C, newHook newHook, kind hooks.Kind, runErr error) (operation.Operation, *ExecuteHookCallbacks, *MockRunnerFactory) { 182 runnerFactory := NewRunHookRunnerFactory(runErr) 183 callbacks := &ExecuteHookCallbacks{ 184 PrepareHookCallbacks: NewPrepareHookCallbacks(), 185 MockNotifyHookCompleted: &MockNotify{}, 186 MockNotifyHookFailed: &MockNotify{}, 187 } 188 factory := operation.NewFactory(operation.FactoryParams{ 189 RunnerFactory: runnerFactory, 190 Callbacks: callbacks, 191 }) 192 op, err := newHook(factory, hook.Info{Kind: kind}) 193 c.Assert(err, jc.ErrorIsNil) 194 return op, callbacks, runnerFactory 195 } 196 197 func (s *RunHookSuite) TestExecuteMissingHookError(c *gc.C) { 198 runErr := context.NewMissingHookError("blah-blah") 199 for _, kind := range hooks.UnitHooks() { 200 c.Logf("hook %v", kind) 201 op, callbacks, runnerFactory := s.getExecuteRunnerTest(c, (operation.Factory).NewRunHook, kind, runErr) 202 _, err := op.Prepare(operation.State{}) 203 c.Assert(err, jc.ErrorIsNil) 204 205 newState, err := op.Execute(operation.State{}) 206 c.Assert(err, jc.ErrorIsNil) 207 c.Assert(newState, gc.DeepEquals, &operation.State{ 208 Kind: operation.RunHook, 209 Step: operation.Done, 210 Hook: &hook.Info{Kind: kind}, 211 }) 212 c.Assert(*runnerFactory.MockNewHookRunner.runner.MockRunHook.gotName, gc.Equals, "some-hook-name") 213 c.Assert(callbacks.MockNotifyHookCompleted.gotName, gc.IsNil) 214 c.Assert(callbacks.MockNotifyHookFailed.gotName, gc.IsNil) 215 216 status, err := runnerFactory.MockNewHookRunner.runner.Context().UnitStatus() 217 c.Assert(err, jc.ErrorIsNil) 218 testAfterHookStatus(c, kind, status, false) 219 } 220 } 221 222 func (s *RunHookSuite) TestExecuteRequeueRebootError(c *gc.C) { 223 runErr := context.ErrRequeueAndReboot 224 op, callbacks, runnerFactory := s.getExecuteRunnerTest(c, (operation.Factory).NewRunHook, hooks.ConfigChanged, runErr) 225 _, err := op.Prepare(operation.State{}) 226 c.Assert(err, jc.ErrorIsNil) 227 228 newState, err := op.Execute(operation.State{}) 229 c.Assert(err, gc.Equals, operation.ErrNeedsReboot) 230 c.Assert(newState, gc.DeepEquals, &operation.State{ 231 Kind: operation.RunHook, 232 Step: operation.Queued, 233 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 234 }) 235 c.Assert(*runnerFactory.MockNewHookRunner.runner.MockRunHook.gotName, gc.Equals, "some-hook-name") 236 c.Assert(*callbacks.MockNotifyHookCompleted.gotName, gc.Equals, "some-hook-name") 237 c.Assert(*callbacks.MockNotifyHookCompleted.gotContext, gc.Equals, runnerFactory.MockNewHookRunner.runner.context) 238 c.Assert(callbacks.MockNotifyHookFailed.gotName, gc.IsNil) 239 } 240 241 func (s *RunHookSuite) TestExecuteRebootError(c *gc.C) { 242 runErr := context.ErrReboot 243 op, callbacks, runnerFactory := s.getExecuteRunnerTest(c, (operation.Factory).NewRunHook, hooks.ConfigChanged, runErr) 244 _, err := op.Prepare(operation.State{}) 245 c.Assert(err, jc.ErrorIsNil) 246 247 newState, err := op.Execute(operation.State{}) 248 c.Assert(err, gc.Equals, operation.ErrNeedsReboot) 249 c.Assert(newState, gc.DeepEquals, &operation.State{ 250 Kind: operation.RunHook, 251 Step: operation.Done, 252 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 253 }) 254 c.Assert(*runnerFactory.MockNewHookRunner.runner.MockRunHook.gotName, gc.Equals, "some-hook-name") 255 c.Assert(*callbacks.MockNotifyHookCompleted.gotName, gc.Equals, "some-hook-name") 256 c.Assert(*callbacks.MockNotifyHookCompleted.gotContext, gc.Equals, runnerFactory.MockNewHookRunner.runner.context) 257 c.Assert(callbacks.MockNotifyHookFailed.gotName, gc.IsNil) 258 } 259 260 func (s *RunHookSuite) TestExecuteOtherError(c *gc.C) { 261 runErr := errors.New("graaargh") 262 op, callbacks, runnerFactory := s.getExecuteRunnerTest(c, (operation.Factory).NewRunHook, hooks.ConfigChanged, runErr) 263 _, err := op.Prepare(operation.State{}) 264 c.Assert(err, jc.ErrorIsNil) 265 266 newState, err := op.Execute(operation.State{}) 267 c.Assert(err, gc.Equals, operation.ErrHookFailed) 268 c.Assert(newState, gc.IsNil) 269 c.Assert(*runnerFactory.MockNewHookRunner.runner.MockRunHook.gotName, gc.Equals, "some-hook-name") 270 c.Assert(*callbacks.MockNotifyHookFailed.gotName, gc.Equals, "some-hook-name") 271 c.Assert(*callbacks.MockNotifyHookFailed.gotContext, gc.Equals, runnerFactory.MockNewHookRunner.runner.context) 272 c.Assert(callbacks.MockNotifyHookCompleted.gotName, gc.IsNil) 273 } 274 275 func (s *RunHookSuite) testExecuteSuccess( 276 c *gc.C, before, after operation.State, setStatusCalled bool, 277 ) { 278 op, callbacks, f := s.getExecuteRunnerTest(c, (operation.Factory).NewRunHook, hooks.ConfigChanged, nil) 279 f.MockNewHookRunner.runner.MockRunHook.setStatusCalled = setStatusCalled 280 midState, err := op.Prepare(before) 281 c.Assert(err, jc.ErrorIsNil) 282 c.Assert(midState, gc.NotNil) 283 284 newState, err := op.Execute(*midState) 285 c.Assert(err, jc.ErrorIsNil) 286 c.Assert(newState, gc.DeepEquals, &after) 287 c.Check(callbacks.executingMessage, gc.Equals, "running some-hook-name hook") 288 } 289 290 func (s *RunHookSuite) TestExecuteSuccess_BlankSlate(c *gc.C) { 291 s.testExecuteSuccess(c, 292 operation.State{}, 293 operation.State{ 294 Kind: operation.RunHook, 295 Step: operation.Done, 296 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 297 StatusSet: true, 298 }, 299 true, 300 ) 301 } 302 303 func (s *RunHookSuite) TestExecuteSuccess_Preserve(c *gc.C) { 304 s.testExecuteSuccess(c, 305 overwriteState, 306 operation.State{ 307 Started: true, 308 Kind: operation.RunHook, 309 Step: operation.Done, 310 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 311 StatusSet: true, 312 }, 313 true, 314 ) 315 } 316 317 func (s *RunHookSuite) testExecuteThenCharmStatus( 318 c *gc.C, before, after operation.State, kind hooks.Kind, setStatusCalled bool, 319 ) { 320 op, _, f := s.getExecuteRunnerTest(c, (operation.Factory).NewRunHook, kind, nil) 321 f.MockNewHookRunner.runner.MockRunHook.setStatusCalled = setStatusCalled 322 midState, err := op.Prepare(before) 323 c.Assert(err, jc.ErrorIsNil) 324 c.Assert(midState, gc.NotNil) 325 326 status, err := f.MockNewHookRunner.runner.Context().UnitStatus() 327 c.Assert(err, jc.ErrorIsNil) 328 329 newState, err := op.Execute(*midState) 330 c.Assert(err, jc.ErrorIsNil) 331 c.Assert(newState, gc.DeepEquals, &after) 332 333 status, err = f.MockNewHookRunner.runner.Context().UnitStatus() 334 c.Assert(err, jc.ErrorIsNil) 335 testAfterHookStatus(c, kind, status, after.StatusSet) 336 } 337 338 func testBeforeHookStatus(c *gc.C, kind hooks.Kind, status *jujuc.StatusInfo) { 339 switch kind { 340 case hooks.Install: 341 c.Assert(status.Status, gc.Equals, "maintenance") 342 c.Assert(status.Info, gc.Equals, "installing charm software") 343 case hooks.Stop: 344 c.Assert(string(status.Status), gc.Equals, "maintenance") 345 c.Assert(status.Info, gc.Equals, "cleaning up prior to charm deletion") 346 default: 347 c.Assert(string(status.Status), gc.Equals, "") 348 } 349 } 350 351 func testAfterHookStatus(c *gc.C, kind hooks.Kind, status *jujuc.StatusInfo, statusSetCalled bool) { 352 switch kind { 353 case hooks.Install: 354 c.Assert(status.Status, gc.Equals, "maintenance") 355 c.Assert(status.Info, gc.Equals, "installing charm software") 356 case hooks.Start: 357 if statusSetCalled { 358 c.Assert(string(status.Status), gc.Equals, "") 359 } else { 360 c.Assert(status.Status, gc.Equals, "unknown") 361 } 362 case hooks.Stop: 363 c.Assert(status.Status, gc.Equals, "terminated") 364 default: 365 c.Assert(string(status.Status), gc.Equals, "") 366 } 367 } 368 369 func (s *RunHookSuite) testBeforeHookExecute(c *gc.C, newHook newHook, kind hooks.Kind) { 370 // To check what happens in the beforeHook() call, we run a hook with an error 371 // so that it does not complete successfully and thus afterHook() does not run, 372 // overwriting the values. 373 runErr := errors.New("graaargh") 374 op, _, runnerFactory := s.getExecuteRunnerTest(c, newHook, kind, runErr) 375 _, err := op.Prepare(operation.State{}) 376 c.Assert(err, jc.ErrorIsNil) 377 378 newState, err := op.Execute(operation.State{}) 379 c.Assert(err, gc.Equals, operation.ErrHookFailed) 380 c.Assert(newState, gc.IsNil) 381 382 status, err := runnerFactory.MockNewHookRunner.runner.Context().UnitStatus() 383 c.Assert(err, jc.ErrorIsNil) 384 testBeforeHookStatus(c, kind, status) 385 } 386 387 func (s *RunHookSuite) TestBeforeHookStatus(c *gc.C) { 388 for _, kind := range hooks.UnitHooks() { 389 c.Logf("hook %v", kind) 390 s.testBeforeHookExecute(c, (operation.Factory).NewRunHook, kind) 391 } 392 } 393 394 func (s *RunHookSuite) testExecuteHookWithSetStatus(c *gc.C, kind hooks.Kind, setStatusCalled bool) { 395 s.testExecuteThenCharmStatus(c, 396 overwriteState, 397 operation.State{ 398 Started: true, 399 Kind: operation.RunHook, 400 Step: operation.Done, 401 Hook: &hook.Info{Kind: kind}, 402 StatusSet: setStatusCalled, 403 }, 404 kind, 405 setStatusCalled, 406 ) 407 } 408 409 func (s *RunHookSuite) TestExecuteHookWithSetStatus(c *gc.C) { 410 for _, kind := range hooks.UnitHooks() { 411 c.Logf("hook %v", kind) 412 s.testExecuteHookWithSetStatus(c, kind, true) 413 s.testExecuteHookWithSetStatus(c, kind, false) 414 } 415 } 416 417 func (s *RunHookSuite) testCommitError(c *gc.C, newHook newHook) { 418 callbacks := &CommitHookCallbacks{ 419 MockCommitHook: &MockCommitHook{nil, errors.New("pow")}, 420 } 421 factory := operation.NewFactory(operation.FactoryParams{ 422 Callbacks: callbacks, 423 }) 424 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 425 c.Assert(err, jc.ErrorIsNil) 426 427 newState, err := op.Commit(operation.State{}) 428 c.Assert(newState, gc.IsNil) 429 c.Assert(err, gc.ErrorMatches, "pow") 430 } 431 432 func (s *RunHookSuite) TestCommitError_Run(c *gc.C) { 433 s.testCommitError(c, (operation.Factory).NewRunHook) 434 } 435 436 func (s *RunHookSuite) TestCommitError_Skip(c *gc.C) { 437 s.testCommitError(c, (operation.Factory).NewSkipHook) 438 } 439 440 func (s *RunHookSuite) testCommitSuccess(c *gc.C, newHook newHook, hookInfo hook.Info, before, after operation.State) { 441 callbacks := &CommitHookCallbacks{ 442 MockCommitHook: &MockCommitHook{}, 443 } 444 factory := operation.NewFactory(operation.FactoryParams{ 445 Callbacks: callbacks, 446 }) 447 op, err := newHook(factory, hookInfo) 448 c.Assert(err, jc.ErrorIsNil) 449 450 newState, err := op.Commit(before) 451 c.Assert(err, jc.ErrorIsNil) 452 c.Assert(newState, gc.DeepEquals, &after) 453 } 454 455 func (s *RunHookSuite) TestCommitSuccess_ConfigChanged_QueueStartHook(c *gc.C) { 456 for i, newHook := range []newHook{ 457 (operation.Factory).NewRunHook, 458 (operation.Factory).NewSkipHook, 459 } { 460 c.Logf("variant %d", i) 461 s.testCommitSuccess(c, 462 newHook, 463 hook.Info{Kind: hooks.ConfigChanged}, 464 operation.State{}, 465 operation.State{ 466 Kind: operation.RunHook, 467 Step: operation.Queued, 468 Hook: &hook.Info{Kind: hooks.Start}, 469 }, 470 ) 471 } 472 } 473 474 func (s *RunHookSuite) TestCommitSuccess_ConfigChanged_Preserve(c *gc.C) { 475 for i, newHook := range []newHook{ 476 (operation.Factory).NewRunHook, 477 (operation.Factory).NewSkipHook, 478 } { 479 c.Logf("variant %d", i) 480 s.testCommitSuccess(c, 481 newHook, 482 hook.Info{Kind: hooks.ConfigChanged}, 483 overwriteState, 484 operation.State{ 485 Started: true, 486 Kind: operation.Continue, 487 Step: operation.Pending, 488 }, 489 ) 490 } 491 } 492 493 func (s *RunHookSuite) TestCommitSuccess_Start_SetStarted(c *gc.C) { 494 for i, newHook := range []newHook{ 495 (operation.Factory).NewRunHook, 496 (operation.Factory).NewSkipHook, 497 } { 498 c.Logf("variant %d", i) 499 s.testCommitSuccess(c, 500 newHook, 501 hook.Info{Kind: hooks.Start}, 502 operation.State{}, 503 operation.State{ 504 Started: true, 505 Kind: operation.Continue, 506 Step: operation.Pending, 507 }, 508 ) 509 } 510 } 511 512 func (s *RunHookSuite) TestCommitSuccess_Start_Preserve(c *gc.C) { 513 for i, newHook := range []newHook{ 514 (operation.Factory).NewRunHook, 515 (operation.Factory).NewSkipHook, 516 } { 517 c.Logf("variant %d", i) 518 s.testCommitSuccess(c, 519 newHook, 520 hook.Info{Kind: hooks.Start}, 521 overwriteState, 522 operation.State{ 523 Started: true, 524 Kind: operation.Continue, 525 Step: operation.Pending, 526 }, 527 ) 528 } 529 } 530 531 func (s *RunHookSuite) testQueueHook_BlankSlate(c *gc.C, cause hooks.Kind) { 532 for i, newHook := range []newHook{ 533 (operation.Factory).NewRunHook, 534 (operation.Factory).NewSkipHook, 535 } { 536 c.Logf("variant %d", i) 537 var hi *hook.Info 538 switch cause { 539 case hooks.UpgradeCharm: 540 hi = &hook.Info{Kind: hooks.ConfigChanged} 541 default: 542 hi = nil 543 } 544 s.testCommitSuccess(c, 545 newHook, 546 hook.Info{Kind: cause}, 547 operation.State{}, 548 operation.State{ 549 Kind: operation.RunHook, 550 Step: operation.Queued, 551 Stopped: cause == hooks.Stop, 552 Hook: hi, 553 }, 554 ) 555 } 556 } 557 558 func (s *RunHookSuite) testQueueHook_Preserve(c *gc.C, cause hooks.Kind) { 559 for i, newHook := range []newHook{ 560 (operation.Factory).NewRunHook, 561 (operation.Factory).NewSkipHook, 562 } { 563 c.Logf("variant %d", i) 564 var hi *hook.Info 565 switch cause { 566 case hooks.UpgradeCharm: 567 hi = &hook.Info{Kind: hooks.ConfigChanged} 568 default: 569 hi = nil 570 } 571 s.testCommitSuccess(c, 572 newHook, 573 hook.Info{Kind: cause}, 574 overwriteState, 575 operation.State{ 576 Kind: operation.RunHook, 577 Step: operation.Queued, 578 Started: true, 579 Stopped: cause == hooks.Stop, 580 Hook: hi, 581 }, 582 ) 583 } 584 } 585 586 func (s *RunHookSuite) TestQueueHook_UpgradeCharm_BlankSlate(c *gc.C) { 587 s.testQueueHook_BlankSlate(c, hooks.UpgradeCharm) 588 } 589 590 func (s *RunHookSuite) TestQueueHook_UpgradeCharm_Preserve(c *gc.C) { 591 s.testQueueHook_Preserve(c, hooks.UpgradeCharm) 592 } 593 594 func (s *RunHookSuite) testQueueNothing_BlankSlate(c *gc.C, hookInfo hook.Info) { 595 for i, newHook := range []newHook{ 596 (operation.Factory).NewRunHook, 597 (operation.Factory).NewSkipHook, 598 } { 599 c.Logf("variant %d", i) 600 s.testCommitSuccess(c, 601 newHook, 602 hookInfo, 603 operation.State{}, 604 operation.State{ 605 Installed: hookInfo.Kind == hooks.Install, 606 Kind: operation.Continue, 607 Step: operation.Pending, 608 Stopped: hookInfo.Kind == hooks.Stop, 609 }, 610 ) 611 } 612 } 613 614 func (s *RunHookSuite) testQueueNothing_Preserve(c *gc.C, hookInfo hook.Info) { 615 for i, newHook := range []newHook{ 616 (operation.Factory).NewRunHook, 617 (operation.Factory).NewSkipHook, 618 } { 619 c.Logf("variant %d", i) 620 s.testCommitSuccess(c, 621 newHook, 622 hookInfo, 623 overwriteState, 624 operation.State{ 625 Kind: operation.Continue, 626 Step: operation.Pending, 627 Installed: hookInfo.Kind == hooks.Install, 628 Started: true, 629 Stopped: hookInfo.Kind == hooks.Stop, 630 }, 631 ) 632 } 633 } 634 635 func (s *RunHookSuite) TestQueueNothing_Install_BlankSlate(c *gc.C) { 636 s.testQueueNothing_BlankSlate(c, hook.Info{ 637 Kind: hooks.Install, 638 }) 639 } 640 641 func (s *RunHookSuite) TestQueueNothing_Install_Preserve(c *gc.C) { 642 s.testQueueNothing_Preserve(c, hook.Info{ 643 Kind: hooks.Install, 644 }) 645 } 646 647 func (s *RunHookSuite) TestQueueNothing_Stop_BlankSlate(c *gc.C) { 648 s.testQueueNothing_BlankSlate(c, hook.Info{ 649 Kind: hooks.Stop, 650 }) 651 } 652 653 func (s *RunHookSuite) TestQueueNothing_Stop_Preserve(c *gc.C) { 654 s.testQueueNothing_Preserve(c, hook.Info{ 655 Kind: hooks.Stop, 656 }) 657 } 658 659 func (s *RunHookSuite) TestQueueNothing_RelationJoined_BlankSlate(c *gc.C) { 660 s.testQueueNothing_BlankSlate(c, hook.Info{ 661 Kind: hooks.RelationJoined, 662 RemoteUnit: "u/0", 663 }) 664 } 665 666 func (s *RunHookSuite) TestQueueNothing_RelationJoined_Preserve(c *gc.C) { 667 s.testQueueNothing_Preserve(c, hook.Info{ 668 Kind: hooks.RelationJoined, 669 RemoteUnit: "u/0", 670 }) 671 } 672 673 func (s *RunHookSuite) TestQueueNothing_RelationChanged_BlankSlate(c *gc.C) { 674 s.testQueueNothing_BlankSlate(c, hook.Info{ 675 Kind: hooks.RelationChanged, 676 RemoteUnit: "u/0", 677 }) 678 } 679 680 func (s *RunHookSuite) TestQueueNothing_RelationChanged_Preserve(c *gc.C) { 681 s.testQueueNothing_Preserve(c, hook.Info{ 682 Kind: hooks.RelationChanged, 683 RemoteUnit: "u/0", 684 }) 685 } 686 687 func (s *RunHookSuite) TestQueueNothing_RelationDeparted_BlankSlate(c *gc.C) { 688 s.testQueueNothing_BlankSlate(c, hook.Info{ 689 Kind: hooks.RelationDeparted, 690 RemoteUnit: "u/0", 691 }) 692 } 693 694 func (s *RunHookSuite) TestQueueNothing_RelationDeparted_Preserve(c *gc.C) { 695 s.testQueueNothing_Preserve(c, hook.Info{ 696 Kind: hooks.RelationDeparted, 697 RemoteUnit: "u/0", 698 }) 699 } 700 701 func (s *RunHookSuite) TestQueueNothing_RelationBroken_BlankSlate(c *gc.C) { 702 s.testQueueNothing_BlankSlate(c, hook.Info{ 703 Kind: hooks.RelationBroken, 704 }) 705 } 706 707 func (s *RunHookSuite) TestQueueNothing_RelationBroken_Preserve(c *gc.C) { 708 s.testQueueNothing_Preserve(c, hook.Info{ 709 Kind: hooks.RelationBroken, 710 }) 711 } 712 713 func (s *RunHookSuite) testNeedsGlobalMachineLock(c *gc.C, newHook newHook, expected bool) { 714 factory := operation.NewFactory(operation.FactoryParams{}) 715 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 716 c.Assert(err, jc.ErrorIsNil) 717 c.Assert(op.NeedsGlobalMachineLock(), gc.Equals, expected) 718 } 719 720 func (s *RunHookSuite) TestNeedsGlobalMachineLock_Run(c *gc.C) { 721 s.testNeedsGlobalMachineLock(c, (operation.Factory).NewRunHook, true) 722 } 723 724 func (s *RunHookSuite) TestNeedsGlobalMachineLock_Skip(c *gc.C) { 725 s.testNeedsGlobalMachineLock(c, (operation.Factory).NewSkipHook, false) 726 }