From 3481dbc61a7210721ac02c8f1119fd9aa40a9d25 Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Wed, 7 Feb 2024 13:17:58 +0100 Subject: [PATCH] fix: fix setup for custom tofu versions (#8) --- go.mod | 2 +- plugin/impl.go | 3 ++- plugin/utils.go | 51 ++++++++++++++++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index e0b989a..5fc2e03 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.1 + github.com/rs/zerolog v1.31.0 github.com/thegeeklab/wp-plugin-go v1.5.0 github.com/urfave/cli/v2 v2.27.1 golang.org/x/sys v0.16.0 @@ -21,7 +22,6 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/reflectwalk v1.0.0 // indirect - github.com/rs/zerolog v1.31.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/spf13/cast v1.3.1 // indirect diff --git a/plugin/impl.go b/plugin/impl.go index c08531d..98a39e3 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -14,10 +14,11 @@ var ( ErrMaxSizeSizeLimit = errors.New("max size limit of decoded data exceeded") ErrActionUnknown = errors.New("action not found") ErrInvalidTofuVersion = errors.New("invalid version string") + ErrHTTPError = errors.New("http error") ) const ( - maxDecompressionSize = 1024 + maxDecompressionSize = 100 * 1024 * 1024 defaultDirPerm = 0o755 ) diff --git a/plugin/utils.go b/plugin/utils.go index 4083234..f04c34f 100644 --- a/plugin/utils.go +++ b/plugin/utils.go @@ -3,6 +3,7 @@ package plugin import ( "archive/zip" "context" + "errors" "fmt" "io" "net/http" @@ -11,29 +12,48 @@ import ( "strings" "github.com/Masterminds/semver/v3" + "github.com/rs/zerolog/log" ) func installPackage(ctx context.Context, client *http.Client, version string, maxSize int64) error { // Sanitize user input - if _, err := semver.NewVersion(version); err != nil { + semverVersion, err := semver.NewVersion(version) + if err != nil { return fmt.Errorf("%w: %v", ErrInvalidTofuVersion, version) } - err := downloadPackage( - ctx, - client, - "/tmp/tofu.zip", - fmt.Sprintf( - "https://github.com/opentofu/opentofu/releases/download/%s/tofu_%s_linux_amd64.zip", - version, - strings.TrimPrefix(version, ""), - ), + packageURL := fmt.Sprintf( + "https://github.com/opentofu/opentofu/releases/download/v%s/tofu_%s_linux_amd64.zip", + semverVersion.String(), + semverVersion.String(), ) + + tmpdir, err := os.MkdirTemp("/tmp", "tofu_dl_") if err != nil { - return err + return fmt.Errorf("failed to create tmp dir: %w", err) } - return unzip("/tmp/tofu.zip", "/bin", maxSize) + defer os.RemoveAll(tmpdir) + + log.Debug(). + Str("tmpdir", tmpdir). + Msgf("Download OpenTofu '%s' from URL '%s'", version, packageURL) + + tmpfile := filepath.Join(tmpdir, "tofu.zip") + + if err := downloadPackage(ctx, client, tmpfile, packageURL); err != nil { + return fmt.Errorf("failed to download: %w", err) + } + + if err := unzip(tmpfile, tmpdir, maxSize); err != nil { + return fmt.Errorf("failed to unzip: %w", err) + } + + if err := os.Rename(filepath.Join(tmpdir, "tofu"), tofuBin); err != nil { + return fmt.Errorf("failed to rename: %w", err) + } + + return nil } func downloadPackage(ctx context.Context, client *http.Client, filepath, url string) error { @@ -54,6 +74,11 @@ func downloadPackage(ctx context.Context, client *http.Client, filepath, url str if err != nil { return err } + + if resp.StatusCode > http.StatusBadRequest { + return fmt.Errorf("%w: %v", ErrHTTPError, resp.Status) + } + defer resp.Body.Close() // Writer the body to file @@ -113,7 +138,7 @@ func unzip(src, dest string, maxSize int64) error { }() written, err := io.CopyN(f, rc, maxSize) - if err != nil { + if err != nil && !errors.Is(err, io.EOF) { return err } else if written == maxSize { return fmt.Errorf("%w: %d", ErrMaxSizeSizeLimit, maxSize)