feat: use new helm version parse function (#760)

* feat: use new helm version parse function

Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
yxxhero 2023-03-23 08:46:11 +08:00 committed by GitHub
parent bfb94314be
commit 5e8a502b41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 17 deletions

View File

@ -12,6 +12,7 @@ import (
"sync"
"github.com/Masterminds/semver/v3"
"github.com/helmfile/chartify"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"helm.sh/helm/v3/pkg/chart"
@ -30,7 +31,7 @@ type decryptedSecret struct {
type execer struct {
helmBinary string
enableLiveOutput bool
version semver.Version
version *semver.Version
runner Runner
logger *zap.SugaredLogger
kubeContext string
@ -57,27 +58,30 @@ func NewLogger(writer io.Writer, logLevel string) *zap.SugaredLogger {
return zap.New(core).Sugar()
}
func parseHelmVersion(versionStr string) (semver.Version, error) {
func parseHelmVersion(versionStr string) (*semver.Version, error) {
if len(versionStr) == 0 {
return semver.Version{}, nil
return nil, fmt.Errorf("empty helm version")
}
versionStr = strings.TrimLeft(versionStr, "Client: ")
versionStr = strings.TrimRight(versionStr, "\n")
v, err := chartify.FindSemVerInfo(versionStr)
ver, err := semver.NewVersion(versionStr)
if err != nil {
return semver.Version{}, fmt.Errorf("error parsing helm version '%s'", versionStr)
return nil, fmt.Errorf("error find helm srmver version '%s': %w", versionStr, err)
}
return *ver, nil
ver, err := semver.NewVersion(v)
if err != nil {
return nil, fmt.Errorf("error parsing helm version '%s'", versionStr)
}
return ver, nil
}
func GetHelmVersion(helmBinary string, runner Runner) (semver.Version, error) {
func GetHelmVersion(helmBinary string, runner Runner) (*semver.Version, error) {
// Autodetect from `helm version`
outBytes, err := runner.Execute(helmBinary, []string{"version", "--client", "--short"}, nil, false)
if err != nil {
return semver.Version{}, fmt.Errorf("error determining helm version: %w", err)
return nil, fmt.Errorf("error determining helm version: %w", err)
}
return parseHelmVersion(string(outBytes))
@ -152,7 +156,7 @@ func (helm *execer) AddRepo(name, repository, cafile, certfile, keyfile, usernam
// See https://github.com/helm/helm/pull/8777
if cons, err := semver.NewConstraint(">= 3.3.2"); err == nil {
if cons.Check(&helm.version) {
if cons.Check(helm.version) {
args = append(args, "--force-update")
}
} else {
@ -450,7 +454,7 @@ func (helm *execer) ChartPull(chart string, path string, flags ...string) error
var helmArgs []string
helm.logger.Infof("Pulling %v", chart)
helmVersionConstraint, _ := semver.NewConstraint(">= 3.7.0")
if helmVersionConstraint.Check(&helm.version) {
if helmVersionConstraint.Check(helm.version) {
// in the 3.7.0 version, the chart pull has been replaced with helm pull
// https://github.com/helm/helm/releases/tag/v3.7.0
ociChartURL, ociChartTag := resolveOciChart(chart)
@ -465,7 +469,7 @@ func (helm *execer) ChartPull(chart string, path string, flags ...string) error
func (helm *execer) ChartExport(chart string, path string, flags ...string) error {
helmVersionConstraint, _ := semver.NewConstraint(">= 3.7.0")
if helmVersionConstraint.Check(&helm.version) {
if helmVersionConstraint.Check(helm.version) {
// in the 3.7.0 version, the chart export has been removed
// https://github.com/helm/helm/releases/tag/v3.7.0
return nil

View File

@ -8,6 +8,7 @@ import (
"path/filepath"
"reflect"
"regexp"
"strings"
"testing"
"github.com/Masterminds/semver/v3"
@ -27,6 +28,10 @@ func (mock *mockRunner) ExecuteStdIn(cmd string, args []string, env map[string]s
}
func (mock *mockRunner) Execute(cmd string, args []string, env map[string]string, enableLiveOutput bool) ([]byte, error) {
if len(mock.output) == 0 && strings.Join(args, " ") == "version --client --short" {
return []byte("v3.2.4+ge29ce2a"), nil
}
return mock.output, mock.err
}
@ -94,7 +99,7 @@ func Test_AddRepo_Helm_3_3_2(t *testing.T) {
logger := NewLogger(&buffer, "debug")
helm := &execer{
helmBinary: "helm",
version: *semver.MustParse("3.3.2"),
version: semver.MustParse("3.3.2"),
logger: logger,
kubeContext: "dev",
runner: &mockRunner{},
@ -737,7 +742,7 @@ exec: helm --kube-context dev pull oci://repo/helm-charts --version 0.14.0 --des
buffer.Reset()
helm := &execer{
helmBinary: tt.helmBin,
version: *semver.MustParse(tt.helmVersion),
version: semver.MustParse(tt.helmVersion),
logger: logger,
kubeContext: "dev",
runner: &mockRunner{},
@ -786,7 +791,7 @@ exec: helm --kube-context dev chart export chart --destination path1 --untar --u
buffer.Reset()
helm := &execer{
helmBinary: tt.helmBin,
version: *semver.MustParse(tt.helmVersion),
version: semver.MustParse(tt.helmVersion),
logger: logger,
kubeContext: "dev",
runner: &mockRunner{},
@ -975,7 +980,7 @@ func Test_ShowChart(t *testing.T) {
showChartRunner := mockRunner{output: []byte("name: my-chart\nversion: 3.2.0\n")}
helm := &execer{
helmBinary: "helm",
version: *semver.MustParse("3.3.2"),
version: semver.MustParse("3.3.2"),
logger: NewLogger(os.Stdout, "info"),
kubeContext: "dev",
runner: &showChartRunner,
@ -992,3 +997,55 @@ func Test_ShowChart(t *testing.T) {
t.Errorf("helmexec.ShowChart() - expected chart version was %s, received: %s", "3.2.0", metadata.Version)
}
}
func TestParseHelmVersion(t *testing.T) {
tests := []struct {
name string
version string
want *semver.Version
wantErr bool
}{
{
name: "helm 2",
version: "Client: v2.16.1+ge13bc94\n",
want: semver.MustParse("v2.16.1+ge13bc94"),
wantErr: false,
},
{
name: "helm 3",
version: "Client: v3.2.4+ge29ce2a\n",
want: semver.MustParse("v3.2.4+ge29ce2a"),
wantErr: false,
},
{
name: "helm 3 with os arch and build info",
version: "Client v3.7.1+7.el8+g8f33223\n",
want: semver.MustParse("v3.7.1+7.el8"),
wantErr: false,
},
{
name: "empty version",
version: "",
want: nil,
wantErr: true,
},
{
name: "invalid version",
version: "oooooo",
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseHelmVersion(tt.version)
if (err != nil) != tt.wantErr {
t.Errorf("parseHelmVersion() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("parseHelmVersion() = %v, want %v", got, tt.want)
}
})
}
}