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

Add support for OpenTofu #1352

Merged
merged 11 commits into from
Oct 9, 2023
74 changes: 70 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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