fix: panic when using helm v3.3 (#1427) (#1428)

This commit is contained in:
Anatoly Rugalev 2020-08-24 02:57:17 +03:00 committed by GitHub
parent a9aa7af572
commit 90a41222e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 28 deletions

View File

@ -48,40 +48,28 @@ func NewLogger(writer io.Writer, logLevel string) *zap.SugaredLogger {
return zap.New(core).Sugar() return zap.New(core).Sugar()
} }
func getHelmVersion(helmBinary string, logger *zap.SugaredLogger, runner Runner) Version { // versionRegex matches versions like v1.1.1 and v1.1
var versionRegex = regexp.MustCompile("v(?P<major>\\d+)\\.(?P<minor>\\d+)(?:\\.(?P<patch>\\d+))?")
// Autodetect from `helm verison` func parseHelmVersion(versionStr string) (Version, error) {
bytes, err := runner.Execute(helmBinary, []string{"version", "--client", "--short"}, nil) if len(versionStr) == 0 {
if err != nil { return Version{}, nil
panic(err)
} }
if bytes == nil || len(bytes) == 0 { matches := versionRegex.FindStringSubmatch(versionStr)
return Version{} if len(matches) == 0 {
return Version{}, fmt.Errorf("error parsing helm verion '%s'", versionStr)
} }
re := regexp.MustCompile("v(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)")
matches := re.FindStringSubmatch(string(bytes))
result := make(map[string]string) result := make(map[string]string)
for i, name := range re.SubexpNames() { for i, name := range versionRegex.SubexpNames() {
result[name] = matches[i] result[name] = matches[i]
} }
major, err := strconv.Atoi(result["major"]) // We ignore errors because regex matches only integers
if err != nil { // If any of the parts does not exist - default "0" will be used
panic(err) major, _ := strconv.Atoi(result["major"])
} minor, _ := strconv.Atoi(result["minor"])
patch, _ := strconv.Atoi(result["patch"])
minor, err := strconv.Atoi(result["minor"])
if err != nil {
panic(err)
}
patch, err := strconv.Atoi(result["patch"])
if err != nil {
panic(err)
}
// Support explicit helm3 opt-in via environment variable // Support explicit helm3 opt-in via environment variable
if os.Getenv("HELMFILE_HELM3") != "" && major < 3 { if os.Getenv("HELMFILE_HELM3") != "" && major < 3 {
@ -89,21 +77,37 @@ func getHelmVersion(helmBinary string, logger *zap.SugaredLogger, runner Runner)
Major: 3, Major: 3,
Minor: 0, Minor: 0,
Patch: 0, Patch: 0,
} }, nil
} }
return Version{ return Version{
Major: major, Major: major,
Minor: minor, Minor: minor,
Patch: patch, Patch: patch,
}, nil
}
func getHelmVersion(helmBinary string, runner Runner) (Version, error) {
// Autodetect from `helm verison`
bytes, err := runner.Execute(helmBinary, []string{"version", "--client", "--short"}, nil)
if err != nil {
return Version{}, fmt.Errorf("error determining helm version: %w", err)
} }
return parseHelmVersion(string(bytes))
} }
// New for running helm commands // New for running helm commands
func New(helmBinary string, logger *zap.SugaredLogger, kubeContext string, runner Runner) *execer { func New(helmBinary string, logger *zap.SugaredLogger, kubeContext string, runner Runner) *execer {
// TODO: proper error handling
version, err := getHelmVersion(helmBinary, runner)
if err != nil {
panic(err)
}
return &execer{ return &execer{
helmBinary: helmBinary, helmBinary: helmBinary,
version: getHelmVersion(helmBinary, logger, runner), version: version,
logger: logger, logger: logger,
kubeContext: kubeContext, kubeContext: kubeContext,
runner: runner, runner: runner,

View File

@ -570,3 +570,50 @@ func Test_IsVersionAtLeast(t *testing.T) {
} }
} }
func Test_parseHelmVersion(t *testing.T) {
tests := []struct {
ver string
want Version
wantErr bool
}{
{
ver: "v1.2.3",
want: Version{
Major: 1,
Minor: 2,
Patch: 3,
},
wantErr: false,
},
{
ver: "v1.2",
want: Version{
Major: 1,
Minor: 2,
Patch: 0,
},
wantErr: false,
},
{
ver: "v1",
wantErr: true,
},
{
ver: "1.1.1",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.ver, func(t *testing.T) {
got, err := parseHelmVersion(tt.ver)
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() got = %v, want %v", got, tt.want)
}
})
}
}