func (api *UserManagerAPI) enableUserImpl(args params.Entities, action string, method func(*state.User) error) (params.ErrorResults, error) { var result params.ErrorResults if len(args.Entities) == 0 { return result, nil } isSuperUser, err := api.hasControllerAdminAccess() if err != nil { return result, errors.Trace(err) } if !api.isAdmin && isSuperUser { return result, common.ErrPerm } // Create the results list to populate. result.Results = make([]params.ErrorResult, len(args.Entities)) for i, arg := range args.Entities { user, err := api.getUser(arg.Tag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } err = method(user) if err != nil { result.Results[i].Error = common.ServerError(errors.Errorf("failed to %s user: %s", action, err)) } } return result, nil }
// DeleteImages deletes the images matching the specified filter. func (api *ImageManagerAPI) DeleteImages(arg params.ImageFilterParams) (params.ErrorResults, error) { if err := api.check.ChangeAllowed(); err != nil { return params.ErrorResults{}, errors.Trace(err) } var result params.ErrorResults result.Results = make([]params.ErrorResult, len(arg.Images)) stor := api.state.ImageStorage() for i, imageSpec := range arg.Images { filter := imagestorage.ImageFilter{ Kind: imageSpec.Kind, Series: imageSpec.Series, Arch: imageSpec.Arch, } imageMetadata, err := stor.ListImages(filter) if err != nil { result.Results[i].Error = common.ServerError(err) continue } if len(imageMetadata) != 1 { result.Results[i].Error = common.ServerError( errors.NotFoundf("image %s/%s/%s", filter.Kind, filter.Series, filter.Arch)) continue } logger.Infof("deleting image with metadata %+v", *imageMetadata[0]) err = stor.DeleteImage(imageMetadata[0]) if err != nil { result.Results[i].Error = common.ServerError(err) } } return result, nil }
func (c *Client) convert(found []params.StorageDetailsResult) ([]params.StorageDetails, error) { var storages []params.StorageDetails var allErr params.ErrorResults for _, result := range found { if result.Error != nil { allErr.Results = append(allErr.Results, params.ErrorResult{result.Error}) continue } storages = append(storages, result.Result) } return storages, allErr.Combine() }
// RemoveUser permanently removes a user from the current controller for each // entity provided. While the user is permanently removed we keep it's // information around for auditing purposes. // TODO(redir): Add information about getting deleted user information when we // add that capability. func (api *UserManagerAPI) RemoveUser(entities params.Entities) (params.ErrorResults, error) { var deletions params.ErrorResults if err := api.check.ChangeAllowed(); err != nil { return deletions, errors.Trace(err) } // Get a handle on the controller model. controllerModel, err := api.state.ControllerModel() if err != nil { return deletions, errors.Trace(err) } // Create the results list to populate. deletions.Results = make([]params.ErrorResult, len(entities.Entities)) isSuperUser, err := api.hasControllerAdminAccess() if err != nil { return deletions, errors.Trace(err) } if !api.isAdmin && !isSuperUser { return deletions, common.ErrPerm } // Remove the entities. for i, e := range entities.Entities { user, err := names.ParseUserTag(e.Tag) if err != nil { deletions.Results[i].Error = common.ServerError(err) continue } if controllerModel.Owner().Id() == user.Id() { deletions.Results[i].Error = common.ServerError( errors.Errorf("cannot delete controller owner %q", user.Name())) continue } err = api.state.RemoveUser(user) if err != nil { if errors.IsUserNotFound(err) { deletions.Results[i].Error = common.ServerError(err) } else { deletions.Results[i].Error = common.ServerError( errors.Annotatef(err, "failed to delete user %q", user.Name())) } continue } deletions.Results[i].Error = nil } return deletions, nil }
// ImportKeys imports new authorised ssh keys from the specified key ids for the specified user. func (api *KeyManagerAPI) ImportKeys(arg params.ModifyUserSSHKeys) (params.ErrorResults, error) { if err := api.check.ChangeAllowed(); err != nil { return params.ErrorResults{}, errors.Trace(err) } result := params.ErrorResults{ Results: make([]params.ErrorResult, len(arg.Keys)), } if len(arg.Keys) == 0 { return result, nil } if !api.canWrite(arg.User) { return params.ErrorResults{}, common.ServerError(common.ErrPerm) } // For now, authorised keys are global, common to all users. sshKeys, currentFingerprints, err := api.currentKeyDataForAdd() if err != nil { return params.ErrorResults{}, common.ServerError(fmt.Errorf("reading current key data: %v", err)) } importedKeyInfo := runSSHKeyImport(arg.Keys) // Ensure we are not going to add invalid or duplicate keys. result.Results = make([]params.ErrorResult, len(importedKeyInfo)) for i, key := range arg.Keys { compoundErr := "" for _, keyInfo := range importedKeyInfo[key] { if keyInfo.err != nil { compoundErr += fmt.Sprintf("%v\n", keyInfo.err) continue } if currentFingerprints.Contains(keyInfo.fingerprint) { compoundErr += fmt.Sprintf("%v\n", errors.Errorf("duplicate ssh key: %s", keyInfo.key)) continue } sshKeys = append(sshKeys, keyInfo.key) } if compoundErr != "" { result.Results[i].Error = common.ServerError(errors.Errorf(strings.TrimSuffix(compoundErr, "\n"))) } } err = api.writeSSHKeys(sshKeys) if err != nil { return params.ErrorResults{}, common.ServerError(err) } return result, nil }
// List returns blocks that are switched on for current environment. func (c *Client) List() ([]params.Block, error) { blocks := params.BlockResults{} if err := c.facade.FacadeCall("List", nil, &blocks); err != nil { return nil, errors.Trace(err) } all := []params.Block{} allErr := params.ErrorResults{} for _, result := range blocks.Results { if result.Error != nil { allErr.Results = append(allErr.Results, params.ErrorResult{result.Error}) continue } all = append(all, result.Result) } return all, allErr.Combine() }
// Run implements Command.Run. func (c *showCommand) Run(ctx *cmd.Context) (err error) { api := c.api if api == nil { api, err = c.NewStorageAPI() if err != nil { return err } defer api.Close() } tags, err := c.getStorageTags() if err != nil { return err } results, err := api.Show(tags) if err != nil { return err } var errs params.ErrorResults var valid []params.StorageDetails for _, result := range results { if result.Error != nil { errs.Results = append(errs.Results, params.ErrorResult{result.Error}) continue } if result.Result != nil { valid = append(valid, *result.Result) } else { valid = append(valid, storageDetailsFromLegacy(result.Legacy)) } } if len(errs.Results) > 0 { return errs.Combine() } output, err := formatStorageDetails(valid) if err != nil { return err } return c.out.Write(ctx, output) }
// SetPassword changes the stored password for the specified users. func (api *UserManagerAPI) SetPassword(args params.EntityPasswords) (params.ErrorResults, error) { if err := api.check.ChangeAllowed(); err != nil { return params.ErrorResults{}, errors.Trace(err) } var result params.ErrorResults if len(args.Changes) == 0 { return result, nil } // Create the results list to populate. result.Results = make([]params.ErrorResult, len(args.Changes)) for i, arg := range args.Changes { if err := api.setPassword(arg); err != nil { result.Results[i].Error = common.ServerError(err) } } return result, nil }
// AddKeys adds new authorised ssh keys for the specified user. func (api *KeyManagerAPI) AddKeys(arg params.ModifyUserSSHKeys) (params.ErrorResults, error) { if err := api.check.ChangeAllowed(); err != nil { return params.ErrorResults{}, errors.Trace(err) } result := params.ErrorResults{ Results: make([]params.ErrorResult, len(arg.Keys)), } if len(arg.Keys) == 0 { return result, nil } if !api.canWrite(arg.User) { return params.ErrorResults{}, common.ServerError(common.ErrPerm) } // For now, authorised keys are global, common to all users. sshKeys, currentFingerprints, err := api.currentKeyDataForAdd() if err != nil { return params.ErrorResults{}, common.ServerError(fmt.Errorf("reading current key data: %v", err)) } // Ensure we are not going to add invalid or duplicate keys. result.Results = make([]params.ErrorResult, len(arg.Keys)) for i, key := range arg.Keys { fingerprint, _, err := ssh.KeyFingerprint(key) if err != nil { result.Results[i].Error = common.ServerError(fmt.Errorf("invalid ssh key: %s", key)) continue } if currentFingerprints.Contains(fingerprint) { result.Results[i].Error = common.ServerError(fmt.Errorf("duplicate ssh key: %s", key)) continue } sshKeys = append(sshKeys, key) } err = api.writeSSHKeys(sshKeys) if err != nil { return params.ErrorResults{}, common.ServerError(err) } return result, nil }
// AssignUnits assigns the units with the given ids to the correct machine. The // error results are returned in the same order as the given entities. func (a *API) AssignUnits(args params.Entities) (params.ErrorResults, error) { result := params.ErrorResults{} // state uses ids, but the API uses Tags, so we have to convert back and // forth (whee!). The list of ids is (crucially) in the same order as the // list of tags. This is the same order as the list of errors we return. ids := make([]string, len(args.Entities)) for i, e := range args.Entities { tag, err := names.ParseUnitTag(e.Tag) if err != nil { return result, err } ids[i] = tag.Id() } res, err := a.st.AssignStagedUnits(ids) if err != nil { return result, common.ServerError(err) } // The results come back from state in an undetermined order and do not // include results for units that were not found, so we have to make up for // that here. resultMap := make(map[string]error, len(ids)) for _, r := range res { resultMap[r.Unit] = r.Error } result.Results = make([]params.ErrorResult, len(args.Entities)) for i, id := range ids { if err, ok := resultMap[id]; ok { result.Results[i].Error = common.ServerError(err) } else { result.Results[i].Error = common.ServerError(errors.NotFoundf("unit %q", args.Entities[i].Tag)) } } return result, nil }
// Run implements Command.Run. func (c *showCommand) Run(ctx *cmd.Context) (err error) { api, err := c.newAPIFunc() if err != nil { return err } defer api.Close() tags, err := c.getStorageTags() if err != nil { return err } results, err := api.StorageDetails(tags) if err != nil { return err } var errs params.ErrorResults var valid []params.StorageDetails for _, result := range results { if result.Error != nil { errs.Results = append(errs.Results, params.ErrorResult{result.Error}) continue } valid = append(valid, *result.Result) } if len(errs.Results) > 0 { return errs.Combine() } output, err := formatStorageDetails(valid) if err != nil { return err } return c.out.Write(ctx, output) }