Skip to content

Commit

Permalink
Add format output for role grant and update (#3930)
Browse files Browse the repository at this point in the history
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
  • Loading branch information
rdimitrov authored Jul 18, 2024
1 parent 3518a0c commit 409ac76
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 25 deletions.
45 changes: 38 additions & 7 deletions cmd/cli/app/project/role/role_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ package role

import (
"context"
"fmt"
"os"
"strings"
"time"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"google.golang.org/grpc"

"github.com/stacklok/minder/cmd/cli/app"
"github.com/stacklok/minder/internal/util"
"github.com/stacklok/minder/internal/util/cli"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
)
Expand All @@ -43,6 +48,12 @@ func GrantCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn *grp
r := viper.GetString("role")
project := viper.GetString("project")
email := viper.GetString("email")
format := viper.GetString("output")

// Ensure the output format is supported
if !app.IsOutputFormatSupported(format) {
return cli.MessageAndError(fmt.Sprintf("Output format %s not supported", format), fmt.Errorf("invalid argument"))
}

// No longer print usage on returned error, since we've parsed our inputs
// See https://github.com/spf13/cobra/issues/340#issuecomment-374617413
Expand All @@ -64,7 +75,7 @@ func GrantCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn *grp
successMsg = "Invite created successfully."
}

ret, err := client.AssignRole(ctx, &minderv1.AssignRoleRequest{
resp, err := client.AssignRole(ctx, &minderv1.AssignRoleRequest{
Context: &minderv1.Context{
Project: &project,
},
Expand All @@ -74,12 +85,30 @@ func GrantCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn *grp
return cli.MessageAndError(failMsg, err)
}

cmd.Println(successMsg)

if ret.Invitation != nil && ret.Invitation.Code != "" {
cmd.Printf("\nThe invitee can accept it by running: \n\nminder auth invite accept %s\n", ret.Invitation.Code)
if ret.Invitation.InviteUrl != "" {
cmd.Printf("\nOr by visiting: %s\n", ret.Invitation.InviteUrl)
switch format {
case app.JSON:
out, err := util.GetJsonFromProto(resp)
if err != nil {
return cli.MessageAndError("Error getting json from proto", err)
}
cmd.Println(out)
case app.YAML:
out, err := util.GetYamlFromProto(resp)
if err != nil {
return cli.MessageAndError("Error getting yaml from proto", err)
}
cmd.Println(out)
case app.Table:
cmd.Println(successMsg)
if resp.Invitation != nil && resp.Invitation.Code != "" {
t := initializeTableForGrantListInvitations()
i := resp.Invitation
t.AddRow(i.Email, i.Role, i.SponsorDisplay, i.ExpiresAt.AsTime().Format(time.RFC3339))
t.Render()
cmd.Printf("\nThe invitee can accept it by running: \n\nminder auth invite accept %s\n", resp.Invitation.Code)
if resp.Invitation.InviteUrl != "" {
cmd.Printf("\nOr by visiting: %s\n", resp.Invitation.InviteUrl)
}
}
}
return nil
Expand All @@ -91,6 +120,8 @@ func init() {
grantCmd.Flags().StringP("sub", "s", "", "subject to grant access to")
grantCmd.Flags().StringP("role", "r", "", "the role to grant")
grantCmd.Flags().StringP("email", "e", "", "email to send invitation to")
grantCmd.Flags().StringP("output", "o", app.Table,
fmt.Sprintf("Output format (one of %s)", strings.Join(app.SupportedOutputFormats(), ",")))
grantCmd.MarkFlagsOneRequired("sub", "email")
grantCmd.MarkFlagsMutuallyExclusive("sub", "email")
if err := grantCmd.MarkFlagRequired("role"); err != nil {
Expand Down
63 changes: 45 additions & 18 deletions cmd/cli/app/project/role/role_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ package role
import (
"context"
"fmt"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"google.golang.org/grpc"

"github.com/stacklok/minder/cmd/cli/app"
"github.com/stacklok/minder/internal/util"
"github.com/stacklok/minder/internal/util/cli"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
)
Expand All @@ -39,10 +42,16 @@ to a user (subject) on a particular project.`,
func UpdateCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn *grpc.ClientConn) error {
client := minderv1.NewPermissionsServiceClient(conn)

r := viper.GetString("role")
role := viper.GetString("role")
project := viper.GetString("project")
sub := viper.GetString("sub")
email := viper.GetString("email")
format := viper.GetString("output")

// Ensure the output format is supported
if !app.IsOutputFormatSupported(format) {
return cli.MessageAndError(fmt.Sprintf("Output format %s not supported", format), fmt.Errorf("invalid argument"))
}

// No longer print usage on returned error, since we've parsed our inputs
// See https://github.com/spf13/cobra/issues/340#issuecomment-374617413
Expand All @@ -52,7 +61,7 @@ func UpdateCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn *gr
Context: &minderv1.Context{
Project: &project,
},
Roles: []string{r},
Roles: []string{role},
Subject: sub,
}
failMsg := "Error updating role"
Expand All @@ -63,28 +72,44 @@ func UpdateCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn *gr
successMsg = "Invite updated successfully."
}

ret, err := client.UpdateRole(ctx, req)
resp, err := client.UpdateRole(ctx, req)
if err != nil {
return cli.MessageAndError(failMsg, err)
}

cmd.Println(successMsg)

// If it was an invitation, print the invite details
if len(ret.Invitations) != 0 {
for _, r := range ret.Invitations {
// TODO: Add a url to the invite
cmd.Printf("Updated an invite for %s to %s on %s\n\nThe invitee can accept it by running: \n\nminder auth invite accept %s\n",
r.Email, r.Role, r.Project, r.Code)
switch format {
case app.JSON:
out, err := util.GetJsonFromProto(resp)
if err != nil {
return cli.MessageAndError("Error getting json from proto", err)
}
return nil
}
// Otherwise, print the role assignments if it was about updating a role
t := initializeTableForGrantListRoleAssignments()
for _, r := range ret.RoleAssignments {
t.AddRow(fmt.Sprintf("%s / %s", r.DisplayName, r.Subject), r.Role, *r.Project)
cmd.Println(out)
case app.YAML:
out, err := util.GetYamlFromProto(resp)
if err != nil {
return cli.MessageAndError("Error getting yaml from proto", err)
}
cmd.Println(out)
case app.Table:
cmd.Println(successMsg)
// If it was an invitation, print the invite details
if len(resp.Invitations) != 0 {
for _, r := range resp.Invitations {
cmd.Printf("Updated an invite for %s to %s on %s\n\nThe invitee can accept it by running: \n\nminder auth invite accept %s\n",
r.Email, r.Role, r.Project, r.Code)
if r.InviteUrl != "" {
cmd.Printf("\nOr by visiting: %s\n", r.InviteUrl)
}
}
return nil
}
// Otherwise, print the role assignments if it was about updating a role
t := initializeTableForGrantListRoleAssignments()
for _, r := range resp.RoleAssignments {
t.AddRow(fmt.Sprintf("%s / %s", r.DisplayName, r.Subject), r.Role, *r.Project)
}
t.Render()
}
t.Render()
return nil
}

Expand All @@ -94,6 +119,8 @@ func init() {
updateCmd.Flags().StringP("role", "r", "", "the role to update it to")
updateCmd.Flags().StringP("sub", "s", "", "subject to update role access for")
updateCmd.Flags().StringP("email", "e", "", "email to send invitation to")
updateCmd.Flags().StringP("output", "o", app.Table,
fmt.Sprintf("Output format (one of %s)", strings.Join(app.SupportedOutputFormats(), ",")))
updateCmd.MarkFlagsOneRequired("sub", "email")
updateCmd.MarkFlagsMutuallyExclusive("sub", "email")
}

0 comments on commit 409ac76

Please sign in to comment.