Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add format output for role grant and update #3930

Merged
merged 1 commit into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")
}