Skip to content

Commit

Permalink
fix: cloud mode download artifacts (#4664)
Browse files Browse the repository at this point in the history
  • Loading branch information
povilasv authored Nov 23, 2023
1 parent cbd81ca commit 143e68b
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 1 deletion.
30 changes: 30 additions & 0 deletions pkg/api/v1/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,36 @@ func NewDirectAPIClient(httpClient *http.Client, sseClient *http.Client, apiURI,
}
}

// NewCloudAPIClient returns cloud api client
func NewCloudAPIClient(httpClient *http.Client, sseClient *http.Client, apiURI, apiPathPrefix string) APIClient {
return APIClient{
TestClient: NewTestClient(
NewCloudClient[testkube.Test](httpClient, apiURI, apiPathPrefix).WithSSEClient(sseClient),
NewCloudClient[testkube.Execution](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.TestWithExecution](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.TestWithExecutionSummary](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.ExecutionsResult](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.Artifact](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.ServerInfo](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.DebugInfo](httpClient, apiURI, apiPathPrefix),
),
TestSuiteClient: NewTestSuiteClient(
NewCloudClient[testkube.TestSuite](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.TestSuiteExecution](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.TestSuiteWithExecution](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.TestSuiteWithExecutionSummary](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.TestSuiteExecutionsResult](httpClient, apiURI, apiPathPrefix),
NewCloudClient[testkube.Artifact](httpClient, apiURI, apiPathPrefix),
),
ExecutorClient: NewExecutorClient(NewCloudClient[testkube.ExecutorDetails](httpClient, apiURI, apiPathPrefix)),
WebhookClient: NewWebhookClient(NewCloudClient[testkube.Webhook](httpClient, apiURI, apiPathPrefix)),
ConfigClient: NewConfigClient(NewCloudClient[testkube.Config](httpClient, apiURI, apiPathPrefix)),
TestSourceClient: NewTestSourceClient(NewCloudClient[testkube.TestSource](httpClient, apiURI, apiPathPrefix)),
CopyFileClient: NewCopyFileDirectClient(httpClient, apiURI, apiPathPrefix),
TemplateClient: NewTemplateClient(NewCloudClient[testkube.Template](httpClient, apiURI, apiPathPrefix)),
}
}

// APIClient struct managing proxy API Client dependencies
type APIClient struct {
TestClient
Expand Down
113 changes: 113 additions & 0 deletions pkg/api/v1/client/cloud_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package client

import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"

"github.com/pkg/errors"
)

func NewCloudClient[A All](httpClient *http.Client, apiURI, apiPathPrefix string) CloudClient[A] {
if apiPathPrefix == "" {
apiPathPrefix = "/" + Version
}

return CloudClient[A]{
client: httpClient,
sseClient: httpClient,
apiURI: apiURI,
apiPathPrefix: apiPathPrefix,
DirectClient: NewDirectClient[A](httpClient, apiURI, apiPathPrefix),
}
}

// CLoudClient is almost the same as Direct client, but has different GetFile method
// which returns a download URL for the artifact instead of downloading it.
type CloudClient[A All] struct {
client *http.Client
sseClient *http.Client
apiURI string
apiPathPrefix string
DirectClient[A]
}

type ArtifactURL struct {
// Download URL for the artifact.
URL string `json:"url"`
}

// GetFile, in cloud we need to call non
func (t CloudClient[A]) GetFile(uri, fileName, destination string, params map[string][]string) (name string, err error) {

cloudURI := strings.Replace(uri, "/agent", "", -1)
req, err := http.NewRequest(http.MethodGet, cloudURI, nil)
if err != nil {
return "", err
}

q := req.URL.Query()
for key, values := range params {
for _, value := range values {
if value != "" {
q.Add(key, value)
}
}
}
req.URL.RawQuery = q.Encode()

resp, err := t.client.Do(req)
if err != nil {
return name, err
}
defer resp.Body.Close()

if resp.StatusCode > 299 {
return name, fmt.Errorf("error: %d", resp.StatusCode)
}

var artifactURL ArtifactURL
err = json.NewDecoder(resp.Body).Decode(&artifactURL)
if err != nil {
return "", err
}

req, err = http.NewRequest(http.MethodGet, artifactURL.URL, nil)
if err != nil {
return "", err
}
resp, err = t.client.Do(req)
if err != nil {
return name, err
}
defer resp.Body.Close()

target := filepath.Join(destination, fileName)
dir := filepath.Dir(target)
if _, err := os.Stat(dir); errors.Is(err, os.ErrNotExist) {
if err = os.MkdirAll(dir, os.ModePerm); err != nil {
return name, err
}
} else if err != nil {
return name, err
}

f, err := os.Create(target)
if err != nil {
return name, err
}

if _, err = io.Copy(f, resp.Body); err != nil {
return name, err
}

if err = t.responseError(resp); err != nil {
return name, fmt.Errorf("api/download-file returned error: %w", err)
}

return f.Name(), nil
}
2 changes: 1 addition & 1 deletion pkg/api/v1/client/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func GetClient(clientType ClientType, options Options) (client Client, err error
case ClientCloud:
ConfigureClient(httpClient, nil, options.CloudApiKey)
ConfigureClient(sseClient, nil, options.CloudApiKey)
client = NewDirectAPIClient(httpClient, sseClient, options.ApiUri, options.CloudApiPathPrefix)
client = NewCloudAPIClient(httpClient, sseClient, options.ApiUri, options.CloudApiPathPrefix)

case ClientDirect:
var token *oauth2.Token
Expand Down

0 comments on commit 143e68b

Please sign in to comment.