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  }