github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/cmd/juju/upgradecharm_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"bytes"
     8  	"io/ioutil"
     9  	"os"
    10  	"path"
    11  
    12  	gc "launchpad.net/gocheck"
    13  
    14  	"launchpad.net/juju-core/charm"
    15  	charmtesting "launchpad.net/juju-core/charm/testing"
    16  	jujutesting "launchpad.net/juju-core/juju/testing"
    17  	"launchpad.net/juju-core/state"
    18  	"launchpad.net/juju-core/testing"
    19  )
    20  
    21  type UpgradeCharmErrorsSuite struct {
    22  	jujutesting.RepoSuite
    23  }
    24  
    25  func (s *UpgradeCharmErrorsSuite) SetUpTest(c *gc.C) {
    26  	s.RepoSuite.SetUpTest(c)
    27  	mockstore := charmtesting.NewMockStore(c, map[string]int{})
    28  	s.AddCleanup(func(*gc.C) { mockstore.Close() })
    29  	s.PatchValue(&charm.Store, &charm.CharmStore{
    30  		BaseURL: mockstore.Address(),
    31  	})
    32  }
    33  
    34  var _ = gc.Suite(&UpgradeCharmErrorsSuite{})
    35  
    36  func runUpgradeCharm(c *gc.C, args ...string) error {
    37  	_, err := testing.RunCommand(c, &UpgradeCharmCommand{}, args)
    38  	return err
    39  }
    40  
    41  func (s *UpgradeCharmErrorsSuite) TestInvalidArgs(c *gc.C) {
    42  	err := runUpgradeCharm(c)
    43  	c.Assert(err, gc.ErrorMatches, "no service specified")
    44  	err = runUpgradeCharm(c, "invalid:name")
    45  	c.Assert(err, gc.ErrorMatches, `invalid service name "invalid:name"`)
    46  	err = runUpgradeCharm(c, "foo", "bar")
    47  	c.Assert(err, gc.ErrorMatches, `unrecognized args: \["bar"\]`)
    48  }
    49  
    50  func (s *UpgradeCharmErrorsSuite) TestWithInvalidRepository(c *gc.C) {
    51  	testing.Charms.ClonedDirPath(s.SeriesPath, "riak")
    52  	err := runDeploy(c, "local:riak", "riak")
    53  	c.Assert(err, gc.IsNil)
    54  
    55  	err = runUpgradeCharm(c, "riak", "--repository=blah")
    56  	c.Assert(err, gc.ErrorMatches, `no repository found at ".*blah"`)
    57  	// Reset JUJU_REPOSITORY explicitly, because repoSuite.SetUpTest
    58  	// overwrites it (TearDownTest will revert it again).
    59  	os.Setenv("JUJU_REPOSITORY", "")
    60  	err = runUpgradeCharm(c, "riak", "--repository=")
    61  	c.Assert(err, gc.ErrorMatches, `charm not found in ".*": local:precise/riak`)
    62  }
    63  
    64  func (s *UpgradeCharmErrorsSuite) TestInvalidService(c *gc.C) {
    65  	err := runUpgradeCharm(c, "phony")
    66  	c.Assert(err, gc.ErrorMatches, `service "phony" not found`)
    67  }
    68  
    69  func (s *UpgradeCharmErrorsSuite) deployService(c *gc.C) {
    70  	testing.Charms.ClonedDirPath(s.SeriesPath, "riak")
    71  	err := runDeploy(c, "local:riak", "riak")
    72  	c.Assert(err, gc.IsNil)
    73  }
    74  
    75  func (s *UpgradeCharmErrorsSuite) TestInvalidSwitchURL(c *gc.C) {
    76  	s.deployService(c)
    77  	err := runUpgradeCharm(c, "riak", "--switch=blah")
    78  	c.Assert(err, gc.ErrorMatches, "charm not found: cs:precise/blah")
    79  	err = runUpgradeCharm(c, "riak", "--switch=cs:missing/one")
    80  	c.Assert(err, gc.ErrorMatches, "charm not found: cs:missing/one")
    81  	// TODO(dimitern): add tests with incompatible charms
    82  }
    83  
    84  func (s *UpgradeCharmErrorsSuite) TestSwitchAndRevisionFails(c *gc.C) {
    85  	s.deployService(c)
    86  	err := runUpgradeCharm(c, "riak", "--switch=riak", "--revision=2")
    87  	c.Assert(err, gc.ErrorMatches, "--switch and --revision are mutually exclusive")
    88  }
    89  
    90  func (s *UpgradeCharmErrorsSuite) TestInvalidRevision(c *gc.C) {
    91  	s.deployService(c)
    92  	err := runUpgradeCharm(c, "riak", "--revision=blah")
    93  	c.Assert(err, gc.ErrorMatches, `invalid value "blah" for flag --revision: strconv.ParseInt: parsing "blah": invalid syntax`)
    94  }
    95  
    96  type UpgradeCharmSuccessSuite struct {
    97  	jujutesting.RepoSuite
    98  	path string
    99  	riak *state.Service
   100  }
   101  
   102  var _ = gc.Suite(&UpgradeCharmSuccessSuite{})
   103  
   104  func (s *UpgradeCharmSuccessSuite) SetUpTest(c *gc.C) {
   105  	s.RepoSuite.SetUpTest(c)
   106  	s.path = testing.Charms.ClonedDirPath(s.SeriesPath, "riak")
   107  	err := runDeploy(c, "local:riak", "riak")
   108  	c.Assert(err, gc.IsNil)
   109  	s.riak, err = s.State.Service("riak")
   110  	c.Assert(err, gc.IsNil)
   111  	ch, forced, err := s.riak.Charm()
   112  	c.Assert(err, gc.IsNil)
   113  	c.Assert(ch.Revision(), gc.Equals, 7)
   114  	c.Assert(forced, gc.Equals, false)
   115  }
   116  
   117  func (s *UpgradeCharmSuccessSuite) assertUpgraded(c *gc.C, revision int, forced bool) *charm.URL {
   118  	err := s.riak.Refresh()
   119  	c.Assert(err, gc.IsNil)
   120  	ch, force, err := s.riak.Charm()
   121  	c.Assert(err, gc.IsNil)
   122  	c.Assert(ch.Revision(), gc.Equals, revision)
   123  	c.Assert(force, gc.Equals, forced)
   124  	s.AssertCharmUploaded(c, ch.URL())
   125  	return ch.URL()
   126  }
   127  
   128  func (s *UpgradeCharmSuccessSuite) assertLocalRevision(c *gc.C, revision int, path string) {
   129  	dir, err := charm.ReadDir(path)
   130  	c.Assert(err, gc.IsNil)
   131  	c.Assert(dir.Revision(), gc.Equals, revision)
   132  }
   133  
   134  func (s *UpgradeCharmSuccessSuite) TestLocalRevisionUnchanged(c *gc.C) {
   135  	err := runUpgradeCharm(c, "riak")
   136  	c.Assert(err, gc.IsNil)
   137  	s.assertUpgraded(c, 8, false)
   138  	// Even though the remote revision is bumped, the local one should
   139  	// be unchanged.
   140  	s.assertLocalRevision(c, 7, s.path)
   141  }
   142  
   143  func (s *UpgradeCharmSuccessSuite) TestRespectsLocalRevisionWhenPossible(c *gc.C) {
   144  	dir, err := charm.ReadDir(s.path)
   145  	c.Assert(err, gc.IsNil)
   146  	err = dir.SetDiskRevision(42)
   147  	c.Assert(err, gc.IsNil)
   148  
   149  	err = runUpgradeCharm(c, "riak")
   150  	c.Assert(err, gc.IsNil)
   151  	s.assertUpgraded(c, 42, false)
   152  	s.assertLocalRevision(c, 42, s.path)
   153  }
   154  
   155  func (s *UpgradeCharmSuccessSuite) TestUpgradesWithBundle(c *gc.C) {
   156  	dir, err := charm.ReadDir(s.path)
   157  	c.Assert(err, gc.IsNil)
   158  	dir.SetRevision(42)
   159  	buf := &bytes.Buffer{}
   160  	err = dir.BundleTo(buf)
   161  	c.Assert(err, gc.IsNil)
   162  	bundlePath := path.Join(s.SeriesPath, "riak.charm")
   163  	err = ioutil.WriteFile(bundlePath, buf.Bytes(), 0644)
   164  	c.Assert(err, gc.IsNil)
   165  
   166  	err = runUpgradeCharm(c, "riak")
   167  	c.Assert(err, gc.IsNil)
   168  	s.assertUpgraded(c, 42, false)
   169  	s.assertLocalRevision(c, 7, s.path)
   170  }
   171  
   172  func (s *UpgradeCharmSuccessSuite) TestForcedUpgrade(c *gc.C) {
   173  	err := runUpgradeCharm(c, "riak", "--force")
   174  	c.Assert(err, gc.IsNil)
   175  	s.assertUpgraded(c, 8, true)
   176  	// Local revision is not changed.
   177  	s.assertLocalRevision(c, 7, s.path)
   178  }
   179  
   180  var myriakMeta = []byte(`
   181  name: myriak
   182  summary: "K/V storage engine"
   183  description: "Scalable K/V Store in Erlang with Clocks :-)"
   184  provides:
   185    endpoint:
   186      interface: http
   187    admin:
   188      interface: http
   189  peers:
   190    ring:
   191      interface: riak
   192  `)
   193  
   194  func (s *UpgradeCharmSuccessSuite) TestSwitch(c *gc.C) {
   195  	myriakPath := testing.Charms.RenamedClonedDirPath(s.SeriesPath, "riak", "myriak")
   196  	err := ioutil.WriteFile(path.Join(myriakPath, "metadata.yaml"), myriakMeta, 0644)
   197  	c.Assert(err, gc.IsNil)
   198  
   199  	// Test with local repo and no explicit revsion.
   200  	err = runUpgradeCharm(c, "riak", "--switch=local:myriak")
   201  	c.Assert(err, gc.IsNil)
   202  	curl := s.assertUpgraded(c, 7, false)
   203  	c.Assert(curl.String(), gc.Equals, "local:precise/myriak-7")
   204  	s.assertLocalRevision(c, 7, myriakPath)
   205  
   206  	// Now try the same with explicit revision - should fail.
   207  	err = runUpgradeCharm(c, "riak", "--switch=local:myriak-7")
   208  	c.Assert(err, gc.ErrorMatches, `already running specified charm "local:precise/myriak-7"`)
   209  
   210  	// Change the revision to 42 and upgrade to it with explicit revision.
   211  	err = ioutil.WriteFile(path.Join(myriakPath, "revision"), []byte("42"), 0644)
   212  	c.Assert(err, gc.IsNil)
   213  	err = runUpgradeCharm(c, "riak", "--switch=local:myriak-42")
   214  	c.Assert(err, gc.IsNil)
   215  	curl = s.assertUpgraded(c, 42, false)
   216  	c.Assert(curl.String(), gc.Equals, "local:precise/myriak-42")
   217  	s.assertLocalRevision(c, 42, myriakPath)
   218  }