launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/cmd/juju/deploy_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package main 5 6 import ( 7 "strings" 8 9 gc "launchpad.net/gocheck" 10 11 "launchpad.net/juju-core/charm" 12 "launchpad.net/juju-core/constraints" 13 "launchpad.net/juju-core/errors" 14 "launchpad.net/juju-core/instance" 15 "launchpad.net/juju-core/juju/testing" 16 "launchpad.net/juju-core/state" 17 coretesting "launchpad.net/juju-core/testing" 18 jc "launchpad.net/juju-core/testing/checkers" 19 ) 20 21 type DeploySuite struct { 22 testing.RepoSuite 23 } 24 25 var _ = gc.Suite(&DeploySuite{}) 26 27 func runDeploy(c *gc.C, args ...string) error { 28 _, err := coretesting.RunCommand(c, &DeployCommand{}, args) 29 return err 30 } 31 32 var initErrorTests = []struct { 33 args []string 34 err string 35 }{ 36 { 37 args: nil, 38 err: `no charm specified`, 39 }, { 40 args: []string{"craz~ness"}, 41 err: `invalid charm name "craz~ness"`, 42 }, { 43 args: []string{"craziness", "burble-1"}, 44 err: `invalid service name "burble-1"`, 45 }, { 46 args: []string{"craziness", "burble1", "-n", "0"}, 47 err: `--num-units must be a positive integer`, 48 }, { 49 args: []string{"craziness", "burble1", "--to", "bigglesplop"}, 50 err: `invalid --to parameter "bigglesplop"`, 51 }, { 52 args: []string{"craziness", "burble1", "-n", "2", "--to", "123"}, 53 err: `cannot use --num-units > 1 with --to`, 54 }, { 55 args: []string{"craziness", "burble1", "--constraints", "gibber=plop"}, 56 err: `invalid value "gibber=plop" for flag --constraints: unknown constraint "gibber"`, 57 }, 58 } 59 60 func (s *DeploySuite) TestInitErrors(c *gc.C) { 61 for i, t := range initErrorTests { 62 c.Logf("test %d", i) 63 err := coretesting.InitCommand(&DeployCommand{}, t.args) 64 c.Assert(err, gc.ErrorMatches, t.err) 65 } 66 } 67 68 func (s *DeploySuite) TestNoCharm(c *gc.C) { 69 err := runDeploy(c, "local:unknown-123") 70 c.Assert(err, gc.ErrorMatches, `charm not found in ".*": local:precise/unknown-123`) 71 } 72 73 func (s *DeploySuite) TestCharmDir(c *gc.C) { 74 coretesting.Charms.ClonedDirPath(s.SeriesPath, "dummy") 75 err := runDeploy(c, "local:dummy") 76 c.Assert(err, gc.IsNil) 77 curl := charm.MustParseURL("local:precise/dummy-1") 78 s.AssertService(c, "dummy", curl, 1, 0) 79 } 80 81 func (s *DeploySuite) TestUpgradeReportsDeprecated(c *gc.C) { 82 coretesting.Charms.ClonedDirPath(s.SeriesPath, "dummy") 83 ctx, err := coretesting.RunCommand(c, &DeployCommand{}, []string{"local:dummy", "-u"}) 84 c.Assert(err, gc.IsNil) 85 86 c.Assert(coretesting.Stderr(ctx), gc.Equals, "") 87 output := strings.Split(coretesting.Stdout(ctx), "\n") 88 c.Check(output[0], gc.Matches, `Added charm ".*" to the environment.`) 89 c.Check(output[1], gc.Equals, "--upgrade (or -u) is deprecated and ignored; charms are always deployed with a unique revision.") 90 } 91 92 func (s *DeploySuite) TestUpgradeCharmDir(c *gc.C) { 93 // Add the charm, so the url will exist and a new revision will be 94 // picked in ServiceDeploy. 95 dummyCharm := s.AddTestingCharm(c, "dummy") 96 97 dirPath := coretesting.Charms.ClonedDirPath(s.SeriesPath, "dummy") 98 err := runDeploy(c, "local:quantal/dummy") 99 c.Assert(err, gc.IsNil) 100 upgradedRev := dummyCharm.Revision() + 1 101 curl := dummyCharm.URL().WithRevision(upgradedRev) 102 s.AssertService(c, "dummy", curl, 1, 0) 103 // Check the charm dir was left untouched. 104 ch, err := charm.ReadDir(dirPath) 105 c.Assert(err, gc.IsNil) 106 c.Assert(ch.Revision(), gc.Equals, 1) 107 } 108 109 func (s *DeploySuite) TestCharmBundle(c *gc.C) { 110 coretesting.Charms.BundlePath(s.SeriesPath, "dummy") 111 err := runDeploy(c, "local:dummy", "some-service-name") 112 c.Assert(err, gc.IsNil) 113 curl := charm.MustParseURL("local:precise/dummy-1") 114 s.AssertService(c, "some-service-name", curl, 1, 0) 115 } 116 117 func (s *DeploySuite) TestSubordinateCharm(c *gc.C) { 118 coretesting.Charms.BundlePath(s.SeriesPath, "logging") 119 err := runDeploy(c, "local:logging") 120 c.Assert(err, gc.IsNil) 121 curl := charm.MustParseURL("local:precise/logging-1") 122 s.AssertService(c, "logging", curl, 0, 0) 123 } 124 125 func (s *DeploySuite) TestConfig(c *gc.C) { 126 coretesting.Charms.BundlePath(s.SeriesPath, "dummy") 127 path := setupConfigFile(c, c.MkDir()) 128 err := runDeploy(c, "local:dummy", "dummy-service", "--config", path) 129 c.Assert(err, gc.IsNil) 130 service, err := s.State.Service("dummy-service") 131 c.Assert(err, gc.IsNil) 132 settings, err := service.ConfigSettings() 133 c.Assert(err, gc.IsNil) 134 c.Assert(settings, gc.DeepEquals, charm.Settings{ 135 "skill-level": int64(9000), 136 "username": "admin001", 137 }) 138 } 139 140 func (s *DeploySuite) TestConfigError(c *gc.C) { 141 coretesting.Charms.BundlePath(s.SeriesPath, "dummy") 142 path := setupConfigFile(c, c.MkDir()) 143 err := runDeploy(c, "local:dummy", "other-service", "--config", path) 144 c.Assert(err, gc.ErrorMatches, `no settings found for "other-service"`) 145 _, err = s.State.Service("other-service") 146 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 147 } 148 149 func (s *DeploySuite) TestConstraints(c *gc.C) { 150 coretesting.Charms.BundlePath(s.SeriesPath, "dummy") 151 err := runDeploy(c, "local:dummy", "--constraints", "mem=2G cpu-cores=2") 152 c.Assert(err, gc.IsNil) 153 curl := charm.MustParseURL("local:precise/dummy-1") 154 service, _ := s.AssertService(c, "dummy", curl, 1, 0) 155 cons, err := service.Constraints() 156 c.Assert(err, gc.IsNil) 157 c.Assert(cons, gc.DeepEquals, constraints.MustParse("mem=2G cpu-cores=2")) 158 } 159 160 func (s *DeploySuite) TestSubordinateConstraints(c *gc.C) { 161 coretesting.Charms.BundlePath(s.SeriesPath, "logging") 162 err := runDeploy(c, "local:logging", "--constraints", "mem=1G") 163 c.Assert(err, gc.ErrorMatches, "cannot use --constraints with subordinate service") 164 } 165 166 func (s *DeploySuite) TestNumUnits(c *gc.C) { 167 coretesting.Charms.BundlePath(s.SeriesPath, "dummy") 168 err := runDeploy(c, "local:dummy", "-n", "13") 169 c.Assert(err, gc.IsNil) 170 curl := charm.MustParseURL("local:precise/dummy-1") 171 s.AssertService(c, "dummy", curl, 13, 0) 172 } 173 174 func (s *DeploySuite) TestNumUnitsSubordinate(c *gc.C) { 175 coretesting.Charms.BundlePath(s.SeriesPath, "logging") 176 err := runDeploy(c, "--num-units", "3", "local:logging") 177 c.Assert(err, gc.ErrorMatches, "cannot use --num-units or --to with subordinate service") 178 _, err = s.State.Service("dummy") 179 c.Assert(err, gc.ErrorMatches, `service "dummy" not found`) 180 } 181 182 func (s *DeploySuite) assertForceMachine(c *gc.C, machineId string) { 183 svc, err := s.State.Service("portlandia") 184 c.Assert(err, gc.IsNil) 185 units, err := svc.AllUnits() 186 c.Assert(err, gc.IsNil) 187 c.Assert(units, gc.HasLen, 1) 188 mid, err := units[0].AssignedMachineId() 189 c.Assert(err, gc.IsNil) 190 c.Assert(mid, gc.Equals, machineId) 191 } 192 193 func (s *DeploySuite) TestForceMachine(c *gc.C) { 194 coretesting.Charms.BundlePath(s.SeriesPath, "dummy") 195 machine, err := s.State.AddMachine("precise", state.JobHostUnits) 196 c.Assert(err, gc.IsNil) 197 err = runDeploy(c, "--to", machine.Id(), "local:dummy", "portlandia") 198 c.Assert(err, gc.IsNil) 199 s.assertForceMachine(c, machine.Id()) 200 } 201 202 func (s *DeploySuite) TestForceMachineExistingContainer(c *gc.C) { 203 coretesting.Charms.BundlePath(s.SeriesPath, "dummy") 204 template := state.MachineTemplate{ 205 Series: "precise", 206 Jobs: []state.MachineJob{state.JobHostUnits}, 207 } 208 container, err := s.State.AddMachineInsideNewMachine(template, template, instance.LXC) 209 c.Assert(err, gc.IsNil) 210 err = runDeploy(c, "--to", container.Id(), "local:dummy", "portlandia") 211 c.Assert(err, gc.IsNil) 212 s.assertForceMachine(c, container.Id()) 213 machines, err := s.State.AllMachines() 214 c.Assert(err, gc.IsNil) 215 c.Assert(machines, gc.HasLen, 2) 216 } 217 218 func (s *DeploySuite) TestForceMachineNewContainer(c *gc.C) { 219 coretesting.Charms.BundlePath(s.SeriesPath, "dummy") 220 machine, err := s.State.AddMachine("precise", state.JobHostUnits) 221 c.Assert(err, gc.IsNil) 222 err = runDeploy(c, "--to", "lxc:"+machine.Id(), "local:dummy", "portlandia") 223 c.Assert(err, gc.IsNil) 224 s.assertForceMachine(c, machine.Id()+"/lxc/0") 225 machines, err := s.State.AllMachines() 226 c.Assert(err, gc.IsNil) 227 c.Assert(machines, gc.HasLen, 2) 228 } 229 230 func (s *DeploySuite) TestForceMachineNotFound(c *gc.C) { 231 coretesting.Charms.BundlePath(s.SeriesPath, "dummy") 232 err := runDeploy(c, "--to", "42", "local:dummy", "portlandia") 233 c.Assert(err, gc.ErrorMatches, `cannot assign unit "portlandia/0" to machine: machine 42 not found`) 234 _, err = s.State.Service("dummy") 235 c.Assert(err, gc.ErrorMatches, `service "dummy" not found`) 236 } 237 238 func (s *DeploySuite) TestForceMachineSubordinate(c *gc.C) { 239 machine, err := s.State.AddMachine("precise", state.JobHostUnits) 240 c.Assert(err, gc.IsNil) 241 coretesting.Charms.BundlePath(s.SeriesPath, "logging") 242 err = runDeploy(c, "--to", machine.Id(), "local:logging") 243 c.Assert(err, gc.ErrorMatches, "cannot use --num-units or --to with subordinate service") 244 _, err = s.State.Service("dummy") 245 c.Assert(err, gc.ErrorMatches, `service "dummy" not found`) 246 }