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  }