launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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  	"os"
     8  	"path/filepath"
     9  	stdtesting "testing"
    10  	"time"
    11  
    12  	errgo "launchpad.net/errgo/errors"
    13  	gc "launchpad.net/gocheck"
    14  
    15  	"launchpad.net/juju-core/agent"
    16  	agenttools "launchpad.net/juju-core/agent/tools"
    17  	envtesting "launchpad.net/juju-core/environs/testing"
    18  	envtools "launchpad.net/juju-core/environs/tools"
    19  	"launchpad.net/juju-core/errors"
    20  	jujutesting "launchpad.net/juju-core/juju/testing"
    21  	"launchpad.net/juju-core/provider/dummy"
    22  	"launchpad.net/juju-core/state"
    23  	"launchpad.net/juju-core/state/api"
    24  	statetesting "launchpad.net/juju-core/state/testing"
    25  	coretesting "launchpad.net/juju-core/testing"
    26  	jc "launchpad.net/juju-core/testing/checkers"
    27  	coretools "launchpad.net/juju-core/tools"
    28  	"launchpad.net/juju-core/version"
    29  	"launchpad.net/juju-core/worker/upgrader"
    30  )
    31  
    32  func TestPackage(t *stdtesting.T) {
    33  	coretesting.MgoTestPackage(t)
    34  }
    35  
    36  type UpgraderSuite struct {
    37  	jujutesting.JujuConnSuite
    38  
    39  	machine       *state.Machine
    40  	state         *api.State
    41  	oldRetryAfter func() <-chan time.Time
    42  }
    43  
    44  var _ = gc.Suite(&UpgraderSuite{})
    45  
    46  func (s *UpgraderSuite) SetUpTest(c *gc.C) {
    47  	s.JujuConnSuite.SetUpTest(c)
    48  	s.state, s.machine = s.OpenAPIAsNewMachine(c)
    49  	// Capture the value of RetryAfter, and use that captured
    50  	// value in the cleanup lambda.
    51  	oldRetryAfter := *upgrader.RetryAfter
    52  	s.AddCleanup(func(*gc.C) {
    53  		*upgrader.RetryAfter = oldRetryAfter
    54  	})
    55  }
    56  
    57  type mockConfig struct {
    58  	agent.Config
    59  	tag     string
    60  	datadir string
    61  }
    62  
    63  func (mock *mockConfig) Tag() string {
    64  	return mock.tag
    65  }
    66  
    67  func (mock *mockConfig) DataDir() string {
    68  	return mock.datadir
    69  }
    70  
    71  func agentConfig(tag, datadir string) agent.Config {
    72  	return &mockConfig{tag: tag, datadir: datadir}
    73  }
    74  
    75  func (s *UpgraderSuite) makeUpgrader() *upgrader.Upgrader {
    76  	config := agentConfig(s.machine.Tag(), s.DataDir())
    77  	return upgrader.NewUpgrader(s.state.Upgrader(), config)
    78  }
    79  
    80  func (s *UpgraderSuite) TestUpgraderSetsTools(c *gc.C) {
    81  	vers := version.MustParseBinary("5.4.3-precise-amd64")
    82  	err := statetesting.SetAgentVersion(s.State, vers.Number)
    83  	c.Assert(err, gc.IsNil)
    84  	stor := s.Conn.Environ.Storage()
    85  	agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), vers)
    86  	err = envtools.MergeAndWriteMetadata(stor, coretools.List{agentTools}, envtools.DoNotWriteMirrors)
    87  	_, err = s.machine.AgentTools()
    88  	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
    89  
    90  	u := s.makeUpgrader()
    91  	statetesting.AssertStop(c, u)
    92  	s.machine.Refresh()
    93  	gotTools, err := s.machine.AgentTools()
    94  	c.Assert(err, gc.IsNil)
    95  	envtesting.CheckTools(c, gotTools, agentTools)
    96  }
    97  
    98  func (s *UpgraderSuite) TestUpgraderSetVersion(c *gc.C) {
    99  	vers := version.MustParseBinary("5.4.3-precise-amd64")
   100  	envtesting.PrimeTools(c, s.Conn.Environ.Storage(), s.DataDir(), vers)
   101  	err := os.RemoveAll(filepath.Join(s.DataDir(), "tools"))
   102  	c.Assert(err, gc.IsNil)
   103  
   104  	_, err = s.machine.AgentTools()
   105  	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
   106  	err = statetesting.SetAgentVersion(s.State, vers.Number)
   107  	c.Assert(err, gc.IsNil)
   108  
   109  	u := s.makeUpgrader()
   110  	statetesting.AssertStop(c, u)
   111  	s.machine.Refresh()
   112  	gotTools, err := s.machine.AgentTools()
   113  	c.Assert(err, gc.IsNil)
   114  	c.Assert(gotTools, gc.DeepEquals, &coretools.Tools{Version: version.Current})
   115  }
   116  
   117  func (s *UpgraderSuite) TestUpgraderUpgradesImmediately(c *gc.C) {
   118  	stor := s.Conn.Environ.Storage()
   119  	oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
   120  	newTools := envtesting.AssertUploadFakeToolsVersions(
   121  		c, stor, version.MustParseBinary("5.4.5-precise-amd64"))[0]
   122  	err := envtools.MergeAndWriteMetadata(stor, coretools.List{oldTools, newTools}, envtools.DoNotWriteMirrors)
   123  	c.Assert(err, gc.IsNil)
   124  	err = statetesting.SetAgentVersion(s.State, newTools.Version.Number)
   125  	c.Assert(err, gc.IsNil)
   126  
   127  	// Make the download take a while so that we verify that
   128  	// the download happens before the upgrader checks if
   129  	// it's been stopped.
   130  	dummy.SetStorageDelay(coretesting.ShortWait)
   131  
   132  	u := s.makeUpgrader()
   133  	err = u.Stop()
   134  	envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   135  		AgentName: s.machine.Tag(),
   136  		OldTools:  oldTools,
   137  		NewTools:  newTools,
   138  		DataDir:   s.DataDir(),
   139  	})
   140  	foundTools, err := agenttools.ReadTools(s.DataDir(), newTools.Version)
   141  	c.Assert(err, gc.IsNil)
   142  	envtesting.CheckTools(c, foundTools, newTools)
   143  }
   144  
   145  func (s *UpgraderSuite) TestUpgraderRetryAndChanged(c *gc.C) {
   146  	stor := s.Conn.Environ.Storage()
   147  	oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
   148  	newTools := envtesting.AssertUploadFakeToolsVersions(
   149  		c, stor, version.MustParseBinary("5.4.5-precise-amd64"))[0]
   150  	err := envtools.MergeAndWriteMetadata(stor, coretools.List{oldTools, newTools}, envtools.DoNotWriteMirrors)
   151  	c.Assert(err, gc.IsNil)
   152  	err = statetesting.SetAgentVersion(s.State, newTools.Version.Number)
   153  	c.Assert(err, gc.IsNil)
   154  
   155  	retryc := make(chan time.Time)
   156  	*upgrader.RetryAfter = func() <-chan time.Time {
   157  		c.Logf("replacement retry after")
   158  		return retryc
   159  	}
   160  	dummy.Poison(s.Conn.Environ.Storage(), envtools.StorageName(newTools.Version), errgo.Newf("a non-fatal dose"))
   161  	u := s.makeUpgrader()
   162  	defer u.Stop()
   163  
   164  	for i := 0; i < 3; i++ {
   165  		select {
   166  		case retryc <- time.Now():
   167  		case <-time.After(coretesting.LongWait):
   168  			c.Fatalf("upgrader did not retry (attempt %d)", i)
   169  		}
   170  	}
   171  
   172  	// Make it upgrade to some newer tools that can be
   173  	// downloaded ok; it should stop retrying, download
   174  	// the newer tools and exit.
   175  	newerTools := envtesting.AssertUploadFakeToolsVersions(
   176  		c, s.Conn.Environ.Storage(), version.MustParseBinary("5.4.6-precise-amd64"))[0]
   177  
   178  	err = statetesting.SetAgentVersion(s.State, newerTools.Version.Number)
   179  	c.Assert(err, gc.IsNil)
   180  
   181  	s.BackingState.StartSync()
   182  	done := make(chan error)
   183  	go func() {
   184  		done <- u.Wait()
   185  	}()
   186  	select {
   187  	case err := <-done:
   188  		envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   189  			AgentName: s.machine.Tag(),
   190  			OldTools:  oldTools,
   191  			NewTools:  newerTools,
   192  			DataDir:   s.DataDir(),
   193  		})
   194  	case <-time.After(coretesting.LongWait):
   195  		c.Fatalf("upgrader did not quit after upgrading")
   196  	}
   197  }
   198  
   199  func (s *UpgraderSuite) TestChangeAgentTools(c *gc.C) {
   200  	oldTools := &coretools.Tools{
   201  		Version: version.MustParseBinary("1.2.3-quantal-amd64"),
   202  	}
   203  	stor := s.Conn.Environ.Storage()
   204  	newTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
   205  	err := envtools.MergeAndWriteMetadata(stor, coretools.List{newTools}, envtools.DoNotWriteMirrors)
   206  	c.Assert(err, gc.IsNil)
   207  	ugErr := &upgrader.UpgradeReadyError{
   208  		AgentName: "anAgent",
   209  		OldTools:  oldTools,
   210  		NewTools:  newTools,
   211  		DataDir:   s.DataDir(),
   212  	}
   213  	err = ugErr.ChangeAgentTools()
   214  	c.Assert(err, gc.IsNil)
   215  	link, err := os.Readlink(agenttools.ToolsDir(s.DataDir(), "anAgent"))
   216  	c.Assert(err, gc.IsNil)
   217  	c.Assert(link, gc.Equals, newTools.Version.String())
   218  }
   219  
   220  func (s *UpgraderSuite) TestEnsureToolsChecksBeforeDownloading(c *gc.C) {
   221  	stor := s.Conn.Environ.Storage()
   222  	newTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
   223  	// We've already downloaded the tools, so change the URL to be
   224  	// something invalid and ensure we don't actually get an error, because
   225  	// it doesn't actually do an HTTP request
   226  	u := s.makeUpgrader()
   227  	newTools.URL = "http://localhost:999999/invalid/path/tools.tgz"
   228  	err := upgrader.EnsureTools(u, newTools, true)
   229  	c.Assert(err, gc.IsNil)
   230  }