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 }