Skip to content

Commit

Permalink
implement own clierror interface
Browse files Browse the repository at this point in the history
  • Loading branch information
pPrecel committed May 15, 2024
1 parent 604328c commit d0fce7d
Show file tree
Hide file tree
Showing 27 changed files with 174 additions and 158 deletions.
2 changes: 1 addition & 1 deletion internal/btp/auth/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type UAA struct {
ZoneID string `json:"zoneid"`
}

func LoadCISCredentials(path string) (*CISCredentials, error) {
func LoadCISCredentials(path string) (*CISCredentials, clierror.Error) {
credentialsBytes, err := os.ReadFile(path)
if err != nil {
return nil, clierror.Wrap(err, clierror.Message("failed to read credentials file"), clierror.Hints("Make sure the path to the credentials file is correct."))
Expand Down
12 changes: 6 additions & 6 deletions internal/btp/auth/credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ func TestLoadCISCredentials(t *testing.T) {
err := os.WriteFile(filename, []byte(correctCredentials), os.ModePerm)
require.NoError(t, err)

credentials, err := LoadCISCredentials(filename)
require.Nil(t, err)
credentials, cliError := LoadCISCredentials(filename)
require.Nil(t, cliError)
require.Equal(t, correctCredentialsStruct, *credentials)
})

Expand All @@ -51,16 +51,16 @@ func TestLoadCISCredentials(t *testing.T) {
err := os.WriteFile(filename, []byte("\n{\n"), os.ModePerm)
require.NoError(t, err)

credentials, err := LoadCISCredentials(filename)
require.Error(t, err)
credentials, cliError := LoadCISCredentials(filename)
require.NotNil(t, cliError)
require.Nil(t, credentials)
})

t.Run("incorrect credentials file error", func(t *testing.T) {
filename := fmt.Sprintf("%s/doesnotexist-creds.txt", tmpDirPath)

credentials, err := LoadCISCredentials(filename)
require.Error(t, err)
credentials, cliError := LoadCISCredentials(filename)
require.NotNil(t, cliError)
require.Nil(t, credentials)
})
}
10 changes: 4 additions & 6 deletions internal/btp/auth/xsuaa.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package auth

import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
Expand All @@ -26,7 +25,7 @@ type XSUAAToken struct {
JTI string `json:"jti"`
}

func GetOAuthToken(grantType, serverURL, username, password string) (*XSUAAToken, error) {
func GetOAuthToken(grantType, serverURL, username, password string) (*XSUAAToken, clierror.Error) {
urlBody := url.Values{}
urlBody.Set("grant_type", grantType)

Expand Down Expand Up @@ -56,7 +55,7 @@ func GetOAuthToken(grantType, serverURL, username, password string) (*XSUAAToken
return decodeAuthSuccessResponse(response)
}

func decodeAuthSuccessResponse(response *http.Response) (*XSUAAToken, error) {
func decodeAuthSuccessResponse(response *http.Response) (*XSUAAToken, clierror.Error) {
token := XSUAAToken{}
err := json.NewDecoder(response.Body).Decode(&token)
if err != nil {
Expand All @@ -66,12 +65,11 @@ func decodeAuthSuccessResponse(response *http.Response) (*XSUAAToken, error) {
return &token, nil
}

func decodeAuthErrorResponse(response *http.Response) error {
func decodeAuthErrorResponse(response *http.Response) clierror.Error {
errorData := xsuaaErrorResponse{}
err := json.NewDecoder(response.Body).Decode(&errorData)
if err != nil {
return clierror.Wrap(err, clierror.Message("failed to decode error response"))
}
// TODO: replace it with New func
return clierror.Wrap(errors.New(errorData.ErrorDescription), clierror.MessageF("error response: %s", response.Status))
return clierror.Wrap(errorData.ErrorDescription, clierror.MessageF("error response: %s", response.Status))
}
2 changes: 1 addition & 1 deletion internal/btp/auth/xsuaa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestGetOAuthToken(t *testing.T) {
name string
credentials *CISCredentials
want *XSUAAToken
expectedErr error
expectedErr clierror.Error
}{
{
name: "Correct credentials",
Expand Down
4 changes: 2 additions & 2 deletions internal/btp/cis/provision.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type ProvisionResponse struct {
PlanName string `json:"planName"`
}

func (c *LocalClient) Provision(pe *ProvisionEnvironment) (*ProvisionResponse, error) {
func (c *LocalClient) Provision(pe *ProvisionEnvironment) (*ProvisionResponse, clierror.Error) {
reqData, err := json.Marshal(pe)
if err != nil {
return nil, clierror.New(clierror.Message(err.Error()))
Expand Down Expand Up @@ -91,7 +91,7 @@ func (c *LocalClient) Provision(pe *ProvisionEnvironment) (*ProvisionResponse, e
return decodeProvisionSuccessResponse(response)
}

func decodeProvisionSuccessResponse(response *http.Response) (*ProvisionResponse, error) {
func decodeProvisionSuccessResponse(response *http.Response) (*ProvisionResponse, clierror.Error) {
provisionResponse := ProvisionResponse{}
err := json.NewDecoder(response.Body).Decode(&provisionResponse)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/btp/cis/provision_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestCISClient_Provision(t *testing.T) {
token *auth.XSUAAToken
pe *ProvisionEnvironment
wantedResponse *ProvisionResponse
expectedErr error
expectedErr clierror.Error
}{
{
name: "Correct data",
Expand Down
14 changes: 14 additions & 0 deletions internal/clierror/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package clierror

import (
"fmt"
"os"
)

// Check prints error and executes os.Exit(1) if the error is not nil
func Check(err Error) {
if err != nil {
fmt.Println(err.String())
os.Exit(1)
}
}
12 changes: 10 additions & 2 deletions internal/clierror/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@ import (
"fmt"
)

type Error interface {
String() string
}

type clierror struct {
message string
details string
hints []string
}

// New creates a new error with the given modifiers
func New(modifiers ...modifier) *clierror {
func New(modifiers ...modifier) Error {
return new(modifiers...)
}

func new(modifiers ...modifier) *clierror {
err := &clierror{}
for _, m := range modifiers {
m(err)
Expand All @@ -20,7 +28,7 @@ func New(modifiers ...modifier) *clierror {
}

// Error returns the error string, compatible with the error interface
func (e clierror) Error() string {
func (e *clierror) String() 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)
Expand Down
4 changes: 2 additions & 2 deletions internal/clierror/error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func Test_CLIError_String(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, tt.err.Error())
assert.Equal(t, tt.want, tt.err.String())
})
}
}
Expand Down Expand Up @@ -157,7 +157,7 @@ func Test_CLIError_Wrap(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.err.wrap(tt.outside)
assert.Equal(t, tt.want, err.Error())
assert.Equal(t, tt.want, err.String())
})
}
}
7 changes: 4 additions & 3 deletions internal/clierror/wrap.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package clierror

func Wrap(inside error, modifiers ...modifier) error {
func Wrap(inside any, modifiers ...modifier) Error {
if err, ok := inside.(*clierror); ok {
return err.wrap(New(modifiers...))
return err.wrap(new(modifiers...))
}

return New(Message(inside.Error())).wrap(New(modifiers...))
// convert any type of inside error to a string
return new(MessageF("%v", inside)).wrap(new(modifiers...))
}
12 changes: 9 additions & 3 deletions internal/clierror/wrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,22 @@ import (
func Test_Wrap(t *testing.T) {
tests := []struct {
name string
inside error
inside any
outside []modifier
want string
}{
{
name: "Wrap string error",
name: "Wrap basic error",
inside: fmt.Errorf("error"),
outside: []modifier{Message("outside"), Hints("hint1", "hint2")},
want: "Error:\n outside\n\nError Details:\n error\n\nHints:\n - hint1\n - hint2\n",
},
{
name: "Wrap string error",
inside: "error",
outside: []modifier{Message("outside"), Hints("hint1", "hint2")},
want: "Error:\n outside\n\nError Details:\n error\n\nHints:\n - hint1\n - hint2\n",
},
{
name: "Wrap Error",
inside: &clierror{message: "error", details: "details", hints: []string{"hint1", "hint2"}},
Expand Down Expand Up @@ -54,7 +60,7 @@ func Test_Wrap(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := Wrap(tt.inside, tt.outside...)
assert.Equal(t, tt.want, err.Error())
assert.Equal(t, tt.want, err.String())
})
}
}
14 changes: 7 additions & 7 deletions internal/cmd/access/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package access

import (
"fmt"
"github.com/kyma-project/cli.v3/internal/clierror"
"k8s.io/apimachinery/pkg/api/errors"

"github.com/kyma-project/cli.v3/internal/clierror"
"github.com/kyma-project/cli.v3/internal/cmdcommon"
"github.com/spf13/cobra"
v1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
Expand All @@ -34,11 +34,11 @@ func NewAccessCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
Use: "access",
Short: "Enrich kubeconfig with access",
Long: "Enrich kubeconfig with Service Account based token and certificate",
PreRunE: func(_ *cobra.Command, args []string) error {
return cfg.KubeClientConfig.Complete()
PreRun: func(_ *cobra.Command, args []string) {
clierror.Check(cfg.KubeClientConfig.Complete())
},
RunE: func(cmd *cobra.Command, args []string) error {
return runAccess(&cfg)
Run: func(cmd *cobra.Command, args []string) {
clierror.Check(runAccess(&cfg))
},
}

Expand All @@ -55,7 +55,7 @@ func NewAccessCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
return cmd
}

func runAccess(cfg *accessConfig) error {
func runAccess(cfg *accessConfig) clierror.Error {
// Create objects
err := createObjects(cfg)
if err != nil {
Expand Down
20 changes: 10 additions & 10 deletions internal/cmd/hana/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ func NewHanaCheckCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
Use: "check",
Short: "Check if the Hana instance is provisioned.",
Long: "Use this command to check if the Hana instance is provisioned on the SAP Kyma platform.",
PreRunE: func(_ *cobra.Command, args []string) error {
return config.KubeClientConfig.Complete()
PreRun: func(_ *cobra.Command, args []string) {
clierror.Check(config.KubeClientConfig.Complete())
},
RunE: func(_ *cobra.Command, _ []string) error {
return runCheck(&config)
Run: func(_ *cobra.Command, _ []string) {
clierror.Check(runCheck(&config))
},
}

Expand All @@ -50,14 +50,14 @@ func NewHanaCheckCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
}

var (
checkCommands = []func(config *hanaCheckConfig) error{
checkCommands = []func(config *hanaCheckConfig) clierror.Error{
checkHanaInstance,
checkHanaBinding,
checkHanaBindingUrl,
}
)

func runCheck(config *hanaCheckConfig) error {
func runCheck(config *hanaCheckConfig) clierror.Error {
fmt.Printf("Checking Hana (%s/%s).\n", config.namespace, config.name)

for _, command := range checkCommands {
Expand All @@ -71,23 +71,23 @@ func runCheck(config *hanaCheckConfig) error {
return nil
}

func checkHanaInstance(config *hanaCheckConfig) error {
func checkHanaInstance(config *hanaCheckConfig) clierror.Error {
u, err := kube.GetServiceInstance(config.KubeClient, config.Ctx, config.namespace, config.name)
return handleCheckResponse(u, err, "Hana instance", config.namespace, config.name)
}

func checkHanaBinding(config *hanaCheckConfig) error {
func checkHanaBinding(config *hanaCheckConfig) clierror.Error {
u, err := kube.GetServiceBinding(config.KubeClient, config.Ctx, config.namespace, config.name)
return handleCheckResponse(u, err, "Hana binding", config.namespace, config.name)
}

func checkHanaBindingUrl(config *hanaCheckConfig) error {
func checkHanaBindingUrl(config *hanaCheckConfig) clierror.Error {
urlName := hanaBindingUrlName(config.name)
u, err := kube.GetServiceBinding(config.KubeClient, config.Ctx, config.namespace, urlName)
return handleCheckResponse(u, err, "Hana URL binding", config.namespace, urlName)
}

func handleCheckResponse(u *unstructured.Unstructured, err error, printedName, namespace, name string) error {
func handleCheckResponse(u *unstructured.Unstructured, err error, printedName, namespace, name string) clierror.Error {
if err != nil {
return clierror.Wrap(err,
clierror.Message("failed to get resource data"),
Expand Down
14 changes: 7 additions & 7 deletions internal/cmd/hana/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ func NewHanaCredentialsCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
Use: "credentials",
Short: "Print credentials of the Hana instance.",
Long: "Use this command to print credentials of the Hana instance on the SAP Kyma platform.",
PreRunE: func(_ *cobra.Command, args []string) error {
return config.KubeClientConfig.Complete()
PreRun: func(_ *cobra.Command, args []string) {
clierror.Check(config.KubeClientConfig.Complete())
},
RunE: func(_ *cobra.Command, _ []string) error {
return runCredentials(&config)
Run: func(_ *cobra.Command, _ []string) {
clierror.Check(runCredentials(&config))
},
}

Expand All @@ -56,7 +56,7 @@ func NewHanaCredentialsCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
return cmd
}

func runCredentials(config *hanaCredentialsConfig) error {
func runCredentials(config *hanaCredentialsConfig) clierror.Error {
fmt.Printf("Getting Hana credentials (%s/%s).\n", config.namespace, config.name)

credentials, err := getHanaCredentials(config)
Expand All @@ -77,7 +77,7 @@ func printCredentials(config *hanaCredentialsConfig, credentials credentials) {
}
}

func getHanaCredentials(config *hanaCredentialsConfig) (credentials, error) {
func getHanaCredentials(config *hanaCredentialsConfig) (credentials, clierror.Error) {
secret, err := config.KubeClient.Static().CoreV1().Secrets(config.namespace).Get(config.Ctx, config.name, metav1.GetOptions{})
if err != nil {
return handleGetHanaCredentialsError(err)
Expand All @@ -88,7 +88,7 @@ func getHanaCredentials(config *hanaCredentialsConfig) (credentials, error) {
}, nil
}

func handleGetHanaCredentialsError(err error) (credentials, error) {
func handleGetHanaCredentialsError(err error) (credentials, clierror.Error) {
hints := []string{
"Make sure that Hana is run and ready to use. You can use command 'kyma hana check'.",
}
Expand Down
Loading

0 comments on commit d0fce7d

Please sign in to comment.