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