From 84c18196dd05758e7d8c868f37e852b8ff83afd5 Mon Sep 17 00:00:00 2001 From: Marques Johansson Date: Mon, 26 Sep 2022 22:28:47 -0400 Subject: [PATCH] add "metal user add" command Signed-off-by: Marques Johansson --- docs/metal_user.md | 3 +- docs/metal_user_add.md | 48 +++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 +-- internal/ssh/retrieve.go | 1 - internal/users/add.go | 77 ++++++++++++++++++++++++++++++++++++++++ internal/users/user.go | 11 +++--- 7 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 docs/metal_user_add.md create mode 100644 internal/users/add.go diff --git a/docs/metal_user.md b/docs/metal_user.md index fa28987e..4324b609 100644 --- a/docs/metal_user.md +++ b/docs/metal_user.md @@ -4,7 +4,7 @@ User operations. For more information on user and account management, visit http ### Synopsis -User operations: get. +User operations: get and add. ### Options @@ -29,5 +29,6 @@ User operations: get. ### SEE ALSO * [metal](metal.md) - Command line interface for Equinix Metal +* [metal user add](metal_user_add.md) - Adds a user to an organization or project * [metal user get](metal_user_get.md) - Retrieves information about the current user or a specified user. diff --git a/docs/metal_user_add.md b/docs/metal_user_add.md new file mode 100644 index 00000000..274c8216 --- /dev/null +++ b/docs/metal_user_add.md @@ -0,0 +1,48 @@ +## metal user add + +Adds a user to an organization or project + +### Synopsis + +Adds a user, by email, to the organization or project specified by the --organization-id or --project-id flag. The user will be assigned the roles specified by the --roles flag. + +``` +metal user add --email --roles [--organization-id ] [--project-id ] [flags] +``` + +### Examples + +``` + # Adds a user to a project with admin role: + metal user add --email user@example.org --roles admin --project-id 3b0795ba-fd0b-4a9e-83a7-063e5e12409d + +``` + +### Options + +``` + --email string Email of the user. + -h, --help help for add + --organization-id string Organization to invite the user to. + -p, --project-id strings Projects to invite the user to with the specified roles. + --roles strings Roles to assign to the user. +``` + +### Options inherited from parent commands + +``` + --config string Path to JSON or YAML configuration file + --exclude strings Comma separated Href references to collapse in results, may be dotted three levels deep + --filter stringArray Filter 'get' actions with name value pairs. Filter is not supported by all resources and is implemented as request query parameters. + --include strings Comma separated Href references to expand in results, may be dotted three levels deep + -o, --output string Output format (*table, json, yaml) + --search string Search keyword for use in 'get' actions. Search is not supported by all resources. + --sort-by string Sort fields for use in 'get' actions. Sort is not supported by all resources. + --sort-dir string Sort field direction for use in 'get' actions. Sort is not supported by all resources. + --token string Metal API Token (METAL_AUTH_TOKEN) +``` + +### SEE ALSO + +* [metal user](metal_user.md) - User operations. For more information on user and account management, visit https://metal.equinix.com/developers/docs/accounts/users/ in the Equinix Metal documentation. + diff --git a/go.mod b/go.mod index 2161d9e7..7696ce1f 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( github.com/manifoldco/promptui v0.9.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/packethost/packngo v0.26.0 + github.com/packethost/packngo v0.27.0 github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.5.0 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index 116f75b4..46a7d9a4 100644 --- a/go.sum +++ b/go.sum @@ -311,8 +311,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/packethost/packngo v0.26.0 h1:jbPHPEd+KpoM2OBQ3EgbgEYiAUK7vpZ9XhqOMEbnk78= -github.com/packethost/packngo v0.26.0/go.mod h1:/UHguFdPs6Lf6FOkkSEPnRY5tgS0fsVM+Zv/bvBrmt0= +github.com/packethost/packngo v0.27.0 h1:wYHZuU37Ej9F0DTOc5sjPS4U3cRQcCTzYT97YqVdsaI= +github.com/packethost/packngo v0.27.0/go.mod h1:/UHguFdPs6Lf6FOkkSEPnRY5tgS0fsVM+Zv/bvBrmt0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= diff --git a/internal/ssh/retrieve.go b/internal/ssh/retrieve.go index 47e98a4d..2251b350 100644 --- a/internal/ssh/retrieve.go +++ b/internal/ssh/retrieve.go @@ -66,7 +66,6 @@ func (c *Client) Retrieve() *cobra.Command { } } sshKeys, _, err := listFn() - if err != nil { return errors.Wrap(err, "Could not list SSH Keys") } diff --git a/internal/users/add.go b/internal/users/add.go new file mode 100644 index 00000000..f48f9624 --- /dev/null +++ b/internal/users/add.go @@ -0,0 +1,77 @@ +// Copyright © 2022 Equinix Metal Developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package users + +import ( + "strconv" + "strings" + + "github.com/packethost/packngo" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +func (c *Client) Add() *cobra.Command { + var email string + var roles []string + var projectsIDs []string + var organizationID string + + // addUserCmd represents the addUser command + addUserCmd := &cobra.Command{ + Use: `add --email --roles [--organization-id ] [--project-id ]`, + Short: "Adds a user to an organization or project", + Long: "Adds a user, by email, to the organization or project specified by the --organization-id or --project-id flag. The user will be assigned the roles specified by the --roles flag.", + Example: ` # Adds a user to a project with admin role: + metal user add --email user@example.org --roles admin --project-id 3b0795ba-fd0b-4a9e-83a7-063e5e12409d +`, + + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + getOpts := c.Servicer.ListOptions(nil, nil) + createRequest := &packngo.InvitationCreateRequest{ + Invitee: email, + Roles: roles, + ProjectsIDs: projectsIDs, + } + invitation, _, err := c.InvitationService.Create(organizationID, createRequest, getOpts) + if err != nil { + return errors.Wrap(err, "Could not add Users") + } + + data := make([][]string, 1) + + data[0] = []string{invitation.ID, invitation.Nonce, invitation.Invitee, invitation.Organization.Href, strconv.Itoa(len(invitation.Projects)), strings.Join(invitation.Roles, ", ")} + header := []string{"ID", "Nonce", "Email", "Organization", "Projects", "Roles"} + + return c.Out.Output(invitation, header, &data) + }, + } + + addUserCmd.Flags().StringVar(&email, "email", "", "Email of the user.") + addUserCmd.Flags().StringVar(&organizationID, "organization-id", "", "Organization to invite the user to.") + addUserCmd.Flags().StringSliceVar(&roles, "roles", []string{""}, "Roles to assign to the user.") + addUserCmd.Flags().StringSliceVarP(&projectsIDs, "project-id", "p", []string{""}, "Projects to invite the user to with the specified roles.") + + _ = addUserCmd.MarkFlagRequired("email") + + return addUserCmd +} diff --git a/internal/users/user.go b/internal/users/user.go index be5698f3..4c4dfaa0 100644 --- a/internal/users/user.go +++ b/internal/users/user.go @@ -27,9 +27,10 @@ import ( ) type Client struct { - Servicer Servicer - Service packngo.UserService - Out outputs.Outputer + Servicer Servicer + Service packngo.UserService + InvitationService packngo.InvitationService + Out outputs.Outputer } func (c *Client) NewCommand() *cobra.Command { @@ -37,7 +38,7 @@ func (c *Client) NewCommand() *cobra.Command { Use: `user`, Aliases: []string{"users"}, Short: "User operations. For more information on user and account management, visit https://metal.equinix.com/developers/docs/accounts/users/ in the Equinix Metal documentation.", - Long: "User operations: get.", + Long: "User operations: get and add.", PersistentPreRun: func(cmd *cobra.Command, args []string) { if root := cmd.Root(); root != nil { @@ -46,11 +47,13 @@ func (c *Client) NewCommand() *cobra.Command { } } c.Service = c.Servicer.API(cmd).Users + c.InvitationService = c.Servicer.API(cmd).Invitations }, } cmd.AddCommand( c.Retrieve(), + c.Add(), ) return cmd }