Example #1
0
func (s *DeployLocalSuite) TestDeployWithFewerPlacement(c *gc.C) {
	err := s.State.SetEnvironConstraints(constraints.MustParse("mem=2G"))
	c.Assert(err, jc.ErrorIsNil)
	serviceCons := constraints.MustParse("cpu-cores=2")
	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			Constraints: serviceCons,
			NumUnits:    3,
			Placement: []*instance.Placement{
				{Scope: s.State.EnvironUUID(), Directive: "valid"},
			},
		})
	c.Assert(err, jc.ErrorIsNil)
	s.assertConstraints(c, service, serviceCons)
	units, err := service.AllUnits()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(units, gc.HasLen, 3)

	// Check each of the newly added units.
	s.assertAssignedUnit(c, units[0], "0", constraints.MustParse("mem=2G cpu-cores=2"))
	s.assertAssignedUnit(c, units[1], "1", constraints.MustParse("mem=2G cpu-cores=2"))
	s.assertAssignedUnit(c, units[2], "2", constraints.MustParse("mem=2G cpu-cores=2"))
}
Example #2
0
func (s *DeployLocalSuite) TestDeployWithBoundRelationNamesAndExtraBindingsNames(c *gc.C) {
	wordpressCharm := s.addWordpressCharmWithExtraBindings(c)
	_, err := s.State.AddSpace("db", "", nil, false)
	c.Assert(err, jc.ErrorIsNil)
	_, err = s.State.AddSpace("public", "", nil, false)
	c.Assert(err, jc.ErrorIsNil)
	_, err = s.State.AddSpace("internal", "", nil, false)
	c.Assert(err, jc.ErrorIsNil)

	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       wordpressCharm,
			EndpointBindings: map[string]string{
				"":          "public",
				"db":        "db",
				"db-client": "db",
				"admin-api": "internal",
			},
		})
	c.Assert(err, jc.ErrorIsNil)

	s.assertBindings(c, service, map[string]string{
		"url":             "public",
		"logging-dir":     "public",
		"monitoring-port": "public",
		"db":              "db",
		"cache":           "public",
		"db-client":       "db",
		"admin-api":       "internal",
		"cluster":         "public",
		"foo-bar":         "public", // like for relations, uses the service-default.
	})
}
Example #3
0
func (s *DeployLocalSuite) TestDeployWithImplicitBindings(c *gc.C) {
	wordpressCharm := s.addWordpressCharmWithExtraBindings(c)

	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName:      "bob",
			Charm:            wordpressCharm,
			EndpointBindings: nil,
		})
	c.Assert(err, jc.ErrorIsNil)

	s.assertBindings(c, service, map[string]string{
		// relation names
		"url":             "",
		"logging-dir":     "",
		"monitoring-port": "",
		"db":              "",
		"cache":           "",
		"cluster":         "",
		// extra-bindings names
		"db-client": "",
		"admin-api": "",
		"foo-bar":   "",
	})
}
Example #4
0
func (s *DeployLocalSuite) TestDeployWithSomeSpecifiedBindings(c *gc.C) {
	wordpressCharm := s.addWordpressCharm(c)
	_, err := s.State.AddSpace("db", "", nil, false)
	c.Assert(err, jc.ErrorIsNil)
	_, err = s.State.AddSpace("public", "", nil, false)
	c.Assert(err, jc.ErrorIsNil)

	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       wordpressCharm,
			EndpointBindings: map[string]string{
				"":   "public",
				"db": "db",
			},
		})
	c.Assert(err, jc.ErrorIsNil)

	s.assertBindings(c, service, map[string]string{
		"url":             "public",
		"logging-dir":     "public",
		"monitoring-port": "public",
		"db":              "db",
		"cache":           "public",
	})
}
Example #5
0
func (s *DeployLocalSuite) TestDeploy(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	serviceCons := constraints.MustParse("cpu-cores=2")
	placement := []*instance.Placement{
		{Scope: s.State.ModelUUID(), Directive: "valid"},
		{Scope: "#", Directive: "0"},
		{Scope: "lxc", Directive: "1"},
		{Scope: "lxc", Directive: ""},
	}
	_, err := juju.DeployService(f,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			Constraints: serviceCons,
			NumUnits:    4,
			Placement:   placement,
		})
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(f.args.Name, gc.Equals, "bob")
	c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
	c.Assert(f.args.Constraints, gc.DeepEquals, serviceCons)
	c.Assert(f.args.NumUnits, gc.Equals, 4)
	c.Assert(f.args.Placement, gc.DeepEquals, placement)
}
Example #6
0
func (s *DeployLocalSuite) TestDeployForceMachineIdWithContainer(c *gc.C) {
	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
	c.Assert(err, gc.IsNil)
	c.Assert(machine.Id(), gc.Equals, "0")
	envCons := constraints.MustParse("mem=2G")
	err = s.State.SetEnvironConstraints(envCons)
	c.Assert(err, gc.IsNil)
	serviceCons := constraints.MustParse("cpu-cores=2")
	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName:   "bob",
			Charm:         s.charm,
			Constraints:   serviceCons,
			NumUnits:      1,
			ToMachineSpec: fmt.Sprintf("%s:0", instance.LXC),
		})
	c.Assert(err, gc.IsNil)
	s.assertConstraints(c, service, serviceCons)
	units, err := service.AllUnits()
	c.Assert(err, gc.IsNil)
	c.Assert(units, gc.HasLen, 1)

	// The newly created container will use the constraints.
	id, err := units[0].AssignedMachineId()
	c.Assert(err, gc.IsNil)
	machine, err = s.State.Machine(id)
	c.Assert(err, gc.IsNil)
	machineCons, err := machine.Constraints()
	c.Assert(err, gc.IsNil)
	unitCons, err := units[0].Constraints()
	c.Assert(err, gc.IsNil)
	c.Assert(machineCons, gc.DeepEquals, *unitCons)
}
Example #7
0
func (s *DeployLocalSuite) TestDeployWithPlacement(c *gc.C) {
	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(machine.Id(), gc.Equals, "0")
	err = s.State.SetEnvironConstraints(constraints.MustParse("mem=2G"))
	c.Assert(err, jc.ErrorIsNil)
	serviceCons := constraints.MustParse("cpu-cores=2")
	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			Constraints: serviceCons,
			NumUnits:    3,
			Placement: []*instance.Placement{
				{Scope: s.State.EnvironUUID(), Directive: "valid"},
				{Scope: "#", Directive: "0"},
				{Scope: "lxc", Directive: "1"},
			},
			ToMachineSpec: "will be ignored",
		})
	c.Assert(err, jc.ErrorIsNil)
	s.assertConstraints(c, service, serviceCons)
	units, err := service.AllUnits()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(units, gc.HasLen, 3)

	// Check each of the newly added units.
	s.assertAssignedUnit(c, units[0], "1", constraints.MustParse("mem=2G cpu-cores=2"))
	s.assertAssignedUnit(c, units[1], "0", constraints.Value{})
	s.assertAssignedUnit(c, units[2], "1/lxc/0", constraints.MustParse("mem=2G cpu-cores=2"))
}
Example #8
0
// ServiceDeploy fetches the charm from the charm store and deploys it.
// AddCharm or AddLocalCharm should be called to add the charm
// before calling ServiceDeploy, although for backward compatibility
// this is not necessary until 1.16 support is removed.
func (c *Client) ServiceDeploy(args params.ServiceDeploy) error {
	curl, err := charm.ParseURL(args.CharmUrl)
	if err != nil {
		return err
	}
	if curl.Revision < 0 {
		return fmt.Errorf("charm url must include revision")
	}

	// Try to find the charm URL in state first.
	ch, err := c.api.state.Charm(curl)
	if errors.IsNotFound(err) {
		// Remove this whole if block when 1.16 compatibility is dropped.
		if curl.Schema != "cs" {
			return fmt.Errorf(`charm url has unsupported schema %q`, curl.Schema)
		}
		err = c.AddCharm(params.CharmURL{args.CharmUrl})
		if err != nil {
			return err
		}
		ch, err = c.api.state.Charm(curl)
		if err != nil {
			return err
		}
	} else if err != nil {
		return err
	}

	var settings charm.Settings
	if len(args.ConfigYAML) > 0 {
		settings, err = ch.Config().ParseSettingsYAML([]byte(args.ConfigYAML), args.ServiceName)
	} else if len(args.Config) > 0 {
		// Parse config in a compatile way (see function comment).
		settings, err = parseSettingsCompatible(ch, args.Config)
	}
	if err != nil {
		return err
	}
	// Convert network tags to names for any given networks.
	requestedNetworks, err := networkTagsToNames(args.Networks)
	if err != nil {
		return err
	}

	_, err = juju.DeployService(c.api.state,
		juju.DeployServiceParams{
			ServiceName: args.ServiceName,
			// TODO(dfc) ServiceOwner should be a tag
			ServiceOwner:   c.api.auth.GetAuthTag().String(),
			Charm:          ch,
			NumUnits:       args.NumUnits,
			ConfigSettings: settings,
			Constraints:    args.Constraints,
			ToMachineSpec:  args.ToMachineSpec,
			Networks:       requestedNetworks,
		})
	return err
}
Example #9
0
func (s *DeployLocalSuite) TestDeployOwnerTag(c *gc.C) {
	s.Factory.MakeUser(factory.UserParams{Username: "******"})
	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName:  "bobwithowner",
			Charm:        s.charm,
			ServiceOwner: "user-foobar",
		})
	c.Assert(err, gc.IsNil)
	c.Assert(service.GetOwnerTag(), gc.Equals, "user-foobar")
}
Example #10
0
func (s *DeployLocalSuite) TestDeployMinimal(c *gc.C) {
	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
		})
	c.Assert(err, gc.IsNil)
	s.assertCharm(c, service, s.charm.URL())
	s.assertSettings(c, service, charm.Settings{})
	s.assertConstraints(c, service, constraints.Value{})
	s.assertMachines(c, service, constraints.Value{})
	c.Assert(service.GetOwnerTag(), gc.Equals, "user-admin")
}
Example #11
0
func (s *DeployLocalSuite) TestDeployWithForceMachineRejectsTooManyUnits(c *gc.C) {
	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
	c.Assert(err, gc.IsNil)
	c.Assert(machine.Id(), gc.Equals, "0")
	_, err = juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName:   "bob",
			Charm:         s.charm,
			NumUnits:      2,
			ToMachineSpec: "0",
		})
	c.Assert(err, gc.ErrorMatches, "cannot use --num-units with --to")
}
Example #12
0
func (s *DeployLocalSuite) TestDeployConstraints(c *gc.C) {
	err := s.State.SetEnvironConstraints(constraints.MustParse("mem=2G"))
	c.Assert(err, gc.IsNil)
	serviceCons := constraints.MustParse("cpu-cores=2")
	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			Constraints: serviceCons,
		})
	c.Assert(err, gc.IsNil)
	s.assertConstraints(c, service, serviceCons)
}
Example #13
0
func (s *DeployLocalSuite) TestDeploySettingsError(c *gc.C) {
	_, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			ConfigSettings: charm.Settings{
				"skill-level": 99.01,
			},
		})
	c.Assert(err, gc.ErrorMatches, `option "skill-level" expected int, got 99.01`)
	_, err = s.State.Service("bob")
	c.Assert(err, jc.Satisfies, errors.IsNotFound)
}
Example #14
0
func (s *DeployLocalSuite) TestDeployNumUnits(c *gc.C) {
	err := s.State.SetEnvironConstraints(constraints.MustParse("mem=2G"))
	c.Assert(err, jc.ErrorIsNil)
	serviceCons := constraints.MustParse("cpu-cores=2")
	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			Constraints: serviceCons,
			NumUnits:    2,
		})
	c.Assert(err, jc.ErrorIsNil)
	s.assertConstraints(c, service, serviceCons)
	s.assertMachines(c, service, constraints.MustParse("mem=2G cpu-cores=2"), "0", "1")
}
Example #15
0
func (s *DeployLocalSuite) TestDeploySeries(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	_, err := juju.DeployService(f,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			Series:      "aseries",
		})
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(f.args.Name, gc.Equals, "bob")
	c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
	c.Assert(f.args.Series, gc.Equals, "aseries")
}
Example #16
0
func (s *DeployLocalSuite) TestDeploySettings(c *gc.C) {
	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			ConfigSettings: charm.Settings{
				"title":       "banana cupcakes",
				"skill-level": 9901,
			},
		})
	c.Assert(err, gc.IsNil)
	s.assertSettings(c, service, charm.Settings{
		"title":       "banana cupcakes",
		"skill-level": int64(9901),
	})
}
Example #17
0
func (s *DeployLocalSuite) TestDeployNumUnits(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	serviceCons := constraints.MustParse("cpu-cores=2")
	_, err := juju.DeployService(f,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			Constraints: serviceCons,
			NumUnits:    2,
		})
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(f.args.Name, gc.Equals, "bob")
	c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
	c.Assert(f.args.Constraints, gc.DeepEquals, serviceCons)
	c.Assert(f.args.NumUnits, gc.Equals, 2)
}
Example #18
0
func (s *DeployLocalSuite) TestDeployResources(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	_, err := juju.DeployService(f,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			EndpointBindings: map[string]string{
				"":   "public",
				"db": "db",
			},
			Resources: map[string]string{"foo": "bar"},
		})
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(f.args.Name, gc.Equals, "bob")
	c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
	c.Assert(f.args.Resources, gc.DeepEquals, map[string]string{"foo": "bar"})
}
Example #19
0
func (s *DeployLocalSuite) TestDeployForceMachineId(c *gc.C) {
	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
	c.Assert(err, gc.IsNil)
	c.Assert(machine.Id(), gc.Equals, "0")
	err = s.State.SetEnvironConstraints(constraints.MustParse("mem=2G"))
	c.Assert(err, gc.IsNil)
	serviceCons := constraints.MustParse("cpu-cores=2")
	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName:   "bob",
			Charm:         s.charm,
			Constraints:   serviceCons,
			NumUnits:      1,
			ToMachineSpec: "0",
		})
	c.Assert(err, gc.IsNil)
	s.assertConstraints(c, service, serviceCons)
	s.assertMachines(c, service, constraints.Value{}, "0")
}
Example #20
0
func (s *DeployLocalSuite) TestDeployWithImplicitBindings(c *gc.C) {
	wordpressCharm := s.addWordpressCharm(c)

	service, err := juju.DeployService(s.State,
		juju.DeployServiceParams{
			ServiceName:      "bob",
			Charm:            wordpressCharm,
			EndpointBindings: nil,
		})
	c.Assert(err, jc.ErrorIsNil)

	s.assertBindings(c, service, map[string]string{
		"url":             "",
		"logging-dir":     "",
		"monitoring-port": "",
		"db":              "",
		"cache":           "",
	})
}
Example #21
0
func (s *DeployLocalSuite) TestDeployForceMachineIdWithContainer(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	serviceCons := constraints.MustParse("cpu-cores=2")
	_, err := juju.DeployService(f,
		juju.DeployServiceParams{
			ServiceName: "bob",
			Charm:       s.charm,
			Constraints: serviceCons,
			NumUnits:    1,
			Placement:   []*instance.Placement{instance.MustParsePlacement(fmt.Sprintf("%s:0", instance.LXC))},
		})
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(f.args.Name, gc.Equals, "bob")
	c.Assert(f.args.Charm, gc.DeepEquals, s.charm)
	c.Assert(f.args.Constraints, gc.DeepEquals, serviceCons)
	c.Assert(f.args.NumUnits, gc.Equals, 1)
	c.Assert(f.args.Placement, gc.HasLen, 1)
	c.Assert(*f.args.Placement[0], gc.Equals, instance.Placement{Scope: string(instance.LXC), Directive: "0"})
}
Example #22
0
// DeployService fetches the charm from the charm store and deploys it.
// The logic has been factored out into a common function which is called by
// both the legacy API on the client facade, as well as the new service facade.
func deployService(st *state.State, owner string, args params.ServiceDeploy) error {
	curl, err := charm.ParseURL(args.CharmUrl)
	if err != nil {
		return errors.Trace(err)
	}
	if curl.Revision < 0 {
		return errors.Errorf("charm url must include revision")
	}

	// Do a quick but not complete validation check before going any further.
	for _, p := range args.Placement {
		if p.Scope != instance.MachineScope {
			continue
		}
		_, err = st.Machine(p.Directive)
		if err != nil {
			return errors.Annotatef(err, `cannot deploy "%v" to machine %v`, args.ServiceName, p.Directive)
		}
	}

	// Try to find the charm URL in state first.
	ch, err := st.Charm(curl)
	if errors.IsNotFound(err) {
		// Clients written to expect 1.16 compatibility require this next block.
		if curl.Schema != "cs" {
			return errors.Errorf(`charm url has unsupported schema %q`, curl.Schema)
		}
		if err = AddCharmWithAuthorization(st, params.AddCharmWithAuthorization{
			URL: args.CharmUrl,
		}); err == nil {
			ch, err = st.Charm(curl)
		}
	}
	if err != nil {
		return errors.Trace(err)
	}

	var settings charm.Settings
	if len(args.ConfigYAML) > 0 {
		settings, err = ch.Config().ParseSettingsYAML([]byte(args.ConfigYAML), args.ServiceName)
	} else if len(args.Config) > 0 {
		// Parse config in a compatible way (see function comment).
		settings, err = parseSettingsCompatible(ch, args.Config)
	}
	if err != nil {
		return errors.Trace(err)
	}
	// Convert network tags to names for any given networks.
	requestedNetworks, err := networkTagsToNames(args.Networks)
	if err != nil {
		return errors.Trace(err)
	}

	_, err = jjj.DeployService(st,
		jjj.DeployServiceParams{
			ServiceName: args.ServiceName,
			Series:      args.Series,
			// TODO(dfc) ServiceOwner should be a tag
			ServiceOwner:   owner,
			Charm:          ch,
			NumUnits:       args.NumUnits,
			ConfigSettings: settings,
			Constraints:    args.Constraints,
			Placement:      args.Placement,
			Networks:       requestedNetworks,
			Storage:        args.Storage,
		})
	return errors.Trace(err)
}