github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/uniter/operation/util_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 utilexec "github.com/juju/utils/exec" 10 corecharm "gopkg.in/juju/charm.v6" 11 "gopkg.in/juju/charm.v6/hooks" 12 13 "github.com/juju/juju/core/model" 14 "github.com/juju/juju/core/relation" 15 "github.com/juju/juju/worker/uniter/charm" 16 "github.com/juju/juju/worker/uniter/hook" 17 "github.com/juju/juju/worker/uniter/operation" 18 "github.com/juju/juju/worker/uniter/runner" 19 "github.com/juju/juju/worker/uniter/runner/context" 20 "github.com/juju/juju/worker/uniter/runner/jujuc" 21 ) 22 23 type MockGetArchiveInfo struct { 24 gotCharmURL *corecharm.URL 25 info charm.BundleInfo 26 err error 27 } 28 29 func (mock *MockGetArchiveInfo) Call(charmURL *corecharm.URL) (charm.BundleInfo, error) { 30 mock.gotCharmURL = charmURL 31 return mock.info, mock.err 32 } 33 34 type MockSetCurrentCharm struct { 35 gotCharmURL *corecharm.URL 36 err error 37 } 38 39 func (mock *MockSetCurrentCharm) Call(charmURL *corecharm.URL) error { 40 mock.gotCharmURL = charmURL 41 return mock.err 42 } 43 44 type MockRemoveUpgradeCharmProfileData struct { 45 err error 46 } 47 48 func (mock *MockRemoveUpgradeCharmProfileData) Call() error { 49 return mock.err 50 } 51 52 type DeployCallbacks struct { 53 operation.Callbacks 54 *MockGetArchiveInfo 55 *MockSetCurrentCharm 56 *MockRemoveUpgradeCharmProfileData 57 MockInitializeMetricsTimers *MockNoArgs 58 } 59 60 func (cb *DeployCallbacks) GetArchiveInfo(charmURL *corecharm.URL) (charm.BundleInfo, error) { 61 return cb.MockGetArchiveInfo.Call(charmURL) 62 } 63 64 func (cb *DeployCallbacks) SetCurrentCharm(charmURL *corecharm.URL) error { 65 return cb.MockSetCurrentCharm.Call(charmURL) 66 } 67 68 func (cb *DeployCallbacks) RemoveUpgradeCharmProfileData() error { 69 return cb.MockRemoveUpgradeCharmProfileData.Call() 70 } 71 72 func (cb *DeployCallbacks) InitializeMetricsTimers() error { 73 return cb.MockInitializeMetricsTimers.Call() 74 } 75 76 type MockBundleInfo struct { 77 charm.BundleInfo 78 } 79 80 type MockStage struct { 81 gotInfo *charm.BundleInfo 82 gotAbort *<-chan struct{} 83 err error 84 } 85 86 func (mock *MockStage) Call(info charm.BundleInfo, abort <-chan struct{}) error { 87 mock.gotInfo = &info 88 mock.gotAbort = &abort 89 return mock.err 90 } 91 92 type MockNoArgs struct { 93 called bool 94 err error 95 } 96 97 func (mock *MockNoArgs) Call() error { 98 mock.called = true 99 return mock.err 100 } 101 102 type MockDeployer struct { 103 charm.Deployer 104 *MockStage 105 MockDeploy *MockNoArgs 106 MockNotifyRevert *MockNoArgs 107 MockNotifyResolved *MockNoArgs 108 } 109 110 func (d *MockDeployer) Stage(info charm.BundleInfo, abort <-chan struct{}) error { 111 return d.MockStage.Call(info, abort) 112 } 113 114 func (d *MockDeployer) Deploy() error { 115 return d.MockDeploy.Call() 116 } 117 118 type MockFailAction struct { 119 gotActionId *string 120 gotMessage *string 121 err error 122 } 123 124 func (mock *MockFailAction) Call(actionId, message string) error { 125 mock.gotActionId = &actionId 126 mock.gotMessage = &message 127 return mock.err 128 } 129 130 type RunActionCallbacks struct { 131 operation.Callbacks 132 *MockFailAction 133 executingMessage string 134 } 135 136 func (cb *RunActionCallbacks) FailAction(actionId, message string) error { 137 return cb.MockFailAction.Call(actionId, message) 138 } 139 140 func (cb *RunActionCallbacks) SetExecutingStatus(message string) error { 141 cb.executingMessage = message 142 return nil 143 } 144 145 type RunCommandsCallbacks struct { 146 operation.Callbacks 147 executingMessage string 148 } 149 150 func (cb *RunCommandsCallbacks) SetExecutingStatus(message string) error { 151 cb.executingMessage = message 152 return nil 153 } 154 155 type MockPrepareHook struct { 156 gotHook *hook.Info 157 name string 158 err error 159 } 160 161 func (mock *MockPrepareHook) Call(hookInfo hook.Info) (string, error) { 162 mock.gotHook = &hookInfo 163 return mock.name, mock.err 164 } 165 166 type PrepareHookCallbacks struct { 167 operation.Callbacks 168 *MockPrepareHook 169 executingMessage string 170 } 171 172 func (cb *PrepareHookCallbacks) PrepareHook(hookInfo hook.Info) (string, error) { 173 return cb.MockPrepareHook.Call(hookInfo) 174 } 175 176 func (cb *PrepareHookCallbacks) SetExecutingStatus(message string) error { 177 cb.executingMessage = message 178 return nil 179 } 180 181 func (cb *PrepareHookCallbacks) SetUpgradeSeriesStatus(model.UpgradeSeriesStatus, string) error { 182 return nil 183 } 184 185 type MockNotify struct { 186 gotName *string 187 gotContext *runner.Context 188 } 189 190 func (mock *MockNotify) Call(hookName string, ctx runner.Context) { 191 mock.gotName = &hookName 192 mock.gotContext = &ctx 193 } 194 195 type ExecuteHookCallbacks struct { 196 *PrepareHookCallbacks 197 MockNotifyHookCompleted *MockNotify 198 MockNotifyHookFailed *MockNotify 199 } 200 201 func (cb *ExecuteHookCallbacks) NotifyHookCompleted(hookName string, ctx runner.Context) { 202 cb.MockNotifyHookCompleted.Call(hookName, ctx) 203 } 204 205 func (cb *ExecuteHookCallbacks) NotifyHookFailed(hookName string, ctx runner.Context) { 206 cb.MockNotifyHookFailed.Call(hookName, ctx) 207 } 208 209 type MockCommitHook struct { 210 gotHook *hook.Info 211 err error 212 } 213 214 func (mock *MockCommitHook) Call(hookInfo hook.Info) error { 215 mock.gotHook = &hookInfo 216 return mock.err 217 } 218 219 type CommitHookCallbacks struct { 220 operation.Callbacks 221 *MockCommitHook 222 } 223 224 func (cb *CommitHookCallbacks) CommitHook(hookInfo hook.Info) error { 225 return cb.MockCommitHook.Call(hookInfo) 226 } 227 228 type MockNewActionRunner struct { 229 gotActionId *string 230 runner *MockRunner 231 err error 232 } 233 234 func (mock *MockNewActionRunner) Call(actionId string) (runner.Runner, error) { 235 mock.gotActionId = &actionId 236 return mock.runner, mock.err 237 } 238 239 type MockNewHookRunner struct { 240 gotHook *hook.Info 241 runner *MockRunner 242 err error 243 } 244 245 func (mock *MockNewHookRunner) Call(hookInfo hook.Info) (runner.Runner, error) { 246 mock.gotHook = &hookInfo 247 return mock.runner, mock.err 248 } 249 250 type MockNewCommandRunner struct { 251 gotInfo *context.CommandInfo 252 runner *MockRunner 253 err error 254 } 255 256 func (mock *MockNewCommandRunner) Call(info context.CommandInfo) (runner.Runner, error) { 257 mock.gotInfo = &info 258 return mock.runner, mock.err 259 } 260 261 type MockRunnerFactory struct { 262 *MockNewActionRunner 263 *MockNewHookRunner 264 *MockNewCommandRunner 265 } 266 267 func (f *MockRunnerFactory) NewActionRunner(actionId string) (runner.Runner, error) { 268 return f.MockNewActionRunner.Call(actionId) 269 } 270 271 func (f *MockRunnerFactory) NewHookRunner(hookInfo hook.Info) (runner.Runner, error) { 272 return f.MockNewHookRunner.Call(hookInfo) 273 } 274 275 func (f *MockRunnerFactory) NewCommandRunner(commandInfo context.CommandInfo) (runner.Runner, error) { 276 return f.MockNewCommandRunner.Call(commandInfo) 277 } 278 279 type MockContext struct { 280 runner.Context 281 testing.Stub 282 actionData *context.ActionData 283 setStatusCalled bool 284 status jujuc.StatusInfo 285 isLeader bool 286 relation *MockRelation 287 } 288 289 func (mock *MockContext) ActionData() (*context.ActionData, error) { 290 if mock.actionData == nil { 291 return nil, errors.New("not an action context") 292 } 293 return mock.actionData, nil 294 } 295 296 func (mock *MockContext) HasExecutionSetUnitStatus() bool { 297 return mock.setStatusCalled 298 } 299 300 func (mock *MockContext) ResetExecutionSetUnitStatus() { 301 mock.setStatusCalled = false 302 } 303 304 func (mock *MockContext) SetUnitStatus(status jujuc.StatusInfo) error { 305 mock.setStatusCalled = true 306 mock.status = status 307 return nil 308 } 309 310 func (mock *MockContext) UnitName() string { 311 return "unit/0" 312 } 313 314 func (mock *MockContext) UnitStatus() (*jujuc.StatusInfo, error) { 315 return &mock.status, nil 316 } 317 318 func (mock *MockContext) Prepare() error { 319 mock.MethodCall(mock, "Prepare") 320 return mock.NextErr() 321 } 322 323 func (mock *MockContext) IsLeader() (bool, error) { 324 return mock.isLeader, nil 325 } 326 327 func (mock *MockContext) Relation(id int) (jujuc.ContextRelation, error) { 328 return mock.relation, nil 329 } 330 331 type MockRelation struct { 332 jujuc.ContextRelation 333 suspended bool 334 status relation.Status 335 } 336 337 func (mock *MockRelation) Suspended() bool { 338 return mock.suspended 339 } 340 341 func (mock *MockRelation) SetStatus(status relation.Status) error { 342 mock.status = status 343 return nil 344 } 345 346 type MockRunAction struct { 347 gotName *string 348 err error 349 } 350 351 func (mock *MockRunAction) Call(actionName string) error { 352 mock.gotName = &actionName 353 return mock.err 354 } 355 356 type MockRunCommands struct { 357 gotCommands *string 358 response *utilexec.ExecResponse 359 err error 360 } 361 362 func (mock *MockRunCommands) Call(commands string) (*utilexec.ExecResponse, error) { 363 mock.gotCommands = &commands 364 return mock.response, mock.err 365 } 366 367 type MockRunHook struct { 368 gotName *string 369 err error 370 setStatusCalled bool 371 } 372 373 func (mock *MockRunHook) Call(hookName string) error { 374 mock.gotName = &hookName 375 return mock.err 376 } 377 378 type MockRunner struct { 379 *MockRunAction 380 *MockRunCommands 381 *MockRunHook 382 context runner.Context 383 } 384 385 func (r *MockRunner) Context() runner.Context { 386 return r.context 387 } 388 389 func (r *MockRunner) RunAction(actionName string) error { 390 return r.MockRunAction.Call(actionName) 391 } 392 393 func (r *MockRunner) RunCommands(commands string) (*utilexec.ExecResponse, error) { 394 return r.MockRunCommands.Call(commands) 395 } 396 397 func (r *MockRunner) RunHook(hookName string) error { 398 r.Context().(*MockContext).setStatusCalled = r.MockRunHook.setStatusCalled 399 return r.MockRunHook.Call(hookName) 400 } 401 402 func NewDeployCallbacks() *DeployCallbacks { 403 return &DeployCallbacks{ 404 MockGetArchiveInfo: &MockGetArchiveInfo{info: &MockBundleInfo{}}, 405 MockSetCurrentCharm: &MockSetCurrentCharm{}, 406 MockRemoveUpgradeCharmProfileData: &MockRemoveUpgradeCharmProfileData{}, 407 } 408 } 409 410 func NewDeployCommitCallbacks(err error) *DeployCallbacks { 411 return &DeployCallbacks{ 412 MockInitializeMetricsTimers: &MockNoArgs{err: err}, 413 } 414 } 415 func NewMockDeployer() *MockDeployer { 416 return &MockDeployer{ 417 MockStage: &MockStage{}, 418 MockDeploy: &MockNoArgs{}, 419 MockNotifyRevert: &MockNoArgs{}, 420 MockNotifyResolved: &MockNoArgs{}, 421 } 422 } 423 424 func NewPrepareHookCallbacks() *PrepareHookCallbacks { 425 return &PrepareHookCallbacks{ 426 MockPrepareHook: &MockPrepareHook{nil, "some-hook-name", nil}, 427 } 428 } 429 430 func NewRunActionRunnerFactory(runErr error) *MockRunnerFactory { 431 return &MockRunnerFactory{ 432 MockNewActionRunner: &MockNewActionRunner{ 433 runner: &MockRunner{ 434 MockRunAction: &MockRunAction{err: runErr}, 435 context: &MockContext{ 436 actionData: &context.ActionData{Name: "some-action-name"}, 437 }, 438 }, 439 }, 440 } 441 } 442 443 func NewRunCommandsRunnerFactory(runResponse *utilexec.ExecResponse, runErr error) *MockRunnerFactory { 444 return &MockRunnerFactory{ 445 MockNewCommandRunner: &MockNewCommandRunner{ 446 runner: &MockRunner{ 447 MockRunCommands: &MockRunCommands{response: runResponse, err: runErr}, 448 context: &MockContext{}, 449 }, 450 }, 451 } 452 } 453 454 func NewRunHookRunnerFactory(runErr error, contextOps ...func(*MockContext)) *MockRunnerFactory { 455 ctx := &MockContext{isLeader: true} 456 for _, op := range contextOps { 457 op(ctx) 458 } 459 460 return &MockRunnerFactory{ 461 MockNewHookRunner: &MockNewHookRunner{ 462 runner: &MockRunner{ 463 MockRunHook: &MockRunHook{err: runErr}, 464 context: ctx, 465 }, 466 }, 467 } 468 } 469 470 type MockSendResponse struct { 471 gotResponse **utilexec.ExecResponse 472 gotErr *error 473 } 474 475 func (mock *MockSendResponse) Call(response *utilexec.ExecResponse, err error) { 476 mock.gotResponse = &response 477 mock.gotErr = &err 478 } 479 480 var curl = corecharm.MustParseURL 481 var someActionId = "f47ac10b-58cc-4372-a567-0e02b2c3d479" 482 var randomActionId = "9f484882-2f18-4fd2-967d-db9663db7bea" 483 var overwriteState = operation.State{ 484 Kind: operation.Continue, 485 Step: operation.Pending, 486 Started: true, 487 CharmURL: curl("cs:quantal/wordpress-2"), 488 ActionId: &randomActionId, 489 Hook: &hook.Info{Kind: hooks.Install}, 490 } 491 var someCommandArgs = operation.CommandArgs{ 492 Commands: "do something", 493 RelationId: 123, 494 RemoteUnitName: "foo/456", 495 ForceRemoteUnit: true, 496 }