コード例 #1
0
ファイル: deploy.go プロジェクト: OSBI/juju
func (c *DeployCommand) handleResources(serviceName string, metaResources map[string]charmresource.Meta) (map[string]string, error) {
	if len(c.Resources) == 0 && len(metaResources) == 0 {
		return nil, nil
	}

	api, err := c.NewAPIRoot()
	if err != nil {
		return nil, errors.Trace(err)
	}

	ids, err := resourceadapters.DeployResources(serviceName, c.Resources, metaResources, api)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return ids, nil
}
コード例 #2
0
ファイル: deploy.go プロジェクト: makyo/juju
func handleResources(c APICmd, resources map[string]string, serviceName string, chID charmstore.CharmID, csMac *macaroon.Macaroon, metaResources map[string]charmresource.Meta) (map[string]string, error) {
	if len(resources) == 0 && len(metaResources) == 0 {
		return nil, nil
	}

	api, err := c.NewAPIRoot()
	if err != nil {
		return nil, errors.Trace(err)
	}

	ids, err := resourceadapters.DeployResources(serviceName, chID, csMac, resources, metaResources, api)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return ids, nil
}
コード例 #3
0
ファイル: bundle.go プロジェクト: bac/juju
// upgradeCharm upgrades the charm for the given application to the given charm id.
// If the application is already deployed using the given charm id, do nothing.
// This function returns an error if the existing charm and the target one are
// incompatible, meaning an upgrade from one to the other is not allowed.
func (h *bundleHandler) upgradeCharm(
	api DeployAPI,
	applicationName string,
	chID charmstore.CharmID,
	csMac *macaroon.Macaroon,
	resources map[string]string,
) error {
	id := chID.URL.String()
	existing, err := h.api.GetCharmURL(applicationName)
	if err != nil {
		return errors.Annotatef(err, "cannot retrieve info for application %q", applicationName)
	}
	if existing.String() == id {
		h.log.Infof("reusing application %s (charm: %s)", applicationName, id)
		return nil
	}
	url, err := charm.ParseURL(id)
	if err != nil {
		return errors.Annotatef(err, "cannot parse charm URL %q", id)
	}
	chID.URL = url
	if url.WithRevision(-1).Path() != existing.WithRevision(-1).Path() {
		return errors.Errorf("bundle charm %q is incompatible with existing charm %q", id, existing)
	}
	charmsClient := charms.NewClient(api)
	resourceLister, err := resourceadapters.NewAPIClient(api)
	if err != nil {
		return errors.Trace(err)
	}
	filtered, err := getUpgradeResources(charmsClient, resourceLister, applicationName, url, resources)
	if err != nil {
		return errors.Trace(err)
	}
	var resNames2IDs map[string]string
	if len(filtered) != 0 {
		resNames2IDs, err = resourceadapters.DeployResources(
			applicationName,
			chID,
			csMac,
			resources,
			filtered,
			api,
		)
		if err != nil {
			return errors.Trace(err)
		}
	}
	cfg := application.SetCharmConfig{
		ApplicationName: applicationName,
		CharmID:         chID,
		ResourceIDs:     resNames2IDs,
	}
	if err := h.api.SetCharm(cfg); err != nil {
		return errors.Annotatef(err, "cannot upgrade charm to %q", id)
	}
	h.log.Infof("upgraded charm for existing application %s (from %s to %s)", applicationName, existing, id)
	for resName := range resNames2IDs {
		h.log.Infof("added resource %s", resName)
	}
	return nil
}
コード例 #4
0
ファイル: deploy.go プロジェクト: kat-co/juju
func (c *DeployCommand) deployCharm(
	id charmstore.CharmID,
	csMac *macaroon.Macaroon,
	series string,
	ctx *cmd.Context,
	apiRoot DeployAPI,
) (rErr error) {
	charmInfo, err := apiRoot.CharmInfo(id.URL.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 application")
		}
		if numUnits == 1 && c.PlacementSpec == "" {
			numUnits = 0
		} else {
			return errors.New("cannot use --num-units or --to with subordinate application")
		}
	}
	serviceName := c.ApplicationName
	if serviceName == "" {
		serviceName = charmInfo.Meta.Name
	}

	var configYAML []byte
	if c.Config.Path != "" {
		configYAML, err = c.Config.Read(ctx)
		if err != nil {
			return errors.Trace(err)
		}
	}

	bakeryClient, err := c.BakeryClient()
	if err != nil {
		return errors.Trace(err)
	}

	uuid, ok := apiRoot.ModelUUID()
	if !ok {
		return errors.New("API connection is controller-only (should never happen)")
	}

	deployInfo := DeploymentInfo{
		CharmID:         id,
		ApplicationName: serviceName,
		ModelUUID:       uuid,
		CharmInfo:       charmInfo,
	}

	for _, step := range c.Steps {
		err = step.RunPre(apiRoot, bakeryClient, ctx, deployInfo)
		if err != nil {
			return errors.Trace(err)
		}
	}

	defer func() {
		for _, step := range c.Steps {
			err = errors.Trace(step.RunPost(apiRoot, bakeryClient, ctx, deployInfo, rErr))
			if err != nil {
				rErr = err
			}
		}
	}()

	if id.URL != nil && id.URL.Schema != "local" && len(charmInfo.Meta.Terms) > 0 {
		ctx.Infof("Deployment under prior agreement to terms: %s",
			strings.Join(charmInfo.Meta.Terms, " "))
	}

	ids, err := resourceadapters.DeployResources(
		serviceName,
		id,
		csMac,
		c.Resources,
		charmInfo.Meta.Resources,
		apiRoot,
	)
	if err != nil {
		return errors.Trace(err)
	}

	return errors.Trace(apiRoot.Deploy(application.DeployArgs{
		CharmID:          id,
		Cons:             c.Constraints,
		ApplicationName:  serviceName,
		Series:           series,
		NumUnits:         numUnits,
		ConfigYAML:       string(configYAML),
		Placement:        c.Placement,
		Storage:          c.Storage,
		Resources:        ids,
		EndpointBindings: c.Bindings,
	}))
}
コード例 #5
0
ファイル: bundle.go プロジェクト: bac/juju
// addService deploys or update an application with no units. Service options are
// also set or updated.
func (h *bundleHandler) addService(
	api DeployAPI,
	id string,
	p bundlechanges.AddApplicationParams,
	chID charmstore.CharmID,
	csMac *macaroon.Macaroon,
) error {
	h.results[id] = p.Application
	ch := chID.URL.String()
	// Handle application configuration.
	configYAML := ""
	if len(p.Options) > 0 {
		config, err := yaml.Marshal(map[string]map[string]interface{}{p.Application: p.Options})
		if err != nil {
			return errors.Annotatef(err, "cannot marshal options for application %q", p.Application)
		}
		configYAML = string(config)
	}
	// Handle application constraints.
	cons, err := constraints.Parse(p.Constraints)
	if err != nil {
		// This should never happen, as the bundle is already verified.
		return errors.Annotate(err, "invalid constraints for application")
	}
	storageConstraints := h.bundleStorage[p.Application]
	if len(p.Storage) > 0 {
		if storageConstraints == nil {
			storageConstraints = make(map[string]storage.Constraints)
		}
		for k, v := range p.Storage {
			if _, ok := storageConstraints[k]; ok {
				// Storage constraints overridden
				// on the command line.
				continue
			}
			cons, err := storage.ParseConstraints(v)
			if err != nil {
				return errors.Annotate(err, "invalid storage constraints")
			}
			storageConstraints[k] = cons
		}
	}
	resources := make(map[string]string)
	for resName, revision := range p.Resources {
		resources[resName] = fmt.Sprint(revision)
	}
	charmInfo, err := h.api.CharmInfo(ch)
	if err != nil {
		return err
	}
	resNames2IDs, err := resourceadapters.DeployResources(
		p.Application,
		chID,
		csMac,
		resources,
		charmInfo.Meta.Resources,
		api,
	)
	if err != nil {
		return errors.Trace(err)
	}

	// Figure out what series we need to deploy with.
	conf, err := getModelConfig(h.api)
	if err != nil {
		return err
	}
	supportedSeries := charmInfo.Meta.Series
	if len(supportedSeries) == 0 && chID.URL.Series != "" {
		supportedSeries = []string{chID.URL.Series}
	}
	selector := seriesSelector{
		seriesFlag:      p.Series,
		charmURLSeries:  chID.URL.Series,
		supportedSeries: supportedSeries,
		conf:            conf,
		fromBundle:      true,
	}
	series, err := selector.charmSeries()
	if err != nil {
		return errors.Trace(err)
	}

	// Deploy the application.
	logger.Debugf("application %s is deploying (charm %s)", p.Application, ch)
	h.log.Infof("Deploying charm %q", ch)
	if err := api.Deploy(application.DeployArgs{
		CharmID:          chID,
		Cons:             cons,
		ApplicationName:  p.Application,
		Series:           series,
		ConfigYAML:       configYAML,
		Storage:          storageConstraints,
		Resources:        resNames2IDs,
		EndpointBindings: p.EndpointBindings,
	}); err == nil {
		for resName := range resNames2IDs {
			h.log.Infof("added resource %s", resName)
		}
		return nil
	} else if !isErrServiceExists(err) {
		return errors.Annotatef(err, "cannot deploy application %q", p.Application)
	}
	// The application is already deployed in the environment: check that its
	// charm is compatible with the one declared in the bundle. If it is,
	// reuse the existing application or upgrade to a specified revision.
	// Exit with an error otherwise.
	if err := h.upgradeCharm(api, p.Application, chID, csMac, resources); err != nil {
		return errors.Annotatef(err, "cannot upgrade application %q", p.Application)
	}
	// Update application configuration.
	if configYAML != "" {
		if err := h.api.Update(params.ApplicationUpdate{
			ApplicationName: p.Application,
			SettingsYAML:    configYAML,
		}); err != nil {
			// This should never happen as possible errors are already returned
			// by the application Deploy call above.
			return errors.Annotatef(err, "cannot update options for application %q", p.Application)
		}
		h.log.Infof("configuration updated for application %s", p.Application)
	}
	// Update application constraints.
	if p.Constraints != "" {
		if err := h.api.SetConstraints(p.Application, cons); err != nil {
			// This should never happen, as the bundle is already verified.
			return errors.Annotatef(err, "cannot update constraints for application %q", p.Application)
		}
		h.log.Infof("constraints applied for application %s", p.Application)
	}
	return nil
}