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 }