Compare commits

..

25 Commits

Author SHA1 Message Date
fe80f029b5 Merge pull request 'Add error handling and improve comments' (#7) from fix-1.9.x into master
Reviewed-on: #7
2024-09-12 00:38:13 +00:00
15742e8f3f Add error handling and improve comments
Added fmt.Errorf for better error messages during HTTP and file handling in InstallTerraformVersion. Also fixed indentation in comments to follow Go conventions. Made other small improvements for better readability and maintainability.
2024-09-11 20:27:10 -04:00
5251c15271 Merge pull request 'feature/fix-mac-arm' (#6) from feature/fix-mac-arm into master
Reviewed-on: #6
2023-10-05 21:36:42 +00:00
2d3d1f881e Merge pull request 'master' (#5) from master into feature/fix-mac-arm
Reviewed-on: #5
2023-10-05 21:05:43 +00:00
cde1201da5 Merge pull request 'Fixed make install command' (#4) from fix-makefile into master
Reviewed-on: #4
2023-10-05 21:05:02 +00:00
6df08053c6 Fixed make install command 2023-10-05 17:02:10 -04:00
8690a026b1 added fix to use x86 in for arm mac's where arm package is unavailable 2023-10-03 19:26:18 -04:00
a7cb1f8aa1 Updated configuration manager to correctly retain stableonly value. 2023-02-04 07:40:33 -05:00
1bc2fddc09 Merge pull request 'Updated to new circle ci image' (#3) from update-ci-image into master
Reviewed-on: #3
2022-10-25 19:21:09 +00:00
4ffb4abbcc Updated to new circle ci image 2022-10-25 09:45:32 -04:00
b4c95f7ce3 Merge pull request 'fixed exit code' (#2) from test_update into master
Reviewed-on: #2
2022-10-25 13:03:06 +00:00
727001e838 fixed exit code 2022-10-25 09:02:00 -04:00
9001410471 Merge pull request 'Added tests for VersionInSlice' (#1) from test_update into master
Reviewed-on: #1
2022-10-24 12:44:36 +00:00
af2855a18c Added tests for VersionInSlice 2022-10-24 08:40:50 -04:00
c0bacf3d52 changed docker image back 2022-10-22 12:00:53 -04:00
b02e04e27b Reduced resource_class size
changed from golang to new go docker image
2022-10-22 11:56:34 -04:00
5cfcabad4b Added coverage report 2022-10-22 11:51:13 -04:00
4c99d54c51 Added circleci badge 2022-10-22 11:46:18 -04:00
55da2682ef Added circleci config 2022-10-22 11:34:55 -04:00
2282560e7a Added exit code 2022-10-21 09:39:06 -04:00
mitch
ce4d829184 Added comments 2022-06-18 09:41:00 -04:00
mitch
98493c8d52 Added support for default terraform version
Added default behavior for > and >= to not use non-stable release versions
Added configuration option of `StableOnly` which defaults to true.  Setting this to false will permit the use of -alpha and -beta releases
2022-06-15 22:52:19 -04:00
mitch
aed9e15f6e Added space to README.md 2022-06-07 08:56:23 -04:00
mitch
3dc30db64c Fixed tests 2022-04-27 19:20:10 -04:00
mitch
ae2805a729 Updated to support sem version comparison 2022-04-27 07:35:49 -04:00
27 changed files with 1359 additions and 121 deletions

49
.circleci/config.yml Normal file
View File

@ -0,0 +1,49 @@
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1
# Define a job to be invoked later in a workflow.
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
jobs:
build:
resource_class: small
working_directory: ~/repo
# Specify the execution environment. You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub.
# See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor
docker:
- image: cimg/go:1.17
# Add steps to the job
# See: https://circleci.com/docs/2.0/configuration-reference/#steps
steps:
- checkout
- restore_cache:
keys:
- go-mod-v4-{{ checksum "go.sum" }}
- run:
name: Install Dependencies
command: go mod download
- save_cache:
key: go-mod-v4-{{ checksum "go.sum" }}
paths:
- "/go/pkg/mod"
- run:
name: Run tests
command: |
mkdir -p /tmp/test-reports
mkdir -p /tmp/artifacts
go test -coverprofile=c.out
go tool cover -html=c.out -o coverage.html
mv coverage.html /tmp/artifacts
gotestsum --junitfile /tmp/test-reports/unit-tests.xml
- store_test_results:
path: /tmp/test-reports
- store_artifacts:
path: /tmp/artifacts
# Invoke jobs via workflows
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
workflows:
build: # This is the name of the workflow, feel free to change it to better match your workflow.
# Inside the workflow, you define the jobs you want to run.
jobs:
- build

View File

@ -7,12 +7,12 @@ build:
# Clean
####################################################
clean:
rm -f ~/.local/bin/versionedTerraform
rm -f $(shell go env GOPATH)/bin/versionedTerraform
####################################################
# Install
####################################################
install:
mv versionedTerraform ~/.local/bin/
mv versionedTerraform $(shell go env GOPATH)/bin/
####################################################
# help feature
####################################################
@ -20,8 +20,8 @@ help:
@echo ''
@echo 'Usage: make [TARGET]'
@echo 'Targets:'
@echo ' build go build -o versionedTerraform ./cmd'
@echo ' clean removes installed versionedTerraform file'
@echo ' install installs versionedTerraform to local user bin folder'
@echo ' all Nothing to do.'
@echo ' build go build -o versionedTerraform ./cmd'
@echo ' clean removes installed versionedTerraform file'
@echo ' install installs versionedTerraform to bin folder in GOPATH'
@echo ' all Nothing to do.'
@echo ''

View File

@ -1,9 +1,11 @@
#Versioned Terraform
[![<ORG_NAME>](https://circleci.com/gh/mitch-thompson/versionedTerraform.svg?style=svg)](<LINK>)
# Versioned Terraform
A wrapper for terraform to detect the expected version of terraform,
download, and execute that version
## Requirements
- go compiler (only tested on go1.17)
- go
## Install
`make build install` for installation to local user<br>
@ -14,9 +16,12 @@ download, and execute that version
All arguments are passed through to terraform
```
## sample usage
## Sample usage
`versionedTerraform version` will display the terraform version executed in a folder
## Configuration
A configuration file is created in `~/.versionedTerraform`<br><br>
`StableOnly` boolean values: <b>true</b>/false<br>
This value is used to restrict terraform to release versions only defaults to true
## Known Issues
Currently, does not support semantic versioning between values<br>
i.e. `required_version = "~> 0.14", "< 0.14.3"`

View File

@ -8,12 +8,15 @@ import (
const (
//todo include others if needed
//todo add comparison i.e. >= 0.11.10, < 0.12.0
latestRelease = ">="
latestPatch = "~>"
latestRelease = ">="
latestPatch = "~>"
versionLessOrEqual = "<="
versionLessThan = "<"
)
type SemVersion struct {
version string
isStable bool
majorVersion int
minorVersion int
patchVersion int
@ -27,6 +30,7 @@ type SemVersionInterface interface {
func NewSemVersion(v string) *SemVersion {
s := new(SemVersion)
s.isStable = true
s.version = removeSpacesVersion(v)
s.setMajorVersion()
@ -35,12 +39,14 @@ func NewSemVersion(v string) *SemVersion {
return s
}
//setMajorVersion setter for SemVersion.majorVersion
func (s *SemVersion) setMajorVersion() {
version := s.version
majorVersionString := strings.Split(version, ".")[0]
s.majorVersion, _ = strconv.Atoi(majorVersionString)
}
//setMinorVersion setter for SemVersion.minorVersion
func (s *SemVersion) setMinorVersion() {
version := s.version
minorVersionString := strings.Split(version, ".")[1]
@ -48,21 +54,30 @@ func (s *SemVersion) setMinorVersion() {
}
//setPatchVersion setter for SemVersion.patchVersion
func (s *SemVersion) setPatchVersion() {
version := s.version
var err error
patchStringSlice := strings.Split(version, ".")
if len(patchStringSlice) < 3 {
s.patchVersion = 0
return
}
s.patchVersion, _ = strconv.Atoi(patchStringSlice[2])
s.patchVersion, err = strconv.Atoi(patchStringSlice[2])
if err != nil {
s.isStable = false
patchStringSlice = strings.Split(patchStringSlice[2], "-")
s.patchVersion, _ = strconv.Atoi(patchStringSlice[0])
}
}
//ToString returns string of SemVersion
func (s *SemVersion) ToString() string {
return s.version
}
//VersionInSlice iterates through slices of SemVersion to check if version is in slice
//Used by main.go to determine if terraform version is currently installed
func (s *SemVersion) VersionInSlice(sSem []SemVersion) bool {
for _, ver := range sSem {
if ver.ToString() == s.ToString() {
@ -71,3 +86,50 @@ func (s *SemVersion) VersionInSlice(sSem []SemVersion) bool {
}
return false
}
func (s *SemVersion) IsEqualTo(s2 SemVersion) bool {
if s.majorVersion == s2.majorVersion && s.minorVersion == s2.minorVersion && s.patchVersion == s2.patchVersion {
return true
}
return false
}
func (s *SemVersion) IsLessThan(s2 SemVersion) bool {
if s2.majorVersion > s.majorVersion {
return true
}
if s2.minorVersion > s.minorVersion && s2.majorVersion == s.majorVersion {
return true
}
if s2.patchVersion > s.patchVersion && s2.majorVersion == s.majorVersion && s2.minorVersion == s.minorVersion {
return true
}
return false
}
func (s *SemVersion) IsGreaterThan(s2 SemVersion) bool {
if s2.majorVersion < s.majorVersion {
return true
}
if s2.minorVersion < s.minorVersion && s2.majorVersion == s.majorVersion {
return true
}
if s2.patchVersion < s.patchVersion && s2.majorVersion == s.majorVersion && s2.minorVersion == s.minorVersion {
return true
}
return false
}
func (s *SemVersion) IsLessOrEqual(s2 SemVersion) bool {
if s.IsLessThan(s2) || s.IsEqualTo(s2) {
return true
}
return false
}
func (s *SemVersion) IsGreaterOrEqual(s2 SemVersion) bool {
if s.IsGreaterThan(s2) || s.IsEqualTo(s2) {
return true
}
return false
}

773
SemVersion_test.go Normal file
View File

@ -0,0 +1,773 @@
package versionedTerraform
import "testing"
func TestSemVersion_VersionInSlice_success(t *testing.T) {
want := SemVersion{
version: "1.1.9",
isStable: true,
majorVersion: 1,
minorVersion: 1,
patchVersion: 9,
}
ver1 := SemVersion{
version: "1.1.10",
isStable: true,
majorVersion: 1,
minorVersion: 1,
patchVersion: 10,
}
ver2 := SemVersion{
version: "0.1.9",
isStable: true,
majorVersion: 0,
minorVersion: 1,
patchVersion: 9,
}
ver3 := SemVersion{
version: "1.0.9",
isStable: true,
majorVersion: 1,
minorVersion: 0,
patchVersion: 9,
}
var semArray []SemVersion
semArray = append(semArray, ver1)
semArray = append(semArray, ver2)
semArray = append(semArray, ver3)
semArray = append(semArray, want)
if !want.VersionInSlice(semArray) {
t.Errorf("Expected Sem Version to be found in semArray")
}
}
func TestSemVersion_VersionInSlice_fail(t *testing.T) {
want := SemVersion{
version: "1.1.9",
isStable: true,
majorVersion: 1,
minorVersion: 1,
patchVersion: 9,
}
ver1 := SemVersion{
version: "1.1.10",
isStable: true,
majorVersion: 1,
minorVersion: 1,
patchVersion: 10,
}
ver2 := SemVersion{
version: "0.1.9",
isStable: true,
majorVersion: 0,
minorVersion: 1,
patchVersion: 9,
}
ver3 := SemVersion{
version: "1.0.9",
isStable: true,
majorVersion: 1,
minorVersion: 0,
patchVersion: 9,
}
var semArray []SemVersion
semArray = append(semArray, ver1)
semArray = append(semArray, ver2)
semArray = append(semArray, ver3)
if want.VersionInSlice(semArray) {
t.Errorf("Expected Sem Version to not be found in semArray")
}
}
func TestSemVersion_IsLessThan(t *testing.T) {
cases := []struct {
name string
want bool
s1, s2 SemVersion
}{
{"IsEqualTo",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionLess",
true,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MinorVersionLess",
true,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
},
{"PatchVersionLess",
true,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionGreater",
false,
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
},
{"MinorVersionGreater",
false,
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"PatchVersionGreater",
false,
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
}
for _, c := range cases {
t.Run("Test: "+c.name, func(t *testing.T) {
t.Parallel()
got := c.s1.IsLessThan(c.s2)
if c.want != got {
t.Errorf("Expected %+v got %+v", c.want, got)
}
})
}
}
func TestSemVersion_IsGreaterThan(t *testing.T) {
cases := []struct {
name string
want bool
s1, s2 SemVersion
}{
{"IsEqualTo",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionLess",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MinorVersionLess",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
},
{"PatchVersionLess",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionGreater",
true,
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
},
{"MinorVersionGreater",
true,
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"PatchVersionGreater",
true,
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
}
for _, c := range cases {
t.Run("Test: "+c.name, func(t *testing.T) {
t.Parallel()
got := c.s1.IsGreaterThan(c.s2)
if c.want != got {
t.Errorf("Expected %+v got %+v", c.want, got)
}
})
}
}
func TestSemVersion_IsEqualTo(t *testing.T) {
cases := []struct {
name string
want bool
s1, s2 SemVersion
}{
{"IsEqualTo",
true,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionLess",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MinorVersionLess",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
},
{"PatchVersionLess",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionGreater",
false,
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
},
{"MinorVersionGreater",
false,
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"PatchVersionGreater",
false,
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
}
for _, c := range cases {
t.Run("Test: "+c.name, func(t *testing.T) {
t.Parallel()
got := c.s1.IsEqualTo(c.s2)
if c.want != got {
t.Errorf("Expected %+v got %+v", c.want, got)
}
})
}
}
func TestSemVersion_IsLessOrEqual(t *testing.T) {
cases := []struct {
name string
want bool
s1, s2 SemVersion
}{
{"IsEqualTo",
true,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionLess",
true,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MinorVersionLess",
true,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
},
{"PatchVersionLess",
true,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionGreater",
false,
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
},
{"MinorVersionGreater",
false,
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"PatchVersionGreater",
false,
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
}
for _, c := range cases {
t.Run("Test: "+c.name, func(t *testing.T) {
t.Parallel()
got := c.s1.IsLessOrEqual(c.s2)
if c.want != got {
t.Errorf("Expected %+v got %+v", c.want, got)
}
})
}
}
func TestSemVersion_IsGreaterOrEqual(t *testing.T) {
cases := []struct {
name string
want bool
s1, s2 SemVersion
}{
{"IsEqualTo",
true,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionLess",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MinorVersionLess",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
},
{"PatchVersionLess",
false,
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
},
{"MajorVersionGreater",
true,
SemVersion{
version: "2.2.3",
isStable: false,
majorVersion: 2,
minorVersion: 2,
patchVersion: 3,
},
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
},
{"MinorVersionGreater",
true,
SemVersion{
version: "1.3.3",
isStable: false,
majorVersion: 1,
minorVersion: 3,
patchVersion: 3,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
{"PatchVersionGreater",
true,
SemVersion{
version: "1.2.4",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 4,
},
SemVersion{
version: "1.2.3",
isStable: false,
majorVersion: 1,
minorVersion: 2,
patchVersion: 3,
},
},
}
for _, c := range cases {
t.Run("Test: "+c.name, func(t *testing.T) {
t.Parallel()
got := c.s1.IsGreaterOrEqual(c.s2)
if c.want != got {
t.Errorf("Expected %+v got %+v", c.want, got)
}
})
}
}

View File

@ -15,20 +15,25 @@ const (
terraformPrefix = "/terraform_"
)
var needsStable = true
func main() {
homeDir, _ := os.UserHomeDir()
configDirString := homeDir + shortConfigDirString
// Create configuration directory if it does not exist
_, err := os.Stat(configDirString)
if os.IsNotExist(err) {
err = versionedTerraform.CreateConfig(configDirString, configFileLocation)
}
// Create configuration file if it does not exist
_, err = os.Stat(configDirString + "/" + configFileLocation)
if os.IsNotExist(err) {
err = versionedTerraform.CreateConfig(configDirString, configFileLocation)
}
// Let the user know if we couldn't create the config directory or file
if err != nil {
fmt.Printf("Unable to create config directory: %v", err)
}
@ -40,24 +45,28 @@ func main() {
flag.Parse()
args := flag.Args()
//Load available versions from configuration file
versionsFromConfig, err = versionedTerraform.LoadVersionsFromConfig(configDir, configFileLocation)
if err != nil {
fmt.Printf("Unable to read config: %v", err)
fmt.Printf("Unable to read config: %v\n", err)
os.Exit(1)
}
//Check if we need to update available versions with terraform's website
//Then update configuration if we do
//todo move this above loading the config
needsUpdate, err := versionedTerraform.NeedToUpdateAvailableVersions(configDir, configFileLocation)
if os.ErrNotExist == err {
fmt.Println("Unable to update version: %v", err)
fmt.Printf("Unable to update version: %v\n", err)
}
fileHandle, _ := os.OpenFile(configDirString+"/"+configFileLocation, os.O_RDWR, 0666)
defer fileHandle.Close()
if needsUpdate {
fileHandle, _ := os.OpenFile(configDirString+"/"+configFileLocation, os.O_RDWR, 0666)
defer fileHandle.Close()
versionedTerraform.UpdateConfig(*fileHandle)
}
// Load a slice of versions which have already been installed
installedVersions, err := versionedTerraform.LoadInstalledVersions(configDir)
if err != nil {
fmt.Printf("Unable to verify installed verisons: %v", err)
@ -69,7 +78,14 @@ func main() {
vSlice = append(vSlice, v.ToString())
}
ver, err := versionedTerraform.GetVersionFromFile(workingDir, vSlice)
// Check if stable version of terraform is required
needsStable, err = versionedTerraform.ConfigRequiresStable(*fileHandle)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to open config file, defaulting to stable versions of terraform only")
}
// Load version required from terraform directory
ver, err := versionedTerraform.GetVersionFromFile(workingDir, vSlice, needsStable)
if err != nil {
fmt.Printf("Unable to retrieve terraform version from files: %v", err)
}
@ -82,6 +98,7 @@ func main() {
}
}
// Execute terraform
terraformFile := configDirString + terraformPrefix + ver.VersionToString()
argsForTerraform := append([]string{""}, args...)
cmd := exec.Cmd{
@ -93,5 +110,9 @@ func main() {
Stdout: os.Stdout,
Stderr: os.Stderr,
}
cmd.Run()
if err := cmd.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
os.Exit(exitError.ExitCode())
}
}
}

View File

@ -12,10 +12,36 @@ import (
)
type configStruct struct {
StableOnly bool
LastUpdate int64
AvailableVersions []string
}
//ConfigRequiresStable returns bool, error only false if StableOnly: false is set in configuration file
func ConfigRequiresStable(File os.File) (bool, error) {
fileHandle, err := os.Open(File.Name())
if err != nil {
return true, err
}
defer fileHandle.Close()
fileScanner := bufio.NewScanner(fileHandle)
fileScanner.Split(bufio.ScanLines)
for fileScanner.Scan() {
_line := fileScanner.Text()
if strings.Contains(_line, "StableOnly: ") {
isStable := strings.SplitAfter(_line, "StableOnly: ")[1]
if strings.EqualFold(isStable, "false") {
return false, nil
}
}
}
return true, nil
}
//NeedToUpdateAvailableVersions returns bool, error checks if last update was older than 1 day ago
// this prevents us from spamming the list of available terraform versions page
func NeedToUpdateAvailableVersions(fileSystem fs.FS, availableVersions string) (bool, error) {
//todo this is used a lot abstract it?
fileHandle, err := fileSystem.Open(availableVersions)
@ -45,6 +71,8 @@ func NeedToUpdateAvailableVersions(fileSystem fs.FS, availableVersions string) (
return false, nil
}
//LoadVersionsFromConfig returns slice of SemVersions and an error from AvailableVersions in configuration file
//This is stored from GetVersionList()
func LoadVersionsFromConfig(fileSystem fs.FS, configFile string) ([]SemVersion, error) {
fileHandle, err := fileSystem.Open(configFile)
removeOpenBracket := regexp.MustCompile("\\[")
@ -74,6 +102,7 @@ func LoadVersionsFromConfig(fileSystem fs.FS, configFile string) ([]SemVersion,
return nil, nil
}
//LoadInstalledVersions returns list of SemVersions and an error from the directory listing of the .versionedTerraform
func LoadInstalledVersions(fileSystem fs.FS) ([]SemVersion, error) {
dir, err := fs.ReadDir(fileSystem, ".")
var installedTerraformVersions []SemVersion
@ -92,24 +121,39 @@ func LoadInstalledVersions(fileSystem fs.FS) ([]SemVersion, error) {
return installedTerraformVersions, nil
}
func UpdateConfig(File os.File) error {
//UpdateConfig returns an error, and updates configuration file
// adding:
// a new date to the last updated field
// the available versions listed on terraforms website
// the status of if the user wants only stable releases
func UpdateConfig(File os.File, timeNow ...time.Time) error {
configValues := new(configStruct)
configValues.AvailableVersions, _ = GetVersionList()
configValues.StableOnly, _ = ConfigRequiresStable(File)
timeNow := time.Now()
configValues.LastUpdate = timeNow.Unix()
var t time.Time
if len(timeNow) > 0 {
t = timeNow[0]
} else {
t = time.Now()
}
configValues.LastUpdate = t.Unix()
File.Truncate(0)
File.Seek(0, 0)
lineToByte := []byte(fmt.Sprintf("LastUpdate: %d\n", configValues.LastUpdate))
lineToByte := []byte(fmt.Sprintf("StableOnly: %+v\n", configValues.StableOnly))
File.Write(lineToByte)
lineToByte = []byte(fmt.Sprintf("LastUpdate: %d\n", configValues.LastUpdate))
File.Write(lineToByte)
lineToByte = []byte(fmt.Sprintf("AvailableVersions: %+v\n", configValues.AvailableVersions))
File.Write(lineToByte)
return nil
}
//CreateConfig returns error, creates a new configuration file
func CreateConfig(directory string, configFile string) error {
configFileName := directory + "/" + configFile
err := os.MkdirAll(directory, 0755)
@ -120,6 +164,8 @@ func CreateConfig(directory string, configFile string) error {
fileHandler, err := os.Create(configFileName)
defer fileHandler.Close()
lineToByte := []byte(fmt.Sprintf("StableOnly: true\n"))
fileHandler.Write(lineToByte)
err = UpdateConfig(*fileHandler)
return err
}

View File

@ -2,8 +2,11 @@ package versionedTerraform
import (
"fmt"
"io"
"os"
"reflect"
"sort"
"strings"
"testing"
"testing/fstest"
"time"
@ -23,26 +26,26 @@ func TestUpdateAvailableVersions(t *testing.T) {
}
t.Run("Test success last update time", func(t *testing.T) {
want := true
want := false
got, err := NeedToUpdateAvailableVersions(fs, "successConfig.conf")
if err != nil {
t.Fatal(err)
}
if got != want {
t.Errorf("updateAvailableVersions had incorrect output expected %v got %v", got, want)
t.Errorf("updateAvailableVersions had incorrect output expected %v got %v", want, got)
}
})
t.Run("Test failed last update time", func(t *testing.T) {
want := false
want := true
got, err := NeedToUpdateAvailableVersions(fs, "failConfig.conf")
if err != nil {
t.Fatal(err)
}
if got != want {
t.Errorf("updateAvailableVersions had incorrect output expected %v got %v", got, want)
t.Errorf("updateAvailableVersions had incorrect output expected %v got %v", want, got)
}
})
}
@ -79,23 +82,27 @@ func TestInstalledVersions(t *testing.T) {
}
fs := fstest.MapFS{
"terraform_0.12.31": {Data: []byte("")},
"terraform_0.12.30": {Data: []byte("")},
"terraform_0.11.10": {Data: []byte("")},
"terraform_0.11.15": {Data: []byte("")},
"terraform_1.0.1": {Data: []byte("")},
"terraform_1.0.12": {Data: []byte("")},
"terraform_1.1.1": {Data: []byte("")},
"terraform_1.1.2": {Data: []byte("")},
"terraform_1.1.3": {Data: []byte("")},
"terraform_1.1.4": {Data: []byte("")},
"terraform_1.1.5": {Data: []byte("")},
"terraform_1.1.6": {Data: []byte("")},
"terraform_1.1.7": {Data: []byte("")},
"terraform_1.1.8": {Data: []byte("")},
"terraform_1.1.9": {Data: []byte("")},
"terraform_1.1.10": {Data: []byte("")},
"terraform_1.1.11": {Data: []byte("")},
"terraform_0.12.31": {Data: []byte("")},
"terraform_0.12.30": {Data: []byte("")},
"terraform_0.11.10": {Data: []byte("")},
"terraform_0.11.15": {Data: []byte("")},
"terraform_1.0.1": {Data: []byte("")},
"terraform_1.0.12": {Data: []byte("")},
"terraform_1.2.23-alpha": {Data: []byte("")},
"terraform_1.1.1": {Data: []byte("")},
"terraform_1.1.2": {Data: []byte("")},
"terraform_1.1.3": {Data: []byte("")},
"terraform_1.1.4": {Data: []byte("")},
"terraform_1.1.5": {Data: []byte("")},
"terraform_1.1.6": {Data: []byte("")},
"terraform_1.1.7": {Data: []byte("")},
"terraform_1.1.8": {Data: []byte("")},
"terraform_1.1.9": {Data: []byte("")},
"terraform_1.1.10": {Data: []byte("")},
"terraform_1.1.11": {Data: []byte("")},
"terraform_0.14.0": {Data: []byte("")},
"terraform_0.13.1": {Data: []byte("")},
"terraform_0.13.0": {Data: []byte("")},
}
t.Run("Test installed versions", func(t *testing.T) {
@ -110,3 +117,73 @@ func TestInstalledVersions(t *testing.T) {
})
}
func TestConfigRequiresStable(t *testing.T) {
availableVersions, _ := GetVersionList()
versions := strings.Join(availableVersions, " ")
cases := []struct {
name, content, want string
timeNow time.Time
}{
{"StableOnly True", "StableOnly: true\n" +
"LastUpdate: 1674481203\n" +
"AvailableVersions: [1.3.7]",
"StableOnly: true\n" +
"LastUpdate: 1286705410\n" +
"AvailableVersions: [" +
versions + "]\n",
time.Date(2010, 10, 10, 10, 10, 10, 10, time.UTC)},
{"StableOnly False", "StableOnly: false\n" +
"LastUpdate: 1674481203\n" +
"AvailableVersions: [1.3.7]",
"StableOnly: false\n" +
"LastUpdate: 1286705410\n" +
"AvailableVersions: [" +
versions + "]\n",
time.Date(2010, 10, 10, 10, 10, 10, 10, time.UTC)},
{"StableOnly not found", "LastUpdate: 1674481203\n" +
"AvailableVersions: [1.3.7]",
"StableOnly: true\n" +
"LastUpdate: 1286705410\n" +
"AvailableVersions: [" +
versions + "]\n",
time.Date(2010, 10, 10, 10, 10, 10, 10, time.UTC)},
}
for _, c := range cases {
t.Run("Test: "+c.name, func(t *testing.T) {
t.Parallel()
tempDir := os.TempDir()
tempFile, err := os.Create(tempDir + "/config")
defer tempFile.Close()
if err != nil {
t.Errorf("Unable to execute test : %v", err)
}
UpdateConfig(*tempFile, c.timeNow)
tempFile.Seek(0, 0)
data := make([]byte, 1024)
var got string
for {
n, err := tempFile.Read(data)
if err == io.EOF {
break
}
if err != nil {
t.Errorf("File reading error : %v", err)
return
}
got += string(data[:n])
}
if !reflect.DeepEqual(got, c.want) {
t.Errorf("%v test failed to meet conditions", c.name)
fmt.Fprintf(os.Stdout, "%v\n", c.want)
fmt.Fprintf(os.Stdout, "%v\n", got)
}
})
}
}

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_darwin_amd64.zip"
fileSuffix = "_darwin_amd64.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_darwin_arm64.zip"
fileSuffix = "_darwin_arm64.zip"
minVersion = "1.0.2"
alternateSuffix = "_darwin_amd64.zip"
)

View File

@ -7,9 +7,15 @@ import (
"strings"
)
var needsStable bool
//GetVersionFromFile returns Version pointer and error
//Iterates through files in current directory and sending to parseVersionFromFile
//todo this should be (Version) GetVers...
func GetVersionFromFile(fileSystem fs.FS, versionList []string) (*Version, error) {
func GetVersionFromFile(fileSystem fs.FS, versionList []string, needsStableValue bool) (*Version, error) {
needsStable = needsStableValue
var versionFinal Version
versionFinal = *NewVersion(">= 0.0.0", versionList)
dir, err := fs.ReadDir(fileSystem, ".")
if err != nil {
return &versionFinal, err
@ -29,6 +35,9 @@ func GetVersionFromFile(fileSystem fs.FS, versionList []string) (*Version, error
}
//todo same here
//parseVersionFromFile returns Version pointer, bool, and error
//bool returns true if required_version is found
//if required_version is found sends to NewVersion to determine required version for the application
func parseVersionFromFile(f fs.FS, fileName string, versionList []string) (*Version, bool, error) {
fileHandle, err := f.Open(fileName)
regex := regexp.MustCompile("required_version\\s+?=")

View File

@ -5,9 +5,8 @@ import (
"testing/fstest"
)
func TestFileHandler(t *testing.T) {
const (
firstFile = `
const (
firstFile = `
resource "aws_mq_broker" "sample" {
depends_on = [aws_security_group.mq]
broker_name = var.name
@ -21,13 +20,14 @@ resource "aws_mq_broker" "sample" {
subnet_ids = ["10.0.0.0/24", "10.0.1.0/24"]
}
`
secondFile = `
secondFile = `
terraform {
required_version = "~> 0.12.4"
}
`
)
)
func TestFileHandler(t *testing.T) {
want := NewVersion("0.12.31", testVersionList())
fs := fstest.MapFS{
@ -35,7 +35,25 @@ terraform {
"versions.tf": {Data: []byte(secondFile)},
}
version, err := GetVersionFromFile(fs, testVersionList())
version, err := GetVersionFromFile(fs, testVersionList(), true)
if err != nil {
t.Fatal(err)
}
got := *version
if got.Version != want.Version {
t.Errorf("Expected %v, got %v", want.Version, got.Version)
}
}
func TestEmptyTerraformVersion(t *testing.T) {
want := NewVersion("1.1.11", testVersionList())
fs := fstest.MapFS{"main.tf": {Data: []byte(firstFile)}}
version, err := GetVersionFromFile(fs, testVersionList(), true)
if err != nil {
t.Fatal(err)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_freebsd_386.zip"
fileSuffix = "_freebsd_386.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_freebsd_amd64.zip"
fileSuffix = "_freebsd_amd64.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_freebsd_arm.zip"
fileSuffix = "_freebsd_arm.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_linux_386.zip"
fileSuffix = "_linux_386.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_linux_amd64.zip"
fileSuffix = "_linux_amd64.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_linux_arm.zip"
fileSuffix = "_linux_arm.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_linux_arm64.zip"
fileSuffix = "_linux_arm64.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_openbsd_386.zip"
fileSuffix = "_openbsd_386.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_openbsd_amd64.zip"
fileSuffix = "_openbsd_amd64.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_solaris_amd64.zip"
fileSuffix = "_solaris_amd64.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -5,22 +5,15 @@ import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"regexp"
"strings"
)
func (*Version) latestMajorVersion() {
}
func (*Version) latestMinorVersion() {
}
func (*Version) latestPatchVersion() {
}
type Version struct {
Version SemVersion
availableVersions []SemVersion
@ -33,95 +26,124 @@ const (
versionedTerraformFolder = "/.versionedTerraform"
)
//getLatestMajorRelease() returns the latest major release from Version
// getLatestMajorRelease() returns the latest major release from Version
func (v *Version) getLatestMajorRelease() {
//todo clean up
for _, release := range v.availableVersions {
if release.majorVersion == v.Version.majorVersion &&
release.minorVersion == v.Version.minorVersion &&
release.patchVersion >= v.Version.patchVersion {
release.patchVersion >= v.Version.patchVersion &&
(v.Version.isStable || !needsStable) {
v.Version = release
}
}
}
//getLatestRelease returns the latest release from Version
func (v *Version) getLatestRelease() {
//todo clean up
// getGreatestRelease() returns less than release
func (v *Version) getOneLessRelease() {
var vSlice []Version
for _, release := range v.availableVersions {
if release.majorVersion > v.Version.majorVersion {
_v := Version{
Version: release,
availableVersions: v.availableVersions,
installedVersions: v.installedVersions,
}
if isVersionGreater(*v, _v) {
vSlice = append(vSlice, _v)
}
}
for i, ver := range vSlice {
if isVersionGreater(ver, *v) || i == 0 {
*v = ver
}
}
}
// getLatestRelease returns the latest release from Version
func (v *Version) getLatestRelease() {
for _, release := range v.availableVersions {
if release.majorVersion > v.Version.majorVersion &&
(release.isStable || !needsStable) {
v.Version = release
}
if release.majorVersion >= v.Version.majorVersion &&
release.minorVersion > v.Version.minorVersion {
release.minorVersion > v.Version.minorVersion &&
(release.isStable || !needsStable) {
v.Version = release
}
if release.majorVersion >= v.Version.majorVersion &&
release.minorVersion >= v.Version.minorVersion &&
release.patchVersion >= v.Version.patchVersion {
release.patchVersion >= v.Version.patchVersion &&
(release.isStable || !needsStable) {
v.Version = release
}
}
}
//InstallTerraformVersion installs the defined terraform Version in the application
//configuration directory
// InstallTerraformVersion installs the defined terraform Version in the application
// configuration directory
func (v *Version) InstallTerraformVersion() error {
homeDir, _ := os.UserHomeDir()
resp, err := http.Get(hashicorpUrl +
suffix := fileSuffix
minV := NewSemVersion(minVersion)
if v.Version.IsLessThan(*minV) {
suffix = alternateSuffix
}
url := hashicorpUrl +
v.Version.ToString() +
"/" + terraformPrefix +
v.Version.ToString() +
fileSuffix)
suffix
resp, err := http.Get(url)
if err != nil {
return err
return fmt.Errorf("failed to download Terraform: %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
return fmt.Errorf("failed to read response body: %v", err)
}
zipReader, err := zip.NewReader(bytes.NewReader(body), int64(len(body)))
if err != nil {
return err
return fmt.Errorf("failed to create zip reader: %v", err)
}
versionedFileName := homeDir + versionedTerraformFolder + "/" + terraformPrefix + v.Version.ToString()
versionedFile, err := os.OpenFile(versionedFileName, os.O_WRONLY, 0755)
if os.IsNotExist(err) {
//_, err = os.Create(versionedFileName)
//if err != nil {
// return err
//}
versionedFile, err = os.OpenFile(versionedFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return err
}
}
versionedFile, err := os.OpenFile(versionedFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return err
return fmt.Errorf("failed to create output file: %v", err)
}
defer versionedFile.Close()
for _, zipFIle := range zipReader.File {
zr, err := zipFIle.Open()
if err != nil {
return err
for _, zipFile := range zipReader.File {
if zipFile.Name != "terraform" {
continue
}
unzippedFileBytes, _ := ioutil.ReadAll(zr)
_, err = versionedFile.Write(unzippedFileBytes)
zr, err := zipFile.Open()
if err != nil {
return err
return fmt.Errorf("failed to open zip file: %v", err)
}
zr.Close()
defer zr.Close()
_, err = io.Copy(versionedFile, zr)
if err != nil {
return fmt.Errorf("failed to write terraform binary: %v", err)
}
break
}
return nil
}
//NewVersion creates a new Version using sem versioning for determining the
//latest release
// NewVersion creates a new Version using sem versioning for determining the
// latest release
func NewVersion(_version string, _vList []string) *Version {
v := new(Version)
v.Version = *NewSemVersion(_version)
@ -130,6 +152,39 @@ func NewVersion(_version string, _vList []string) *Version {
v.availableVersions = append(v.availableVersions, *NewSemVersion(release))
}
hasMultiVersions, _ := regexp.MatchString("\\d+,", v.Version.ToString())
if hasMultiVersions {
releases := strings.Split(v.Version.ToString(), ",")
for iteration, _release := range releases {
_v := new(Version)
_v.availableVersions = v.availableVersions
switch {
case strings.Contains(_release, latestRelease):
release := strings.Split(_release, latestRelease)[1]
_v.Version = *NewSemVersion(release)
_v.getLatestRelease()
case strings.Contains(_release, latestPatch):
release := strings.Split(_release, latestPatch)[1]
_v.Version = *NewSemVersion(release)
_v.getLatestMajorRelease()
case strings.Contains(_release, versionLessOrEqual):
release := strings.Split(_release, versionLessOrEqual)[1]
_v.Version = *NewSemVersion(release)
case strings.Contains(_release, versionLessThan):
release := strings.Split(_release, versionLessThan)[1]
_v.Version = *NewSemVersion(release)
_v.getOneLessRelease()
}
if isVersionGreater(*_v, *v) || iteration == 0 {
v = _v
}
}
return v
}
switch {
case strings.Contains(v.Version.ToString(), latestRelease):
release := strings.Split(v.Version.ToString(), latestRelease)[1]
@ -139,12 +194,19 @@ func NewVersion(_version string, _vList []string) *Version {
release := strings.Split(v.Version.ToString(), latestPatch)[1]
v.Version = *NewSemVersion(release)
v.getLatestMajorRelease()
case strings.Contains(v.Version.ToString(), versionLessOrEqual):
release := strings.Split(v.Version.ToString(), versionLessOrEqual)[1]
v.Version = *NewSemVersion(release)
case strings.Contains(v.Version.ToString(), versionLessThan):
release := strings.Split(v.Version.ToString(), versionLessThan)[1]
v.Version = *NewSemVersion(release)
v.getOneLessRelease()
}
return v
}
//GetVersionList returns a list of available versions from hashicorp's release page
// GetVersionList returns a list of available versions from hashicorp's release page
func GetVersionList() ([]string, error) {
var versionList []string
resp, err := http.Get(hashicorpUrl)
@ -176,7 +238,7 @@ func GetVersionList() ([]string, error) {
return versionList, nil
}
//removeSpacesVersion removes spaces from Version string for parsing
// removeSpacesVersion removes spaces from Version string for parsing
func removeSpacesVersion(v string) string {
splitV := strings.Split(v, " ")
var returnString string
@ -187,7 +249,33 @@ func removeSpacesVersion(v string) string {
return strings.TrimSpace(returnString)
}
//VersionToString returns string of a Version
// VersionToString returns string of a Version
func (v *Version) VersionToString() string {
return v.Version.ToString()
}
// isVersionGreater returns true if v1 is greater than v2
func isVersionGreater(v1 Version, v2 Version) bool {
if v1.Version.majorVersion != v2.Version.majorVersion {
if v1.Version.majorVersion > v2.Version.majorVersion {
return true
}
return false
}
if v1.Version.minorVersion != v2.Version.minorVersion {
if v1.Version.minorVersion > v2.Version.minorVersion {
return true
}
return false
}
if v1.Version.patchVersion != v2.Version.patchVersion {
if v1.Version.patchVersion > v2.Version.patchVersion {
return true
}
return false
}
return false
}

View File

@ -6,6 +6,7 @@ import (
func testVersionList() []string {
return []string{
"1.2.23-alpha",
"1.1.11",
"1.1.10",
"1.1.9",
@ -19,6 +20,9 @@ func testVersionList() []string {
"1.1.1",
"1.0.12",
"1.0.1",
"0.14.0",
"0.13.1",
"0.13.0",
"0.12.31",
"0.12.30",
"0.11.15",
@ -39,6 +43,11 @@ func TestGetVersion(t *testing.T) {
{testVersionList(), ">= 0.11.15", "1.1.11"},
{testVersionList(), ">= 0.12.0", "1.1.11"},
{testVersionList(), "~> 0.12", "0.12.31"},
{testVersionList(), "< 0.12", "0.11.15"},
{testVersionList(), "<= 0.12.31", "0.12.31"},
{testVersionList(), "~> 0.12.0, < 0.13", "0.12.31"},
{testVersionList(), "~> 0.12.0, < 0.14", "0.13.1"},
{testVersionList(), "~> 0.12.0, <= 0.14.0", "0.14.0"},
}
for _, c := range cases {
@ -74,9 +83,62 @@ func TestRemoveSpacesVersion(t *testing.T) {
}
}
func TestIsVersionGreater(t *testing.T) {
cases := []struct {
testName string
testValueOne, testValueTwo Version
want bool
}{
{"equal versions",
*NewVersion("0.12.10", testVersionList()),
*NewVersion("0.12.10", testVersionList()),
false,
},
{"major greater versions",
*NewVersion("1.12.10", testVersionList()),
*NewVersion("0.12.10", testVersionList()),
true,
},
{"major less versions",
*NewVersion("0.12.10", testVersionList()),
*NewVersion("1.12.10", testVersionList()),
false,
},
{"minor greater versions",
*NewVersion("0.13.10", testVersionList()),
*NewVersion("0.12.10", testVersionList()),
true,
},
{"minor less versions",
*NewVersion("0.12.10", testVersionList()),
*NewVersion("0.13.10", testVersionList()),
false,
},
{"patch greater versions",
*NewVersion("0.12.11", testVersionList()),
*NewVersion("0.12.10", testVersionList()),
true,
},
{"patch less versions",
*NewVersion("0.12.10", testVersionList()),
*NewVersion("0.12.11", testVersionList()),
false,
},
}
for _, c := range cases {
t.Run("test isVersionGreater: "+c.testName, func(t *testing.T) {
got := isVersionGreater(c.testValueOne, c.testValueTwo)
if got != c.want {
t.Errorf("Got %t, want %t", got, c.want)
}
})
}
}
func TestGetVersionList(t *testing.T) {
//todo write test for this
//response, _ := getVersionList()
//response, _ := GetVersionList()
//for _, Version := range response {
// t.Errorf("%v", Version)
//}

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_windows_386.zip"
fileSuffix = "_windows_386.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)

View File

@ -4,5 +4,7 @@
package versionedTerraform
const (
fileSuffix = "_windows_amd64.zip"
fileSuffix = "_windows_amd64.zip"
minVersion = "0.0.0"
alternateSuffix = ""
)