diff --git a/NOTICE b/NOTICE index 584da72..c861e91 100644 --- a/NOTICE +++ b/NOTICE @@ -125,9 +125,9 @@ License URL: https://github.com/go-git/gcfg/blob/3a3c6141e376/LICENSE ---------- Module: github.com/go-git/go-billy/v5 -Version: v5.7.0 +Version: v5.8.0 License: Apache-2.0 -License URL: https://github.com/go-git/go-billy/blob/v5.7.0/LICENSE +License URL: https://github.com/go-git/go-billy/blob/v5.8.0/LICENSE ---------- Module: github.com/go-git/go-git/v5 diff --git a/api/client.go b/api/client.go index c392e14..2dd261d 100644 --- a/api/client.go +++ b/api/client.go @@ -78,46 +78,46 @@ func NewHttpClient() *http.Client { } func (c *Client) ListDataCenters() ([]DataCenter, error) { - datacenters, _, err := c.api.MetadataAPI.MetadataGetDatacenters(c.ctx).Execute() - return datacenters, errors.FormatAPIError(err) + datacenters, r, err := c.api.MetadataAPI.MetadataGetDatacenters(c.ctx).Execute() + return datacenters, errors.FormatAPIError(r, err) } func (c *Client) ListDomains(teamId int) ([]Domain, error) { - domains, _, err := c.api.DomainsAPI.DomainsListDomains(c.ctx, float32(teamId)).Execute() - return domains, errors.FormatAPIError(err) + domains, r, err := c.api.DomainsAPI.DomainsListDomains(c.ctx, float32(teamId)).Execute() + return domains, errors.FormatAPIError(r, err) } func (c *Client) GetDomain(teamId int, domainName string) (*Domain, error) { - domain, _, err := c.api.DomainsAPI.DomainsGetDomain(c.ctx, float32(teamId), domainName).Execute() - return domain, errors.FormatAPIError(err) + domain, r, err := c.api.DomainsAPI.DomainsGetDomain(c.ctx, float32(teamId), domainName).Execute() + return domain, errors.FormatAPIError(r, err) } func (c *Client) CreateDomain(teamId int, domainName string) (*Domain, error) { - domain, _, err := c.api.DomainsAPI.DomainsCreateDomain(c.ctx, float32(teamId), domainName).Execute() - return domain, errors.FormatAPIError(err) + domain, r, err := c.api.DomainsAPI.DomainsCreateDomain(c.ctx, float32(teamId), domainName).Execute() + return domain, errors.FormatAPIError(r, err) } func (c *Client) DeleteDomain(teamId int, domainName string) error { - _, err := c.api.DomainsAPI.DomainsDeleteDomain(c.ctx, float32(teamId), domainName).Execute() - return errors.FormatAPIError(err) + r, err := c.api.DomainsAPI.DomainsDeleteDomain(c.ctx, float32(teamId), domainName).Execute() + return errors.FormatAPIError(r, err) } func (c *Client) UpdateDomain( teamId int, domainName string, args UpdateDomainArgs, ) (*Domain, error) { - domain, _, err := c.api.DomainsAPI. + domain, r, err := c.api.DomainsAPI. DomainsUpdateDomain(c.ctx, float32(teamId), domainName). DomainsUpdateDomainRequest(args). Execute() - return domain, errors.FormatAPIError(err) + return domain, errors.FormatAPIError(r, err) } func (c *Client) VerifyDomain( teamId int, domainName string, ) (*DomainVerificationStatus, error) { - status, _, err := c.api.DomainsAPI. + status, r, err := c.api.DomainsAPI. DomainsVerifyDomain(c.ctx, float32(teamId), domainName).Execute() - return status, errors.FormatAPIError(err) + return status, errors.FormatAPIError(r, err) } func (c *Client) UpdateWorkspaceConnections( @@ -131,13 +131,13 @@ func (c *Client) UpdateWorkspaceConnections( } req[path] = ids } - domain, _, err := c.api.DomainsAPI. + domain, r, err := c.api.DomainsAPI. DomainsUpdateWorkspaceConnections(c.ctx, float32(teamId), domainName). RequestBody(req).Execute() - return domain, errors.FormatAPIError(err) + return domain, errors.FormatAPIError(r, err) } func (c *Client) ListBaseimages() ([]Baseimage, error) { - baseimages, _, err := c.api.MetadataAPI.MetadataGetWorkspaceBaseImages(c.ctx).Execute() - return baseimages, errors.FormatAPIError(err) + baseimages, r, err := c.api.MetadataAPI.MetadataGetWorkspaceBaseImages(c.ctx).Execute() + return baseimages, errors.FormatAPIError(r, err) } diff --git a/api/errors/errors.go b/api/errors/errors.go index 0bd1892..c074074 100644 --- a/api/errors/errors.go +++ b/api/errors/errors.go @@ -6,6 +6,8 @@ package errors import ( "encoding/json" "fmt" + "net/http" + "net/url" "time" "github.com/codesphere-cloud/cs-go/api/openapi_client" @@ -60,24 +62,33 @@ type APIErrorResponse struct { TraceId string `json:"traceId"` } -func FormatAPIError(err error) error { +func FormatAPIError(r *http.Response, err error) error { if err == nil { return nil } + if r == nil { + r = &http.Response{ + StatusCode: -1, + } + } + if r.Request == nil { + r.Request = &http.Request{URL: &url.URL{}} + } + openAPIErr, ok := err.(*openapi_client.GenericOpenAPIError) if !ok { - return err + return fmt.Errorf("unexpected error %d at URL %s: %w", r.StatusCode, r.Request.URL, err) } body := openAPIErr.Body() if len(body) == 0 { - return err + return fmt.Errorf("unexpected error %d at URL %s: %w", r.StatusCode, r.Request.URL, err) } var apiErr APIErrorResponse if json.Unmarshal(body, &apiErr) != nil { - return err + return fmt.Errorf("unexpected error %d at URL %s: %w", r.StatusCode, r.Request.URL, err) } return fmt.Errorf("codesphere API returned error %d (%s): %s", apiErr.Status, apiErr.Title, apiErr.Detail) diff --git a/api/errors/errors_test.go b/api/errors/errors_test.go index eb6fcb3..bdc6773 100644 --- a/api/errors/errors_test.go +++ b/api/errors/errors_test.go @@ -5,6 +5,8 @@ package errors_test import ( "fmt" + "net/http" + "net/url" "reflect" "unsafe" @@ -29,20 +31,30 @@ func makeGenericOpenAPIError(body []byte, errStr string) error { } var _ = Describe("FormatAPIError", func() { + var ( + r *http.Response + ) + + BeforeEach(func() { + r = &http.Response{ + StatusCode: 123, + Request: &http.Request{URL: &url.URL{Scheme: "http", Host: "codesphere.com", Path: "/api/fake"}}, + } + }) It("returns nil for nil error", func() { - Expect(errors.FormatAPIError(nil)).To(BeNil()) + Expect(errors.FormatAPIError(nil, nil)).To(BeNil()) }) It("returns regular error unchanged", func() { err := fmt.Errorf("regular error") - res := errors.FormatAPIError(err) + res := errors.FormatAPIError(r, err) Expect(res).ToNot(BeNil()) - Expect(res.Error()).To(Equal("regular error")) + Expect(res.Error()).To(Equal(fmt.Sprintf("unexpected error %d at URL %s: %s", r.StatusCode, r.Request.URL.String(), err.Error()))) }) It("parses API JSON error and formats it", func() { apiErr := makeGenericOpenAPIError([]byte(`{"status":400,"title":"Workspace is not running","detail":"Workspace '796636' is not in a running state.","traceId":"svJDMa5"}`), "400 Bad Request") - res := errors.FormatAPIError(apiErr) + res := errors.FormatAPIError(r, apiErr) Expect(res).ToNot(BeNil()) Expect(res.Error()).To(Equal("API error 400 Workspace is not running: Workspace '796636' is not in a running state.")) }) diff --git a/api/plan.go b/api/plan.go index 9d8caf0..6cb744b 100644 --- a/api/plan.go +++ b/api/plan.go @@ -27,6 +27,6 @@ func (client *Client) PlanByName(name string) (WorkspacePlan, error) { } func (c *Client) ListWorkspacePlans() ([]WorkspacePlan, error) { - plans, _, err := c.api.MetadataAPI.MetadataGetWorkspacePlans(c.ctx).Execute() - return plans, cserrors.FormatAPIError(err) + plans, r, err := c.api.MetadataAPI.MetadataGetWorkspacePlans(c.ctx).Execute() + return plans, cserrors.FormatAPIError(r, err) } diff --git a/api/team.go b/api/team.go index 48b2b7b..2f259ca 100644 --- a/api/team.go +++ b/api/team.go @@ -40,26 +40,26 @@ func (client *Client) TeamIdByName(name string) (Team, error) { } func (c *Client) ListTeams() ([]Team, error) { - teams, _, err := c.api.TeamsAPI.TeamsListTeams(c.ctx).Execute() - return teams, cserrors.FormatAPIError(err) + teams, r, err := c.api.TeamsAPI.TeamsListTeams(c.ctx).Execute() + return teams, cserrors.FormatAPIError(r, err) } func (c *Client) GetTeam(teamId int) (*Team, error) { - team, _, err := c.api.TeamsAPI.TeamsGetTeam(c.ctx, float32(teamId)).Execute() - return ConvertToTeam(team), cserrors.FormatAPIError(err) + team, r, err := c.api.TeamsAPI.TeamsGetTeam(c.ctx, float32(teamId)).Execute() + return ConvertToTeam(team), cserrors.FormatAPIError(r, err) } func (c *Client) CreateTeam(name string, dc int) (*Team, error) { - team, _, err := c.api.TeamsAPI.TeamsCreateTeam(c.ctx). + team, r, err := c.api.TeamsAPI.TeamsCreateTeam(c.ctx). TeamsCreateTeamRequest(openapi_client.TeamsCreateTeamRequest{ Name: name, Dc: dc, }). Execute() - return ConvertToTeam(team), cserrors.FormatAPIError(err) + return ConvertToTeam(team), cserrors.FormatAPIError(r, err) } func (c *Client) DeleteTeam(teamId int) error { - _, err := c.api.TeamsAPI.TeamsDeleteTeam(c.ctx, float32(teamId)).Execute() - return cserrors.FormatAPIError(err) + r, err := c.api.TeamsAPI.TeamsDeleteTeam(c.ctx, float32(teamId)).Execute() + return cserrors.FormatAPIError(r, err) } diff --git a/api/workspace.go b/api/workspace.go index 2ec8ef1..3400139 100644 --- a/api/workspace.go +++ b/api/workspace.go @@ -13,32 +13,32 @@ import ( ) func (c *Client) ListWorkspaces(teamId int) ([]Workspace, error) { - workspaces, _, err := c.api.WorkspacesAPI.WorkspacesListWorkspaces(c.ctx, float32(teamId)).Execute() - return workspaces, errors.FormatAPIError(err) + workspaces, r, err := c.api.WorkspacesAPI.WorkspacesListWorkspaces(c.ctx, float32(teamId)).Execute() + return workspaces, errors.FormatAPIError(r, err) } func (c *Client) GetWorkspace(workspaceId int) (Workspace, error) { - workspace, _, err := c.api.WorkspacesAPI.WorkspacesGetWorkspace(c.ctx, float32(workspaceId)).Execute() + workspace, r, err := c.api.WorkspacesAPI.WorkspacesGetWorkspace(c.ctx, float32(workspaceId)).Execute() if workspace != nil { - return *workspace, errors.FormatAPIError(err) + return *workspace, errors.FormatAPIError(r, err) } - return Workspace{}, errors.FormatAPIError(err) + return Workspace{}, errors.FormatAPIError(r, err) } func (c *Client) DeleteWorkspace(workspaceId int) error { - _, err := c.api.WorkspacesAPI.WorkspacesDeleteWorkspace(c.ctx, float32(workspaceId)).Execute() - return errors.FormatAPIError(err) + r, err := c.api.WorkspacesAPI.WorkspacesDeleteWorkspace(c.ctx, float32(workspaceId)).Execute() + return errors.FormatAPIError(r, err) } func (c *Client) WorkspaceStatus(workspaceId int) (*WorkspaceStatus, error) { - status, _, err := c.api.WorkspacesAPI.WorkspacesGetWorkspaceStatus(c.ctx, float32(workspaceId)).Execute() - return status, errors.FormatAPIError(err) + status, r, err := c.api.WorkspacesAPI.WorkspacesGetWorkspaceStatus(c.ctx, float32(workspaceId)).Execute() + return status, errors.FormatAPIError(r, err) } func (c *Client) CreateWorkspace(args CreateWorkspaceArgs) (*Workspace, error) { - workspace, _, err := c.api.WorkspacesAPI.WorkspacesCreateWorkspace(c.ctx).WorkspacesCreateWorkspaceRequest(args).Execute() - return workspace, errors.FormatAPIError(err) + workspace, r, err := c.api.WorkspacesAPI.WorkspacesCreateWorkspace(c.ctx).WorkspacesCreateWorkspaceRequest(args).Execute() + return workspace, errors.FormatAPIError(r, err) } func (c *Client) SetEnvVarOnWorkspace(workspaceId int, envVars map[string]string) error { @@ -52,8 +52,8 @@ func (c *Client) SetEnvVarOnWorkspace(workspaceId int, envVars map[string]string req := c.api.WorkspacesAPI.WorkspacesSetEnvVar(c.ctx, float32(workspaceId)). WorkspacesCreateWorkspaceRequestEnvInner(vars) - _, err := c.api.WorkspacesAPI.WorkspacesSetEnvVarExecute(req) - return errors.FormatAPIError(err) + r, err := c.api.WorkspacesAPI.WorkspacesSetEnvVarExecute(req) + return errors.FormatAPIError(r, err) } func (c *Client) ExecCommand(workspaceId int, command string, workdir string, env map[string]string) (string, string, error) { @@ -69,43 +69,43 @@ func (c *Client) ExecCommand(workspaceId int, command string, workdir string, en } req := c.api.WorkspacesAPI.WorkspacesExecuteCommand(c.ctx, float32(workspaceId)).WorkspacesExecuteCommandRequest(cmd) - res, _, err := req.Execute() + res, r, err := req.Execute() if err != nil { - return "", "", errors.FormatAPIError(err) + return "", "", errors.FormatAPIError(r, err) } if res == nil { - return "", "", errors.FormatAPIError(err) + return "", "", errors.FormatAPIError(r, err) } - return res.Output, res.Error, errors.FormatAPIError(err) + return res.Output, res.Error, errors.FormatAPIError(r, err) } func (c *Client) DeployLandscape(wsId int, profile string) error { if profile == "ci.yml" || profile == "" { req := c.api.WorkspacesAPI.WorkspacesDeployLandscape(c.ctx, float32(wsId)) - _, err := req.Execute() - return errors.FormatAPIError(err) + r, err := req.Execute() + return errors.FormatAPIError(r, err) } req := c.api.WorkspacesAPI.WorkspacesDeployLandscape1(c.ctx, float32(wsId), profile) - _, err := req.Execute() - return errors.FormatAPIError(err) + r, err := req.Execute() + return errors.FormatAPIError(r, err) } func (c *Client) StartPipelineStage(wsId int, profile string, stage string) error { if profile == "ci.yml" || profile == "" { req := c.api.WorkspacesAPI.WorkspacesStartPipelineStage(c.ctx, float32(wsId), stage) - _, err := req.Execute() - return errors.FormatAPIError(err) + r, err := req.Execute() + return errors.FormatAPIError(r, err) } req := c.api.WorkspacesAPI.WorkspacesStartPipelineStage1(c.ctx, float32(wsId), stage, profile) - _, err := req.Execute() - return errors.FormatAPIError(err) + r, err := req.Execute() + return errors.FormatAPIError(r, err) } func (c *Client) GetPipelineState(wsId int, stage string) ([]PipelineStatus, error) { req := c.api.WorkspacesAPI.WorkspacesPipelineStatus(c.ctx, float32(wsId), stage) - res, _, err := req.Execute() - return res, errors.FormatAPIError(err) + res, r, err := req.Execute() + return res, errors.FormatAPIError(r, err) } // ScaleWorkspace sets the number of replicas for a workspace. @@ -115,8 +115,8 @@ func (c *Client) ScaleWorkspace(wsId int, replicas int) error { WorkspacesUpdateWorkspaceRequest(openapi_client.WorkspacesUpdateWorkspaceRequest{ Replicas: &replicas, }) - _, err := req.Execute() - return errors.FormatAPIError(err) + r, err := req.Execute() + return errors.FormatAPIError(r, err) } // Waits for a given workspace to be running. @@ -131,7 +131,7 @@ func (client *Client) WaitForWorkspaceRunning(workspace *Workspace, timeout time if err != nil { if client.time.Now().After(maxWaitTime) { - return errors.FormatAPIError(err) + return err } client.time.Sleep(delay) continue @@ -202,11 +202,11 @@ func (client Client) DeployWorkspace(args DeployWorkspaceArgs) (*Workspace, erro func (c Client) GitPull(workspaceId int, remote string, branch string) error { if remote == "" { req := c.api.WorkspacesAPI.WorkspacesGitPull(c.ctx, float32(workspaceId)) - _, err := req.Execute() - return errors.FormatAPIError(err) + r, err := req.Execute() + return errors.FormatAPIError(r, err) } req := c.api.WorkspacesAPI.WorkspacesGitPull2(c.ctx, float32(workspaceId), remote, branch) - _, err := req.Execute() - return errors.FormatAPIError(err) + r, err := req.Execute() + return errors.FormatAPIError(r, err) } diff --git a/cli/cmd/exec.go b/cli/cmd/exec.go index e8d0d83..3738486 100644 --- a/cli/cmd/exec.go +++ b/cli/cmd/exec.go @@ -9,7 +9,6 @@ import ( "os" "strings" - "github.com/codesphere-cloud/cs-go/api/errors" "github.com/codesphere-cloud/cs-go/pkg/cs" "github.com/codesphere-cloud/cs-go/pkg/io" @@ -81,5 +80,5 @@ func (c *ExecCmd) ExecCommand(client Client, command string) error { log.Println("STDERR:") fmt.Fprintln(os.Stderr, stderr) } - return errors.FormatAPIError(err) + return err } diff --git a/cli/cmd/git_pull.go b/cli/cmd/git_pull.go index fa94bd1..feaa565 100644 --- a/cli/cmd/git_pull.go +++ b/cli/cmd/git_pull.go @@ -51,7 +51,7 @@ func AddGitPullCmd(git *cobra.Command, opts GlobalOptions) { Long: io.Long(`Pull latest changes from the remote git repository. if specified, pulls a specific branch.`), - Example: io.FormatExampleCommands("pull", []io.Example{ + Example: io.FormatExampleCommands("git pull", []io.Example{ {Cmd: "", Desc: "Pull latest HEAD from current branch"}, {Cmd: "--remote origin --branch staging", Desc: "Pull branch staging from remote origin"}, }), diff --git a/docs/cs_git_pull.md b/docs/cs_git_pull.md index 909d9d7..e72c903 100644 --- a/docs/cs_git_pull.md +++ b/docs/cs_git_pull.md @@ -16,10 +16,10 @@ cs git pull [flags] ``` # Pull latest HEAD from current branch -$ cs pull +$ cs git pull # Pull branch staging from remote origin -$ cs pull --remote origin --branch staging +$ cs git pull --remote origin --branch staging ``` ### Options diff --git a/pkg/tmpl/NOTICE b/pkg/tmpl/NOTICE index 584da72..c861e91 100644 --- a/pkg/tmpl/NOTICE +++ b/pkg/tmpl/NOTICE @@ -125,9 +125,9 @@ License URL: https://github.com/go-git/gcfg/blob/3a3c6141e376/LICENSE ---------- Module: github.com/go-git/go-billy/v5 -Version: v5.7.0 +Version: v5.8.0 License: Apache-2.0 -License URL: https://github.com/go-git/go-billy/blob/v5.7.0/LICENSE +License URL: https://github.com/go-git/go-billy/blob/v5.8.0/LICENSE ---------- Module: github.com/go-git/go-git/v5