Route upload client by pipeline
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -22,7 +23,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
uploadPath = "upload"
|
||||
runsPath = "runs"
|
||||
idempotencyKeyHeader = "Idempotency-Key"
|
||||
defaultHTTPTimeout = 30 * time.Second
|
||||
@@ -34,6 +34,8 @@ const (
|
||||
redactedSecret = "[redacted]"
|
||||
)
|
||||
|
||||
var pipelineIDPattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9._-]*$`)
|
||||
|
||||
func NewClient(opts ClientOptions) (*Client, error) {
|
||||
endpoint, err := cleanEndpoint(opts.Endpoint)
|
||||
if err != nil {
|
||||
@@ -65,6 +67,9 @@ func (c *Client) UploadBundle(ctx context.Context, opts UploadBundleOptions) (Re
|
||||
if opts.Validate && opts.DisableValidation {
|
||||
return Result{}, fmt.Errorf("validate and disable validation cannot both be set")
|
||||
}
|
||||
if err := validatePipelineID(opts.PipelineID); err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
if opts.Root == "" {
|
||||
return Result{}, fmt.Errorf("root is required")
|
||||
}
|
||||
@@ -85,7 +90,7 @@ func (c *Client) UploadBundle(ctx context.Context, opts UploadBundleOptions) (Re
|
||||
if err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
return c.uploadArchive(ctx, archive, key)
|
||||
return c.uploadArchive(ctx, opts.PipelineID, archive, key)
|
||||
}
|
||||
|
||||
func (c *Client) UploadFiles(ctx context.Context, opts UploadFilesOptions) (Result, error) {
|
||||
@@ -95,6 +100,9 @@ func (c *Client) UploadFiles(ctx context.Context, opts UploadFilesOptions) (Resu
|
||||
if opts.Validate && opts.DisableValidation {
|
||||
return Result{}, fmt.Errorf("validate and disable validation cannot both be set")
|
||||
}
|
||||
if err := validatePipelineID(opts.PipelineID); err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
if opts.ID == "" {
|
||||
return Result{}, fmt.Errorf("id is required")
|
||||
}
|
||||
@@ -131,7 +139,7 @@ func (c *Client) UploadFiles(ctx context.Context, opts UploadFilesOptions) (Resu
|
||||
if err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
return c.uploadArchive(ctx, archive, key)
|
||||
return c.uploadArchive(ctx, opts.PipelineID, archive, key)
|
||||
}
|
||||
|
||||
func (c *Client) Status(ctx context.Context, runID string) (RunStatus, error) {
|
||||
@@ -167,7 +175,7 @@ func (c *Client) Status(ctx context.Context, runID string) (RunStatus, error) {
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func (c *Client) uploadArchive(ctx context.Context, archive []byte, idempotencyKey string) (Result, error) {
|
||||
func (c *Client) uploadArchive(ctx context.Context, pipelineID string, archive []byte, idempotencyKey string) (Result, error) {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
@@ -176,7 +184,7 @@ func (c *Client) uploadArchive(ctx context.Context, archive []byte, idempotencyK
|
||||
if err := ctx.Err(); err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
result, retry, err := c.uploadAttempt(ctx, archive, idempotencyKey)
|
||||
result, retry, err := c.uploadAttempt(ctx, pipelineID, archive, idempotencyKey)
|
||||
if err == nil {
|
||||
return result, nil
|
||||
}
|
||||
@@ -191,8 +199,8 @@ func (c *Client) uploadArchive(ctx context.Context, archive []byte, idempotencyK
|
||||
return Result{}, lastErr
|
||||
}
|
||||
|
||||
func (c *Client) uploadAttempt(ctx context.Context, archive []byte, idempotencyKey string) (Result, bool, error) {
|
||||
request, err := http.NewRequestWithContext(ctx, http.MethodPost, c.uploadURL(), bytes.NewReader(archive))
|
||||
func (c *Client) uploadAttempt(ctx context.Context, pipelineID string, archive []byte, idempotencyKey string) (Result, bool, error) {
|
||||
request, err := http.NewRequestWithContext(ctx, http.MethodPost, c.uploadURL(pipelineID), bytes.NewReader(archive))
|
||||
if err != nil {
|
||||
return Result{}, false, c.redactError(err)
|
||||
}
|
||||
@@ -227,8 +235,8 @@ func (c *Client) authorize(request *http.Request) {
|
||||
request.Header.Set("Authorization", authorizationPrefix+c.token)
|
||||
}
|
||||
|
||||
func (c *Client) uploadURL() string {
|
||||
return joinEndpointPath(c.endpoint, uploadPath)
|
||||
func (c *Client) uploadURL(pipelineID string) string {
|
||||
return joinEndpointPath(c.endpoint, "v1", "pipelines", pipelineID, "upload")
|
||||
}
|
||||
|
||||
func (c *Client) statusURL(runID string) string {
|
||||
@@ -343,6 +351,16 @@ func uploadIdempotencyKey(value string) (string, error) {
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func validatePipelineID(value string) error {
|
||||
if value == "" {
|
||||
return fmt.Errorf("pipeline id is required")
|
||||
}
|
||||
if !pipelineIDPattern.MatchString(value) {
|
||||
return fmt.Errorf("pipeline id must be a slug-like identifier")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateIdempotencyKey(value string) error {
|
||||
if value == "" {
|
||||
return fmt.Errorf("idempotency key is required")
|
||||
|
||||
Reference in New Issue
Block a user