Example #1
0
func (s *DeployLocalSuite) TestDeploy(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	serviceCons := constraints.MustParse("cores=2")
	placement := []*instance.Placement{
		{Scope: s.State.ModelUUID(), Directive: "valid"},
		{Scope: "#", Directive: "0"},
		{Scope: "lxd", Directive: "1"},
		{Scope: "lxd", Directive: ""},
	}
	_, err := juju.DeployApplication(f,
		juju.DeployApplicationParams{
			ApplicationName: "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 #2
0
func (s *DeployLocalSuite) TestDeployWithImplicitBindings(c *gc.C) {
	wordpressCharm := s.addWordpressCharmWithExtraBindings(c)

	service, err := juju.DeployApplication(s.State,
		juju.DeployApplicationParams{
			ApplicationName:  "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 #3
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.DeployApplication(s.State,
		juju.DeployApplicationParams{
			ApplicationName: "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 application-default.
	})
}
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.DeployApplication(s.State,
		juju.DeployApplicationParams{
			ApplicationName: "bob",
			Charm:           wordpressCharm,
			EndpointBindings: map[string]string{
				"":   "public",
				"db": "db",
			},
		})
	c.Assert(err, jc.ErrorIsNil)

	s.assertBindings(c, service, map[string]string{
		// relation names
		"url":             "public",
		"logging-dir":     "public",
		"monitoring-port": "public",
		"db":              "db",
		"cache":           "public",
		// extra-bindings names
		"db-client": "public",
		"admin-api": "public",
		"foo-bar":   "public",
	})
}
Example #5
0
func (s *DeployLocalSuite) TestDeployMinimal(c *gc.C) {
	service, err := juju.DeployApplication(s.State,
		juju.DeployApplicationParams{
			ApplicationName: "bob",
			Charm:           s.charm,
		})
	c.Assert(err, jc.ErrorIsNil)
	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{})
}
Example #6
0
func (s *DeployLocalSuite) TestDeployConstraints(c *gc.C) {
	err := s.State.SetModelConstraints(constraints.MustParse("mem=2G"))
	c.Assert(err, jc.ErrorIsNil)
	serviceCons := constraints.MustParse("cores=2")
	service, err := juju.DeployApplication(s.State,
		juju.DeployApplicationParams{
			ApplicationName: "bob",
			Charm:           s.charm,
			Constraints:     serviceCons,
		})
	c.Assert(err, jc.ErrorIsNil)
	s.assertConstraints(c, service, serviceCons)
}
Example #7
0
func (s *DeployLocalSuite) TestDeploySettingsError(c *gc.C) {
	_, err := juju.DeployApplication(s.State,
		juju.DeployApplicationParams{
			ApplicationName: "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.Application("bob")
	c.Assert(err, jc.Satisfies, errors.IsNotFound)
}
Example #8
0
func (s *DeployLocalSuite) TestDeploySeries(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	_, err := juju.DeployApplication(f,
		juju.DeployApplicationParams{
			ApplicationName: "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 #9
0
func (s *DeployLocalSuite) TestDeploySettings(c *gc.C) {
	service, err := juju.DeployApplication(s.State,
		juju.DeployApplicationParams{
			ApplicationName: "bob",
			Charm:           s.charm,
			ConfigSettings: charm.Settings{
				"title":       "banana cupcakes",
				"skill-level": 9901,
			},
		})
	c.Assert(err, jc.ErrorIsNil)
	s.assertSettings(c, service, charm.Settings{
		"title":       "banana cupcakes",
		"skill-level": int64(9901),
	})
}
Example #10
0
func (s *DeployLocalSuite) TestDeployNumUnits(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	serviceCons := constraints.MustParse("cores=2")
	_, err := juju.DeployApplication(f,
		juju.DeployApplicationParams{
			ApplicationName: "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 #11
0
func (s *DeployLocalSuite) TestDeployResources(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	_, err := juju.DeployApplication(f,
		juju.DeployApplicationParams{
			ApplicationName: "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 #12
0
func (s *DeployLocalSuite) TestDeployForceMachineIdWithContainer(c *gc.C) {
	f := &fakeDeployer{State: s.State}

	serviceCons := constraints.MustParse("cores=2")
	_, err := juju.DeployApplication(f,
		juju.DeployApplicationParams{
			ApplicationName: "bob",
			Charm:           s.charm,
			Constraints:     serviceCons,
			NumUnits:        1,
			Placement:       []*instance.Placement{instance.MustParsePlacement(fmt.Sprintf("%s:0", instance.LXD))},
		})
	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.LXD), Directive: "0"})
}
Example #13
0
// deployApplication 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 application facade.
func deployApplication(
	backend Backend,
	stateCharm func(Charm) *state.Charm,
	args params.ApplicationDeploy,
) 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 = backend.Machine(p.Directive)
		if err != nil {
			return errors.Annotatef(err, `cannot deploy "%v" to machine %v`, args.ApplicationName, p.Directive)
		}
	}

	// Try to find the charm URL in state first.
	ch, err := backend.Charm(curl)
	if err != nil {
		return errors.Trace(err)
	}

	if err := checkMinVersion(ch); err != nil {
		return errors.Trace(err)
	}

	var settings charm.Settings
	if len(args.ConfigYAML) > 0 {
		settings, err = ch.Config().ParseSettingsYAML([]byte(args.ConfigYAML), args.ApplicationName)
	} else if len(args.Config) > 0 {
		// Parse config in a compatible way (see function comment).
		settings, err = parseSettingsCompatible(ch.Config(), args.Config)
	}
	if err != nil {
		return errors.Trace(err)
	}

	channel := csparams.Channel(args.Channel)

	_, err = jjj.DeployApplication(backend,
		jjj.DeployApplicationParams{
			ApplicationName:  args.ApplicationName,
			Series:           args.Series,
			Charm:            stateCharm(ch),
			Channel:          channel,
			NumUnits:         args.NumUnits,
			ConfigSettings:   settings,
			Constraints:      args.Constraints,
			Placement:        args.Placement,
			Storage:          args.Storage,
			EndpointBindings: args.EndpointBindings,
			Resources:        args.Resources,
		})
	return errors.Trace(err)
}