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) }
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": "", }) }
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. }) }
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", }) }
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{}) }
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) }
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) }
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") }
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), }) }
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) }
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"}) }
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"}) }
// 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) }