Skip to content

Commit

Permalink
Fix cheking of requirement bin versions #69
Browse files Browse the repository at this point in the history
  • Loading branch information
TheRealSpaceShip committed Apr 2, 2024
1 parent 892d536 commit bb87c44
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ staticcheck: bin/$(OS)/staticcheck
@$(GOBIN)/staticcheck github.com/epam/hubctl/...
.PHONY: staticcheck

test:
test: deps
go test -race -timeout 60s ./cmd/hub/...
.PHONY: test

Expand Down
32 changes: 17 additions & 15 deletions cmd/hub/lifecycle/requirement.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
Expand All @@ -28,7 +27,7 @@ import (

const (
providedByEnv = "*environment*"
gcpServiceAccountsHelp = "https://cloud.google.com/docs/authentication/getting-started"
gcpServiceAccountsHelp = "https://cloud.google.com/docs/authentication/provide-credentials-adc"
azureGoSdkAuthHelp = "https://docs.microsoft.com/en-us/go/azure/azure-sdk-go-authorization"
)

Expand Down Expand Up @@ -161,14 +160,15 @@ func setupRequirement(requirement string, provider string,
}

var bins = map[string][]string{
"aws": {"aws", "s3", "ls", "--page-size", "5"},
"aws": {"aws", "--version"},
"azure": {"az", "version"},
"gcp": {"gcloud", "version"},
"gcs": {"gsutil", "version"},
"kubectl": {"kubectl", "version", "--client"},
"kubernetes": {"kubectl", "version", "--client"},
"helm": {"helm", "version", "--client"},
"etcd": {"etcdctl", "--version"},
"kubectl": {"kubectl", "version", "--client", "--output=json"},
"kubernetes": {"kubectl", "version", "--client", "--output=json"},
"vault": {"vault", "version"},
"helm": {"helm", "version"},
"terraform": {"terraform", "version"},
}

type BinVersion struct {
Expand All @@ -185,12 +185,14 @@ func semver(s string) *version.Version {
}

var binVersion = map[string]*BinVersion{
"gcloud": {semver("246.0.0"), regexp.MustCompile(`Google Cloud SDK ([\d.]+)`)},
"gsutil": {semver("4.38"), regexp.MustCompile(`version: ([\d.]+)`)},
"vault": {semver("1.3.2"), regexp.MustCompile(`Vault v([\d.]+)`)},
"kubectl": {semver("1.18.15"), regexp.MustCompile(`GitVersion:"v([\d.]+)`)},
"helm": {semver("3.5.1"), regexp.MustCompile(`(?:SemVer|Version):"v([\d.]+)`)},
"terraform": {semver("0.14.0"), regexp.MustCompile(`Terraform v([\d.]+)`)},
"aws": {semver("2.10.0"), regexp.MustCompile(`aws-cli/([\d.]+)`)},
"az": {semver("2.40.0"), regexp.MustCompile(`"azure-cli": "([\d.]+)"`)},
"gcloud": {semver("400.0.0"), regexp.MustCompile(`Google Cloud SDK ([\d.]+)`)},
"gsutil": {semver("5.0"), regexp.MustCompile(`version: ([\d.]+)`)},
"vault": {semver("1.10"), regexp.MustCompile(`Vault v([\d.]+)`)},
"kubectl": {semver("1.19"), regexp.MustCompile(`"gitVersion": "v([\d.]+)"`)},
"helm": {semver("3.11"), regexp.MustCompile(`(?:SemVer|Version):"v([\d.]+)"`)},
"terraform": {semver("1.0"), regexp.MustCompile(`Terraform v([\d.]+)`)},
}

func checkStackRequires(requires []string, optional, requiresOfOptionalComponents map[string][]string) map[string][]string {
Expand Down Expand Up @@ -290,7 +292,7 @@ func checkRequiresBin(bin ...string) ([]byte, error) {
// validates binary version against minimum required version
//
// reqVer: required version and regexp to extract version string
// currVer: raw output from binary
// out: raw output from binary
//
// returns error version is not valid
func checkRequiresBinVersion(reqVer *BinVersion, out []byte) error {
Expand Down Expand Up @@ -395,7 +397,7 @@ func checkRequiresGcp() error {
return err
}

jsonData, err := ioutil.ReadFile(credsFile)
jsonData, err := os.ReadFile(credsFile)
if err != nil {
return fmt.Errorf("Unable to read `%s`: %v", credsFile, err)
}
Expand Down
94 changes: 74 additions & 20 deletions cmd/hub/lifecycle/requirement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,89 @@ import (
"fmt"
"testing"

"github.com/hashicorp/go-version"
"github.com/stretchr/testify/assert"
)

var helmVerTpl = "version.BuildInfo{Version:\"%s\", GitCommit:\"50f003e5ee8704ec937a756c646870227d7c8b58\", GitTreeState:\"clean\", GoVersion:\"go1.18.8\"}"
var outputTemplates = map[string]string{
"aws": "aws-cli/%s Python/3.11.5 Linux/5.15.90.1 source/x86_64.ubuntu.22 prompt/off",
"az": `{
"azure-cli": "%s",
"azure-cli-core": "2.52.0",
"azure-cli-telemetry": "1.1.0",
"extensions": {}
}`,
"gcloud": `Google Cloud SDK %s
alpha 2023.09.13
beta 2023.09.13
bq 2.0.98
bundled-python3-unix 3.9.16
core 2023.09.13
gcloud-crc32c 1.0.0
gsutil 5.25`,
"gsutil": "version: %s",
"vault": "Vault v%s ('56debfa71653e72433345f23cd26276bc90629ce+CHANGES'), built 2023-09-11T21:23:55Z",
"kubectl": `{
"clientVersion": {
"major": "1",
"minor": "28",
"gitVersion": "v%s",
"gitCommit": "8dc49c4b984b897d423aab4971090e1879eb4f23",
"gitTreeState": "clean",
"buildDate": "2023-08-24T11:16:29Z",
"goVersion": "go1.20.7",
"compiler": "gc",
"platform": "linux/amd64"
},
"kustomizeVersion": "v5.0.4-0.20230601165947-6ce0bf390ce3"
}`,
"helm": "version.BuildInfo{Version:\"v%s\", GitCommit:\"3a31588ad33fe3b89af5a2a54ee1d25bfe6eaa5e\", GitTreeState:\"clean\", GoVersion:\"go1.20.7\"}",
"terraform": "Terraform v%s\non linux_amd64",
}

func formatVersion(binary, version string) []byte {
return []byte(fmt.Sprintf(outputTemplates[binary], version))
}

func testRequiredbinaryVersion(binary, equalVersion, newerVersion, olderVersion, startFromTen string, t *testing.T) {
reqVer := binVersion[binary]
err := checkRequiresBinVersion(reqVer, formatVersion(binary, equalVersion))
assert.NoError(t, err, "When version is equal with minimal required, checkRequiresBinVersion should not return validation error")
err = checkRequiresBinVersion(reqVer, formatVersion(binary, newerVersion))
assert.NoError(t, err, "When version is greater than minimal required, checkRequiresBinVersion should not return validation error")
err = checkRequiresBinVersion(reqVer, formatVersion(binary, olderVersion))
assert.Error(t, err, "When version is less than minimal required, checkRequiresBinVersion should return validation error")
err = checkRequiresBinVersion(reqVer, formatVersion(binary, startFromTen))
assert.NoError(t, err, "When version number starts with 1 but actually is 10, checkRequiresBinVersion should not return validation error")
}

func TestCheckAwsVersion(t *testing.T) {
testRequiredbinaryVersion("aws", "2.10", "2.13.19", "2.0.2", "10.1.1", t)
}

func formatHelmVersion(version string) []byte {
return []byte(fmt.Sprintf(helmVerTpl, version))
func TestCheckAzureVersion(t *testing.T) {
testRequiredbinaryVersion("az", "2.40", "2.52.0", "2.0.2", "10.1.1", t)
}

func TestCheckRequiresBinVersion(t *testing.T) {
min, _ := version.NewVersion("3.5.2")
helm := binVersion["helm"]
helm.minVersion = min
func TestCheckGcloudVersion(t *testing.T) {
testRequiredbinaryVersion("gcloud", "400.0.0", "446.0.1", "140.0.2", "1010.1.1", t)
}

raw_data := formatHelmVersion(min.String())
err := checkRequiresBinVersion(helm, raw_data)
assert.Error(t, err, "When versions are equal, checkRequiresBinVersion should not return validation error")
func TestCheckGsutilVersion(t *testing.T) {
testRequiredbinaryVersion("gsutil", "5.0", "5.25", "3.52", "10.1.1", t)
}

raw_data = formatHelmVersion("v0.0.1")
err = checkRequiresBinVersion(helm, raw_data)
assert.Error(t, err, "When version is less than required, checkRequiresBinVersion should return validation error")
func TestCheckVaultVersion(t *testing.T) {
testRequiredbinaryVersion("vault", "1.10.0", "1.14.3", "1.9.10", "10.1.1", t)
}

raw_data = formatHelmVersion("v100.0.0")
err = checkRequiresBinVersion(helm, raw_data)
assert.NoError(t, err, "When version is greater than required, checkRequiresBinVersion should not return validation error")
func TestCheckKubectlVersion(t *testing.T) {
testRequiredbinaryVersion("kubectl", "1.19", "1.28.1", "1.18.15", "10.1.1", t)
}

raw_data = formatHelmVersion("v3.10.2")
err = checkRequiresBinVersion(helm, raw_data)
assert.NoError(t, err, "When version number starts with 1 but actually is 10 there should be no error")
func TestCheckHelmVersion(t *testing.T) {
testRequiredbinaryVersion("helm", "3.11", "3.12.3", "3.5.1", "10.1.1", t)
}

func TestCheckTerraformVersion(t *testing.T) {
testRequiredbinaryVersion("terraform", "1.0", "1.5.7", "0.14.1", "10.1.1", t)
}

0 comments on commit bb87c44

Please sign in to comment.