Skip to content

Commit

Permalink
Merge pull request #1352 from gruntwork-io/feature/opentofu-1333
Browse files Browse the repository at this point in the history
Add support for OpenTofu
  • Loading branch information
denis256 committed Oct 9, 2023
2 parents e4dc9c3 + df5dcc8 commit 48ff8d3
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 9 deletions.
74 changes: 70 additions & 4 deletions .circleci/config.yml
Expand Up @@ -3,9 +3,9 @@ env: &env
GRUNTWORK_INSTALLER_VERSION: v0.0.36
MODULE_CI_VERSION: v0.46.0
MODULE_GCP_CI_VERSION: v0.1.1
TERRAFORM_VERSION: 1.1.4
TERRAFORM_VERSION: 1.5.7
PACKER_VERSION: 1.7.4
TERRAGRUNT_VERSION: v0.36.0
TERRAGRUNT_VERSION: v0.52.0
OPA_VERSION: v0.33.1
GO_VERSION: 1.21.1
GO111MODULE: auto
Expand Down Expand Up @@ -63,6 +63,16 @@ install_gruntwork_utils: &install_gruntwork_utils
sudo ln -s /usr/local/go/bin/go /usr/bin/go
echo "The installed version of Go is now $(go version)"
install_tofu: &install_tofu
name: Install OpenTofu
command: |
curl -L "https://github.com/opentofu/opentofu/releases/download/v1.6.0-alpha1/tofu_1.6.0-alpha1_linux_amd64.zip" -o tofu.zip
unzip -o tofu.zip
sudo install -m 0755 tofu /usr/local/bin/tofu
rm -rf tofu
rm -rf tofu.zip
tofu --version
install_docker_buildx: &install_docker_buildx
name: install docker buildx
command: |
Expand Down Expand Up @@ -158,7 +168,8 @@ jobs:
paths:
- project

test:
# run tests with terraform binary
test_terraform:
<<: *defaults
resource_class: large
steps:
Expand Down Expand Up @@ -195,6 +206,48 @@ jobs:
- store_test_results:
path: /tmp/logs

# run tests with tofu binary
test_tofu:
<<: *defaults
resource_class: large
steps:
- attach_workspace:
at: /home/circleci

- run:
<<: *install_gruntwork_utils
- run:
<<: *install_docker_buildx
- run:
<<: *install_tofu

# The weird way you have to set PATH in Circle 2.0
- run: |
echo 'export PATH=$HOME/.local/bin:$HOME/terraform:$HOME/packer:$PATH' >> $BASH_ENV
# remove terraform binary so tofu will be used
sudo rm -f $(which terraform)
# Run the tests. Note that we set the "-p 1" flag to tell Go to run tests in each package sequentially. Without
# this, Go buffers all log output until all packages are done, which with slower running tests can cause CircleCI
# to kill the build after more than 10 minutes without log output.
# NOTE: because this doesn't build with the kubernetes tag, it will not run the kubernetes tests. See
# kubernetes_test build steps.
- run: mkdir -p /tmp/logs
# check we can compile the azure code, but don't actually run the tests
- run: run-go-tests --packages "-p 1 -tags=azure -run IDontExist ./modules/azure"
- run: run-go-tests --packages "-p 1 ./..." | tee /tmp/logs/test_output.log

- run:
command: |
./cmd/bin/terratest_log_parser_linux_amd64 --testlog /tmp/logs/test_output.log --outputdir /tmp/logs
when: always

# Store test result and log artifacts for browsing purposes
- store_artifacts:
path: /tmp/logs
- store_test_results:
path: /tmp/logs

# We run the GCP tests in a separate build step using the Docker executor for better isolation and resiliency. Using
# The Docker executor ensures GCP tests do not erroneously make metadata network calls within CircleCI's private
# environment. For more information see: https://github.com/gruntwork-io/terratest/pull/765.
Expand Down Expand Up @@ -363,7 +416,20 @@ workflows:
tags:
only: /^v.*/

- test:
- test_terraform:
context:
- AWS__PHXDEVOPS__circle-ci-test
- GITHUB__PAT__gruntwork-ci
- SLACK__TOKEN__refarch-deployer-test
- SLACK__WEBHOOK__refarch-deployer-test
- SLACK__CHANNEL__test-workflow-approvals
requires:
- setup
filters:
tags:
only: /^v.*/

- test_tofu:
context:
- AWS__PHXDEVOPS__circle-ci-test
- GITHUB__PAT__gruntwork-ci
Expand Down
27 changes: 26 additions & 1 deletion modules/terraform/cmd.go
Expand Up @@ -2,6 +2,7 @@ package terraform

import (
"fmt"
"os/exec"

"github.com/gruntwork-io/terratest/modules/collections"
"github.com/gruntwork-io/terratest/modules/retry"
Expand Down Expand Up @@ -30,10 +31,20 @@ var commandsWithParallelism = []string{
"destroy-all",
}

const (
// TofuDefaultPath command to run tofu
TofuDefaultPath = "tofu"

// TerraformDefaultPath to run terraform
TerraformDefaultPath = "terraform"
)

var DefaultExecutable = defaultTerraformExecutable()

// GetCommonOptions extracts commons terraform options
func GetCommonOptions(options *Options, args ...string) (*Options, []string) {
if options.TerraformBinary == "" {
options.TerraformBinary = "terraform"
options.TerraformBinary = DefaultExecutable
}

if options.TerraformBinary == "terragrunt" {
Expand Down Expand Up @@ -112,3 +123,17 @@ func GetExitCodeForTerraformCommandE(t testing.TestingT, additionalOptions *Opti
}
return DefaultErrorExitCode, getExitCodeErr
}

func defaultTerraformExecutable() string {
cmd := exec.Command(TerraformDefaultPath, "-version")
cmd.Stdin = nil
cmd.Stdout = nil
cmd.Stderr = nil

if err := cmd.Run(); err == nil {
return TerraformDefaultPath
}

// fallback to Tofu if terraform is not available
return TofuDefaultPath
}
5 changes: 4 additions & 1 deletion modules/terraform/plan_test.go
Expand Up @@ -3,6 +3,7 @@ package terraform
import (
"fmt"
"path/filepath"
"strings"
"testing"

"github.com/gruntwork-io/terratest/modules/files"
Expand Down Expand Up @@ -79,8 +80,10 @@ func TestInitAndPlanWithPlanFile(t *testing.T) {

out, err := InitAndPlanE(t, options)
require.NoError(t, err)
// clean output to be consistent in checks
out = strings.ReplaceAll(out, "\n", "")
assert.Contains(t, out, "1 to add, 0 to change, 0 to destroy.")
assert.Contains(t, out, fmt.Sprintf("Saved the plan to: %s", planFilePath))
assert.Contains(t, out, fmt.Sprintf("Saved the plan to:%s", planFilePath))
assert.FileExists(t, planFilePath, "Plan file was not saved to expected location:", planFilePath)
}

Expand Down
7 changes: 5 additions & 2 deletions modules/terraform/show_test.go
Expand Up @@ -3,6 +3,7 @@ package terraform
import (
"fmt"
"path/filepath"
"strings"
"testing"

"github.com/gruntwork-io/terratest/modules/files"
Expand All @@ -25,7 +26,8 @@ func TestShowWithInlinePlan(t *testing.T) {
}

out := InitAndPlan(t, options)
require.Contains(t, out, fmt.Sprintf("Saved the plan to: %s", planFilePath))
out = strings.ReplaceAll(out, "\n", "")
require.Contains(t, out, fmt.Sprintf("Saved the plan to:%s", planFilePath))
require.FileExists(t, planFilePath, "Plan file was not saved to expected location:", planFilePath)

// show command does not accept Vars
Expand Down Expand Up @@ -55,7 +57,8 @@ func TestShowWithStructInlinePlan(t *testing.T) {
}

out := InitAndPlan(t, options)
require.Contains(t, out, fmt.Sprintf("Saved the plan to: %s", planFilePath))
out = strings.ReplaceAll(out, "\n", "")
require.Contains(t, out, fmt.Sprintf("Saved the plan to:%s", planFilePath))
require.FileExists(t, planFilePath, "Plan file was not saved to expected location:", planFilePath)

// show command does not accept Vars
Expand Down
4 changes: 3 additions & 1 deletion modules/version-checker/version_checker.go
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"regexp"

"github.com/gruntwork-io/terratest/modules/terraform"

"github.com/gruntwork-io/terratest/modules/shell"
"github.com/gruntwork-io/terratest/modules/testing"
"github.com/hashicorp/go-version"
Expand Down Expand Up @@ -125,7 +127,7 @@ func getBinary(params CheckVersionParams) (string, error) {
case Packer:
return "packer", nil
case Terraform:
return "terraform", nil
return terraform.DefaultExecutable, nil
default:
return "", fmt.Errorf("unsupported Binary for checking versions {%d}", params.Binary)
}
Expand Down

0 comments on commit 48ff8d3

Please sign in to comment.