Skip to content

Commit

Permalink
fix: Fixing remote state init skip (#3345)
Browse files Browse the repository at this point in the history
* fix: Fixing remote state init skip

* fix: Fixing `TestTerragruntDisableBucketUpdate` test

* fix: Using flag name constant
  • Loading branch information
yhakbar committed Aug 15, 2024
1 parent 446f6df commit 583bf70
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 16 deletions.
13 changes: 10 additions & 3 deletions remote/remote_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync"

"github.com/gruntwork-io/go-commons/errors"
"github.com/gruntwork-io/terragrunt/cli/commands"
"github.com/gruntwork-io/terragrunt/codegen"
"github.com/gruntwork-io/terragrunt/internal/cache"
"github.com/gruntwork-io/terragrunt/options"
Expand Down Expand Up @@ -94,10 +95,16 @@ func (remoteState *RemoteState) Initialize(ctx context.Context, terragruntOption

// Returns true if remote state needs to be configured. This will be the case when:
//
// 1. Remote state has not already been configured
// 2. Remote state has been configured, but with a different configuration
// 3. The remote state initializer for this backend type, if there is one, says initialization is necessary
// 1. Remote state auto-initialization has been disabled
// 2. Remote state has not already been configured
// 3. Remote state has been configured, but with a different configuration
// 4. The remote state initializer for this backend type, if there is one, says initialization is necessary
func (remoteState *RemoteState) NeedsInit(terragruntOptions *options.TerragruntOptions) (bool, error) {
if terragruntOptions.DisableBucketUpdate {
terragruntOptions.Logger.Debugf("Skipping remote state initialization due to %s flag", commands.TerragruntDisableBucketUpdateFlagName)
return false, nil
}

state, err := ParseTerraformStateFileFromLocation(remoteState.Backend, remoteState.Config, terragruntOptions.WorkingDir, terragruntOptions.DataDir())
if err != nil {
return false, err
Expand Down
17 changes: 12 additions & 5 deletions test/fixture/main.tf
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
terraform {
backend "s3" {}

required_providers {
external = {
source = "hashicorp/external"
version = "2.3.3"
}
}
}

# Create an arbitrary local resource
data "template_file" "test" {
template = "Hello, I am a template. My sample_var value = $${sample_var}"
data "external" "hello" {
program = ["bash", "-c", "sample_var=\"$$(cat - jq '.sample_var')\" && echo '{\"output\": \"Hello, I am a template. My sample_var value = $$sample_var\"}'"]

vars = {
query = {
sample_var = var.sample_var
}
}
}

5 changes: 3 additions & 2 deletions test/fixture/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
output "rendered_template" {
value = data.template_file.test.rendered
}
value = data.external.hello.result["output"]
}

22 changes: 22 additions & 0 deletions test/integration_s3_encryption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,28 @@ func TestTerragruntS3EncryptionWarning(t *testing.T) {
assert.NotContains(t, output, "Encryption is not enabled on the S3 remote state bucket "+s3BucketName)
}

func TestTerragruntSkipBackend(t *testing.T) {
t.Parallel()

tmpEnvPath := copyEnvironment(t, s3SSEAESFixturePath)
cleanupTerraformFolder(t, tmpEnvPath)
testPath := util.JoinPath(tmpEnvPath, s3SSEAESFixturePath)

// The bucket and table name here are intentionally invalid.
tmpTerragruntConfigPath := createTmpTerragruntConfig(t, s3SSEAESFixturePath, "N/A", "N/A", config.DefaultTerragruntConfigPath)

_, _, err := runTerragruntCommandWithOutput(t, "terragrunt init --terragrunt-non-interactive --terragrunt-config "+tmpTerragruntConfigPath+" --terragrunt-working-dir "+testPath+" -backend=false")
require.Error(t, err)

lockFile := util.JoinPath(testPath, ".terraform.lock.hcl")
assert.False(t, util.FileExists(lockFile), "Lock file %s exists", lockFile)

_, _, err = runTerragruntCommandWithOutput(t, "terragrunt init --terragrunt-non-interactive --terragrunt-config "+tmpTerragruntConfigPath+" --terragrunt-working-dir "+testPath+" --terragrunt-disable-bucket-update -backend=false")
require.NoError(t, err)

assert.True(t, util.FileExists(lockFile), "Lock file %s does not exist", lockFile)
}

func applyCommand(configPath, fixturePath string) string {
return fmt.Sprintf("terragrunt apply -auto-approve --terragrunt-non-interactive --terragrunt-config %s --terragrunt-working-dir %s", configPath, fixturePath)
}
52 changes: 46 additions & 6 deletions test/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4718,6 +4718,12 @@ func assertS3PublicAccessBlocks(t *testing.T, client *s3.S3, bucketName string)
assert.True(t, aws.BoolValue(publicAccessBlockConfig.RestrictPublicBuckets))
}

// createS3Bucket creates a test S3 bucket for state.
func createS3Bucket(t *testing.T, awsRegion string, bucketName string) {
err := createS3BucketE(t, awsRegion, bucketName)
require.NoError(t, err)
}

// createS3BucketE create test S3 bucket.
func createS3BucketE(t *testing.T, awsRegion string, bucketName string) error {
mockOptions, err := options.NewTerragruntOptionsForTest("integration_test")
Expand All @@ -4744,6 +4750,41 @@ func createS3BucketE(t *testing.T, awsRegion string, bucketName string) error {
return nil
}

// createDynamoDbTable creates a test DynamoDB table.
func createDynamoDbTable(t *testing.T, awsRegion string, tableName string) {
err := createDynamoDbTableE(t, awsRegion, tableName)
require.NoError(t, err)
}

// createDynamoDbTableE creates a test DynamoDB table, and returns an error if the table creation fails.
func createDynamoDbTableE(t *testing.T, awsRegion string, tableName string) error {
client := createDynamoDbClientForTest(t, awsRegion)
_, err := client.CreateTable(&dynamodb.CreateTableInput{
AttributeDefinitions: []*dynamodb.AttributeDefinition{
{
AttributeName: aws.String("LockID"),
AttributeType: aws.String("S"),
},
},
KeySchema: []*dynamodb.KeySchemaElement{
{
AttributeName: aws.String("LockID"),
KeyType: aws.String("HASH"),
},
},
TableName: aws.String(tableName),
ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
ReadCapacityUnits: aws.Int64(1),
WriteCapacityUnits: aws.Int64(1),
},
})
if err != nil {
return err
}
client.WaitUntilTableExists(&dynamodb.DescribeTableInput{TableName: aws.String(tableName)})
return nil
}

// deleteS3BucketWithRetry will attempt to delete the specified S3 bucket, retrying up to 3 times if there are errors to
// handle eventual consistency issues.
func deleteS3BucketWithRetry(t *testing.T, awsRegion string, bucketName string) {
Expand Down Expand Up @@ -6487,8 +6528,8 @@ func TestTerragruntDisableBucketUpdate(t *testing.T) {
s3BucketName := "terragrunt-test-bucket-" + strings.ToLower(uniqueId())
lockTableName := "terragrunt-test-locks-" + strings.ToLower(uniqueId())

err := createS3BucketE(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)
require.NoError(t, err)
createS3Bucket(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)
createDynamoDbTable(t, TERRAFORM_REMOTE_STATE_S3_REGION, lockTableName)

defer deleteS3Bucket(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)
defer cleanupTableForTest(t, lockTableName, TERRAFORM_REMOTE_STATE_S3_REGION)
Expand All @@ -6497,7 +6538,7 @@ func TestTerragruntDisableBucketUpdate(t *testing.T) {

runTerragrunt(t, fmt.Sprintf("terragrunt apply -auto-approve --terragrunt-disable-bucket-update --terragrunt-non-interactive --terragrunt-config %s --terragrunt-working-dir %s", tmpTerragruntConfigPath, rootPath))

_, err = bucketPolicy(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)
_, err := bucketPolicy(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)
// validate that bucket policy is not updated, because of --terragrunt-disable-bucket-update
require.Error(t, err)
}
Expand Down Expand Up @@ -6937,16 +6978,15 @@ func TestTerragruntUpdatePolicy(t *testing.T) {
s3BucketName := "terragrunt-test-bucket-" + strings.ToLower(uniqueId())
lockTableName := "terragrunt-test-locks-" + strings.ToLower(uniqueId())

err := createS3BucketE(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)
require.NoError(t, err)
createS3Bucket(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)

defer deleteS3Bucket(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)
defer cleanupTableForTest(t, lockTableName, TERRAFORM_REMOTE_STATE_S3_REGION)

tmpTerragruntConfigPath := createTmpTerragruntConfig(t, rootPath, s3BucketName, lockTableName, config.DefaultTerragruntConfigPath)

// check that there is no policy on created bucket
_, err = bucketPolicy(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)
_, err := bucketPolicy(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)
require.Error(t, err)

runTerragrunt(t, fmt.Sprintf("terragrunt apply -auto-approve --terragrunt-non-interactive --terragrunt-config %s --terragrunt-working-dir %s", tmpTerragruntConfigPath, rootPath))
Expand Down

0 comments on commit 583bf70

Please sign in to comment.