From 574c835250aef27ae723ecaf99d331c1014975ef Mon Sep 17 00:00:00 2001 From: Filip Strozik Date: Tue, 14 May 2024 13:59:44 +0200 Subject: [PATCH] add more clierror wrapping --- go.mod | 4 +- go.sum | 14 ----- internal/btp/auth/credentials.go | 4 +- internal/btp/auth/xsuaa.go | 9 ++-- internal/btp/cis/provision.go | 5 +- internal/clierror/{cli_error.go => error.go} | 42 ++++++--------- .../{cli_error_test.go => error_test.go} | 0 internal/clierror/wrap.go | 13 +++++ internal/cmd/hana/check.go | 22 ++++---- internal/cmd/hana/credentials.go | 23 ++++---- internal/cmd/hana/delete.go | 5 +- internal/cmd/hana/map.go | 54 ++++++++----------- internal/cmd/hana/provision.go | 5 +- internal/cmd/provision/provision.go | 12 +++-- internal/kube/client.go | 5 +- internal/kube/service.go | 5 +- 16 files changed, 100 insertions(+), 122 deletions(-) rename internal/clierror/{cli_error.go => error.go} (82%) rename internal/clierror/{cli_error_test.go => error_test.go} (100%) create mode 100644 internal/clierror/wrap.go diff --git a/go.mod b/go.mod index 73e6e9769..88265248a 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( k8s.io/api v0.30.0 k8s.io/apimachinery v0.30.0 k8s.io/client-go v0.30.0 - sigs.k8s.io/controller-runtime v0.18.2 ) require ( @@ -27,7 +26,6 @@ require ( github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -53,6 +51,8 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect + github.com/onsi/ginkgo/v2 v2.17.1 // indirect + github.com/onsi/gomega v1.32.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect diff --git a/go.sum b/go.sum index 521e7fd4a..8bf781fe7 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,6 @@ github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxER github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gboddin/go-www-authenticate-parser v0.0.0-20230926203616-ec0b649bb077 h1:JvEO7eltd2aCHF+ABLquTUziO7hzC6G7H3tgENYkDBc= @@ -46,8 +44,6 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= -github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= @@ -172,15 +168,9 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= @@ -250,8 +240,6 @@ gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA= k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE= -k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs= -k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y= k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ= @@ -262,8 +250,6 @@ k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7F k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.18.2 h1:RqVW6Kpeaji67CY5nPEfRz6ZfFMk0lWQlNrLqlNpx+Q= -sigs.k8s.io/controller-runtime v0.18.2/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= diff --git a/internal/btp/auth/credentials.go b/internal/btp/auth/credentials.go index f14c0e489..9bde17c3a 100644 --- a/internal/btp/auth/credentials.go +++ b/internal/btp/auth/credentials.go @@ -49,13 +49,13 @@ type UAA struct { func LoadCISCredentials(path string) (*CISCredentials, error) { credentialsBytes, err := os.ReadFile(path) if err != nil { - return nil, &clierror.Error{Message: "failed to read credentials file", Details: err.Error(), Hints: []string{"Make sure the path to the credentials file is correct."}} + return nil, clierror.Wrap(err, &clierror.Error{Message: "failed to read credentials file", Hints: []string{"Make sure the path to the credentials file is correct."}}) } credentials := CISCredentials{} err = json.Unmarshal(credentialsBytes, &credentials) if err != nil { - return nil, &clierror.Error{Message: "failed to unmarshal file data", Details: err.Error(), Hints: []string{"Make sure the credentials file is in the correct format."}} + return nil, clierror.Wrap(err, &clierror.Error{Message: "failed to unmarshal file data", Hints: []string{"Make sure the credentials file is in the correct format."}}) } return &credentials, nil diff --git a/internal/btp/auth/xsuaa.go b/internal/btp/auth/xsuaa.go index a73372661..d388c2fba 100644 --- a/internal/btp/auth/xsuaa.go +++ b/internal/btp/auth/xsuaa.go @@ -35,7 +35,7 @@ func GetOAuthToken(grantType, serverURL, username, password string) (*XSUAAToken strings.NewReader(urlBody.Encode()), ) if err != nil { - return nil, &clierror.Error{Message: "failed to build request", Details: err.Error(), Hints: []string{"Make sure the server URL in the config is correct."}} + return nil, clierror.Wrap(err, &clierror.Error{Message: "failed to build request", Hints: []string{"Make sure the server URL in the config is correct."}}) } defer request.Body.Close() @@ -44,7 +44,7 @@ func GetOAuthToken(grantType, serverURL, username, password string) (*XSUAAToken response, err := http.DefaultClient.Do(request) if err != nil { - return nil, &clierror.Error{Message: "failed to get token from server", Details: err.Error()} + return nil, clierror.Wrap(err, &clierror.Error{Message: "failed to get token from server"}) } defer response.Body.Close() @@ -59,7 +59,7 @@ func decodeAuthSuccessResponse(response *http.Response) (*XSUAAToken, error) { token := XSUAAToken{} err := json.NewDecoder(response.Body).Decode(&token) if err != nil { - return nil, &clierror.Error{Message: fmt.Sprintf("failed to decode response with Status %s", response.Status), Details: err.Error()} + return nil, clierror.Wrap(err, &clierror.Error{Message: fmt.Sprintf("failed to decode response with Status %s", response.Status)}) } return &token, nil @@ -69,7 +69,8 @@ func decodeAuthErrorResponse(response *http.Response) error { errorData := xsuaaErrorResponse{} err := json.NewDecoder(response.Body).Decode(&errorData) if err != nil { - return &clierror.Error{Message: "failed to decode error response", Details: err.Error()} + return clierror.Wrap(err, &clierror.Error{Message: "failed to decode error response"}) } + // TODO: replace it with New func return &clierror.Error{Message: fmt.Sprintf("error response: %s", response.Status), Details: errorData.ErrorDescription} } diff --git a/internal/btp/cis/provision.go b/internal/btp/cis/provision.go index 8ea5a1604..98b59ee79 100644 --- a/internal/btp/cis/provision.go +++ b/internal/btp/cis/provision.go @@ -95,10 +95,7 @@ func decodeProvisionSuccessResponse(response *http.Response) (*ProvisionResponse provisionResponse := ProvisionResponse{} err := json.NewDecoder(response.Body).Decode(&provisionResponse) if err != nil { - return nil, &clierror.Error{ - Message: "failed to decode response", - Details: err.Error(), - } + return nil, clierror.Wrap(err, &clierror.Error{Message: "failed to decode response"}) } return &provisionResponse, nil diff --git a/internal/clierror/cli_error.go b/internal/clierror/error.go similarity index 82% rename from internal/clierror/cli_error.go rename to internal/clierror/error.go index 6d86d7dee..0c580a309 100644 --- a/internal/clierror/cli_error.go +++ b/internal/clierror/error.go @@ -10,6 +10,21 @@ type Error struct { Hints []string } +// Error returns the error string, compatible with the error interface +func (e Error) Error() string { + output := fmt.Sprintf("Error:\n %s\n\n", e.Message) + if e.Details != "" { + output += fmt.Sprintf("Error Details:\n %s\n\n", e.Details) + } + if len(e.Hints) > 0 { + output += "Hints:\n" + for _, hint := range e.Hints { + output += fmt.Sprintf(" - %s\n", hint) + } + } + return output +} + // Wrap adds a new message and hints to the error func (inside *Error) wrap(outside *Error) *Error { newError := &Error{ @@ -46,30 +61,3 @@ func wrapDetails(outside, inside string) string { } return fmt.Sprintf("%s: %s", outside, inside) } - -func Wrap(inside error, outside *Error) error { - if err, ok := inside.(*Error); ok { - return err.wrap(outside) - } else { - return &Error{ - Message: outside.Message, - Details: wrapDetails(outside.Details, inside.Error()), - Hints: outside.Hints, - } - } -} - -// Error returns the error string, compatible with the error interface -func (e Error) Error() string { - output := fmt.Sprintf("Error:\n %s\n\n", e.Message) - if e.Details != "" { - output += fmt.Sprintf("Error Details:\n %s\n\n", e.Details) - } - if len(e.Hints) > 0 { - output += "Hints:\n" - for _, hint := range e.Hints { - output += fmt.Sprintf(" - %s\n", hint) - } - } - return output -} diff --git a/internal/clierror/cli_error_test.go b/internal/clierror/error_test.go similarity index 100% rename from internal/clierror/cli_error_test.go rename to internal/clierror/error_test.go diff --git a/internal/clierror/wrap.go b/internal/clierror/wrap.go new file mode 100644 index 000000000..b5190eb64 --- /dev/null +++ b/internal/clierror/wrap.go @@ -0,0 +1,13 @@ +package clierror + +func Wrap(inside error, outside *Error) error { + if err, ok := inside.(*Error); ok { + return err.wrap(outside) + } else { + return &Error{ + Message: outside.Message, + Details: wrapDetails(outside.Details, inside.Error()), + Hints: outside.Hints, + } + } +} diff --git a/internal/cmd/hana/check.go b/internal/cmd/hana/check.go index 4bb143653..2690ba257 100644 --- a/internal/cmd/hana/check.go +++ b/internal/cmd/hana/check.go @@ -89,21 +89,23 @@ func checkHanaBindingUrl(config *hanaCheckConfig) error { func handleCheckResponse(u *unstructured.Unstructured, err error, printedName, namespace, name string) error { if err != nil { - return &clierror.Error{ - Message: "failed to get resource data", - Details: err.Error(), - Hints: []string{ - "Make sure that Hana was provisioned.", + return clierror.Wrap(err, + &clierror.Error{ + Message: "failed to get resource data", + Hints: []string{ + "Make sure that Hana was provisioned.", + }, }, - } + ) } ready, error := kube.IsReady(u) if error != nil { - return &clierror.Error{ - Message: "failed to check readiness of Hana resources", - Details: error.Error(), - } + return clierror.Wrap(err, + &clierror.Error{ + Message: "failed to check readiness of Hana resources", + }, + ) } if !ready { fmt.Printf("%s is not ready (%s/%s).\n", printedName, namespace, name) diff --git a/internal/cmd/hana/credentials.go b/internal/cmd/hana/credentials.go index 8ee7c885a..c51229c8b 100644 --- a/internal/cmd/hana/credentials.go +++ b/internal/cmd/hana/credentials.go @@ -89,17 +89,18 @@ func getHanaCredentials(config *hanaCredentialsConfig) (credentials, error) { } func handleGetHanaCredentialsError(err error) (credentials, error) { - error := &clierror.Error{ - Message: "failed to get Hana credentails", - Details: err.Error(), - Hints: []string{ - "Make sure that Hana is run and ready to use. You can use command 'kyma hana check'.", - }, + hints := []string{ + "Make sure that Hana is run and ready to use. You can use command 'kyma hana check'.", } - if error.Details == "Unauthorized" { - error.Hints = []string{ - "Make sure that your kubeconfig has access to kubernetes.", - } + + if err.Error() == "Unauthorized" { + hints = append(hints, "Make sure that your kubeconfig has access to kubernetes.") } - return credentials{}, error + + credErr := clierror.Wrap(err, &clierror.Error{ + Message: "failed to get Hana credentails", + Hints: hints, + }) + + return credentials{}, credErr } diff --git a/internal/cmd/hana/delete.go b/internal/cmd/hana/delete.go index 9530c2190..20ec7e394 100644 --- a/internal/cmd/hana/delete.go +++ b/internal/cmd/hana/delete.go @@ -99,8 +99,7 @@ func handleDeleteResponse(err error, printedName, namespace, name string) error fmt.Printf("%s (%s/%s) not found.\n", printedName, namespace, name) return nil } - return &clierror.Error{ + return clierror.Wrap(err, &clierror.Error{ Message: "failed to delete Hana resource.", - Details: err.Error(), - } + }) } diff --git a/internal/cmd/hana/map.go b/internal/cmd/hana/map.go index 0f499fc9c..09dda58f7 100644 --- a/internal/cmd/hana/map.go +++ b/internal/cmd/hana/map.go @@ -94,11 +94,11 @@ func createHanaAPIBindingIfNeeded(config *hanaCheckConfig) error { func createHanaAPIInstance(config *hanaCheckConfig) error { data, err := hanaAPIInstance(config) if err != nil { - return &clierror.Error{ + return clierror.Wrap(err, &clierror.Error{ Message: "failed to create Hana API instance object", - Details: err.Error(), - } + }) } + _, err = config.KubeClient.Dynamic().Resource(operator.GVRServiceInstance). Namespace(config.namespace). Create(config.Ctx, data, metav1.CreateOptions{}) @@ -108,10 +108,9 @@ func createHanaAPIInstance(config *hanaCheckConfig) error { func createHanaAPIBinding(config *hanaCheckConfig) error { data, err := hanaAPIBinding(config) if err != nil { - return &clierror.Error{ + return clierror.Wrap(err, &clierror.Error{ Message: "failed to create Hana API binding object", - Details: err.Error(), - } + }) } _, err = config.KubeClient.Dynamic().Resource(operator.GVRServiceBinding). Namespace(config.namespace). @@ -198,10 +197,9 @@ func createHanaInstanceMapping(config *hanaCheckConfig) error { func getClusterID(config *hanaCheckConfig) (string, error) { cm, err := config.KubeClient.Static().CoreV1().ConfigMaps("kyma-system").Get(config.Ctx, "sap-btp-operator-config", metav1.GetOptions{}) if err != nil { - return "", &clierror.Error{ + return "", clierror.Wrap(err, &clierror.Error{ Message: "failed to get cluster ID", - Details: err.Error(), - } + }) } return cm.Data["CLUSTER_ID"], nil } @@ -224,17 +222,15 @@ func getHanaID(config *hanaCheckConfig) (string, error) { Namespace(config.namespace). Get(config.Ctx, config.name, metav1.GetOptions{}) if err != nil { - return "", &clierror.Error{ + return "", clierror.Wrap(err, &clierror.Error{ Message: "failed to get Hana instance", - Details: err.Error(), - } + }) } status, err := kube.GetServiceStatus(u) if err != nil { - return "", &clierror.Error{ + return "", clierror.Wrap(err, &clierror.Error{ Message: "failed to read resource data", - Details: err.Error(), - } + }) } return status.InstanceID, nil @@ -260,16 +256,14 @@ func readHanaAPISecret(config *hanaCheckConfig) (string, *auth.UAA, error) { fmt.Println("Failed") return "", nil, clierror.Wrap(err, &clierror.Error{ Message: "timeout while waiting for Hana API binding", - Details: err.Error(), }) } fmt.Println("done") secret, err := config.KubeClient.Static().CoreV1().Secrets(config.namespace).Get(config.Ctx, hanaBindingAPIName(config.name), metav1.GetOptions{}) if err != nil { - return "", nil, &clierror.Error{ + return "", nil, clierror.Wrap(err, &clierror.Error{ Message: "failed to get secret", - Details: err.Error(), - } + }) } baseURL := secret.Data["baseurl"] uaaData := secret.Data["uaa"] @@ -277,10 +271,9 @@ func readHanaAPISecret(config *hanaCheckConfig) (string, *auth.UAA, error) { uaa := &auth.UAA{} err = json.Unmarshal(uaaData, uaa) if err != nil { - return "", nil, &clierror.Error{ + return "", nil, clierror.Wrap(err, &clierror.Error{ Message: "failed to decode UAA data", - Details: err.Error(), - } + }) } return string(baseURL), uaa, nil } @@ -295,27 +288,24 @@ func hanaInstanceMapping(baseURL, clusterID, hanaID, token string) error { requestString, err := json.Marshal(requestData) if err != nil { - return &clierror.Error{ + return clierror.Wrap(err, &clierror.Error{ Message: "failed to create mapping request", - Details: err.Error(), - } + }) } request, err := http.NewRequest("POST", fmt.Sprintf("https://%s/inventory/v2/serviceInstances/%s/instanceMappings", baseURL, hanaID), bytes.NewBuffer(requestString)) if err != nil { - return &clierror.Error{ + return clierror.Wrap(err, &clierror.Error{ Message: "failed to create mapping request", - Details: err.Error(), - } + }) } request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token)) resp, err := client.Do(request) if err != nil { - return &clierror.Error{ - Message: "failed to create mapping", - Details: err.Error(), - } + return clierror.Wrap(err, &clierror.Error{ + Message:"failed to create mapping", + }) } // server sends status Created when mapping is created, and 200 if it already exists diff --git a/internal/cmd/hana/provision.go b/internal/cmd/hana/provision.go index bb2e18764..140c8ee6b 100644 --- a/internal/cmd/hana/provision.go +++ b/internal/cmd/hana/provision.go @@ -103,10 +103,9 @@ func handleProvisionResponse(err error, printedName, namespace, name string) err fmt.Printf("Created %s (%s/%s).\n", printedName, namespace, name) return nil } - return &clierror.Error{ + return clierror.Wrap(err, &clierror.Error{ Message: "failed to provision Hana resource", - Details: err.Error(), - } + }) } func hanaInstance(config *hanaProvisionConfig) *unstructured.Unstructured { diff --git a/internal/cmd/provision/provision.go b/internal/cmd/provision/provision.go index 5f55cea34..907e1571a 100644 --- a/internal/cmd/provision/provision.go +++ b/internal/cmd/provision/provision.go @@ -61,11 +61,15 @@ func runProvision(config *provisionConfig) error { credentials.UAA.ClientSecret, ) if err != nil { - retErr := clierror.Wrap(err, &clierror.Error{Message: "failed to get access token"}) - if strings.Contains(retErr.(*clierror.Error).Details, "Internal Server Error") { - retErr.(*clierror.Error).Hints = append(retErr.(*clierror.Error).Hints, "check if CIS grant type is set to client credentials") + hints := []string{} + if strings.Contains(err.Error(), "Internal Server Error") { + hints = append(hints, "check if CIS grant type is set to client credentials") } - return retErr + + return clierror.Wrap(err, &clierror.Error{ + Message: "failed to get access token", + Hints: hints, + }) } // TODO: maybe we should pass only credentials.Endpoints? diff --git a/internal/kube/client.go b/internal/kube/client.go index 489af9290..74a301506 100644 --- a/internal/kube/client.go +++ b/internal/kube/client.go @@ -28,13 +28,12 @@ type client struct { func NewClient(kubeconfig string) (Client, error) { client, err := newClient(kubeconfig) if err != nil { - return nil, &clierror.Error{ + return nil, clierror.Wrap(err, &clierror.Error{ Message: "failed to initialise kubernetes client", - Details: err.Error(), Hints: []string{ "Make sure that kubeconfig is proper.", }, - } + }) } return client, nil } diff --git a/internal/kube/service.go b/internal/kube/service.go index 27c332aad..ca8672bc3 100644 --- a/internal/kube/service.go +++ b/internal/kube/service.go @@ -25,10 +25,9 @@ type Status struct { func GetServiceStatus(u *unstructured.Unstructured) (Status, error) { instance := somethingWithStatus{} if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &instance); err != nil { - return Status{}, &clierror.Error{ + return Status{}, clierror.Wrap(err, &clierror.Error{ Message: "failed to read resource data", - Details: err.Error(), - } + }) } return instance.Status, nil