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