Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/semver constraints #208

Merged
merged 3 commits into from
Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ require (
github.com/chzyer/logex v1.1.10 // indirect
github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3 // indirect
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
github.com/hashicorp/go-version v1.3.0 // indirect
github.com/hashicorp/go-version v1.4.0
github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80
github.com/hashicorp/terraform-config-inspect v0.0.0-20211115214459-90acf1ca460f
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect
github.com/kiranjthomas/terraform-config-inspect v0.0.0-20191120205521-a1d709eb2824
github.com/lunixbochs/vtclean v0.0.0-20170504063817-d14193dfc626 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,18 @@ github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FK
github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw=
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4=
github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl/v2 v2.0.0 h1:efQznTz+ydmQXq3BOnRa3AXzvCeTq1P4dKj/z5GLlY8=
github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90=
github.com/hashicorp/hcl2 v0.0.0-20190821123243-0c888d1241f6/go.mod h1:Cxv+IJLuBiEhQ7pBYGEuORa0nr4U994pE8mYLuFd7v0=
github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80 h1:PFfGModn55JA0oBsvFghhj0v93me+Ctr3uHC/UmFAls=
github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80/go.mod h1:Cxv+IJLuBiEhQ7pBYGEuORa0nr4U994pE8mYLuFd7v0=
github.com/hashicorp/terraform-config-inspect v0.0.0-20211115214459-90acf1ca460f h1:R8UIC07Ha9jZYkdcJ51l4ownCB8xYwfJtrgZSMvqjWI=
github.com/hashicorp/terraform-config-inspect v0.0.0-20211115214459-90acf1ca460f/go.mod h1:Z0Nnk4+3Cy89smEbrq+sl1bxc9198gIP4I7wcQF6Kqs=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
Expand Down Expand Up @@ -166,6 +172,7 @@ github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgq
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
Expand Down
166 changes: 19 additions & 147 deletions lib/download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ import (
"path/filepath"
"testing"

lib "github.com/warrensbox/terraform-switcher/lib"
"github.com/warrensbox/terraform-switcher/lib"
)

// TestDownloadFromURL_FileNameMatch : Check expected filename exist when downloaded
func TestDownloadFromURL_FileNameMatch(t *testing.T) {

hashiURL := "https://releases.hashicorp.com/terraform/"
installVersion := "terraform_"
installPath := GetInstallLocation(".terraform.versions_test")
tempDir := t.TempDir()
installPath := fmt.Sprintf(tempDir + string(os.PathSeparator) + ".terraform.versions_test")
macOS := "_darwin_amd64.zip"

// get current user
Expand All @@ -31,16 +32,16 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) {

// create /.terraform.versions_test/ directory to store code
if _, err := os.Stat(installLocation); os.IsNotExist(err) {
log.Printf("Creating directory for terraform: %v", installLocation)
t.Logf("Creating directory for terraform: %v", installLocation)
err = os.MkdirAll(installLocation, 0755)
if err != nil {
fmt.Printf("Unable to create directory for terraform: %v", installLocation)
panic(err)
t.Logf("Unable to create directory for terraform: %v", installLocation)
t.Error("Test fail")
}
}

/* test download lowest terraform version */
lowestVersion := "0.1.0"
/* test download old terraform version */
lowestVersion := "0.11.0"

url := hashiURL + lowestVersion + "/" + installVersion + lowestVersion + macOS
expectedFile := filepath.Join(usr.HomeDir, installPath, installVersion+lowestVersion+macOS)
Expand All @@ -61,156 +62,27 @@ func TestDownloadFromURL_FileNameMatch(t *testing.T) {
t.Error("Download file mismatches expected file (unexpected)")
}

/* test download latest terraform version */
latestVersion := "0.11.7"

url = hashiURL + latestVersion + "/" + installVersion + latestVersion + macOS
expectedFile = filepath.Join(usr.HomeDir, installPath, installVersion+latestVersion+macOS)
installedFile, errDownload = lib.DownloadFromURL(installLocation, url)

if errDownload != nil {
t.Logf("Expected file name %v to be downloaded", expectedFile)
t.Error("Download not possible (unexpected)")
}

if installedFile == expectedFile {
t.Logf("Expected file name %v", expectedFile)
t.Logf("Downloaded file name %v", installedFile)
t.Log("Download file name matches expected file")
} else {
t.Logf("Expected file name %v", expectedFile)
t.Logf("Downloaded file name %v", installedFile)
t.Error("Dowload file name mismatches expected file (unexpected)")
}

cleanUp(installLocation)
}

// TestDownloadFromURL_FileExist : Check expected file exist when downloaded
func TestDownloadFromURL_FileExist(t *testing.T) {

hashiURL := "https://releases.hashicorp.com/terraform/"
installFile := "terraform"
installVersion := "terraform_"
installPath := GetInstallLocation(".terraform.versions_test")
macOS := "_darwin_amd64.zip"

// get current user
usr, errCurr := user.Current()
if errCurr != nil {
log.Fatal(errCurr)
}

fmt.Printf("Current user: %v \n", usr.HomeDir)
installLocation := filepath.Join(usr.HomeDir, installPath)

// create /.terraform.versions_test/ directory to store code
if _, err := os.Stat(installLocation); os.IsNotExist(err) {
log.Printf("Creating directory for terraform: %v", installLocation)
err = os.MkdirAll(installLocation, 0755)
if err != nil {
fmt.Printf("Unable to create directory for terraform: %v", installLocation)
panic(err)
}
}

/* test download lowest terraform version */
lowestVersion := "0.1.0"

url := hashiURL + lowestVersion + "/" + installVersion + lowestVersion + macOS
expectedFile := filepath.Join(usr.HomeDir, installPath, installVersion+lowestVersion+macOS)
installedFile, errDownload := lib.DownloadFromURL(installLocation, url)

if errDownload != nil {
t.Logf("Expected file name %v to be downloaded", expectedFile)
t.Error("Download not possible (unexpected)")
}

if checkFileExist(expectedFile) {
t.Logf("Expected file %v", expectedFile)
t.Logf("Downloaded file %v", installedFile)
t.Log("Download file matches expected file")
} else {
t.Logf("Expected file %v", expectedFile)
t.Logf("Downloaded file %v", installedFile)
t.Error("Download file mismatches expected file (unexpected)")
}

/* test download latest terraform version */
latestVersion := "0.11.7"

url = hashiURL + latestVersion + "/" + installVersion + latestVersion + macOS
expectedFile = filepath.Join(usr.HomeDir, installPath, installVersion+latestVersion+macOS)
installFile, errDownload = lib.DownloadFromURL(installLocation, url)

if errDownload != nil {
t.Logf("Expected file name %v to be downloaded", expectedFile)
t.Error("Download not possible (unexpected)")
}

if checkFileExist(expectedFile) {
t.Logf("Expected file %v", expectedFile)
t.Logf("Downloaded file %v", installFile)
t.Log("Download file matches expected file")
} else {
t.Logf("Expected file %v", expectedFile)
t.Logf("Downloaded file %v", installFile)
t.Error("Download file mismatches expected file (unexpected)")
}

cleanUp(installLocation)
}

// TestInvalidURL : Invalid url should throw an error
func TestInvalidURL(t *testing.T) {

hashiURL := "https://releases.hashicorp.com/terraform/"
installVersion := "terraform_"
installPath := GetInstallLocation(".terraform.versions_test")
macOS := "_darwin_amd64.zip"
invalidVersion := "0.11.7-nonexistent"

// get current user
usr, errCurr := user.Current()
if errCurr != nil {
log.Fatal(errCurr)
}

fmt.Printf("Current user: %v \n", usr.HomeDir)
installLocation := filepath.Join(usr.HomeDir, installPath)

// create /.terraform.versions_test/ directory to store code
if _, err := os.Stat(installLocation); os.IsNotExist(err) {
log.Printf("Creating directory for terraform: %v\n", installLocation)
err = os.MkdirAll(installLocation, 0755)
if err != nil {
fmt.Printf("Unable to create directory for terraform: %v\n", installLocation)
panic(err)
}
}

url := hashiURL + invalidVersion + "/" + installVersion + invalidVersion + macOS
//expectedFile :=filepath.Join(usr.HomeDir, installPath, installVersion + invalidVersion + macOS)
_, errDownload := lib.DownloadFromURL(installLocation, url)

if errDownload != nil {
t.Logf("Unable to download from %s - invalid url or version (expected)\n", url)
t.Logf("Download not possible (expected)")
//check file name is what is expected
_, err := os.Stat(expectedFile)
if err != nil {
t.Logf("Expected file does not exist %v", expectedFile)
}

cleanUp(installLocation)
t.Cleanup(func() {
defer os.Remove(tempDir)
fmt.Println("Cleanup temporary directory")
})
}

// TestDownloadFromURL_Valid : Test if https://releases.hashicorp.com/terraform/ is still valid
// // TestDownloadFromURL_Valid : Test if https://releases.hashicorp.com/terraform/ is still valid
func TestDownloadFromURL_Valid(t *testing.T) {

hashiURL := "https://releases.hashicorp.com/terraform/"

url, err := url.ParseRequestURI(hashiURL)
if err != nil {
t.Errorf("Valid URL provided: %v", err)
t.Errorf("Invalid URL %v", err)
t.Errorf("Invalid URL %v [unexpected]", err)
} else {
t.Logf("Valid URL from %v", url)
t.Logf("Valid URL from %v [expected]", url)
}
}
61 changes: 61 additions & 0 deletions lib/semver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package lib

import (
"fmt"
"sort"

semver "github.com/hashicorp/go-version"
)

// GetSemver : returns version that will be installed based on server constaint provided
func GetSemver(tfconstraint *string, mirrorURL *string) (string, error) {

listAll := true
tflist, _ := GetTFList(*mirrorURL, listAll) //get list of versions
fmt.Printf("Reading required version from constraint: %s\n", *tfconstraint)
tfversion, err := SemVerParser(tfconstraint, tflist)
return tfversion, err
}

// ValidateSemVer : Goes through the list of terraform version, return a valid tf version for contraint provided
func SemVerParser(tfconstraint *string, tflist []string) (string, error) {
tfversion := ""
constraints, err := semver.NewConstraint(*tfconstraint) //NewConstraint returns a Constraints instance that a Version instance can be checked against
if err != nil {
return "", fmt.Errorf("error parsing constraint: %s", *tfconstraint)
}
versions := make([]*semver.Version, len(tflist))
//put tfversion into semver object
for i, tfvals := range tflist {
version, err := semver.NewVersion(tfvals) //NewVersion parses a given version and returns an instance of Version or an error if unable to parse the version.
if err != nil {
return "", fmt.Errorf("error parsing constraint: %s", err)
}
versions[i] = version
}

sort.Sort(sort.Reverse(semver.Collection(versions)))

for _, element := range versions {
if constraints.Check(element) { // Validate a version against a constraint
tfversion = element.String()
fmt.Printf("Matched version: %s\n", tfversion)
if ValidVersionFormat(tfversion) { //check if version format is correct
return tfversion, nil
}
}
}

PrintInvalidTFVersion()
return "", fmt.Errorf("error parsing constraint: %s", *tfconstraint)
}

// Print invalid TF version
func PrintInvalidTFVersion() {
fmt.Println("Version does not exist or invalid terraform version format.\n Format should be #.#.# or #.#.#-@# where # are numbers and @ are word characters.\n For example, 0.11.7 and 0.11.9-beta1 are valid versions")
}

// Print invalid TF version
func PrintInvalidMinorTFVersion() {
fmt.Println("Invalid minor terraform version format. Format should be #.# where # are numbers. For example, 0.11 is valid version")
}
Loading