// applicationSetCharm sets the charm for the given for the application. func (api *API) applicationSetCharm( appName string, application Application, url string, channel csparams.Channel, configSettingsStrings map[string]string, configSettingsYAML string, forceSeries, forceUnits bool, resourceIDs map[string]string, storageConstraints map[string]params.StorageConstraints, ) error { curl, err := charm.ParseURL(url) if err != nil { return errors.Trace(err) } sch, err := api.backend.Charm(curl) if err != nil { return errors.Trace(err) } var settings charm.Settings if configSettingsYAML != "" { settings, err = sch.Config().ParseSettingsYAML([]byte(configSettingsYAML), appName) } else if len(configSettingsStrings) > 0 { settings, err = parseSettingsCompatible(sch.Config(), configSettingsStrings) } if err != nil { return errors.Annotate(err, "parsing config settings") } var stateStorageConstraints map[string]state.StorageConstraints if len(storageConstraints) > 0 { stateStorageConstraints = make(map[string]state.StorageConstraints) for name, cons := range storageConstraints { stateCons := state.StorageConstraints{Pool: cons.Pool} if cons.Size != nil { stateCons.Size = *cons.Size } if cons.Count != nil { stateCons.Count = *cons.Count } stateStorageConstraints[name] = stateCons } } cfg := state.SetCharmConfig{ Charm: api.stateCharm(sch), Channel: channel, ConfigSettings: settings, ForceSeries: forceSeries, ForceUnits: forceUnits, ResourceIDs: resourceIDs, StorageConstraints: stateStorageConstraints, } return application.SetCharm(cfg) }
// AddToUnit validates and creates additional storage instances for units. // This method handles bulk add operations and // a failure on one individual storage instance does not block remaining // instances from being processed. // A "CHANGE" block can block this operation. func (a *API) AddToUnit(args params.StoragesAddParams) (params.ErrorResults, error) { // Check if changes are allowed and the operation may proceed. blockChecker := common.NewBlockChecker(a.storage) if err := blockChecker.ChangeAllowed(); err != nil { return params.ErrorResults{}, errors.Trace(err) } if len(args.Storages) == 0 { return params.ErrorResults{}, nil } serverErr := func(err error) params.ErrorResult { if errors.IsNotFound(err) { err = common.ErrPerm } return params.ErrorResult{Error: common.ServerError(err)} } paramsToState := func(p params.StorageConstraints) state.StorageConstraints { s := state.StorageConstraints{Pool: p.Pool} if p.Size != nil { s.Size = *p.Size } if p.Count != nil { s.Count = *p.Count } return s } result := make([]params.ErrorResult, len(args.Storages)) for i, one := range args.Storages { u, err := names.ParseUnitTag(one.UnitTag) if err != nil { result[i] = serverErr( errors.Annotatef(err, "parsing unit tag %v", one.UnitTag)) continue } err = a.storage.AddStorageForUnit(u, one.StorageName, paramsToState(one.Constraints)) if err != nil { result[i] = serverErr( errors.Annotatef(err, "adding storage %v for %v", one.StorageName, one.UnitTag)) } } return params.ErrorResults{Results: result}, nil }