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

Display request ids in the CLI. #4763

Merged
merged 1 commit into from
Oct 17, 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
12 changes: 3 additions & 9 deletions cmd/cli/app/auth/auth_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

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

"github.com/mindersec/minder/internal/config"
clientconfig "github.com/mindersec/minder/internal/config/client"
Expand All @@ -33,13 +34,11 @@ var loginCmd = &cobra.Command{
Short: "Login to Minder",
Long: `The login command allows for logging in to Minder. Upon successful login, credentials will be saved to
$XDG_CONFIG_HOME/minder/credentials.json`,
RunE: LoginCommand,
RunE: cli.GRPCClientWrapRunE(LoginCommand),
}

// LoginCommand is the login subcommand
func LoginCommand(cmd *cobra.Command, _ []string) error {
ctx := context.Background()

func LoginCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn *grpc.ClientConn) error {
clientConfig, err := config.ReadConfigFromViper[clientconfig.Config](viper.GetViper())
if err != nil {
return cli.MessageAndError("Unable to read config", err)
Expand All @@ -53,11 +52,6 @@ func LoginCommand(cmd *cobra.Command, _ []string) error {
return cli.MessageAndError("Error ensuring credentials", err)
}

conn, err := cli.GrpcForCommand(viper.GetViper())
if err != nil {
return cli.MessageAndError("Error getting grpc connection", err)
}
defer conn.Close()
client := minderv1.NewUserServiceClient(conn)

// check if the user already exists in the local database
Expand Down
20 changes: 15 additions & 5 deletions cmd/cli/app/quickstart/quickstart.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ var cmd = &cobra.Command{
// quickstartCommand is the quickstart command
//
//nolint:gocyclo
func quickstartCommand(_ context.Context, cmd *cobra.Command, _ []string, conn *grpc.ClientConn) error {
func quickstartCommand(
ctx context.Context,
cmd *cobra.Command,
_ []string,
conn *grpc.ClientConn,
) error {
var err error
repoClient := minderv1.NewRepositoryServiceClient(conn)
profileClient := minderv1.NewProfileServiceClient(conn)
Expand All @@ -180,13 +185,13 @@ func quickstartCommand(_ context.Context, cmd *cobra.Command, _ []string, conn *
userClient := minderv1.NewUserServiceClient(conn)
_, err = userClient.GetUser(cmd.Context(), &minderv1.GetUserRequest{})
if err != nil {
err = loginPromptErrWrapper(cmd, err)
err = loginPromptErrWrapper(ctx, cmd, conn, err)
if err != nil {
return cli.MessageAndError("", err)
}
// User logged in successfully
// We now have to re-create the gRPC connection
newConn, err := cli.GrpcForCommand(viper.GetViper())
newConn, err := cli.GrpcForCommand(cmd, viper.GetViper())
if err != nil {
return err
}
Expand Down Expand Up @@ -399,7 +404,12 @@ func getQuickstartContext(ctx context.Context, v *viper.Viper) (context.Context,
return cli.GetAppContextWithTimeoutDuration(ctx, v, 30)
}

func loginPromptErrWrapper(cmnd *cobra.Command, inErr error) error {
func loginPromptErrWrapper(
ctx context.Context,
cmnd *cobra.Command,
conn *grpc.ClientConn,
inErr error,
) error {
// Check if the error is unauthenticated, if so, prompt the user to log in
if rpcStatus, ok := status.FromError(inErr); ok {
if rpcStatus.Code() == codes.Unauthenticated {
Expand All @@ -411,7 +421,7 @@ func loginPromptErrWrapper(cmnd *cobra.Command, inErr error) error {
true)
if yes {
// Run the login command
err := auth.LoginCommand(cmnd, []string{})
err := auth.LoginCommand(ctx, cmnd, []string{}, conn)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions cmd/cli/app/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func init() {
RootCmd.Printf("error: %s", err)
os.Exit(1)
}
RootCmd.PersistentFlags().BoolP("verbose", "v", false, "Output additional messages to STDERR")
viper.AutomaticEnv()
}

Expand Down
2 changes: 1 addition & 1 deletion internal/util/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func GRPCClientWrapRunE(
ctx, cancel := GetAppContext(cmd.Context(), viper.GetViper())
defer cancel()

c, err := GrpcForCommand(viper.GetViper())
c, err := GrpcForCommand(cmd, viper.GetViper())
if err != nil {
return err
}
Expand Down
38 changes: 36 additions & 2 deletions internal/util/cli/rpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
httphelper "github.com/zitadel/oidc/v3/pkg/http"
"github.com/zitadel/oidc/v3/pkg/oidc"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"

"github.com/mindersec/minder/internal/config"
clientconfig "github.com/mindersec/minder/internal/config/client"
Expand All @@ -52,8 +53,28 @@ var accessDeniedHtml []byte
//go:embed html/generic_failure.html
var genericAuthFailure []byte

func requestIDInterceptor(printer func(string, ...interface{})) grpc.UnaryClientInterceptor {
return func(
ctx context.Context,
method string,
req any,
reply any,
cc *grpc.ClientConn,
invoker grpc.UnaryInvoker,
opts ...grpc.CallOption,
) error {
var header metadata.MD
opts = append(opts, grpc.Header(&header))
err := invoker(ctx, method, req, reply, cc, opts...)
if len(header.Get("request-id")) != 0 {
printer("Request ID: %s\n", header.Get("request-id")[0])
}
return err
}
}

// GrpcForCommand is a helper for getting a testing connection from cobra flags
func GrpcForCommand(v *viper.Viper) (*grpc.ClientConn, error) {
func GrpcForCommand(cmd *cobra.Command, v *viper.Viper) (*grpc.ClientConn, error) {
clientConfig, err := config.ReadConfigFromViper[clientconfig.Config](v)
if err != nil {
return nil, fmt.Errorf("unable to read config: %w", err)
Expand All @@ -67,8 +88,21 @@ func GrpcForCommand(v *viper.Viper) (*grpc.ClientConn, error) {
issuerUrl := clientConfig.Identity.CLI.IssuerUrl
clientId := clientConfig.Identity.CLI.ClientId

opts := []grpc.DialOption{}
opts = append(opts, grpc.WithUserAgent(useragent.GetUserAgent()))

if viper.GetBool("verbose") {
opts = append(opts, grpc.WithUnaryInterceptor(requestIDInterceptor(cmd.PrintErrf)))
}

return util.GetGrpcConnection(
grpcHost, grpcPort, allowInsecure, issuerUrl, clientId, grpc.WithUserAgent(useragent.GetUserAgent()))
grpcHost,
grpcPort,
allowInsecure,
issuerUrl,
clientId,
opts...,
)
}

// EnsureCredentials is a PreRunE function to ensure that the user
Expand Down