diff --git a/internal/api/controller/repo/import_progress.go b/internal/api/controller/repo/import_progress.go index 8b7cf03fa..26dca2281 100644 --- a/internal/api/controller/repo/import_progress.go +++ b/internal/api/controller/repo/import_progress.go @@ -6,9 +6,13 @@ package repo import ( "context" + "errors" + "fmt" apiauth "github.com/harness/gitness/internal/api/auth" + "github.com/harness/gitness/internal/api/usererror" "github.com/harness/gitness/internal/auth" + "github.com/harness/gitness/internal/services/importer" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) @@ -28,5 +32,13 @@ func (c *Controller) ImportProgress(ctx context.Context, return types.JobProgress{}, err } - return c.importer.GetProgress(ctx, repo) + progress, err := c.importer.GetProgress(ctx, repo) + if errors.Is(err, importer.ErrNotFound) { + return types.JobProgress{}, usererror.NotFound("No recent or ongoing import found for repository.") + } + if err != nil { + return types.JobProgress{}, fmt.Errorf("failed to retrieve import progress: %w", err) + } + + return progress, err } diff --git a/internal/api/controller/space/export_progress.go b/internal/api/controller/space/export_progress.go index 9de448f4a..5b76db782 100644 --- a/internal/api/controller/space/export_progress.go +++ b/internal/api/controller/space/export_progress.go @@ -2,12 +2,15 @@ package space import ( "context" + "fmt" apiauth "github.com/harness/gitness/internal/api/auth" "github.com/harness/gitness/internal/api/usererror" "github.com/harness/gitness/internal/auth" + "github.com/harness/gitness/internal/services/exporter" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" + "github.com/pkg/errors" ) type ExportProgressOutput struct { @@ -18,24 +21,23 @@ type ExportProgressOutput struct { func (c *Controller) ExportProgress(ctx context.Context, session *auth.Session, spaceRef string, -) (*ExportProgressOutput, error) { +) (ExportProgressOutput, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { - return nil, err + return ExportProgressOutput{}, err } if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, false); err != nil { - return nil, err + return ExportProgressOutput{}, err } progress, err := c.exporter.GetProgressForSpace(ctx, space.ID) + if errors.Is(err, exporter.ErrNotFound) { + return ExportProgressOutput{}, usererror.NotFound("No recent or ongoing export found for space.") + } if err != nil { - return nil, err + return ExportProgressOutput{}, fmt.Errorf("failed to retrieve export progress: %w", err) } - if len(progress) == 0 { - return nil, usererror.NotFound("No ongoing export found for space.") - } - - return &ExportProgressOutput{Repos: progress}, nil + return ExportProgressOutput{Repos: progress}, nil } diff --git a/internal/services/exporter/harness_code_client.go b/internal/services/exporter/harness_code_client.go index 45dd89dc2..517ab60d5 100644 --- a/internal/services/exporter/harness_code_client.go +++ b/internal/services/exporter/harness_code_client.go @@ -12,11 +12,12 @@ import ( "crypto/tls" "encoding/json" "fmt" - "github.com/harness/gitness/internal/api/controller/repo" - "github.com/harness/gitness/types" "io" "net/http" "strings" + + "github.com/harness/gitness/internal/api/controller/repo" + "github.com/harness/gitness/types" ) const ( @@ -27,16 +28,16 @@ const ( ) var ( - ErrNotFound = fmt.Errorf("not found") - ErrBadRequest = fmt.Errorf("bad request") - ErrInternal = fmt.Errorf("internal error") + errHTTPNotFound = fmt.Errorf("not found") + errHTTPBadRequest = fmt.Errorf("bad request") + errHTTPInternal = fmt.Errorf("internal error") ) -type HarnessCodeClient struct { - client *Client +type harnessCodeClient struct { + client *client } -type Client struct { +type client struct { baseURL string httpClient http.Client @@ -47,8 +48,8 @@ type Client struct { token string } -// NewClient creates a new harness Client for interacting with the platforms APIs. -func NewClient(baseURL string, accountID string, orgId string, projectId string, token string) (*Client, error) { +// newClient creates a new harness Client for interacting with the platforms APIs. +func newClient(baseURL string, accountID string, orgId string, projectId string, token string) (*client, error) { if baseURL == "" { return nil, fmt.Errorf("baseUrl required") } @@ -65,7 +66,7 @@ func NewClient(baseURL string, accountID string, orgId string, projectId string, return nil, fmt.Errorf("token required") } - return &Client{ + return &client{ baseURL: baseURL, accountId: accountID, orgId: orgId, @@ -81,17 +82,17 @@ func NewClient(baseURL string, accountID string, orgId string, projectId string, }, nil } -func NewHarnessCodeClient(baseUrl string, accountID string, orgId string, projectId string, token string) (*HarnessCodeClient, error) { - client, err := NewClient(baseUrl, accountID, orgId, projectId, token) +func newHarnessCodeClient(baseUrl string, accountID string, orgId string, projectId string, token string) (*harnessCodeClient, error) { + client, err := newClient(baseUrl, accountID, orgId, projectId, token) if err != nil { return nil, err } - return &HarnessCodeClient{ + return &harnessCodeClient{ client: client, }, nil } -func (c *HarnessCodeClient) CreateRepo(ctx context.Context, input repo.CreateInput) (*types.Repository, error) { +func (c *harnessCodeClient) CreateRepo(ctx context.Context, input repo.CreateInput) (*types.Repository, error) { path := fmt.Sprintf(pathCreateRepo, c.client.accountId, c.client.orgId, c.client.projectId) bodyBytes, err := json.Marshal(input) if err != nil { @@ -140,7 +141,7 @@ func addQueryParams(req *http.Request, params map[string]string) { } } -func (c *HarnessCodeClient) DeleteRepo(ctx context.Context, repoUid string) error { +func (c *harnessCodeClient) DeleteRepo(ctx context.Context, repoUid string) error { path := fmt.Sprintf(pathDeleteRepo, c.client.accountId, c.client.orgId, c.client.projectId, repoUid) req, err := http.NewRequestWithContext(ctx, http.MethodDelete, appendPath(c.client.baseURL, path), nil) if err != nil { @@ -168,7 +169,7 @@ func appendPath(uri string, path string) string { return strings.TrimRight(uri, "/") + "/" + strings.TrimLeft(path, "/") } -func (c *Client) Do(r *http.Request) (*http.Response, error) { +func (c *client) Do(r *http.Request) (*http.Response, error) { addAuthHeader(r, c.token) return c.httpClient.Do(r) } @@ -196,13 +197,13 @@ func unmarshalResponse(resp *http.Response, data interface{}) error { func mapStatusCodeToError(statusCode int) error { switch { case statusCode == 500: - return ErrInternal + return errHTTPInternal case statusCode >= 500: return fmt.Errorf("received server side error status code %d", statusCode) case statusCode == 404: - return ErrNotFound + return errHTTPNotFound case statusCode == 400: - return ErrBadRequest + return errHTTPBadRequest case statusCode >= 400: return fmt.Errorf("received client side error status code %d", statusCode) case statusCode >= 300: diff --git a/internal/services/exporter/repository.go b/internal/services/exporter/repository.go index 2fa882fca..33f5db30f 100644 --- a/internal/services/exporter/repository.go +++ b/internal/services/exporter/repository.go @@ -8,6 +8,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "net/url" "strings" @@ -26,6 +27,11 @@ import ( "github.com/harness/gitness/types" ) +var ( + // ErrNotFound is returned if no export data was found. + ErrNotFound = errors.New("export not found") +) + type Repository struct { urlProvider *gitnessurl.Provider git gitrpc.Interface @@ -117,7 +123,7 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo return "", err } harnessCodeInfo := input.HarnessCodeInfo - client, err := NewHarnessCodeClient(r.urlProvider.GetHarnessCodeInternalUrl(), harnessCodeInfo.AccountId, harnessCodeInfo.OrgIdentifier, harnessCodeInfo.ProjectIdentifier, harnessCodeInfo.Token) + client, err := newHarnessCodeClient(r.urlProvider.GetHarnessCodeInternalUrl(), harnessCodeInfo.AccountId, harnessCodeInfo.OrgIdentifier, harnessCodeInfo.ProjectIdentifier, harnessCodeInfo.Token) if err != nil { return "", err } @@ -202,6 +208,11 @@ func (r *Repository) GetProgressForSpace(ctx context.Context, spaceID int64) ([] if err != nil { return nil, fmt.Errorf("failed to get job progress for group: %w", err) } + + if len(progress) == 0 { + return nil, ErrNotFound + } + return progress, nil } diff --git a/internal/services/importer/repository.go b/internal/services/importer/repository.go index e4bf19d77..5c1530076 100644 --- a/internal/services/importer/repository.go +++ b/internal/services/importer/repository.go @@ -35,6 +35,11 @@ const ( importJobMaxDuration = 45 * time.Minute ) +var ( + // ErrNotFound is returned if no import data was found. + ErrNotFound = errors.New("import not found") +) + type Repository struct { defaultBranch string urlProvider *gitnessurl.Provider @@ -268,15 +273,15 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo } func (r *Repository) GetProgress(ctx context.Context, repo *types.Repository) (types.JobProgress, error) { - if !repo.Importing { - // if the repo is not being imported, or it's job ID has been cleared (or never existed) return state=finished - return job.DoneProgress(), nil - } - progress, err := r.scheduler.GetJobProgress(ctx, JobIDFromRepoID(repo.ID)) if errors.Is(err, gitness_store.ErrResourceNotFound) { - // if the job is not found return state=failed - return job.FailProgress(), nil + if repo.Importing { + // if the job is not found but repo is marked as importing, return state=failed + return job.FailProgress(), nil + } + + // otherwise there either was no import, or it completed a long time ago (job cleaned up by now) + return types.JobProgress{}, ErrNotFound } if err != nil { return types.JobProgress{}, fmt.Errorf("failed to get job progress: %w", err) diff --git a/internal/services/job/executor.go b/internal/services/job/executor.go index 1b0cb6849..1d6138aac 100644 --- a/internal/services/job/executor.go +++ b/internal/services/job/executor.go @@ -141,15 +141,6 @@ func (e *Executor) exec( return exec.Handle(ctx, input, progressReporter) // runs the job } -func DoneProgress() types.JobProgress { - return types.JobProgress{ - State: enum.JobStateFinished, - Progress: ProgressMax, - Result: "", - Failure: "", - } -} - func FailProgress() types.JobProgress { return types.JobProgress{ State: enum.JobStateFailed,