Skip to content

Commit

Permalink
feat: Support multiple TF version constraints from module and improve…
Browse files Browse the repository at this point in the history
… logging (#362)

* feat: Support multiple TF version constaints from module
* Improve logging on reading TF version constraint (moved from #361)
* Align with https://github.com/hashicorp/terraform-config-inspect/blob/master/main.go#L35C2-L37
* Update `test-data/integration-tests/test_versiontf/version.tf` with multiple TF version constraints
* Drop `required_providers` from `test-data/integration-tests/test_versiontf/version.tf` as `tfswitch` does not handle TF providers
* Modified function to return an error in case of non matching constraints
* Added testcase for non matching constraints
* Moved failing testcase to skip-integration tests

---------

Co-authored-by: Johannes Brunswicker <johannes.brunswicker@crownpeak.com>
Co-authored-by: Hugh Wells <hugh@crablab.co.uk>
  • Loading branch information
3 people authored Apr 23, 2024
1 parent e7404d4 commit 87853c8
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 16 deletions.
2 changes: 1 addition & 1 deletion lib/param_parsing/parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func GetParameters() Params {
} else if terraformVersionFileExists(params) {
params, err = GetParamsFromTerraformVersion(params)
} else if isTerraformModule(params) {
params, _ = GetVersionFromVersionsTF(params)
params, err = GetVersionFromVersionsTF(params)
} else if terraGruntFileExists(params) {
params, err = GetVersionFromTerragrunt(params)
} else {
Expand Down
61 changes: 56 additions & 5 deletions lib/param_parsing/versiontf.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,69 @@
package param_parsing

import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/hashicorp/terraform-config-inspect/tfconfig"
"github.com/warrensbox/terraform-switcher/lib"
)

func GetVersionFromVersionsTF(params Params) (Params, error) {
logger.Infof("Reading version from terraform module at %q", params.ChDirPath)
module, err := tfconfig.LoadModule(params.ChDirPath)
var tfConstraints []string
var exactConstraints []string

curDir, err := os.Getwd()
if err != nil {
logger.Fatalf("Could not get current working directory: %v", err)
}

absPath := params.ChDirPath
if !filepath.IsAbs(params.ChDirPath) {
absPath, err = filepath.Abs(params.ChDirPath)
if err != nil {
logger.Fatalf("Could not derive absolute path to %q: %v", params.ChDirPath, err)
}
}

relPath, err := filepath.Rel(curDir, absPath)
if err != nil {
logger.Errorf("Could not load terraform module at %q", params.ChDirPath)
return params, err.Err()
logger.Fatalf("Could not derive relative path to %q: %v", params.ChDirPath, err)
}

logger.Infof("Reading version from Terraform module at %q", relPath)
module, _ := tfconfig.LoadModule(params.ChDirPath)
if module.Diagnostics.HasErrors() {
logger.Fatalf("Could not load Terraform module at %q", params.ChDirPath)
}
tfConstraint := module.RequiredCore[0]

requiredVersions := module.RequiredCore

for key := range requiredVersions {
tfConstraint := requiredVersions[key]
tfConstraintParts := strings.Fields(tfConstraint)

if len(tfConstraintParts) > 2 {
logger.Fatalf("Invalid version constraint found: %q", tfConstraint)
} else if len(tfConstraintParts) == 1 {
exactConstraints = append(exactConstraints, tfConstraint)
tfConstraint = "= " + tfConstraintParts[0]
}

if tfConstraintParts[0] == "=" {
exactConstraints = append(exactConstraints, tfConstraint)
}

tfConstraints = append(tfConstraints, tfConstraint)
}

if len(exactConstraints) > 0 && len(tfConstraints) > 1 {
return params, fmt.Errorf("exact constraint (%q) cannot be combined with other conditions", strings.Join(exactConstraints, ", "))
}

tfConstraint := strings.Join(tfConstraints, ", ")

version, err2 := lib.GetSemver(tfConstraint, params.MirrorURL)
if err2 != nil {
logger.Errorf("No version found matching %q", tfConstraint)
Expand Down
27 changes: 22 additions & 5 deletions lib/param_parsing/versiontf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,37 @@ import (
"fmt"
"github.com/hashicorp/go-version"
"github.com/warrensbox/terraform-switcher/lib"
"strings"
"testing"
)

func TestGetVersionFromVersionsTF(t *testing.T) {
func TestGetVersionFromVersionsTF_matches_version(t *testing.T) {
logger = lib.InitLogger("DEBUG")
var params Params
params = initParams(params)
params.ChDirPath = "../../test-data/integration-tests/test_versiontf"
params, _ = GetVersionFromVersionsTF(params)
v1, _ := version.NewVersion("1.0.0")
v2, _ := version.NewVersion("2.0.0")
v1, _ := version.NewVersion("1.0.5")
actualVersion, _ := version.NewVersion(params.Version)
if !actualVersion.GreaterThanOrEqual(v1) || !actualVersion.LessThan(v2) {
t.Error("Determined version is not between 1.0.0 and 2.0.0")
if !actualVersion.Equal(v1) {
t.Error("Determined version is not 1.0.5")
}
}

func TestGetVersionFromVersionsTF_non_matching_constraints(t *testing.T) {
logger = lib.InitLogger("DEBUG")
var params Params
params = initParams(params)
params.ChDirPath = "../../test-data/skip-integration-tests/test_versiontf_non_matching_constraints"
params, err := GetVersionFromVersionsTF(params)
if err == nil {
t.Error("Expected error but got nil")
} else {
expected := "exact constraint ("
expected2 := ") cannot be combined with other conditions"
if !strings.Contains(fmt.Sprint(err), expected) || !strings.Contains(fmt.Sprint(err), expected2) {
t.Errorf("Expected error string containing %q and %q. Got %q", expected, expected2, err)
}
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/semver.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func SemVerParser(tfconstraint *string, tflist []string) (string, error) {
}
}
}

return "", fmt.Errorf("did not find version matching constraint: %s", *tfconstraint)
}

Expand Down
9 changes: 4 additions & 5 deletions test-data/integration-tests/test_versiontf/version.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
terraform {
required_version = "~> 1.0.0"
}

required_providers {
aws = ">= 2.52.0"
kubernetes = ">= 1.11.1"
}
}
terraform {
required_version = "<= 1.0.5"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
terraform {
required_version = "~> 1.0.0"
}

terraform {
required_version = "= 1.0.5"
}

terraform {
required_version = "<= 1.0.4"
}

0 comments on commit 87853c8

Please sign in to comment.