github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/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  	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  	s.PatchValue(&version.Current, agentTools.Version)
    87  	err = envtools.MergeAndWriteMetadata(stor, coretools.List{agentTools}, envtools.DoNotWriteMirrors)
    88  	_, err = s.machine.AgentTools()
    89  	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
    90  
    91  	u := s.makeUpgrader()
    92  	statetesting.AssertStop(c, u)
    93  	s.machine.Refresh()
    94  	gotTools, err := s.machine.AgentTools()
    95  	c.Assert(err, gc.IsNil)
    96  	envtesting.CheckTools(c, gotTools, agentTools)
    97  }
    98  
    99  func (s *UpgraderSuite) TestUpgraderSetVersion(c *gc.C) {
   100  	vers := version.MustParseBinary("5.4.3-precise-amd64")
   101  	agentTools := envtesting.PrimeTools(c, s.Conn.Environ.Storage(), s.DataDir(), vers)
   102  	s.PatchValue(&version.Current, agentTools.Version)
   103  	err := os.RemoveAll(filepath.Join(s.DataDir(), "tools"))
   104  	c.Assert(err, gc.IsNil)
   105  
   106  	_, err = s.machine.AgentTools()
   107  	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
   108  	err = statetesting.SetAgentVersion(s.State, vers.Number)
   109  	c.Assert(err, gc.IsNil)
   110  
   111  	u := s.makeUpgrader()
   112  	statetesting.AssertStop(c, u)
   113  	s.machine.Refresh()
   114  	gotTools, err := s.machine.AgentTools()
   115  	c.Assert(err, gc.IsNil)
   116  	c.Assert(gotTools, gc.DeepEquals, &coretools.Tools{Version: version.Current})
   117  }
   118  
   119  func (s *UpgraderSuite) TestUpgraderUpgradesImmediately(c *gc.C) {
   120  	stor := s.Conn.Environ.Storage()
   121  	oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
   122  	s.PatchValue(&version.Current, oldTools.Version)
   123  	newTools := envtesting.AssertUploadFakeToolsVersions(
   124  		c, stor, version.MustParseBinary("5.4.5-precise-amd64"))[0]
   125  	err := envtools.MergeAndWriteMetadata(stor, coretools.List{oldTools, newTools}, envtools.DoNotWriteMirrors)
   126  	c.Assert(err, gc.IsNil)
   127  	err = statetesting.SetAgentVersion(s.State, newTools.Version.Number)
   128  	c.Assert(err, gc.IsNil)
   129  
   130  	// Make the download take a while so that we verify that
   131  	// the download happens before the upgrader checks if
   132  	// it's been stopped.
   133  	dummy.SetStorageDelay(coretesting.ShortWait)
   134  
   135  	u := s.makeUpgrader()
   136  	err = u.Stop()
   137  	envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   138  		AgentName: s.machine.Tag(),
   139  		OldTools:  oldTools.Version,
   140  		NewTools:  newTools.Version,
   141  		DataDir:   s.DataDir(),
   142  	})
   143  	foundTools, err := agenttools.ReadTools(s.DataDir(), newTools.Version)
   144  	c.Assert(err, gc.IsNil)
   145  	envtesting.CheckTools(c, foundTools, newTools)
   146  }
   147  
   148  func (s *UpgraderSuite) TestUpgraderRetryAndChanged(c *gc.C) {
   149  	stor := s.Conn.Environ.Storage()
   150  	oldTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
   151  	s.PatchValue(&version.Current, oldTools.Version)
   152  	newTools := envtesting.AssertUploadFakeToolsVersions(
   153  		c, stor, version.MustParseBinary("5.4.5-precise-amd64"))[0]
   154  	err := envtools.MergeAndWriteMetadata(stor, coretools.List{oldTools, newTools}, envtools.DoNotWriteMirrors)
   155  	c.Assert(err, gc.IsNil)
   156  	err = statetesting.SetAgentVersion(s.State, newTools.Version.Number)
   157  	c.Assert(err, gc.IsNil)
   158  
   159  	retryc := make(chan time.Time)
   160  	*upgrader.RetryAfter = func() <-chan time.Time {
   161  		c.Logf("replacement retry after")
   162  		return retryc
   163  	}
   164  	dummy.Poison(s.Conn.Environ.Storage(), envtools.StorageName(newTools.Version), fmt.Errorf("a non-fatal dose"))
   165  	u := s.makeUpgrader()
   166  	defer u.Stop()
   167  
   168  	for i := 0; i < 3; i++ {
   169  		select {
   170  		case retryc <- time.Now():
   171  		case <-time.After(coretesting.LongWait):
   172  			c.Fatalf("upgrader did not retry (attempt %d)", i)
   173  		}
   174  	}
   175  
   176  	// Make it upgrade to some newer tools that can be
   177  	// downloaded ok; it should stop retrying, download
   178  	// the newer tools and exit.
   179  	newerTools := envtesting.AssertUploadFakeToolsVersions(
   180  		c, s.Conn.Environ.Storage(), version.MustParseBinary("5.4.6-precise-amd64"))[0]
   181  
   182  	err = statetesting.SetAgentVersion(s.State, newerTools.Version.Number)
   183  	c.Assert(err, gc.IsNil)
   184  
   185  	s.BackingState.StartSync()
   186  	done := make(chan error)
   187  	go func() {
   188  		done <- u.Wait()
   189  	}()
   190  	select {
   191  	case err := <-done:
   192  		envtesting.CheckUpgraderReadyError(c, err, &upgrader.UpgradeReadyError{
   193  			AgentName: s.machine.Tag(),
   194  			OldTools:  oldTools.Version,
   195  			NewTools:  newerTools.Version,
   196  			DataDir:   s.DataDir(),
   197  		})
   198  	case <-time.After(coretesting.LongWait):
   199  		c.Fatalf("upgrader did not quit after upgrading")
   200  	}
   201  }
   202  
   203  func (s *UpgraderSuite) TestChangeAgentTools(c *gc.C) {
   204  	oldTools := &coretools.Tools{
   205  		Version: version.MustParseBinary("1.2.3-quantal-amd64"),
   206  	}
   207  	stor := s.Conn.Environ.Storage()
   208  	newTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
   209  	s.PatchValue(&version.Current, newTools.Version)
   210  	err := envtools.MergeAndWriteMetadata(stor, coretools.List{newTools}, envtools.DoNotWriteMirrors)
   211  	c.Assert(err, gc.IsNil)
   212  	ugErr := &upgrader.UpgradeReadyError{
   213  		AgentName: "anAgent",
   214  		OldTools:  oldTools.Version,
   215  		NewTools:  newTools.Version,
   216  		DataDir:   s.DataDir(),
   217  	}
   218  	err = ugErr.ChangeAgentTools()
   219  	c.Assert(err, gc.IsNil)
   220  	link, err := os.Readlink(agenttools.ToolsDir(s.DataDir(), "anAgent"))
   221  	c.Assert(err, gc.IsNil)
   222  	c.Assert(link, gc.Equals, newTools.Version.String())
   223  }
   224  
   225  func (s *UpgraderSuite) TestEnsureToolsChecksBeforeDownloading(c *gc.C) {
   226  	stor := s.Conn.Environ.Storage()
   227  	newTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64"))
   228  	s.PatchValue(&version.Current, newTools.Version)
   229  	// We've already downloaded the tools, so change the URL to be
   230  	// something invalid and ensure we don't actually get an error, because
   231  	// it doesn't actually do an HTTP request
   232  	u := s.makeUpgrader()
   233  	newTools.URL = "http://localhost:999999/invalid/path/tools.tgz"
   234  	err := upgrader.EnsureTools(u, newTools, true)
   235  	c.Assert(err, gc.IsNil)
   236  }