From b3ae11bc3d76df9aaf5175daa44f675dac08fec1 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 7 Aug 2023 08:57:19 -0400 Subject: [PATCH 01/14] releases: support enterprise versions --- internal/releasesjson/releases.go | 20 --------- internal/releasesjson/releases_test.go | 18 +++++--- releases/latest_version.go | 18 ++++++++ releases/latest_version_test.go | 62 ++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 27 deletions(-) diff --git a/internal/releasesjson/releases.go b/internal/releasesjson/releases.go index acbb676..755019f 100644 --- a/internal/releasesjson/releases.go +++ b/internal/releasesjson/releases.go @@ -115,13 +115,6 @@ func (r *Releases) ListProductVersions(ctx context.Context, productName string) continue } - if ok, _ := versionIsSupported(v); !ok { - // Remove (currently unsupported) enterprise - // version and any other "custom" build - delete(p.Versions, rawVersion) - continue - } - p.Versions[rawVersion].Version = v } @@ -129,10 +122,6 @@ func (r *Releases) ListProductVersions(ctx context.Context, productName string) } func (r *Releases) GetProductVersion(ctx context.Context, product string, version *version.Version) (*ProductVersion, error) { - if ok, err := versionIsSupported(version); !ok { - return nil, fmt.Errorf("%s: %w", product, err) - } - client := httpclient.NewHTTPClient() indexURL := fmt.Sprintf("%s/%s/%s/index.json", @@ -178,12 +167,3 @@ func (r *Releases) GetProductVersion(ctx context.Context, product string, versio return pv, nil } - -func versionIsSupported(v *version.Version) (bool, error) { - isSupported := v.Metadata() == "" - if !isSupported { - return false, fmt.Errorf("cannot obtain %s (enterprise versions are not supported)", - v.String()) - } - return true, nil -} diff --git a/internal/releasesjson/releases_test.go b/internal/releasesjson/releases_test.go index 5142fd7..aaa6768 100644 --- a/internal/releasesjson/releases_test.go +++ b/internal/releasesjson/releases_test.go @@ -11,7 +11,7 @@ import ( "github.com/hashicorp/hc-install/internal/testutil" ) -func TestListProductVersions_excludesEnterpriseBuilds(t *testing.T) { +func TestListProductVersions_includesEnterpriseBuilds(t *testing.T) { testutil.EndToEndTest(t) r := NewReleases() @@ -25,12 +25,12 @@ func TestListProductVersions_excludesEnterpriseBuilds(t *testing.T) { testEntVersion := "1.9.8+ent" _, ok := pVersions[testEntVersion] - if ok { - t.Fatalf("Found unexpected Consul Enterprise version %q", testEntVersion) + if !ok { + t.Fatalf("Failed to find expected Consul Enterprise version %q", testEntVersion) } } -func TestGetProductVersion_excludesEnterpriseBuild(t *testing.T) { +func TestGetProductVersion_includesEnterpriseBuild(t *testing.T) { testutil.EndToEndTest(t) r := NewReleases() @@ -40,9 +40,13 @@ func TestGetProductVersion_excludesEnterpriseBuild(t *testing.T) { testEntVersion := version.Must(version.NewVersion("1.9.8+ent")) - _, err := r.GetProductVersion(ctx, "consul", testEntVersion) - if err == nil { - t.Fatalf("Expected enterprise version %q to error out", + version, err := r.GetProductVersion(ctx, "consul", testEntVersion) + if err != nil { + t.Fatalf("Unexpected error getting enterprise version %q", testEntVersion.String()) } + + if version.RawVersion != testEntVersion.Original() { + t.Fatalf("Expected version %q, got %q", testEntVersion.String(), version.Version.String()) + } } diff --git a/releases/latest_version.go b/releases/latest_version.go index 0dc1ffa..65fc3f3 100644 --- a/releases/latest_version.go +++ b/releases/latest_version.go @@ -27,6 +27,8 @@ type LatestVersion struct { InstallDir string Timeout time.Duration IncludePrereleases bool + Enterprise bool // Require "+ent" suffix? + EnterpriseMeta string // "hsm", "fips1402", "hsm.fips1402", etc. SkipChecksumVerification bool @@ -156,6 +158,7 @@ func (lv *LatestVersion) Remove(ctx context.Context) error { } func (lv *LatestVersion) findLatestMatchingVersion(pvs rjson.ProductVersionsMap, vc version.Constraints) (*rjson.ProductVersion, bool) { + requiredMetadata := lv.requiredMetadata() versions := make(version.Collection, 0) for _, pv := range pvs.AsSlice() { if !lv.IncludePrereleases && pv.Version.Prerelease() != "" { @@ -163,6 +166,10 @@ func (lv *LatestVersion) findLatestMatchingVersion(pvs rjson.ProductVersionsMap, continue } + if pv.Version.Metadata() != requiredMetadata { + continue + } + versions = append(versions, pv.Version) } @@ -175,3 +182,14 @@ func (lv *LatestVersion) findLatestMatchingVersion(pvs rjson.ProductVersionsMap, return pvs[latestVersion.Original()], true } + +func (lv *LatestVersion) requiredMetadata() string { + metadata := "" + if lv.Enterprise { + metadata += "ent" + } + if lv.EnterpriseMeta != "" { + metadata += "." + lv.EnterpriseMeta + } + return metadata +} diff --git a/releases/latest_version_test.go b/releases/latest_version_test.go index 4ca20e9..d6b6915 100644 --- a/releases/latest_version_test.go +++ b/releases/latest_version_test.go @@ -7,6 +7,8 @@ import ( "fmt" "testing" + "github.com/hashicorp/go-version" + rjson "github.com/hashicorp/hc-install/internal/releasesjson" "github.com/hashicorp/hc-install/product" ) @@ -64,3 +66,63 @@ func TestLatestVersionValidate(t *testing.T) { }) } } + +func TestLatestVersion_FindLatestMatchingVersion(t *testing.T) { + t.Parallel() + + possibleVersions := rjson.ProductVersionsMap{ + "1.14.0": &rjson.ProductVersion{ + Version: version.Must(version.NewVersion("1.14.0")), + }, + "1.14.1": &rjson.ProductVersion{ + Version: version.Must(version.NewVersion("1.14.1")), + }, + "1.14.1+ent": &rjson.ProductVersion{ + Version: version.Must(version.NewVersion("1.14.1+ent")), + }, + "1.14.1+ent.fips1402": &rjson.ProductVersion{ + Version: version.Must(version.NewVersion("1.14.1+ent.fips1402")), + }, + } + + testCases := map[string]struct { + lv LatestVersion + expectedVersion string + }{ + "oss": { + lv: LatestVersion{ + Product: product.Vault, + }, + expectedVersion: "1.14.1", + }, + "enterprise": { + lv: LatestVersion{ + Product: product.Vault, + Enterprise: true, + }, + expectedVersion: "1.14.1+ent", + }, + "enterprise-fips1402": { + lv: LatestVersion{ + Product: product.Vault, + Enterprise: true, + EnterpriseMeta: "fips1402", + }, + expectedVersion: "1.14.1+ent.fips1402", + }, + } + + for name, testCase := range testCases { + name, testCase := name, testCase + + t.Run(name, func(t *testing.T) { + t.Parallel() + + latest, _ := testCase.lv.findLatestMatchingVersion(possibleVersions, testCase.lv.Constraints) + + if latest.Version.Original() != testCase.expectedVersion { + t.Fatalf("expected version %s, got %s", testCase.expectedVersion, latest.Version.Original()) + } + }) + } +} From 83cd6423baa8dcea590ea1ef6ef3fb954d30a575 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 28 Aug 2023 10:15:01 -0400 Subject: [PATCH 02/14] releases: refactor enterprise options into struct --- releases/enterprise.go | 17 +++++++++++++++++ releases/latest_version.go | 16 ++-------------- releases/latest_version_test.go | 14 +++++++++----- 3 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 releases/enterprise.go diff --git a/releases/enterprise.go b/releases/enterprise.go new file mode 100644 index 0000000..e5b6c3b --- /dev/null +++ b/releases/enterprise.go @@ -0,0 +1,17 @@ +package releases + +type EnterpriseOptions struct { + Enterprise bool + Meta string // optional; may be "hsm", "fips1402", "hsm.fips1402", etc. +} + +func (eo *EnterpriseOptions) requiredMetadata() string { + metadata := "" + if eo.Enterprise { + metadata += "ent" + } + if eo.Meta != "" { + metadata += "." + eo.Meta + } + return metadata +} diff --git a/releases/latest_version.go b/releases/latest_version.go index 65fc3f3..1c47af1 100644 --- a/releases/latest_version.go +++ b/releases/latest_version.go @@ -27,8 +27,7 @@ type LatestVersion struct { InstallDir string Timeout time.Duration IncludePrereleases bool - Enterprise bool // Require "+ent" suffix? - EnterpriseMeta string // "hsm", "fips1402", "hsm.fips1402", etc. + Enterprise EnterpriseOptions SkipChecksumVerification bool @@ -158,7 +157,7 @@ func (lv *LatestVersion) Remove(ctx context.Context) error { } func (lv *LatestVersion) findLatestMatchingVersion(pvs rjson.ProductVersionsMap, vc version.Constraints) (*rjson.ProductVersion, bool) { - requiredMetadata := lv.requiredMetadata() + requiredMetadata := lv.Enterprise.requiredMetadata() versions := make(version.Collection, 0) for _, pv := range pvs.AsSlice() { if !lv.IncludePrereleases && pv.Version.Prerelease() != "" { @@ -182,14 +181,3 @@ func (lv *LatestVersion) findLatestMatchingVersion(pvs rjson.ProductVersionsMap, return pvs[latestVersion.Original()], true } - -func (lv *LatestVersion) requiredMetadata() string { - metadata := "" - if lv.Enterprise { - metadata += "ent" - } - if lv.EnterpriseMeta != "" { - metadata += "." + lv.EnterpriseMeta - } - return metadata -} diff --git a/releases/latest_version_test.go b/releases/latest_version_test.go index d6b6915..1245376 100644 --- a/releases/latest_version_test.go +++ b/releases/latest_version_test.go @@ -97,16 +97,20 @@ func TestLatestVersion_FindLatestMatchingVersion(t *testing.T) { }, "enterprise": { lv: LatestVersion{ - Product: product.Vault, - Enterprise: true, + Product: product.Vault, + Enterprise: EnterpriseOptions{ + Enterprise: true, + }, }, expectedVersion: "1.14.1+ent", }, "enterprise-fips1402": { lv: LatestVersion{ - Product: product.Vault, - Enterprise: true, - EnterpriseMeta: "fips1402", + Product: product.Vault, + Enterprise: EnterpriseOptions{ + Enterprise: true, + Meta: "fips1402", + }, }, expectedVersion: "1.14.1+ent.fips1402", }, From c5b5e155442074837680fed23d71a4fee7692992 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 28 Aug 2023 11:49:38 -0400 Subject: [PATCH 03/14] fix: readme spelling/grammar --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d3012d7..6d1dcbd 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,14 @@ Each comes with different trade-offs described below. - **Pros:** - Fast and reliable way of obtaining any pre-built version of any product - **Cons:** - - Installation may consume some bandwith, disk space and a little time + - Installation may consume some bandwidth, disk space and a little time - Potentially less stable builds (see `checkpoint` below) - `checkpoint.LatestVersion` - Downloads, verifies & installs any known product available in HashiCorp Checkpoint - **Pros:** - Checkpoint typically contains only product versions considered stable - **Cons:** - - Installation may consume some bandwith, disk space and a little time - - Currently doesn't allow installation of a old versions (see `releases` above) + - Installation may consume some bandwidth, disk space and a little time + - Currently doesn't allow installation of old versions (see `releases` above) - `build.GitRevision` - Clones raw source code and builds the product from it - **Pros:** - Useful for catching bugs and incompatibilities as early as possible (prior to product release). From b4efdfbd2f5c440ccf822387bd0192efcf9600c4 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 28 Aug 2023 11:11:48 -0400 Subject: [PATCH 04/14] releases: support enterprise options for ExactVersion and Versions --- README.md | 3 ++- releases/exact_version.go | 21 ++++++++++++++++- releases/versions.go | 9 +++++++ releases/versions_test.go | 49 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6d1dcbd..6e78b5a 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Each comes with different trade-offs described below. - `releases.{LatestVersion,ExactVersion}` - Downloads, verifies & installs any known product from `releases.hashicorp.com` - **Pros:** - Fast and reliable way of obtaining any pre-built version of any product + - Allows installation of enterprise versions - **Cons:** - Installation may consume some bandwidth, disk space and a little time - Potentially less stable builds (see `checkpoint` below) @@ -49,7 +50,7 @@ Each comes with different trade-offs described below. - Checkpoint typically contains only product versions considered stable - **Cons:** - Installation may consume some bandwidth, disk space and a little time - - Currently doesn't allow installation of old versions (see `releases` above) + - Currently doesn't allow installation of old versions or enterprise versions (see `releases` above) - `build.GitRevision` - Clones raw source code and builds the product from it - **Pros:** - Useful for catching bugs and incompatibilities as early as possible (prior to product release). diff --git a/releases/exact_version.go b/releases/exact_version.go index 0311123..4d71ced 100644 --- a/releases/exact_version.go +++ b/releases/exact_version.go @@ -27,6 +27,7 @@ type ExactVersion struct { Version *version.Version InstallDir string Timeout time.Duration + Enterprise EnterpriseOptions SkipChecksumVerification bool @@ -100,7 +101,7 @@ func (ev *ExactVersion) Install(ctx context.Context) (string, error) { rels.BaseURL = ev.apiBaseURL } rels.SetLogger(ev.log()) - pv, err := rels.GetProductVersion(ctx, ev.Product.Name, ev.Version) + pv, err := rels.GetProductVersion(ctx, ev.Product.Name, versionWithMetadata(ev.Version, ev.Enterprise.requiredMetadata())) if err != nil { return "", err } @@ -151,3 +152,21 @@ func (ev *ExactVersion) Remove(ctx context.Context) error { return nil } + +// versionWithMetadata returns a new version by combining the given version with the given metadata +func versionWithMetadata(v *version.Version, metadata string) *version.Version { + if v == nil { + return nil + } + + if metadata == "" { + return v + } + + v2, err := version.NewVersion(fmt.Sprintf("%s+%s", v.Core(), metadata)) + if err != nil { + return nil + } + + return v2 +} diff --git a/releases/versions.go b/releases/versions.go index 9084c91..ab416ec 100644 --- a/releases/versions.go +++ b/releases/versions.go @@ -21,6 +21,7 @@ import ( type Versions struct { Product product.Product Constraints version.Constraints + Enterprise EnterpriseOptions ListTimeout time.Duration @@ -61,6 +62,8 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { versions := pvs.AsSlice() sort.Stable(versions) + requiredMetadata := v.Enterprise.requiredMetadata() + installables := make([]src.Source, 0) for _, pv := range versions { if !v.Constraints.Check(pv.Version) { @@ -68,11 +71,17 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { continue } + if pv.Version.Metadata() != requiredMetadata { + // skip version which doesn't match required metadata for enterprise or OSS versions + continue + } + ev := &ExactVersion{ Product: v.Product, Version: pv.Version, InstallDir: v.Install.Dir, Timeout: v.Install.Timeout, + Enterprise: v.Enterprise, ArmoredPublicKey: v.Install.ArmoredPublicKey, SkipChecksumVerification: v.Install.SkipChecksumVerification, diff --git a/releases/versions_test.go b/releases/versions_test.go index 4b1989c..e43c5f9 100644 --- a/releases/versions_test.go +++ b/releases/versions_test.go @@ -50,6 +50,55 @@ func TestVersions_List(t *testing.T) { } } +func TestVersions_List_enterprise(t *testing.T) { + testutil.EndToEndTest(t) + + cons, err := version.NewConstraint(">= 1.9.0, < 1.9.9") + if err != nil { + t.Fatal(err) + } + + versions := &Versions{ + Product: product.Vault, + Constraints: cons, + Enterprise: EnterpriseOptions{ + Enterprise: true, + Meta: "hsm", + }, + } + + ctx := context.Background() + sources, err := versions.List(ctx) + if err != nil { + t.Fatal(err) + } + + expectedVersions := []string{ + "1.9.0+ent.hsm", + "1.9.1+ent.hsm", + "1.9.2+ent.hsm", + "1.9.3+ent.hsm", + "1.9.4+ent.hsm", + "1.9.5+ent.hsm", + "1.9.6+ent.hsm", + "1.9.7+ent.hsm", + "1.9.8+ent.hsm", + } + if diff := cmp.Diff(expectedVersions, sourcesToRawVersions(sources)); diff != "" { + t.Fatalf("unexpected versions: %s", diff) + } + + for _, source := range sources { + if source.(*ExactVersion).Enterprise != versions.Enterprise { + t.Fatalf("unexpected Enterprise data: %v", source.(*ExactVersion).Enterprise) + } + + if &source.(*ExactVersion).Enterprise == &versions.Enterprise { + t.Fatalf("the Enterprise data should be copied, not referenced") + } + } +} + func sourcesToRawVersions(srcs []src.Source) []string { rawVersions := make([]string, len(srcs)) From 1dbbc3a8a0c41c6db51674459a216457e75c5f87 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 28 Aug 2023 11:10:46 -0400 Subject: [PATCH 05/14] releases: require enterprise license installation --- checkpoint/latest_version.go | 2 +- internal/releasesjson/downloader.go | 26 +++++++++++++++++++++++++- releases/enterprise.go | 12 ++++++++++++ releases/exact_version.go | 6 +++++- releases/exact_version_test.go | 10 ++++++++++ releases/latest_version.go | 6 +++++- releases/latest_version_test.go | 9 +++++++++ releases/versions.go | 4 ++++ releases/versions_test.go | 1 + 9 files changed, 72 insertions(+), 4 deletions(-) diff --git a/checkpoint/latest_version.go b/checkpoint/latest_version.go index 23c6891..2cd5379 100644 --- a/checkpoint/latest_version.go +++ b/checkpoint/latest_version.go @@ -126,7 +126,7 @@ func (lv *LatestVersion) Install(ctx context.Context) (string, error) { if lv.ArmoredPublicKey != "" { d.ArmoredPublicKey = lv.ArmoredPublicKey } - zipFilePath, err := d.DownloadAndUnpack(ctx, pv, dstDir) + zipFilePath, err := d.DownloadAndUnpack(ctx, pv, dstDir, "") if zipFilePath != "" { lv.pathsToRemove = append(lv.pathsToRemove, zipFilePath) } diff --git a/internal/releasesjson/downloader.go b/internal/releasesjson/downloader.go index c5d71b3..f462ccd 100644 --- a/internal/releasesjson/downloader.go +++ b/internal/releasesjson/downloader.go @@ -29,7 +29,7 @@ type Downloader struct { BaseURL string } -func (d *Downloader) DownloadAndUnpack(ctx context.Context, pv *ProductVersion, dstDir string) (zipFilePath string, err error) { +func (d *Downloader) DownloadAndUnpack(ctx context.Context, pv *ProductVersion, binDir string, licenseDir string) (zipFilePath string, err error) { if len(pv.Builds) == 0 { return "", fmt.Errorf("no builds found for %s %s", pv.Name, pv.Version) } @@ -166,6 +166,14 @@ func (d *Downloader) DownloadAndUnpack(ctx context.Context, pv *ProductVersion, return pkgFilePath, err } + // Determine the appropriate destination file path + var dstDir string + if isLicenseFile(f.Name) && licenseDir != "" { + dstDir = licenseDir + } else { + dstDir = binDir + } + d.Logger.Printf("unpacking %s to %s", f.Name, dstDir) dstPath := filepath.Join(dstDir, f.Name) dstFile, err := os.Create(dstPath) @@ -200,3 +208,19 @@ func contentTypeIsZip(contentType string) bool { } return false } + +// Enterprise products have a few additional license files +// that need to be extracted to a separate directory +var licenseFiles = []string{ + "EULA.txt", + "TermsOfEvaluation.txt", +} + +func isLicenseFile(filename string) bool { + for _, lf := range licenseFiles { + if lf == filename { + return true + } + } + return false +} diff --git a/releases/enterprise.go b/releases/enterprise.go index e5b6c3b..526d96e 100644 --- a/releases/enterprise.go +++ b/releases/enterprise.go @@ -1,8 +1,13 @@ package releases +import ( + "fmt" +) + type EnterpriseOptions struct { Enterprise bool Meta string // optional; may be "hsm", "fips1402", "hsm.fips1402", etc. + LicenseDir string // required when Enterprise is true } func (eo *EnterpriseOptions) requiredMetadata() string { @@ -15,3 +20,10 @@ func (eo *EnterpriseOptions) requiredMetadata() string { } return metadata } + +func (eo *EnterpriseOptions) validate() error { + if eo.Enterprise && eo.LicenseDir == "" { + return fmt.Errorf("license dir must be provided when requesting enterprise versions") + } + return nil +} diff --git a/releases/exact_version.go b/releases/exact_version.go index 4d71ced..32de484 100644 --- a/releases/exact_version.go +++ b/releases/exact_version.go @@ -68,6 +68,10 @@ func (ev *ExactVersion) Validate() error { return fmt.Errorf("unknown version") } + if err := ev.Enterprise.validate(); err != nil { + return err + } + return nil } @@ -119,7 +123,7 @@ func (ev *ExactVersion) Install(ctx context.Context) (string, error) { d.BaseURL = ev.apiBaseURL } - zipFilePath, err := d.DownloadAndUnpack(ctx, pv, dstDir) + zipFilePath, err := d.DownloadAndUnpack(ctx, pv, dstDir, ev.Enterprise.LicenseDir) if zipFilePath != "" { ev.pathsToRemove = append(ev.pathsToRemove, zipFilePath) } diff --git a/releases/exact_version_test.go b/releases/exact_version_test.go index 6efd573..e60a032 100644 --- a/releases/exact_version_test.go +++ b/releases/exact_version_test.go @@ -48,6 +48,16 @@ func TestExactVersionValidate(t *testing.T) { }, expectedErr: fmt.Errorf("unknown version"), }, + "Enterprise-missing-license-dir": { + ev: ExactVersion{ + Product: product.Vault, + Version: version.Must(version.NewVersion("1.9.8")), + Enterprise: EnterpriseOptions{ + Enterprise: true, + }, + }, + expectedErr: fmt.Errorf("license dir must be provided when requesting enterprise versions"), + }, } for name, testCase := range testCases { diff --git a/releases/latest_version.go b/releases/latest_version.go index 1c47af1..0d69a3c 100644 --- a/releases/latest_version.go +++ b/releases/latest_version.go @@ -64,6 +64,10 @@ func (lv *LatestVersion) Validate() error { return fmt.Errorf("invalid binary name: %q", lv.Product.BinaryName()) } + if err := lv.Enterprise.validate(); err != nil { + return err + } + return nil } @@ -123,7 +127,7 @@ func (lv *LatestVersion) Install(ctx context.Context) (string, error) { if lv.apiBaseURL != "" { d.BaseURL = lv.apiBaseURL } - zipFilePath, err := d.DownloadAndUnpack(ctx, versionToInstall, dstDir) + zipFilePath, err := d.DownloadAndUnpack(ctx, versionToInstall, dstDir, lv.Enterprise.LicenseDir) if zipFilePath != "" { lv.pathsToRemove = append(lv.pathsToRemove, zipFilePath) } diff --git a/releases/latest_version_test.go b/releases/latest_version_test.go index 1245376..90cd6c9 100644 --- a/releases/latest_version_test.go +++ b/releases/latest_version_test.go @@ -42,6 +42,15 @@ func TestLatestVersionValidate(t *testing.T) { Product: product.Terraform, }, }, + "Enterprise-missing-license-dir": { + lv: LatestVersion{ + Product: product.Vault, + Enterprise: EnterpriseOptions{ + Enterprise: true, + }, + }, + expectedErr: fmt.Errorf("license dir must be provided when requesting enterprise versions"), + }, } for name, testCase := range testCases { diff --git a/releases/versions.go b/releases/versions.go index ab416ec..a775e58 100644 --- a/releases/versions.go +++ b/releases/versions.go @@ -46,6 +46,10 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { return nil, fmt.Errorf("invalid product name: %q", v.Product.Name) } + if err := v.Enterprise.validate(); err != nil { + return nil, err + } + timeout := defaultListTimeout if v.ListTimeout > 0 { timeout = v.ListTimeout diff --git a/releases/versions_test.go b/releases/versions_test.go index e43c5f9..0ab6739 100644 --- a/releases/versions_test.go +++ b/releases/versions_test.go @@ -64,6 +64,7 @@ func TestVersions_List_enterprise(t *testing.T) { Enterprise: EnterpriseOptions{ Enterprise: true, Meta: "hsm", + LicenseDir: "/some/path", }, } From f480e9a9073192e1dcb04bd5b9ce00146f9e1e00 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 28 Aug 2023 11:56:32 -0400 Subject: [PATCH 06/14] releases: e2e test for enterprise installation --- installer_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/installer_test.go b/installer_test.go index f867ed6..2f0bda5 100644 --- a/installer_test.go +++ b/installer_test.go @@ -9,6 +9,7 @@ import ( "path/filepath" "testing" + "github.com/hashicorp/go-version" "github.com/hashicorp/hc-install" "github.com/hashicorp/hc-install/fs" "github.com/hashicorp/hc-install/internal/testutil" @@ -98,3 +99,49 @@ func TestInstaller_Install(t *testing.T) { t.Fatal(err) } } + +func TestInstaller_Install_enterprise(t *testing.T) { + testutil.EndToEndTest(t) + + // most of this logic is already tested within individual packages + // so this is just a simple E2E test to ensure the public API + // also works and continues working + + tmpBinaryDir := t.TempDir() + tmpLicenseDir := t.TempDir() + + i := install.NewInstaller() + i.SetLogger(testutil.TestLogger()) + ctx := context.Background() + _, err := i.Install(ctx, []src.Installable{ + &releases.ExactVersion{ + Product: product.Vault, + Version: version.Must(version.NewVersion("1.9.8")), + InstallDir: tmpBinaryDir, + Enterprise: releases.EnterpriseOptions{ + Enterprise: true, + LicenseDir: tmpLicenseDir, + }, + }, + }) + if err != nil { + t.Fatal(err) + } + + // Ensure the binary was installed + if _, err = os.Stat(filepath.Join(tmpBinaryDir, "vault")); err != nil { + t.Fatal(err) + } + // Ensure the enterprise license files were installed + if _, err = os.Stat(filepath.Join(tmpLicenseDir, "EULA.txt")); err != nil { + t.Fatal(err) + } + if _, err = os.Stat(filepath.Join(tmpLicenseDir, "TermsOfEvaluation.txt")); err != nil { + t.Fatal(err) + } + + err = i.Remove(ctx) + if err != nil { + t.Fatal(err) + } +} From 93622ccf1a67e0d4683f9bebd04df924f71b053f Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 28 Aug 2023 11:57:03 -0400 Subject: [PATCH 07/14] releases: example of installing enterprise versions --- installer_examples_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/installer_examples_test.go b/installer_examples_test.go index d3af29f..87dac54 100644 --- a/installer_examples_test.go +++ b/installer_examples_test.go @@ -131,3 +131,29 @@ func ExampleInstaller_installAndBuildMultipleVersions() { // run any tests } } + +// Installation of a single exact enterprise version +func ExampleInstaller_enterpriseVersion() { + ctx := context.Background() + i := install.NewInstaller() + defer i.Remove(ctx) + v1_9 := version.Must(version.NewVersion("1.9.8")) + licenseDir := "/some/path" + + execPath, err := i.Install(ctx, []src.Installable{ + &releases.ExactVersion{ + Product: product.Vault, + Version: v1_9, + Enterprise: releases.EnterpriseOptions{ + Enterprise: true, + LicenseDir: licenseDir, // required for enterprise versions + }, + }, + }) + if err != nil { + log.Fatal(err) + } + log.Printf("Vault %s Enterprise installed to %s; license information installed to %s", v1_9, execPath, licenseDir) + + // run any tests +} From 9a9a2d2a10d78765dd294a5d625d5cbf2cca54d4 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 29 Aug 2023 09:32:43 -0400 Subject: [PATCH 08/14] releases: add missing copywrite header --- releases/enterprise.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/releases/enterprise.go b/releases/enterprise.go index 526d96e..993ea24 100644 --- a/releases/enterprise.go +++ b/releases/enterprise.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package releases import ( From 667b17e80a300e93ef06079abccdb130f7b6cbc2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 29 Aug 2023 09:34:24 -0400 Subject: [PATCH 09/14] installer: fix failing windows test --- installer_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/installer_test.go b/installer_test.go index 2f0bda5..2422fe3 100644 --- a/installer_test.go +++ b/installer_test.go @@ -7,6 +7,7 @@ import ( "context" "os" "path/filepath" + "runtime" "testing" "github.com/hashicorp/go-version" @@ -129,7 +130,11 @@ func TestInstaller_Install_enterprise(t *testing.T) { } // Ensure the binary was installed - if _, err = os.Stat(filepath.Join(tmpBinaryDir, "vault")); err != nil { + binName := "vault" + if runtime.GOOS == "windows" { + binName = "vault.exe" + } + if _, err = os.Stat(filepath.Join(tmpBinaryDir, binName)); err != nil { t.Fatal(err) } // Ensure the enterprise license files were installed From 6aa31025c04422d12f66dcbacc376a11970f6d23 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 29 Aug 2023 09:35:33 -0400 Subject: [PATCH 10/14] simplify destination path conditional --- internal/releasesjson/downloader.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/releasesjson/downloader.go b/internal/releasesjson/downloader.go index f462ccd..146c1cf 100644 --- a/internal/releasesjson/downloader.go +++ b/internal/releasesjson/downloader.go @@ -167,11 +167,9 @@ func (d *Downloader) DownloadAndUnpack(ctx context.Context, pv *ProductVersion, } // Determine the appropriate destination file path - var dstDir string + dstDir := binDir if isLicenseFile(f.Name) && licenseDir != "" { dstDir = licenseDir - } else { - dstDir = binDir } d.Logger.Printf("unpacking %s to %s", f.Name, dstDir) From 2eaee3388b295d5dab85127a3d25b14b3b4b8bfb Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 29 Aug 2023 10:23:51 -0400 Subject: [PATCH 11/14] releases: make EnterpriseOptions a pointer instead --- installer_examples_test.go | 5 ++--- installer_test.go | 3 +-- releases/enterprise.go | 10 +++------- releases/exact_version.go | 20 +++++++++++++++----- releases/exact_version_test.go | 8 +++----- releases/latest_version.go | 20 +++++++++++++++----- releases/latest_version_test.go | 17 ++++++----------- releases/versions.go | 21 ++++++++++++++++----- releases/versions_test.go | 7 +++---- 9 files changed, 64 insertions(+), 47 deletions(-) diff --git a/installer_examples_test.go b/installer_examples_test.go index 87dac54..c3069c4 100644 --- a/installer_examples_test.go +++ b/installer_examples_test.go @@ -144,9 +144,8 @@ func ExampleInstaller_enterpriseVersion() { &releases.ExactVersion{ Product: product.Vault, Version: v1_9, - Enterprise: releases.EnterpriseOptions{ - Enterprise: true, - LicenseDir: licenseDir, // required for enterprise versions + Enterprise: &releases.EnterpriseOptions{ // specify that we want the enterprise version + LicenseDir: licenseDir, // where license files should be placed (required for enterprise versions) }, }, }) diff --git a/installer_test.go b/installer_test.go index 2422fe3..d29b776 100644 --- a/installer_test.go +++ b/installer_test.go @@ -119,8 +119,7 @@ func TestInstaller_Install_enterprise(t *testing.T) { Product: product.Vault, Version: version.Must(version.NewVersion("1.9.8")), InstallDir: tmpBinaryDir, - Enterprise: releases.EnterpriseOptions{ - Enterprise: true, + Enterprise: &releases.EnterpriseOptions{ LicenseDir: tmpLicenseDir, }, }, diff --git a/releases/enterprise.go b/releases/enterprise.go index 993ea24..16abc82 100644 --- a/releases/enterprise.go +++ b/releases/enterprise.go @@ -8,16 +8,12 @@ import ( ) type EnterpriseOptions struct { - Enterprise bool + LicenseDir string // required Meta string // optional; may be "hsm", "fips1402", "hsm.fips1402", etc. - LicenseDir string // required when Enterprise is true } func (eo *EnterpriseOptions) requiredMetadata() string { - metadata := "" - if eo.Enterprise { - metadata += "ent" - } + metadata := "ent" if eo.Meta != "" { metadata += "." + eo.Meta } @@ -25,7 +21,7 @@ func (eo *EnterpriseOptions) requiredMetadata() string { } func (eo *EnterpriseOptions) validate() error { - if eo.Enterprise && eo.LicenseDir == "" { + if eo.LicenseDir == "" { return fmt.Errorf("license dir must be provided when requesting enterprise versions") } return nil diff --git a/releases/exact_version.go b/releases/exact_version.go index 32de484..fbea4c0 100644 --- a/releases/exact_version.go +++ b/releases/exact_version.go @@ -27,7 +27,7 @@ type ExactVersion struct { Version *version.Version InstallDir string Timeout time.Duration - Enterprise EnterpriseOptions + Enterprise *EnterpriseOptions // require enterprise version if set (leave nil for OSS) SkipChecksumVerification bool @@ -68,8 +68,10 @@ func (ev *ExactVersion) Validate() error { return fmt.Errorf("unknown version") } - if err := ev.Enterprise.validate(); err != nil { - return err + if ev.Enterprise != nil { + if err := ev.Enterprise.validate(); err != nil { + return err + } } return nil @@ -105,7 +107,11 @@ func (ev *ExactVersion) Install(ctx context.Context) (string, error) { rels.BaseURL = ev.apiBaseURL } rels.SetLogger(ev.log()) - pv, err := rels.GetProductVersion(ctx, ev.Product.Name, versionWithMetadata(ev.Version, ev.Enterprise.requiredMetadata())) + installVersion := ev.Version + if ev.Enterprise != nil { + installVersion = versionWithMetadata(installVersion, ev.Enterprise.requiredMetadata()) + } + pv, err := rels.GetProductVersion(ctx, ev.Product.Name, installVersion) if err != nil { return "", err } @@ -123,7 +129,11 @@ func (ev *ExactVersion) Install(ctx context.Context) (string, error) { d.BaseURL = ev.apiBaseURL } - zipFilePath, err := d.DownloadAndUnpack(ctx, pv, dstDir, ev.Enterprise.LicenseDir) + licenseDir := "" + if ev.Enterprise != nil { + licenseDir = ev.Enterprise.LicenseDir + } + zipFilePath, err := d.DownloadAndUnpack(ctx, pv, dstDir, licenseDir) if zipFilePath != "" { ev.pathsToRemove = append(ev.pathsToRemove, zipFilePath) } diff --git a/releases/exact_version_test.go b/releases/exact_version_test.go index e60a032..556ca05 100644 --- a/releases/exact_version_test.go +++ b/releases/exact_version_test.go @@ -50,11 +50,9 @@ func TestExactVersionValidate(t *testing.T) { }, "Enterprise-missing-license-dir": { ev: ExactVersion{ - Product: product.Vault, - Version: version.Must(version.NewVersion("1.9.8")), - Enterprise: EnterpriseOptions{ - Enterprise: true, - }, + Product: product.Vault, + Version: version.Must(version.NewVersion("1.9.8")), + Enterprise: &EnterpriseOptions{}, }, expectedErr: fmt.Errorf("license dir must be provided when requesting enterprise versions"), }, diff --git a/releases/latest_version.go b/releases/latest_version.go index 0d69a3c..7b5578a 100644 --- a/releases/latest_version.go +++ b/releases/latest_version.go @@ -27,7 +27,7 @@ type LatestVersion struct { InstallDir string Timeout time.Duration IncludePrereleases bool - Enterprise EnterpriseOptions + Enterprise *EnterpriseOptions // require enterprise version if set (leave nil for OSS) SkipChecksumVerification bool @@ -64,8 +64,10 @@ func (lv *LatestVersion) Validate() error { return fmt.Errorf("invalid binary name: %q", lv.Product.BinaryName()) } - if err := lv.Enterprise.validate(); err != nil { - return err + if lv.Enterprise != nil { + if err := lv.Enterprise.validate(); err != nil { + return err + } } return nil @@ -127,7 +129,11 @@ func (lv *LatestVersion) Install(ctx context.Context) (string, error) { if lv.apiBaseURL != "" { d.BaseURL = lv.apiBaseURL } - zipFilePath, err := d.DownloadAndUnpack(ctx, versionToInstall, dstDir, lv.Enterprise.LicenseDir) + licenseDir := "" + if lv.Enterprise != nil { + licenseDir = lv.Enterprise.LicenseDir + } + zipFilePath, err := d.DownloadAndUnpack(ctx, versionToInstall, dstDir, licenseDir) if zipFilePath != "" { lv.pathsToRemove = append(lv.pathsToRemove, zipFilePath) } @@ -161,7 +167,11 @@ func (lv *LatestVersion) Remove(ctx context.Context) error { } func (lv *LatestVersion) findLatestMatchingVersion(pvs rjson.ProductVersionsMap, vc version.Constraints) (*rjson.ProductVersion, bool) { - requiredMetadata := lv.Enterprise.requiredMetadata() + requiredMetadata := "" + if lv.Enterprise != nil { + requiredMetadata = lv.Enterprise.requiredMetadata() + } + versions := make(version.Collection, 0) for _, pv := range pvs.AsSlice() { if !lv.IncludePrereleases && pv.Version.Prerelease() != "" { diff --git a/releases/latest_version_test.go b/releases/latest_version_test.go index 90cd6c9..1443d49 100644 --- a/releases/latest_version_test.go +++ b/releases/latest_version_test.go @@ -44,10 +44,8 @@ func TestLatestVersionValidate(t *testing.T) { }, "Enterprise-missing-license-dir": { lv: LatestVersion{ - Product: product.Vault, - Enterprise: EnterpriseOptions{ - Enterprise: true, - }, + Product: product.Vault, + Enterprise: &EnterpriseOptions{}, }, expectedErr: fmt.Errorf("license dir must be provided when requesting enterprise versions"), }, @@ -106,19 +104,16 @@ func TestLatestVersion_FindLatestMatchingVersion(t *testing.T) { }, "enterprise": { lv: LatestVersion{ - Product: product.Vault, - Enterprise: EnterpriseOptions{ - Enterprise: true, - }, + Product: product.Vault, + Enterprise: &EnterpriseOptions{}, }, expectedVersion: "1.14.1+ent", }, "enterprise-fips1402": { lv: LatestVersion{ Product: product.Vault, - Enterprise: EnterpriseOptions{ - Enterprise: true, - Meta: "fips1402", + Enterprise: &EnterpriseOptions{ + Meta: "fips1402", }, }, expectedVersion: "1.14.1+ent.fips1402", diff --git a/releases/versions.go b/releases/versions.go index a775e58..bda0df7 100644 --- a/releases/versions.go +++ b/releases/versions.go @@ -21,7 +21,7 @@ import ( type Versions struct { Product product.Product Constraints version.Constraints - Enterprise EnterpriseOptions + Enterprise *EnterpriseOptions // require enterprise version if set (leave nil for OSS) ListTimeout time.Duration @@ -46,8 +46,10 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { return nil, fmt.Errorf("invalid product name: %q", v.Product.Name) } - if err := v.Enterprise.validate(); err != nil { - return nil, err + if v.Enterprise != nil { + if err := v.Enterprise.validate(); err != nil { + return nil, err + } } timeout := defaultListTimeout @@ -66,7 +68,10 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { versions := pvs.AsSlice() sort.Stable(versions) - requiredMetadata := v.Enterprise.requiredMetadata() + requiredMetadata := "" + if v.Enterprise != nil { + requiredMetadata = v.Enterprise.requiredMetadata() + } installables := make([]src.Source, 0) for _, pv := range versions { @@ -85,12 +90,18 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { Version: pv.Version, InstallDir: v.Install.Dir, Timeout: v.Install.Timeout, - Enterprise: v.Enterprise, ArmoredPublicKey: v.Install.ArmoredPublicKey, SkipChecksumVerification: v.Install.SkipChecksumVerification, } + if v.Enterprise != nil { + ev.Enterprise = &EnterpriseOptions{ + Meta: v.Enterprise.Meta, + LicenseDir: v.Enterprise.LicenseDir, + } + } + installables = append(installables, ev) } diff --git a/releases/versions_test.go b/releases/versions_test.go index 0ab6739..5ba23f9 100644 --- a/releases/versions_test.go +++ b/releases/versions_test.go @@ -61,8 +61,7 @@ func TestVersions_List_enterprise(t *testing.T) { versions := &Versions{ Product: product.Vault, Constraints: cons, - Enterprise: EnterpriseOptions{ - Enterprise: true, + Enterprise: &EnterpriseOptions{ Meta: "hsm", LicenseDir: "/some/path", }, @@ -90,11 +89,11 @@ func TestVersions_List_enterprise(t *testing.T) { } for _, source := range sources { - if source.(*ExactVersion).Enterprise != versions.Enterprise { + if *source.(*ExactVersion).Enterprise != *versions.Enterprise { t.Fatalf("unexpected Enterprise data: %v", source.(*ExactVersion).Enterprise) } - if &source.(*ExactVersion).Enterprise == &versions.Enterprise { + if source.(*ExactVersion).Enterprise == versions.Enterprise { t.Fatalf("the Enterprise data should be copied, not referenced") } } From ca8e21bc3daf0f0839ab1f80b7b75a6918851da4 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 29 Aug 2023 10:24:07 -0400 Subject: [PATCH 12/14] fix error messages --- releases/enterprise.go | 2 +- releases/exact_version_test.go | 2 +- releases/latest_version_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/enterprise.go b/releases/enterprise.go index 16abc82..1bd58d6 100644 --- a/releases/enterprise.go +++ b/releases/enterprise.go @@ -22,7 +22,7 @@ func (eo *EnterpriseOptions) requiredMetadata() string { func (eo *EnterpriseOptions) validate() error { if eo.LicenseDir == "" { - return fmt.Errorf("license dir must be provided when requesting enterprise versions") + return fmt.Errorf("LicenseDir must be provided when requesting enterprise versions") } return nil } diff --git a/releases/exact_version_test.go b/releases/exact_version_test.go index 556ca05..003344e 100644 --- a/releases/exact_version_test.go +++ b/releases/exact_version_test.go @@ -54,7 +54,7 @@ func TestExactVersionValidate(t *testing.T) { Version: version.Must(version.NewVersion("1.9.8")), Enterprise: &EnterpriseOptions{}, }, - expectedErr: fmt.Errorf("license dir must be provided when requesting enterprise versions"), + expectedErr: fmt.Errorf("LicenseDir must be provided when requesting enterprise versions"), }, } diff --git a/releases/latest_version_test.go b/releases/latest_version_test.go index 1443d49..71760c2 100644 --- a/releases/latest_version_test.go +++ b/releases/latest_version_test.go @@ -47,7 +47,7 @@ func TestLatestVersionValidate(t *testing.T) { Product: product.Vault, Enterprise: &EnterpriseOptions{}, }, - expectedErr: fmt.Errorf("license dir must be provided when requesting enterprise versions"), + expectedErr: fmt.Errorf("LicenseDir must be provided when requesting enterprise versions"), }, } From 0212924a663ed614ed55d64deca9dfcdd7dfd79d Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Thu, 31 Aug 2023 10:56:43 +0100 Subject: [PATCH 13/14] refactoring: reduce nil checks --- releases/enterprise.go | 24 +++++++++++++++++------- releases/exact_version.go | 12 ++++++------ releases/latest_version.go | 18 +++++++----------- releases/versions.go | 21 +++++---------------- 4 files changed, 35 insertions(+), 40 deletions(-) diff --git a/releases/enterprise.go b/releases/enterprise.go index 1bd58d6..179d40d 100644 --- a/releases/enterprise.go +++ b/releases/enterprise.go @@ -3,16 +3,21 @@ package releases -import ( - "fmt" -) +import "fmt" type EnterpriseOptions struct { - LicenseDir string // required - Meta string // optional; may be "hsm", "fips1402", "hsm.fips1402", etc. + // LicenseDir represents directory path where to install license files (required) + LicenseDir string + + // Meta represents optional version metadata (e.g. hsm, fips1402) + Meta string } -func (eo *EnterpriseOptions) requiredMetadata() string { +func enterpriseVersionMetadata(eo *EnterpriseOptions) string { + if eo == nil { + return "" + } + metadata := "ent" if eo.Meta != "" { metadata += "." + eo.Meta @@ -20,9 +25,14 @@ func (eo *EnterpriseOptions) requiredMetadata() string { return metadata } -func (eo *EnterpriseOptions) validate() error { +func validateEnterpriseOptions(eo *EnterpriseOptions) error { + if eo == nil { + return nil + } + if eo.LicenseDir == "" { return fmt.Errorf("LicenseDir must be provided when requesting enterprise versions") } + return nil } diff --git a/releases/exact_version.go b/releases/exact_version.go index fbea4c0..e42f4d2 100644 --- a/releases/exact_version.go +++ b/releases/exact_version.go @@ -27,7 +27,9 @@ type ExactVersion struct { Version *version.Version InstallDir string Timeout time.Duration - Enterprise *EnterpriseOptions // require enterprise version if set (leave nil for OSS) + + // Enterprise indicates installation of enterprise version (leave nil for Community editions) + Enterprise *EnterpriseOptions SkipChecksumVerification bool @@ -68,10 +70,8 @@ func (ev *ExactVersion) Validate() error { return fmt.Errorf("unknown version") } - if ev.Enterprise != nil { - if err := ev.Enterprise.validate(); err != nil { - return err - } + if err := validateEnterpriseOptions(ev.Enterprise); err != nil { + return err } return nil @@ -109,7 +109,7 @@ func (ev *ExactVersion) Install(ctx context.Context) (string, error) { rels.SetLogger(ev.log()) installVersion := ev.Version if ev.Enterprise != nil { - installVersion = versionWithMetadata(installVersion, ev.Enterprise.requiredMetadata()) + installVersion = versionWithMetadata(installVersion, enterpriseVersionMetadata(ev.Enterprise)) } pv, err := rels.GetProductVersion(ctx, ev.Product.Name, installVersion) if err != nil { diff --git a/releases/latest_version.go b/releases/latest_version.go index 7b5578a..8873b5d 100644 --- a/releases/latest_version.go +++ b/releases/latest_version.go @@ -27,7 +27,9 @@ type LatestVersion struct { InstallDir string Timeout time.Duration IncludePrereleases bool - Enterprise *EnterpriseOptions // require enterprise version if set (leave nil for OSS) + + // Enterprise indicates installation of enterprise version (leave nil for Community editions) + Enterprise *EnterpriseOptions SkipChecksumVerification bool @@ -64,10 +66,8 @@ func (lv *LatestVersion) Validate() error { return fmt.Errorf("invalid binary name: %q", lv.Product.BinaryName()) } - if lv.Enterprise != nil { - if err := lv.Enterprise.validate(); err != nil { - return err - } + if err := validateEnterpriseOptions(lv.Enterprise); err != nil { + return err } return nil @@ -167,11 +167,7 @@ func (lv *LatestVersion) Remove(ctx context.Context) error { } func (lv *LatestVersion) findLatestMatchingVersion(pvs rjson.ProductVersionsMap, vc version.Constraints) (*rjson.ProductVersion, bool) { - requiredMetadata := "" - if lv.Enterprise != nil { - requiredMetadata = lv.Enterprise.requiredMetadata() - } - + expectedMetadata := enterpriseVersionMetadata(lv.Enterprise) versions := make(version.Collection, 0) for _, pv := range pvs.AsSlice() { if !lv.IncludePrereleases && pv.Version.Prerelease() != "" { @@ -179,7 +175,7 @@ func (lv *LatestVersion) findLatestMatchingVersion(pvs rjson.ProductVersionsMap, continue } - if pv.Version.Metadata() != requiredMetadata { + if pv.Version.Metadata() != expectedMetadata { continue } diff --git a/releases/versions.go b/releases/versions.go index bda0df7..8d91909 100644 --- a/releases/versions.go +++ b/releases/versions.go @@ -46,10 +46,8 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { return nil, fmt.Errorf("invalid product name: %q", v.Product.Name) } - if v.Enterprise != nil { - if err := v.Enterprise.validate(); err != nil { - return nil, err - } + if err := validateEnterpriseOptions(v.Enterprise); err != nil { + return nil, err } timeout := defaultListTimeout @@ -68,10 +66,7 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { versions := pvs.AsSlice() sort.Stable(versions) - requiredMetadata := "" - if v.Enterprise != nil { - requiredMetadata = v.Enterprise.requiredMetadata() - } + expectedMetadata := enterpriseVersionMetadata(v.Enterprise) installables := make([]src.Source, 0) for _, pv := range versions { @@ -80,7 +75,7 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { continue } - if pv.Version.Metadata() != requiredMetadata { + if pv.Version.Metadata() != expectedMetadata { // skip version which doesn't match required metadata for enterprise or OSS versions continue } @@ -88,6 +83,7 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { ev := &ExactVersion{ Product: v.Product, Version: pv.Version, + Enterprise: v.Enterprise, InstallDir: v.Install.Dir, Timeout: v.Install.Timeout, @@ -95,13 +91,6 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { SkipChecksumVerification: v.Install.SkipChecksumVerification, } - if v.Enterprise != nil { - ev.Enterprise = &EnterpriseOptions{ - Meta: v.Enterprise.Meta, - LicenseDir: v.Enterprise.LicenseDir, - } - } - installables = append(installables, ev) } From c453d8f60e4c59c2249867c65288247dd3ba9216 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Thu, 31 Aug 2023 11:20:55 +0100 Subject: [PATCH 14/14] releases: revert to copying EnterpriseOptions I'm not entirely sure this is actually necessary or beneficial (from memory consumption perspective) but I'm keeping it as-is as it should do no harm to existing users who do not install enterprise products. --- releases/versions.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/releases/versions.go b/releases/versions.go index 8d91909..49b1af7 100644 --- a/releases/versions.go +++ b/releases/versions.go @@ -83,7 +83,6 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { ev := &ExactVersion{ Product: v.Product, Version: pv.Version, - Enterprise: v.Enterprise, InstallDir: v.Install.Dir, Timeout: v.Install.Timeout, @@ -91,6 +90,13 @@ func (v *Versions) List(ctx context.Context) ([]src.Source, error) { SkipChecksumVerification: v.Install.SkipChecksumVerification, } + if v.Enterprise != nil { + ev.Enterprise = &EnterpriseOptions{ + Meta: v.Enterprise.Meta, + LicenseDir: v.Enterprise.LicenseDir, + } + } + installables = append(installables, ev) }