Skip to content
This repository was archived by the owner on Sep 17, 2024. It is now read-only.

Commit 3d61182

Browse files
narphmergify-bot
authored andcommitted
Update fetchBeatsBinary to be reused in elastic-agent-poc (#1984)
* update func * fix path * work on download * small fix * remove test * add sha to google * fix typo * add comment (cherry picked from commit d3365c9) # Conflicts: # pkg/downloads/versions.go
1 parent 668a9f3 commit 3d61182

File tree

4 files changed

+105
-57
lines changed

4 files changed

+105
-57
lines changed

internal/utils/utils.go

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
2626
//nolint:unused
2727
var seededRand = rand.New(rand.NewSource(time.Now().UnixNano()))
2828

29+
// DownloadRequest struct contains download details ad path and URL
30+
type DownloadRequest struct {
31+
URL string
32+
DownloadPath string
33+
UnsanitizedFilePath string
34+
}
35+
2936
// GetArchitecture retrieves if the underlying system platform is arm64 or amd64
3037
func GetArchitecture() string {
3138
arch, present := os.LookupEnv("GOARCH")
@@ -40,36 +47,41 @@ func GetArchitecture() string {
4047
// DownloadFile will download a url and store it in a temporary path.
4148
// It writes to the destination file as it downloads it, without
4249
// loading the entire file into memory.
43-
func DownloadFile(url string) (string, error) {
44-
tempParentDir := filepath.Join(os.TempDir(), uuid.NewString())
45-
internalio.MkdirAll(tempParentDir)
50+
func DownloadFile(downloadRequest *DownloadRequest) error {
51+
var filePath string
52+
if downloadRequest.DownloadPath == "" {
53+
tempParentDir := filepath.Join(os.TempDir(), uuid.NewString())
54+
internalio.MkdirAll(tempParentDir)
55+
filePath = filepath.Join(tempParentDir, uuid.NewString())
56+
downloadRequest.DownloadPath = filePath
57+
} else {
58+
filePath = filepath.Join(downloadRequest.DownloadPath, uuid.NewString())
59+
}
4660

47-
tempFile, err := os.Create(filepath.Join(tempParentDir, uuid.NewString()))
61+
tempFile, err := os.Create(filePath)
4862
if err != nil {
4963
log.WithFields(log.Fields{
5064
"error": err,
51-
"url": url,
65+
"url": downloadRequest.URL,
5266
}).Error("Error creating file")
53-
return "", err
67+
return err
5468
}
5569
defer tempFile.Close()
5670

57-
filepathFull := tempFile.Name()
58-
71+
downloadRequest.UnsanitizedFilePath = tempFile.Name()
5972
exp := GetExponentialBackOff(3)
6073

6174
retryCount := 1
6275
var fileReader io.ReadCloser
63-
6476
download := func() error {
65-
resp, err := http.Get(url)
77+
resp, err := http.Get(downloadRequest.URL)
6678
if err != nil {
6779
log.WithFields(log.Fields{
6880
"elapsedTime": exp.GetElapsedTime(),
6981
"error": err,
70-
"path": filepathFull,
82+
"path": downloadRequest.UnsanitizedFilePath,
7183
"retry": retryCount,
72-
"url": url,
84+
"url": downloadRequest.URL,
7385
}).Warn("Could not download the file")
7486

7587
retryCount++
@@ -80,8 +92,8 @@ func DownloadFile(url string) (string, error) {
8092
log.WithFields(log.Fields{
8193
"elapsedTime": exp.GetElapsedTime(),
8294
"retries": retryCount,
83-
"path": filepathFull,
84-
"url": url,
95+
"path": downloadRequest.UnsanitizedFilePath,
96+
"url": downloadRequest.URL,
8597
}).Trace("File downloaded")
8698

8799
fileReader = resp.Body
@@ -90,30 +102,30 @@ func DownloadFile(url string) (string, error) {
90102
}
91103

92104
log.WithFields(log.Fields{
93-
"url": url,
94-
"path": filepathFull,
105+
"url": downloadRequest.URL,
106+
"path": downloadRequest.UnsanitizedFilePath,
95107
}).Trace("Downloading file")
96108

97109
err = backoff.Retry(download, exp)
98110
if err != nil {
99-
return "", err
111+
return err
100112
}
101113
defer fileReader.Close()
102114

103115
_, err = io.Copy(tempFile, fileReader)
104116
if err != nil {
105117
log.WithFields(log.Fields{
106118
"error": err,
107-
"url": url,
108-
"path": filepathFull,
119+
"url": downloadRequest.URL,
120+
"path": downloadRequest.UnsanitizedFilePath,
109121
}).Error("Could not write file")
110122

111-
return filepathFull, err
123+
return err
112124
}
113125

114126
_ = os.Chmod(tempFile.Name(), 0666)
115127

116-
return filepathFull, nil
128+
return nil
117129
}
118130

119131
// IsCommit returns true if the string matches commit format

internal/utils/utils_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@ import (
99
)
1010

1111
func TestDownloadFile(t *testing.T) {
12-
f, err := DownloadFile("https://www.elastic.co/robots.txt")
12+
var dRequest = DownloadRequest{
13+
URL: "https://www.elastic.co/robots.txt",
14+
DownloadPath: "",
15+
}
16+
err := DownloadFile(&dRequest)
1317
assert.Nil(t, err)
14-
defer os.Remove(filepath.Dir(f))
18+
assert.NotEmpty(t, dRequest.UnsanitizedFilePath)
19+
defer os.Remove(filepath.Dir(dRequest.UnsanitizedFilePath))
1520
}
1621

1722
func TestGetArchitecture(t *testing.T) {

pkg/downloads/versions.go

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func CheckPRVersion(version string, fallbackVersion string) string {
8383
// FetchElasticArtifact fetches an artifact from the right repository, returning binary name, path and error
8484
func FetchElasticArtifact(ctx context.Context, artifact string, version string, os string, arch string, extension string, isDocker bool, xpack bool) (string, string, error) {
8585
binaryName := buildArtifactName(artifact, version, os, arch, extension, isDocker)
86-
binaryPath, err := fetchBeatsBinary(ctx, binaryName, artifact, version, utils.TimeoutFactor, xpack)
86+
binaryPath, err := FetchBeatsBinary(ctx, binaryName, artifact, version, utils.TimeoutFactor, xpack, "", false)
8787
if err != nil {
8888
log.WithFields(log.Fields{
8989
"artifact": artifact,
@@ -106,10 +106,11 @@ func GetCommitVersion(version string) string {
106106

107107
// GetElasticArtifactURL returns the URL of a released artifact, which its full name is defined in the first argument,
108108
// from Elastic's artifact repository, building the JSON path query based on the full name
109+
// It also returns the URL of the sha512 file of the released artifact.
109110
// i.e. GetElasticArtifactURL("elastic-agent-$VERSION-$ARCH.deb", "elastic-agent", "$VERSION")
110111
// i.e. GetElasticArtifactURL("elastic-agent-$VERSION-x86_64.rpm", "elastic-agent","$VERSION")
111112
// i.e. GetElasticArtifactURL("elastic-agent-$VERSION-linux-$ARCH.tar.gz", "elastic-agent","$VERSION")
112-
func GetElasticArtifactURL(artifactName string, artifact string, version string) (string, error) {
113+
func GetElasticArtifactURL(artifactName string, artifact string, version string) (string, string, error) {
113114
exp := utils.GetExponentialBackOff(time.Minute)
114115

115116
retryCount := 1
@@ -161,7 +162,7 @@ func GetElasticArtifactURL(artifactName string, artifact string, version string)
161162

162163
err := backoff.Retry(apiStatus, exp)
163164
if err != nil {
164-
return "", err
165+
return "", "", err
165166
}
166167

167168
jsonParsed, err := gabs.ParseJSON([]byte(body))
@@ -171,7 +172,7 @@ func GetElasticArtifactURL(artifactName string, artifact string, version string)
171172
"artifactName": artifactName,
172173
"version": tmpVersion,
173174
}).Error("Could not parse the response body for the artifact")
174-
return "", err
175+
return "", "", err
175176
}
176177

177178
log.WithFields(log.Fields{
@@ -191,8 +192,9 @@ func GetElasticArtifactURL(artifactName string, artifact string, version string)
191192
// we need to get keys with dots using Search instead of Path
192193
downloadObject := packagesObject.Search(artifactName)
193194
downloadURL := downloadObject.Path("url").Data().(string)
195+
downloadshaURL := downloadObject.Path("sha_url").Data().(string)
194196

195-
return downloadURL, nil
197+
return downloadURL, downloadshaURL, nil
196198
}
197199

198200
// GetElasticArtifactVersion returns the current version:
@@ -348,14 +350,19 @@ func buildArtifactName(artifact string, artifactVersion string, OS string, arch
348350

349351
}
350352

351-
// fetchBeatsBinary it downloads the binary and returns the location of the downloaded file
353+
// FetchBeatsBinary it downloads the binary and returns the location of the downloaded file
352354
// If the environment variable BEATS_LOCAL_PATH is set, then the artifact
353355
// to be used will be defined by the local snapshot produced by the local build.
354356
// Else, if the environment variable GITHUB_CHECK_SHA1 is set, then the artifact
355357
// to be downloaded will be defined by the snapshot produced by the Beats CI for that commit.
358+
<<<<<<< HEAD
356359
func fetchBeatsBinary(ctx context.Context, artifactName string, artifact string, version string, timeoutFactor int, xpack bool) (string, error) {
357360
beatsLocalPath := shell.GetEnv("BEATS_LOCAL_PATH", "")
358361
if beatsLocalPath != "" {
362+
=======
363+
func FetchBeatsBinary(ctx context.Context, artifactName string, artifact string, version string, timeoutFactor int, xpack bool, downloadPath string, downloadSHAFile bool) (string, error) {
364+
if BeatsLocalPath != "" {
365+
>>>>>>> d3365c99 (Update `fetchBeatsBinary` to be reused in elastic-agent-poc (#1984))
359366
span, _ := apm.StartSpanOptions(ctx, "Fetching Beats binary", "beats.local.fetch-binary", apm.SpanOptions{
360367
Parent: apm.SpanFromContext(ctx).TraceContext(),
361368
})
@@ -378,6 +385,11 @@ func fetchBeatsBinary(ctx context.Context, artifactName string, artifact string,
378385
}
379386

380387
handleDownload := func(URL string) (string, error) {
388+
name := artifactName
389+
downloadRequest := utils.DownloadRequest{
390+
DownloadPath: downloadPath,
391+
URL: URL,
392+
}
381393
span, _ := apm.StartSpanOptions(ctx, "Fetching Beats binary", "beats.url.fetch-binary", apm.SpanOptions{
382394
Parent: apm.SpanFromContext(ctx).TraceContext(),
383395
})
@@ -391,28 +403,31 @@ func fetchBeatsBinary(ctx context.Context, artifactName string, artifact string,
391403
return val, nil
392404
}
393405

394-
filePathFull, err := utils.DownloadFile(URL)
406+
err := utils.DownloadFile(&downloadRequest)
395407
if err != nil {
396-
return filePathFull, err
408+
return downloadRequest.UnsanitizedFilePath, err
397409
}
398410

411+
if strings.HasSuffix(URL, ".sha512") {
412+
name = fmt.Sprintf("%s.sha512", name)
413+
}
399414
// use artifact name as file name to avoid having URL params in the name
400-
sanitizedFilePath := filepath.Join(path.Dir(filePathFull), artifactName)
401-
err = os.Rename(filePathFull, sanitizedFilePath)
415+
sanitizedFilePath := filepath.Join(path.Dir(downloadRequest.UnsanitizedFilePath), name)
416+
err = os.Rename(downloadRequest.UnsanitizedFilePath, sanitizedFilePath)
402417
if err != nil {
403418
log.WithFields(log.Fields{
404-
"fileName": filePathFull,
419+
"fileName": downloadRequest.UnsanitizedFilePath,
405420
"sanitizedFileName": sanitizedFilePath,
406421
}).Warn("Could not sanitize downloaded file name. Keeping old name")
407-
sanitizedFilePath = filePathFull
422+
sanitizedFilePath = downloadRequest.UnsanitizedFilePath
408423
}
409424

410425
binariesCache[URL] = sanitizedFilePath
411426

412427
return sanitizedFilePath, nil
413428
}
414429

415-
var downloadURL string
430+
var downloadURL, downloadShaURL string
416431
var err error
417432

418433
useCISnapshots := GithubCommitSha1 != ""
@@ -424,24 +439,41 @@ func fetchBeatsBinary(ctx context.Context, artifactName string, artifact string,
424439

425440
log.Debugf("Using CI snapshots for %s", artifact)
426441

427-
bucket, prefix, object := getGCPBucketCoordinates(artifactName, artifact)
428-
429442
maxTimeout := time.Duration(timeoutFactor) * time.Minute
430443

444+
bucket, prefix, object := getGCPBucketCoordinates(artifactName, artifact)
445+
431446
downloadURL, err = getObjectURLFromBucket(bucket, prefix, object, maxTimeout)
432447
if err != nil {
433448
return "", err
434449
}
450+
downloadLocation, err := handleDownload(downloadURL)
435451

452+
// check if sha file should be downloaded, else return
453+
if downloadSHAFile == false {
454+
return downloadLocation, err
455+
}
456+
457+
bucket, prefix, object = getGCPBucketCoordinates(fmt.Sprintf("%s.sha512", artifactName), artifact)
458+
downloadURL, err = getObjectURLFromBucket(bucket, prefix, object, maxTimeout)
459+
if err != nil {
460+
return "", err
461+
}
436462
return handleDownload(downloadURL)
437463
}
438464

439-
downloadURL, err = GetElasticArtifactURL(artifactName, artifact, version)
465+
downloadURL, downloadShaURL, err = GetElasticArtifactURL(artifactName, artifact, version)
440466
if err != nil {
441467
return "", err
442468
}
443-
444-
return handleDownload(downloadURL)
469+
downloadLocation, err := handleDownload(downloadURL)
470+
if err != nil {
471+
return "", err
472+
}
473+
if downloadSHAFile == true && downloadShaURL != "" {
474+
downloadLocation, err = handleDownload(downloadShaURL)
475+
}
476+
return downloadLocation, err
445477
}
446478

447479
func getBucketSearchNextPageParam(jsonParsed *gabs.Container) string {

0 commit comments

Comments
 (0)