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

better error messages for BTP/CIS #2019

Merged
merged 1 commit into from
Mar 28, 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
9 changes: 5 additions & 4 deletions internal/btp/auth/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package auth

import (
"encoding/json"
"fmt"
"os"

"github.com/kyma-project/cli.v3/internal/clierror"
)

type CISCredentials struct {
Expand Down Expand Up @@ -45,16 +46,16 @@ 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, fmt.Errorf("failed to read credentials file: %s", err.Error())
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."}}
}

credentials := CISCredentials{}
err = json.Unmarshal(credentialsBytes, &credentials)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal file data: %s", err.Error())
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 &credentials, nil
Expand Down
18 changes: 10 additions & 8 deletions internal/btp/auth/xsuaa.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"net/http"
"net/url"
"strings"

"github.com/kyma-project/cli.v3/internal/clierror"
)

const authorizationEndpoint = "oauth/token"
Expand All @@ -23,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 All @@ -33,7 +35,7 @@ func GetOAuthToken(grantType, serverURL, username, password string) (*XSUAAToken
strings.NewReader(urlBody.Encode()),
)
if err != nil {
return nil, fmt.Errorf("failed to build request: %s", err.Error())
return nil, &clierror.Error{Message: "failed to build request", Details: err.Error(), Hints: []string{"Make sure the server URL in the config is correct."}}
}
defer request.Body.Close()

Expand All @@ -42,7 +44,7 @@ func GetOAuthToken(grantType, serverURL, username, password string) (*XSUAAToken

response, err := http.DefaultClient.Do(request)
if err != nil {
return nil, fmt.Errorf("failed to get token from server: %s", err.Error())
return nil, &clierror.Error{Message: "failed to get token from server", Details: err.Error()}
}
defer response.Body.Close()

Expand All @@ -53,21 +55,21 @@ 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 {
return nil, fmt.Errorf("failed to decode response with Status '%s': %s", response.Status, err.Error())
return nil, &clierror.Error{Message: fmt.Sprintf("failed to decode response with Status %s", response.Status), Details: err.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 fmt.Errorf("failed to decode error response: %s", err.Error())
return &clierror.Error{Message: "failed to decode error response", Details: err.Error()}
}
return fmt.Errorf("error response: %s: %s", response.Status, errorData.ErrorDescription)
return &clierror.Error{Message: fmt.Sprintf("error response: %s", response.Status), Details: errorData.ErrorDescription}
}
12 changes: 7 additions & 5 deletions internal/btp/cis/provision.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/json"
"fmt"
"net/http"

"github.com/kyma-project/cli.v3/internal/clierror"
)

const provisionEndpoint = "provisioning/v1/environments"
Expand Down Expand Up @@ -53,10 +55,10 @@ 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, err
return nil, &clierror.Error{Message: err.Error()}
}

provisionURL := fmt.Sprintf("%s/%s", c.credentials.Endpoints.ProvisioningServiceURL, provisionEndpoint)
Expand All @@ -69,18 +71,18 @@ func (c *LocalClient) Provision(pe *ProvisionEnvironment) (*ProvisionResponse, e

response, err := c.cis.post(provisionURL, options)
if err != nil {
return nil, fmt.Errorf("failed to provision: %s", err.Error())
return nil, &clierror.Error{Message: err.Error()}
}
defer response.Body.Close()

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 {
return nil, fmt.Errorf("failed to decode response: %s", err.Error())
return nil, &clierror.Error{Message: "failed to decode response", Details: err.Error()}
}

return &provisionResponse, nil
Expand Down
11 changes: 3 additions & 8 deletions internal/cmd/provision/provision.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/kyma-project/cli.v3/internal/btp/auth"
"github.com/kyma-project/cli.v3/internal/btp/cis"
"github.com/kyma-project/cli.v3/internal/clierror"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -47,11 +46,7 @@ func runProvision(config *provisionConfig) error {
// TODO: is the credentials a good name for this field? it contains much more than credentials only
credentials, err := auth.LoadCISCredentials(config.credentialsPath)
if err != nil {
return clierror.Error{
Message: "failed to load credentials",
Details: err.Error(),
Hints: []string{"Make sure the path to the credentials file is correct."},
}
return err.Wrap("failed to load credentials", []string{})
}

token, err := auth.GetOAuthToken(
Expand All @@ -61,7 +56,7 @@ func runProvision(config *provisionConfig) error {
credentials.UAA.ClientSecret,
)
if err != nil {
return fmt.Errorf("failed to get access token: %s", err.Error())
return err.Wrap("failed to get access token:", []string{})
}

// TODO: maybe we should pass only credentials.Endpoints?
Expand All @@ -79,7 +74,7 @@ func runProvision(config *provisionConfig) error {
}
response, err := localCISClient.Provision(ProvisionEnvironment)
if err != nil {
return fmt.Errorf("failed to provision kyma runtime: %s", err.Error())
return err.Wrap("failed to provision kyma runtime", []string{})
}

fmt.Printf("Kyma environment provisioning, environment name: '%s', id: '%s'\n", response.Name, response.ID)
Expand Down
Loading