Terraform AWS Provider Version 4 Upgrade Guide
Version 4.0.0 of the AWS provider for Terraform is a major release and includes some changes that you will need to consider when upgrading. We intend this guide to help with that process and focus only on changes from version 3.X to version 4.0.0. See the Version 3 Upgrade Guide for information about upgrading from 1.X to version 3.0.0.
We previously marked most of the changes we outline in this guide as deprecated in the Terraform plan/apply output throughout previous provider releases. You can find these changes, including deprecation notices, in the Terraform AWS Provider CHANGELOG.
\~> NOTE: Versions 4.0.0 through v4.8.0 of the AWS Provider introduce significant breaking changes to the awsS3Bucket
resource. See S3 Bucket Refactor for more details. We recommend upgrading to v4.9.0 or later of the AWS Provider instead, where only non-breaking changes and deprecation notices are introduced to the awsS3Bucket
. See Changes to S3 Bucket Drift Detection for additional considerations when upgrading to v4.9.0 or later.
\~> NOTE: Version 4.0.0 of the AWS Provider introduces changes to the precedence of some authentication and configuration parameters. These changes bring the provider in line with the AWS CLI and SDKs. See Changes to Authentication for more details.
\~> NOTE: Version 4.0.0 of the AWS Provider will be the last major version to support EC2-Classic resources as AWS plans to fully retire EC2-Classic Networking. See the AWS News Blog for additional details.
\~> NOTE: Version 4.0.0 and 4.x.x versions of the AWS Provider will be the last versions compatible with Terraform 0.12-0.15.
Upgrade topics:
- Provider Version Configuration
- Changes to Authentication
- New Provider Arguments
- Changes to S3 Bucket Drift Detection (Applicable to v4.9.0 and later of the AWS Provider)
- S3 Bucket Refactor (Only applicable to v4.0.0 through v4.8.0 of the AWS Provider)
accelerationStatus
Argumentacl
ArgumentcorsRule
Argumentgrant
ArgumentlifecycleRule
Argumentlogging
ArgumentobjectLockConfiguration
rule
Argumentpolicy
ArgumentreplicationConfiguration
ArgumentrequestPayer
ArgumentserverSideEncryptionConfiguration
Argumentversioning
Argumentwebsite
,websiteDomain
, andwebsiteEndpoint
Arguments- Full Resource Lifecycle of Default Resources
- Resource: aws_default_subnet
- Resource: aws_default_vpc
- Plural Data Source Behavior
- Empty Strings Not Valid For Certain Resources
- Resource: aws_cloudwatch_event_target (Empty String)
- Resource: aws_customer_gateway
- Resource: aws_default_network_acl
- Resource: aws_default_route_table
- Resource: aws_default_vpc (Empty String)
- Resource: aws_efs_mount_target
- Resource: aws_elasticsearch_domain
- Resource: aws_instance
- Resource: aws_network_acl
- Resource: aws_route
- Resource: aws_route_table
- Resource: aws_vpc
- Resource: aws_vpc_ipv6_cidr_block_association
- Data Source: aws_cloudwatch_log_group
- Data Source: aws_subnet_ids
- Data Source: aws_s3_bucket_object
- Data Source: aws_s3_bucket_objects
- Resource: aws_batch_compute_environment
- Resource: aws_cloudwatch_event_target
- Resource: aws_elasticache_cluster
- Resource: aws_elasticache_global_replication_group
- Resource: aws_fsx_ontap_storage_virtual_machine
- Resource: aws_lb_target_group
- Resource: aws_s3_bucket_object
- Resource: aws_spot_instance_request
Additional Topics:
Provider Version Configuration
-> Before upgrading to version 4.0.0, upgrade to the most recent 3.X version of the provider and ensure that your environment successfully runs terraformPlan
. You should not see changes you don't expect or deprecation notices.
Use version constraints when configuring Terraform providers. If you are following that recommendation, update the version constraints in your Terraform configuration and run terraformInitUpgrade
to download the new version.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.provider.AwsProvider(this, "aws", {});
Update to the latest 4.X version:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.provider.AwsProvider(this, "aws", {});
Changes to Authentication
The authentication configuration for the AWS Provider has changed in this version to match the behavior of other AWS products, including the AWS SDK and AWS CLI. This will cause authentication failures in AWS provider configurations where you set a non-empty profile
in the provider
configuration but the profile does not correspond to an AWS profile with valid credentials.
Precedence for authentication settings is as follows:
provider
configuration- Environment variables
- Shared credentials and configuration files (e.g.,
~/Aws/credentials
and~/Aws/config
)
In previous versions of the provider, you could explicitly set profile
in the provider
, and if the profile did not correspond to valid credentials, the provider would use credentials from environment variables. Starting in v4.0, the Terraform AWS provider enforces the precedence shown above, similarly to how the AWS SDK and AWS CLI behave.
In other words, when you explicitly set profile
in provider
, the AWS provider will not use environment variables per the precedence shown above. Before v4.0, if profile
was configured in the provider
configuration but did not correspond to an AWS profile or valid credentials, the provider would attempt to use environment variables. This is no longer the case. An explicitly set profile that does not have valid credentials will cause an authentication error.
For example, with the following, the environment variables will not be used:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.provider.AwsProvider(this, "aws", {
profile: "customprofile",
region: "us-west-2",
});
New Provider Arguments
Version 4.x adds these new provider
arguments:
assumeRoleDuration
- Assume role duration as a string, e.g.,"1H"
or"1H30S"
. Terraform AWS Provider v4.0.0 deprecatesassumeRoleDurationSeconds
and a future version will remove it.customCaBundle
- File containing custom root and intermediate certificates. Can also be configured using theawsCaBundle
environment variable. (SettingcaBundle
in the shared config file is not supported.)ec2MetadataServiceEndpoint
- Address of the EC2 metadata service (IMDS) endpoint to use. Can also be set with theawsEc2MetadataServiceEndpoint
environment variable.ec2MetadataServiceEndpointMode
- Mode to use in communicating with the metadata service. Valid values areiPv4
andiPv6
. Can also be set with theawsEc2MetadataServiceEndpointMode
environment variable.s3UsePathStyle
- Replacess3ForcePathStyle
, which has been deprecated in Terraform AWS Provider v4.0.0 and support will be removed in a future version.sharedConfigFiles
- List of paths to AWS shared config files. If not set, the default is[~/Aws/config]
. A single value can also be set with theawsConfigFile
environment variable.sharedCredentialsFiles
- List of paths to the shared credentials file. If not set, the default is[~/Aws/credentials]
. A single value can also be set with theawsSharedCredentialsFile
environment variable. ReplacessharedCredentialsFile
, which has been deprecated in Terraform AWS Provider v4.0.0 and support will be removed in a future version.stsRegion
- Region where AWS STS operations will take place. For example,usEast1
andusWest2
.useDualstackEndpoint
- Force the provider to resolve endpoints with DualStack capability. Can also be set with theawsUseDualstackEndpoint
environment variable or in a shared config file (useDualstackEndpoint
).useFipsEndpoint
- Force the provider to resolve endpoints with FIPS capability. Can also be set with theawsUseFipsEndpoint
environment variable or in a shared config file (useFipsEndpoint
).
\~> NOTE: Using the awsMetadataUrl
environment variable has been deprecated in Terraform AWS Provider v4.0.0 and support will be removed in a future version. Change any scripts or environments using awsMetadataUrl
to instead use awsEc2MetadataServiceEndpoint
.
For example, in previous versions, to use FIPS endpoints, you would need to provide all the FIPS endpoints that you wanted to use in the endpoints
configuration block:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.provider.AwsProvider(this, "aws", {
endpoints: [
{
ec2: "https://ec2-fips.us-west-2.amazonaws.com",
s3: "https://s3-fips.us-west-2.amazonaws.com",
sts: "https://sts-fips.us-west-2.amazonaws.com",
},
],
});
In v4.0.0, you can still set endpoints in the same way. However, you can instead use the useFipsEndpoint
argument to have the provider automatically resolve FIPS endpoints for all supported services:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.provider.AwsProvider(this, "aws", {
useFipsEndpoint: true,
});
Note that the provider can only resolve FIPS endpoints where AWS provides FIPS support. Support depends on the service and may include usEast1
, usEast2
, usWest1
, usWest2
, usGovEast1
, usGovWest1
, and caCentral1
. For more information, see Federal Information Processing Standard (FIPS) 140-2.
Changes to S3 Bucket Drift Detection
\~> NOTE: This only applies to v4.9.0 and later of the AWS Provider.
\~> NOTE: If you are migrating from v3.75.x of the AWS Provider and you have already adopted the standalone S3 bucket resources (e.g. awsS3BucketLifecycleConfiguration
), a lifecycle
configuration block to ignore changes to the internal parameters of the source awsS3Bucket
resources will no longer be necessary and can be removed upon upgrade.
\~> NOTE: In the next major version, v5.0, the parameters listed below will be removed entirely from the awsS3Bucket
resource. For this reason, a deprecation notice is printed in the Terraform CLI for each of the parameters when used in a configuration.
To remediate the breaking changes introduced to the awsS3Bucket
resource in v4.0.0 of the AWS Provider, v4.9.0 and later retain the same configuration parameters of the awsS3Bucket
resource as in v3.x and functionality of the awsS3Bucket
resource only differs from v3.x in that Terraform will only perform drift detection for each of the following parameters if a configuration value is provided:
accelerationStatus
acl
corsRule
grant
lifecycleRule
logging
objectLockConfiguration
policy
replicationConfiguration
requestPayer
serverSideEncryptionConfiguration
versioning
website
Thus, if one of these parameters was once configured and then is entirely removed from an awsS3Bucket
resource configuration, Terraform will not pick up on these changes on a subsequent terraformPlan
or terraformApply
.
For example, given the following configuration with a single corsRule
:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
corsRule: [
{
allowedHeaders: ["*"],
allowedMethods: ["PUT", "POST"],
allowedOrigins: ["https://s3-website-test.hashicorp.com"],
exposeHeaders: ["ETag"],
maxAgeSeconds: 3000,
},
],
});
When updated to the following configuration without a corsRule
:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
Terraform CLI with v4.9.0 of the AWS Provider will report back:
aws_s3_bucket.example: Refreshing state... [id=yournamehere]
...
No changes. Your infrastructure matches the configuration.
With that said, to manage changes to these parameters in the awsS3Bucket
resource, practitioners should configure each parameter's respective standalone resource and perform updates directly on those new configurations. The parameters are mapped to the standalone resources as follows:
awsS3Bucket Parameter | Standalone Resource |
---|---|
accelerationStatus | awsS3BucketAccelerateConfiguration |
acl | awsS3BucketAcl |
corsRule | awsS3BucketCorsConfiguration |
grant | awsS3BucketAcl |
lifecycleRule | awsS3BucketLifecycleConfiguration |
logging | awsS3BucketLogging |
objectLockConfiguration | awsS3BucketObjectLockConfiguration |
policy | awsS3BucketPolicy |
replicationConfiguration | awsS3BucketReplicationConfiguration |
requestPayer | awsS3BucketRequestPaymentConfiguration |
serverSideEncryptionConfiguration | awsS3BucketServerSideEncryptionConfiguration |
versioning | awsS3BucketVersioning |
website | awsS3BucketWebsiteConfiguration |
Going back to the earlier example, given the following configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
corsRule: [
{
allowedHeaders: ["*"],
allowedMethods: ["PUT", "POST"],
allowedOrigins: ["https://s3-website-test.hashicorp.com"],
exposeHeaders: ["ETag"],
maxAgeSeconds: 3000,
},
],
});
Practitioners can upgrade to v4.9.0 and then introduce the standalone awsS3BucketCorsConfiguration
resource, e.g.
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketCorsConfigurationExample =
new aws.s3BucketCorsConfiguration.S3BucketCorsConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
corsRule: [
{
allowedHeaders: ["*"],
allowedMethods: ["PUT", "POST"],
allowedOrigins: ["https://s3-website-test.hashicorp.com"],
exposeHeaders: ["ETag"],
maxAgeSeconds: 3000,
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketCorsConfigurationExample.overrideLogicalId("example");
Depending on the tools available to you, the above configuration can either be directly applied with Terraform or the standalone resource can be imported into Terraform state. Please refer to each standalone resource's Import documentation for the proper syntax.
Once the standalone resources are managed by Terraform, updates and removal can be performed as needed.
The following sections depict standalone resource adoption per individual parameter. Standalone resource adoption is not required to upgrade but is recommended to ensure drift is detected by Terraform. The examples below are by no means exhaustive. The aim is to provide important concepts when migrating to a standalone resource whose parameters may not entirely align with the corresponding parameter in the awsS3Bucket
resource.
Migrating to awsS3BucketAccelerateConfiguration
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
accelerationStatus: "Enabled",
bucket: "yournamehere",
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketAccelerateConfigurationExample =
new aws.s3BucketAccelerateConfiguration.S3BucketAccelerateConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
status: "Enabled",
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketAccelerateConfigurationExample.overrideLogicalId("example");
Migrating to awsS3BucketAcl
With acl
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
acl: "private",
bucket: "yournamehere",
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketAclExample = new aws.s3BucketAcl.S3BucketAcl(
this,
"example_1",
{
acl: "private",
bucket: awsS3BucketExample.id,
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketAclExample.overrideLogicalId("example");
With grant
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
grant: [
{
id: "${data.aws_canonical_user_id.current_user.id}",
permissions: ["FULL_CONTROL"],
type: "CanonicalUser",
},
{
permissions: ["READ_ACP", "WRITE"],
type: "Group",
uri: "http://acs.amazonaws.com/groups/s3/LogDelivery",
},
],
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketAclExample = new aws.s3BucketAcl.S3BucketAcl(
this,
"example_1",
{
accessControlPolicy: {
grant: [
{
grantee: {
id: "${data.aws_canonical_user_id.current_user.id}",
type: "CanonicalUser",
},
permission: "FULL_CONTROL",
},
{
grantee: {
type: "Group",
uri: "http://acs.amazonaws.com/groups/s3/LogDelivery",
},
permission: "READ_ACP",
},
{
grantee: {
type: "Group",
uri: "http://acs.amazonaws.com/groups/s3/LogDelivery",
},
permission: "WRITE",
},
],
owner: {
id: "${data.aws_canonical_user_id.current_user.id}",
},
},
bucket: awsS3BucketExample.id,
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketAclExample.overrideLogicalId("example");
Migrating to awsS3BucketCorsConfiguration
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
corsRule: [
{
allowedHeaders: ["*"],
allowedMethods: ["PUT", "POST"],
allowedOrigins: ["https://s3-website-test.hashicorp.com"],
exposeHeaders: ["ETag"],
maxAgeSeconds: 3000,
},
],
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketCorsConfigurationExample =
new aws.s3BucketCorsConfiguration.S3BucketCorsConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
corsRule: [
{
allowedHeaders: ["*"],
allowedMethods: ["PUT", "POST"],
allowedOrigins: ["https://s3-website-test.hashicorp.com"],
exposeHeaders: ["ETag"],
maxAgeSeconds: 3000,
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketCorsConfigurationExample.overrideLogicalId("example");
Migrating to awsS3BucketLifecycleConfiguration
\~> Note: In version 3X
of the provider, the lifecycleRuleId
argument was optional, while in version 4X
, the awsS3BucketLifecycleConfigurationRuleId
argument required. Use the AWS CLI s3api get-bucket-lifecycle-configuration to get the source bucket's lifecycle configuration to determine the ID.
For Lifecycle Rules with no prefix
previously configured
\~> Note: When configuring the ruleFilter
configuration block in the new awsS3BucketLifecycleConfiguration
resource, use the AWS CLI s3api get-bucket-lifecycle-configuration to get the source bucket's lifecycle configuration and determine if the filter
is configured as "filter" : {}
or "filter" : { "prefix": "" }
. If AWS returns the former, configure ruleFilter
as filter {}
. Otherwise, neither a ruleFilter
nor rulePrefix
parameter should be configured as shown here:
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
lifecycleRule: [
{
enabled: true,
id: "Keep previous version 30 days, then in Glacier another 60",
noncurrentVersionExpiration: {
days: 90,
},
noncurrentVersionTransition: [
{
days: 30,
storageClass: "GLACIER",
},
],
},
{
abortIncompleteMultipartUploadDays: 7,
enabled: true,
id: "Delete old incomplete multi-part uploads",
},
],
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLifecycleConfigurationExample =
new aws.s3BucketLifecycleConfiguration.S3BucketLifecycleConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
id: "Keep previous version 30 days, then in Glacier another 60",
noncurrentVersionExpiration: {
noncurrentDays: 90,
},
noncurrentVersionTransition: [
{
noncurrentDays: 30,
storageClass: "GLACIER",
},
],
status: "Enabled",
},
{
abortIncompleteMultipartUpload: {
daysAfterInitiation: 7,
},
id: "Delete old incomplete multi-part uploads",
status: "Enabled",
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLifecycleConfigurationExample.overrideLogicalId("example");
For Lifecycle Rules with prefix
previously configured as an empty string
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
lifecycleRule: [
{
enabled: true,
id: "log-expiration",
prefix: "",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 180,
storageClass: "GLACIER",
},
],
},
],
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLifecycleConfigurationExample =
new aws.s3BucketLifecycleConfiguration.S3BucketLifecycleConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
id: "log-expiration",
status: "Enabled",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 180,
storageClass: "GLACIER",
},
],
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLifecycleConfigurationExample.overrideLogicalId("example");
For Lifecycle Rules with prefix
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
lifecycleRule: [
{
enabled: true,
id: "log-expiration",
prefix: "foobar",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 180,
storageClass: "GLACIER",
},
],
},
],
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLifecycleConfigurationExample =
new aws.s3BucketLifecycleConfiguration.S3BucketLifecycleConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
filter: {
prefix: "foobar",
},
id: "log-expiration",
status: "Enabled",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 180,
storageClass: "GLACIER",
},
],
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLifecycleConfigurationExample.overrideLogicalId("example");
For Lifecycle Rules with prefix
and tags
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
lifecycleRule: [
{
enabled: true,
expiration: {
days: 90,
},
id: "log",
prefix: "log/",
tags: {
autoclean: "true",
rule: "log",
},
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 60,
storageClass: "GLACIER",
},
],
},
{
enabled: true,
expiration: {
date: "2022-12-31",
},
id: "tmp",
prefix: "tmp/",
},
],
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLifecycleConfigurationExample =
new aws.s3BucketLifecycleConfiguration.S3BucketLifecycleConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
expiration: {
days: 90,
},
filter: {
and: {
prefix: "log/",
tags: {
autoclean: "true",
rule: "log",
},
},
},
id: "log",
status: "Enabled",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 60,
storageClass: "GLACIER",
},
],
},
{
expiration: {
date: "2022-12-31T00:00:00Z",
},
filter: {
prefix: "tmp/",
},
id: "tmp",
status: "Enabled",
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLifecycleConfigurationExample.overrideLogicalId("example");
Migrating to awsS3BucketLogging
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketLogBucket = new aws.s3Bucket.S3Bucket(this, "log_bucket", {
bucket: "example-log-bucket",
});
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
logging: {
targetBucket: awsS3BucketLogBucket.id,
targetPrefix: "log/",
},
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLogBucket = new aws.s3Bucket.S3Bucket(this, "log_bucket", {
bucket: "example-log-bucket",
});
const awsS3BucketLoggingExample = new aws.s3BucketLogging.S3BucketLoggingA(
this,
"example_2",
{
bucket: awsS3BucketExample.id,
targetBucket: awsS3BucketLogBucket.id,
targetPrefix: "log/",
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLoggingExample.overrideLogicalId("example");
Migrating to awsS3BucketObjectLockConfiguration
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
objectLockConfiguration: {
objectLockEnabled: "Enabled",
rule: {
defaultRetention: {
days: 3,
mode: "COMPLIANCE",
},
},
},
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
objectLockEnabled: true,
});
const awsS3BucketObjectLockConfigurationExample =
new aws.s3BucketObjectLockConfiguration.S3BucketObjectLockConfigurationA(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: {
defaultRetention: {
days: 3,
mode: "COMPLIANCE",
},
},
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketObjectLockConfigurationExample.overrideLogicalId("example");
Migrating to awsS3BucketPolicy
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
policy:
'{\n "Id": "Policy1446577137248",\n "Statement": [\n {\n "Action": "s3:PutObject",\n "Effect": "Allow",\n "Principal": {\n "AWS": "${data.aws_elb_service_account.current.arn}"\n },\n "Resource": "arn:${data.aws_partition.current.partition}:s3:::yournamehere/*",\n "Sid": "Stmt1446575236270"\n }\n ],\n "Version": "2012-10-17"\n}\n',
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketPolicyExample = new aws.s3BucketPolicy.S3BucketPolicy(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
policy: `{
"Id": "Policy1446577137248",
"Statement": [
{
"Action": "s3:PutObject",
"Effect": "Allow",
"Principal": {
"AWS": "\${data.aws_elb_service_account.current.arn}"
},
"Resource": "\${${awsS3BucketExample.arn}}/*",
"Sid": "Stmt1446575236270"
}
],
"Version": "2012-10-17"
}
`,
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketPolicyExample.overrideLogicalId("example");
Migrating to awsS3BucketReplicationConfiguration
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
provider: "${aws.central}",
replicationConfiguration: {
role: "${aws_iam_role.replication.arn}",
rules: [
{
destination: {
bucket: "${aws_s3_bucket.destination.arn}",
metrics: {
minutes: 15,
status: "Enabled",
},
replicationTime: {
minutes: 15,
status: "Enabled",
},
storageClass: "STANDARD",
},
filter: {
tags: {},
},
id: "foobar",
status: "Enabled",
},
],
},
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
provider: "${aws.central}",
});
const awsS3BucketReplicationConfigurationExample =
new aws.s3BucketReplicationConfiguration.S3BucketReplicationConfigurationA(
this,
"example_1",
{
bucket: "${aws_s3_bucket.source.id}",
role: "${aws_iam_role.replication.arn}",
rule: [
{
deleteMarkerReplication: {
status: "Enabled",
},
destination: {
bucket: "${aws_s3_bucket.destination.arn}",
metrics: {
eventThreshold: {
minutes: 15,
},
status: "Enabled",
},
replicationTime: {
status: "Enabled",
time: {
minutes: 15,
},
},
storageClass: "STANDARD",
},
filter: {},
id: "foobar",
status: "Enabled",
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketReplicationConfigurationExample.overrideLogicalId("example");
Migrating to awsS3BucketRequestPaymentConfiguration
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
requestPayer: "Requester",
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketRequestPaymentConfigurationExample =
new aws.s3BucketRequestPaymentConfiguration.S3BucketRequestPaymentConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
payer: "Requester",
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketRequestPaymentConfigurationExample.overrideLogicalId("example");
Migrating to awsS3BucketServerSideEncryptionConfiguration
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
serverSideEncryptionConfiguration: {
rule: {
applyServerSideEncryptionByDefault: {
kmsMasterKeyId: "${aws_kms_key.mykey.arn}",
sseAlgorithm: "aws:kms",
},
},
},
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketServerSideEncryptionConfigurationExample =
new aws.s3BucketServerSideEncryptionConfiguration.S3BucketServerSideEncryptionConfigurationA(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
applyServerSideEncryptionByDefault: {
kmsMasterKeyId: "${aws_kms_key.mykey.arn}",
sseAlgorithm: "aws:kms",
},
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketServerSideEncryptionConfigurationExample.overrideLogicalId(
"example"
);
Migrating to awsS3BucketVersioning
\~> NOTE: As awsS3BucketVersioning
is a separate resource, any S3 objects for which versioning is important (e.g., a truststore for mutual TLS authentication) must implicitly or explicitly depend on the awsS3BucketVersioning
resource. Otherwise, the S3 objects may be created before versioning has been set. See below for an example. Also note that AWS recommends waiting 15 minutes after enabling versioning on a bucket before putting or deleting objects in/from the bucket.
Buckets With Versioning Enabled
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
versioning: {
enabled: true,
},
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketVersioningExample =
new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", {
bucket: awsS3BucketExample.id,
versioningConfiguration: {
status: "Enabled",
},
});
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketVersioningExample.overrideLogicalId("example");
Buckets With Versioning Disabled or Suspended
Depending on the version of the Terraform AWS Provider you are migrating from, the interpretation of versioningEnabled =False
in your awsS3Bucket
resource will differ and thus the migration to the awsS3BucketVersioning
resource will also differ as follows.
If you are migrating from the Terraform AWS Provider v3700
or later:
- For new S3 buckets,
enabled =False
is synonymous todisabled
. - For existing S3 buckets,
enabled =False
is synonymous tosuspended
.
If you are migrating from an earlier version of the Terraform AWS Provider:
- For both new and existing S3 buckets,
enabled =False
is synonymous tosuspended
.
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
versioning: {
enabled: false,
},
});
Update the configuration to one of the following:
-
If migrating from Terraform AWS Provider
v3700
or later and bucket versioning was never enabled:/*Provider bindings are generated by running cdktf get. See https://cdk.tf/provider-generation for more details.*/ import * as aws from "./.gen/providers/aws"; const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", { bucket: "yournamehere", }); const awsS3BucketVersioningExample = new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", { bucket: awsS3BucketExample.id, versioningConfiguration: { status: "Disabled", }, }); /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/ awsS3BucketVersioningExample.overrideLogicalId("example");
-
If migrating from Terraform AWS Provider
v3700
or later and bucket versioning was enabled at one point:/*Provider bindings are generated by running cdktf get. See https://cdk.tf/provider-generation for more details.*/ import * as aws from "./.gen/providers/aws"; const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", { bucket: "yournamehere", }); const awsS3BucketVersioningExample = new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", { bucket: awsS3BucketExample.id, versioningConfiguration: { status: "Suspended", }, }); /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/ awsS3BucketVersioningExample.overrideLogicalId("example");
-
If migrating from an earlier version of Terraform AWS Provider:
/*Provider bindings are generated by running cdktf get. See https://cdk.tf/provider-generation for more details.*/ import * as aws from "./.gen/providers/aws"; const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", { bucket: "yournamehere", }); const awsS3BucketVersioningExample = new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", { bucket: awsS3BucketExample.id, versioningConfiguration: { status: "Suspended", }, }); /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/ awsS3BucketVersioningExample.overrideLogicalId("example");
Ensure Objects Depend on Versioning
When you create an object whose versionId
you need and an awsS3BucketVersioning
resource in the same configuration, you are more likely to have success by ensuring the s3Object
depends either implicitly (see below) or explicitly (i.e., using dependsOn = [awsS3BucketVersioningExample]
) on the awsS3BucketVersioning
resource.
\~> NOTE: For critical and/or production S3 objects, do not create a bucket, enable versioning, and create an object in the bucket within the same configuration. Doing so will not allow the AWS-recommended 15 minutes between enabling versioning and writing to the bucket.
This example shows the awsS3ObjectExample
depending implicitly on the versioning resource through the reference to awsS3BucketVersioningExampleBucket
to define bucket
:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yotto",
});
const awsS3BucketVersioningExample =
new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", {
bucket: awsS3BucketExample.id,
versioningConfiguration: {
status: "Enabled",
},
});
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketVersioningExample.overrideLogicalId("example");
const awsS3ObjectExample = new aws.s3Object.S3Object(this, "example_2", {
bucket: awsS3BucketVersioningExample.bucket,
key: "droeloe",
source: "example.txt",
});
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3ObjectExample.overrideLogicalId("example");
Migrating to awsS3BucketWebsiteConfiguration
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
website: {
errorDocument: "error.html",
indexDocument: "index.html",
},
});
Update the configuration to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketWebsiteConfigurationExample =
new aws.s3BucketWebsiteConfiguration.S3BucketWebsiteConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
errorDocument: {
key: "error.html",
},
indexDocument: {
suffix: "index.html",
},
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketWebsiteConfigurationExample.overrideLogicalId("example");
Given this previous configuration that uses the awsS3Bucket
parameter websiteDomain
with awsRoute53Record
:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsRoute53ZoneMain = new aws.route53Zone.Route53Zone(this, "main", {
name: "domain.test",
});
const awsS3BucketWebsite = new aws.s3Bucket.S3Bucket(this, "website", {
website: {
errorDocument: "error.html",
indexDocument: "index.html",
},
});
new aws.route53Record.Route53Record(this, "alias", {
alias: {
evaluateTargetHealth: true,
name: awsS3BucketWebsite.websiteDomain,
zoneId: awsS3BucketWebsite.hostedZoneId,
},
name: "www",
type: "A",
zoneId: awsRoute53ZoneMain.zoneId,
});
Update the configuration to use the awsS3BucketWebsiteConfiguration
resource and its websiteDomain
parameter:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsRoute53ZoneMain = new aws.route53Zone.Route53Zone(this, "main", {
name: "domain.test",
});
const awsS3BucketWebsite = new aws.s3Bucket.S3Bucket(this, "website", {});
const awsS3BucketWebsiteConfigurationExample =
new aws.s3BucketWebsiteConfiguration.S3BucketWebsiteConfiguration(
this,
"example",
{
bucket: awsS3BucketWebsite.id,
indexDocument: {
suffix: "index.html",
},
}
);
new aws.route53Record.Route53Record(this, "alias", {
alias: {
evaluateTargetHealth: true,
name: awsS3BucketWebsiteConfigurationExample.websiteDomain,
zoneId: awsS3BucketWebsite.hostedZoneId,
},
name: "www",
type: "A",
zoneId: awsRoute53ZoneMain.zoneId,
});
S3 Bucket Refactor
\~> NOTE: This only applies to v4.0.0 through v4.8.0 of the AWS Provider, which introduce significant breaking changes to the awsS3Bucket
resource. We recommend upgrading to v4.9.0 of the AWS Provider instead. See the section above, Changes to S3 Bucket Drift Detection, for additional upgrade considerations.
To help distribute the management of S3 bucket settings via independent resources, various arguments and attributes in the awsS3Bucket
resource have become read-only.
Configurations dependent on these arguments should be updated to use the corresponding awsS3Bucket_*
resource in order to prevent Terraform from reporting “unconfigurable attribute” errors for read-only arguments. Once updated, it is recommended to import new awsS3Bucket_*
resources into Terraform state.
In the event practitioners do not anticipate future modifications to the S3 bucket settings associated with these read-only arguments or drift detection is not needed, these read-only arguments should be removed from awsS3Bucket
resource configurations in order to prevent Terraform from reporting “unconfigurable attribute” errors; the states of these arguments will be preserved but are subject to change with modifications made outside Terraform.
\~> NOTE: Each of the new awsS3Bucket_*
resources relies on S3 API calls that utilize a put
action in order to modify the target S3 bucket. These calls follow standard HTTP methods for REST APIs, and therefore should handle situations where the target configuration already exists. While it is not strictly necessary to import new awsS3Bucket_*
resources where the updated configuration matches the configuration used in previous versions of the AWS provider, skipping this step will lead to a diff in the first plan after a configuration change indicating that any new awsS3Bucket_*
resources will be created, making it more difficult to determine whether the appropriate actions will be taken.
accelerationStatus
Argument
Switch your Terraform configuration to the awsS3BucketAccelerateConfiguration
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
accelerationStatus: "Enabled",
bucket: "yournamehere",
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "acceleration_status": its value will be decided automatically based on the result of applying this configuration.
Since accelerationStatus
is now read only, update your configuration to use the awsS3BucketAccelerateConfiguration
resource and remove accelerationStatus
in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketAccelerateConfigurationExample =
new aws.s3BucketAccelerateConfiguration.S3BucketAccelerateConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
status: "Enabled",
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketAccelerateConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_accelerate_configuration.example yournamehere
aws_s3_bucket_accelerate_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_accelerate_configuration.example: Import prepared!
Prepared aws_s3_bucket_accelerate_configuration for import
aws_s3_bucket_accelerate_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
acl
Argument
Switch your Terraform configuration to the awsS3BucketAcl
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
acl: "private",
bucket: "yournamehere",
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "acl": its value will be decided automatically based on the result of applying this configuration.
Since acl
is now read only, update your configuration to use the awsS3BucketAcl
resource and remove the acl
argument in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketAclExample = new aws.s3BucketAcl.S3BucketAcl(
this,
"example_1",
{
acl: "private",
bucket: awsS3BucketExample.id,
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketAclExample.overrideLogicalId("example");
\~> NOTE: When importing into awsS3BucketAcl
, make sure you use the S3 bucket name (e.g., yournamehere
in the example above) as part of the ID, and not the Terraform bucket configuration name (e.g., example
in the example above).
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_acl.example yournamehere,private
aws_s3_bucket_acl.example: Importing from ID "yournamehere,private"...
aws_s3_bucket_acl.example: Import prepared!
Prepared aws_s3_bucket_acl for import
aws_s3_bucket_acl.example: Refreshing state... [id=yournamehere,private]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
corsRule
Argument
Switch your Terraform configuration to the awsS3BucketCorsConfiguration
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
corsRule: [
{
allowedHeaders: ["*"],
allowedMethods: ["PUT", "POST"],
allowedOrigins: ["https://s3-website-test.hashicorp.com"],
exposeHeaders: ["ETag"],
maxAgeSeconds: 3000,
},
],
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "cors_rule": its value will be decided automatically based on the result of applying this configuration.
Since corsRule
is now read only, update your configuration to use the awsS3BucketCorsConfiguration
resource and remove corsRule
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketCorsConfigurationExample =
new aws.s3BucketCorsConfiguration.S3BucketCorsConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
corsRule: [
{
allowedHeaders: ["*"],
allowedMethods: ["PUT", "POST"],
allowedOrigins: ["https://s3-website-test.hashicorp.com"],
exposeHeaders: ["ETag"],
maxAgeSeconds: 3000,
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketCorsConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_cors_configuration.example yournamehere
aws_s3_bucket_cors_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_cors_configuration.example: Import prepared!
Prepared aws_s3_bucket_cors_configuration for import
aws_s3_bucket_cors_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
grant
Argument
Switch your Terraform configuration to the awsS3BucketAcl
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
grant: [
{
id: "${data.aws_canonical_user_id.current_user.id}",
permissions: ["FULL_CONTROL"],
type: "CanonicalUser",
},
{
permissions: ["READ_ACP", "WRITE"],
type: "Group",
uri: "http://acs.amazonaws.com/groups/s3/LogDelivery",
},
],
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "grant": its value will be decided automatically based on the result of applying this configuration.
Since grant
is now read only, update your configuration to use the awsS3BucketAcl
resource and remove grant
in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketAclExample = new aws.s3BucketAcl.S3BucketAcl(
this,
"example_1",
{
accessControlPolicy: {
grant: [
{
grantee: {
id: "${data.aws_canonical_user_id.current_user.id}",
type: "CanonicalUser",
},
permission: "FULL_CONTROL",
},
{
grantee: {
type: "Group",
uri: "http://acs.amazonaws.com/groups/s3/LogDelivery",
},
permission: "READ_ACP",
},
{
grantee: {
type: "Group",
uri: "http://acs.amazonaws.com/groups/s3/LogDelivery",
},
permission: "WRITE",
},
],
owner: {
id: "${data.aws_canonical_user_id.current_user.id}",
},
},
bucket: awsS3BucketExample.id,
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketAclExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_acl.example yournamehere
aws_s3_bucket_acl.example: Importing from ID "yournamehere"...
aws_s3_bucket_acl.example: Import prepared!
Prepared aws_s3_bucket_acl for import
aws_s3_bucket_acl.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
lifecycleRule
Argument
Switch your Terraform configuration to the awsS3BucketLifecycleConfiguration
resource instead.
For Lifecycle Rules with no prefix
previously configured
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
lifecycleRule: [
{
enabled: true,
id: "Keep previous version 30 days, then in Glacier another 60",
noncurrentVersionExpiration: {
days: 90,
},
noncurrentVersionTransition: [
{
days: 30,
storageClass: "GLACIER",
},
],
},
{
abortIncompleteMultipartUploadDays: 7,
enabled: true,
id: "Delete old incomplete multi-part uploads",
},
],
});
You will receive the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "lifecycle_rule": its value will be decided automatically based on the result of applying this configuration.
Since the lifecycleRule
argument changed to read-only, update the configuration to use the awsS3BucketLifecycleConfiguration
resource and remove lifecycleRule
and its nested arguments in the awsS3Bucket
resource.
\~> Note: When configuring the ruleFilter
configuration block in the new awsS3BucketLifecycleConfiguration
resource, use the AWS CLI s3api get-bucket-lifecycle-configuration to get the source bucket's lifecycle configuration and determine if the filter
is configured as "filter" : {}
or "filter" : { "prefix": "" }
. If AWS returns the former, configure ruleFilter
as filter {}
. Otherwise, neither a ruleFilter
nor rulePrefix
parameter should be configured as shown here:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLifecycleConfigurationExample =
new aws.s3BucketLifecycleConfiguration.S3BucketLifecycleConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
id: "Keep previous version 30 days, then in Glacier another 60",
noncurrentVersionExpiration: {
noncurrentDays: 90,
},
noncurrentVersionTransition: [
{
noncurrentDays: 30,
storageClass: "GLACIER",
},
],
status: "Enabled",
},
{
abortIncompleteMultipartUpload: {
daysAfterInitiation: 7,
},
id: "Delete old incomplete multi-part uploads",
status: "Enabled",
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLifecycleConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_lifecycle_configuration.example yournamehere
aws_s3_bucket_lifecycle_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_lifecycle_configuration.example: Import prepared!
Prepared aws_s3_bucket_lifecycle_configuration for import
aws_s3_bucket_lifecycle_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
For Lifecycle Rules with prefix
previously configured as an empty string
For example, given this configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
lifecycleRule: [
{
enabled: true,
id: "log-expiration",
prefix: "",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 180,
storageClass: "GLACIER",
},
],
},
],
});
You will receive the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "lifecycle_rule": its value will be decided automatically based on the result of applying this configuration.
Since the lifecycleRule
argument changed to read-only, update the configuration to use the awsS3BucketLifecycleConfiguration
resource and remove lifecycleRule
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLifecycleConfigurationExample =
new aws.s3BucketLifecycleConfiguration.S3BucketLifecycleConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
id: "log-expiration",
status: "Enabled",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 180,
storageClass: "GLACIER",
},
],
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLifecycleConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_lifecycle_configuration.example yournamehere
aws_s3_bucket_lifecycle_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_lifecycle_configuration.example: Import prepared!
Prepared aws_s3_bucket_lifecycle_configuration for import
aws_s3_bucket_lifecycle_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
For Lifecycle Rules with prefix
For example, given this configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
lifecycleRule: [
{
enabled: true,
id: "log-expiration",
prefix: "foobar",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 180,
storageClass: "GLACIER",
},
],
},
],
});
You will receive the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "lifecycle_rule": its value will be decided automatically based on the result of applying this configuration.
Since the lifecycleRule
argument changed to read-only, update the configuration to use the awsS3BucketLifecycleConfiguration
resource and remove lifecycleRule
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLifecycleConfigurationExample =
new aws.s3BucketLifecycleConfiguration.S3BucketLifecycleConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
filter: {
prefix: "foobar",
},
id: "log-expiration",
status: "Enabled",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 180,
storageClass: "GLACIER",
},
],
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLifecycleConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_lifecycle_configuration.example yournamehere
aws_s3_bucket_lifecycle_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_lifecycle_configuration.example: Import prepared!
Prepared aws_s3_bucket_lifecycle_configuration for import
aws_s3_bucket_lifecycle_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
For Lifecycle Rules with prefix
and tags
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
lifecycleRule: [
{
enabled: true,
expiration: {
days: 90,
},
id: "log",
prefix: "log/",
tags: {
autoclean: "true",
rule: "log",
},
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 60,
storageClass: "GLACIER",
},
],
},
{
enabled: true,
expiration: {
date: "2022-12-31",
},
id: "tmp",
prefix: "tmp/",
},
],
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "lifecycle_rule": its value will be decided automatically based on the result of applying this configuration.
Since lifecycleRule
is now read only, update your configuration to use the awsS3BucketLifecycleConfiguration
resource and remove lifecycleRule
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLifecycleConfigurationExample =
new aws.s3BucketLifecycleConfiguration.S3BucketLifecycleConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
expiration: {
days: 90,
},
filter: {
and: {
prefix: "log/",
tags: {
autoclean: "true",
rule: "log",
},
},
},
id: "log",
status: "Enabled",
transition: [
{
days: 30,
storageClass: "STANDARD_IA",
},
{
days: 60,
storageClass: "GLACIER",
},
],
},
{
expiration: {
date: "2022-12-31T00:00:00Z",
},
filter: {
prefix: "tmp/",
},
id: "tmp",
status: "Enabled",
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLifecycleConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_lifecycle_configuration.example yournamehere
aws_s3_bucket_lifecycle_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_lifecycle_configuration.example: Import prepared!
Prepared aws_s3_bucket_lifecycle_configuration for import
aws_s3_bucket_lifecycle_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
logging
Argument
Switch your Terraform configuration to the awsS3BucketLogging
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketLogBucket = new aws.s3Bucket.S3Bucket(this, "log_bucket", {
bucket: "example-log-bucket",
});
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
logging: {
targetBucket: awsS3BucketLogBucket.id,
targetPrefix: "log/",
},
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "logging": its value will be decided automatically based on the result of applying this configuration.
Since logging
is now read only, update your configuration to use the awsS3BucketLogging
resource and remove logging
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketLogBucket = new aws.s3Bucket.S3Bucket(this, "log_bucket", {
bucket: "example-log-bucket",
});
const awsS3BucketLoggingExample = new aws.s3BucketLogging.S3BucketLoggingA(
this,
"example_2",
{
bucket: awsS3BucketExample.id,
targetBucket: awsS3BucketLogBucket.id,
targetPrefix: "log/",
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketLoggingExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_logging.example yournamehere
aws_s3_bucket_logging.example: Importing from ID "yournamehere"...
aws_s3_bucket_logging.example: Import prepared!
Prepared aws_s3_bucket_logging for import
aws_s3_bucket_logging.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
objectLockConfiguration
rule
Argument
Switch your Terraform configuration to the awsS3BucketObjectLockConfiguration
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
objectLockConfiguration: {
objectLockEnabled: "Enabled",
rule: {
defaultRetention: {
days: 3,
mode: "COMPLIANCE",
},
},
},
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "object_lock_configuration.0.rule": its value will be decided automatically based on the result of applying this configuration.
Since the rule
argument of the objectLockConfiguration
configuration block changed to read-only, update your configuration to use the awsS3BucketObjectLockConfiguration
resource and remove rule
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
objectLockEnabled: true,
});
const awsS3BucketObjectLockConfigurationExample =
new aws.s3BucketObjectLockConfiguration.S3BucketObjectLockConfigurationA(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: {
defaultRetention: {
days: 3,
mode: "COMPLIANCE",
},
},
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketObjectLockConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_object_lock_configuration.example yournamehere
aws_s3_bucket_object_lock_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_object_lock_configuration.example: Import prepared!
Prepared aws_s3_bucket_object_lock_configuration for import
aws_s3_bucket_object_lock_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
policy
Argument
Switch your Terraform configuration to the awsS3BucketPolicy
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
policy:
'{\n "Id": "Policy1446577137248",\n "Statement": [\n {\n "Action": "s3:PutObject",\n "Effect": "Allow",\n "Principal": {\n "AWS": "${data.aws_elb_service_account.current.arn}"\n },\n "Resource": "arn:${data.aws_partition.current.partition}:s3:::yournamehere/*",\n "Sid": "Stmt1446575236270"\n }\n ],\n "Version": "2012-10-17"\n}\n',
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "policy": its value will be decided automatically based on the result of applying this configuration.
Since policy
is now read only, update your configuration to use the awsS3BucketPolicy
resource and remove policy
in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketPolicyExample = new aws.s3BucketPolicy.S3BucketPolicy(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
policy: `{
"Id": "Policy1446577137248",
"Statement": [
{
"Action": "s3:PutObject",
"Effect": "Allow",
"Principal": {
"AWS": "\${data.aws_elb_service_account.current.arn}"
},
"Resource": "\${${awsS3BucketExample.arn}}/*",
"Sid": "Stmt1446575236270"
}
],
"Version": "2012-10-17"
}
`,
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketPolicyExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_policy.example yournamehere
aws_s3_bucket_policy.example: Importing from ID "yournamehere"...
aws_s3_bucket_policy.example: Import prepared!
Prepared aws_s3_bucket_policy for import
aws_s3_bucket_policy.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
replicationConfiguration
Argument
Switch your Terraform configuration to the awsS3BucketReplicationConfiguration
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
provider: "${aws.central}",
replicationConfiguration: {
role: "${aws_iam_role.replication.arn}",
rules: [
{
destination: {
bucket: "${aws_s3_bucket.destination.arn}",
metrics: {
minutes: 15,
status: "Enabled",
},
replicationTime: {
minutes: 15,
status: "Enabled",
},
storageClass: "STANDARD",
},
filter: {
tags: {},
},
id: "foobar",
status: "Enabled",
},
],
},
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "replication_configuration": its value will be decided automatically based on the result of applying this configuration.
Since replicationConfiguration
is now read only, update your configuration to use the awsS3BucketReplicationConfiguration
resource and remove replicationConfiguration
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
provider: "${aws.central}",
});
const awsS3BucketReplicationConfigurationExample =
new aws.s3BucketReplicationConfiguration.S3BucketReplicationConfigurationA(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
role: "${aws_iam_role.replication.arn}",
rule: [
{
deleteMarkerReplication: {
status: "Enabled",
},
destination: {
bucket: "${aws_s3_bucket.destination.arn}",
metrics: {
eventThreshold: {
minutes: 15,
},
status: "Enabled",
},
replicationTime: {
status: "Enabled",
time: {
minutes: 15,
},
},
storageClass: "STANDARD",
},
filter: {},
id: "foobar",
status: "Enabled",
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketReplicationConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_replication_configuration.example yournamehere
aws_s3_bucket_replication_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_replication_configuration.example: Import prepared!
Prepared aws_s3_bucket_replication_configuration for import
aws_s3_bucket_replication_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
requestPayer
Argument
Switch your Terraform configuration to the awsS3BucketRequestPaymentConfiguration
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
requestPayer: "Requester",
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "request_payer": its value will be decided automatically based on the result of applying this configuration.
Since requestPayer
is now read only, update your configuration to use the awsS3BucketRequestPaymentConfiguration
resource and remove requestPayer
in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketRequestPaymentConfigurationExample =
new aws.s3BucketRequestPaymentConfiguration.S3BucketRequestPaymentConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
payer: "Requester",
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketRequestPaymentConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_request_payment_configuration.example yournamehere
aws_s3_bucket_request_payment_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_request_payment_configuration.example: Import prepared!
Prepared aws_s3_bucket_request_payment_configuration for import
aws_s3_bucket_request_payment_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
serverSideEncryptionConfiguration
Argument
Switch your Terraform configuration to the awsS3BucketServerSideEncryptionConfiguration
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
serverSideEncryptionConfiguration: {
rule: {
applyServerSideEncryptionByDefault: {
kmsMasterKeyId: "${aws_kms_key.mykey.arn}",
sseAlgorithm: "aws:kms",
},
},
},
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "server_side_encryption_configuration": its value will be decided automatically based on the result of applying this configuration.
Since serverSideEncryptionConfiguration
is now read only, update your configuration to use the awsS3BucketServerSideEncryptionConfiguration
resource and remove serverSideEncryptionConfiguration
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketServerSideEncryptionConfigurationExample =
new aws.s3BucketServerSideEncryptionConfiguration.S3BucketServerSideEncryptionConfigurationA(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
rule: [
{
applyServerSideEncryptionByDefault: {
kmsMasterKeyId: "${aws_kms_key.mykey.arn}",
sseAlgorithm: "aws:kms",
},
},
],
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketServerSideEncryptionConfigurationExample.overrideLogicalId(
"example"
);
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_server_side_encryption_configuration.example yournamehere
aws_s3_bucket_server_side_encryption_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_server_side_encryption_configuration.example: Import prepared!
Prepared aws_s3_bucket_server_side_encryption_configuration for import
aws_s3_bucket_server_side_encryption_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
versioning
Argument
Switch your Terraform configuration to the awsS3BucketVersioning
resource instead.
\~> NOTE: As awsS3BucketVersioning
is a separate resource, any S3 objects for which versioning is important (e.g., a truststore for mutual TLS authentication) must implicitly or explicitly depend on the awsS3BucketVersioning
resource. Otherwise, the S3 objects may be created before versioning has been set. See below for an example. Also note that AWS recommends waiting 15 minutes after enabling versioning on a bucket before putting or deleting objects in/from the bucket.
Buckets With Versioning Enabled
Given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
versioning: {
enabled: true,
},
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "versioning": its value will be decided automatically based on the result of applying this configuration.
Since versioning
is now read only, update your configuration to use the awsS3BucketVersioning
resource and remove versioning
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketVersioningExample =
new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", {
bucket: awsS3BucketExample.id,
versioningConfiguration: {
status: "Enabled",
},
});
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketVersioningExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_versioning.example yournamehere
aws_s3_bucket_versioning.example: Importing from ID "yournamehere"...
aws_s3_bucket_versioning.example: Import prepared!
Prepared aws_s3_bucket_versioning for import
aws_s3_bucket_versioning.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
Buckets With Versioning Disabled or Suspended
Depending on the version of the Terraform AWS Provider you are migrating from, the interpretation of versioningEnabled =False
in your awsS3Bucket
resource will differ and thus the migration to the awsS3BucketVersioning
resource will also differ as follows.
If you are migrating from the Terraform AWS Provider v3700
or later:
- For new S3 buckets,
enabled =False
is synonymous todisabled
. - For existing S3 buckets,
enabled =False
is synonymous tosuspended
.
If you are migrating from an earlier version of the Terraform AWS Provider:
- For both new and existing S3 buckets,
enabled =False
is synonymous tosuspended
.
Given this previous configuration :
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
versioning: {
enabled: false,
},
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "versioning": its value will be decided automatically based on the result of applying this configuration.
Since versioning
is now read only, update your configuration to use the awsS3BucketVersioning
resource and remove versioning
and its nested arguments in the awsS3Bucket
resource.
-
If migrating from Terraform AWS Provider
v3700
or later and bucket versioning was never enabled:/*Provider bindings are generated by running cdktf get. See https://cdk.tf/provider-generation for more details.*/ import * as aws from "./.gen/providers/aws"; const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", { bucket: "yournamehere", }); const awsS3BucketVersioningExample = new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", { bucket: awsS3BucketExample.id, versioningConfiguration: { status: "Disabled", }, }); /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/ awsS3BucketVersioningExample.overrideLogicalId("example");
-
If migrating from Terraform AWS Provider
v3700
or later and bucket versioning was enabled at one point:/*Provider bindings are generated by running cdktf get. See https://cdk.tf/provider-generation for more details.*/ import * as aws from "./.gen/providers/aws"; const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", { bucket: "yournamehere", }); const awsS3BucketVersioningExample = new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", { bucket: awsS3BucketExample.id, versioningConfiguration: { status: "Suspended", }, }); /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/ awsS3BucketVersioningExample.overrideLogicalId("example");
-
If migrating from an earlier version of Terraform AWS Provider:
/*Provider bindings are generated by running cdktf get. See https://cdk.tf/provider-generation for more details.*/ import * as aws from "./.gen/providers/aws"; const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", { bucket: "yournamehere", }); const awsS3BucketVersioningExample = new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", { bucket: awsS3BucketExample.id, versioningConfiguration: { status: "Suspended", }, }); /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/ awsS3BucketVersioningExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_versioning.example yournamehere
aws_s3_bucket_versioning.example: Importing from ID "yournamehere"...
aws_s3_bucket_versioning.example: Import prepared!
Prepared aws_s3_bucket_versioning for import
aws_s3_bucket_versioning.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
Ensure Objects Depend on Versioning
When you create an object whose versionId
you need and an awsS3BucketVersioning
resource in the same configuration, you are more likely to have success by ensuring the s3Object
depends either implicitly (see below) or explicitly (i.e., using dependsOn = [awsS3BucketVersioningExample]
) on the awsS3BucketVersioning
resource.
\~> NOTE: For critical and/or production S3 objects, do not create a bucket, enable versioning, and create an object in the bucket within the same configuration. Doing so will not allow the AWS-recommended 15 minutes between enabling versioning and writing to the bucket.
This example shows the awsS3ObjectExample
depending implicitly on the versioning resource through the reference to awsS3BucketVersioningExampleBucket
to define bucket
:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yotto",
});
const awsS3BucketVersioningExample =
new aws.s3BucketVersioning.S3BucketVersioningA(this, "example_1", {
bucket: awsS3BucketExample.id,
versioningConfiguration: {
status: "Enabled",
},
});
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketVersioningExample.overrideLogicalId("example");
const awsS3ObjectExample = new aws.s3Object.S3Object(this, "example_2", {
bucket: awsS3BucketVersioningExample.bucket,
key: "droeloe",
source: "example.txt",
});
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3ObjectExample.overrideLogicalId("example");
website
, websiteDomain
, and websiteEndpoint
Arguments
Switch your Terraform configuration to the awsS3BucketWebsiteConfiguration
resource instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
website: {
errorDocument: "error.html",
indexDocument: "index.html",
},
});
You will get the following error after upgrading:
│ Error: Value for unconfigurable attribute
│
│ with aws_s3_bucket.example,
│ on main.tf line 1, in resource "aws_s3_bucket" "example":
│ 1: resource "aws_s3_bucket" "example" {
│
│ Can't configure a value for "website": its value will be decided automatically based on the result of applying this configuration.
Since website
is now read only, update your configuration to use the awsS3BucketWebsiteConfiguration
resource and remove website
and its nested arguments in the awsS3Bucket
resource:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsS3BucketExample = new aws.s3Bucket.S3Bucket(this, "example", {
bucket: "yournamehere",
});
const awsS3BucketWebsiteConfigurationExample =
new aws.s3BucketWebsiteConfiguration.S3BucketWebsiteConfiguration(
this,
"example_1",
{
bucket: awsS3BucketExample.id,
errorDocument: {
key: "error.html",
},
indexDocument: {
suffix: "index.html",
},
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsS3BucketWebsiteConfigurationExample.overrideLogicalId("example");
Run terraformImport
on each new resource, e.g.,
$ terraform import aws_s3_bucket_website_configuration.example yournamehere
aws_s3_bucket_website_configuration.example: Importing from ID "yournamehere"...
aws_s3_bucket_website_configuration.example: Import prepared!
Prepared aws_s3_bucket_website_configuration for import
aws_s3_bucket_website_configuration.example: Refreshing state... [id=yournamehere]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
For example, if you use the awsS3Bucket
attribute websiteDomain
with awsRoute53Record
, as shown below, you will need to update your configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsRoute53ZoneMain = new aws.route53Zone.Route53Zone(this, "main", {
name: "domain.test",
});
const awsS3BucketWebsite = new aws.s3Bucket.S3Bucket(this, "website", {
website: {
errorDocument: "error.html",
indexDocument: "index.html",
},
});
new aws.route53Record.Route53Record(this, "alias", {
alias: {
evaluateTargetHealth: true,
name: awsS3BucketWebsite.websiteDomain,
zoneId: awsS3BucketWebsite.hostedZoneId,
},
name: "www",
type: "A",
zoneId: awsRoute53ZoneMain.zoneId,
});
Instead, you will now use the awsS3BucketWebsiteConfiguration
resource and its websiteDomain
attribute:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsRoute53ZoneMain = new aws.route53Zone.Route53Zone(this, "main", {
name: "domain.test",
});
const awsS3BucketWebsite = new aws.s3Bucket.S3Bucket(this, "website", {});
const awsS3BucketWebsiteConfigurationExample =
new aws.s3BucketWebsiteConfiguration.S3BucketWebsiteConfiguration(
this,
"example",
{
bucket: awsS3BucketWebsite.id,
indexDocument: {
suffix: "index.html",
},
}
);
new aws.route53Record.Route53Record(this, "alias", {
alias: {
evaluateTargetHealth: true,
name: awsS3BucketWebsiteConfigurationExample.websiteDomain,
zoneId: awsS3BucketWebsite.hostedZoneId,
},
name: "www",
type: "A",
zoneId: awsRoute53ZoneMain.zoneId,
});
Full Resource Lifecycle of Default Resources
Default subnets and vpcs can now do full resource lifecycle operations such that resource creation and deletion are now supported.
Resource: aws_default_subnet
The awsDefaultSubnet
resource behaves differently from normal resources in that if a default subnet exists in the specified Availability Zone, Terraform does not create this resource, but instead "adopts" it into management. If no default subnet exists, Terraform creates a new default subnet. By default, terraformDestroy
does not delete the default subnet but does remove the resource from Terraform state. Set the forceDestroy
argument to true
to delete the default subnet.
For example, given this previous configuration with no existing default subnet:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.provider.AwsProvider(this, "aws", {
region: "eu-west-2",
});
new aws.defaultSubnet.DefaultSubnet(this, "default", {});
The following error was thrown on terraformApply
:
│ Error: Default subnet not found.
│
│ with aws_default_subnet.default,
│ on main.tf line 5, in resource "aws_default_subnet" "default":
│ 5: resource "aws_default_subnet" "default" {}
Now after upgrading, the above configuration will apply successfully.
To delete the default subnet, the above configuration should be updated as follows:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.defaultSubnet.DefaultSubnet(this, "default", {
forceDestroy: true,
});
Resource: aws_default_vpc
The awsDefaultVpc
resource behaves differently from normal resources in that if a default VPC exists, Terraform does not create this resource, but instead "adopts" it into management. If no default VPC exists, Terraform creates a new default VPC, which leads to the implicit creation of other resources. By default, terraformDestroy
does not delete the default VPC but does remove the resource from Terraform state. Set the forceDestroy
argument to true
to delete the default VPC.
For example, given this previous configuration with no existing default VPC:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.defaultVpc.DefaultVpc(this, "default", {});
The following error was thrown on terraformApply
:
│ Error: No default VPC found in this region.
│
│ with aws_default_vpc.default,
│ on main.tf line 5, in resource "aws_default_vpc" "default":
│ 5: resource "aws_default_vpc" "default" {}
Now after upgrading, the above configuration will apply successfully.
To delete the default VPC, the above configuration should be updated to:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.defaultVpc.DefaultVpc(this, "default", {
forceDestroy: true,
});
Plural Data Source Behavior
The following plural data sources are now consistent with Provider Design such that they no longer return an error if zero results are found.
- aws_cognito_user_pools
- aws_db_event_categories
- aws_ebs_volumes
- aws_ec2_coip_pools
- aws_ec2_local_gateway_route_tables
- aws_ec2_local_gateway_virtual_interface_groups
- aws_ec2_local_gateways
- aws_ec2_transit_gateway_route_tables
- aws_efs_access_points
- aws_emr_release_labels
- aws_inspector_rules_packages
- aws_ip_ranges
- aws_network_acls
- aws_route_tables
- aws_security_groups
- aws_ssoadmin_instances
- aws_vpcs
- aws_vpc_peering_connections
Empty Strings Not Valid For Certain Resources
First, this is a breaking change but should affect very few configurations.
Second, the motivation behind this change is that previously, you might set an argument to ""
to explicitly convey it is empty. However, with the introduction of null
in Terraform 0.12 and to prepare for continuing enhancements that distinguish between unset arguments and those that have a value, including an empty string (""
), we are moving away from this use of zero values. We ask practitioners to either use null
instead or remove the arguments that are set to ""
.
Resource: aws_cloudwatch_event_target (Empty String)
Previously, you could set ecsTarget0LaunchType
to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., launchType =Null
) or remove the empty-string configuration.
For example, this type of configuration is now not valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.cloudwatchEventTarget.CloudwatchEventTarget(this, "example", {
ecsTarget: {
launchType: "",
taskCount: 1,
taskDefinitionArn: "${aws_ecs_task_definition.task.arn}",
},
});
We fix this configuration by setting launchType
to null
:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.cloudwatchEventTarget.CloudwatchEventTarget(this, "example", {
ecsTarget: {
launchType: null,
taskCount: 1,
taskDefinitionArn: "${aws_ecs_task_definition.task.arn}",
},
});
Resource: aws_customer_gateway
Previously, you could set ipAddress
to ""
, which would result in an AWS error. However, the provider now also gives an error.
Resource: aws_default_network_acl
Previously, you could set egress.*CidrBlock
, egress.*Ipv6CidrBlock
, ingress.*CidrBlock
, or ingress.*Ipv6CidrBlock
to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., ipv6CidrBlock =Null
) or remove the empty-string configuration.
For example, this type of configuration is now not valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.defaultNetworkAcl.DefaultNetworkAcl(this, "example", {
egress: [
{
cidrBlock: "0.0.0.0/0",
ipv6CidrBlock: "",
},
],
});
To fix this configuration, we remove the empty-string configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.defaultNetworkAcl.DefaultNetworkAcl(this, "example", {
egress: [
{
cidrBlock: "0.0.0.0/0",
},
],
});
Resource: aws_default_route_table
Previously, you could set route.*CidrBlock
or route.*Ipv6CidrBlock
to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., ipv6CidrBlock =Null
) or remove the empty-string configuration.
For example, this type of configuration is now not valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.defaultRouteTable.DefaultRouteTable(this, "example", {
route: [
{
cidrBlock: '${local.ipv6 ? "" : local.destination}',
ipv6CidrBlock: '${local.ipv6 ? local.destination_ipv6 : ""}',
},
],
});
We fix this configuration by using null
instead of an empty string (""
):
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.defaultRouteTable.DefaultRouteTable(this, "example", {
route: [
{
cidrBlock: "${local.ipv6 ? null : local.destination}",
ipv6CidrBlock: "${local.ipv6 ? local.destination_ipv6 : null}",
},
],
});
Resource: aws_default_vpc (Empty String)
Previously, you could set ipv6CidrBlock
to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., ipv6CidrBlock =Null
) or remove the empty-string configuration.
Resource: aws_instance
Previously, you could set privateIp
to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., privateIp =Null
) or remove the empty-string configuration.
For example, this type of configuration is now not valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.instance.Instance(this, "example", {
instanceType: "t2.micro",
privateIp: "",
});
We fix this configuration by removing the empty-string configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.instance.Instance(this, "example", {
instanceType: "t2.micro",
});
Resource: aws_efs_mount_target
Previously, you could set ipAddress
to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., ipAddress =Null
) or remove the empty-string configuration.
For example, this type of configuration is now not valid: ipAddress = ""
.
Resource: aws_elasticsearch_domain
Previously, you could set ebsOptions0VolumeType
to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., volumeType =Null
) or remove the empty-string configuration.
For example, this type of configuration is now not valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.elasticsearchDomain.ElasticsearchDomain(this, "example", {
ebsOptions: {
ebsEnabled: true,
volumeSize: "${var.volume_size}",
volumeType: '${var.volume_size > 0 ? local.volume_type : ""}',
},
});
We fix this configuration by using null
instead of ""
:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.elasticsearchDomain.ElasticsearchDomain(this, "example", {
ebsOptions: {
ebsEnabled: true,
volumeSize: "${var.volume_size}",
volumeType: "${var.volume_size > 0 ? local.volume_type : null}",
},
});
Resource: aws_network_acl
Previously, egress.*CidrBlock
, egress.*Ipv6CidrBlock
, ingress.*CidrBlock
, and ingress.*Ipv6CidrBlock
could be set to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., ipv6CidrBlock =Null
) or remove the empty-string configuration.
For example, this type of configuration is now not valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.networkAcl.NetworkAcl(this, "example", {
egress: [
{
cidrBlock: "0.0.0.0/0",
ipv6CidrBlock: "",
},
],
});
We fix this configuration by removing the empty-string configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.networkAcl.NetworkAcl(this, "example", {
egress: [
{
cidrBlock: "0.0.0.0/0",
},
],
});
Resource: aws_route
Previously, destinationCidrBlock
and destinationIpv6CidrBlock
could be set to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., destinationIpv6CidrBlock =Null
) or remove the empty-string configuration.
In addition, now exactly one of destinationCidrBlock
, destinationIpv6CidrBlock
, and destinationPrefixListId
can be set.
For example, this type of configuration for awsRoute
is now not valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.route.Route(this, "example", {
destinationCidrBlock: '${local.ipv6 ? "" : local.destination}',
destinationIpv6CidrBlock: '${local.ipv6 ? local.destination_ipv6 : ""}',
gatewayId: "${aws_internet_gateway.example.id}",
routeTableId: "${aws_route_table.example.id}",
});
We fix this configuration by using null
instead of an empty-string (""
):
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.route.Route(this, "example", {
destinationCidrBlock: "${local.ipv6 ? null : local.destination}",
destinationIpv6CidrBlock: "${local.ipv6 ? local.destination_ipv6 : null}",
gatewayId: "${aws_internet_gateway.example.id}",
routeTableId: "${aws_route_table.example.id}",
});
Resource: aws_route_table
Previously, route.*CidrBlock
and route.*Ipv6CidrBlock
could be set to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., ipv6CidrBlock =Null
) or remove the empty-string configuration.
For example, this type of configuration is now not valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.routeTable.RouteTable(this, "example", {
route: [
{
cidrBlock: '${local.ipv6 ? "" : local.destination}',
ipv6CidrBlock: '${local.ipv6 ? local.destination_ipv6 : ""}',
},
],
});
We fix this configuration by usingd null
instead of an empty-string (""
):
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.routeTable.RouteTable(this, "example", {
route: [
{
cidrBlock: "${local.ipv6 ? null : local.destination}",
ipv6CidrBlock: "${local.ipv6 ? local.destination_ipv6 : null}",
},
],
});
Resource: aws_vpc
Previously, ipv6CidrBlock
could be set to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., ipv6CidrBlock =Null
) or remove the empty-string configuration.
For example, this type of configuration is now not valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.vpc.Vpc(this, "example", {
cidrBlock: "10.1.0.0/16",
ipv6CidrBlock: "",
});
We fix this configuration by removing ipv6CidrBlock
:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.vpc.Vpc(this, "example", {
cidrBlock: "10.1.0.0/16",
});
Resource: aws_vpc_ipv6_cidr_block_association
Previously, ipv6CidrBlock
could be set to ""
. However, the value ""
is no longer valid. Now, set the argument to null
(e.g., ipv6CidrBlock =Null
) or remove the empty-string configuration.
Data Source: aws_cloudwatch_log_group
Removal of arn Wildcard Suffix
Previously, the data source returned the ARN directly from the API, which included a :*
suffix to denote all CloudWatch Log Streams under the CloudWatch Log Group. Most other AWS resources that return ARNs and many other AWS services do not use the :*
suffix. The suffix is now automatically removed. For example, the data source previously returned an ARN such as arn:aws:logs:usEast1:123456789012:logGroup:/example:*
but will now return arn:aws:logs:usEast1:123456789012:logGroup:/example
.
Workarounds, such as using replace()
as shown below, should be removed:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const dataAwsCloudwatchLogGroupExample =
new aws.dataAwsCloudwatchLogGroup.DataAwsCloudwatchLogGroup(this, "example", {
name: "example",
});
const awsDatasyncTaskExample = new aws.datasyncTask.DatasyncTask(
this,
"example_1",
{
cloudwatchLogGroupArn: `\${replace(${dataAwsCloudwatchLogGroupExample.arn}, ":*", "")}`,
}
);
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsDatasyncTaskExample.overrideLogicalId("example");
Removing the :*
suffix is a breaking change for some configurations. Fix these configurations using string interpolations as demonstrated below. For example, this configuration is now broken:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.dataAwsIamPolicyDocument.DataAwsIamPolicyDocument(
this,
"ad-log-policy",
{
statement: [
{
actions: ["logs:CreateLogStream", "logs:PutLogEvents"],
effect: "Allow",
principals: [
{
identifiers: ["ds.amazonaws.com"],
type: "Service",
},
],
resources: ["${data.aws_cloudwatch_log_group.example.arn}"],
},
],
}
);
An updated configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.dataAwsIamPolicyDocument.DataAwsIamPolicyDocument(
this,
"ad-log-policy",
{
statement: [
{
actions: ["logs:CreateLogStream", "logs:PutLogEvents"],
effect: "Allow",
principals: [
{
identifiers: ["ds.amazonaws.com"],
type: "Service",
},
],
resources: ["${data.aws_cloudwatch_log_group.example.arn}:*"],
},
],
}
);
Data Source: aws_subnet_ids
The awsSubnetIds
data source has been deprecated and will be removed in a future version. Use the awsSubnets
data source instead.
For example, change a configuration such as
data "aws_subnet_ids" "example" {
vpc_id = var.vpc_id
}
data "aws_subnet" "example" {
for_each = data.aws_subnet_ids.example.ids
id = each.value
}
output "subnet_cidr_blocks" {
value = [for s in data.aws_subnet.example : s.cidr_block]
}
to
data "aws_subnets" "example" {
filter {
name = "vpc-id"
values = [var.vpc_id]
}
}
data "aws_subnet" "example" {
for_each = data.aws_subnets.example.ids
id = each.value
}
output "subnet_cidr_blocks" {
value = [for s in data.aws_subnet.example : s.cidr_block]
}
Data Source: aws_s3_bucket_object
Version 4.x deprecates the awsS3BucketObject
data source. Maintainers will remove it in a future version. Use awsS3Object
instead, where new features and fixes will be added.
Data Source: aws_s3_bucket_objects
Version 4.x deprecates the awsS3BucketObjects
data source. Maintainers will remove it in a future version. Use awsS3Objects
instead, where new features and fixes will be added.
Resource: aws_batch_compute_environment
You can no longer specify computeResources
when type
is unmanaged
.
Previously, you could apply this configuration and the provider would ignore any compute resources:
resource "aws_batch_compute_environment" "test" {
compute_environment_name = "test"
compute_resources {
instance_role = aws_iam_instance_profile.ecs_instance.arn
instance_type = [
"c4.large",
]
max_vcpus = 16
min_vcpus = 0
security_group_ids = [
aws_security_group.test.id
]
subnets = [
aws_subnet.test.id
]
type = "EC2"
}
service_role = aws_iam_role.batch_service.arn
type = "UNMANAGED"
}
Now, this configuration is invalid and will result in an error during plan.
To resolve this error, simply remove or comment out the computeResources
configuration block.
resource "aws_batch_compute_environment" "test" {
compute_environment_name = "test"
service_role = aws_iam_role.batch_service.arn
type = "UNMANAGED"
}
Resource: aws_cloudwatch_event_target
Removal of ecsTarget
launchType
default value
Previously, the provider assigned ecsTarget
launchType
the default value of ec2
if you did not configure a value. However, the provider no longer assigns a default value.
For example, previously you could workaround the default value by using an empty string (""
), as shown:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.cloudwatchEventTarget.CloudwatchEventTarget(this, "test", {
arn: "${aws_ecs_cluster.test.id}",
ecsTarget: {
launchType: "",
networkConfiguration: {
subnets: ["${aws_subnet.subnet.id}"],
},
taskCount: 1,
taskDefinitionArn: "${aws_ecs_task_definition.task.arn}",
},
roleArn: "${aws_iam_role.test.arn}",
rule: "${aws_cloudwatch_event_rule.test.id}",
});
This is no longer necessary. We fix the configuration by removing the empty string assignment:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.cloudwatchEventTarget.CloudwatchEventTarget(this, "test", {
arn: "${aws_ecs_cluster.test.id}",
ecsTarget: {
networkConfiguration: {
subnets: ["${aws_subnet.subnet.id}"],
},
taskCount: 1,
taskDefinitionArn: "${aws_ecs_task_definition.task.arn}",
},
roleArn: "${aws_iam_role.test.arn}",
rule: "${aws_cloudwatch_event_rule.test.id}",
});
Resource: aws_elasticache_cluster
Error raised if neither engine
nor replicationGroupId
is specified
Previously, when you did not specify either engine
or replicationGroupId
, Terraform would not prevent you from applying the invalid configuration. Now, this will produce an error similar to the one below:
Error: Invalid combination of arguments
with aws_elasticache_cluster.example,
on terraform_plugin_test.tf line 2, in resource "aws_elasticache_cluster" "example":
2: resource "aws_elasticache_cluster" "example" {
"replication_group_id": one of `engine,replication_group_id` must be
specified
Error: Invalid combination of arguments
with aws_elasticache_cluster.example,
on terraform_plugin_test.tf line 2, in resource "aws_elasticache_cluster" "example":
2: resource "aws_elasticache_cluster" "example" {
"engine": one of `engine,replication_group_id` must be specified
Update your configuration to supply one of engine
or replicationGroupId
.
Resource: aws_elasticache_global_replication_group
actual_engine_version Attribute removal
Switch your Terraform configuration from using actualEngineVersion
to use the engineVersionActual
attribute instead.
For example, given this previous configuration:
import * as cdktf from "cdktf";
new cdktf.TerraformOutput(
this,
"elasticache_global_replication_group_version_result",
{
value:
"${aws_elasticache_global_replication_group.example.actual_engine_version}",
}
);
An updated configuration:
import * as cdktf from "cdktf";
new cdktf.TerraformOutput(
this,
"elasticache_global_replication_group_version_result",
{
value:
"${aws_elasticache_global_replication_group.example.engine_version_actual}",
}
);
Resource: aws_fsx_ontap_storage_virtual_machine
We removed the misspelled argument activeDirectoryConfiguration0SelfManagedActiveDirectoryConfiguration0OrganizationalUnitDistinguidshedName
that we previously deprecated. Use activeDirectoryConfiguration0SelfManagedActiveDirectoryConfiguration0OrganizationalUnitDistinguishedName
now instead. Terraform will automatically migrate the state to activeDirectoryConfiguration0SelfManagedActiveDirectoryConfiguration0OrganizationalUnitDistinguishedName
during planning.
Resource: aws_lb_target_group
For protocol = "tcp"
, you can no longer set stickinessType
to lbCookie
even when enabled =False
. Instead, either change the protocol
to "http"
or "https"
, or change stickinessType
to "sourceIp"
.
For example, this configuration is no longer valid:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.lbTargetGroup.LbTargetGroup(this, "test", {
port: 25,
protocol: "TCP",
stickiness: {
enabled: false,
type: "lb_cookie",
},
vpcId: "${aws_vpc.test.id}",
});
To fix this, we change the stickinessType
to "sourceIp"
.
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.lbTargetGroup.LbTargetGroup(this, "test", {
port: 25,
protocol: "TCP",
stickiness: {
enabled: false,
type: "source_ip",
},
vpcId: "${aws_vpc.test.id}",
});
Resource: aws_s3_bucket_object
Version 4.x deprecates the awsS3BucketObject
and maintainers will remove it in a future version. Use awsS3Object
instead, where new features and fixes will be added.
When replacing awsS3BucketObject
with awsS3Object
in your configuration, on the next apply, Terraform will recreate the object. If you prefer to not have Terraform recreate the object, import the object using awsS3Object
.
For example, the following will import an S3 object into state, assuming the configuration exists, as awsS3ObjectExample
:
\~> CAUTION: We do not recommend modifying the state file manually. If you do, you can make it unusable. However, if you accept that risk, some community members have upgraded to the new resource by searching and replacing "type": "awsS3BucketObject",
with "type": "awsS3Object",
in the state file, and then running terraformApplyRefreshOnly
.
Resource: aws_spot_instance_request
instance_interruption_behaviour Argument removal
Switch your Terraform configuration from the instanceInterruptionBehaviour
attribute to the instanceInterruptionBehavior
attribute instead.
For example, given this previous configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.spotInstanceRequest.SpotInstanceRequest(this, "example", {
instance_interruption_behaviour: "hibernate",
});
An updated configuration:
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.spotInstanceRequest.SpotInstanceRequest(this, "example", {
instanceInterruptionBehavior: "hibernate",
});
EC2-Classic Resource and Data Source Support
While an upgrade to this major version will not directly impact EC2-Classic resources configured with Terraform, it is important to keep in the mind the following AWS Provider resources will eventually no longer be compatible with EC2-Classic as AWS completes their EC2-Classic networking retirement (expected around August 15, 2022).