diff --git a/pkg/helm/build.go b/pkg/helm/build.go index c4f0bf1..691a5ab 100644 --- a/pkg/helm/build.go +++ b/pkg/helm/build.go @@ -5,9 +5,15 @@ import ( "strings" "get.porter.sh/porter/pkg/exec/builder" + "github.com/Masterminds/semver" + "github.com/pkg/errors" yaml "gopkg.in/yaml.v2" ) +// clientVersionConstraint represents the semver constraint for the Helm client version +// Currently, this mixin only supports Helm clients versioned v2.x.x +const clientVersionConstraint string = "^v2.x" + // These values may be referenced elsewhere (init.go), hence consts const helmArchiveTmpl string = "helm-%s-linux-amd64.tar.gz" const helmDownloadURLTmpl string = "https://get.helm.sh/%s" @@ -70,8 +76,18 @@ func (m *Mixin) Build() error { if err != nil { return err } - if input.Config.ClientVersion != "" { - m.HelmClientVersion = input.Config.ClientVersion + + suppliedClientVersion := input.Config.ClientVersion + if suppliedClientVersion != "" { + ok, err := validate(suppliedClientVersion, clientVersionConstraint) + if err != nil { + return err + } + if !ok { + return errors.Errorf("supplied clientVersion %q does not meet semver constraint %q", + suppliedClientVersion, clientVersionConstraint) + } + m.HelmClientVersion = suppliedClientVersion } var helmArchiveVersion = fmt.Sprintf(helmArchiveTmpl, m.HelmClientVersion) @@ -119,3 +135,18 @@ func GetAddRepositoryCommand(name, url, cafile, certfile, keyfile, username, pas return commandBuilder, nil } + +// validate validates that the supplied clientVersion meets the supplied semver constraint +func validate(clientVersion, constraint string) (bool, error) { + c, err := semver.NewConstraint(constraint) + if err != nil { + return false, errors.Wrapf(err, "unable to parse version constraint %q", constraint) + } + + v, err := semver.NewVersion(clientVersion) + if err != nil { + return false, errors.Wrapf(err, "supplied client version %q cannot be parsed as semver", clientVersion) + } + + return c.Check(v), nil +} diff --git a/pkg/helm/build_test.go b/pkg/helm/build_test.go index 7cbf6d9..cd8ac15 100644 --- a/pkg/helm/build_test.go +++ b/pkg/helm/build_test.go @@ -61,7 +61,7 @@ RUN apt-get update && \ t.Run("build with a defined helm client version", func(t *testing.T) { - b, err := ioutil.ReadFile("testdata/build-input-with-version.yaml") + b, err := ioutil.ReadFile("testdata/build-input-with-supported-client-version.yaml") require.NoError(t, err) m := NewTestMixin(t) @@ -73,4 +73,28 @@ RUN apt-get update && \ gotOutput := m.TestContext.GetOutput() assert.Equal(t, wantOutput, gotOutput) }) + + t.Run("build with a defined helm client version that does not meet the semver constraint", func(t *testing.T) { + + b, err := ioutil.ReadFile("testdata/build-input-with-unsupported-client-version.yaml") + require.NoError(t, err) + + m := NewTestMixin(t) + m.Debug = false + m.In = bytes.NewReader(b) + err = m.Build() + require.EqualError(t, err, `supplied clientVersion "v3.2.1" does not meet semver constraint "^v2.x"`) + }) + + t.Run("build with a defined helm client version that does not parse as valid semver", func(t *testing.T) { + + b, err := ioutil.ReadFile("testdata/build-input-with-invalid-client-version.yaml") + require.NoError(t, err) + + m := NewTestMixin(t) + m.Debug = false + m.In = bytes.NewReader(b) + err = m.Build() + require.EqualError(t, err, `supplied client version "v3.2.1.0" cannot be parsed as semver: Invalid Semantic Version`) + }) } diff --git a/pkg/helm/testdata/build-input-with-invalid-client-version.yaml b/pkg/helm/testdata/build-input-with-invalid-client-version.yaml new file mode 100644 index 0000000..6f2c4d8 --- /dev/null +++ b/pkg/helm/testdata/build-input-with-invalid-client-version.yaml @@ -0,0 +1,8 @@ +config: + clientVersion: v3.2.1.0 +install: + - helm: + description: "Install MySQL" + name: porter-ci-mysql + chart: stable/mysql + version: 0.10.2 diff --git a/pkg/helm/testdata/build-input-with-supported-client-version.yaml b/pkg/helm/testdata/build-input-with-supported-client-version.yaml new file mode 100644 index 0000000..56c52ec --- /dev/null +++ b/pkg/helm/testdata/build-input-with-supported-client-version.yaml @@ -0,0 +1,8 @@ +config: + clientVersion: v2.16.1 +install: + - helm: + description: "Install MySQL" + name: porter-ci-mysql + chart: stable/mysql + version: 0.10.2 diff --git a/pkg/helm/testdata/build-input-with-version.yaml b/pkg/helm/testdata/build-input-with-unsupported-client-version.yaml similarity index 85% rename from pkg/helm/testdata/build-input-with-version.yaml rename to pkg/helm/testdata/build-input-with-unsupported-client-version.yaml index f80f8bd..ae31d8a 100644 --- a/pkg/helm/testdata/build-input-with-version.yaml +++ b/pkg/helm/testdata/build-input-with-unsupported-client-version.yaml @@ -1,5 +1,5 @@ config: - version: v2.16.1 + clientVersion: v3.2.1 install: - helm: description: "Install MySQL"