Skip to content

Commit

Permalink
Update lifecycle.DownloadBinary to work with local file (#5398)
Browse files Browse the repository at this point in the history
Signed-off-by: khanhtc1202 <[email protected]>
  • Loading branch information
khanhtc1202 authored Dec 9, 2024
1 parent dcecc2d commit 38af047
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 18 deletions.
53 changes: 37 additions & 16 deletions pkg/lifecycle/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -104,7 +105,7 @@ func RunBinary(ctx context.Context, execPath string, args []string) (*Command, e

// DownloadBinary downloads a file from the given URL into the specified path
// this also marks it executable and returns its full path.
func DownloadBinary(url, destDir, destFile string, logger *zap.Logger) (string, error) {
func DownloadBinary(sourceURL, destDir, destFile string, logger *zap.Logger) (string, error) {
if err := os.MkdirAll(destDir, 0755); err != nil {
return "", fmt.Errorf("could not create directory %s (%w)", destDir, err)
}
Expand Down Expand Up @@ -132,32 +133,52 @@ func DownloadBinary(url, destDir, destFile string, logger *zap.Logger) (string,
}
}()

logger.Info("downloading binary", zap.String("url", url))
logger.Info("downloading binary", zap.String("url", sourceURL))

req, err := http.NewRequest("GET", url, nil)
u, err := url.Parse(sourceURL)
if err != nil {
return "", fmt.Errorf("could not create request (%w)", err)
return "", fmt.Errorf("could not parse URL %s (%w)", sourceURL, err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("HTTP GET %s failed (%w)", url, err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("HTTP GET %s failed with error %d", url, resp.StatusCode)
}
switch u.Scheme {
case "http", "https":
req, err := http.NewRequest("GET", sourceURL, nil)
if err != nil {
return "", fmt.Errorf("could not create request (%w)", err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("HTTP GET %s failed (%w)", sourceURL, err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("HTTP GET %s failed with error %d", sourceURL, resp.StatusCode)
}

if _, err = io.Copy(tmpFile, resp.Body); err != nil {
return "", fmt.Errorf("could not copy from %s to %s (%w)", url, tmpName, err)
if _, err = io.Copy(tmpFile, resp.Body); err != nil {
return "", fmt.Errorf("could not copy from %s to %s (%w)", sourceURL, tmpName, err)
}

case "file":
data, err := os.ReadFile(u.Path)
if err != nil {
return "", fmt.Errorf("could not read file %s (%w)", u.Path, err)
}

if _, err = tmpFile.Write(data); err != nil {
return "", fmt.Errorf("could not write to %s (%w)", tmpName, err)
}

default:
return "", fmt.Errorf("unsupported file scheme %s", u.Scheme)
}

if err := os.Chmod(tmpName, 0755); err != nil {
return "", fmt.Errorf("could not chmod file %s (%w)", tmpName, err)
}

tmpFile.Close()
if err := os.Rename(tmpName, destPath); err != nil {
return "", fmt.Errorf("could not move %s to %s (%w)", tmpName, destPath, err)
}
Expand Down
37 changes: 35 additions & 2 deletions pkg/lifecycle/binary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"context"
"net/http"
"net/http/httptest"
"os"
"path"
"strconv"
"testing"
"time"
Expand Down Expand Up @@ -91,17 +93,19 @@ func TestDownloadBinary(t *testing.T) {
defer server.Close()

logger := zaptest.NewLogger(t)
destDir := t.TempDir()
destFile := "test-binary"

t.Run("successful download", func(t *testing.T) {
destDir := t.TempDir()
destFile := "test-binary"
url := server.URL + "/binary"
path, err := DownloadBinary(url, destDir, destFile, logger)
require.NoError(t, err)
assert.FileExists(t, path)
})

t.Run("file already exists", func(t *testing.T) {
destDir := t.TempDir()
destFile := "test-binary"
url := server.URL + "/binary"
path, err := DownloadBinary(url, destDir, destFile, logger)
require.NoError(t, err)
Expand All @@ -112,6 +116,35 @@ func TestDownloadBinary(t *testing.T) {
require.NoError(t, err)
assert.FileExists(t, path)
})

t.Run("file on local", func(t *testing.T) {
sourceDir := t.TempDir()
sourceFile := "test-binary"
sourcePath := path.Join(sourceDir, sourceFile)
err := os.WriteFile(sourcePath, []byte("test binary content"), 0755)
require.NoError(t, err)

destDir := t.TempDir()
destFile := "test-binary"
url := "file://" + sourcePath

path, err := DownloadBinary(url, destDir, destFile, logger)
require.NoError(t, err)
assert.FileExists(t, path)
content, err := os.ReadFile(path)
require.NoError(t, err)
assert.Equal(t, "test binary content", string(content))
})

t.Run("not valid source url given", func(t *testing.T) {
destDir := t.TempDir()
destFile := "test-binary"
url := "ftp://invalid-url"

path, err := DownloadBinary(url, destDir, destFile, logger)
require.Error(t, err)
assert.Empty(t, path)
})
}

func httpTestServer() *httptest.Server {
Expand Down

0 comments on commit 38af047

Please sign in to comment.