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