From f92606ab96be66754b84d3f4f75d378eda55001e Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora <54686422+LeelaChacha@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:11:16 +0200 Subject: [PATCH] module command: Add Error Code for Kyma Warning State (#1692) * module command: Add Error Code for Kyma Warning State * Fix Linting Issues --- cmd/kyma/alpha/disable/module/module.go | 6 +-- cmd/kyma/alpha/enable/module/module.go | 2 +- cmd/kyma/alpha/enable/module/module_test.go | 4 +- cmd/main.go | 3 +- go.mod | 2 +- go.sum | 4 +- internal/cli/alpha/module/errors.go | 5 +++ internal/cli/alpha/module/module.go | 2 + internal/cli/exit_code.go | 48 ++++++++++++++++++++ internal/cli/exit_code_test.go | 50 +++++++++++++++++++++ 10 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 internal/cli/alpha/module/errors.go create mode 100644 internal/cli/exit_code.go create mode 100644 internal/cli/exit_code_test.go diff --git a/cmd/kyma/alpha/disable/module/module.go b/cmd/kyma/alpha/disable/module/module.go index 6c6e37874..33a2448bd 100644 --- a/cmd/kyma/alpha/disable/module/module.go +++ b/cmd/kyma/alpha/disable/module/module.go @@ -139,10 +139,8 @@ func (cmd *command) run(ctx context.Context, l *zap.SugaredLogger, moduleName st if cmd.opts.Wait { waitStep := cmd.NewStep("Waiting for Kyma to become Ready") - if err = moduleInteractor.WaitUntilReady( - ctx, - ); err != nil { - waitStep.Failuref("Kyma did not get Ready") + if err = moduleInteractor.WaitUntilReady(ctx); err != nil { + waitStep.Failuref("kyma did not get ready: %s", err) return err } waitStep.Successf("Kyma is Ready") diff --git a/cmd/kyma/alpha/enable/module/module.go b/cmd/kyma/alpha/enable/module/module.go index aedcf9df1..be2c76f71 100644 --- a/cmd/kyma/alpha/enable/module/module.go +++ b/cmd/kyma/alpha/enable/module/module.go @@ -148,7 +148,7 @@ func (cmd *command) run(ctx context.Context, l *zap.SugaredLogger, moduleName st if cmd.opts.Wait { waitStep := cmd.NewStep("Waiting for Kyma to become Ready") if err = moduleInteractor.WaitUntilReady(ctx); err != nil { - waitStep.Failuref("Kyma did not get Ready") + waitStep.Failuref("kyma did not get ready: %s", err) return err } waitStep.Successf("Kyma is Ready") diff --git a/cmd/kyma/alpha/enable/module/module_test.go b/cmd/kyma/alpha/enable/module/module_test.go index 0267ad07b..9a3563dbb 100644 --- a/cmd/kyma/alpha/enable/module/module_test.go +++ b/cmd/kyma/alpha/enable/module/module_test.go @@ -19,13 +19,13 @@ func TestChannelValidation(t *testing.T) { ControllerName: "-", Channel: "fast", CustomResourcePolicy: "-", - }, unstructured.Unstructured{}, false) + }, unstructured.Unstructured{}, false, false, false) template2, _ := testutils.ModuleTemplateFactory(v1beta2.Module{ Name: "not-test", ControllerName: "-", Channel: "alpha", CustomResourcePolicy: "-", - }, unstructured.Unstructured{}, false) + }, unstructured.Unstructured{}, false, false, false) allTemplates := v1beta2.ModuleTemplateList{ TypeMeta: metav1.TypeMeta{}, ListMeta: metav1.ListMeta{}, diff --git a/cmd/main.go b/cmd/main.go index 4aee24518..bc552736c 100755 --- a/cmd/main.go +++ b/cmd/main.go @@ -11,7 +11,8 @@ func main() { command := kyma.NewCmd(cli.NewOptions()) err := command.Execute() + if err != nil { - os.Exit(1) + os.Exit(cli.GetExitCode(err)) } } diff --git a/go.mod b/go.mod index 677ba9741..f029dd6fe 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/kyma-incubator/reconciler v0.0.0-20230630093527-31217ab6a174 github.com/kyma-project/hydroform/function v0.0.0-20230628151226-25b31247e585 github.com/kyma-project/hydroform/provision v0.0.0-20230418133637-1ea26b368bb6 - github.com/kyma-project/lifecycle-manager v0.0.0-20230515084114-0cd8e8e80748 + github.com/kyma-project/lifecycle-manager v0.0.0-20230626125722-e28fc6438d83 github.com/mandelsoft/vfs v0.0.0-20220805210647-bf14a11bfe31 github.com/open-component-model/ocm v0.3.0-rc.1 github.com/opencontainers/go-digest v1.0.0 diff --git a/go.sum b/go.sum index b61966ddf..3f14c16a6 100644 --- a/go.sum +++ b/go.sum @@ -1181,8 +1181,8 @@ github.com/kyma-project/hydroform/provision v0.0.0-20230418133637-1ea26b368bb6 h github.com/kyma-project/hydroform/provision v0.0.0-20230418133637-1ea26b368bb6/go.mod h1:eXIZaENQU/Y4sq20z3AgiFg6hSZUP4DmQ2JTMtFt+A8= github.com/kyma-project/istio/operator v0.0.0-20221129102055-d37c5c8e6add h1:ohTtnIlNXSQPHB/nMZvBXs+uBnTqQ6HRSgAvptyWzlc= github.com/kyma-project/istio/operator v0.0.0-20221129102055-d37c5c8e6add/go.mod h1:K5jDoHdqW8EI2vXX+7J+RnEmk4YQRnd6fTmuuSyQ3Qg= -github.com/kyma-project/lifecycle-manager v0.0.0-20230515084114-0cd8e8e80748 h1:9XdRAm5obA1/cHdrstolxz0TwxZdmgTyTw31oPrjTHQ= -github.com/kyma-project/lifecycle-manager v0.0.0-20230515084114-0cd8e8e80748/go.mod h1:G+HHF0oOUQYQ8g2VNvpYe1wreR42ri/upK3lj5D4J2c= +github.com/kyma-project/lifecycle-manager v0.0.0-20230626125722-e28fc6438d83 h1:kA6QUuA6oSOQe9F0gW2e8x4dGRdol9UAsw8zPIUKswo= +github.com/kyma-project/lifecycle-manager v0.0.0-20230626125722-e28fc6438d83/go.mod h1:mik/72CzndvOf8OH11a+CGufl2Ua6Lqk8HIUet3u7To= github.com/kyma-project/module-manager/operator v0.0.0-20221020113457-620af4f4b365 h1:50FLPAynQ7++CJb2ZEdfnCRO68cDcJoa+eo3qUwElc4= github.com/kyma-project/module-manager/operator v0.0.0-20221020113457-620af4f4b365/go.mod h1:N0kmS8pTNXq+7/Bdr6vfogmw03H+uYMCauTQ6U6+kA0= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= diff --git a/internal/cli/alpha/module/errors.go b/internal/cli/alpha/module/errors.go new file mode 100644 index 000000000..345822a81 --- /dev/null +++ b/internal/cli/alpha/module/errors.go @@ -0,0 +1,5 @@ +package module + +import "errors" + +var ErrKymaInWarningState = errors.New("kyma CR in warning state error") diff --git a/internal/cli/alpha/module/module.go b/internal/cli/alpha/module/module.go index 297c2e9d5..dfc6b8e50 100644 --- a/internal/cli/alpha/module/module.go +++ b/internal/cli/alpha/module/module.go @@ -185,6 +185,8 @@ func IsKymaReady(l *zap.SugaredLogger, obj runtime.Object) error { ) } return nil + case v1beta2.StateWarning: + return ErrKymaInWarningState default: lastOperation := kyma.Status.LastOperation if lastOperation.Operation == "" { diff --git a/internal/cli/exit_code.go b/internal/cli/exit_code.go new file mode 100644 index 000000000..c45618b43 --- /dev/null +++ b/internal/cli/exit_code.go @@ -0,0 +1,48 @@ +package cli + +import ( + "github.com/avast/retry-go" + "github.com/kyma-project/cli/internal/cli/alpha/module" + "github.com/pkg/errors" +) + +var ErrorCodeMap = map[error]int{ + module.ErrKymaInWarningState: 2, +} + +func GetExitCode(err error) int { + switch err := err.(type) { + default: + return handleSingleError(err) + case retry.Error: + return handleListOfErrors(err) + } +} + +func handleSingleError(err error) int { + if errorCode, found := mapNestedErrorToCode(err); found { + return errorCode + } + return 1 +} + +func handleListOfErrors(errorList retry.Error) int { + for _, err := range errorList { + if errorCode, found := mapNestedErrorToCode(err); found { + return errorCode + } + } + return 1 +} + +func mapNestedErrorToCode(err error) (int, bool) { + for { + if errorCode, ok := ErrorCodeMap[err]; ok { + return errorCode, true + } + err = errors.Unwrap(err) + if err == nil { + return -1, false + } + } +} diff --git a/internal/cli/exit_code_test.go b/internal/cli/exit_code_test.go new file mode 100644 index 000000000..12aefc382 --- /dev/null +++ b/internal/cli/exit_code_test.go @@ -0,0 +1,50 @@ +package cli + +import ( + "errors" + "fmt" + "github.com/avast/retry-go" + "github.com/kyma-project/cli/internal/cli/alpha/module" + "testing" +) + +func TestGetExitCode(t *testing.T) { + tests := []struct { + name string + err error + want int + }{ + { + name: "correct exit code for single error", + err: module.ErrKymaInWarningState, + want: ErrorCodeMap[module.ErrKymaInWarningState], + }, + { + name: "correct exit code for wrapped error", + err: fmt.Errorf("wrapped error 2: %w", + fmt.Errorf("wrapped error 1: %w", + module.ErrKymaInWarningState)), + want: ErrorCodeMap[module.ErrKymaInWarningState], + }, + { + name: "correct exit code for error in a list", + err: retry.Error([]error{ + errors.New("random non-mapped error"), + module.ErrKymaInWarningState, + }), + want: ErrorCodeMap[module.ErrKymaInWarningState], + }, + { + name: "default exit code for non-mapped error", + err: errors.New("random non-mapped error"), + want: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := GetExitCode(tt.err); got != tt.want { + t.Errorf("GetExitCode() = %v, want %v", got, tt.want) + } + }) + } +}