diff --git a/cli/cmd/configure_cmd.go b/cli/cmd/configure_cmd.go index ef9d8582f0..934df57c1e 100644 --- a/cli/cmd/configure_cmd.go +++ b/cli/cmd/configure_cmd.go @@ -21,8 +21,7 @@ var configureCmd = &cobra.Command{ Short: "Configure your tracetest CLI", Long: "Configure your tracetest CLI", PreRun: setupLogger, - Run: WithResultHandler(WithParamsHandler(configParams)(func(cmd *cobra.Command, _ []string) (string, error) { - ctx := context.Background() + Run: WithResultHandler(WithParamsHandler(configParams)(func(ctx context.Context, cmd *cobra.Command, _ []string) (string, error) { flags := agentConfig.Flags{ CI: configParams.CI, } diff --git a/cli/cmd/dashboard_cmd.go b/cli/cmd/dashboard_cmd.go index a1598a2188..c2f50e94b6 100644 --- a/cli/cmd/dashboard_cmd.go +++ b/cli/cmd/dashboard_cmd.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "fmt" "github.com/kubeshop/tracetest/cli/ui" @@ -13,7 +14,7 @@ var dashboardCmd = &cobra.Command{ Short: "Opens the Tracetest Dashboard URL", Long: "Opens the Tracetest Dashboard URL", PreRun: setupCommand(), - Run: WithResultHandler(func(_ *cobra.Command, _ []string) (string, error) { + Run: WithResultHandler(func(_ context.Context, _ *cobra.Command, _ []string) (string, error) { if cliConfig.IsEmpty() { return "", fmt.Errorf("missing Tracetest endpoint configuration") } diff --git a/cli/cmd/middleware.go b/cli/cmd/middleware.go index 473ebffb0a..d738ecd357 100644 --- a/cli/cmd/middleware.go +++ b/cli/cmd/middleware.go @@ -1,25 +1,55 @@ package cmd import ( + "context" "errors" "fmt" "os" + "github.com/kubeshop/tracetest/cli/config" "github.com/kubeshop/tracetest/cli/pkg/resourcemanager" + "github.com/kubeshop/tracetest/cli/ui" "github.com/spf13/cobra" ) -type RunFn func(cmd *cobra.Command, args []string) (string, error) +type RunFn func(ctx context.Context, cmd *cobra.Command, args []string) (string, error) type CobraRunFn func(cmd *cobra.Command, args []string) type MiddlewareWrapper func(RunFn) RunFn +func rootCtx(cmd *cobra.Command) context.Context { + // cobra does not correctly progpagate rootcmd context to sub commands, + // so we need to manually traverse the command tree to find the root context + if cmd == nil { + return nil + } + + var ( + ctx = cmd.Context() + p = cmd.Parent() + ) + if cmd.Parent() == nil { + return ctx + } + for { + ctx = p.Context() + p = p.Parent() + if p == nil { + break + } + } + return ctx +} + func WithResultHandler(runFn RunFn) CobraRunFn { return func(cmd *cobra.Command, args []string) { - res, err := runFn(cmd, args) + // we need the root cmd context in case of an error caused rerun + ctx := rootCtx(cmd) + + res, err := runFn(ctx, cmd, args) if err != nil { - OnError(err) + handleError(ctx, err) return } @@ -29,6 +59,28 @@ func WithResultHandler(runFn RunFn) CobraRunFn { } } +func handleError(ctx context.Context, err error) { + reqErr := resourcemanager.RequestError{} + if errors.As(err, &reqErr) && reqErr.IsAuthError { + handleAuthError(ctx) + } else { + OnError(err) + } +} + +func handleAuthError(ctx context.Context) { + ui.DefaultUI.Warning("Your authentication token has expired, please log in again.") + configurator. + WithOnFinish(func(ctx context.Context, _ config.Config) { + retryCommand(ctx) + }). + ExecuteUserLogin(ctx, cliConfig) +} + +func retryCommand(ctx context.Context) { + handleRootExecErr(rootCmd.ExecuteContext(ctx)) +} + type errorMessageRenderer interface { Render() } @@ -66,7 +118,7 @@ func handleErrorMessage(err error) string { func WithParamsHandler(validators ...Validator) MiddlewareWrapper { return func(runFn RunFn) RunFn { - return func(cmd *cobra.Command, args []string) (string, error) { + return func(ctx context.Context, cmd *cobra.Command, args []string) (string, error) { errors := make([]error, 0) for _, validator := range validators { @@ -82,7 +134,7 @@ func WithParamsHandler(validators ...Validator) MiddlewareWrapper { return "", fmt.Errorf(errorText) } - return runFn(cmd, args) + return runFn(ctx, cmd, args) } } } diff --git a/cli/cmd/resource_apply_cmd.go b/cli/cmd/resource_apply_cmd.go index fa91fb884f..2f9e902499 100644 --- a/cli/cmd/resource_apply_cmd.go +++ b/cli/cmd/resource_apply_cmd.go @@ -21,9 +21,8 @@ func init() { Short: "Apply resources", Long: "Apply (create/update) resources to your Tracetest server", PreRun: setupCommand(), - Run: WithResourceMiddleware(func(_ *cobra.Command, args []string) (string, error) { + Run: WithResourceMiddleware(func(ctx context.Context, _ *cobra.Command, args []string) (string, error) { resourceType := resourceParams.ResourceName - ctx := context.Background() resourceClient, err := resources.Get(resourceType) if err != nil { diff --git a/cli/cmd/resource_delete_cmd.go b/cli/cmd/resource_delete_cmd.go index 13fd1e1ee5..ab291527a6 100644 --- a/cli/cmd/resource_delete_cmd.go +++ b/cli/cmd/resource_delete_cmd.go @@ -21,9 +21,8 @@ func init() { Short: "Delete resources", Long: "Delete resources from your Tracetest server", PreRun: setupCommand(), - Run: WithResourceMiddleware(func(_ *cobra.Command, args []string) (string, error) { + Run: WithResourceMiddleware(func(ctx context.Context, _ *cobra.Command, args []string) (string, error) { resourceType := resourceParams.ResourceName - ctx := context.Background() resourceClient, err := resources.Get(resourceType) if err != nil { diff --git a/cli/cmd/resource_export_cmd.go b/cli/cmd/resource_export_cmd.go index cba48c3d7e..a9d33cefeb 100644 --- a/cli/cmd/resource_export_cmd.go +++ b/cli/cmd/resource_export_cmd.go @@ -21,9 +21,8 @@ func init() { Long: "Export a resource from your Tracetest server", Short: "Export resource", PreRun: setupCommand(), - Run: WithResourceMiddleware(func(_ *cobra.Command, args []string) (string, error) { + Run: WithResourceMiddleware(func(ctx context.Context, _ *cobra.Command, args []string) (string, error) { resourceType := resourceParams.ResourceName - ctx := context.Background() resourceClient, err := resources.Get(resourceType) if err != nil { diff --git a/cli/cmd/resource_get_cmd.go b/cli/cmd/resource_get_cmd.go index b10dece6d5..09760770f4 100644 --- a/cli/cmd/resource_get_cmd.go +++ b/cli/cmd/resource_get_cmd.go @@ -20,9 +20,8 @@ func init() { Short: "Get resource", Long: "Get a resource from your Tracetest server", PreRun: setupCommand(), - Run: WithResourceMiddleware(func(_ *cobra.Command, args []string) (string, error) { + Run: WithResourceMiddleware(func(ctx context.Context, _ *cobra.Command, args []string) (string, error) { resourceType := resourceParams.ResourceName - ctx := context.Background() resourceClient, err := resources.Get(resourceType) if err != nil { diff --git a/cli/cmd/resource_list_cmd.go b/cli/cmd/resource_list_cmd.go index 59f6bcb7d1..a2536b36b2 100644 --- a/cli/cmd/resource_list_cmd.go +++ b/cli/cmd/resource_list_cmd.go @@ -19,9 +19,8 @@ func init() { Short: "List resources", Long: "List resources from your Tracetest server", PreRun: setupCommand(), - Run: WithResourceMiddleware(func(_ *cobra.Command, args []string) (string, error) { + Run: WithResourceMiddleware(func(ctx context.Context, _ *cobra.Command, args []string) (string, error) { resourceType := resourceParams.ResourceName - ctx := context.Background() resourceClient, err := resources.Get(resourceType) if err != nil { diff --git a/cli/cmd/resource_run_cmd.go b/cli/cmd/resource_run_cmd.go index 39e3c1ffbe..1eb2022b4a 100644 --- a/cli/cmd/resource_run_cmd.go +++ b/cli/cmd/resource_run_cmd.go @@ -24,8 +24,7 @@ func init() { Short: "run resources", Long: "run resources", PreRun: setupCommand(WithOptionalResourceName()), - Run: WithResourceMiddleware(func(_ *cobra.Command, args []string) (string, error) { - ctx := context.Background() + Run: WithResourceMiddleware(func(ctx context.Context, _ *cobra.Command, args []string) (string, error) { resourceType, err := getResourceType(runParams, resourceParams) if err != nil { return "", err diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 72a1c3fc40..b73ad1d65f 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -31,10 +31,16 @@ var rootCmd = &cobra.Command{ } func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - ExitCLI(1) + handleRootExecErr(rootCmd.Execute()) +} + +func handleRootExecErr(err error) { + if err == nil { + ExitCLI(0) } + + fmt.Fprintln(os.Stderr, err) + ExitCLI(1) } func ExitCLI(errorCode int) { diff --git a/cli/cmd/start_cmd.go b/cli/cmd/start_cmd.go index d32095ee02..955ff48f07 100644 --- a/cli/cmd/start_cmd.go +++ b/cli/cmd/start_cmd.go @@ -4,14 +4,16 @@ import ( "context" "os" + "github.com/davecgh/go-spew/spew" agentConfig "github.com/kubeshop/tracetest/agent/config" "github.com/kubeshop/tracetest/agent/runner" "github.com/kubeshop/tracetest/agent/ui" + "github.com/kubeshop/tracetest/cli/config" "github.com/spf13/cobra" ) var ( - agentRunner = runner.NewRunner(configurator, resources, ui.DefaultUI) + agentRunner = runner.NewRunner(configurator.WithErrorHandler(handleError), resources, ui.DefaultUI) defaultToken = os.Getenv("TRACETEST_TOKEN") defaultEndpoint = os.Getenv("TRACETEST_SERVER_URL") defaultAPIKey = os.Getenv("TRACETEST_API_KEY") @@ -24,9 +26,7 @@ var startCmd = &cobra.Command{ Short: "Start Tracetest", Long: "Start using Tracetest", PreRun: setupCommand(SkipConfigValidation(), SkipVersionMismatchCheck()), - Run: WithResultHandler((func(_ *cobra.Command, _ []string) (string, error) { - ctx := context.Background() - + Run: WithResultHandler((func(ctx context.Context, _ *cobra.Command, _ []string) (string, error) { flags := agentConfig.Flags{ OrganizationID: saveParams.organizationID, EnvironmentID: saveParams.environmentID, @@ -37,6 +37,17 @@ var startCmd = &cobra.Command{ LogLevel: saveParams.logLevel, } + // override organization and environment id from context. + // this happens when auto rerunning the cmd after relogin + if orgID := config.ContextGetOrganizationID(ctx); orgID != "" { + flags.OrganizationID = orgID + } + if envID := config.ContextGetEnvironmentID(ctx); envID != "" { + flags.EnvironmentID = envID + } + + spew.Dump(flags) + cfg, err := agentConfig.LoadConfig() if err != nil { return "", err diff --git a/cli/cmd/version_cmd.go b/cli/cmd/version_cmd.go index 2df624019d..04026d6903 100644 --- a/cli/cmd/version_cmd.go +++ b/cli/cmd/version_cmd.go @@ -1,6 +1,8 @@ package cmd import ( + "context" + "github.com/spf13/cobra" ) @@ -10,7 +12,7 @@ var versionCmd = &cobra.Command{ Short: "Display this CLI tool version", Long: "Display this CLI tool version", PreRun: setupCommand(), - Run: WithResultHandler(func(_ *cobra.Command, _ []string) (string, error) { + Run: WithResultHandler(func(_ context.Context, _ *cobra.Command, _ []string) (string, error) { return versionText, nil }), PostRun: teardownCommand, diff --git a/cli/config/config.go b/cli/config/config.go index 86f1a77343..d95d5fe146 100644 --- a/cli/config/config.go +++ b/cli/config/config.go @@ -1,6 +1,7 @@ package config import ( + "context" "encoding/json" "fmt" "os" @@ -143,15 +144,45 @@ func ParseServerURL(serverURL string) (scheme, endpoint, serverPath string, err return url.Scheme, url.Host, url.Path, nil } -func Save(config Config) error { +type orgIDKeyType struct{} +type envIDKeyType struct{} + +var orgIDKey = orgIDKeyType{} +var envIDKey = envIDKeyType{} + +func ContextWithOrganizationID(ctx context.Context, orgID string) context.Context { + return context.WithValue(ctx, orgIDKey, orgID) +} + +func ContextWithEnvironmentID(ctx context.Context, envID string) context.Context { + return context.WithValue(ctx, envIDKey, envID) +} + +func ContextGetOrganizationID(ctx context.Context) string { + v := ctx.Value(orgIDKey) + if v == nil { + return "" + } + return v.(string) +} + +func ContextGetEnvironmentID(ctx context.Context) string { + v := ctx.Value(envIDKey) + if v == nil { + return "" + } + return v.(string) +} + +func Save(ctx context.Context, config Config) (context.Context, error) { configPath, err := GetConfigurationPath() if err != nil { - return fmt.Errorf("could not get configuration path: %w", err) + return ctx, fmt.Errorf("could not get configuration path: %w", err) } configYml, err := yaml.Marshal(config) if err != nil { - return fmt.Errorf("could not marshal configuration into yml: %w", err) + return ctx, fmt.Errorf("could not marshal configuration into yml: %w", err) } if _, err := os.Stat(configPath); os.IsNotExist(err) { @@ -159,10 +190,13 @@ func Save(config Config) error { } err = os.WriteFile(configPath, configYml, 0755) if err != nil { - return fmt.Errorf("could not write file: %w", err) + return ctx, fmt.Errorf("could not write file: %w", err) } - return nil + ctx = ContextWithOrganizationID(ctx, config.OrganizationID) + ctx = ContextWithEnvironmentID(ctx, config.EnvironmentID) + + return ctx, nil } func GetConfigurationPath() (string, error) { diff --git a/cli/config/configurator.go b/cli/config/configurator.go index aa695bf224..a74f73719b 100644 --- a/cli/config/configurator.go +++ b/cli/config/configurator.go @@ -20,6 +20,7 @@ type Configurator struct { resources *resourcemanager.Registry ui cliUI.UI onFinish onFinishFn + errorHandlerFn errorHandlerFn flags agentConfig.Flags finalServerURL string } @@ -34,6 +35,9 @@ func NewConfigurator(resources *resourcemanager.Registry) Configurator { ui.Success("Successfully configured Tracetest CLI") ui.Finish() }, + errorHandlerFn: func(ctx context.Context, err error) { + ui.Exit(err.Error()) + }, flags: agentConfig.Flags{}, } } @@ -43,6 +47,13 @@ func (c Configurator) WithOnFinish(onFinish onFinishFn) Configurator { return c } +type errorHandlerFn func(ctx context.Context, err error) + +func (c Configurator) WithErrorHandler(fn errorHandlerFn) Configurator { + c.errorHandlerFn = fn + return c +} + func (c Configurator) Start(ctx context.Context, prev *Config, flags agentConfig.Flags) error { c.flags = flags serverURL, err := c.getServerURL(prev, flags) @@ -67,7 +78,7 @@ func (c Configurator) Start(ctx context.Context, prev *Config, flags agentConfig } if flags.CI { - err = Save(cfg) + _, err = Save(ctx, cfg) if err != nil { return err } @@ -143,7 +154,7 @@ func (c Configurator) populateConfigWithVersionInfo(ctx context.Context, cfg Con serverType := version.GetType() if serverType == "oss" { - err := Save(cfg) + _, err = Save(ctx, cfg) if err != nil { return Config{}, fmt.Errorf("could not save configuration: %w", err), false } @@ -187,6 +198,10 @@ func (c Configurator) handleOAuth(ctx context.Context, cfg Config, prev *Config, return cfg, nil } + return c.ExecuteUserLogin(ctx, cfg) +} + +func (c Configurator) ExecuteUserLogin(ctx context.Context, cfg Config) (Config, error) { oauthServer := oauth.NewOAuthServer(cfg.OAuthEndpoint(), cfg.UIEndpoint) err := oauthServer.WithOnSuccess(c.onOAuthSuccess(ctx, cfg)). WithOnFailure(c.onOAuthFailure). @@ -195,7 +210,7 @@ func (c Configurator) handleOAuth(ctx context.Context, cfg Config, prev *Config, return Config{}, err } - return cfg, nil + return cfg, err } func (c Configurator) exchangeToken(cfg Config, token string) (Config, error) { @@ -245,7 +260,7 @@ func (c Configurator) onOAuthSuccess(ctx context.Context, cfg Config) func(token } func (c Configurator) onOAuthFailure(err error) { - c.ui.Exit(err.Error()) + c.errorHandlerFn(context.Background(), err) } func (c Configurator) ShowOrganizationSelector(ctx context.Context, cfg Config, flags agentConfig.Flags) { @@ -253,7 +268,7 @@ func (c Configurator) ShowOrganizationSelector(ctx context.Context, cfg Config, if cfg.OrganizationID == "" && flags.AgentApiKey == "" { orgID, err := c.organizationSelector(ctx, cfg) if err != nil { - c.ui.Exit(err.Error()) + c.errorHandlerFn(ctx, err) return } @@ -264,16 +279,16 @@ func (c Configurator) ShowOrganizationSelector(ctx context.Context, cfg Config, if cfg.EnvironmentID == "" && flags.AgentApiKey == "" { envID, err := c.environmentSelector(ctx, cfg) if err != nil { - c.ui.Exit(err.Error()) + c.errorHandlerFn(ctx, err) return } cfg.EnvironmentID = envID } - err := Save(cfg) + ctx, err := Save(ctx, cfg) if err != nil { - c.ui.Exit(err.Error()) + c.errorHandlerFn(ctx, err) return } diff --git a/cli/pkg/resourcemanager/client.go b/cli/pkg/resourcemanager/client.go index 0f3ba2c900..5e66d42d81 100644 --- a/cli/pkg/resourcemanager/client.go +++ b/cli/pkg/resourcemanager/client.go @@ -134,8 +134,9 @@ var ErrNotFound = RequestError{ } type RequestError struct { - Code int `json:"code"` - Message string `json:"error"` + Code int `json:"code"` + Message string `json:"error"` + IsAuthError bool `json:"isAuthError"` } type alternateRequestError struct { @@ -152,6 +153,10 @@ func (e RequestError) Is(target error) bool { return ok && t.Code == e.Code } +func isAuthError(resp *http.Response) bool { + return resp.StatusCode == http.StatusUnauthorized +} + func isSuccessResponse(resp *http.Response) bool { // successfull http status codes are 2xx return resp.StatusCode >= 200 && resp.StatusCode < 300 @@ -188,9 +193,9 @@ func parseRequestError(resp *http.Response, format Format) error { if err != nil { return fmt.Errorf("cannot parse response body: %w", err) } - return RequestError{ - Code: alternateReqError.Status, - Message: alternateReqError.Detail, + Code: alternateReqError.Status, + Message: alternateReqError.Detail, + IsAuthError: isAuthError(resp), } } diff --git a/go.mod b/go.mod index e481c05224..7ca83b22e2 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/fluidtruck/deepcopy v1.0.0 github.com/fsnotify/fsnotify v1.6.0 github.com/fullstorydev/grpcurl v1.8.6 + github.com/gdamore/tcell/v2 v2.7.0 github.com/goccy/go-yaml v1.11.0 github.com/gogo/protobuf v1.3.2 github.com/golang-jwt/jwt v3.2.1+incompatible @@ -49,6 +50,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/prometheus v1.8.2-0.20211217191541-41f1a8125e66 github.com/pterm/pterm v0.12.69 + github.com/rivo/tview v0.0.0-20240122063236-8526c9fe1b54 github.com/segmentio/analytics-go/v3 v3.2.1 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 @@ -113,7 +115,6 @@ require ( github.com/fatih/color v1.13.0 // indirect github.com/felixge/httpsnoop v1.0.2 // indirect github.com/gdamore/encoding v1.0.0 // indirect - github.com/gdamore/tcell/v2 v2.7.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-redis/redis/v7 v7.4.1 // indirect @@ -162,7 +163,6 @@ require ( github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/tview v0.0.0-20240122063236-8526c9fe1b54 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/segmentio/backo-go v1.0.0 // indirect diff --git a/go.sum b/go.sum index 890bb6d9ef..f4e712bba7 100644 --- a/go.sum +++ b/go.sum @@ -633,8 +633,6 @@ github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmx github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell/v2 v2.6.1-0.20231203215052-2917c3801e73 h1:SeDV6ZUSVlTAUUPdMzPXgMyj96z+whQJRRUff8dIeic= -github.com/gdamore/tcell/v2 v2.6.1-0.20231203215052-2917c3801e73/go.mod h1:pwzJMyH4Hd0AZMJkWQ+/g01dDvYWEvmJuaiRU71Xl8k= github.com/gdamore/tcell/v2 v2.7.0 h1:I5LiGTQuwrysAt1KS9wg1yFfOI3arI3ucFrxtd/xqaA= github.com/gdamore/tcell/v2 v2.7.0/go.mod h1:hl/KtAANGBecfIPxk+FzKvThTqI84oplgbPEmVX60b8= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= @@ -1345,7 +1343,6 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= @@ -2408,8 +2405,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2419,7 +2414,6 @@ golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2436,7 +2430,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=