From c633b24824ce141417ea37437e5de2e3fbb1035b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Bia=C5=82o=C5=84?= Date: Thu, 26 Oct 2023 11:14:50 +0200 Subject: [PATCH] Backend/S3: Add support for `use_path_style` (#787) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin Białoń --- CHANGELOG.md | 1 + internal/backend/remote-state/s3/backend.go | 29 ++++++++++++- .../backend/remote-state/s3/backend_test.go | 41 +++++++++++++++++++ .../docs/language/settings/backends/s3.mdx | 3 +- 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e24370ce1a..652a1d4765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ S3 BACKEND: * Adds support for `ec2_metadata_service_endpoint` and `ec2_metadata_service_endpoint_mode` arguments to enable overriding the EC2 metadata service (IMDS) endpoint. ([#693](https://github.com/opentofu/opentofu/issues/693)) * Adds support for the `retry_mode` attribute. ([#698](https://github.com/opentofu/opentofu/issues/698)) * Adds support for the `http_proxy`, `insecure`, `use_dualstack_endpoint`, and `use_fips_endpoint` attributes. ([#694](https://github.com/opentofu/opentofu/issues/694)) +* Adds support for the `use_path_style` argument and deprecates the `force_path_style` argument. ([#783](https://github.com/opentofu/opentofu/issues/783)) ## Previous Releases diff --git a/internal/backend/remote-state/s3/backend.go b/internal/backend/remote-state/s3/backend.go index 752de7d54e..0bd80f9c62 100644 --- a/internal/backend/remote-state/s3/backend.go +++ b/internal/backend/remote-state/s3/backend.go @@ -223,7 +223,13 @@ func (b *Backend) ConfigSchema(context.Context) *configschema.Block { "force_path_style": { Type: cty.Bool, Optional: true, - Description: "Force s3 to use path style api.", + Description: "Force s3 to use path style api. Use `use_path_style` instead.", + Deprecated: true, + }, + "use_path_style": { + Type: cty.Bool, + Optional: true, + Description: "Enable path-style S3 URLs.", }, "retry_mode": { Type: cty.String, @@ -490,6 +496,24 @@ func (b *Backend) PrepareConfig(ctx context.Context, obj cty.Value) (cty.Value, attrPath)) } + if val := obj.GetAttr("force_path_style"); !val.IsNull() { + attrPath := cty.GetAttrPath("force_path_style") + detail := fmt.Sprintf( + `Parameter "%s" is deprecated. Use "%s" instead.`, + pathString(attrPath), + pathString(cty.GetAttrPath("use_path_style"))) + + diags = diags.Append(attributeWarningDiag( + "Deprecated Parameter", + detail, + attrPath)) + } + + validateAttributesConflict( + cty.GetAttrPath("force_path_style"), + cty.GetAttrPath("use_path_style"), + )(obj, cty.Path{}, &diags) + var assumeRoleDeprecatedFields = map[string]string{ "role_arn": "assume_role.role_arn", "session_name": "assume_role.session_name", @@ -769,6 +793,9 @@ func getS3Config(obj cty.Value) func(options *s3.Options) { if v, ok := boolAttrOk(obj, "force_path_style"); ok { options.UsePathStyle = v } + if v, ok := boolAttrOk(obj, "use_path_style"); ok { + options.UsePathStyle = v + } } } diff --git a/internal/backend/remote-state/s3/backend_test.go b/internal/backend/remote-state/s3/backend_test.go index dc8def70e5..032afca56e 100644 --- a/internal/backend/remote-state/s3/backend_test.go +++ b/internal/backend/remote-state/s3/backend_test.go @@ -766,6 +766,47 @@ func TestBackendConfig_PrepareConfigValidation(t *testing.T) { } } +func TestBackendConfig_PrepareConfigValidationWarnings(t *testing.T) { + cases := map[string]struct { + config cty.Value + expectedWarn string + }{ + "deprecated force path style": { + config: cty.ObjectVal(map[string]cty.Value{ + "bucket": cty.StringVal("test"), + "key": cty.StringVal("test"), + "region": cty.StringVal("us-west-2"), + "force_path_style": cty.BoolVal(false), + }), + expectedWarn: `Deprecated Parameter: Parameter "force_path_style" is deprecated. Use "use_path_style" instead.`, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + oldEnv := servicemocks.StashEnv() + defer servicemocks.PopEnv(oldEnv) + + b := New() + + ctx := context.Background() + + _, diags := b.PrepareConfig(ctx, populateSchema(t, b.ConfigSchema(ctx), tc.config)) + if tc.expectedWarn != "" { + if err := diags.ErrWithWarnings(); err != nil { + if !strings.Contains(err.Error(), tc.expectedWarn) { + t.Fatalf("unexpected validation result: %v", err) + } + } else { + t.Fatal("expected a warning, got none") + } + } else if err := diags.ErrWithWarnings(); err != nil { + t.Fatalf("expected no warnings, got %s", err) + } + }) + } +} + func TestBackendConfig_PrepareConfigWithEnvVars(t *testing.T) { cases := map[string]struct { config cty.Value diff --git a/website/docs/language/settings/backends/s3.mdx b/website/docs/language/settings/backends/s3.mdx index 5a8e3b9c37..30f063c946 100644 --- a/website/docs/language/settings/backends/s3.mdx +++ b/website/docs/language/settings/backends/s3.mdx @@ -315,7 +315,8 @@ The following configuration is optional: * `acl` - (Optional) [Canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl) to be applied to the state file. * `encrypt` - (Optional) Enable [server side encryption](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingServerSideEncryption.html) of the state file. * `endpoint` - (Optional) Custom endpoint for the AWS S3 API. This can also be sourced from the `AWS_S3_ENDPOINT` environment variable. -* `force_path_style` - (Optional) Enable path-style S3 URLs (`https:///` instead of `https://.`). +* `force_path_style` - (Optional) **Deprecated** Enable path-style S3 URLs (`https:///` instead of `https://.`). Use `use_path_style` instead. +* `use_path_style` - (Optional) Enable path-style S3 URLs (`https:///` instead of `https://.`). * `kms_key_id` - (Optional) Amazon Resource Name (ARN) of a Key Management Service (KMS) Key to use for encrypting the state. Note that if this value is specified, OpenTofu will need `kms:Encrypt`, `kms:Decrypt` and `kms:GenerateDataKey` permissions on this KMS key. * `sse_customer_key` - (Optional) The key to use for encrypting state with [Server-Side Encryption with Customer-Provided Keys (SSE-C)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerSideEncryptionCustomerKeys.html). This is the base64-encoded value of the key, which must decode to 256 bits. This can also be sourced from the `AWS_SSE_CUSTOMER_KEY` environment variable, which is recommended due to the sensitivity of the value. Setting it inside an OpenTofu file will cause it to be persisted to disk in `terraform.tfstate`. * `workspace_key_prefix` - (Optional) Prefix applied to the state path inside the bucket. This is only relevant when using a non-default workspace. Defaults to `env:`.