From 37382762820370a731d86d690054163474e7d36a Mon Sep 17 00:00:00 2001 From: Rob Lazzurs Date: Sat, 12 Oct 2024 14:55:02 +0100 Subject: [PATCH] fix: Move force_path_style to use_path_style As per the documentation linked below the force_path_style option is now deprecated and should be changed to use_path_style. https://developer.hashicorp.com/terraform/language/backend/s3#force_path_style As per the comments in #3472 I have made this PR to support both options but commented the code and the documentation to indicate that the old option is now deprecated --- ...eep-your-remote-state-configuration-dry.md | 4 +- go.mod | 13 +++-- go.sum | 14 +++++ remote/remote_state_s3.go | 4 +- remote/remote_state_s3_test.go | 56 +++++++++++++++++-- remote/remote_state_test.go | 4 +- 6 files changed, 81 insertions(+), 14 deletions(-) diff --git a/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md b/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md index c06ca9cec2..0ede97d1f4 100644 --- a/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md +++ b/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md @@ -229,6 +229,8 @@ For the `s3` backend, the following config options can be used for S3-compatible **Note**: The `skip_bucket_accesslogging` is now DEPRECATED. It is replaced by `accesslogging_bucket_name`. Please read below for more details on when to use the new config option. +**Note**: The `force_path_style` is now DEPRECATED. It is replaced by `use_path_style`. Please read below for more details on when to use the new config option. + ``` hcl remote_state { # ... @@ -245,7 +247,7 @@ remote_state { shared_credentials_file = "/path/to/credentials/file" skip_metadata_api_check = true - force_path_style = true + use_path_style = true } } ``` diff --git a/go.mod b/go.mod index 84141246f2..050754b666 100644 --- a/go.mod +++ b/go.mod @@ -28,10 +28,10 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 github.com/zclconf/go-cty v1.14.1 - golang.org/x/crypto v0.26.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/oauth2 v0.22.0 golang.org/x/sync v0.8.0 - golang.org/x/sys v0.24.0 + golang.org/x/sys v0.26.0 google.golang.org/api v0.195.0 ) @@ -92,8 +92,8 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.28.0 go.opentelemetry.io/otel/trace v1.29.0 golang.org/x/exp v0.0.0-20231006140011-7918f672742d - golang.org/x/term v0.23.0 - golang.org/x/text v0.17.0 + golang.org/x/term v0.25.0 + golang.org/x/text v0.19.0 google.golang.org/grpc v1.66.0 google.golang.org/protobuf v1.34.2 gopkg.in/ini.v1 v1.67.0 @@ -251,8 +251,9 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.28.0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/tools v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 0dbc38626f..a56b7792e2 100644 --- a/go.sum +++ b/go.sum @@ -1219,6 +1219,8 @@ golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1259,6 +1261,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1323,6 +1327,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1455,6 +1461,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1466,6 +1474,8 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1480,6 +1490,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1542,6 +1554,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/remote/remote_state_s3.go b/remote/remote_state_s3.go index aa2df72315..dce6902e16 100644 --- a/remote/remote_state_s3.go +++ b/remote/remote_state_s3.go @@ -115,7 +115,8 @@ type RemoteStateConfigS3 struct { LockTable string `mapstructure:"lock_table"` // Deprecated in Terraform version 0.13 or newer. DynamoDBTable string `mapstructure:"dynamodb_table"` CredsFilename string `mapstructure:"shared_credentials_file"` - S3ForcePathStyle bool `mapstructure:"force_path_style"` + S3ForcePathStyle bool `mapstructure:"force_path_style"` // Deprecated in Terraform version 1.6 or newer. + S3UsePathStyle bool `mapstructure:"use_path_style"` AssumeRole RemoteStateConfigS3AssumeRole `mapstructure:"assume_role"` } @@ -132,6 +133,7 @@ func (c *ExtendedRemoteStateConfigS3) GetAwsSessionConfig() *awshelper.AwsSessio SessionName: c.RemoteStateConfigS3.GetSessionName(), CredsFilename: c.RemoteStateConfigS3.CredsFilename, S3ForcePathStyle: c.RemoteStateConfigS3.S3ForcePathStyle, + S3UsePathStyle: c.RemoteStateConfigS3.S3UsePathStyle, DisableComputeChecksums: c.DisableAWSClientChecksums, } } diff --git a/remote/remote_state_s3_test.go b/remote/remote_state_s3_test.go index da3967c3a4..9f7f2c565c 100644 --- a/remote/remote_state_s3_test.go +++ b/remote/remote_state_s3_test.go @@ -287,7 +287,55 @@ func TestAwsForcePathStyleClientSession(t *testing.T) { s3Client, err := remote.CreateS3Client(s3ConfigExtended.GetAwsSessionConfig(), terragruntOptions) require.NoError(t, err, "Unexpected error creating client for test: %v", err) - actual := aws.BoolValue(s3Client.Config.S3ForcePathStyle) + actual := aws.BoolValue(s3Client.Config.S3UsePathStyle) + assert.Equal(t, testCase.expected, actual) + }) + } +} + +func TestAwsUsePathStyleClientSession(t *testing.T) { + t.Parallel() + + terragruntOptions, err := options.NewTerragruntOptionsForTest("s3_client_test") + require.NoError(t, err, "Unexpected error creating NewTerragruntOptionsForTest: %v", err) + + testCases := []struct { + name string + config map[string]interface{} + expected bool + }{ + { + "path-style-true", + map[string]interface{}{"use_path_style": true}, + true, + }, + { + "path-style-false", + map[string]interface{}{"use_path_style": false}, + false, + }, + { + "path-style-non-existent", + map[string]interface{}{}, + false, + }, + } + + for _, testCase := range testCases { + // The following is necessary to make sure testCase's values don't + // get updated due to concurrency within the scope of t.Run(..) below + testCase := testCase + + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + s3ConfigExtended, err := remote.ParseExtendedS3Config(testCase.config) + require.NoError(t, err, "Unexpected error parsing config for test: %v", err) + + s3Client, err := remote.CreateS3Client(s3ConfigExtended.GetAwsSessionConfig(), terragruntOptions) + require.NoError(t, err, "Unexpected error creating client for test: %v", err) + + actual := aws.BoolValue(s3Client.Config.S3UsePathStyle) assert.Equal(t, testCase.expected, actual) }) } @@ -302,7 +350,7 @@ func TestAwsGetAwsSessionConfig(t *testing.T) { }{ { "all-values", - map[string]interface{}{"region": "foo", "endpoint": "bar", "profile": "baz", "role_arn": "arn::it", "shared_credentials_file": "my-file", "force_path_style": true}, + map[string]interface{}{"region": "foo", "endpoint": "bar", "profile": "baz", "role_arn": "arn::it", "shared_credentials_file": "my-file", "use_path_style": true}, }, { "no-values", @@ -310,7 +358,7 @@ func TestAwsGetAwsSessionConfig(t *testing.T) { }, { "extra-values", - map[string]interface{}{"something": "unexpected", "region": "foo", "endpoint": "bar", "dynamodb_endpoint": "foobar", "profile": "baz", "role_arn": "arn::it", "shared_credentials_file": "my-file", "force_path_style": false}, + map[string]interface{}{"something": "unexpected", "region": "foo", "endpoint": "bar", "dynamodb_endpoint": "foobar", "profile": "baz", "role_arn": "arn::it", "shared_credentials_file": "my-file", "use_path_style": false}, }, } @@ -332,7 +380,7 @@ func TestAwsGetAwsSessionConfig(t *testing.T) { Profile: s3ConfigExtended.RemoteStateConfigS3.Profile, RoleArn: s3ConfigExtended.RemoteStateConfigS3.RoleArn, CredsFilename: s3ConfigExtended.RemoteStateConfigS3.CredsFilename, - S3ForcePathStyle: s3ConfigExtended.RemoteStateConfigS3.S3ForcePathStyle, + S3UsePathStyle: s3ConfigExtended.RemoteStateConfigS3.S3UsePathStyle, DisableComputeChecksums: s3ConfigExtended.DisableAWSClientChecksums, } diff --git a/remote/remote_state_test.go b/remote/remote_state_test.go index 8860ac5f33..9a348a5ac3 100644 --- a/remote/remote_state_test.go +++ b/remote/remote_state_test.go @@ -42,13 +42,13 @@ func TestToTerraformInitArgs(t *testing.T) { "skip_bucket_versioning": true, "shared_credentials_file": "my-file", - "force_path_style": true, + "use_path_style": true, }, } args := remoteState.ToTerraformInitArgs() // must not contain s3_bucket_tags or dynamodb_table_tags or accesslogging_bucket_tags or skip_bucket_versioning - assertTerraformInitArgsEqual(t, args, "-backend-config=encrypt=true -backend-config=bucket=my-bucket -backend-config=key=terraform.tfstate -backend-config=region=us-east-1 -backend-config=force_path_style=true -backend-config=shared_credentials_file=my-file") + assertTerraformInitArgsEqual(t, args, "-backend-config=encrypt=true -backend-config=bucket=my-bucket -backend-config=key=terraform.tfstate -backend-config=region=us-east-1 -backend-config=use_path_style=true -backend-config=shared_credentials_file=my-file") } func TestToTerraformInitArgsForGCS(t *testing.T) {