github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/upgrader/upgrader_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package upgrader_test
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"path/filepath"
    10  	stdtesting "testing"
    11  	"time"
    12  
    13  	"github.com/juju/errors"
    14  	"github.com/juju/os/series"
    15  	"github.com/juju/testing"
    16  	jc "github.com/juju/testing/checkers"
    17  	"github.com/juju/utils"
    18  	"github.com/juju/utils/arch"
    19  	"github.com/juju/utils/symlink"
    20  	"github.com/juju/version"
    21  	gc "gopkg.in/check.v1"
    22  	"gopkg.in/juju/names.v2"
    23  
    24  	"github.com/juju/juju/agent"
    25  	agenttools "github.com/juju/juju/agent/tools"
    26  	"github.com/juju/juju/api"
    27  	envtesting "github.com/juju/juju/environs/testing"
    28  	envtools "github.com/juju/juju/environs/tools"
    29  	jujutesting "github.com/juju/juju/juju/testing"
    30  	"github.com/juju/juju/state"
    31  	statetesting "github.com/juju/juju/state/testing"
    32  	coretesting "github.com/juju/juju/testing"
    33  	coretools "github.com/juju/juju/tools"
    34  	"github.com/juju/juju/upgrades"
    35  	jujuversion "github.com/juju/juju/version"
    36  	"github.com/juju/juju/worker/gate"
    37  	"github.com/juju/juju/worker/upgrader"
    38  )
    39  
    40  func TestPackage(t *stdtesting.T) {
    41  	coretesting.MgoTestPackage(t)
    42  }
    43  
    44  type UpgraderSuite struct {
    45  	jujutesting.JujuConnSuite
    46  
    47  	machine              *state.Machine
    48  	state                api.Connection
    49  	oldRetryAfter        func() <-chan time.Time
    50  	confVersion          version.Number
    51  	upgradeStepsComplete gate.Lock
    52  	initialCheckComplete gate.Lock
    53  }
    54  
    55  type AllowedTargetVersionSuite struct{}
    56  
    57  var _ = gc.Suite(&UpgraderSuite{})
    58  var _ = gc.Suite(&AllowedTargetVersionSuite{})
    59  
    60  func (s *UpgraderSuite) SetUpTest(c *gc.C) {
    61  	s.JujuConnSuite.SetUpTest(c)
    62  	// s.machine needs to have IsManager() so that it can get the actual
    63  	// current revision to upgrade to.
    64  	s.state, s.machine = s.OpenAPIAsNewMachine(c, state.JobManageModel)
    65  	// Capture the value of RetryAfter, and use that captured
    66  	// value in the cleanup lambda.
    67  	oldRetryAfter := *upgrader.RetryAfter
    68  	s.AddCleanup(func(*gc.C) {
    69  		*upgrader.RetryAfter = oldRetryAfter
    70  	})
    71  	s.upgradeStepsComplete = gate.NewLock()
    72  	s.initialCheckComplete = gate.NewLock()
    73  }
    74  
    75  func (s *UpgraderSuite) patchVersion(v version.Binary) {
    76  	s.PatchValue(&arch.HostArch, func() string { return v.Arch })
    77  	s.PatchValue(&series.MustHostSeries, func() string { return v.Series })
    78  	s.PatchValue(&jujuversion.Current, v.Number)
    79  }
    80  
    81  type mockConfig struct {
    82  	agent.Config
    83  	tag     names.Tag
    84  	datadir string
    85  	version version.Number
    86  }
    87  
    88  func (mock *mockConfig) Tag() names.Tag {
    89  	return mock.tag
    90  }
    91  
    92  func (mock *mockConfig) DataDir() string {
    93  	return mock.datadir
    94  }
    95  
    96  func agentConfig(tag names.Tag, datadir string) agent.Config {
    97  	return &mockConfig{
    98  		tag:     tag,
    99  		datadir: datadir,
   100  	}
   101  }
   102  
   103  func (s *UpgraderSuite) makeUpgrader(c *gc.C) *upgrader.Upgrader {
   104  	w, err := upgrader.NewAgentUpgrader(upgrader.Config{
   105  		State:                       s.state.Upgrader(),
   106  		AgentConfig:                 agentConfig(s.machine.Tag(), s.DataDir()),
   107  		OrigAgentVersion:            s.confVersion,
   108  		UpgradeStepsWaiter:          s.upgradeStepsComplete,
   109  		InitialUpgradeCheckComplete: s.initialCheckComplete,
   110  		CheckDiskSpace:              func(string, uint64) error { return nil },
   111  	})
   112  	c.Assert(err, jc.ErrorIsNil)
   113  	return w
   114  }
   115  
   116  func (s *UpgraderSuite) TestUpgraderSetsTools(c *gc.C) {
   117  	vers := version.MustParseBinary("5.4.3-precise-amd64")
   118  	err := statetesting.SetAgentVersion(s.State, vers.Number)
   119  	c.Assert(err, jc.ErrorIsNil)
   120  	stor := s.DefaultToolsStorage
   121  	agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), vers)
   122  	s.patchVersion(agentTools.Version)
   123  	err = envtools.MergeAndWriteMetadata(stor, "released", "released", coretools.List{agentTools}, envtools.DoNotWriteMirrors)
   124  	_, err = s.machine.AgentTools()
   125  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   126  
   127  	u := s.makeUpgrader(c)
   128  	statetesting.AssertStop(c, u)
   129  	s.expectInitialUpgradeCheckDone(c)
   130  	s.machine.Refresh()
   131  	gotTools, err := s.machine.AgentTools()
   132  	c.Assert(err, jc.ErrorIsNil)
   133  	envtesting.CheckTools(c, gotTools, agentTools)
   134  }
   135  
   136  func (s *UpgraderSuite) TestUpgraderSetVersion(c *gc.C) {
   137  	vers := version.MustParseBinary("5.4.3-precise-amd64")
   138  	agentTools := envtesting.PrimeTools(c, s.DefaultToolsStorage, s.DataDir(), s.Environ.Config().AgentStream(), vers)
   139  	s.patchVersion(agentTools.Version)
   140  	err := os.RemoveAll(filepath.Join(s.DataDir(), "tools"))
   141  	c.Assert(err, jc.ErrorIsNil)
   142  
   143  	_, err = s.machine.AgentTools()
   144  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   145  	err = statetesting.SetAgentVersion(s.State, vers.Number)
   146  	c.Assert(err, jc.ErrorIsNil)
   147  
   148  	u := s.makeUpgrader(c)
   149  	statetesting.AssertStop(c, u)
   150  	s.expectInitialUpgradeCheckDone(c)
   151  	s.machine.Refresh()
   152  	gotTools, err := s.machine.AgentTools()
   153  	c.Assert(err, jc.ErrorIsNil)
   154  	c.Assert(gotTools, gc.DeepEquals, &coretools.Tools{Version: vers})
   155  }
   156  
   157  func (s *UpgraderSuite) expectInitialUpgradeCheckDone(c *gc.C) {
   158  	c.Assert(s.initialCheckComplete.IsUnlocked(), jc.IsTrue)
   159  }
   160  
   161  func (s *UpgraderSuite) expectInitialUpgradeCheckNotDone(c *gc.C) {
   162  	c.Assert(s.initialCheckComplete.IsUnlocked(), jc.IsFalse)
   163  }
   164  
   165  func (s *UpgraderSuite) TestUpgraderUpgradesImmediately(c *gc.C) {
   166  	stor := s.DefaultToolsStorage
   167  	oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64"))
   168  	s.patchVersion(oldTools.Version)
   169  	newTools := envtesting.AssertUploadFakeToolsVersions(
   170  		c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.5-precise-amd64"))[0]
   171  	err := statetesting.SetAgentVersion(s.State, newTools.Version.Number)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  
   174  	u := s.makeUpgrader(c)
   175  	err = u.Stop()
   176  	s.expectInitialUpgradeCheckNotDone(c)
   177  	envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   178  		AgentName: s.machine.Tag().String(),
   179  		OldTools:  oldTools.Version,
   180  		NewTools:  newTools.Version,
   181  		DataDir:   s.DataDir(),
   182  	})
   183  	foundTools, err := agenttools.ReadTools(s.DataDir(), newTools.Version)
   184  	c.Assert(err, jc.ErrorIsNil)
   185  	newTools.URL = fmt.Sprintf("https://%s/model/%s/tools/5.4.5-precise-amd64",
   186  		s.APIState.Addr(), coretesting.ModelTag.Id())
   187  	envtesting.CheckTools(c, foundTools, newTools)
   188  }
   189  
   190  func (s *UpgraderSuite) TestUpgraderRetryAndChanged(c *gc.C) {
   191  	stor := s.DefaultToolsStorage
   192  	oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64"))
   193  	s.patchVersion(oldTools.Version)
   194  	newTools := envtesting.AssertUploadFakeToolsVersions(
   195  		c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.5-precise-amd64"))[0]
   196  	err := statetesting.SetAgentVersion(s.State, newTools.Version.Number)
   197  	c.Assert(err, jc.ErrorIsNil)
   198  
   199  	retryc := make(chan time.Time)
   200  	*upgrader.RetryAfter = func(time.Duration) <-chan time.Time {
   201  		c.Logf("replacement retry after")
   202  		return retryc
   203  	}
   204  	err = stor.Remove(envtools.StorageName(newTools.Version, "released"))
   205  	c.Assert(err, jc.ErrorIsNil)
   206  	u := s.makeUpgrader(c)
   207  	defer u.Stop()
   208  	s.expectInitialUpgradeCheckNotDone(c)
   209  
   210  	for i := 0; i < 3; i++ {
   211  		select {
   212  		case retryc <- time.Now():
   213  		case <-time.After(coretesting.LongWait):
   214  			c.Fatalf("upgrader did not retry (attempt %d)", i)
   215  		}
   216  	}
   217  
   218  	// Make it upgrade to some newer tools that can be
   219  	// downloaded ok; it should stop retrying, download
   220  	// the newer tools and exit.
   221  	newerTools := envtesting.AssertUploadFakeToolsVersions(
   222  		c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.6-precise-amd64"))[0]
   223  
   224  	err = statetesting.SetAgentVersion(s.State, newerTools.Version.Number)
   225  	c.Assert(err, jc.ErrorIsNil)
   226  
   227  	s.BackingState.StartSync()
   228  	done := make(chan error)
   229  	go func() {
   230  		done <- u.Wait()
   231  	}()
   232  	select {
   233  	case err := <-done:
   234  		envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   235  			AgentName: s.machine.Tag().String(),
   236  			OldTools:  oldTools.Version,
   237  			NewTools:  newerTools.Version,
   238  			DataDir:   s.DataDir(),
   239  		})
   240  	case <-time.After(coretesting.LongWait):
   241  		c.Fatalf("upgrader did not quit after upgrading")
   242  	}
   243  }
   244  
   245  func (s *UpgraderSuite) TestChangeAgentTools(c *gc.C) {
   246  	oldTools := &coretools.Tools{
   247  		Version: version.MustParseBinary("1.2.3-quantal-amd64"),
   248  	}
   249  	stor := s.DefaultToolsStorage
   250  	newToolsBinary := "5.4.3-precise-amd64"
   251  	newTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary(newToolsBinary))
   252  	s.patchVersion(newTools.Version)
   253  	err := envtools.MergeAndWriteMetadata(stor, "released", "released", coretools.List{newTools}, envtools.DoNotWriteMirrors)
   254  	c.Assert(err, jc.ErrorIsNil)
   255  	ugErr := &upgrader.UpgradeReadyError{
   256  		AgentName: "anAgent",
   257  		OldTools:  oldTools.Version,
   258  		NewTools:  newTools.Version,
   259  		DataDir:   s.DataDir(),
   260  	}
   261  	err = ugErr.ChangeAgentTools()
   262  	c.Assert(err, jc.ErrorIsNil)
   263  	target := agenttools.ToolsDir(s.DataDir(), newToolsBinary)
   264  	link, err := symlink.Read(agenttools.ToolsDir(s.DataDir(), "anAgent"))
   265  	c.Assert(err, jc.ErrorIsNil)
   266  	c.Assert(link, jc.SamePath, target)
   267  }
   268  
   269  func (s *UpgraderSuite) TestUsesAlreadyDownloadedToolsIfAvailable(c *gc.C) {
   270  	oldVersion := version.MustParseBinary("1.2.3-quantal-amd64")
   271  	s.patchVersion(oldVersion)
   272  
   273  	newVersion := version.MustParseBinary("5.4.3-quantal-amd64")
   274  	err := statetesting.SetAgentVersion(s.State, newVersion.Number)
   275  	c.Assert(err, jc.ErrorIsNil)
   276  
   277  	// Install tools matching the new version in the data directory
   278  	// but *not* in environment storage. The upgrader should find the
   279  	// downloaded tools without looking in environment storage.
   280  	envtesting.InstallFakeDownloadedTools(c, s.DataDir(), newVersion)
   281  
   282  	u := s.makeUpgrader(c)
   283  	err = u.Stop()
   284  	s.expectInitialUpgradeCheckNotDone(c)
   285  
   286  	envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   287  		AgentName: s.machine.Tag().String(),
   288  		OldTools:  oldVersion,
   289  		NewTools:  newVersion,
   290  		DataDir:   s.DataDir(),
   291  	})
   292  }
   293  
   294  func (s *UpgraderSuite) TestUpgraderRefusesToDowngradeMinorVersions(c *gc.C) {
   295  	stor := s.DefaultToolsStorage
   296  	origTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64"))
   297  	s.patchVersion(origTools.Version)
   298  	downgradeTools := envtesting.AssertUploadFakeToolsVersions(
   299  		c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.3.3-precise-amd64"))[0]
   300  	err := statetesting.SetAgentVersion(s.State, downgradeTools.Version.Number)
   301  	c.Assert(err, jc.ErrorIsNil)
   302  
   303  	u := s.makeUpgrader(c)
   304  	err = u.Stop()
   305  	s.expectInitialUpgradeCheckDone(c)
   306  	// If the upgrade would have triggered, we would have gotten an
   307  	// UpgradeReadyError, since it was skipped, we get no error
   308  	c.Check(err, jc.ErrorIsNil)
   309  	_, err = agenttools.ReadTools(s.DataDir(), downgradeTools.Version)
   310  	// TODO: ReadTools *should* be returning some form of errors.NotFound,
   311  	// however, it just passes back a fmt.Errorf so we live with it
   312  	// c.Assert(err, jc.Satisfies, errors.IsNotFound)
   313  	c.Check(err, gc.ErrorMatches, "cannot read agent metadata in directory.*"+utils.NoSuchFileErrRegexp)
   314  }
   315  
   316  func (s *UpgraderSuite) TestUpgraderAllowsDowngradingPatchVersions(c *gc.C) {
   317  	stor := s.DefaultToolsStorage
   318  	origTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64"))
   319  	s.patchVersion(origTools.Version)
   320  	downgradeTools := envtesting.AssertUploadFakeToolsVersions(
   321  		c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.2-precise-amd64"))[0]
   322  	err := statetesting.SetAgentVersion(s.State, downgradeTools.Version.Number)
   323  	c.Assert(err, jc.ErrorIsNil)
   324  
   325  	u := s.makeUpgrader(c)
   326  	err = u.Stop()
   327  	s.expectInitialUpgradeCheckNotDone(c)
   328  	envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   329  		AgentName: s.machine.Tag().String(),
   330  		OldTools:  origTools.Version,
   331  		NewTools:  downgradeTools.Version,
   332  		DataDir:   s.DataDir(),
   333  	})
   334  	foundTools, err := agenttools.ReadTools(s.DataDir(), downgradeTools.Version)
   335  	c.Assert(err, jc.ErrorIsNil)
   336  	downgradeTools.URL = fmt.Sprintf("https://%s/model/%s/tools/5.4.2-precise-amd64",
   337  		s.APIState.Addr(), coretesting.ModelTag.Id())
   338  	envtesting.CheckTools(c, foundTools, downgradeTools)
   339  }
   340  
   341  func (s *UpgraderSuite) TestUpgraderAllowsDowngradeToOrigVersionIfUpgradeInProgress(c *gc.C) {
   342  	// note: otherwise illegal version jump
   343  	downgradeVersion := version.MustParseBinary("5.3.0-precise-amd64")
   344  	s.confVersion = downgradeVersion.Number
   345  
   346  	stor := s.DefaultToolsStorage
   347  	origTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64"))
   348  	s.patchVersion(origTools.Version)
   349  	downgradeTools := envtesting.AssertUploadFakeToolsVersions(
   350  		c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), downgradeVersion)[0]
   351  	err := statetesting.SetAgentVersion(s.State, downgradeVersion.Number)
   352  	c.Assert(err, jc.ErrorIsNil)
   353  
   354  	u := s.makeUpgrader(c)
   355  	err = u.Stop()
   356  	s.expectInitialUpgradeCheckNotDone(c)
   357  	envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   358  		AgentName: s.machine.Tag().String(),
   359  		OldTools:  origTools.Version,
   360  		NewTools:  downgradeVersion,
   361  		DataDir:   s.DataDir(),
   362  	})
   363  	foundTools, err := agenttools.ReadTools(s.DataDir(), downgradeTools.Version)
   364  	c.Assert(err, jc.ErrorIsNil)
   365  	downgradeTools.URL = fmt.Sprintf("https://%s/model/%s/tools/5.3.0-precise-amd64",
   366  		s.APIState.Addr(), coretesting.ModelTag.Id())
   367  	envtesting.CheckTools(c, foundTools, downgradeTools)
   368  }
   369  
   370  func (s *UpgraderSuite) TestUpgraderRefusesDowngradeToOrigVersionIfUpgradeNotInProgress(c *gc.C) {
   371  	downgradeVersion := version.MustParseBinary("5.3.0-precise-amd64")
   372  	s.confVersion = downgradeVersion.Number
   373  	s.upgradeStepsComplete.Unlock()
   374  
   375  	stor := s.DefaultToolsStorage
   376  	origTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64"))
   377  	s.patchVersion(origTools.Version)
   378  	envtesting.AssertUploadFakeToolsVersions(
   379  		c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), downgradeVersion)
   380  	err := statetesting.SetAgentVersion(s.State, downgradeVersion.Number)
   381  	c.Assert(err, jc.ErrorIsNil)
   382  
   383  	u := s.makeUpgrader(c)
   384  	err = u.Stop()
   385  	s.expectInitialUpgradeCheckDone(c)
   386  
   387  	// If the upgrade would have triggered, we would have gotten an
   388  	// UpgradeReadyError, since it was skipped, we get no error
   389  	c.Check(err, jc.ErrorIsNil)
   390  }
   391  
   392  func (s *UpgraderSuite) TestChecksSpaceBeforeDownloading(c *gc.C) {
   393  	stor := s.DefaultToolsStorage
   394  	oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.3-precise-amd64"))
   395  	s.patchVersion(oldTools.Version)
   396  	newTools := envtesting.AssertUploadFakeToolsVersions(
   397  		c, stor, s.Environ.Config().AgentStream(), s.Environ.Config().AgentStream(), version.MustParseBinary("5.4.5-precise-amd64"))[0]
   398  	err := statetesting.SetAgentVersion(s.State, newTools.Version.Number)
   399  	c.Assert(err, jc.ErrorIsNil)
   400  
   401  	var diskSpaceStub testing.Stub
   402  	diskSpaceStub.SetErrors(nil, errors.Errorf("full-up"))
   403  
   404  	var retryStub testing.Stub
   405  	retryc := make(chan time.Time)
   406  	*upgrader.RetryAfter = func(d time.Duration) <-chan time.Time {
   407  		retryStub.AddCall("retryAfter", d)
   408  		c.Logf("replacement retry after")
   409  		return retryc
   410  	}
   411  
   412  	u, err := upgrader.NewAgentUpgrader(upgrader.Config{
   413  		State:                       s.state.Upgrader(),
   414  		AgentConfig:                 agentConfig(s.machine.Tag(), s.DataDir()),
   415  		OrigAgentVersion:            s.confVersion,
   416  		UpgradeStepsWaiter:          s.upgradeStepsComplete,
   417  		InitialUpgradeCheckComplete: s.initialCheckComplete,
   418  		CheckDiskSpace: func(dir string, size uint64) error {
   419  			diskSpaceStub.AddCall("CheckDiskSpace", dir, size)
   420  			return diskSpaceStub.NextErr()
   421  		},
   422  	})
   423  	c.Assert(err, jc.ErrorIsNil)
   424  	err = u.Stop()
   425  	s.expectInitialUpgradeCheckNotDone(c)
   426  
   427  	c.Assert(err, jc.ErrorIsNil)
   428  	c.Assert(diskSpaceStub.Calls(), gc.HasLen, 2)
   429  	diskSpaceStub.CheckCall(c, 0, "CheckDiskSpace", s.DataDir(), upgrades.MinDiskSpaceMib)
   430  	diskSpaceStub.CheckCall(c, 1, "CheckDiskSpace", os.TempDir(), upgrades.MinDiskSpaceMib)
   431  
   432  	c.Assert(retryStub.Calls(), gc.HasLen, 1)
   433  	retryStub.CheckCall(c, 0, "retryAfter", time.Minute)
   434  
   435  	_, err = agenttools.ReadTools(s.DataDir(), newTools.Version)
   436  	// Would end with "no such file or directory" on *nix - not sure
   437  	// about Windows so leaving it off.
   438  	c.Assert(err, gc.ErrorMatches, `cannot read agent metadata in directory .*`)
   439  }
   440  
   441  type allowedTest struct {
   442  	original       string
   443  	current        string
   444  	target         string
   445  	upgradeRunning bool
   446  	allowed        bool
   447  }
   448  
   449  func (s *AllowedTargetVersionSuite) TestAllowedTargetVersionSuite(c *gc.C) {
   450  	cases := []allowedTest{
   451  		{original: "1.2.3", current: "1.2.3", upgradeRunning: false, target: "1.3.3", allowed: true},
   452  		{original: "1.2.3", current: "1.2.3", upgradeRunning: false, target: "1.2.3", allowed: true},
   453  		{original: "1.2.3", current: "1.2.3", upgradeRunning: false, target: "2.2.3", allowed: true},
   454  		{original: "1.2.3", current: "1.2.3", upgradeRunning: false, target: "1.1.3", allowed: false},
   455  		{original: "1.2.3", current: "1.2.3", upgradeRunning: false, target: "1.2.2", allowed: true}, // downgrade between builds
   456  		{original: "1.2.3", current: "1.2.3", upgradeRunning: false, target: "0.2.3", allowed: false},
   457  		{original: "0.2.3", current: "1.2.3", upgradeRunning: false, target: "0.2.3", allowed: false},
   458  		{original: "0.2.3", current: "1.2.3", upgradeRunning: true, target: "0.2.3", allowed: true}, // downgrade during upgrade
   459  	}
   460  	for i, test := range cases {
   461  		c.Logf("test case %d, %#v", i, test)
   462  		original := version.MustParse(test.original)
   463  		current := version.MustParse(test.current)
   464  		target := version.MustParse(test.target)
   465  		result := upgrader.AllowedTargetVersion(original, current, test.upgradeRunning, target)
   466  		c.Check(result, gc.Equals, test.allowed)
   467  	}
   468  }