diff --git a/.changelog/45535.txt b/.changelog/45535.txt new file mode 100644 index 000000000000..83bfdadc0b8a --- /dev/null +++ b/.changelog/45535.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_cloudfront_multitenant_distribution +``` \ No newline at end of file diff --git a/.changelog/45656.txt b/.changelog/45656.txt new file mode 100644 index 000000000000..75d6564d1ee7 --- /dev/null +++ b/.changelog/45656.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_ecs_capacity_provider: Add spot support for managed instance capacity provider +``` diff --git a/.ci/tools/go.mod b/.ci/tools/go.mod index ca344d235df8..fa9df50a2160 100644 --- a/.ci/tools/go.mod +++ b/.ci/tools/go.mod @@ -3,7 +3,7 @@ module github.com/hashicorp/terraform-provider-aws/tools go 1.24.11 require ( - github.com/YakDriver/copyplop v0.4.0 + github.com/YakDriver/copyplop v0.5.0 github.com/YakDriver/tfproviderdocs v0.23.3 github.com/client9/misspell v0.3.4 github.com/golangci/golangci-lint/v2 v2.7.2 diff --git a/.ci/tools/go.sum b/.ci/tools/go.sum index 1a06670009aa..9888fe76dc32 100644 --- a/.ci/tools/go.sum +++ b/.ci/tools/go.sum @@ -697,8 +697,8 @@ github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgz github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= -github.com/YakDriver/copyplop v0.4.0 h1:vAG4QdYdusw3apjR3zbF4WMUEPbhg+mfEo37VW0gk4I= -github.com/YakDriver/copyplop v0.4.0/go.mod h1:AVy2Cx2/QquETJ4KlEhfbUpxBO8KDXMqp1lgRvZgshk= +github.com/YakDriver/copyplop v0.5.0 h1:zMyD3u5Byq2p1ZglpYr8K+gnKBRDM7YK95N3y1xdRP0= +github.com/YakDriver/copyplop v0.5.0/go.mod h1:AVy2Cx2/QquETJ4KlEhfbUpxBO8KDXMqp1lgRvZgshk= github.com/YakDriver/tfproviderdocs v0.23.3 h1:3phUu5Wyml5lH0y5hAkxfqHmgPgG6P28rCzYp1zPaYc= github.com/YakDriver/tfproviderdocs v0.23.3/go.mod h1:AMFL4IE88Mf18DklXvcL4pJXbuFVsjuePyJ/7B4DmHw= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= diff --git a/CHANGELOG.md b/CHANGELOG.md index 804c0bd5ba60..8f259c982304 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 6.28.0 (Unreleased) +FEATURES: + +* **New Resource:** `aws_cloudfront_multitenant_distribution` ([#45535](https://github.com/hashicorp/terraform-provider-aws/issues/45535)) + ENHANCEMENTS: * data-source/aws_db_proxy: Add `endpoint_network_type` and `target_connection_network_type` attributes ([#45634](https://github.com/hashicorp/terraform-provider-aws/issues/45634)) diff --git a/go.mod b/go.mod index e3ed54d79b98..7a35b3673781 100644 --- a/go.mod +++ b/go.mod @@ -33,9 +33,9 @@ require ( github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.18.3 github.com/aws/aws-sdk-go-v2/service/appmesh v1.35.7 github.com/aws/aws-sdk-go-v2/service/apprunner v1.39.9 - github.com/aws/aws-sdk-go-v2/service/appstream v1.52.5 + github.com/aws/aws-sdk-go-v2/service/appstream v1.53.0 github.com/aws/aws-sdk-go-v2/service/appsync v1.53.0 - github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.18 + github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.3.0 github.com/aws/aws-sdk-go-v2/service/arczonalshift v1.22.18 github.com/aws/aws-sdk-go-v2/service/athena v1.56.4 github.com/aws/aws-sdk-go-v2/service/auditmanager v1.46.7 @@ -46,14 +46,14 @@ require ( github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.12.9 github.com/aws/aws-sdk-go-v2/service/bedrock v1.53.0 github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.52.2 - github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.15.2 + github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.16.0 github.com/aws/aws-sdk-go-v2/service/billing v1.9.4 github.com/aws/aws-sdk-go-v2/service/budgets v1.42.3 github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.16 github.com/aws/aws-sdk-go-v2/service/chime v1.41.7 github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.16 github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.28.8 - github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.38.2 + github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.39.0 github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.15 github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.29.8 github.com/aws/aws-sdk-go-v2/service/cloudformation v1.71.4 @@ -105,10 +105,10 @@ require ( github.com/aws/aws-sdk-go-v2/service/drs v1.36.8 github.com/aws/aws-sdk-go-v2/service/dsql v1.12.3 github.com/aws/aws-sdk-go-v2/service/dynamodb v1.53.5 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.277.0 - github.com/aws/aws-sdk-go-v2/service/ecr v1.54.4 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.278.0 + github.com/aws/aws-sdk-go-v2/service/ecr v1.55.0 github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.8 - github.com/aws/aws-sdk-go-v2/service/ecs v1.69.5 + github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0 github.com/aws/aws-sdk-go-v2/service/efs v1.41.9 github.com/aws/aws-sdk-go-v2/service/eks v1.76.3 github.com/aws/aws-sdk-go-v2/service/elasticache v1.51.8 @@ -144,7 +144,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/inspector2 v1.46.1 github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.26.9 github.com/aws/aws-sdk-go-v2/service/invoicing v1.9.3 - github.com/aws/aws-sdk-go-v2/service/iot v1.70.0 + github.com/aws/aws-sdk-go-v2/service/iot v1.71.0 github.com/aws/aws-sdk-go-v2/service/ivs v1.48.9 github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.15 github.com/aws/aws-sdk-go-v2/service/kafka v1.46.5 @@ -189,7 +189,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/oam v1.23.10 github.com/aws/aws-sdk-go-v2/service/observabilityadmin v1.9.1 github.com/aws/aws-sdk-go-v2/service/odb v1.7.0 - github.com/aws/aws-sdk-go-v2/service/opensearch v1.56.0 + github.com/aws/aws-sdk-go-v2/service/opensearch v1.57.0 github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.28.1 github.com/aws/aws-sdk-go-v2/service/organizations v1.50.0 github.com/aws/aws-sdk-go-v2/service/osis v1.21.9 @@ -242,7 +242,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.21 github.com/aws/aws-sdk-go-v2/service/servicequotas v1.34.0 github.com/aws/aws-sdk-go-v2/service/ses v1.34.17 - github.com/aws/aws-sdk-go-v2/service/sesv2 v1.58.0 + github.com/aws/aws-sdk-go-v2/service/sesv2 v1.59.0 github.com/aws/aws-sdk-go-v2/service/sfn v1.40.5 github.com/aws/aws-sdk-go-v2/service/shield v1.34.16 github.com/aws/aws-sdk-go-v2/service/signer v1.32.0 @@ -252,9 +252,9 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.31.9 github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.15 github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.16 - github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.15 + github.com/aws/aws-sdk-go-v2/service/ssmsap v1.26.0 github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 - github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.12 + github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.13 github.com/aws/aws-sdk-go-v2/service/storagegateway v1.43.9 github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 github.com/aws/aws-sdk-go-v2/service/swf v1.33.11 diff --git a/go.sum b/go.sum index 940a1e074b84..0b5846a9a2cd 100644 --- a/go.sum +++ b/go.sum @@ -77,12 +77,12 @@ github.com/aws/aws-sdk-go-v2/service/appmesh v1.35.7 h1:nW1jsdX6e1VT0vqthwJztdwg github.com/aws/aws-sdk-go-v2/service/appmesh v1.35.7/go.mod h1:9H7Oyy2M/EiRYzY4MfkrjPuIB2+LLLx1eCxTmQUyV70= github.com/aws/aws-sdk-go-v2/service/apprunner v1.39.9 h1:3MgcobMoBK3IqP2TbuySbdjc79EYCmN+ZRCKQD6d0GU= github.com/aws/aws-sdk-go-v2/service/apprunner v1.39.9/go.mod h1:n6b+O7QJ6E37dXZYPdLnC4S7Cc5HUYOQPZijLeDKIGY= -github.com/aws/aws-sdk-go-v2/service/appstream v1.52.5 h1:06hhJyKERzoGJ7wFPqoUUdEQ1PLygC8+mRoO7tcU4QA= -github.com/aws/aws-sdk-go-v2/service/appstream v1.52.5/go.mod h1:bBWE9r4oj7moGUvEyihhpcLcSAP4HXsb1cYFOqoXrrc= +github.com/aws/aws-sdk-go-v2/service/appstream v1.53.0 h1:ik7TXyRrtDpJiCOnuxFNGkEFL+qwvPiRJxqj3ytTet8= +github.com/aws/aws-sdk-go-v2/service/appstream v1.53.0/go.mod h1:bBWE9r4oj7moGUvEyihhpcLcSAP4HXsb1cYFOqoXrrc= github.com/aws/aws-sdk-go-v2/service/appsync v1.53.0 h1:8I7CLKciARX91L7cKj1horWon1/Z1eGG9E1ZvjW7HwA= github.com/aws/aws-sdk-go-v2/service/appsync v1.53.0/go.mod h1:iLJM8Rf5z8Td/Zvz5qv/XxP4h4E9aoBNXDUVoryy110= -github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.18 h1:phqqCBtQ7lVakKqqxijj8c91E2oq2Tt4Pz4x2EbNwgs= -github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.18/go.mod h1:vcL9EzuMufqrNk+Ns3vT7yWv9rm9n4RYnBzfNrInggE= +github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.3.0 h1:56LbI4Uo5r65xIkdde6TtlyBU2K06igoenqqBvc4rT4= +github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.3.0/go.mod h1:vcL9EzuMufqrNk+Ns3vT7yWv9rm9n4RYnBzfNrInggE= github.com/aws/aws-sdk-go-v2/service/arczonalshift v1.22.18 h1:Ds0ydJxnG4lvRCIm/IdzgrVf3dyHLAfCWjRffAr2Mwo= github.com/aws/aws-sdk-go-v2/service/arczonalshift v1.22.18/go.mod h1:oYmUhJIeABHyxIpxhZqJ+7jaCXeV+qxtTQ8FoVyMsRg= github.com/aws/aws-sdk-go-v2/service/athena v1.56.4 h1:kCHAYlcGKCKKDGMRUfnY6pI992vC3UdA3+oPdfDBSHE= @@ -103,8 +103,8 @@ github.com/aws/aws-sdk-go-v2/service/bedrock v1.53.0 h1:cmQBS5qaRe1yV7eL7shROYjB github.com/aws/aws-sdk-go-v2/service/bedrock v1.53.0/go.mod h1:LV2LELzMlToA6tauFUTYr0iy20Gp4TKz2vMQYaKq0Pw= github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.52.2 h1:jrOALh0fIx8kUfesQS4jMkXGPDQ2xKt5bbREgsoHcmw= github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.52.2/go.mod h1:hRzcNxU8BOG5ijgeMDLyw0sx4fBOxrjPDB/DnDK6X1M= -github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.15.2 h1:UduoRYiZpRrlXvd9YsRJ5F0BfpTWD71hEUs1u3JNQk4= -github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.15.2/go.mod h1:3zWDBnJEUh72XdC7iEqdCSwPwDuveVsKTmtThuGwC2s= +github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.16.0 h1:ENycjQ5LASzpc3+izF684aXHPndd+SHCf/D2fK8aro0= +github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.16.0/go.mod h1:3zWDBnJEUh72XdC7iEqdCSwPwDuveVsKTmtThuGwC2s= github.com/aws/aws-sdk-go-v2/service/billing v1.9.4 h1:IMiahVCNEL61U2HfsRdvrdNQ3gyj4qN5cJrogppduPU= github.com/aws/aws-sdk-go-v2/service/billing v1.9.4/go.mod h1:DbptyYoS5RY5n7oFKdqkXbYvuxqhp/Z5QMohp6uKsII= github.com/aws/aws-sdk-go-v2/service/budgets v1.42.3 h1:SWmlAqhAeh9ByGn56CLqJEEFwd1tsDM1t9ojTcxpnvo= @@ -117,8 +117,8 @@ github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.16 h1:Of5xU2ny github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.16/go.mod h1:Fk1uZOvXuciwTTxX6qWudPL2v4rH4VGuHbqfKdC30ew= github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.28.8 h1:0hxpLzWPOFNofMbyOSZltrD8IvrtpOjBjQUpmZRjUfI= github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.28.8/go.mod h1:r7zkhVfcXyRi8L7AM6iaZiQaJVM82xkitxsq8e3Yvs0= -github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.38.2 h1:6l7T7NzEIX1H4mshRGlrUKBsspYZf1v6wLpbbgAQIcQ= -github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.38.2/go.mod h1:cIHgZyLi8PuZkq2lsJfeHtC87kitSmbsNvgxW7HAM3U= +github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.39.0 h1:1rniE6ggSl4WNuHhChB6wKtQPJkSuGBfR2+HGQyB9/Y= +github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.39.0/go.mod h1:cIHgZyLi8PuZkq2lsJfeHtC87kitSmbsNvgxW7HAM3U= github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.15 h1:VKLLGKz1jfsQMf/tCjqiqzwha+5n8bcndAqH4/yMJEk= github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.15/go.mod h1:6eUG6qcUwAACFF/b0fIlZF0sSUwRwY2yJaJ0KoRNjF8= github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.29.8 h1:Dmsh7h8g+P7lA3QLkdmr/lm56tlRIqgXoaxeXf6um5g= @@ -221,14 +221,14 @@ github.com/aws/aws-sdk-go-v2/service/dsql v1.12.3 h1:RoFmi9T73/kXMKPuATxor3ORCVZ github.com/aws/aws-sdk-go-v2/service/dsql v1.12.3/go.mod h1:gO9U7P8RS8V+2eWjNcdSa4L5v0uDYju7IVr/malpnoo= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.53.5 h1:mSBrQCXMjEvLHsYyJVbN8QQlcITXwHEuu+8mX9e2bSo= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.53.5/go.mod h1:eEuD0vTf9mIzsSjGBFWIaNQwtH5/mzViJOVQfnMY5DE= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.277.0 h1:RHJSkRXDGkAKrV4CTEsZsZkOmSpxXKO4aKx4rXd94K4= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.277.0/go.mod h1:Wg68QRgy2gEGGdmTPU/UbVpdv8sM14bUZmF64KFwAsY= -github.com/aws/aws-sdk-go-v2/service/ecr v1.54.4 h1:4THfkydiKvFeOFlfY1ABHe4Nsj+Jy6S6tHBqUAojY0M= -github.com/aws/aws-sdk-go-v2/service/ecr v1.54.4/go.mod h1:8n8vVvu7LzveA0or4iWQwNndJStpKOX4HiVHM5jax2U= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.278.0 h1:Cx/Rs2zaG30Dn4QMvUGC5rCAZagA8heta0TWAdBE/Xc= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.278.0/go.mod h1:Wg68QRgy2gEGGdmTPU/UbVpdv8sM14bUZmF64KFwAsY= +github.com/aws/aws-sdk-go-v2/service/ecr v1.55.0 h1:Mz6rvVhqmqGPzZNDLolW9IwPzhL/V+QS+dvX+vm/zh8= +github.com/aws/aws-sdk-go-v2/service/ecr v1.55.0/go.mod h1:8n8vVvu7LzveA0or4iWQwNndJStpKOX4HiVHM5jax2U= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.8 h1:2QlSMAimXfMKYRFlxGkbRMRtKN3OqIOB/CfxMcVdzjM= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.8/go.mod h1:esoP/SqS8FVryu4PPLX6ND925slId/IxPxvUBKuBqRk= -github.com/aws/aws-sdk-go-v2/service/ecs v1.69.5 h1:5nkhwt0d/gjuT3AQ2LUK0aFRNB3MGlzB2elqy/ZsKP4= -github.com/aws/aws-sdk-go-v2/service/ecs v1.69.5/go.mod h1:LQMlcWBoiFVD3vUVEz42ST0yTiaDujv2dRE6sXt1yPE= +github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0 h1:IZpZatHsscdOKjwmDXC6idsCXmm3F/obutAUNjnX+OM= +github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0/go.mod h1:LQMlcWBoiFVD3vUVEz42ST0yTiaDujv2dRE6sXt1yPE= github.com/aws/aws-sdk-go-v2/service/efs v1.41.9 h1:uHir2myVtdCfpe6ZcmOgmkUFRTUq2mKfhvfQpBcrry4= github.com/aws/aws-sdk-go-v2/service/efs v1.41.9/go.mod h1:qOhKklI/Hn44U8oZPT16hdCAAjap4PWmCkwDm5YNVPY= github.com/aws/aws-sdk-go-v2/service/eks v1.76.3 h1:840uwcJTIwrMPLuEUQVFKZbPgwnYzc5WDyXMiMYm5Ts= @@ -309,8 +309,8 @@ github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.26.9 h1:TMnrStLgz43BqBtf github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.26.9/go.mod h1:TCzNbB10tslhTf7ZEJafSIaFfdwAzPmO/3V1+e/Dsrw= github.com/aws/aws-sdk-go-v2/service/invoicing v1.9.3 h1:wxTRhCgKwZlHHHaWyCLZzfXc0Z7JkQEf5Glv74HbjuA= github.com/aws/aws-sdk-go-v2/service/invoicing v1.9.3/go.mod h1:AXcwyknhBgVBjG0ra2Jo+KDHHBgk9iOYDx/qndgU0jo= -github.com/aws/aws-sdk-go-v2/service/iot v1.70.0 h1:e9LtnXmY7NQ5+JU/uaKZbDsavZTHWV1HtwSKXelwVhc= -github.com/aws/aws-sdk-go-v2/service/iot v1.70.0/go.mod h1:y/GDsulMROoS3zX2iGWhVtsXQ1YXWPinm3mjqxmWYWY= +github.com/aws/aws-sdk-go-v2/service/iot v1.71.0 h1:6KvLqcT4EqZwbcgEgJ5g7brurJL5ZutjR27QKgWxx0U= +github.com/aws/aws-sdk-go-v2/service/iot v1.71.0/go.mod h1:y/GDsulMROoS3zX2iGWhVtsXQ1YXWPinm3mjqxmWYWY= github.com/aws/aws-sdk-go-v2/service/ivs v1.48.9 h1:6C64paCnqf1w9nrrNB0XyVI34HIaApe9EMXazi7Jl6I= github.com/aws/aws-sdk-go-v2/service/ivs v1.48.9/go.mod h1:+gda20Gu0g3caQSrAof5V+Kyl07F6N0cVDvFfOHMru0= github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.15 h1:Z5cflX4kjGZLiGLfnd/7JRCYQeSlhAbZqcEz8GIoJn0= @@ -399,8 +399,8 @@ github.com/aws/aws-sdk-go-v2/service/observabilityadmin v1.9.1 h1:EOLU6qXaLwCuJn github.com/aws/aws-sdk-go-v2/service/observabilityadmin v1.9.1/go.mod h1:oI09oxkji3dh/cPHWSMOVISPdlY3S4N1HO/NRAgTm+o= github.com/aws/aws-sdk-go-v2/service/odb v1.7.0 h1:VygXCW2iVsTyGTHxCfN6YXFTxNYDcoTBA9dp9c0RDyY= github.com/aws/aws-sdk-go-v2/service/odb v1.7.0/go.mod h1:j2q8xXADdmPeBiXj4MCrqas5NuZRQRSwm45PxcS2Z3A= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.56.0 h1:5fEX9xgasulnog9z/s2tfA1HzxoOcTzjFNZxbRvURYw= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.56.0/go.mod h1:0VgDf/vMiSyGBTP1OrqqdWLpbAJQd9wKfFpLtWffrFQ= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.57.0 h1:O+FQ+Jfe8VPEj8ehKSUvfMeUdnnGaAU1N5TvldLMNwk= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.57.0/go.mod h1:0VgDf/vMiSyGBTP1OrqqdWLpbAJQd9wKfFpLtWffrFQ= github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.28.1 h1:3UM9bGhz7+3f/ldvj8JPkqdq5q7A7iqscExCaBjQe4A= github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.28.1/go.mod h1:HpoYvkQFTR3IwYDCJQrxOGqtQpwWYF8O6a7YeDjfyCo= github.com/aws/aws-sdk-go-v2/service/organizations v1.50.0 h1:HGC9bFaqjHWWD8cnNYVbQIrkzZwRJs2UxqdrGnaeSvE= @@ -505,8 +505,8 @@ github.com/aws/aws-sdk-go-v2/service/servicequotas v1.34.0 h1:hZ5/DIZpiYtHxnNk18 github.com/aws/aws-sdk-go-v2/service/servicequotas v1.34.0/go.mod h1:zfrr8eV7yr3nakr+K+22q+wA3t5ApjqTiNSCbEzK7fM= github.com/aws/aws-sdk-go-v2/service/ses v1.34.17 h1:XR7CtY988tck2Bhuy1JP4FsV8z0OAwjuh+gb7nAy8/M= github.com/aws/aws-sdk-go-v2/service/ses v1.34.17/go.mod h1:2CspeTVldnJdRixX36SzTZuoIpjyKlfeXyB7/JB5KGk= -github.com/aws/aws-sdk-go-v2/service/sesv2 v1.58.0 h1:5Rv2iCikjKo1pU2E8EL0uVns2/5V2ibb6oJ3QAL43WI= -github.com/aws/aws-sdk-go-v2/service/sesv2 v1.58.0/go.mod h1:p0iz0in3/mt3aS2Ovk3aKeOq5vwM/V3prQG9nlBO/OM= +github.com/aws/aws-sdk-go-v2/service/sesv2 v1.59.0 h1:HQYog9wJM8D9aF0bOVzzWbjpWZ7exyjc3rLb7P8Qb8E= +github.com/aws/aws-sdk-go-v2/service/sesv2 v1.59.0/go.mod h1:p0iz0in3/mt3aS2Ovk3aKeOq5vwM/V3prQG9nlBO/OM= github.com/aws/aws-sdk-go-v2/service/sfn v1.40.5 h1:nhPlRp9oCZOh1M/4zVn4pqguzEJ3Q3emnyS9k8sW8u8= github.com/aws/aws-sdk-go-v2/service/sfn v1.40.5/go.mod h1:dfVRuB5XudlLMY6PVMu4T2lmfXYMARapmdc2/cUN2Mw= github.com/aws/aws-sdk-go-v2/service/shield v1.34.16 h1:O4ji2ueMOLBwd81y1PyfMbIj5o83fVw3ICR0iIh/Xbc= @@ -527,12 +527,12 @@ github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.15 h1:qsrylJR2awA00U/c+2 github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.15/go.mod h1:xQp5IcwUQqzB9UR6saKM6inR+8sng6RXrUOVBoFYiCo= github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.16 h1:9DKnEt9pWeBYWmy2gCyAtgKtfSg54dErFG9/W+Woe+I= github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.16/go.mod h1:NquyVWFm19AdsR+UrvxYhUWPVBaJ1G/FFclxDRjkbfg= -github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.15 h1:RFfnrJ4kCHhZrybUAEAXgLBRkTMXFnZGOacjHZi2/us= -github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.15/go.mod h1:bKHP0BahB1yKINXTjQ/iBDMl82wodt4aGpdqefZF2Xw= +github.com/aws/aws-sdk-go-v2/service/ssmsap v1.26.0 h1:kC7Lx4jIlVSgEQ2XEI/Bw4Gum+jDwE47TiS5EbuU1Ro= +github.com/aws/aws-sdk-go-v2/service/ssmsap v1.26.0/go.mod h1:bKHP0BahB1yKINXTjQ/iBDMl82wodt4aGpdqefZF2Xw= github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 h1:aM/Q24rIlS3bRAhTyFurowU8A0SMyGDtEOY/l/s/1Uw= github.com/aws/aws-sdk-go-v2/service/sso v1.30.8/go.mod h1:+fWt2UHSb4kS7Pu8y+BMBvJF0EWx+4H0hzNwtDNRTrg= -github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.12 h1:5uwMt+itx/rZLocKDf88XfUbBqy+YvudvkMRsUcixlA= -github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.12/go.mod h1:ETe6RIU0wxLv9cYh5EEXyExIeZj2/xgEv6eRKLboBJM= +github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.13 h1:Ryd6BIcvbVrnru3ikEzSxs0rBePGZwZCGYHg0SQaLhA= +github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.13/go.mod h1:ETe6RIU0wxLv9cYh5EEXyExIeZj2/xgEv6eRKLboBJM= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 h1:AHDr0DaHIAo8c9t1emrzAlVDFp+iMMKnPdYy6XO4MCE= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12/go.mod h1:GQ73XawFFiWxyWXMHWfhiomvP3tXtdNar/fi8z18sx0= github.com/aws/aws-sdk-go-v2/service/storagegateway v1.43.9 h1:nCEsDXS7zjGluay/uiybSRbO2rnBR3b+cvINB4hNbcY= diff --git a/internal/service/cloudfront/distribution.go b/internal/service/cloudfront/distribution.go index fa7bef206ba2..1be0fe7c852b 100644 --- a/internal/service/cloudfront/distribution.go +++ b/internal/service/cloudfront/distribution.go @@ -1209,7 +1209,7 @@ func deleteDistribution(ctx context.Context, conn *cloudfront.Client, id string) return fmt.Errorf("deleting CloudFront Distribution (%s): %w", id, err) } - if _, err := waitDistributionDeleted(ctx, conn, id); err != nil { + if err := waitDistributionDeleted(ctx, conn, id); err != nil { return fmt.Errorf("waiting for CloudFront Distribution (%s) delete: %w", id, err) } @@ -1296,8 +1296,8 @@ func findDistributionByID(ctx context.Context, conn *cloudfront.Client, id strin return output, nil } -func statusDistribution(ctx context.Context, conn *cloudfront.Client, id string) sdkretry.StateRefreshFunc { - return func() (any, string, error) { +func statusDistribution(conn *cloudfront.Client, id string) retry.StateRefreshFuncOf[any, string] { + return func(ctx context.Context) (any, string, error) { output, err := findDistributionByID(ctx, conn, id) if retry.NotFound(err) { @@ -1317,10 +1317,10 @@ func statusDistribution(ctx context.Context, conn *cloudfront.Client, id string) } func waitDistributionDeployed(ctx context.Context, conn *cloudfront.Client, id string) (*cloudfront.GetDistributionOutput, error) { - stateConf := &sdkretry.StateChangeConf{ + stateConf := &retry.StateChangeConf{ Pending: []string{distributionStatusInProgress}, Target: []string{distributionStatusDeployed}, - Refresh: statusDistribution(ctx, conn, id), + Refresh: statusDistribution(conn, id), Timeout: 90 * time.Minute, MinTimeout: 15 * time.Second, Delay: 30 * time.Second, @@ -1335,23 +1335,19 @@ func waitDistributionDeployed(ctx context.Context, conn *cloudfront.Client, id s return nil, err } -func waitDistributionDeleted(ctx context.Context, conn *cloudfront.Client, id string) (*cloudfront.GetDistributionOutput, error) { - stateConf := &sdkretry.StateChangeConf{ +func waitDistributionDeleted(ctx context.Context, conn *cloudfront.Client, id string) error { + stateConf := &retry.StateChangeConf{ Pending: []string{distributionStatusInProgress, distributionStatusDeployed}, Target: []string{}, - Refresh: statusDistribution(ctx, conn, id), + Refresh: statusDistribution(conn, id), Timeout: 90 * time.Minute, MinTimeout: 15 * time.Second, Delay: 15 * time.Second, } - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*cloudfront.GetDistributionOutput); ok { - return output, err - } + _, err := stateConf.WaitForStateContext(ctx) - return nil, err + return err } func expandDistributionConfig(d *schema.ResourceData) *awstypes.DistributionConfig { diff --git a/internal/service/cloudfront/exports_test.go b/internal/service/cloudfront/exports_test.go index c9556eedd1d6..696700c32428 100644 --- a/internal/service/cloudfront/exports_test.go +++ b/internal/service/cloudfront/exports_test.go @@ -13,6 +13,7 @@ var ( ResourceFunction = resourceFunction ResourceKeyGroup = resourceKeyGroup ResourceMonitoringSubscription = resourceMonitoringSubscription + ResourceMultiTenantDistribution = newMultiTenantDistributionResource ResourceOriginAccessControl = resourceOriginAccessControl ResourceOriginAccessIdentity = resourceOriginAccessIdentity ResourceOriginRequestPolicy = resourceOriginRequestPolicy diff --git a/internal/service/cloudfront/multitenant_distribution.go b/internal/service/cloudfront/multitenant_distribution.go new file mode 100644 index 000000000000..7d9729fa52cb --- /dev/null +++ b/internal/service/cloudfront/multitenant_distribution.go @@ -0,0 +1,1188 @@ +// Copyright IBM Corp. 2014, 2025 +// SPDX-License-Identifier: MPL-2.0 + +package cloudfront + +import ( + "context" + "fmt" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/cloudfront" + awstypes "github.com/aws/aws-sdk-go-v2/service/cloudfront/types" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int32default" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/retry" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +const ( + defaultConnectionAttempts = 3 + defaultConnectionTimeout = 10 + defaultResponseCompletionTimeout = 30 + defaultOriginKeepaliveTimeout = 5 + defaultOriginReadTimeout = 30 +) + +// @FrameworkResource("aws_cloudfront_multitenant_distribution", name="Multi-tenant Distribution") +// @Tags(identifierAttribute="arn") +// +// Multi-tenant Distribution Limitations: +// The following fields are NOT supported for multi-tenant distributions and have been excluded from the schema: +// - ActiveTrustedSigners (use ActiveTrustedKeyGroups instead) +// - AliasICPRecordals (managed by connection groups) +// - CacheBehavior.DefaultTTL, MaxTTL, MinTTL (use cache policies instead) +// - CacheBehavior.ForwardedValues (deprecated and not supported) +// - CacheBehavior.SmoothStreaming +// - CacheBehavior.TrustedSigners (use TrustedKeyGroups instead) +// - DefaultCacheBehavior.DefaultTTL, MaxTTL, MinTTL (use cache policies instead) +// - DefaultCacheBehavior.ForwardedValues (deprecated and not supported) +// - DefaultCacheBehavior.SmoothStreaming +// - DefaultCacheBehavior.TrustedSigners (use TrustedKeyGroups instead) +// - DistributionConfig.Aliases (managed by connection groups) +// - DistributionConfig.AnycastIpListId (use connection group instead) +// - DistributionConfig.ContinuousDeploymentPolicyId +// - DistributionConfig.IsIPV6Enabled (use connection group instead) +// - DistributionConfig.PriceClass +// - DistributionConfig.Staging +// - S3OriginConfig (use origin access control instead) +// - ViewerCertificate.IAMCertificateId (use ACM certificates instead) +// +// Multi-tenant Distribution Requirements: +// - DistributionConfig.ConnectionMode is automatically set to "tenant-only" +// - DistributionConfig.TenantConfig must be specified (contains parameter definitions) +// - DistributionConfig.WebACLId must be a WAF V2 web ACL if specified +func newMultiTenantDistributionResource(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &multiTenantDistributionResource{} + + r.SetDefaultCreateTimeout(30 * time.Minute) + r.SetDefaultUpdateTimeout(30 * time.Minute) + r.SetDefaultDeleteTimeout(30 * time.Minute) + + return r, nil +} + +type multiTenantDistributionResource struct { + framework.ResourceWithModel[multiTenantDistributionResourceModel] + framework.WithImportByID + framework.WithTimeouts +} + +func (r *multiTenantDistributionResource) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + names.AttrARN: framework.ARNAttributeComputedOnly(), + names.AttrDomainName: schema.StringAttribute{Computed: true}, + "etag": schema.StringAttribute{Computed: true}, + names.AttrID: framework.IDAttribute(), + "in_progress_invalidation_batches": schema.Int32Attribute{Computed: true}, + "last_modified_time": schema.StringAttribute{ + CustomType: timetypes.RFC3339Type{}, + Computed: true, + }, + names.AttrStatus: schema.StringAttribute{Computed: true}, + "caller_reference": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "connection_mode": schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.ConnectionMode](), + Computed: true, + }, + names.AttrComment: schema.StringAttribute{ + Required: true, + }, + "default_root_object": schema.StringAttribute{ + Optional: true, + }, + names.AttrEnabled: schema.BoolAttribute{ + Required: true, + }, + "http_version": schema.StringAttribute{ + Optional: true, + Computed: true, + CustomType: fwtypes.StringEnumType[awstypes.HttpVersion](), + }, + names.AttrTags: tftags.TagsAttribute(), + names.AttrTagsAll: tftags.TagsAttributeComputedOnly(), + "web_acl_id": schema.StringAttribute{ + Optional: true, + // Note: For multi-tenant distributions, this must be a WAF V2 web ACL if specified + }, + }, + Blocks: map[string]schema.Block{ + "active_trusted_key_groups": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[activeTrustedKeyGroupsModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + names.AttrEnabled: schema.BoolAttribute{Computed: true}, + }, + Blocks: map[string]schema.Block{ + "items": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[kgKeyPairIDsModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "key_group_id": schema.StringAttribute{Computed: true}, + "key_pair_ids": schema.ListAttribute{ + CustomType: fwtypes.ListOfStringType, + Computed: true, + ElementType: types.StringType, + }, + }, + }, + }, + }, + }, + }, + "custom_error_response": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[customErrorResponseModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "error_caching_min_ttl": schema.Int64Attribute{ + Optional: true, + Computed: true, + Default: int64default.StaticInt64(0), + }, + "error_code": schema.Int64Attribute{ + Required: true, + }, + "response_code": schema.StringAttribute{ + Optional: true, + }, + "response_page_path": schema.StringAttribute{ + Optional: true, + }, + }, + }, + }, + "cache_behavior": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[cacheBehaviorModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "cache_policy_id": schema.StringAttribute{ + Optional: true, + }, + "compress": schema.BoolAttribute{ + Optional: true, + Computed: true, + Default: booldefault.StaticBool(false), + }, + "field_level_encryption_id": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString(""), + }, + "origin_request_policy_id": schema.StringAttribute{ + Optional: true, + }, + "path_pattern": schema.StringAttribute{ + Required: true, + }, + "realtime_log_config_arn": schema.StringAttribute{ + Optional: true, + }, + "response_headers_policy_id": schema.StringAttribute{ + Optional: true, + }, + "target_origin_id": schema.StringAttribute{ + Required: true, + }, + "viewer_protocol_policy": schema.StringAttribute{ + Required: true, + CustomType: fwtypes.StringEnumType[awstypes.ViewerProtocolPolicy](), + }, + }, + Blocks: map[string]schema.Block{ + "allowed_methods": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[allowedMethodsModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "items": schema.SetAttribute{ + Required: true, + CustomType: fwtypes.SetOfStringEnumType[awstypes.Method](), + }, + "cached_methods": schema.SetAttribute{ + Required: true, + CustomType: fwtypes.SetOfStringEnumType[awstypes.Method](), + }, + }, + }, + }, + "function_association": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[functionAssociationModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "event_type": schema.StringAttribute{ + Required: true, + CustomType: fwtypes.StringEnumType[awstypes.EventType](), + }, + names.AttrFunctionARN: schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + "lambda_function_association": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[lambdaFunctionAssociationModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "event_type": schema.StringAttribute{ + Required: true, + CustomType: fwtypes.StringEnumType[awstypes.EventType](), + }, + "include_body": schema.BoolAttribute{ + Optional: true, + Computed: true, + }, + "lambda_function_arn": schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + "trusted_key_groups": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[trustedKeyGroupsModel](ctx), + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "items": schema.ListAttribute{ + Optional: true, + CustomType: fwtypes.ListOfStringType, + }, + names.AttrEnabled: schema.BoolAttribute{ + Optional: true, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + "default_cache_behavior": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[defaultCacheBehaviorModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "cache_policy_id": schema.StringAttribute{ + Optional: true, + }, + "compress": schema.BoolAttribute{ + Optional: true, + Computed: true, + Default: booldefault.StaticBool(false), + }, + "field_level_encryption_id": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString(""), + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "origin_request_policy_id": schema.StringAttribute{ + Optional: true, + }, + "realtime_log_config_arn": schema.StringAttribute{ + Optional: true, + }, + "response_headers_policy_id": schema.StringAttribute{ + Optional: true, + }, + "target_origin_id": schema.StringAttribute{ + Required: true, + }, + "viewer_protocol_policy": schema.StringAttribute{ + Required: true, + CustomType: fwtypes.StringEnumType[awstypes.ViewerProtocolPolicy](), + }, + }, + Blocks: map[string]schema.Block{ + "allowed_methods": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[allowedMethodsModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "items": schema.SetAttribute{ + Required: true, + CustomType: fwtypes.SetOfStringEnumType[awstypes.Method](), + }, + "cached_methods": schema.SetAttribute{ + Required: true, + CustomType: fwtypes.SetOfStringEnumType[awstypes.Method](), + }, + }, + }, + }, + "function_association": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[functionAssociationModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "event_type": schema.StringAttribute{ + Required: true, + CustomType: fwtypes.StringEnumType[awstypes.EventType](), + }, + names.AttrFunctionARN: schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + "lambda_function_association": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[lambdaFunctionAssociationModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "event_type": schema.StringAttribute{ + Required: true, + CustomType: fwtypes.StringEnumType[awstypes.EventType](), + }, + "include_body": schema.BoolAttribute{ + Optional: true, + Computed: true, + }, + "lambda_function_arn": schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + "trusted_key_groups": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[trustedKeyGroupsModel](ctx), + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "items": schema.ListAttribute{ + Optional: true, + CustomType: fwtypes.ListOfStringType, + }, + names.AttrEnabled: schema.BoolAttribute{ + Optional: true, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + "origin": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[originModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "connection_attempts": schema.Int32Attribute{ + Optional: true, + Computed: true, + Default: int32default.StaticInt32(defaultConnectionAttempts), + }, + "connection_timeout": schema.Int32Attribute{ + Optional: true, + Computed: true, + Default: int32default.StaticInt32(defaultConnectionTimeout), + }, + names.AttrDomainName: schema.StringAttribute{ + Required: true, + }, + names.AttrID: schema.StringAttribute{ + Required: true, + }, + "origin_access_control_id": schema.StringAttribute{ + Optional: true, + }, + "origin_path": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString(""), + }, + "response_completion_timeout": schema.Int32Attribute{ + Optional: true, + Computed: true, + Default: int32default.StaticInt32(defaultResponseCompletionTimeout), + }, + }, + Blocks: map[string]schema.Block{ + "custom_header": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[customHeaderModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "header_name": schema.StringAttribute{ + Required: true, + }, + "header_value": schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + "custom_origin_config": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[customOriginConfigModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "http_port": schema.Int32Attribute{ + Required: true, + }, + "https_port": schema.Int32Attribute{ + Required: true, + }, + names.AttrIPAddressType: schema.StringAttribute{ + Optional: true, + CustomType: fwtypes.StringEnumType[awstypes.IpAddressType](), + }, + "origin_keepalive_timeout": schema.Int32Attribute{ + Optional: true, + Computed: true, + Default: int32default.StaticInt32(defaultOriginKeepaliveTimeout), + }, + "origin_read_timeout": schema.Int32Attribute{ + Optional: true, + Computed: true, + Default: int32default.StaticInt32(defaultOriginReadTimeout), + }, + "origin_protocol_policy": schema.StringAttribute{ + Required: true, + CustomType: fwtypes.StringEnumType[awstypes.OriginProtocolPolicy](), + }, + "origin_ssl_protocols": schema.SetAttribute{ + Required: true, + CustomType: fwtypes.SetOfStringEnumType[awstypes.SslProtocol](), + }, + }, + }, + }, + "origin_shield": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[originShieldModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + names.AttrEnabled: schema.BoolAttribute{ + Required: true, + }, + "origin_shield_region": schema.StringAttribute{ + Optional: true, + }, + }, + }, + }, + + "vpc_origin_config": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[vpcOriginConfigModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "origin_keepalive_timeout": schema.Int32Attribute{ + Optional: true, + Computed: true, + Default: int32default.StaticInt32(defaultOriginKeepaliveTimeout), + }, + "origin_read_timeout": schema.Int32Attribute{ + Optional: true, + Computed: true, + Default: int32default.StaticInt32(defaultOriginReadTimeout), + }, + "vpc_origin_id": schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + }, + }, + }, + "origin_group": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[originGroupModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "origin_id": schema.StringAttribute{ + Required: true, + }, + }, + Blocks: map[string]schema.Block{ + "failover_criteria": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[failoverCriteriaModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "status_codes": schema.SetAttribute{ + Required: true, + ElementType: types.Int64Type, + }, + }, + }, + }, + "member": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[memberModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtLeast(2), + listvalidator.SizeAtMost(2), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "origin_id": schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + }, + }, + }, + "restrictions": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[restrictionsModel](ctx), + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Blocks: map[string]schema.Block{ + "geo_restriction": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[geoRestrictionModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "items": schema.SetAttribute{ + Optional: true, + CustomType: fwtypes.SetOfStringType, + }, + "restriction_type": schema.StringAttribute{ + Required: true, + CustomType: fwtypes.StringEnumType[awstypes.GeoRestrictionType](), + }, + }, + }, + }, + }, + }, + }, + "tenant_config": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[tenantConfigModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Blocks: map[string]schema.Block{ + "parameter_definition": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[parameterDefinitionModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + names.AttrName: schema.StringAttribute{ + Required: true, + }, + }, + Blocks: map[string]schema.Block{ + "definition": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[parameterDefinitionSchemaModel](ctx), + NestedObject: schema.NestedBlockObject{ + Blocks: map[string]schema.Block{ + "string_schema": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[stringSchemaConfigModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "required": schema.BoolAttribute{ + Required: true, + }, + names.AttrComment: schema.StringAttribute{ + Optional: true, + }, + names.AttrDefaultValue: schema.StringAttribute{ + Optional: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + names.AttrTimeouts: timeouts.Block(ctx, timeouts.Opts{ + Create: true, + Delete: true, + Update: true, + }), + "viewer_certificate": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[viewerCertificateModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "acm_certificate_arn": schema.StringAttribute{ + Optional: true, + }, + "cloudfront_default_certificate": schema.BoolAttribute{ + Optional: true, + }, + "minimum_protocol_version": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString(string(awstypes.MinimumProtocolVersionTLSv1)), + CustomType: fwtypes.StringEnumType[awstypes.MinimumProtocolVersion](), + }, + "ssl_support_method": schema.StringAttribute{ + Optional: true, + Computed: true, + CustomType: fwtypes.StringEnumType[awstypes.SSLSupportMethod](), + }, + }, + }, + }, + }, + } +} + +func (r *multiTenantDistributionResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var data multiTenantDistributionResourceModel + response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().CloudFrontClient(ctx) + + input := &cloudfront.CreateDistributionWithTagsInput{ + DistributionConfigWithTags: &awstypes.DistributionConfigWithTags{ + DistributionConfig: &awstypes.DistributionConfig{}, + Tags: &awstypes.Tags{Items: []awstypes.Tag{}}, + }, + } + response.Diagnostics.Append(fwflex.Expand(ctx, data, input.DistributionConfigWithTags.DistributionConfig)...) + if response.Diagnostics.HasError() { + return + } + + // Set required computed fields that AutoFlex can't handle + input.DistributionConfigWithTags.DistributionConfig.CallerReference = aws.String(id.UniqueId()) + + // Set ConnectionMode to "tenant-only" to create a multi-tenant distribution instead of standard distribution + // This is the key field that distinguishes multi-tenant from standard distributions + input.DistributionConfigWithTags.DistributionConfig.ConnectionMode = awstypes.ConnectionModeTenantOnly + + if tags := getTagsIn(ctx); len(tags) > 0 { + input.DistributionConfigWithTags.Tags.Items = tags + } + + output, err := conn.CreateDistributionWithTags(ctx, input) + if err != nil { + response.Diagnostics.AddError("creating CloudFront Multi-tenant Distribution", err.Error()) + return + } + + // Set ID immediately + data.ID = types.StringValue(aws.ToString(output.Distribution.Id)) + data.ARN = types.StringValue(aws.ToString(output.Distribution.ARN)) + + // Wait for distribution to be deployed + distro, err := waitDistributionDeployed(ctx, conn, data.ID.ValueString()) + if err != nil { + response.State.SetAttribute(ctx, path.Root(names.AttrID), data.ID) // Set 'id' so as to taint the resource. + response.Diagnostics.AddError(fmt.Sprintf("waiting for CloudFront Multi-tenant Distribution (%s) create", data.ID.ValueString()), err.Error()) + return + } + + // Read the distribution to get consistent state + data.ETag = fwflex.StringToFramework(ctx, distro.ETag) + response.Diagnostics.Append(fwflex.Flatten(ctx, distro.Distribution.DistributionConfig, &data)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(fwflex.Flatten(ctx, distro.Distribution, &data)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &data)...) +} + +func (r *multiTenantDistributionResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var data multiTenantDistributionResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().CloudFrontClient(ctx) + + output, err := findDistributionByID(ctx, conn, data.ID.ValueString()) + if retry.NotFound(err) { + response.Diagnostics.AddWarning( + "CloudFront Multi-tenant Distribution not found", + fmt.Sprintf("CloudFront Multi-tenant Distribution (%s) not found, removing from state", data.ID.ValueString()), + ) + response.State.RemoveResource(ctx) + return + } + if err != nil { + response.Diagnostics.AddError("reading CloudFront Multi-tenant Distribution", err.Error()) + return + } + + response.Diagnostics.Append(fwflex.Flatten(ctx, output.Distribution, &data)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(fwflex.Flatten(ctx, output.Distribution.DistributionConfig, &data)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &data)...) +} + +func (r *multiTenantDistributionResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var old, new multiTenantDistributionResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &old)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(request.Plan.Get(ctx, &new)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().CloudFrontClient(ctx) + + // Handle tag updates first + if !new.Tags.Equal(old.Tags) { + if err := updateTags(ctx, conn, new.ARN.ValueString(), old.Tags, new.Tags); err != nil { + response.Diagnostics.AddError("updating CloudFront Multi-tenant Distribution tags", err.Error()) + return + } + } + + // Check if distribution config needs updating (anything other than tags) + if mtDistributionHasChanges(old, new) { + // Get current distribution to get ETag for update + output, err := findDistributionByID(ctx, conn, new.ID.ValueString()) + if err != nil { + response.Diagnostics.AddError("reading CloudFront Multi-tenant Distribution for update", err.Error()) + return + } + + // Prepare update input - start with existing config to preserve all fields + input := cloudfront.UpdateDistributionInput{ + Id: new.ID.ValueStringPointer(), + IfMatch: output.ETag, + DistributionConfig: output.Distribution.DistributionConfig, + } + + // Expand the new configuration over the existing config + response.Diagnostics.Append(fwflex.Expand(ctx, new, input.DistributionConfig)...) + if response.Diagnostics.HasError() { + return + } + + // Ensure ConnectionMode remains tenant-only + input.DistributionConfig.ConnectionMode = awstypes.ConnectionModeTenantOnly + + // Update the distribution + updateOutput, err := conn.UpdateDistribution(ctx, &input) + if err != nil { + response.Diagnostics.AddError("updating CloudFront Multi-tenant Distribution", err.Error()) + return + } + + // Wait for deployment if enabled + if new.Enabled.ValueBool() { + _, err = waitDistributionDeployed(ctx, conn, new.ID.ValueString()) + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("waiting for CloudFront Multi-tenant Distribution (%s) update", new.ID.ValueString()), err.Error()) + return + } + } + + // Update ETag from response + new.ETag = fwflex.StringToFramework(ctx, updateOutput.ETag) + } + + // Read back the updated distribution to ensure state consistency + output, err := findDistributionByID(ctx, conn, new.ID.ValueString()) + if err != nil { + response.Diagnostics.AddError("reading CloudFront Multi-tenant Distribution after update", err.Error()) + return + } + + response.Diagnostics.Append(fwflex.Flatten(ctx, output.Distribution, &new)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(fwflex.Flatten(ctx, output.Distribution.DistributionConfig, &new)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &new)...) +} + +// mtDistributionHasChanges checks if distribution configuration has changed (excluding tags) +func mtDistributionHasChanges(old, new multiTenantDistributionResourceModel) bool { + return !old.Comment.Equal(new.Comment) || + !old.DefaultRootObject.Equal(new.DefaultRootObject) || + !old.Enabled.Equal(new.Enabled) || + !old.HTTPVersion.Equal(new.HTTPVersion) || + !old.WebACLID.Equal(new.WebACLID) || + !old.CacheBehavior.Equal(new.CacheBehavior) || + !old.CustomErrorResponse.Equal(new.CustomErrorResponse) || + !old.DefaultCacheBehavior.Equal(new.DefaultCacheBehavior) || + !old.Origin.Equal(new.Origin) || + !old.OriginGroup.Equal(new.OriginGroup) || + !old.Restrictions.Equal(new.Restrictions) || + !old.TenantConfig.Equal(new.TenantConfig) || + !old.ViewerCertificate.Equal(new.ViewerCertificate) +} + +func (r *multiTenantDistributionResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var data multiTenantDistributionResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + conn := r.Meta().CloudFrontClient(ctx) + id := data.ID.ValueString() + + // 1. Start by waiting for deployment (returns immediate if already deployed) + if _, err := waitDistributionDeployed(ctx, conn, id); err != nil && !retry.NotFound(err) && !errs.IsA[*awstypes.NoSuchDistribution](err) { + response.Diagnostics.AddError("waiting for CloudFront Multi-tenant Distribution deploy before delete", err.Error()) + return + } + + // 2. Try delete + err := deleteMultiTenantDistribution(ctx, conn, id) + + // 3. Return early for success + if err == nil || retry.NotFound(err) || errs.IsA[*awstypes.NoSuchDistribution](err) { + return + } + + // 4. If not disabled error, disable, wait for deploy, delete + if errs.IsA[*awstypes.DistributionNotDisabled](err) { + disableErr := disableMultiTenantDistribution(ctx, conn, id) + if disableErr == nil || retry.NotFound(disableErr) || errs.IsA[*awstypes.NoSuchDistribution](disableErr) { + return + } + if disableErr != nil { + response.Diagnostics.AddError("disabling CloudFront Multi-tenant Distribution", disableErr.Error()) + return + } + + err = deleteMultiTenantDistribution(ctx, conn, id) + } + + // 5. If precondition/invalidifmatchversion, retry delete + if errs.IsA[*awstypes.PreconditionFailed](err) || errs.IsA[*awstypes.InvalidIfMatchVersion](err) { + const timeout = 1 * time.Minute + _, err = tfresource.RetryWhenIsOneOf2[any, *awstypes.PreconditionFailed, *awstypes.InvalidIfMatchVersion](ctx, timeout, func(ctx context.Context) (any, error) { + return nil, deleteMultiTenantDistribution(ctx, conn, id) + }) + } + + // 6. Return early for success + if err == nil || retry.NotFound(err) || errs.IsA[*awstypes.NoSuchDistribution](err) { + return + } + + // 7. If err != nil, add error + response.Diagnostics.AddError("deleting CloudFront Multi-tenant Distribution", err.Error()) +} + +func deleteMultiTenantDistribution(ctx context.Context, conn *cloudfront.Client, id string) error { + etag, err := distroETag(ctx, conn, id) + + if err != nil { + return err + } + + input := cloudfront.DeleteDistributionInput{ + Id: aws.String(id), + IfMatch: aws.String(etag), + } + + _, err = conn.DeleteDistribution(ctx, &input) + + if err != nil { + return fmt.Errorf("deleting CloudFront Multi-tenant Distribution (%s): %w", id, err) + } + + if err := waitDistributionDeleted(ctx, conn, id); err != nil { + return fmt.Errorf("waiting for CloudFront Multi-tenant Distribution (%s) delete: %w", id, err) + } + + return nil +} + +func disableMultiTenantDistribution(ctx context.Context, conn *cloudfront.Client, id string) error { + output, err := findDistributionByID(ctx, conn, id) + + if err != nil { + return fmt.Errorf("reading CloudFront Multi-tenant Distribution (%s): %w", id, err) + } + + if aws.ToString(output.Distribution.Status) == distributionStatusInProgress { + output, err = waitDistributionDeployed(ctx, conn, id) + + if err != nil { + return fmt.Errorf("waiting for CloudFront Multi-tenant Distribution (%s) deploy: %w", id, err) + } + } + + if !aws.ToBool(output.Distribution.DistributionConfig.Enabled) { + return nil + } + + input := cloudfront.UpdateDistributionInput{ + DistributionConfig: output.Distribution.DistributionConfig, + Id: aws.String(id), + IfMatch: output.ETag, + } + input.DistributionConfig.Enabled = aws.Bool(false) + + _, err = conn.UpdateDistribution(ctx, &input) + + if err != nil { + return fmt.Errorf("updating CloudFront Multi-tenant Distribution (%s): %w", id, err) + } + + if _, err := waitDistributionDeployed(ctx, conn, id); err != nil { + return fmt.Errorf("waiting for CloudFront Multi-tenant Distribution (%s) deploy: %w", id, err) + } + + return nil +} + +type multiTenantDistributionResourceModel struct { + ActiveTrustedKeyGroups fwtypes.ListNestedObjectValueOf[activeTrustedKeyGroupsModel] `tfsdk:"active_trusted_key_groups" autoflex:",xmlwrapper=Items,omitempty"` + ARN types.String `tfsdk:"arn"` + CacheBehavior fwtypes.ListNestedObjectValueOf[cacheBehaviorModel] `tfsdk:"cache_behavior" autoflex:",xmlwrapper=Items,omitempty"` + CallerReference types.String `tfsdk:"caller_reference"` + ConnectionMode fwtypes.StringEnum[awstypes.ConnectionMode] `tfsdk:"connection_mode"` + Comment types.String `tfsdk:"comment"` + CustomErrorResponse fwtypes.ListNestedObjectValueOf[customErrorResponseModel] `tfsdk:"custom_error_response" autoflex:",xmlwrapper=Items,omitempty"` + DefaultCacheBehavior fwtypes.ListNestedObjectValueOf[defaultCacheBehaviorModel] `tfsdk:"default_cache_behavior"` + DefaultRootObject types.String `tfsdk:"default_root_object" autoflex:",omitempty"` + DomainName types.String `tfsdk:"domain_name"` + Enabled types.Bool `tfsdk:"enabled"` + ETag types.String `tfsdk:"etag"` + HTTPVersion fwtypes.StringEnum[awstypes.HttpVersion] `tfsdk:"http_version"` + ID types.String `tfsdk:"id"` + InProgressInvalidationBatches types.Int32 `tfsdk:"in_progress_invalidation_batches"` + LastModifiedTime timetypes.RFC3339 `tfsdk:"last_modified_time"` + Origin fwtypes.ListNestedObjectValueOf[originModel] `tfsdk:"origin" autoflex:",xmlwrapper=Items"` + OriginGroup fwtypes.ListNestedObjectValueOf[originGroupModel] `tfsdk:"origin_group" autoflex:",xmlwrapper=Items,omitempty"` + Restrictions fwtypes.ListNestedObjectValueOf[restrictionsModel] `tfsdk:"restrictions"` + Status types.String `tfsdk:"status"` + Tags tftags.Map `tfsdk:"tags"` + TagsAll tftags.Map `tfsdk:"tags_all"` + TenantConfig fwtypes.ListNestedObjectValueOf[tenantConfigModel] `tfsdk:"tenant_config"` + Timeouts timeouts.Value `tfsdk:"timeouts"` + ViewerCertificate fwtypes.ListNestedObjectValueOf[viewerCertificateModel] `tfsdk:"viewer_certificate"` + WebACLID types.String `tfsdk:"web_acl_id" autoflex:",omitempty"` +} + +type originModel struct { + ConnectionAttempts types.Int32 `tfsdk:"connection_attempts"` + ConnectionTimeout types.Int32 `tfsdk:"connection_timeout"` + CustomHeader fwtypes.ListNestedObjectValueOf[customHeaderModel] `tfsdk:"custom_header" autoflex:",xmlwrapper=Items"` + CustomOriginConfig fwtypes.ListNestedObjectValueOf[customOriginConfigModel] `tfsdk:"custom_origin_config" autoflex:",omitempty"` + DomainName types.String `tfsdk:"domain_name"` + ID types.String `tfsdk:"id"` + OriginAccessControlID types.String `tfsdk:"origin_access_control_id" autoflex:",omitempty"` + OriginPath types.String `tfsdk:"origin_path"` + OriginShield fwtypes.ListNestedObjectValueOf[originShieldModel] `tfsdk:"origin_shield" autoflex:",omitempty"` + ResponseCompletionTimeout types.Int32 `tfsdk:"response_completion_timeout"` + VpcOriginConfig fwtypes.ListNestedObjectValueOf[vpcOriginConfigModel] `tfsdk:"vpc_origin_config" autoflex:",omitempty"` +} + +type customHeaderModel struct { + HeaderName types.String `tfsdk:"header_name"` + HeaderValue types.String `tfsdk:"header_value"` +} + +type customOriginConfigModel struct { + HTTPPort types.Int32 `tfsdk:"http_port"` + HTTPSPort types.Int32 `tfsdk:"https_port"` + IPAddressType fwtypes.StringEnum[awstypes.IpAddressType] `tfsdk:"ip_address_type"` + OriginKeepaliveTimeout types.Int32 `tfsdk:"origin_keepalive_timeout"` + OriginReadTimeout types.Int32 `tfsdk:"origin_read_timeout"` + OriginProtocolPolicy fwtypes.StringEnum[awstypes.OriginProtocolPolicy] `tfsdk:"origin_protocol_policy"` + OriginSSLProtocols fwtypes.SetValueOf[fwtypes.StringEnum[awstypes.SslProtocol]] `tfsdk:"origin_ssl_protocols" autoflex:",xmlwrapper=Items"` +} + +type originShieldModel struct { + Enabled types.Bool `tfsdk:"enabled"` + OriginShieldRegion types.String `tfsdk:"origin_shield_region"` +} + +type vpcOriginConfigModel struct { + OriginKeepaliveTimeout types.Int32 `tfsdk:"origin_keepalive_timeout"` + OriginReadTimeout types.Int32 `tfsdk:"origin_read_timeout"` + VpcOriginID types.String `tfsdk:"vpc_origin_id"` +} + +type originGroupModel struct { + FailoverCriteria fwtypes.ListNestedObjectValueOf[failoverCriteriaModel] `tfsdk:"failover_criteria"` + Member fwtypes.ListNestedObjectValueOf[memberModel] `tfsdk:"member" autoflex:",xmlwrapper=Items"` + OriginID types.String `tfsdk:"origin_id"` +} + +type failoverCriteriaModel struct { + StatusCodes fwtypes.SetValueOf[types.Int64] `tfsdk:"status_codes"` +} + +type memberModel struct { + OriginID types.String `tfsdk:"origin_id"` +} + +type defaultCacheBehaviorModel struct { + AllowedMethods fwtypes.ListNestedObjectValueOf[allowedMethodsModel] `tfsdk:"allowed_methods"` + CachePolicyID types.String `tfsdk:"cache_policy_id"` + Compress types.Bool `tfsdk:"compress"` + FieldLevelEncryptionID types.String `tfsdk:"field_level_encryption_id"` + FunctionAssociation fwtypes.ListNestedObjectValueOf[functionAssociationModel] `tfsdk:"function_association" autoflex:",xmlwrapper=Items,omitempty"` + LambdaFunctionAssociation fwtypes.ListNestedObjectValueOf[lambdaFunctionAssociationModel] `tfsdk:"lambda_function_association" autoflex:",xmlwrapper=Items"` + OriginRequestPolicyID types.String `tfsdk:"origin_request_policy_id"` + RealtimeLogConfigARN types.String `tfsdk:"realtime_log_config_arn"` + ResponseHeadersPolicyID types.String `tfsdk:"response_headers_policy_id"` + TargetOriginID types.String `tfsdk:"target_origin_id"` + TrustedKeyGroups fwtypes.ListNestedObjectValueOf[trustedKeyGroupsModel] `tfsdk:"trusted_key_groups" autoflex:",omitempty"` + ViewerProtocolPolicy fwtypes.StringEnum[awstypes.ViewerProtocolPolicy] `tfsdk:"viewer_protocol_policy"` + // Note: SmoothStreaming and TrustedSigners removed - not supported for multi-tenant distributions +} + +type allowedMethodsModel struct { + Items fwtypes.SetValueOf[fwtypes.StringEnum[awstypes.Method]] `tfsdk:"items" autoflex:",xmlwrapper=Items"` + CachedMethods fwtypes.SetValueOf[fwtypes.StringEnum[awstypes.Method]] `tfsdk:"cached_methods" autoflex:",xmlwrapper=Items"` +} + +type cacheBehaviorModel struct { + AllowedMethods fwtypes.ListNestedObjectValueOf[allowedMethodsModel] `tfsdk:"allowed_methods"` + CachePolicyID types.String `tfsdk:"cache_policy_id"` + Compress types.Bool `tfsdk:"compress"` + FieldLevelEncryptionID types.String `tfsdk:"field_level_encryption_id"` + FunctionAssociation fwtypes.ListNestedObjectValueOf[functionAssociationModel] `tfsdk:"function_association" autoflex:",xmlwrapper=Items,omitempty"` + LambdaFunctionAssociation fwtypes.ListNestedObjectValueOf[lambdaFunctionAssociationModel] `tfsdk:"lambda_function_association" autoflex:",xmlwrapper=Items"` + OriginRequestPolicyID types.String `tfsdk:"origin_request_policy_id"` + PathPattern types.String `tfsdk:"path_pattern"` + RealtimeLogConfigARN types.String `tfsdk:"realtime_log_config_arn"` + ResponseHeadersPolicyID types.String `tfsdk:"response_headers_policy_id"` + TargetOriginID types.String `tfsdk:"target_origin_id"` + TrustedKeyGroups fwtypes.ListNestedObjectValueOf[trustedKeyGroupsModel] `tfsdk:"trusted_key_groups" autoflex:",omitempty"` + ViewerProtocolPolicy fwtypes.StringEnum[awstypes.ViewerProtocolPolicy] `tfsdk:"viewer_protocol_policy"` + // Note: SmoothStreaming and TrustedSigners removed - not supported for multi-tenant distributions +} + +type customErrorResponseModel struct { + ErrorCachingMinTtl types.Int64 `tfsdk:"error_caching_min_ttl"` + ErrorCode types.Int64 `tfsdk:"error_code"` + ResponseCode types.String `tfsdk:"response_code"` + ResponsePagePath types.String `tfsdk:"response_page_path"` +} + +type restrictionsModel struct { + GeoRestriction fwtypes.ListNestedObjectValueOf[geoRestrictionModel] `tfsdk:"geo_restriction"` +} + +type geoRestrictionModel struct { + Items fwtypes.SetValueOf[types.String] `tfsdk:"items" autoflex:",omitempty"` + RestrictionType fwtypes.StringEnum[awstypes.GeoRestrictionType] `tfsdk:"restriction_type"` +} + +type viewerCertificateModel struct { + ACMCertificateARN types.String `tfsdk:"acm_certificate_arn"` + CloudfrontDefaultCertificate types.Bool `tfsdk:"cloudfront_default_certificate"` + MinimumProtocolVersion fwtypes.StringEnum[awstypes.MinimumProtocolVersion] `tfsdk:"minimum_protocol_version"` + SSLSupportMethod fwtypes.StringEnum[awstypes.SSLSupportMethod] `tfsdk:"ssl_support_method"` +} + +type functionAssociationModel struct { + EventType fwtypes.StringEnum[awstypes.EventType] `tfsdk:"event_type"` + FunctionARN types.String `tfsdk:"function_arn"` +} + +type lambdaFunctionAssociationModel struct { + EventType fwtypes.StringEnum[awstypes.EventType] `tfsdk:"event_type"` + IncludeBody types.Bool `tfsdk:"include_body"` + LambdaFunctionARN types.String `tfsdk:"lambda_function_arn"` +} + +type tenantConfigModel struct { + ParameterDefinition fwtypes.ListNestedObjectValueOf[parameterDefinitionModel] `tfsdk:"parameter_definition"` +} + +type parameterDefinitionModel struct { + Name types.String `tfsdk:"name"` + Definition fwtypes.ListNestedObjectValueOf[parameterDefinitionSchemaModel] `tfsdk:"definition"` +} + +type parameterDefinitionSchemaModel struct { + StringSchema fwtypes.ListNestedObjectValueOf[stringSchemaConfigModel] `tfsdk:"string_schema"` +} + +type stringSchemaConfigModel struct { + Required types.Bool `tfsdk:"required"` + Comment types.String `tfsdk:"comment"` + DefaultValue types.String `tfsdk:"default_value"` +} + +type trustedKeyGroupsModel struct { + Items fwtypes.ListValueOf[types.String] `tfsdk:"items" autoflex:",xmlwrapper=Items,omitempty"` + Enabled types.Bool `tfsdk:"enabled"` +} + +type activeTrustedKeyGroupsModel struct { + Enabled types.Bool `tfsdk:"enabled"` + Items fwtypes.ListNestedObjectValueOf[kgKeyPairIDsModel] `tfsdk:"items"` +} + +type kgKeyPairIDsModel struct { + KeyGroupID types.String `tfsdk:"key_group_id"` + KeyPairIDs fwtypes.ListValueOf[types.String] `tfsdk:"key_pair_ids" autoflex:",xmlwrapper=Items"` +} diff --git a/internal/service/cloudfront/multitenant_distribution_test.go b/internal/service/cloudfront/multitenant_distribution_test.go new file mode 100644 index 000000000000..e74ee75108a5 --- /dev/null +++ b/internal/service/cloudfront/multitenant_distribution_test.go @@ -0,0 +1,566 @@ +// Copyright IBM Corp. 2014, 2025 +// SPDX-License-Identifier: MPL-2.0 + +package cloudfront_test + +import ( + "context" + "fmt" + "strings" + "testing" + + awstypes "github.com/aws/aws-sdk-go-v2/service/cloudfront/types" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/retry" + tfcloudfront "github.com/hashicorp/terraform-provider-aws/internal/service/cloudfront" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccCloudFrontMultiTenantDistribution_basic(t *testing.T) { + t.Parallel() + + ctx := acctest.Context(t) + var distribution awstypes.Distribution + resourceName := "aws_cloudfront_multitenant_distribution.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.CloudFrontEndpointID) }, + ErrorCheck: acctest.ErrorCheck(t, names.CloudFrontServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMultiTenantDistributionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMultiTenantDistributionConfig_basic(), + Check: resource.ComposeTestCheckFunc( + testAccCheckMultiTenantDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, names.AttrEnabled, acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "tenant_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tenant_config.0.parameter_definition.0.definition.0.string_schema.0.required", acctest.CtTrue), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag"}, + }, + }, + }) +} + +func TestAccCloudFrontMultiTenantDistribution_disappears(t *testing.T) { + ctx := acctest.Context(t) + var distribution awstypes.Distribution + resourceName := "aws_cloudfront_multitenant_distribution.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.CloudFrontEndpointID) }, + ErrorCheck: acctest.ErrorCheck(t, names.CloudFrontServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMultiTenantDistributionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMultiTenantDistributionConfig_basic(), + Check: resource.ComposeTestCheckFunc( + testAccCheckMultiTenantDistributionExists(ctx, resourceName, &distribution), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfcloudfront.ResourceMultiTenantDistribution, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccCloudFrontMultiTenantDistribution_comprehensive(t *testing.T) { + t.Parallel() + + ctx := acctest.Context(t) + var distribution awstypes.Distribution + resourceName := "aws_cloudfront_multitenant_distribution.test" + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.CloudFrontEndpointID) }, + ErrorCheck: acctest.ErrorCheck(t, names.CloudFrontServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMultiTenantDistributionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMultiTenantDistributionConfig_comprehensive(rName, "Comprehensive multi-tenant distribution test", "index.html", false), + Check: resource.ComposeTestCheckFunc( + testAccCheckMultiTenantDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, names.AttrEnabled, acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, names.AttrComment, "Comprehensive multi-tenant distribution test"), + resource.TestCheckResourceAttr(resourceName, "default_root_object", "index.html"), + resource.TestCheckResourceAttr(resourceName, "http_version", "http2"), + + // Check connection_mode is computed + resource.TestCheckResourceAttrSet(resourceName, "connection_mode"), + + // Check multiple origins + resource.TestCheckResourceAttr(resourceName, "origin.#", "1"), + resource.TestCheckResourceAttr(resourceName, "origin.0.id", "custom-origin"), + resource.TestCheckResourceAttr(resourceName, "origin.0.domain_name", "example.com"), + resource.TestCheckResourceAttr(resourceName, "origin.0.origin_path", "/api"), + resource.TestCheckResourceAttr(resourceName, "origin.0.custom_header.#", "1"), + resource.TestCheckResourceAttr(resourceName, "origin.0.custom_header.0.header_name", "X-Custom-Header"), + resource.TestCheckResourceAttr(resourceName, "origin.0.custom_header.0.header_value", "test-value"), + + // Check cache behaviors + resource.TestCheckResourceAttr(resourceName, "cache_behavior.#", "1"), + resource.TestCheckResourceAttr(resourceName, "cache_behavior.0.path_pattern", "/api/*"), + resource.TestCheckResourceAttr(resourceName, "cache_behavior.0.target_origin_id", "custom-origin"), + resource.TestCheckResourceAttr(resourceName, "cache_behavior.0.compress", acctest.CtFalse), + + // Check custom error responses + resource.TestCheckResourceAttr(resourceName, "custom_error_response.#", "1"), + resource.TestCheckResourceAttr(resourceName, "custom_error_response.0.error_code", "404"), + resource.TestCheckResourceAttr(resourceName, "custom_error_response.0.response_code", "200"), + resource.TestCheckResourceAttr(resourceName, "custom_error_response.0.response_page_path", "/404.html"), + + // Check tags + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "2"), + resource.TestCheckResourceAttr(resourceName, "tags.Environment", "test"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + + // Check tenant config with single parameter + resource.TestCheckResourceAttr(resourceName, "tenant_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tenant_config.0.parameter_definition.#", "1"), + ), + }, + { + Config: testAccMultiTenantDistributionConfig_comprehensive(rName, "Updated comprehensive test", "updated.html", true), + Check: resource.ComposeTestCheckFunc( + testAccCheckMultiTenantDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, names.AttrEnabled, acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, names.AttrComment, "Updated comprehensive test"), + resource.TestCheckResourceAttr(resourceName, "default_root_object", "updated.html"), + resource.TestCheckResourceAttr(resourceName, "cache_behavior.0.compress", acctest.CtTrue), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag"}, + }, + }, + }) +} + +func TestAccCloudFrontMultiTenantDistribution_tags(t *testing.T) { + t.Parallel() + + ctx := acctest.Context(t) + var distribution awstypes.Distribution + resourceName := "aws_cloudfront_multitenant_distribution.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.CloudFrontEndpointID) }, + ErrorCheck: acctest.ErrorCheck(t, names.CloudFrontServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMultiTenantDistributionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMultiTenantDistributionConfig_tags(map[string]string{acctest.CtKey1: acctest.CtValue1}), + Check: resource.ComposeTestCheckFunc( + testAccCheckMultiTenantDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "1"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag"}, + }, + { + Config: testAccMultiTenantDistributionConfig_tags(map[string]string{acctest.CtKey1: acctest.CtValue1Updated, acctest.CtKey2: acctest.CtValue2}), + Check: resource.ComposeTestCheckFunc( + testAccCheckMultiTenantDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "2"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1Updated), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + { + Config: testAccMultiTenantDistributionConfig_tags(map[string]string{acctest.CtKey2: acctest.CtValue2}), + Check: resource.ComposeTestCheckFunc( + testAccCheckMultiTenantDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "1"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + }, + }) +} + +func TestAccCloudFrontMultiTenantDistribution_update(t *testing.T) { + t.Parallel() + + ctx := acctest.Context(t) + var distribution awstypes.Distribution + resourceName := "aws_cloudfront_multitenant_distribution.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, names.CloudFrontEndpointID) }, + ErrorCheck: acctest.ErrorCheck(t, names.CloudFrontServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMultiTenantDistributionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccMultiTenantDistributionConfig_update("Initial comment", "http1.1", ""), + Check: resource.ComposeTestCheckFunc( + testAccCheckMultiTenantDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, names.AttrEnabled, acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, names.AttrComment, "Initial comment"), + resource.TestCheckResourceAttr(resourceName, "http_version", "http1.1"), + ), + }, + { + Config: testAccMultiTenantDistributionConfig_update("Updated comment", "http2", "updated.html"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMultiTenantDistributionExists(ctx, resourceName, &distribution), + resource.TestCheckResourceAttr(resourceName, names.AttrEnabled, acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, names.AttrComment, "Updated comment"), + resource.TestCheckResourceAttr(resourceName, "http_version", "http2"), + resource.TestCheckResourceAttr(resourceName, "default_root_object", "updated.html"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag"}, + }, + }, + }) +} + +func testAccCheckMultiTenantDistributionDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).CloudFrontClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_cloudfront_multitenant_distribution" { + continue + } + + _, err := tfcloudfront.FindDistributionByID(ctx, conn, rs.Primary.ID) + + if retry.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("CloudFront Multi-tenant Distribution %s still exists", rs.Primary.ID) + } + + return nil + } +} + +func testAccCheckMultiTenantDistributionExists(ctx context.Context, n string, v *awstypes.Distribution) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).CloudFrontClient(ctx) + + output, err := tfcloudfront.FindDistributionByID(ctx, conn, rs.Primary.ID) + + if err != nil { + return err + } + + *v = *output.Distribution + + return nil + } +} + +func testAccMultiTenantDistributionConfig_basic() string { + return ` +resource "aws_cloudfront_multitenant_distribution" "test" { + enabled = false + comment = "Test multi-tenant distribution" + + origin { + domain_name = "example.com" + id = "example" + + custom_origin_config { + http_port = 80 + https_port = 443 + origin_protocol_policy = "https-only" + origin_ssl_protocols = ["TLSv1.2"] + } + } + + default_cache_behavior { + target_origin_id = "example" + viewer_protocol_policy = "redirect-to-https" + cache_policy_id = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad" # AWS Managed CachingDisabled policy + + allowed_methods { + items = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] + cached_methods = ["GET", "HEAD", "OPTIONS"] + } + } + + viewer_certificate { + cloudfront_default_certificate = true + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } + + tenant_config { + parameter_definition { + name = "origin_domain" + definition { + string_schema { + required = true + comment = "Origin domain parameter for tenants" + } + } + } + } +} +` +} + +func testAccMultiTenantDistributionConfig_comprehensive(rName, comment, defaultRootObject string, compress bool) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q + force_destroy = true +} + +resource "aws_cloudfront_origin_access_control" "test" { + name = %[1]q + origin_access_control_origin_type = "s3" + signing_behavior = "always" + signing_protocol = "sigv4" +} + +resource "aws_cloudfront_multitenant_distribution" "test" { + enabled = false + comment = %[2]q + default_root_object = %[3]q + + origin { + domain_name = "example.com" + id = "custom-origin" + origin_path = "/api" + + custom_header { + header_name = "X-Custom-Header" + header_value = "test-value" + } + + custom_origin_config { + http_port = 80 + https_port = 443 + origin_protocol_policy = "https-only" + origin_ssl_protocols = ["TLSv1.2"] + } + } + + default_cache_behavior { + target_origin_id = "custom-origin" + viewer_protocol_policy = "redirect-to-https" + cache_policy_id = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad" # AWS Managed CachingDisabled policy + + allowed_methods { + items = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] + cached_methods = ["GET", "HEAD"] + } + } + + # Single cache behavior + cache_behavior { + path_pattern = "/api/*" + target_origin_id = "custom-origin" + viewer_protocol_policy = "https-only" + cache_policy_id = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad" + compress = %[4]t + + allowed_methods { + items = ["GET", "HEAD", "OPTIONS"] + cached_methods = ["GET", "HEAD"] + } + } + + # Custom error response + custom_error_response { + error_code = 404 + response_code = "200" + response_page_path = "/404.html" + } + + viewer_certificate { + cloudfront_default_certificate = true + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } + + # Simplified tenant config + tenant_config { + parameter_definition { + name = "origin_domain" + definition { + string_schema { + required = true + comment = "Origin domain parameter for tenants" + } + } + } + } + + tags = { + Environment = "test" + Name = %[1]q + } +} +`, rName, comment, defaultRootObject, compress) +} + +func testAccMultiTenantDistributionConfig_tags(tags map[string]string) string { + var tagLines []string + for key, value := range tags { + tagLines = append(tagLines, fmt.Sprintf(" %q = %q", key, value)) + } + tagConfig := fmt.Sprintf(" tags = {\n%s\n }", strings.Join(tagLines, "\n")) + + return fmt.Sprintf(` +resource "aws_cloudfront_multitenant_distribution" "test" { + enabled = false + comment = "Test multi-tenant distribution for tags" + + origin { + domain_name = "example.com" + id = "example" + + custom_origin_config { + http_port = 80 + https_port = 443 + origin_protocol_policy = "https-only" + origin_ssl_protocols = ["TLSv1.2"] + } + } + + default_cache_behavior { + target_origin_id = "example" + viewer_protocol_policy = "redirect-to-https" + cache_policy_id = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad" # AWS Managed CachingDisabled policy + + allowed_methods { + items = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] + cached_methods = ["GET", "HEAD", "OPTIONS"] + } + } + + viewer_certificate { + cloudfront_default_certificate = true + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } + + tenant_config { + parameter_definition { + name = "origin_domain" + definition { + string_schema { + required = true + comment = "Origin domain parameter for tenants" + } + } + } + } + +%s +} +`, tagConfig) +} + +func testAccMultiTenantDistributionConfig_update(comment, httpVersion, defaultRootObject string) string { + defaultRootObjectConfig := "" + if defaultRootObject != "" { + defaultRootObjectConfig = fmt.Sprintf("default_root_object = %q", defaultRootObject) + } + + return fmt.Sprintf(` +resource "aws_cloudfront_multitenant_distribution" "test" { + enabled = false + comment = %[1]q + http_version = %[2]q + %[3]s + + origin { + domain_name = "example.com" + id = "example" + + custom_origin_config { + http_port = 80 + https_port = 443 + origin_protocol_policy = "https-only" + origin_ssl_protocols = ["TLSv1.2"] + } + } + + default_cache_behavior { + target_origin_id = "example" + viewer_protocol_policy = "redirect-to-https" + cache_policy_id = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad" # AWS Managed CachingDisabled policy + + allowed_methods { + items = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] + cached_methods = ["GET", "HEAD"] + } + } + + viewer_certificate { + cloudfront_default_certificate = true + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } + + tenant_config { + parameter_definition { + name = "origin_domain" + definition { + string_schema { + required = true + comment = "Updated origin domain parameter for tenants" + } + } + } + } +} +`, comment, httpVersion, defaultRootObjectConfig) +} diff --git a/internal/service/cloudfront/service_package_gen.go b/internal/service/cloudfront/service_package_gen.go index 7b2cfbc38613..a6f8e9737c1d 100644 --- a/internal/service/cloudfront/service_package_gen.go +++ b/internal/service/cloudfront/service_package_gen.go @@ -60,6 +60,15 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*inttypes.Ser WrappedImport: true, }, }, + { + Factory: newMultiTenantDistributionResource, + TypeName: "aws_cloudfront_multitenant_distribution", + Name: "Multi-tenant Distribution", + Tags: unique.Make(inttypes.ServicePackageResourceTags{ + IdentifierAttribute: names.AttrARN, + }), + Region: unique.Make(inttypes.ResourceRegionDisabled()), + }, { Factory: newTrustStoreResource, TypeName: "aws_cloudfront_trust_store", diff --git a/internal/service/ecs/capacity_provider.go b/internal/service/ecs/capacity_provider.go index d51aa0ac069b..348b3e557731 100644 --- a/internal/service/ecs/capacity_provider.go +++ b/internal/service/ecs/capacity_provider.go @@ -180,6 +180,13 @@ func resourceCapacityProvider() *schema.Resource { Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "capacity_option_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: awstypes.CapacityOptionTypeOnDemand, + ValidateDiagFunc: enum.Validate[awstypes.CapacityOptionType](), + }, "ec2_instance_profile_arn": { Type: schema.TypeString, Required: true, @@ -1006,6 +1013,10 @@ func expandInstanceLaunchTemplateCreate(tfList []any) *awstypes.InstanceLaunchTe tfMap := tfList[0].(map[string]any) apiObject := &awstypes.InstanceLaunchTemplate{} + if v, ok := tfMap["capacity_option_type"].(string); ok && v != "" { + apiObject.CapacityOptionType = awstypes.CapacityOptionType(v) + } + if v, ok := tfMap["ec2_instance_profile_arn"].(string); ok && v != "" { apiObject.Ec2InstanceProfileArn = aws.String(v) } @@ -1413,6 +1424,7 @@ func flattenInstanceLaunchTemplate(template *awstypes.InstanceLaunchTemplate) [] tfMap := map[string]any{ "ec2_instance_profile_arn": aws.ToString(template.Ec2InstanceProfileArn), "monitoring": template.Monitoring, + "capacity_option_type": template.CapacityOptionType, } if template.InstanceRequirements != nil { diff --git a/internal/service/ecs/capacity_provider_test.go b/internal/service/ecs/capacity_provider_test.go index e5035a630736..30719427b470 100644 --- a/internal/service/ecs/capacity_provider_test.go +++ b/internal/service/ecs/capacity_provider_test.go @@ -293,6 +293,7 @@ func TestAccECSCapacityProvider_createManagedInstancesProvider_basic(t *testing. resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.#", "1"), resource.TestCheckResourceAttrPair(resourceName, "managed_instances_provider.0.infrastructure_role_arn", "aws_iam_role.test", names.AttrARN), resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.capacity_option_type", "ON_DEMAND"), resource.TestCheckResourceAttrPair(resourceName, "managed_instances_provider.0.instance_launch_template.0.ec2_instance_profile_arn", "aws_iam_instance_profile.test", names.AttrARN), resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.network_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.network_configuration.0.subnets.#", "2"), @@ -329,6 +330,7 @@ func TestAccECSCapacityProvider_createManagedInstancesProvider_withInstanceRequi Check: resource.ComposeAggregateTestCheckFunc( testAccCheckCapacityProviderExists(ctx, resourceName, &provider), resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.capacity_option_type", "SPOT"), resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.#", "1"), resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.vcpu_count.#", "1"), resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.instance_requirements.0.vcpu_count.0.min", "2"), @@ -457,6 +459,39 @@ func TestAccECSCapacityProvider_createManagedInstancesProvider_withInfrastructur }) } +func TestAccECSCapacityProvider_managedInstancesProvider_capacityOptionTypeReplacement(t *testing.T) { + ctx := acctest.Context(t) + var provider1, provider2 awstypes.CapacityProvider + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_ecs_capacity_provider.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckCapacityProviderDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccCapacityProviderConfig_managedInstancesProvider_capacityOptionType(rName, "ON_DEMAND"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckCapacityProviderExists(ctx, resourceName, &provider1), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.capacity_option_type", "ON_DEMAND"), + ), + }, + { + Config: testAccCapacityProviderConfig_managedInstancesProvider_capacityOptionType(rName, "SPOT"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckCapacityProviderExists(ctx, resourceName, &provider2), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.#", "1"), + resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.instance_launch_template.0.capacity_option_type", "SPOT"), + testAccCheckCapacityProviderRecreated(&provider1, &provider2), + ), + }, + }, + }) +} + func testAccCheckCapacityProviderDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).ECSClient(ctx) @@ -848,6 +883,7 @@ resource "aws_ecs_capacity_provider" "test" { propagate_tags = "NONE" instance_launch_template { + capacity_option_type = "SPOT" ec2_instance_profile_arn = aws_iam_instance_profile.test.arn network_configuration { @@ -982,3 +1018,51 @@ resource "aws_ecs_capacity_provider" "test" { } `, rName, scaleInAfter)) } + +func testAccCheckCapacityProviderRecreated(before, after *awstypes.CapacityProvider) resource.TestCheckFunc { + return func(s *terraform.State) error { + if before.CapacityProviderArn != nil && after.CapacityProviderArn != nil { + if *before.CapacityProviderArn == *after.CapacityProviderArn { + return fmt.Errorf("ECS Capacity Provider was not recreated") + } + } + return nil + } +} + +func testAccCapacityProviderConfig_managedInstancesProvider_capacityOptionType(rName, capacityOptionType string) string { + return acctest.ConfigCompose(testAccCapacityProviderConfig_managedInstancesProvider_base(rName), fmt.Sprintf(` +resource "aws_ecs_capacity_provider" "test" { + lifecycle { + create_before_destroy = true + } + + name = %[2]q + cluster = aws_ecs_cluster.test.name + + managed_instances_provider { + infrastructure_role_arn = aws_iam_role.test.arn + + instance_launch_template { + capacity_option_type = %[2]q + ec2_instance_profile_arn = aws_iam_instance_profile.test.arn + + network_configuration { + subnets = aws_subnet.test[*].id + security_groups = [aws_security_group.test.id] + } + + instance_requirements { + vcpu_count { + min = 1 + } + + memory_mib { + min = 1024 + } + } + } + } +} +`, rName, capacityOptionType)) +} diff --git a/tools/tfsdk2fw/go.mod b/tools/tfsdk2fw/go.mod index 8d4397bb7716..5f5c54c58c1c 100644 --- a/tools/tfsdk2fw/go.mod +++ b/tools/tfsdk2fw/go.mod @@ -45,9 +45,9 @@ require ( github.com/aws/aws-sdk-go-v2/service/applicationsignals v1.18.3 // indirect github.com/aws/aws-sdk-go-v2/service/appmesh v1.35.7 // indirect github.com/aws/aws-sdk-go-v2/service/apprunner v1.39.9 // indirect - github.com/aws/aws-sdk-go-v2/service/appstream v1.52.5 // indirect + github.com/aws/aws-sdk-go-v2/service/appstream v1.53.0 // indirect github.com/aws/aws-sdk-go-v2/service/appsync v1.53.0 // indirect - github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.18 // indirect + github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.3.0 // indirect github.com/aws/aws-sdk-go-v2/service/arczonalshift v1.22.18 // indirect github.com/aws/aws-sdk-go-v2/service/athena v1.56.4 // indirect github.com/aws/aws-sdk-go-v2/service/auditmanager v1.46.7 // indirect @@ -58,14 +58,14 @@ require ( github.com/aws/aws-sdk-go-v2/service/bcmdataexports v1.12.9 // indirect github.com/aws/aws-sdk-go-v2/service/bedrock v1.53.0 // indirect github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.52.2 // indirect - github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.15.2 // indirect + github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.16.0 // indirect github.com/aws/aws-sdk-go-v2/service/billing v1.9.4 // indirect github.com/aws/aws-sdk-go-v2/service/budgets v1.42.3 // indirect github.com/aws/aws-sdk-go-v2/service/chatbot v1.14.16 // indirect github.com/aws/aws-sdk-go-v2/service/chime v1.41.7 // indirect github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.16 // indirect github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.28.8 // indirect - github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.38.2 // indirect + github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.39.0 // indirect github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.15 // indirect github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.29.8 // indirect github.com/aws/aws-sdk-go-v2/service/cloudformation v1.71.4 // indirect @@ -117,10 +117,10 @@ require ( github.com/aws/aws-sdk-go-v2/service/drs v1.36.8 // indirect github.com/aws/aws-sdk-go-v2/service/dsql v1.12.3 // indirect github.com/aws/aws-sdk-go-v2/service/dynamodb v1.53.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ec2 v1.277.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ecr v1.54.4 // indirect + github.com/aws/aws-sdk-go-v2/service/ec2 v1.278.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.55.0 // indirect github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.8 // indirect - github.com/aws/aws-sdk-go-v2/service/ecs v1.69.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0 // indirect github.com/aws/aws-sdk-go-v2/service/efs v1.41.9 // indirect github.com/aws/aws-sdk-go-v2/service/eks v1.76.3 // indirect github.com/aws/aws-sdk-go-v2/service/elasticache v1.51.8 // indirect @@ -161,7 +161,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 // indirect github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.26.9 // indirect github.com/aws/aws-sdk-go-v2/service/invoicing v1.9.3 // indirect - github.com/aws/aws-sdk-go-v2/service/iot v1.70.0 // indirect + github.com/aws/aws-sdk-go-v2/service/iot v1.71.0 // indirect github.com/aws/aws-sdk-go-v2/service/ivs v1.48.9 // indirect github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.15 // indirect github.com/aws/aws-sdk-go-v2/service/kafka v1.46.5 // indirect @@ -206,7 +206,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/oam v1.23.10 // indirect github.com/aws/aws-sdk-go-v2/service/observabilityadmin v1.9.1 // indirect github.com/aws/aws-sdk-go-v2/service/odb v1.7.0 // indirect - github.com/aws/aws-sdk-go-v2/service/opensearch v1.56.0 // indirect + github.com/aws/aws-sdk-go-v2/service/opensearch v1.57.0 // indirect github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.28.1 // indirect github.com/aws/aws-sdk-go-v2/service/organizations v1.50.0 // indirect github.com/aws/aws-sdk-go-v2/service/osis v1.21.9 // indirect @@ -259,7 +259,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.39.21 // indirect github.com/aws/aws-sdk-go-v2/service/servicequotas v1.34.0 // indirect github.com/aws/aws-sdk-go-v2/service/ses v1.34.17 // indirect - github.com/aws/aws-sdk-go-v2/service/sesv2 v1.58.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sesv2 v1.59.0 // indirect github.com/aws/aws-sdk-go-v2/service/sfn v1.40.5 // indirect github.com/aws/aws-sdk-go-v2/service/shield v1.34.16 // indirect github.com/aws/aws-sdk-go-v2/service/signer v1.32.0 // indirect @@ -270,9 +270,9 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssmcontacts v1.31.9 // indirect github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.15 // indirect github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.16 // indirect - github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ssmsap v1.26.0 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 // indirect - github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.12 // indirect + github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.13 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 // indirect github.com/aws/aws-sdk-go-v2/service/storagegateway v1.43.9 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 // indirect diff --git a/tools/tfsdk2fw/go.sum b/tools/tfsdk2fw/go.sum index 57a54c1475d0..22279e101fde 100644 --- a/tools/tfsdk2fw/go.sum +++ b/tools/tfsdk2fw/go.sum @@ -77,12 +77,12 @@ github.com/aws/aws-sdk-go-v2/service/appmesh v1.35.7 h1:nW1jsdX6e1VT0vqthwJztdwg github.com/aws/aws-sdk-go-v2/service/appmesh v1.35.7/go.mod h1:9H7Oyy2M/EiRYzY4MfkrjPuIB2+LLLx1eCxTmQUyV70= github.com/aws/aws-sdk-go-v2/service/apprunner v1.39.9 h1:3MgcobMoBK3IqP2TbuySbdjc79EYCmN+ZRCKQD6d0GU= github.com/aws/aws-sdk-go-v2/service/apprunner v1.39.9/go.mod h1:n6b+O7QJ6E37dXZYPdLnC4S7Cc5HUYOQPZijLeDKIGY= -github.com/aws/aws-sdk-go-v2/service/appstream v1.52.5 h1:06hhJyKERzoGJ7wFPqoUUdEQ1PLygC8+mRoO7tcU4QA= -github.com/aws/aws-sdk-go-v2/service/appstream v1.52.5/go.mod h1:bBWE9r4oj7moGUvEyihhpcLcSAP4HXsb1cYFOqoXrrc= +github.com/aws/aws-sdk-go-v2/service/appstream v1.53.0 h1:ik7TXyRrtDpJiCOnuxFNGkEFL+qwvPiRJxqj3ytTet8= +github.com/aws/aws-sdk-go-v2/service/appstream v1.53.0/go.mod h1:bBWE9r4oj7moGUvEyihhpcLcSAP4HXsb1cYFOqoXrrc= github.com/aws/aws-sdk-go-v2/service/appsync v1.53.0 h1:8I7CLKciARX91L7cKj1horWon1/Z1eGG9E1ZvjW7HwA= github.com/aws/aws-sdk-go-v2/service/appsync v1.53.0/go.mod h1:iLJM8Rf5z8Td/Zvz5qv/XxP4h4E9aoBNXDUVoryy110= -github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.18 h1:phqqCBtQ7lVakKqqxijj8c91E2oq2Tt4Pz4x2EbNwgs= -github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.2.18/go.mod h1:vcL9EzuMufqrNk+Ns3vT7yWv9rm9n4RYnBzfNrInggE= +github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.3.0 h1:56LbI4Uo5r65xIkdde6TtlyBU2K06igoenqqBvc4rT4= +github.com/aws/aws-sdk-go-v2/service/arcregionswitch v1.3.0/go.mod h1:vcL9EzuMufqrNk+Ns3vT7yWv9rm9n4RYnBzfNrInggE= github.com/aws/aws-sdk-go-v2/service/arczonalshift v1.22.18 h1:Ds0ydJxnG4lvRCIm/IdzgrVf3dyHLAfCWjRffAr2Mwo= github.com/aws/aws-sdk-go-v2/service/arczonalshift v1.22.18/go.mod h1:oYmUhJIeABHyxIpxhZqJ+7jaCXeV+qxtTQ8FoVyMsRg= github.com/aws/aws-sdk-go-v2/service/athena v1.56.4 h1:kCHAYlcGKCKKDGMRUfnY6pI992vC3UdA3+oPdfDBSHE= @@ -103,8 +103,8 @@ github.com/aws/aws-sdk-go-v2/service/bedrock v1.53.0 h1:cmQBS5qaRe1yV7eL7shROYjB github.com/aws/aws-sdk-go-v2/service/bedrock v1.53.0/go.mod h1:LV2LELzMlToA6tauFUTYr0iy20Gp4TKz2vMQYaKq0Pw= github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.52.2 h1:jrOALh0fIx8kUfesQS4jMkXGPDQ2xKt5bbREgsoHcmw= github.com/aws/aws-sdk-go-v2/service/bedrockagent v1.52.2/go.mod h1:hRzcNxU8BOG5ijgeMDLyw0sx4fBOxrjPDB/DnDK6X1M= -github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.15.2 h1:UduoRYiZpRrlXvd9YsRJ5F0BfpTWD71hEUs1u3JNQk4= -github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.15.2/go.mod h1:3zWDBnJEUh72XdC7iEqdCSwPwDuveVsKTmtThuGwC2s= +github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.16.0 h1:ENycjQ5LASzpc3+izF684aXHPndd+SHCf/D2fK8aro0= +github.com/aws/aws-sdk-go-v2/service/bedrockagentcorecontrol v1.16.0/go.mod h1:3zWDBnJEUh72XdC7iEqdCSwPwDuveVsKTmtThuGwC2s= github.com/aws/aws-sdk-go-v2/service/billing v1.9.4 h1:IMiahVCNEL61U2HfsRdvrdNQ3gyj4qN5cJrogppduPU= github.com/aws/aws-sdk-go-v2/service/billing v1.9.4/go.mod h1:DbptyYoS5RY5n7oFKdqkXbYvuxqhp/Z5QMohp6uKsII= github.com/aws/aws-sdk-go-v2/service/budgets v1.42.3 h1:SWmlAqhAeh9ByGn56CLqJEEFwd1tsDM1t9ojTcxpnvo= @@ -117,8 +117,8 @@ github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.16 h1:Of5xU2ny github.com/aws/aws-sdk-go-v2/service/chimesdkmediapipelines v1.26.16/go.mod h1:Fk1uZOvXuciwTTxX6qWudPL2v4rH4VGuHbqfKdC30ew= github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.28.8 h1:0hxpLzWPOFNofMbyOSZltrD8IvrtpOjBjQUpmZRjUfI= github.com/aws/aws-sdk-go-v2/service/chimesdkvoice v1.28.8/go.mod h1:r7zkhVfcXyRi8L7AM6iaZiQaJVM82xkitxsq8e3Yvs0= -github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.38.2 h1:6l7T7NzEIX1H4mshRGlrUKBsspYZf1v6wLpbbgAQIcQ= -github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.38.2/go.mod h1:cIHgZyLi8PuZkq2lsJfeHtC87kitSmbsNvgxW7HAM3U= +github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.39.0 h1:1rniE6ggSl4WNuHhChB6wKtQPJkSuGBfR2+HGQyB9/Y= +github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.39.0/go.mod h1:cIHgZyLi8PuZkq2lsJfeHtC87kitSmbsNvgxW7HAM3U= github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.15 h1:VKLLGKz1jfsQMf/tCjqiqzwha+5n8bcndAqH4/yMJEk= github.com/aws/aws-sdk-go-v2/service/cloud9 v1.33.15/go.mod h1:6eUG6qcUwAACFF/b0fIlZF0sSUwRwY2yJaJ0KoRNjF8= github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.29.8 h1:Dmsh7h8g+P7lA3QLkdmr/lm56tlRIqgXoaxeXf6um5g= @@ -221,14 +221,14 @@ github.com/aws/aws-sdk-go-v2/service/dsql v1.12.3 h1:RoFmi9T73/kXMKPuATxor3ORCVZ github.com/aws/aws-sdk-go-v2/service/dsql v1.12.3/go.mod h1:gO9U7P8RS8V+2eWjNcdSa4L5v0uDYju7IVr/malpnoo= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.53.5 h1:mSBrQCXMjEvLHsYyJVbN8QQlcITXwHEuu+8mX9e2bSo= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.53.5/go.mod h1:eEuD0vTf9mIzsSjGBFWIaNQwtH5/mzViJOVQfnMY5DE= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.277.0 h1:RHJSkRXDGkAKrV4CTEsZsZkOmSpxXKO4aKx4rXd94K4= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.277.0/go.mod h1:Wg68QRgy2gEGGdmTPU/UbVpdv8sM14bUZmF64KFwAsY= -github.com/aws/aws-sdk-go-v2/service/ecr v1.54.4 h1:4THfkydiKvFeOFlfY1ABHe4Nsj+Jy6S6tHBqUAojY0M= -github.com/aws/aws-sdk-go-v2/service/ecr v1.54.4/go.mod h1:8n8vVvu7LzveA0or4iWQwNndJStpKOX4HiVHM5jax2U= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.278.0 h1:Cx/Rs2zaG30Dn4QMvUGC5rCAZagA8heta0TWAdBE/Xc= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.278.0/go.mod h1:Wg68QRgy2gEGGdmTPU/UbVpdv8sM14bUZmF64KFwAsY= +github.com/aws/aws-sdk-go-v2/service/ecr v1.55.0 h1:Mz6rvVhqmqGPzZNDLolW9IwPzhL/V+QS+dvX+vm/zh8= +github.com/aws/aws-sdk-go-v2/service/ecr v1.55.0/go.mod h1:8n8vVvu7LzveA0or4iWQwNndJStpKOX4HiVHM5jax2U= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.8 h1:2QlSMAimXfMKYRFlxGkbRMRtKN3OqIOB/CfxMcVdzjM= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.8/go.mod h1:esoP/SqS8FVryu4PPLX6ND925slId/IxPxvUBKuBqRk= -github.com/aws/aws-sdk-go-v2/service/ecs v1.69.5 h1:5nkhwt0d/gjuT3AQ2LUK0aFRNB3MGlzB2elqy/ZsKP4= -github.com/aws/aws-sdk-go-v2/service/ecs v1.69.5/go.mod h1:LQMlcWBoiFVD3vUVEz42ST0yTiaDujv2dRE6sXt1yPE= +github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0 h1:IZpZatHsscdOKjwmDXC6idsCXmm3F/obutAUNjnX+OM= +github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0/go.mod h1:LQMlcWBoiFVD3vUVEz42ST0yTiaDujv2dRE6sXt1yPE= github.com/aws/aws-sdk-go-v2/service/efs v1.41.9 h1:uHir2myVtdCfpe6ZcmOgmkUFRTUq2mKfhvfQpBcrry4= github.com/aws/aws-sdk-go-v2/service/efs v1.41.9/go.mod h1:qOhKklI/Hn44U8oZPT16hdCAAjap4PWmCkwDm5YNVPY= github.com/aws/aws-sdk-go-v2/service/eks v1.76.3 h1:840uwcJTIwrMPLuEUQVFKZbPgwnYzc5WDyXMiMYm5Ts= @@ -309,8 +309,8 @@ github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.26.9 h1:TMnrStLgz43BqBtf github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.26.9/go.mod h1:TCzNbB10tslhTf7ZEJafSIaFfdwAzPmO/3V1+e/Dsrw= github.com/aws/aws-sdk-go-v2/service/invoicing v1.9.3 h1:wxTRhCgKwZlHHHaWyCLZzfXc0Z7JkQEf5Glv74HbjuA= github.com/aws/aws-sdk-go-v2/service/invoicing v1.9.3/go.mod h1:AXcwyknhBgVBjG0ra2Jo+KDHHBgk9iOYDx/qndgU0jo= -github.com/aws/aws-sdk-go-v2/service/iot v1.70.0 h1:e9LtnXmY7NQ5+JU/uaKZbDsavZTHWV1HtwSKXelwVhc= -github.com/aws/aws-sdk-go-v2/service/iot v1.70.0/go.mod h1:y/GDsulMROoS3zX2iGWhVtsXQ1YXWPinm3mjqxmWYWY= +github.com/aws/aws-sdk-go-v2/service/iot v1.71.0 h1:6KvLqcT4EqZwbcgEgJ5g7brurJL5ZutjR27QKgWxx0U= +github.com/aws/aws-sdk-go-v2/service/iot v1.71.0/go.mod h1:y/GDsulMROoS3zX2iGWhVtsXQ1YXWPinm3mjqxmWYWY= github.com/aws/aws-sdk-go-v2/service/ivs v1.48.9 h1:6C64paCnqf1w9nrrNB0XyVI34HIaApe9EMXazi7Jl6I= github.com/aws/aws-sdk-go-v2/service/ivs v1.48.9/go.mod h1:+gda20Gu0g3caQSrAof5V+Kyl07F6N0cVDvFfOHMru0= github.com/aws/aws-sdk-go-v2/service/ivschat v1.21.15 h1:Z5cflX4kjGZLiGLfnd/7JRCYQeSlhAbZqcEz8GIoJn0= @@ -399,8 +399,8 @@ github.com/aws/aws-sdk-go-v2/service/observabilityadmin v1.9.1 h1:EOLU6qXaLwCuJn github.com/aws/aws-sdk-go-v2/service/observabilityadmin v1.9.1/go.mod h1:oI09oxkji3dh/cPHWSMOVISPdlY3S4N1HO/NRAgTm+o= github.com/aws/aws-sdk-go-v2/service/odb v1.7.0 h1:VygXCW2iVsTyGTHxCfN6YXFTxNYDcoTBA9dp9c0RDyY= github.com/aws/aws-sdk-go-v2/service/odb v1.7.0/go.mod h1:j2q8xXADdmPeBiXj4MCrqas5NuZRQRSwm45PxcS2Z3A= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.56.0 h1:5fEX9xgasulnog9z/s2tfA1HzxoOcTzjFNZxbRvURYw= -github.com/aws/aws-sdk-go-v2/service/opensearch v1.56.0/go.mod h1:0VgDf/vMiSyGBTP1OrqqdWLpbAJQd9wKfFpLtWffrFQ= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.57.0 h1:O+FQ+Jfe8VPEj8ehKSUvfMeUdnnGaAU1N5TvldLMNwk= +github.com/aws/aws-sdk-go-v2/service/opensearch v1.57.0/go.mod h1:0VgDf/vMiSyGBTP1OrqqdWLpbAJQd9wKfFpLtWffrFQ= github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.28.1 h1:3UM9bGhz7+3f/ldvj8JPkqdq5q7A7iqscExCaBjQe4A= github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.28.1/go.mod h1:HpoYvkQFTR3IwYDCJQrxOGqtQpwWYF8O6a7YeDjfyCo= github.com/aws/aws-sdk-go-v2/service/organizations v1.50.0 h1:HGC9bFaqjHWWD8cnNYVbQIrkzZwRJs2UxqdrGnaeSvE= @@ -505,8 +505,8 @@ github.com/aws/aws-sdk-go-v2/service/servicequotas v1.34.0 h1:hZ5/DIZpiYtHxnNk18 github.com/aws/aws-sdk-go-v2/service/servicequotas v1.34.0/go.mod h1:zfrr8eV7yr3nakr+K+22q+wA3t5ApjqTiNSCbEzK7fM= github.com/aws/aws-sdk-go-v2/service/ses v1.34.17 h1:XR7CtY988tck2Bhuy1JP4FsV8z0OAwjuh+gb7nAy8/M= github.com/aws/aws-sdk-go-v2/service/ses v1.34.17/go.mod h1:2CspeTVldnJdRixX36SzTZuoIpjyKlfeXyB7/JB5KGk= -github.com/aws/aws-sdk-go-v2/service/sesv2 v1.58.0 h1:5Rv2iCikjKo1pU2E8EL0uVns2/5V2ibb6oJ3QAL43WI= -github.com/aws/aws-sdk-go-v2/service/sesv2 v1.58.0/go.mod h1:p0iz0in3/mt3aS2Ovk3aKeOq5vwM/V3prQG9nlBO/OM= +github.com/aws/aws-sdk-go-v2/service/sesv2 v1.59.0 h1:HQYog9wJM8D9aF0bOVzzWbjpWZ7exyjc3rLb7P8Qb8E= +github.com/aws/aws-sdk-go-v2/service/sesv2 v1.59.0/go.mod h1:p0iz0in3/mt3aS2Ovk3aKeOq5vwM/V3prQG9nlBO/OM= github.com/aws/aws-sdk-go-v2/service/sfn v1.40.5 h1:nhPlRp9oCZOh1M/4zVn4pqguzEJ3Q3emnyS9k8sW8u8= github.com/aws/aws-sdk-go-v2/service/sfn v1.40.5/go.mod h1:dfVRuB5XudlLMY6PVMu4T2lmfXYMARapmdc2/cUN2Mw= github.com/aws/aws-sdk-go-v2/service/shield v1.34.16 h1:O4ji2ueMOLBwd81y1PyfMbIj5o83fVw3ICR0iIh/Xbc= @@ -527,12 +527,12 @@ github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.15 h1:qsrylJR2awA00U/c+2 github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.39.15/go.mod h1:xQp5IcwUQqzB9UR6saKM6inR+8sng6RXrUOVBoFYiCo= github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.16 h1:9DKnEt9pWeBYWmy2gCyAtgKtfSg54dErFG9/W+Woe+I= github.com/aws/aws-sdk-go-v2/service/ssmquicksetup v1.8.16/go.mod h1:NquyVWFm19AdsR+UrvxYhUWPVBaJ1G/FFclxDRjkbfg= -github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.15 h1:RFfnrJ4kCHhZrybUAEAXgLBRkTMXFnZGOacjHZi2/us= -github.com/aws/aws-sdk-go-v2/service/ssmsap v1.25.15/go.mod h1:bKHP0BahB1yKINXTjQ/iBDMl82wodt4aGpdqefZF2Xw= +github.com/aws/aws-sdk-go-v2/service/ssmsap v1.26.0 h1:kC7Lx4jIlVSgEQ2XEI/Bw4Gum+jDwE47TiS5EbuU1Ro= +github.com/aws/aws-sdk-go-v2/service/ssmsap v1.26.0/go.mod h1:bKHP0BahB1yKINXTjQ/iBDMl82wodt4aGpdqefZF2Xw= github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 h1:aM/Q24rIlS3bRAhTyFurowU8A0SMyGDtEOY/l/s/1Uw= github.com/aws/aws-sdk-go-v2/service/sso v1.30.8/go.mod h1:+fWt2UHSb4kS7Pu8y+BMBvJF0EWx+4H0hzNwtDNRTrg= -github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.12 h1:5uwMt+itx/rZLocKDf88XfUbBqy+YvudvkMRsUcixlA= -github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.12/go.mod h1:ETe6RIU0wxLv9cYh5EEXyExIeZj2/xgEv6eRKLboBJM= +github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.13 h1:Ryd6BIcvbVrnru3ikEzSxs0rBePGZwZCGYHg0SQaLhA= +github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.36.13/go.mod h1:ETe6RIU0wxLv9cYh5EEXyExIeZj2/xgEv6eRKLboBJM= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 h1:AHDr0DaHIAo8c9t1emrzAlVDFp+iMMKnPdYy6XO4MCE= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12/go.mod h1:GQ73XawFFiWxyWXMHWfhiomvP3tXtdNar/fi8z18sx0= github.com/aws/aws-sdk-go-v2/service/storagegateway v1.43.9 h1:nCEsDXS7zjGluay/uiybSRbO2rnBR3b+cvINB4hNbcY= diff --git a/website/docs/r/cloudfront_multitenant_distribution.html.markdown b/website/docs/r/cloudfront_multitenant_distribution.html.markdown new file mode 100644 index 000000000000..6505c21206e1 --- /dev/null +++ b/website/docs/r/cloudfront_multitenant_distribution.html.markdown @@ -0,0 +1,288 @@ +--- +subcategory: "CloudFront" +layout: "aws" +page_title: "AWS: aws_cloudfront_multitenant_distribution" +description: |- + Provides a CloudFront multi-tenant distribution resource. +--- + +# Resource: aws_cloudfront_multitenant_distribution + +Creates an Amazon CloudFront multi-tenant distribution. + +Multi-tenant distributions are a specialized type of CloudFront distribution designed for multi-tenant applications. They have specific limitations and requirements compared to standard CloudFront distributions. + +For information about CloudFront multi-tenant distributions, see the [Amazon CloudFront Developer Guide](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/). + +~> **NOTE:** CloudFront distributions take about 15 minutes to reach a deployed state after creation or modification. During this time, deletes to resources will be blocked. If you need to delete a distribution that is enabled and you do not want to wait, you need to use the `retain_on_delete` flag. + +## Multi-tenant Distribution Limitations + +Multi-tenant distributions have the following limitations compared to standard CloudFront distributions: + +- **Connection Mode**: Automatically set to `tenant-only` and cannot be modified +- **Cache Policies**: Must use cache policies instead of legacy TTL settings +- **Trusted Key Groups**: Must use trusted key groups instead of trusted signers +- **WAF Integration**: Only supports WAF v2 web ACLs +- **Certificate Management**: Must use ACM certificates (IAM certificates not supported) + +### Unsupported Attributes + +The following attributes that are available in standard CloudFront distributions are **not supported** for multi-tenant distributions: + +- `active_trusted_signers` - Use `active_trusted_key_groups` instead +- `alias_icp_recordals` - Managed by connection groups +- `aliases` - Managed by connection groups +- `anycast_ip_list_id` - Use connection groups instead +- `continuous_deployment_policy_id` +- `forwarded_values` in cache behaviors - Deprecated, use cache policies instead +- `is_ipv6_enabled` - Managed by connection groups +- `price_class` - Managed by connection groups +- `smooth_streaming` in cache behaviors +- `staging` mode +- `trusted_signers` in cache behaviors - Use `trusted_key_groups` instead +- Cache behavior TTL settings (`default_ttl`, `max_ttl`, `min_ttl`) - Use cache policies instead + +## Example Usage + +```terraform +resource "aws_cloudfront_multitenant_distribution" "example" { + comment = "Multi-tenant distribution for my application" + enabled = true + + origin { + domain_name = "example.com" + origin_id = "example-origin" + + custom_origin_config { + http_port = 80 + https_port = 443 + origin_protocol_policy = "https-only" + origin_ssl_protocols = ["TLSv1.2"] + } + } + + default_cache_behavior { + target_origin_id = "example-origin" + viewer_protocol_policy = "redirect-to-https" + cache_policy_id = aws_cloudfront_cache_policy.example.id + + allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] + cached_methods = ["GET", "HEAD"] + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } + + viewer_certificate { + acm_certificate_arn = aws_acm_certificate.example.arn + ssl_support_method = "sni-only" + } + + tags = { + Environment = "production" + } +} +``` + +## Argument Reference + +This resource supports the following arguments: + +* `cache_behavior` - (Optional) Ordered list of cache behaviors resource for this distribution. See [Cache Behavior](#cache-behavior) below. +* `comment` - (Required) Any comments you want to include about the distribution. +* `custom_error_response` - (Optional) One or more custom error response elements. See [Custom Error Response](#custom-error-response) below. +* `default_cache_behavior` - (Required) Default cache behavior for this distribution. See [Default Cache Behavior](#default-cache-behavior) below. +* `default_root_object` - (Optional) Object that you want CloudFront to return when an end user requests the root URL. +* `enabled` - (Required) Whether the distribution is enabled to accept end user requests for content. +* `http_version` - (Optional) Maximum HTTP version to support on the distribution. Allowed values are `http1.1`, `http2`, `http2and3`, and `http3`. Default: `http2`. +* `origin_group` - (Optional) One or more origin_group for this distribution (multiples allowed). See [Origin Group](#origin-group) below. +* `origin` - (Required) One or more origins for this distribution (multiples allowed). See [Origin](#origin) below. +* `restrictions` - (Required) Restriction configuration for this distribution. See [Restrictions](#restrictions) below. +* `tags` - (Optional) Map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. +* `tenant_config` - (Required) Tenant configuration that contains parameter definitions for multi-tenant distributions. See [Tenant Config](#tenant-config) below. +* `viewer_certificate` - (Required) SSL configuration for this distribution. See [Viewer Certificate](#viewer-certificate) below. +* `web_acl_id` - (Optional) Unique identifier that specifies the AWS WAF v2 web ACL to associate with this distribution. + +### Cache Behavior + +Cache behavior supports all the same arguments as [Default Cache Behavior](#default-cache-behavior) with the addition of: + +* `path_pattern` - (Required) Pattern that specifies which requests you want this cache behavior to apply to. + +### Default Cache Behavior + +* `target_origin_id` - (Required) Value of ID for the origin that you want CloudFront to route requests to when a request matches the path pattern either for a cache behavior or for the default cache behavior. +* `viewer_protocol_policy` - (Required) Use this element to specify the protocol that users can use to access the files in the origin specified by TargetOriginId when a request matches the path pattern in PathPattern. One of `allow-all`, `https-only`, or `redirect-to-https`. +* `allowed_methods` - (Required) Controls which HTTP methods CloudFront processes and forwards to your Amazon S3 bucket or your custom origin. +* `cached_methods` - (Required) Controls whether CloudFront caches the response to requests using the specified HTTP methods. +* `cache_policy_id` - (Optional) Unique identifier of the cache policy that is attached to the cache behavior. +* `compress` - (Optional) Whether you want CloudFront to automatically compress content for web requests that include `Accept-Encoding: gzip` in the request header. Default: `false`. +* `field_level_encryption_id` - (Optional) Field level encryption configuration ID. +* `function_association` - (Optional) Configuration block for CloudFront Functions associations. See [Function Association](#function-association) below. +* `lambda_function_association` - (Optional) Configuration block for Lambda@Edge associations. See [Lambda Function Association](#lambda-function-association) below. +* `origin_request_policy_id` - (Optional) Unique identifier of the origin request policy that is attached to the behavior. +* `realtime_log_config_arn` - (Optional) ARN of the real-time log configuration that is attached to this cache behavior. +* `response_headers_policy_id` - (Optional) Identifier for a response headers policy. +* `trusted_key_groups` - (Optional) List of key group IDs that CloudFront can use to validate signed URLs or signed cookies. + +### Function Association + +* `event_type` - (Required) Specific event to trigger this function. Valid values: `viewer-request`, `origin-request`, `viewer-response`, `origin-response`. +* `function_arn` - (Required) ARN of the CloudFront function. + +### Lambda Function Association + +* `event_type` - (Required) Specific event to trigger this function. Valid values: `viewer-request`, `origin-request`, `viewer-response`, `origin-response`. +* `include_body` - (Optional) When set to true, the request body is exposed to the Lambda function. Default: `false`. +* `lambda_function_arn` - (Required) ARN of the Lambda function. + +### Origin + +* `domain_name` - (Required) DNS domain name of either the S3 bucket, or web site of your custom origin. +* `origin_id` - (Required) Unique identifier for the origin. +* `connection_attempts` - (Optional) Number of times that CloudFront attempts to connect to the origin. Must be between 1-3. Default: 3. +* `connection_timeout` - (Optional) Number of seconds that CloudFront waits when trying to establish a connection to the origin. Must be between 1-10. Default: 10. +* `custom_header` - (Optional) One or more sub-resources with `name` and `value` parameters that specify header data that will be sent to the origin. See [Custom Header](#custom-header) below. +* `custom_origin_config` - (Optional) CloudFront origin access identity to associate with the origin. See [Custom Origin Config](#custom-origin-config) below. +* `origin_access_control_id` - (Optional) CloudFront origin access control identifier to associate with the origin. +* `origin_path` - (Optional) Optional element that causes CloudFront to request your content from a directory in your Amazon S3 bucket or your custom origin. +* `origin_shield` - (Optional) CloudFront Origin Shield configuration information. See [Origin Shield](#origin-shield) below. +* `response_completion_timeout` - (Optional) Number of seconds that CloudFront waits for a response after forwarding a request to the origin. Default: 30. +* `vpc_origin_config` - (Optional) CloudFront VPC origin configuration. See [VPC Origin Config](#vpc-origin-config) below. + +### Custom Header + +* `header_name` - (Required) Name of the header. +* `header_value` - (Required) Value for the header. + +### Custom Origin Config + +* `http_port` - (Required) HTTP port the custom origin listens on. +* `https_port` - (Required) HTTPS port the custom origin listens on. +* `ip_address_type` - (Optional) Type of IP addresses used by your origins. Valid values are `ipv4` and `dualstack`. +* `origin_keepalive_timeout` - (Optional) Custom keep-alive timeout, in seconds. Default: 5. +* `origin_read_timeout` - (Optional) Custom read timeout, in seconds. Default: 30. +* `origin_protocol_policy` - (Required) Origin protocol policy to apply to your origin. Valid values are `http-only`, `https-only`, and `match-viewer`. +* `origin_ssl_protocols` - (Required) List of SSL/TLS protocols that you want CloudFront to use when communicating with your origin over HTTPS. + +### Origin Shield + +* `enabled` - (Required) Whether Origin Shield is enabled. +* `origin_shield_region` - (Optional) AWS Region for Origin Shield. Required when `enabled` is `true`. + +### Origin Group + +* `origin_id` - (Required) Unique identifier for the origin group. +* `failover_criteria` - (Required) Failover criteria for when to failover to the secondary origin. See [Failover Criteria](#failover-criteria) below. +* `member` - (Required) List of origins in this origin group. Must contain exactly 2 members. See [Origin Group Member](#origin-group-member) below. + +### Failover Criteria + +* `status_codes` - (Required) List of HTTP status codes that trigger a failover to the secondary origin. + +### Origin Group Member + +* `origin_id` - (Required) Unique identifier of an origin in the origin group. + +### Restrictions + +* `geo_restriction` - (Required) Geographic restriction configuration. See [Geo Restriction](#geo-restriction) below. + +### Geo Restriction + +* `restriction_type` - (Required) Method to restrict distribution of your content by country. Valid values are `none`, `whitelist`, and `blacklist`. +* `items` - (Optional) List of ISO 3166-1-alpha-2 country codes for which you want CloudFront either to distribute your content (`whitelist`) or not distribute your content (`blacklist`). Required when `restriction_type` is `whitelist` or `blacklist`. + +### Active Trusted Key Groups + +* `enabled` - Whether any of the key groups have public keys that CloudFront can use to verify the signatures of signed URLs and signed cookies. +* `items` - List of key groups. See [Key Group Items](#key-group-items) below. + +### Key Group Items + +* `key_group_id` - ID of the key group that contains the public keys. +* `key_pair_ids` - Set of active CloudFront key pairs associated with the signer that can be used to verify the signatures of signed URLs and signed cookies. + +### VPC Origin Config + +* `origin_keepalive_timeout` - (Optional) Custom keep-alive timeout, in seconds. By default, CloudFront uses a default timeout. Default: 5. +* `origin_read_timeout` - (Optional) Custom read timeout, in seconds. By default, CloudFront uses a default timeout. Default: 30. +* `vpc_origin_id` - (Required) ID of the VPC origin that you want CloudFront to route requests to. + +### Custom Error Response + +* `error_caching_min_ttl` - (Optional) Minimum amount of time that you want CloudFront to cache the HTTP status code specified in ErrorCode. +* `error_code` - (Required) HTTP status code for which you want to specify a custom error page and/or a caching duration. +* `response_code` - (Optional) HTTP status code that you want CloudFront to return to the viewer along with the custom error page. +* `response_page_path` - (Optional) Path to the custom error page that you want CloudFront to return to a viewer when your origin returns the HTTP status code specified by ErrorCode. + +### Tenant Config + +* `parameter_definition` - (Required) One or more parameter definitions for the tenant configuration. See [Parameter Definition](#parameter-definition) below. + +### Parameter Definition + +* `name` - (Required) Name of the parameter. +* `definition` - (Required) Definition of the parameter schema. See [Parameter Definition Schema](#parameter-definition-schema) below. + +### Parameter Definition Schema + +* `string_schema` - (Required) String schema configuration. See [String Schema](#string-schema) below. + +### String Schema + +* `required` - (Required) Whether the parameter is required. +* `comment` - (Optional) Comment describing the parameter. +* `default_value` - (Optional) Default value for the parameter. + +### Viewer Certificate + +* `acm_certificate_arn` - (Optional) ARN of the AWS Certificate Manager certificate that you wish to use with this distribution. Required when using a custom SSL certificate. +* `cloudfront_default_certificate` - (Optional) Whether to use the CloudFront default certificate. Cannot be used with `acm_certificate_arn`. +* `minimum_protocol_version` - (Optional) Minimum version of the SSL protocol that you want CloudFront to use for HTTPS connections. Default: `TLSv1`. +* `ssl_support_method` - (Optional) How you want CloudFront to serve HTTPS requests. Valid values are `sni-only` and `vip`. Required when `acm_certificate_arn` is specified. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `arn` - ARN for the distribution. +* `caller_reference` - Internal value used by CloudFront to allow future updates to the distribution configuration. +* `connection_mode` - Connection mode for the distribution. Always set to `tenant-only` for multi-tenant distributions. +* `domain_name` - Domain name corresponding to the distribution. +* `etag` - Current version of the distribution's information. +* `id` - Identifier for the distribution. +* `in_progress_invalidation_batches` - Number of invalidation batches currently in progress. +* `last_modified_time` - Date and time the distribution was last modified. +* `status` - Current status of the distribution. `Deployed` if the distribution's information is fully propagated throughout the Amazon CloudFront system. +* `tags_all` - Map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). +* `active_trusted_key_groups` - List of key groups that CloudFront can use to validate signed URLs or signed cookies. See [Active Trusted Key Groups](#active-trusted-key-groups) below. + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `30m`) +* `update` - (Default `30m`) +* `delete` - (Default `30m`) + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import CloudFront Multi-tenant Distributions using the `id`. For example: + +```terraform +import { + to = aws_cloudfront_multitenant_distribution.distribution + id = "E74FTE3AEXAMPLE" +} +``` + +Using `terraform import`, import CloudFront Multi-tenant Distributions using the `id`. For example: + +```console +% terraform import aws_cloudfront_multitenant_distribution.distribution E74FTE3AEXAMPLE +``` diff --git a/website/docs/r/ecs_capacity_provider.html.markdown b/website/docs/r/ecs_capacity_provider.html.markdown index 77b9f3bc5f4d..94b79e7446cc 100644 --- a/website/docs/r/ecs_capacity_provider.html.markdown +++ b/website/docs/r/ecs_capacity_provider.html.markdown @@ -126,6 +126,7 @@ This resource supports the following arguments: ### `instance_launch_template` +* `capacity_option_type` - (Optional) The purchasing option for the EC2 instances used in the capacity provider. Determines whether to use On-Demand or Spot instances. Valid values are `ON_DEMAND` and `SPOT`. Defaults to `ON_DEMAND` when not specified. Changing this value will trigger replacement of the capacity provider. For more information, see [Amazon EC2 billing and purchasing options](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-purchasing-options.html) in the Amazon EC2 User Guide. * `ec2_instance_profile_arn` - (Required) The Amazon Resource Name (ARN) of the instance profile that Amazon ECS applies to Amazon ECS Managed Instances. This instance profile must include the necessary permissions for your tasks to access AWS services and resources. For more information, see [Amazon ECS instance profile for Managed Instances](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html) in the Amazon ECS Developer Guide. * `instance_requirements` - (Optional) The instance requirements. You can specify the instance types and instance requirements such as vCPU count, memory, network performance, and accelerator specifications. Amazon ECS automatically selects the instances that match the specified criteria. Detailed below. * `monitoring` - (Optional) CloudWatch provides two categories of monitoring: basic monitoring and detailed monitoring. By default, your managed instance is configured for basic monitoring. You can optionally enable detailed monitoring to help you more quickly identify and act on operational issues. You can enable or turn off detailed monitoring at launch or when the managed instance is running or stopped. For more information, see [Detailed monitoring for Amazon ECS Managed Instances](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cloudwatch-metrics.html) in the Amazon ECS Developer Guide. Valid values are `BASIC` and `DETAILED`.