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