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 }