github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/uniter/operation/deploy_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  	corecharm "gopkg.in/juju/charm.v6"
    12  	"gopkg.in/juju/charm.v6/hooks"
    13  
    14  	"github.com/juju/juju/worker/uniter/hook"
    15  	"github.com/juju/juju/worker/uniter/operation"
    16  )
    17  
    18  type DeploySuite struct {
    19  	testing.IsolationSuite
    20  }
    21  
    22  var _ = gc.Suite(&DeploySuite{})
    23  
    24  type newDeploy func(operation.Factory, *corecharm.URL) (operation.Operation, error)
    25  
    26  func (s *DeploySuite) testPrepareAlreadyDone(
    27  	c *gc.C, newDeploy newDeploy, kind operation.Kind,
    28  ) {
    29  	callbacks := &DeployCallbacks{}
    30  	factory := operation.NewFactory(operation.FactoryParams{Callbacks: callbacks})
    31  	op, err := newDeploy(factory, curl("cs:quantal/hive-23"))
    32  	c.Assert(err, jc.ErrorIsNil)
    33  	newState, err := op.Prepare(operation.State{
    34  		Kind:     kind,
    35  		Step:     operation.Done,
    36  		CharmURL: curl("cs:quantal/hive-23"),
    37  	})
    38  	c.Check(newState, gc.IsNil)
    39  	c.Check(errors.Cause(err), gc.Equals, operation.ErrSkipExecute)
    40  }
    41  
    42  func (s *DeploySuite) TestPrepareAlreadyDone_Install(c *gc.C) {
    43  	s.testPrepareAlreadyDone(c,
    44  		(operation.Factory).NewInstall,
    45  		operation.Install,
    46  	)
    47  }
    48  
    49  func (s *DeploySuite) TestPrepareAlreadyDone_Upgrade(c *gc.C) {
    50  	s.testPrepareAlreadyDone(c,
    51  		(operation.Factory).NewUpgrade,
    52  		operation.Upgrade,
    53  	)
    54  }
    55  
    56  func (s *DeploySuite) TestPrepareAlreadyDone_RevertUpgrade(c *gc.C) {
    57  	s.testPrepareAlreadyDone(c,
    58  		(operation.Factory).NewRevertUpgrade,
    59  		operation.Upgrade,
    60  	)
    61  }
    62  
    63  func (s *DeploySuite) TestPrepareAlreadyDone_ResolvedUpgrade(c *gc.C) {
    64  	s.testPrepareAlreadyDone(c,
    65  		(operation.Factory).NewResolvedUpgrade,
    66  		operation.Upgrade,
    67  	)
    68  }
    69  
    70  func (s *DeploySuite) TestPrepareRemoveUpgradeCharmProfileData_Install(c *gc.C) {
    71  	callbacks := &DeployCallbacks{
    72  		MockRemoveUpgradeCharmProfileData: &MockRemoveUpgradeCharmProfileData{},
    73  	}
    74  	factory := operation.NewFactory(operation.FactoryParams{Callbacks: callbacks})
    75  	op, err := (operation.Factory).NewInstall(factory, curl("cs:quantal/hive-23"))
    76  	c.Assert(err, jc.ErrorIsNil)
    77  	newState, err := op.Prepare(operation.State{
    78  		Kind:     operation.Install,
    79  		Step:     operation.Done,
    80  		CharmURL: curl("cs:quantal/hive-23"),
    81  	})
    82  	c.Check(newState, gc.IsNil)
    83  	c.Check(errors.Cause(err), gc.Equals, operation.ErrSkipExecute)
    84  }
    85  
    86  func (s *DeploySuite) TestPrepareRemoveUpgradeCharmProfileDataError_Install(c *gc.C) {
    87  	callbacks := &DeployCallbacks{
    88  		MockRemoveUpgradeCharmProfileData: &MockRemoveUpgradeCharmProfileData{err: errors.New("pew")},
    89  	}
    90  	deployer := &MockDeployer{
    91  		MockNotifyRevert:   &MockNoArgs{},
    92  		MockNotifyResolved: &MockNoArgs{},
    93  	}
    94  	factory := operation.NewFactory(operation.FactoryParams{
    95  		Deployer:  deployer,
    96  		Callbacks: callbacks,
    97  	})
    98  	op, err := (operation.Factory).NewInstall(factory, curl("cs:quantal/hive-23"))
    99  	c.Assert(err, jc.ErrorIsNil)
   100  
   101  	newState, err := op.Prepare(operation.State{})
   102  	c.Check(newState, gc.IsNil)
   103  	c.Check(err, gc.ErrorMatches, "pew")
   104  }
   105  
   106  func (s *DeploySuite) testPrepareArchiveInfoError(c *gc.C, newDeploy newDeploy) {
   107  	callbacks := &DeployCallbacks{
   108  		MockGetArchiveInfo:                &MockGetArchiveInfo{err: errors.New("pew")},
   109  		MockRemoveUpgradeCharmProfileData: &MockRemoveUpgradeCharmProfileData{}, // for Install
   110  	}
   111  	deployer := &MockDeployer{
   112  		MockNotifyRevert:   &MockNoArgs{},
   113  		MockNotifyResolved: &MockNoArgs{},
   114  	}
   115  	factory := operation.NewFactory(operation.FactoryParams{
   116  		Deployer:  deployer,
   117  		Callbacks: callbacks,
   118  	})
   119  	op, err := newDeploy(factory, curl("cs:quantal/hive-23"))
   120  	c.Assert(err, jc.ErrorIsNil)
   121  
   122  	newState, err := op.Prepare(operation.State{})
   123  	c.Check(newState, gc.IsNil)
   124  	c.Check(err, gc.ErrorMatches, "pew")
   125  	c.Check(callbacks.MockGetArchiveInfo.gotCharmURL, gc.DeepEquals, curl("cs:quantal/hive-23"))
   126  }
   127  
   128  func (s *DeploySuite) TestPrepareArchiveInfoError_Install(c *gc.C) {
   129  	s.testPrepareArchiveInfoError(c, (operation.Factory).NewInstall)
   130  }
   131  
   132  func (s *DeploySuite) TestPrepareArchiveInfoError_Upgrade(c *gc.C) {
   133  	s.testPrepareArchiveInfoError(c, (operation.Factory).NewUpgrade)
   134  }
   135  
   136  func (s *DeploySuite) TestPrepareArchiveInfoError_RevertUpgrade(c *gc.C) {
   137  	s.testPrepareArchiveInfoError(c, (operation.Factory).NewRevertUpgrade)
   138  }
   139  
   140  func (s *DeploySuite) TestPrepareArchiveInfoError_ResolvedUpgrade(c *gc.C) {
   141  	s.testPrepareArchiveInfoError(c, (operation.Factory).NewResolvedUpgrade)
   142  }
   143  
   144  func (s *DeploySuite) testPrepareStageError(c *gc.C, newDeploy newDeploy) {
   145  	callbacks := &DeployCallbacks{
   146  		MockGetArchiveInfo:                &MockGetArchiveInfo{info: &MockBundleInfo{}},
   147  		MockRemoveUpgradeCharmProfileData: &MockRemoveUpgradeCharmProfileData{}, // for Install
   148  	}
   149  	deployer := &MockDeployer{
   150  		MockNotifyRevert:   &MockNoArgs{},
   151  		MockNotifyResolved: &MockNoArgs{},
   152  		MockStage:          &MockStage{err: errors.New("squish")},
   153  	}
   154  	var abort <-chan struct{} = make(chan struct{})
   155  	factory := operation.NewFactory(operation.FactoryParams{
   156  		Deployer:  deployer,
   157  		Callbacks: callbacks,
   158  		Abort:     abort,
   159  	})
   160  	op, err := newDeploy(factory, curl("cs:quantal/hive-23"))
   161  	c.Assert(err, jc.ErrorIsNil)
   162  
   163  	newState, err := op.Prepare(operation.State{})
   164  	c.Check(newState, gc.IsNil)
   165  	c.Check(err, gc.ErrorMatches, "squish")
   166  	c.Check(*deployer.MockStage.gotInfo, gc.Equals, callbacks.MockGetArchiveInfo.info)
   167  	c.Check(*deployer.MockStage.gotAbort, gc.Equals, abort)
   168  }
   169  
   170  func (s *DeploySuite) TestPrepareStageError_Install(c *gc.C) {
   171  	s.testPrepareStageError(c, (operation.Factory).NewInstall)
   172  }
   173  
   174  func (s *DeploySuite) TestPrepareStageError_Upgrade(c *gc.C) {
   175  	s.testPrepareStageError(c, (operation.Factory).NewUpgrade)
   176  }
   177  
   178  func (s *DeploySuite) TestPrepareStageError_RevertUpgrade(c *gc.C) {
   179  	s.testPrepareStageError(c, (operation.Factory).NewRevertUpgrade)
   180  }
   181  
   182  func (s *DeploySuite) TestPrepareStageError_ResolvedUpgrade(c *gc.C) {
   183  	s.testPrepareStageError(c, (operation.Factory).NewResolvedUpgrade)
   184  }
   185  
   186  func (s *DeploySuite) testPrepareSetCharmError(c *gc.C, newDeploy newDeploy) {
   187  	callbacks := &DeployCallbacks{
   188  		MockGetArchiveInfo:                &MockGetArchiveInfo{},
   189  		MockSetCurrentCharm:               &MockSetCurrentCharm{err: errors.New("blargh")},
   190  		MockRemoveUpgradeCharmProfileData: &MockRemoveUpgradeCharmProfileData{}, // for Install
   191  	}
   192  	deployer := &MockDeployer{
   193  		MockNotifyRevert:   &MockNoArgs{},
   194  		MockNotifyResolved: &MockNoArgs{},
   195  		MockStage:          &MockStage{},
   196  	}
   197  	factory := operation.NewFactory(operation.FactoryParams{
   198  		Deployer:  deployer,
   199  		Callbacks: callbacks,
   200  	})
   201  
   202  	op, err := newDeploy(factory, curl("cs:quantal/hive-23"))
   203  	c.Assert(err, jc.ErrorIsNil)
   204  
   205  	newState, err := op.Prepare(operation.State{})
   206  	c.Check(newState, gc.IsNil)
   207  	c.Check(err, gc.ErrorMatches, "blargh")
   208  	c.Check(callbacks.MockSetCurrentCharm.gotCharmURL, gc.DeepEquals, curl("cs:quantal/hive-23"))
   209  }
   210  
   211  func (s *DeploySuite) TestPrepareSetCharmError_Install(c *gc.C) {
   212  	s.testPrepareSetCharmError(c, (operation.Factory).NewInstall)
   213  }
   214  
   215  func (s *DeploySuite) TestPrepareSetCharmError_Upgrade(c *gc.C) {
   216  	s.testPrepareSetCharmError(c, (operation.Factory).NewUpgrade)
   217  }
   218  
   219  func (s *DeploySuite) TestPrepareSetCharmError_RevertUpgrade(c *gc.C) {
   220  	s.testPrepareSetCharmError(c, (operation.Factory).NewRevertUpgrade)
   221  }
   222  
   223  func (s *DeploySuite) TestPrepareSetCharmError_ResolvedUpgrade(c *gc.C) {
   224  	s.testPrepareSetCharmError(c, (operation.Factory).NewResolvedUpgrade)
   225  }
   226  
   227  func (s *DeploySuite) testPrepareSuccess(c *gc.C, newDeploy newDeploy, before, after operation.State) {
   228  	callbacks := NewDeployCallbacks()
   229  	deployer := &MockDeployer{
   230  		MockNotifyRevert:   &MockNoArgs{},
   231  		MockNotifyResolved: &MockNoArgs{},
   232  		MockStage:          &MockStage{},
   233  	}
   234  	factory := operation.NewFactory(operation.FactoryParams{
   235  		Deployer:  deployer,
   236  		Callbacks: callbacks,
   237  	})
   238  	op, err := newDeploy(factory, curl("cs:quantal/nyancat-4"))
   239  	c.Assert(err, jc.ErrorIsNil)
   240  
   241  	newState, err := op.Prepare(before)
   242  	c.Check(err, jc.ErrorIsNil)
   243  	c.Check(newState, gc.DeepEquals, &after)
   244  	c.Check(callbacks.MockSetCurrentCharm.gotCharmURL, gc.DeepEquals, curl("cs:quantal/nyancat-4"))
   245  }
   246  
   247  func (s *DeploySuite) TestPrepareSuccess_Install_BlankSlate(c *gc.C) {
   248  	s.testPrepareSuccess(c,
   249  		(operation.Factory).NewInstall,
   250  		operation.State{},
   251  		operation.State{
   252  			Kind:     operation.Install,
   253  			Step:     operation.Pending,
   254  			CharmURL: curl("cs:quantal/nyancat-4"),
   255  		},
   256  	)
   257  }
   258  
   259  func (s *DeploySuite) TestPrepareSuccess_Install_Queued(c *gc.C) {
   260  	s.testPrepareSuccess(c,
   261  		(operation.Factory).NewInstall,
   262  		operation.State{
   263  			Kind:     operation.Install,
   264  			Step:     operation.Queued,
   265  			CharmURL: curl("cs:quantal/nyancat-4"),
   266  		},
   267  		operation.State{
   268  			Kind:     operation.Install,
   269  			Step:     operation.Pending,
   270  			CharmURL: curl("cs:quantal/nyancat-4"),
   271  		},
   272  	)
   273  }
   274  
   275  func (s *DeploySuite) TestPrepareSuccess_Upgrade_PreservePendingHook(c *gc.C) {
   276  	for i, newDeploy := range []newDeploy{
   277  		(operation.Factory).NewUpgrade,
   278  		(operation.Factory).NewRevertUpgrade,
   279  		(operation.Factory).NewResolvedUpgrade,
   280  	} {
   281  		c.Logf("variant %d", i)
   282  		s.testPrepareSuccess(c,
   283  			newDeploy,
   284  			operation.State{
   285  				Kind: operation.RunHook,
   286  				Step: operation.Pending,
   287  				Hook: &hook.Info{Kind: hooks.ConfigChanged},
   288  			},
   289  			operation.State{
   290  				Kind:     operation.Upgrade,
   291  				Step:     operation.Pending,
   292  				CharmURL: curl("cs:quantal/nyancat-4"),
   293  				Hook:     &hook.Info{Kind: hooks.ConfigChanged},
   294  			},
   295  		)
   296  	}
   297  }
   298  
   299  func (s *DeploySuite) TestPrepareSuccess_Upgrade_PreserveOriginalPendingHook(c *gc.C) {
   300  	for i, newDeploy := range []newDeploy{
   301  		(operation.Factory).NewUpgrade,
   302  		(operation.Factory).NewRevertUpgrade,
   303  		(operation.Factory).NewResolvedUpgrade,
   304  	} {
   305  		c.Logf("variant %d", i)
   306  		s.testPrepareSuccess(c,
   307  			newDeploy,
   308  			operation.State{
   309  				Kind:     operation.Upgrade,
   310  				Step:     operation.Pending,
   311  				CharmURL: curl("cs:quantal/random-23"),
   312  				Hook:     &hook.Info{Kind: hooks.ConfigChanged},
   313  			},
   314  			operation.State{
   315  				Kind:     operation.Upgrade,
   316  				Step:     operation.Pending,
   317  				CharmURL: curl("cs:quantal/nyancat-4"),
   318  				Hook:     &hook.Info{Kind: hooks.ConfigChanged},
   319  			},
   320  		)
   321  	}
   322  }
   323  
   324  func (s *DeploySuite) TestPrepareSuccess_Upgrade_PreserveNoHook(c *gc.C) {
   325  	for i, newDeploy := range []newDeploy{
   326  		(operation.Factory).NewUpgrade,
   327  		(operation.Factory).NewRevertUpgrade,
   328  		(operation.Factory).NewResolvedUpgrade,
   329  	} {
   330  		c.Logf("variant %d", i)
   331  		s.testPrepareSuccess(c,
   332  			newDeploy,
   333  			overwriteState,
   334  			operation.State{
   335  				Kind:     operation.Upgrade,
   336  				Step:     operation.Pending,
   337  				CharmURL: curl("cs:quantal/nyancat-4"),
   338  				Started:  true,
   339  			},
   340  		)
   341  	}
   342  }
   343  
   344  func (s *DeploySuite) TestExecuteConflictError_Install(c *gc.C) {
   345  	s.testExecuteError(c, (operation.Factory).NewInstall)
   346  }
   347  
   348  func (s *DeploySuite) TestExecuteConflictError_Upgrade(c *gc.C) {
   349  	s.testExecuteError(c, (operation.Factory).NewUpgrade)
   350  }
   351  
   352  func (s *DeploySuite) TestExecuteConflictError_RevertUpgrade(c *gc.C) {
   353  	s.testExecuteError(c, (operation.Factory).NewRevertUpgrade)
   354  }
   355  
   356  func (s *DeploySuite) TestExecuteConflictError_ResolvedUpgrade(c *gc.C) {
   357  	s.testExecuteError(c, (operation.Factory).NewResolvedUpgrade)
   358  }
   359  
   360  func (s *DeploySuite) testExecuteError(c *gc.C, newDeploy newDeploy) {
   361  	callbacks := NewDeployCallbacks()
   362  	deployer := &MockDeployer{
   363  		MockNotifyRevert:   &MockNoArgs{},
   364  		MockNotifyResolved: &MockNoArgs{},
   365  		MockStage:          &MockStage{},
   366  		MockDeploy:         &MockNoArgs{err: errors.New("rasp")},
   367  	}
   368  	factory := operation.NewFactory(operation.FactoryParams{
   369  		Deployer:  deployer,
   370  		Callbacks: callbacks,
   371  	})
   372  	op, err := newDeploy(factory, curl("cs:quantal/nyancat-4"))
   373  	c.Assert(err, jc.ErrorIsNil)
   374  	_, err = op.Prepare(operation.State{})
   375  	c.Assert(err, jc.ErrorIsNil)
   376  
   377  	newState, err := op.Execute(operation.State{})
   378  	c.Check(newState, gc.IsNil)
   379  	c.Check(err, gc.ErrorMatches, "rasp")
   380  	c.Check(deployer.MockDeploy.called, jc.IsTrue)
   381  }
   382  
   383  func (s *DeploySuite) TestExecuteError_Install(c *gc.C) {
   384  	s.testExecuteError(c, (operation.Factory).NewInstall)
   385  }
   386  
   387  func (s *DeploySuite) TestExecuteError_Upgrade(c *gc.C) {
   388  	s.testExecuteError(c, (operation.Factory).NewUpgrade)
   389  }
   390  
   391  func (s *DeploySuite) TestExecuteError_RevertUpgrade(c *gc.C) {
   392  	s.testExecuteError(c, (operation.Factory).NewRevertUpgrade)
   393  }
   394  
   395  func (s *DeploySuite) TestExecuteError_ResolvedUpgrade(c *gc.C) {
   396  	s.testExecuteError(c, (operation.Factory).NewResolvedUpgrade)
   397  }
   398  
   399  func (s *DeploySuite) testExecuteSuccess(
   400  	c *gc.C, newDeploy newDeploy, before, after operation.State,
   401  ) {
   402  	deployer := NewMockDeployer()
   403  	callbacks := NewDeployCallbacks()
   404  	factory := operation.NewFactory(operation.FactoryParams{
   405  		Deployer:  deployer,
   406  		Callbacks: callbacks,
   407  	})
   408  	op, err := newDeploy(factory, curl("cs:quantal/lol-1"))
   409  	c.Assert(err, jc.ErrorIsNil)
   410  
   411  	midState, err := op.Prepare(before)
   412  	c.Assert(err, jc.ErrorIsNil)
   413  	c.Assert(midState, gc.NotNil)
   414  
   415  	newState, err := op.Execute(*midState)
   416  	c.Check(err, jc.ErrorIsNil)
   417  	c.Check(newState, gc.DeepEquals, &after)
   418  	c.Check(deployer.MockDeploy.called, jc.IsTrue)
   419  }
   420  
   421  func (s *DeploySuite) TestExecuteSuccess_Install_BlankSlate(c *gc.C) {
   422  	s.testExecuteSuccess(c,
   423  		(operation.Factory).NewInstall,
   424  		operation.State{},
   425  		operation.State{
   426  			Kind:     operation.Install,
   427  			Step:     operation.Done,
   428  			CharmURL: curl("cs:quantal/lol-1"),
   429  		},
   430  	)
   431  }
   432  
   433  func (s *DeploySuite) TestExecuteSuccess_Install_Queued(c *gc.C) {
   434  	s.testExecuteSuccess(c,
   435  		(operation.Factory).NewInstall,
   436  		operation.State{
   437  			Kind:     operation.Install,
   438  			Step:     operation.Queued,
   439  			CharmURL: curl("cs:quantal/lol-1"),
   440  		},
   441  		operation.State{
   442  			Kind:     operation.Install,
   443  			Step:     operation.Done,
   444  			CharmURL: curl("cs:quantal/lol-1"),
   445  		},
   446  	)
   447  }
   448  
   449  func (s *DeploySuite) TestExecuteSuccess_Upgrade_PreservePendingHook(c *gc.C) {
   450  	for i, newDeploy := range []newDeploy{
   451  		(operation.Factory).NewUpgrade,
   452  		(operation.Factory).NewRevertUpgrade,
   453  		(operation.Factory).NewResolvedUpgrade,
   454  	} {
   455  		c.Logf("variant %d", i)
   456  		s.testExecuteSuccess(c,
   457  			newDeploy,
   458  			operation.State{
   459  				Kind: operation.RunHook,
   460  				Step: operation.Pending,
   461  				Hook: &hook.Info{Kind: hooks.ConfigChanged},
   462  			},
   463  			operation.State{
   464  				Kind:     operation.Upgrade,
   465  				Step:     operation.Done,
   466  				CharmURL: curl("cs:quantal/lol-1"),
   467  				Hook:     &hook.Info{Kind: hooks.ConfigChanged},
   468  			},
   469  		)
   470  	}
   471  }
   472  
   473  func (s *DeploySuite) TestExecuteSuccess_Upgrade_PreserveOriginalPendingHook(c *gc.C) {
   474  	for i, newDeploy := range []newDeploy{
   475  		(operation.Factory).NewUpgrade,
   476  		(operation.Factory).NewRevertUpgrade,
   477  		(operation.Factory).NewResolvedUpgrade,
   478  	} {
   479  		c.Logf("variant %d", i)
   480  		s.testExecuteSuccess(c,
   481  			newDeploy,
   482  			operation.State{
   483  				Kind:     operation.Upgrade,
   484  				Step:     operation.Pending,
   485  				CharmURL: curl("cs:quantal/wild-9"),
   486  				Hook:     &hook.Info{Kind: hooks.ConfigChanged},
   487  			},
   488  			operation.State{
   489  				Kind:     operation.Upgrade,
   490  				Step:     operation.Done,
   491  				CharmURL: curl("cs:quantal/lol-1"),
   492  				Hook:     &hook.Info{Kind: hooks.ConfigChanged},
   493  			},
   494  		)
   495  	}
   496  }
   497  
   498  func (s *DeploySuite) TestExecuteSuccess_Upgrade_PreserveNoHook(c *gc.C) {
   499  	for i, newDeploy := range []newDeploy{
   500  		(operation.Factory).NewUpgrade,
   501  		(operation.Factory).NewRevertUpgrade,
   502  		(operation.Factory).NewResolvedUpgrade,
   503  	} {
   504  		c.Logf("variant %d", i)
   505  		s.testExecuteSuccess(c,
   506  			newDeploy,
   507  			overwriteState,
   508  			operation.State{
   509  				Kind:     operation.Upgrade,
   510  				Step:     operation.Done,
   511  				CharmURL: curl("cs:quantal/lol-1"),
   512  				Started:  true,
   513  			},
   514  		)
   515  	}
   516  }
   517  
   518  func (s *DeploySuite) TestCommitQueueInstallHook(c *gc.C) {
   519  	callbacks := NewDeployCommitCallbacks(nil)
   520  	factory := operation.NewFactory(operation.FactoryParams{Callbacks: callbacks})
   521  	op, err := factory.NewInstall(curl("cs:quantal/x-0"))
   522  	c.Assert(err, jc.ErrorIsNil)
   523  	newState, err := op.Commit(operation.State{
   524  		Kind:     operation.Install,
   525  		Step:     operation.Done,
   526  		CharmURL: nil, // doesn't actually matter here
   527  	})
   528  	c.Check(err, jc.ErrorIsNil)
   529  	c.Check(newState, gc.DeepEquals, &operation.State{
   530  		Kind: operation.RunHook,
   531  		Step: operation.Queued,
   532  		Hook: &hook.Info{Kind: hooks.Install},
   533  	})
   534  }
   535  
   536  func (s *DeploySuite) testCommitQueueUpgradeHook(c *gc.C, newDeploy newDeploy) {
   537  	callbacks := NewDeployCommitCallbacks(nil)
   538  	factory := operation.NewFactory(operation.FactoryParams{Callbacks: callbacks})
   539  	op, err := newDeploy(factory, curl("cs:quantal/x-0"))
   540  	c.Assert(err, jc.ErrorIsNil)
   541  	newState, err := op.Commit(operation.State{
   542  		Kind:     operation.Upgrade,
   543  		Step:     operation.Done,
   544  		CharmURL: nil, // doesn't actually matter here
   545  	})
   546  	c.Check(err, jc.ErrorIsNil)
   547  	c.Check(newState, gc.DeepEquals, &operation.State{
   548  		Kind: operation.RunHook,
   549  		Step: operation.Queued,
   550  		Hook: &hook.Info{Kind: hooks.UpgradeCharm},
   551  	})
   552  }
   553  
   554  func (s *DeploySuite) TestCommitQueueUpgradeHook_Upgrade(c *gc.C) {
   555  	s.testCommitQueueUpgradeHook(c, (operation.Factory).NewUpgrade)
   556  }
   557  
   558  func (s *DeploySuite) TestCommitQueueUpgradeHook_RevertUpgrade(c *gc.C) {
   559  	s.testCommitQueueUpgradeHook(c, (operation.Factory).NewRevertUpgrade)
   560  }
   561  
   562  func (s *DeploySuite) TestCommitQueueUpgradeHook_ResolvedUpgrade(c *gc.C) {
   563  	s.testCommitQueueUpgradeHook(c, (operation.Factory).NewResolvedUpgrade)
   564  }
   565  
   566  func (s *DeploySuite) testCommitInterruptedHook(c *gc.C, newDeploy newDeploy) {
   567  	callbacks := NewDeployCommitCallbacks(nil)
   568  	factory := operation.NewFactory(operation.FactoryParams{Callbacks: callbacks})
   569  	op, err := newDeploy(factory, curl("cs:quantal/x-0"))
   570  	c.Assert(err, jc.ErrorIsNil)
   571  	newState, err := op.Commit(operation.State{
   572  		Kind:     operation.Upgrade,
   573  		Step:     operation.Done,
   574  		CharmURL: nil, // doesn't actually matter here
   575  		Hook:     &hook.Info{Kind: hooks.ConfigChanged},
   576  	})
   577  	c.Check(err, jc.ErrorIsNil)
   578  	c.Check(newState, gc.DeepEquals, &operation.State{
   579  		Kind: operation.RunHook,
   580  		Step: operation.Pending,
   581  		Hook: &hook.Info{Kind: hooks.ConfigChanged},
   582  	})
   583  }
   584  
   585  func (s *DeploySuite) TestCommitInterruptedHook_Upgrade(c *gc.C) {
   586  	s.testCommitInterruptedHook(c, (operation.Factory).NewUpgrade)
   587  }
   588  
   589  func (s *DeploySuite) TestCommitInterruptedHook_RevertUpgrade(c *gc.C) {
   590  	s.testCommitInterruptedHook(c, (operation.Factory).NewRevertUpgrade)
   591  }
   592  
   593  func (s *DeploySuite) TestCommitInterruptedHook_ResolvedUpgrade(c *gc.C) {
   594  	s.testCommitInterruptedHook(c, (operation.Factory).NewResolvedUpgrade)
   595  }
   596  
   597  func (s *DeploySuite) testDoesNotNeedGlobalMachineLock(c *gc.C, newDeploy newDeploy) {
   598  	factory := operation.NewFactory(operation.FactoryParams{})
   599  	op, err := newDeploy(factory, curl("cs:quantal/x-0"))
   600  	c.Assert(err, jc.ErrorIsNil)
   601  	c.Assert(op.NeedsGlobalMachineLock(), jc.IsFalse)
   602  }
   603  
   604  func (s *DeploySuite) TestDoesNotNeedGlobalMachineLock_Install(c *gc.C) {
   605  	s.testDoesNotNeedGlobalMachineLock(c, (operation.Factory).NewInstall)
   606  }
   607  
   608  func (s *DeploySuite) TestDoesNotNeedGlobalMachineLock_Upgrade(c *gc.C) {
   609  	s.testDoesNotNeedGlobalMachineLock(c, (operation.Factory).NewUpgrade)
   610  }
   611  
   612  func (s *DeploySuite) TestDoesNotNeedGlobalMachineLock_RevertUpgrade(c *gc.C) {
   613  	s.testDoesNotNeedGlobalMachineLock(c, (operation.Factory).NewRevertUpgrade)
   614  }
   615  
   616  func (s *DeploySuite) TestDoesNotNeedGlobalMachineLock_ResolvedUpgrade(c *gc.C) {
   617  	s.testDoesNotNeedGlobalMachineLock(c, (operation.Factory).NewResolvedUpgrade)
   618  }