github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/machine_upgradeseries_test.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	jc "github.com/juju/testing/checkers"
     8  	gc "gopkg.in/check.v1"
     9  
    10  	"github.com/juju/juju/core/model"
    11  	"github.com/juju/juju/state"
    12  )
    13  
    14  func (s *MachineSuite) TestCreateUpgradeSeriesLock(c *gc.C) {
    15  	mach := s.setupTestUpdateMachineSeries(c)
    16  	locked, err := mach.IsLockedForSeriesUpgrade()
    17  	c.Assert(err, jc.ErrorIsNil)
    18  	c.Assert(locked, jc.IsFalse)
    19  
    20  	unitIds := []string{"multi-series/0", "multi-series-subordinate/0"}
    21  	err = mach.CreateUpgradeSeriesLock(unitIds, state.UbuntuBase("16.04"))
    22  	c.Assert(err, jc.ErrorIsNil)
    23  
    24  	locked, err = mach.IsLockedForSeriesUpgrade()
    25  	c.Assert(err, jc.ErrorIsNil)
    26  	c.Assert(locked, jc.IsTrue)
    27  
    28  	units, err := mach.UpgradeSeriesUnitStatuses()
    29  	c.Assert(err, jc.ErrorIsNil)
    30  
    31  	lockedUnitsIds := make([]string, len(units))
    32  	i := 0
    33  	for id := range units {
    34  		lockedUnitsIds[i] = id
    35  		i++
    36  	}
    37  	c.Assert(lockedUnitsIds, jc.SameContents, unitIds)
    38  }
    39  
    40  func (s *MachineSuite) TestIsParentLockedForSeriesUpgrade(c *gc.C) {
    41  	parent, err := s.State.AddMachine(state.UbuntuBase("16.04"), state.JobHostUnits)
    42  	c.Assert(err, jc.ErrorIsNil)
    43  
    44  	template := state.MachineTemplate{
    45  		Base: state.UbuntuBase("16.04"),
    46  		Jobs: []state.MachineJob{state.JobHostUnits},
    47  	}
    48  	child, err := s.State.AddMachineInsideMachine(template, parent.Id(), "lxd")
    49  	c.Assert(err, jc.ErrorIsNil)
    50  
    51  	err = parent.CreateUpgradeSeriesLock([]string{}, state.UbuntuBase("18.04"))
    52  	c.Assert(err, jc.ErrorIsNil)
    53  
    54  	locked, err := child.IsParentLockedForSeriesUpgrade()
    55  	c.Assert(err, jc.ErrorIsNil)
    56  	c.Assert(locked, jc.IsTrue)
    57  }
    58  
    59  func (s *MachineSuite) TestCreateUpgradeSeriesLockErrorsIfLockExists(c *gc.C) {
    60  	mach := s.setupTestUpdateMachineSeries(c)
    61  	err := mach.CreateUpgradeSeriesLock([]string{"multi-series/0", "multi-series-subordinate/0"}, state.UbuntuBase("16.04"))
    62  	c.Assert(err, jc.ErrorIsNil)
    63  	err = mach.CreateUpgradeSeriesLock([]string{}, state.UbuntuBase("16.04"))
    64  	c.Assert(err, gc.ErrorMatches, "upgrade series lock for machine \".*\" already exists")
    65  }
    66  
    67  func (s *MachineSuite) TestDoesNotCreateUpgradeSeriesLockOnDyingMachine(c *gc.C) {
    68  	mach, err := s.State.AddMachine(state.UbuntuBase("12.04"), state.JobHostUnits)
    69  	c.Assert(err, jc.ErrorIsNil)
    70  
    71  	err = mach.Destroy()
    72  	c.Assert(err, jc.ErrorIsNil)
    73  
    74  	err = mach.CreateUpgradeSeriesLock([]string{""}, state.UbuntuBase("16.04"))
    75  	c.Assert(err, gc.ErrorMatches, "machine not found or not alive")
    76  }
    77  
    78  func (s *MachineSuite) TestDoesNotCreateUpgradeSeriesLockOnSameSeries(c *gc.C) {
    79  	mach, err := s.State.AddMachine(state.UbuntuBase("16.04"), state.JobHostUnits)
    80  	c.Assert(err, jc.ErrorIsNil)
    81  
    82  	err = mach.CreateUpgradeSeriesLock([]string{""}, state.UbuntuBase("16.04"))
    83  	c.Assert(err, gc.ErrorMatches, "machine .* already at base ubuntu@16.04/stable")
    84  }
    85  
    86  func (s *MachineSuite) TestDoesNotCreateUpgradeSeriesLockUnitsChanged(c *gc.C) {
    87  	mach := s.setupTestUpdateMachineSeries(c)
    88  
    89  	err := mach.CreateUpgradeSeriesLock([]string{"wordpress/0"}, state.UbuntuBase("16.04"))
    90  	c.Assert(err, gc.ErrorMatches, "Units have changed, please retry (.*)")
    91  }
    92  
    93  func (s *MachineSuite) TestUpgradeSeriesTarget(c *gc.C) {
    94  	mach := s.setupTestUpdateMachineSeries(c)
    95  
    96  	units := []string{"multi-series/0", "multi-series-subordinate/0"}
    97  	err := mach.CreateUpgradeSeriesLock(units, state.UbuntuBase("18.04"))
    98  	c.Assert(err, jc.ErrorIsNil)
    99  
   100  	target, err := mach.UpgradeSeriesTarget()
   101  	c.Assert(err, jc.ErrorIsNil)
   102  	c.Check(target, gc.Equals, "ubuntu@18.04/stable")
   103  }
   104  
   105  func (s *MachineSuite) TestRemoveUpgradeSeriesLockUnlocksMachine(c *gc.C) {
   106  	mach, err := s.State.AddMachine(state.UbuntuBase("12.04"), state.JobHostUnits)
   107  	c.Assert(err, jc.ErrorIsNil)
   108  	AssertMachineIsNOTLockedForPrepare(c, mach)
   109  
   110  	err = mach.CreateUpgradeSeriesLock([]string{}, state.UbuntuBase("16.04"))
   111  	c.Assert(err, jc.ErrorIsNil)
   112  	AssertMachineLockedForPrepare(c, mach)
   113  
   114  	err = mach.RemoveUpgradeSeriesLock()
   115  	c.Assert(err, jc.ErrorIsNil)
   116  	AssertMachineIsNOTLockedForPrepare(c, mach)
   117  }
   118  
   119  func (s *MachineSuite) TestRemoveUpgradeSeriesLockIsNoOpIfMachineIsNotLocked(c *gc.C) {
   120  	mach, err := s.State.AddMachine(state.UbuntuBase("12.04"), state.JobHostUnits)
   121  	c.Assert(err, jc.ErrorIsNil)
   122  	AssertMachineIsNOTLockedForPrepare(c, mach)
   123  
   124  	err = mach.RemoveUpgradeSeriesLock()
   125  	c.Assert(err, jc.ErrorIsNil)
   126  }
   127  
   128  func (s *MachineSuite) TestForceMarksSeriesLockUnlocksMachineForCleanup(c *gc.C) {
   129  	mach, err := s.State.AddMachine(state.UbuntuBase("12.04"), state.JobHostUnits)
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	AssertMachineIsNOTLockedForPrepare(c, mach)
   132  
   133  	err = mach.CreateUpgradeSeriesLock([]string{}, state.UbuntuBase("16.04"))
   134  	c.Assert(err, jc.ErrorIsNil)
   135  	AssertMachineLockedForPrepare(c, mach)
   136  
   137  	err = mach.ForceDestroy(dontWait)
   138  	c.Assert(err, jc.ErrorIsNil)
   139  
   140  	// After a forced destroy an upgrade series lock on a machine should be
   141  	// marked for cleanup and therefore should be cleaned up if anything
   142  	// should trigger a state cleanup.
   143  	s.State.Cleanup()
   144  
   145  	// The machine, since it was destroyed, its lock should have been
   146  	// cleaned up. Checking to see if the machine is not locked, that is,
   147  	// checking to see if no lock exist for the machine should yield a
   148  	// positive result.
   149  	AssertMachineIsNOTLockedForPrepare(c, mach)
   150  }
   151  
   152  func (s *MachineSuite) TestCompleteSeriesUpgradeShouldFailWhenMachineIsNotComplete(c *gc.C) {
   153  	err := s.machine.CreateUpgradeSeriesLock([]string{}, state.UbuntuBase("22.04"))
   154  	c.Assert(err, jc.ErrorIsNil)
   155  
   156  	err = s.machine.CompleteUpgradeSeries()
   157  	assertMachineIsNotReadyForCompletion(c, err)
   158  }
   159  
   160  func (s *MachineSuite) TestCompleteSeriesUpgradeShouldSucceedWhenMachinePrepareIsComplete(c *gc.C) {
   161  	unit0 := s.addMachineUnit(c, s.machine)
   162  	err := s.machine.CreateUpgradeSeriesLock([]string{unit0.Name()}, state.UbuntuBase("22.04"))
   163  	c.Assert(err, jc.ErrorIsNil)
   164  
   165  	err = s.machine.SetUpgradeSeriesStatus(model.UpgradeSeriesPrepareCompleted, "")
   166  	c.Assert(err, jc.ErrorIsNil)
   167  
   168  	err = s.machine.CompleteUpgradeSeries()
   169  	c.Assert(err, jc.ErrorIsNil)
   170  }
   171  
   172  func (s *MachineSuite) TestCompleteSeriesUpgradeShouldSetCompleteStatusOfMachine(c *gc.C) {
   173  	err := s.machine.CreateUpgradeSeriesLock([]string{}, state.UbuntuBase("22.04"))
   174  	c.Assert(err, jc.ErrorIsNil)
   175  
   176  	err = s.machine.SetUpgradeSeriesStatus(model.UpgradeSeriesPrepareCompleted, "")
   177  	c.Assert(err, jc.ErrorIsNil)
   178  
   179  	err = s.machine.CompleteUpgradeSeries()
   180  	c.Assert(err, jc.ErrorIsNil)
   181  
   182  	sts, err := s.machine.UpgradeSeriesStatus()
   183  	c.Assert(err, jc.ErrorIsNil)
   184  	c.Assert(sts, gc.Equals, model.UpgradeSeriesCompleteStarted)
   185  }
   186  
   187  func (s *MachineSuite) TestCompleteSeriesUpgradeShouldFailIfAlreadyInCompleteState(c *gc.C) {
   188  	unit0 := s.addMachineUnit(c, s.machine)
   189  	err := s.machine.CreateUpgradeSeriesLock([]string{unit0.Name()}, state.UbuntuBase("22.04"))
   190  	c.Assert(err, jc.ErrorIsNil)
   191  
   192  	err = s.machine.SetUpgradeSeriesStatus(model.UpgradeSeriesPrepareCompleted, "")
   193  	c.Assert(err, jc.ErrorIsNil)
   194  
   195  	err = s.machine.CompleteUpgradeSeries()
   196  	c.Assert(err, jc.ErrorIsNil)
   197  
   198  	err = s.machine.CompleteUpgradeSeries()
   199  	assertMachineIsNotReadyForCompletion(c, err)
   200  }
   201  
   202  func (s *MachineSuite) TestHasUpgradeSeriesLocks(c *gc.C) {
   203  	// Ensure we don't have any locks before testing.
   204  	lock, err := s.State.HasUpgradeSeriesLocks()
   205  	c.Assert(err, jc.ErrorIsNil)
   206  	c.Assert(lock, jc.IsFalse)
   207  
   208  	unit0 := s.addMachineUnit(c, s.machine)
   209  	err = s.machine.CreateUpgradeSeriesLock([]string{unit0.Name()}, state.UbuntuBase("22.04"))
   210  	c.Assert(err, jc.ErrorIsNil)
   211  
   212  	lock, err = s.State.HasUpgradeSeriesLocks()
   213  	c.Assert(err, jc.ErrorIsNil)
   214  	c.Assert(lock, jc.IsTrue)
   215  }
   216  
   217  func assertMachineIsNotReadyForCompletion(c *gc.C, err error) {
   218  	c.Assert(err, gc.ErrorMatches, "machine \"[0-9].*\" can not complete, it is either not prepared or already completed")
   219  }
   220  
   221  func (s *MachineSuite) TestUnitsHaveChangedFalse(c *gc.C) {
   222  	mach := s.setupTestUpdateMachineSeries(c)
   223  	err := mach.Refresh()
   224  	c.Assert(err, jc.ErrorIsNil)
   225  	changed, err := state.UnitsHaveChanged(mach, []string{"multi-series/0", "multi-series-subordinate/0"})
   226  	c.Assert(err, jc.ErrorIsNil)
   227  	c.Assert(changed, jc.IsFalse)
   228  }
   229  
   230  func (s *MachineSuite) TestUnitsHaveChangedTrue(c *gc.C) {
   231  	mach := s.setupTestUpdateMachineSeries(c)
   232  	err := mach.Refresh()
   233  	c.Assert(err, jc.ErrorIsNil)
   234  	changed, err := state.UnitsHaveChanged(mach, []string{"multi-series-subordinate/0"})
   235  	c.Assert(err, jc.ErrorIsNil)
   236  	c.Assert(changed, jc.IsTrue)
   237  }
   238  
   239  func (s *MachineSuite) TestUnitsHaveChangedFalseNoUnits(c *gc.C) {
   240  	mach, err := s.State.AddMachine(state.UbuntuBase("16.04"), state.JobHostUnits)
   241  	c.Assert(err, jc.ErrorIsNil)
   242  	changed, err := state.UnitsHaveChanged(mach, []string{})
   243  	c.Assert(err, jc.ErrorIsNil)
   244  	c.Assert(changed, jc.IsFalse)
   245  }
   246  
   247  func (s *MachineSuite) TestGetUpgradeSeriesMessagesMissingLockMeansFinished(c *gc.C) {
   248  	_, finished, err := s.machine.GetUpgradeSeriesMessages()
   249  	c.Assert(err, jc.ErrorIsNil)
   250  	c.Assert(finished, jc.IsTrue)
   251  }
   252  
   253  func (s *MachineSuite) TestIsLockedIndicatesUnlockedWhenNoLockDocIsFound(c *gc.C) {
   254  	locked, err := s.machine.IsLockedForSeriesUpgrade()
   255  	c.Assert(err, jc.ErrorIsNil)
   256  	c.Assert(locked, jc.IsFalse)
   257  }
   258  
   259  func AssertMachineLockedForPrepare(c *gc.C, mach *state.Machine) {
   260  	locked, err := mach.IsLockedForSeriesUpgrade()
   261  	c.Assert(err, jc.ErrorIsNil)
   262  	c.Assert(locked, jc.IsTrue)
   263  }
   264  
   265  func AssertMachineIsNOTLockedForPrepare(c *gc.C, mach *state.Machine) {
   266  	locked, err := mach.IsLockedForSeriesUpgrade()
   267  	c.Assert(err, jc.ErrorIsNil)
   268  	c.Assert(locked, jc.IsFalse)
   269  }