// DeployService takes a charm and various parameters and deploys it. func DeployService(st *state.State, args DeployServiceParams) (*state.Service, error) { if args.NumUnits > 1 && args.ToMachineSpec != "" { return nil, errors.New("cannot use --num-units with --to") } settings, err := args.Charm.Config().ValidateSettings(args.ConfigSettings) if err != nil { return nil, err } if args.Charm.Meta().Subordinate { if args.NumUnits != 0 || args.ToMachineSpec != "" { return nil, fmt.Errorf("subordinate service must be deployed without units") } if !constraints.IsEmpty(&args.Constraints) { return nil, fmt.Errorf("subordinate service must be deployed without constraints") } } if args.ServiceOwner == "" { args.ServiceOwner = "user-admin" } // TODO(fwereade): transactional State.AddService including settings, constraints // (minimumUnitCount, initialMachineIds?). service, err := st.AddService( args.ServiceName, args.ServiceOwner, args.Charm, args.IncludeNetworks, args.ExcludeNetworks, ) if err != nil { return nil, err } if len(settings) > 0 { if err := service.UpdateConfigSettings(settings); err != nil { return nil, err } } if args.Charm.Meta().Subordinate { return service, nil } if !constraints.IsEmpty(&args.Constraints) { if err := service.SetConstraints(args.Constraints); err != nil { return nil, err } } if args.NumUnits > 0 { if _, err := AddUnits(st, service, args.NumUnits, args.ToMachineSpec); err != nil { return nil, err } } return service, nil }
func (s *CommonProvisionerSuite) checkStartInstanceCustom(c *gc.C, m *state.Machine, secret string, cons constraints.Value, includeNetworks, excludeNetworks []string, networkInfo []network.Info, waitInstanceId bool) (inst instance.Instance) { s.BackingState.StartSync() for { select { case o := <-s.op: switch o := o.(type) { case dummy.OpStartInstance: inst = o.Instance if waitInstanceId { s.waitInstanceId(c, m, inst.Id()) } // Check the instance was started with the expected params. c.Assert(o.MachineId, gc.Equals, m.Id()) nonceParts := strings.SplitN(o.MachineNonce, ":", 2) c.Assert(nonceParts, gc.HasLen, 2) c.Assert(nonceParts[0], gc.Equals, names.MachineTag("0")) c.Assert(nonceParts[1], jc.Satisfies, utils.IsValidUUIDString) c.Assert(o.Secret, gc.Equals, secret) c.Assert(o.IncludeNetworks, jc.DeepEquals, includeNetworks) c.Assert(o.ExcludeNetworks, jc.DeepEquals, excludeNetworks) c.Assert(o.NetworkInfo, jc.DeepEquals, networkInfo) // All provisioned machines in this test suite have // their hardware characteristics attributes set to // the same values as the constraints due to the dummy // environment being used. if !constraints.IsEmpty(&cons) { c.Assert(o.Constraints, gc.DeepEquals, cons) hc, err := m.HardwareCharacteristics() c.Assert(err, gc.IsNil) c.Assert(*hc, gc.DeepEquals, instance.HardwareCharacteristics{ Arch: cons.Arch, Mem: cons.Mem, RootDisk: cons.RootDisk, CpuCores: cons.CpuCores, CpuPower: cons.CpuPower, Tags: cons.Tags, }) } return default: c.Logf("ignoring unexpected operation %#v", o) } case <-time.After(2 * time.Second): c.Fatalf("provisioner did not start an instance") return } } return }
func (c *DeployCommand) Run(ctx *cmd.Context) error { client, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer client.Close() attrs, err := client.EnvironmentGet() if err != nil { return err } conf, err := config.New(config.NoDefaults, attrs) if err != nil { return err } curl, err := resolveCharmURL(c.CharmName, client, conf) if err != nil { return err } repo, err := charm.InferRepository(curl.Reference, ctx.AbsPath(c.RepoPath)) if err != nil { return err } repo = config.SpecializeCharmRepo(repo, conf) curl, err = addCharmViaAPI(client, ctx, curl, repo) if err != nil { return err } if c.BumpRevision { ctx.Infof("--upgrade (or -u) is deprecated and ignored; charms are always deployed with a unique revision.") } var includeNetworks []string var excludeNetworks []string haveNetworks := false if c.Networks != "" { includeNetworks = parseNetworks(c.Networks) haveNetworks = true } if c.ExcludeNetworks != "" { excludeNetworks = parseNetworks(c.ExcludeNetworks) haveNetworks = true } if haveNetworks { env, err := environs.New(conf) if err != nil { return err } if !env.SupportNetworks() { return errors.New("cannot use --networks/--exclude-networks: not supported by the environment") } } charmInfo, err := client.CharmInfo(curl.String()) if err != nil { return err } numUnits := c.NumUnits if charmInfo.Meta.Subordinate { if !constraints.IsEmpty(&c.Constraints) { return errors.New("cannot use --constraints with subordinate service") } if numUnits == 1 && c.ToMachineSpec == "" { numUnits = 0 } else { return errors.New("cannot use --num-units or --to with subordinate service") } } serviceName := c.ServiceName if serviceName == "" { serviceName = charmInfo.Meta.Name } var configYAML []byte if c.Config.Path != "" { configYAML, err = c.Config.Read(ctx) if err != nil { return err } } err = client.ServiceDeployWithNetworks( curl.String(), serviceName, numUnits, string(configYAML), c.Constraints, c.ToMachineSpec, includeNetworks, excludeNetworks, ) if params.IsCodeNotImplemented(err) { if haveNetworks { return errors.New("cannot use --networks/--exclude-networks: not supported by the API server") } err = client.ServiceDeploy( curl.String(), serviceName, numUnits, string(configYAML), c.Constraints, c.ToMachineSpec) } return err }