From 2a80a2504e807ec973724af0ae8e9f6eeff2a101 Mon Sep 17 00:00:00 2001 From: Tom Elliott Date: Fri, 10 May 2024 21:11:15 +0000 Subject: [PATCH] Add support for creating backend files at runtime Add a "reconfigure" param for working directories that force an init for each command. Add a provider for working directories to provide paths to the actual module. --- rules/terraform.bzl | 29 ++++++++++++++++++---- tests/backend_init/BUILD | 23 ++++++++++++++++++ tests/backend_init/main.tf | 13 ++++++++++ tests/backend_init/test.sh | 49 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 tests/backend_init/BUILD create mode 100644 tests/backend_init/main.tf create mode 100755 tests/backend_init/test.sh diff --git a/rules/terraform.bzl b/rules/terraform.bzl index ea37323..e74b411 100644 --- a/rules/terraform.bzl +++ b/rules/terraform.bzl @@ -3,6 +3,11 @@ load("@tf_modules//rules:module.bzl", "TerraformModuleInfo") load("@tf_modules//rules:provider.bzl", "TerraformProviderInfo") load("@tf_modules//toolchains/terraform:toolchain.bzl", "TerraformExecutableInfo") +TerraformWorkingDirInfo = provider( + doc = "Contains information about a Terraform working directory", + fields = ["module_working_directory", "terraform_version", "terraform_binary_path"], +) + def terraform_working_directory_impl(ctx): module = ctx.attr.module[TerraformModuleInfo] terraform_version = ctx.attr.terraform[TerraformExecutableInfo].version @@ -29,6 +34,10 @@ def terraform_working_directory_impl(ctx): prep_command = "tar -xvzf .terraform.tar.gz > /dev/null" + reconfigure_cmd = "" + if ctx.attr.reconfigure: + reconfigure_cmd = "$BASE_PATH/{} init -input=false -reconfigure".format(ctx.executable.terraform.short_path) + # Create the script that runs Terraform ctx.actions.write( output = ctx.outputs.executable, @@ -38,12 +47,14 @@ BASE_PATH=$(pwd) {2} cd {0} {3} +{4} $BASE_PATH/{1} $@ """.format( build_base_path + "/" + working_dir, ctx.executable.terraform.short_path, env_vars, prep_command, + reconfigure_cmd, ), ) @@ -159,11 +170,18 @@ disable_checkpoint = true if terraform_version < "0.14": all_outputs += intermediates - return DefaultInfo( - executable = ctx.outputs.executable, - files = depset(all_outputs), - runfiles = ctx.runfiles(all_outputs + [ctx.executable.terraform]) - ) + return [ + DefaultInfo( + executable = ctx.outputs.executable, + files = depset(all_outputs), + runfiles = ctx.runfiles(all_outputs + [ctx.executable.terraform]) + ), + TerraformWorkingDirInfo( + module_working_directory = dot_terraform_tar.dirname, + terraform_version = terraform_version, + terraform_binary_path = ctx.executable.terraform.path, + ) + ] terraform_working_directory = rule( implementation = terraform_working_directory_impl, @@ -180,5 +198,6 @@ terraform_working_directory = rule( "tf_vars": attr.string_dict(), "providers": attr.label_list(providers = [TerraformProviderInfo]), "allow_provider_download": attr.bool(default=False), + "reconfigure": attr.bool(default=False, doc="Run `terraform init -reconfigure` before each operation to accept changes in backend configuration."), }, ) diff --git a/tests/backend_init/BUILD b/tests/backend_init/BUILD new file mode 100644 index 0000000..f3bfbb5 --- /dev/null +++ b/tests/backend_init/BUILD @@ -0,0 +1,23 @@ +load("@tf_modules//rules:module.bzl", "terraform_module") +load("@tf_modules//rules:terraform.bzl", "terraform_working_directory") + +terraform_module( + name = "provider", + srcs = ["main.tf"], + visibility = ["//visibility:public"], +) + +terraform_working_directory( + name = "terraform", + module = ":provider", + allow_provider_download = True, + reconfigure = True, +) + +sh_test( + name = "terraform_test", + size = "small", + srcs = ["test.sh"], + data = [":terraform"], +) + diff --git a/tests/backend_init/main.tf b/tests/backend_init/main.tf new file mode 100644 index 0000000..77f8e69 --- /dev/null +++ b/tests/backend_init/main.tf @@ -0,0 +1,13 @@ +terraform { + required_providers { + local = { + source = "hashicorp/local" + version = ">= 2.4.1" + } + } +} + +resource "local_file" "foo" { + content = "foo!" + filename = "${path.module}/foo.bar" +} \ No newline at end of file diff --git a/tests/backend_init/test.sh b/tests/backend_init/test.sh new file mode 100755 index 0000000..5923fd3 --- /dev/null +++ b/tests/backend_init/test.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +STATE_DIR=$(mktemp -d) + +MODULE_DIR=./tests/backend_init/terraform_working/tests/backend_init + +BACKEND_FILE="$MODULE_DIR/local_backend.tf" +cat > "$BACKEND_FILE" <<-EOF +terraform { + backend "local" { + path = "$STATE_DIR/terraform.tfstate" + + } +} +EOF + +if [ -f $STATE_DIR/terraform.tfstate ]; then + echo "Temp tfstate file should not exist before apply" + exit 1 +fi + +OUT=$(./tests/backend_init/terraform apply -auto-approve -no-color) +if [ $? -ne 0 ]; +then + echo 'Apply failed'; + exit 1 +fi + +PASS=1 + +function expect_output() { + if [[ "$OUT" != *"$1"* ]]; then + echo "FAIL: Expected text '$1'" + PASS=0 + fi +} + +expect_output "+ resource \"local_file\" \"foo\" {" +expect_output "1 to add" + +if [[ $PASS == 0 ]]; then + echo "$OUT" + exit 1 +fi + +if [ ! -f $STATE_DIR/terraform.tfstate ]; then + echo "Temp tfstate file should exist after apply" + exit 1 +fi \ No newline at end of file