diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index d5886a6..75deea3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -3,6 +3,7 @@ repos:
rev: v1.77.0
hooks:
- id: terraform_fmt
+ - id: terraform_wrapper_module_for_each
- id: terraform_validate
- id: terraform_docs
args:
diff --git a/README.md b/README.md
index d216e3d..2616e3b 100644
--- a/README.md
+++ b/README.md
@@ -2,20 +2,132 @@
Terraform module which creates SNS resources on AWS
+[](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)
+
## Usage
+### Simple Topic
+
+```hcl
+module "sns_topic" {
+ source = "terraform-aws-modules/sns/aws"
+
+ name = "simple"
+
+ tags = {
+ Environment = "dev"
+ Terraform = "true"
+ }
+}
+```
+
+### Topic w/ SQS Subscription
+
+```hcl
+module "sns_topic" {
+ source = "terraform-aws-modules/sns/aws"
+
+ name = "pub-sub"
+
+ topic_policy_statements = {
+ pub = {
+ actions = ["sns:Publish"]
+ principals = [{
+ type = "AWS"
+ identifiers = ["arn:aws:iam::66666666666:role/publisher"]
+ }]
+ },
+
+ sub = {
+ actions = [
+ "sns:Subscribe",
+ "sns:Receive",
+ ]
+
+ principals = [{
+ type = "AWS"
+ identifiers = ["*"]
+ }]
+
+ conditions = [{
+ test = "StringLike"
+ variable = "sns:Endpoint"
+ values = ["arn:aws:sqs:eu-west-1:11111111111:subscriber"]
+ }]
+ }
+ }
+
+ subscriptions = {
+ sqs = {
+ protocol = "sqs"
+ endpoint = "arn:aws:sqs:eu-west-1:11111111111:subscriber"
+ }
+ }
+
+ tags = {
+ Environment = "dev"
+ Terraform = "true"
+ }
+}
+```
+
+### FIFO Topic w/ FIFO SQS Subscription
+
```hcl
module "sns_topic" {
source = "terraform-aws-modules/sns/aws"
- version = "~> 3.0"
name = "my-topic"
+
+ # SQS queue must be FIFO as well
+ fifo_topic = true
+ content_based_deduplication = true
+
+ topic_policy_statements = {
+ pub = {
+ actions = ["sns:Publish"]
+ principals = [{
+ type = "AWS"
+ identifiers = ["arn:aws:iam::66666666666:role/publisher"]
+ }]
+ },
+
+ sub = {
+ actions = [
+ "sns:Subscribe",
+ "sns:Receive",
+ ]
+
+ principals = [{
+ type = "AWS"
+ identifiers = ["*"]
+ }]
+
+ conditions = [{
+ test = "StringLike"
+ variable = "sns:Endpoint"
+ values = ["arn:aws:sqs:eu-west-1:11111111111:subscriber.fifo"]
+ }]
+ }
+ }
+
+ subscriptions = {
+ sqs = {
+ protocol = "sqs"
+ endpoint = "arn:aws:sqs:eu-west-1:11111111111:subscriber.fifo"
+ }
+ }
+
+ tags = {
+ Environment = "dev"
+ Terraform = "true"
+ }
}
```
## Examples
-- [Complete SNS topics](https://github.com/terraform-aws-modules/terraform-aws-sns/tree/master/examples/complete)
+- [Complete](https://github.com/terraform-aws-modules/terraform-aws-sns/tree/master/examples/complete)
## Requirements
@@ -23,13 +135,13 @@ module "sns_topic" {
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.0 |
-| [aws](#requirement\_aws) | >= 4.0 |
+| [aws](#requirement\_aws) | >= 4.40 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 4.0 |
+| [aws](#provider\_aws) | >= 4.40 |
## Modules
@@ -40,45 +152,47 @@ No modules.
| Name | Type |
|------|------|
| [aws_sns_topic.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource |
+| [aws_sns_topic_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource |
+| [aws_sns_topic_subscription.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource |
+| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
+| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
-| [application\_failure\_feedback\_role\_arn](#input\_application\_failure\_feedback\_role\_arn) | IAM role for failure feedback | `string` | `null` | no |
-| [application\_success\_feedback\_role\_arn](#input\_application\_success\_feedback\_role\_arn) | The IAM role permitted to receive success feedback for this topic | `string` | `null` | no |
-| [application\_success\_feedback\_sample\_rate](#input\_application\_success\_feedback\_sample\_rate) | Percentage of success to sample | `string` | `null` | no |
+| [application\_feedback](#input\_application\_feedback) | Map of IAM role ARNs and sample rate for success and failure feedback | `map(string)` | `{}` | no |
| [content\_based\_deduplication](#input\_content\_based\_deduplication) | Boolean indicating whether or not to enable content-based deduplication for FIFO topics. | `bool` | `false` | no |
-| [create\_sns\_topic](#input\_create\_sns\_topic) | Whether to create the SNS topic | `bool` | `true` | no |
+| [create](#input\_create) | Determines whether resources will be created (affects all resources) | `bool` | `true` | no |
+| [create\_subscription](#input\_create\_subscription) | Determines whether an SNS subscription is created | `bool` | `true` | no |
+| [create\_topic\_policy](#input\_create\_topic\_policy) | Determines whether an SNS topic policy is created | `bool` | `true` | no |
| [delivery\_policy](#input\_delivery\_policy) | The SNS delivery policy | `string` | `null` | no |
| [display\_name](#input\_display\_name) | The display name for the SNS topic | `string` | `null` | no |
+| [enable\_default\_topic\_policy](#input\_enable\_default\_topic\_policy) | Specifies whether to enable the default topic policy. Defaults to `true` | `bool` | `true` | no |
| [fifo\_topic](#input\_fifo\_topic) | Boolean indicating whether or not to create a FIFO (first-in-first-out) topic | `bool` | `false` | no |
-| [firehose\_failure\_feedback\_role\_arn](#input\_firehose\_failure\_feedback\_role\_arn) | IAM role for failure feedback | `string` | `null` | no |
-| [firehose\_success\_feedback\_role\_arn](#input\_firehose\_success\_feedback\_role\_arn) | The IAM role permitted to receive success feedback for this topic | `string` | `null` | no |
-| [firehose\_success\_feedback\_sample\_rate](#input\_firehose\_success\_feedback\_sample\_rate) | Percentage of success to sample | `number` | `null` | no |
-| [http\_failure\_feedback\_role\_arn](#input\_http\_failure\_feedback\_role\_arn) | IAM role for failure feedback | `string` | `null` | no |
-| [http\_success\_feedback\_role\_arn](#input\_http\_success\_feedback\_role\_arn) | The IAM role permitted to receive success feedback for this topic | `string` | `null` | no |
-| [http\_success\_feedback\_sample\_rate](#input\_http\_success\_feedback\_sample\_rate) | Percentage of success to sample | `string` | `null` | no |
+| [firehose\_feedback](#input\_firehose\_feedback) | Map of IAM role ARNs and sample rate for success and failure feedback | `map(string)` | `{}` | no |
+| [http\_feedback](#input\_http\_feedback) | Map of IAM role ARNs and sample rate for success and failure feedback | `map(string)` | `{}` | no |
| [kms\_master\_key\_id](#input\_kms\_master\_key\_id) | The ID of an AWS-managed customer master key (CMK) for Amazon SNS or a custom CMK | `string` | `null` | no |
-| [lambda\_failure\_feedback\_role\_arn](#input\_lambda\_failure\_feedback\_role\_arn) | IAM role for failure feedback | `string` | `null` | no |
-| [lambda\_success\_feedback\_role\_arn](#input\_lambda\_success\_feedback\_role\_arn) | The IAM role permitted to receive success feedback for this topic | `string` | `null` | no |
-| [lambda\_success\_feedback\_sample\_rate](#input\_lambda\_success\_feedback\_sample\_rate) | Percentage of success to sample | `string` | `null` | no |
+| [lambda\_feedback](#input\_lambda\_feedback) | Map of IAM role ARNs and sample rate for success and failure feedback | `map(string)` | `{}` | no |
| [name](#input\_name) | The name of the SNS topic to create | `string` | `null` | no |
-| [name\_prefix](#input\_name\_prefix) | The prefix name of the SNS topic to create | `string` | `null` | no |
-| [policy](#input\_policy) | The fully-formed AWS policy as JSON | `string` | `null` | no |
-| [sqs\_failure\_feedback\_role\_arn](#input\_sqs\_failure\_feedback\_role\_arn) | IAM role for failure feedback | `string` | `null` | no |
-| [sqs\_success\_feedback\_role\_arn](#input\_sqs\_success\_feedback\_role\_arn) | The IAM role permitted to receive success feedback for this topic | `string` | `null` | no |
-| [sqs\_success\_feedback\_sample\_rate](#input\_sqs\_success\_feedback\_sample\_rate) | Percentage of success to sample | `string` | `null` | no |
-| [tags](#input\_tags) | A mapping of tags to assign to all resources | `map(string)` | `{}` | no |
+| [override\_topic\_policy\_documents](#input\_override\_topic\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. In merging, statements with non-blank `sid`s will override statements with the same `sid` | `list(string)` | `[]` | no |
+| [source\_topic\_policy\_documents](#input\_source\_topic\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s | `list(string)` | `[]` | no |
+| [sqs\_feedback](#input\_sqs\_feedback) | Map of IAM role ARNs and sample rate for success and failure feedback | `map(string)` | `{}` | no |
+| [subscriptions](#input\_subscriptions) | A map of subscription definitions to create | `any` | `{}` | no |
+| [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
+| [topic\_policy](#input\_topic\_policy) | An externally created fully-formed AWS policy as JSON | `string` | `null` | no |
+| [topic\_policy\_statements](#input\_topic\_policy\_statements) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage | `any` | `{}` | no |
+| [use\_name\_prefix](#input\_use\_name\_prefix) | Determines whether `name` is used as a prefix | `bool` | `false` | no |
## Outputs
| Name | Description |
|------|-------------|
-| [sns\_topic\_arn](#output\_sns\_topic\_arn) | ARN of SNS topic |
-| [sns\_topic\_id](#output\_sns\_topic\_id) | ID of SNS topic |
-| [sns\_topic\_name](#output\_sns\_topic\_name) | NAME of SNS topic |
-| [sns\_topic\_owner](#output\_sns\_topic\_owner) | OWNER of SNS topic |
+| [subscriptions](#output\_subscriptions) | Map of subscriptions created and their attributes |
+| [topic\_arn](#output\_topic\_arn) | The ARN of the SNS topic, as a more obvious property (clone of id) |
+| [topic\_id](#output\_topic\_id) | The ARN of the SNS topic |
+| [topic\_name](#output\_topic\_name) | The name of the topic |
+| [topic\_owner](#output\_topic\_owner) | The AWS Account ID of the SNS topic owner |
## Authors
diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md
new file mode 100644
index 0000000..cce4c53
--- /dev/null
+++ b/UPGRADE-5.0.md
@@ -0,0 +1,142 @@
+# Upgrade from v4.x to v5.x
+
+If you have any questions regarding this upgrade process, please consult the [`examples`](https://github.com/terraform-aws-modules/terraform-aws-sns/tree/master/examples/complete) directory:
+
+If you find a bug, please open an issue with supporting configuration to reproduce.
+
+## List of backwards incompatible changes
+
+- `create_sns_topic` has been renamed to `create`
+- `policy` has been renamed to `topic_policy`
+- `name_prefix` has been replaced with the combination of `name` and `use_name_prefix = true` to ensure only one value is provided
+- `*_failure_feedback_role_arn`, `*_success_feedback_role_arn`, `*_success_feedback_sample_rate` variables have been replaced with a respective top level variable that contains a map to the three attributes. See before and after below for further clarification.
+- Outputs have had the `sns_` prefix stripped from their names
+
+## Additional changes
+
+### Added
+
+- Support for topic policy creation and subscriptions
+
+### Variable and output changes
+
+1. Removed variables:
+
+ - None
+
+2. Renamed variables:
+
+ - `create_sns_topic` -> `create`
+ - `policy` -> `topic_policy`
+ - `application_feedback_failure_role_arn`/`application_feedback_success_role_arn`/`application_feedback_success_feedback_sample_rate` -> `application_feedback`
+ - `firehose_feedback_failure_role_arn`/`firehose_feedback_success_role_arn`/`firehose_feedback_success_feedback_sample_rate` -> `firehose_feedback`
+ - `http_feedback_failure_role_arn`/`http_feedback_success_role_arn`/`http_feedback_success_feedback_sample_rate` -> `http_feedback`
+ - `lambda_feedback_failure_role_arn`/`lambda_feedback_success_role_arn`/`lambda_feedback_success_feedback_sample_rate` -> `lambda_feedback`
+ - `sqs_feedback_failure_role_arn`/`sqs_feedback_success_role_arn`/`sqs_feedback_success_feedback_sample_rate` -> `sqs_feedback`
+
+3. Added variables:
+
+ - `use_name_prefix`
+ - `create_topic_policy`
+ - `source_topic_policy_documents`
+ - `override_topic_policy_documents`
+ - `enable_default_topic_policy`
+ - `topic_policy_statements`
+ - `create_subscription`
+ - `subscriptions`
+
+4. Removed outputs:
+
+ - None
+
+5. Renamed outputs:
+
+ - `sns_` prefix removed from all outputs
+
+6. Added outputs:
+
+ - `subscriptions`
+
+## Upgrade Migrations
+
+Note: Only the affected attributes are shown below for brevity.
+
+### Before 4.x Example
+
+```hcl
+module "sns" {
+ source = "terraform-aws-modules/sns/aws"
+ version = "~> 4.0"
+
+ create_sns_topic = true
+
+ name_prefix = "example-"
+ policy = "..."
+
+ application_feedback_failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:application"
+ application_feedback_success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:application"
+ application_feedback_success_sample_rate = 100
+
+ firehose_feedback_failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:firehose"
+ firehose_feedback_success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:firehose"
+ firehose_feedback_success_sample_rate = 100
+
+ http_feedback_failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:http"
+ http_feedback_success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:http"
+ http_feedback_success_sample_rate = 100
+
+ lambda_feedback = {
+ lambda_feedback_failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:lambda"
+ lambda_feedback_success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:lambda"
+ lambda_feedback_success_sample_rate = 100
+
+ sqs_feedback_failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:sqs"
+ sqs_feedback_success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:sqs"
+ sqs_feedback_success_sample_rate = 100
+}
+```
+
+### After 5.x Example
+
+```hcl
+module "sns" {
+ source = "terraform-aws-modules/sns/aws"
+ version = "~> 5.0"
+
+ create = true
+
+ name = "example-"
+ use_name_prefix = true
+ topic_policy = "..."
+
+ application_feedback = {
+ failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:application"
+ success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:application"
+ success_sample_rate = 100
+ }
+ firehose_feedback = {
+ failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:firehose"
+ success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:firehose"
+ success_sample_rate = 100
+ }
+ http_feedback = {
+ failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:http"
+ success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:http"
+ success_sample_rate = 100
+ }
+ lambda_feedback = {
+ failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:lambda"
+ success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:lambda"
+ success_sample_rate = 100
+ }
+ sqs_feedback = {
+ failure_role_arn = "arn:aws:sqs:eu-west-1:11111111111:sqs"
+ success_role_arn = "arn:aws:sqs:eu-west-1:11111111111:sqs"
+ success_sample_rate = 100
+ }
+}
+```
+
+### State Changes
+
+No state changes required.
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..f417c0a
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,8 @@
+# Examples
+
+Please note - the examples provided serve two primary means:
+
+1. Show users working examples of the various ways in which the module can be configured and features supported
+2. A means of testing/validating module changes
+
+Please do not mistake the examples provided as "best practices". It is up to users to consult the AWS service documentation for best practices, usage recommendations, etc.
diff --git a/examples/complete/README.md b/examples/complete/README.md
index b696131..9692aa6 100644
--- a/examples/complete/README.md
+++ b/examples/complete/README.md
@@ -1,6 +1,9 @@
# Complete SNS topic example
-Configuration in this directory creates SNS topics.
+Configuration in this directory creates:
+- A simple, default SNS topic
+- A FIFO SNS topic with FIFO SQS subscription; shows most of the supported arguments
+- A disabled SNS topic
## Usage
@@ -20,26 +23,30 @@ Note that this example may create resources which cost money. Run `terraform des
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.0 |
-| [aws](#requirement\_aws) | >= 4.0 |
+| [aws](#requirement\_aws) | >= 4.40 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 4.0 |
+| [aws](#provider\_aws) | >= 4.40 |
## Modules
| Name | Source | Version |
|------|--------|---------|
-| [users\_encrypted](#module\_users\_encrypted) | ../../ | n/a |
-| [users\_unencrypted](#module\_users\_unencrypted) | ../../ | n/a |
+| [complete\_sns](#module\_complete\_sns) | ../../ | n/a |
+| [default\_sns](#module\_default\_sns) | ../../ | n/a |
+| [disabled\_sns](#module\_disabled\_sns) | ../../ | n/a |
+| [kms](#module\_kms) | terraform-aws-modules/kms/aws | ~> 1.0 |
+| [sqs](#module\_sqs) | terraform-aws-modules/sqs/aws | ~> 4.0 |
## Resources
| Name | Type |
|------|------|
-| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
+| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
+| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
## Inputs
@@ -49,6 +56,14 @@ No inputs.
| Name | Description |
|------|-------------|
-| [users\_encrypted\_sns\_topic\_arn](#output\_users\_encrypted\_sns\_topic\_arn) | The ARN of the SNS topic |
-| [users\_unencrypted\_sns\_topic\_arn](#output\_users\_unencrypted\_sns\_topic\_arn) | The ARN of the SNS topic |
+| [complete\_sns\_subscriptions](#output\_complete\_sns\_subscriptions) | Map of subscriptions created and their attributes |
+| [complete\_sns\_topic\_arn](#output\_complete\_sns\_topic\_arn) | The ARN of the SNS topic, as a more obvious property (clone of id) |
+| [complete\_sns\_topic\_id](#output\_complete\_sns\_topic\_id) | The ARN of the SNS topic |
+| [complete\_sns\_topic\_name](#output\_complete\_sns\_topic\_name) | The name of the topic |
+| [complete\_sns\_topic\_owner](#output\_complete\_sns\_topic\_owner) | The AWS Account ID of the SNS topic owner |
+| [default\_sns\_subscriptions](#output\_default\_sns\_subscriptions) | Map of subscriptions created and their attributes |
+| [default\_sns\_topic\_arn](#output\_default\_sns\_topic\_arn) | The ARN of the SNS topic, as a more obvious property (clone of id) |
+| [default\_sns\_topic\_id](#output\_default\_sns\_topic\_id) | The ARN of the SNS topic |
+| [default\_sns\_topic\_name](#output\_default\_sns\_topic\_name) | The name of the topic |
+| [default\_sns\_topic\_owner](#output\_default\_sns\_topic\_owner) | The AWS Account ID of the SNS topic owner |
diff --git a/examples/complete/main.tf b/examples/complete/main.tf
index c418d1f..372114d 100644
--- a/examples/complete/main.tf
+++ b/examples/complete/main.tf
@@ -1,27 +1,233 @@
provider "aws" {
+ region = local.region
+}
+
+data "aws_caller_identity" "current" {}
+
+locals {
region = "eu-west-1"
+ name = "sns-ex-${basename(path.cwd)}"
+
+ tags = {
+ Name = local.name
+ Example = "complete"
+ Repository = "github.com/terraform-aws-modules/terraform-aws-sns"
+ }
}
-resource "aws_kms_key" "this" {}
+################################################################################
+# SNS Module
+################################################################################
-module "users_unencrypted" {
+module "default_sns" {
source = "../../"
- name = "users-unencrypted"
+ name = "${local.name}-default"
- tags = {
- Secure = "false"
+ tags = local.tags
+}
+
+module "complete_sns" {
+ source = "../../"
+
+ name = local.name
+ use_name_prefix = true
+ display_name = "complete"
+ kms_master_key_id = module.kms.key_id
+
+ # SQS queue must be FIFO as well
+ fifo_topic = true
+ content_based_deduplication = true
+
+ delivery_policy = jsonencode({
+ "http" : {
+ "defaultHealthyRetryPolicy" : {
+ "minDelayTarget" : 20,
+ "maxDelayTarget" : 20,
+ "numRetries" : 3,
+ "numMaxDelayRetries" : 0,
+ "numNoDelayRetries" : 0,
+ "numMinDelayRetries" : 0,
+ "backoffFunction" : "linear"
+ },
+ "disableSubscriptionOverrides" : false,
+ "defaultThrottlePolicy" : {
+ "maxReceivesPerSecond" : 1
+ }
+ }
+ })
+
+ create_topic_policy = true
+ enable_default_topic_policy = true
+ topic_policy_statements = {
+ pub = {
+ actions = ["sns:Publish"]
+ principals = [{
+ type = "AWS"
+ identifiers = [data.aws_caller_identity.current.arn]
+ }]
+ },
+
+ sub = {
+ actions = [
+ "sns:Subscribe",
+ "sns:Receive",
+ ]
+
+ principals = [{
+ type = "AWS"
+ identifiers = ["*"]
+ }]
+
+ conditions = [{
+ test = "StringLike"
+ variable = "sns:Endpoint"
+ values = [module.sqs.queue_arn]
+ }]
+ }
+ }
+
+ subscriptions = {
+ sqs = {
+ protocol = "sqs"
+ endpoint = module.sqs.queue_arn
+ }
+ }
+
+ # Feedback
+ application_feedback = {
+ failure_role_arn = aws_iam_role.this.arn
+ success_role_arn = aws_iam_role.this.arn
+ success_sample_rate = 100
+ }
+ firehose_feedback = {
+ failure_role_arn = aws_iam_role.this.arn
+ success_role_arn = aws_iam_role.this.arn
+ success_sample_rate = 100
+ }
+ http_feedback = {
+ failure_role_arn = aws_iam_role.this.arn
+ success_role_arn = aws_iam_role.this.arn
+ success_sample_rate = 100
}
+ lambda_feedback = {
+ failure_role_arn = aws_iam_role.this.arn
+ success_role_arn = aws_iam_role.this.arn
+ success_sample_rate = 100
+ }
+ sqs_feedback = {
+ failure_role_arn = aws_iam_role.this.arn
+ success_role_arn = aws_iam_role.this.arn
+ success_sample_rate = 100
+ }
+
+ tags = local.tags
}
-module "users_encrypted" {
+module "disabled_sns" {
source = "../../"
- name_prefix = "users-encrypted-"
- display_name = "users-encrypted"
- kms_master_key_id = aws_kms_key.this.id
+ create = false
+}
- tags = {
- Secure = "true"
+################################################################################
+# Supporting Resources
+################################################################################
+
+module "kms" {
+ source = "terraform-aws-modules/kms/aws"
+ version = "~> 1.0"
+
+ aliases = ["sns/${local.name}"]
+ description = "KMS key to encrypt topic"
+
+ # Policy
+ key_statements = [
+ {
+ sid = "SNS"
+ actions = [
+ "kms:GenerateDataKey*",
+ "kms:Decrypt"
+ ]
+ resources = ["*"]
+ principals = [{
+ type = "Service"
+ identifiers = ["sns.amazonaws.com"]
+ }]
+ }
+ ]
+
+ tags = local.tags
+}
+
+module "sqs" {
+ source = "terraform-aws-modules/sqs/aws"
+ version = "~> 4.0"
+
+ name = local.name
+ fifo_queue = true
+
+ create_queue_policy = true
+ queue_policy_statements = {
+ sns = {
+ sid = "SNS"
+ actions = ["sqs:SendMessage"]
+
+ principals = [
+ {
+ type = "Service"
+ identifiers = ["sns.amazonaws.com"]
+ }
+ ]
+
+ condition = {
+ test = "ArnEquals"
+ variable = "aws:SourceArn"
+ values = [module.complete_sns.topic_arn]
+ }
+ }
}
+
+ tags = local.tags
+}
+
+resource "aws_iam_role" "this" {
+ name = local.name
+
+ assume_role_policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Sid = "SnsAssume"
+ Principal = {
+ Service = "sns.amazonaws.com"
+ }
+ },
+ ]
+ })
+
+ inline_policy {
+ name = local.name
+
+ policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Action = [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:PutLogEvents",
+ "logs:PutMetricFilter",
+ "logs:PutRetentionPolicy",
+ ]
+ Effect = "Allow"
+ Resource = "*"
+ },
+ ]
+ })
+ }
+
+ tags = local.tags
}
diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf
index 2568e14..a756ba3 100644
--- a/examples/complete/outputs.tf
+++ b/examples/complete/outputs.tf
@@ -1,9 +1,57 @@
-output "users_unencrypted_sns_topic_arn" {
+################################################################################
+# Default
+################################################################################
+
+output "default_sns_topic_arn" {
+ description = "The ARN of the SNS topic, as a more obvious property (clone of id)"
+ value = module.default_sns.topic_arn
+}
+
+output "default_sns_topic_id" {
description = "The ARN of the SNS topic"
- value = module.users_unencrypted.sns_topic_arn
+ value = module.default_sns.topic_id
+}
+
+output "default_sns_topic_name" {
+ description = "The name of the topic"
+ value = module.default_sns.topic_name
+}
+
+output "default_sns_topic_owner" {
+ description = "The AWS Account ID of the SNS topic owner"
+ value = module.default_sns.topic_owner
+}
+
+output "default_sns_subscriptions" {
+ description = "Map of subscriptions created and their attributes"
+ value = module.default_sns.subscriptions
}
-output "users_encrypted_sns_topic_arn" {
+################################################################################
+# Complete
+################################################################################
+
+output "complete_sns_topic_arn" {
+ description = "The ARN of the SNS topic, as a more obvious property (clone of id)"
+ value = module.complete_sns.topic_arn
+}
+
+output "complete_sns_topic_id" {
description = "The ARN of the SNS topic"
- value = module.users_encrypted.sns_topic_arn
+ value = module.complete_sns.topic_id
+}
+
+output "complete_sns_topic_name" {
+ description = "The name of the topic"
+ value = module.complete_sns.topic_name
+}
+
+output "complete_sns_topic_owner" {
+ description = "The AWS Account ID of the SNS topic owner"
+ value = module.complete_sns.topic_owner
+}
+
+output "complete_sns_subscriptions" {
+ description = "Map of subscriptions created and their attributes"
+ value = module.complete_sns.subscriptions
}
diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf
index d8dd1a4..fa875db 100644
--- a/examples/complete/versions.tf
+++ b/examples/complete/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 4.0"
+ version = ">= 4.40"
}
}
}
diff --git a/main.tf b/main.tf
index ae17a9a..4ea2073 100644
--- a/main.tf
+++ b/main.tf
@@ -1,30 +1,155 @@
+data "aws_caller_identity" "current" {}
+
+################################################################################
+# Topic
+################################################################################
+
resource "aws_sns_topic" "this" {
- count = var.create_sns_topic ? 1 : 0
-
- name = var.name
- name_prefix = var.name_prefix
-
- display_name = var.display_name
- policy = var.policy
- delivery_policy = var.delivery_policy
- application_success_feedback_role_arn = var.application_success_feedback_role_arn
- application_success_feedback_sample_rate = var.application_success_feedback_sample_rate
- application_failure_feedback_role_arn = var.application_failure_feedback_role_arn
- firehose_success_feedback_role_arn = var.firehose_success_feedback_role_arn
- firehose_success_feedback_sample_rate = var.firehose_success_feedback_sample_rate
- firehose_failure_feedback_role_arn = var.firehose_failure_feedback_role_arn
- http_success_feedback_role_arn = var.http_success_feedback_role_arn
- http_success_feedback_sample_rate = var.http_success_feedback_sample_rate
- http_failure_feedback_role_arn = var.http_failure_feedback_role_arn
- lambda_success_feedback_role_arn = var.lambda_success_feedback_role_arn
- lambda_success_feedback_sample_rate = var.lambda_success_feedback_sample_rate
- lambda_failure_feedback_role_arn = var.lambda_failure_feedback_role_arn
- sqs_success_feedback_role_arn = var.sqs_success_feedback_role_arn
- sqs_success_feedback_sample_rate = var.sqs_success_feedback_sample_rate
- sqs_failure_feedback_role_arn = var.sqs_failure_feedback_role_arn
- kms_master_key_id = var.kms_master_key_id
- fifo_topic = var.fifo_topic
- content_based_deduplication = var.content_based_deduplication
+ count = var.create ? 1 : 0
+
+ name = var.use_name_prefix ? null : var.name
+ name_prefix = var.use_name_prefix ? var.name : null
+
+ application_failure_feedback_role_arn = try(var.application_feedback.failure_role_arn, null)
+ application_success_feedback_role_arn = try(var.application_feedback.success_role_arn, null)
+ application_success_feedback_sample_rate = try(var.application_feedback.success_sample_rate, null)
+
+ content_based_deduplication = var.content_based_deduplication
+ delivery_policy = var.delivery_policy
+ display_name = var.display_name
+ fifo_topic = var.fifo_topic
+
+ firehose_failure_feedback_role_arn = try(var.firehose_feedback.failure_role_arn, null)
+ firehose_success_feedback_role_arn = try(var.firehose_feedback.success_role_arn, null)
+ firehose_success_feedback_sample_rate = try(var.firehose_feedback.success_sample_rate, null)
+
+ http_failure_feedback_role_arn = try(var.http_feedback.failure_role_arn, null)
+ http_success_feedback_role_arn = try(var.http_feedback.success_role_arn, null)
+ http_success_feedback_sample_rate = try(var.http_feedback.success_sample_rate, null)
+
+ kms_master_key_id = var.kms_master_key_id
+
+ lambda_failure_feedback_role_arn = try(var.lambda_feedback.failure_role_arn, null)
+ lambda_success_feedback_role_arn = try(var.lambda_feedback.success_role_arn, null)
+ lambda_success_feedback_sample_rate = try(var.lambda_feedback.success_sample_rate, null)
+
+ policy = var.create_topic_policy ? var.topic_policy : null
+
+ sqs_failure_feedback_role_arn = try(var.sqs_feedback.failure_role_arn, null)
+ sqs_success_feedback_role_arn = try(var.sqs_feedback.success_role_arn, null)
+ sqs_success_feedback_sample_rate = try(var.sqs_feedback.success_sample_rate, null)
tags = var.tags
}
+
+################################################################################
+# Topic Policy
+################################################################################
+
+data "aws_iam_policy_document" "this" {
+ count = var.create && var.create_topic_policy ? 1 : 0
+
+ source_policy_documents = var.source_topic_policy_documents
+ override_policy_documents = var.override_topic_policy_documents
+
+ dynamic "statement" {
+ for_each = var.enable_default_topic_policy ? [1] : []
+
+ content {
+ sid = "__default_statement_ID"
+ actions = [
+ "sns:Subscribe",
+ "sns:SetTopicAttributes",
+ "sns:RemovePermission",
+ "sns:Receive",
+ "sns:Publish",
+ "sns:ListSubscriptionsByTopic",
+ "sns:GetTopicAttributes",
+ "sns:DeleteTopic",
+ "sns:AddPermission",
+ ]
+ effect = "Allow"
+ resources = [aws_sns_topic.this[0].arn]
+
+ principals {
+ type = "AWS"
+ identifiers = ["*"]
+ }
+
+ condition {
+ test = "StringEquals"
+ values = [data.aws_caller_identity.current.account_id]
+ variable = "AWS:SourceOwner"
+ }
+ }
+ }
+
+ dynamic "statement" {
+ for_each = var.topic_policy_statements
+
+ content {
+ sid = try(statement.value.sid, statement.key)
+ actions = try(statement.value.actions, null)
+ not_actions = try(statement.value.not_actions, null)
+ effect = try(statement.value.effect, null)
+ # This avoids the chicken vs the egg scenario since its embedded and can reference the topic
+ resources = try(statement.value.resources, [aws_sns_topic.this[0].arn])
+ not_resources = try(statement.value.not_resources, null)
+
+ dynamic "principals" {
+ for_each = try(statement.value.principals, [])
+
+ content {
+ type = principals.value.type
+ identifiers = principals.value.identifiers
+ }
+ }
+
+ dynamic "not_principals" {
+ for_each = try(statement.value.not_principals, [])
+
+ content {
+ type = not_principals.value.type
+ identifiers = not_principals.value.identifiers
+ }
+ }
+
+ dynamic "condition" {
+ for_each = try(statement.value.conditions, [])
+
+ content {
+ test = condition.value.test
+ values = condition.value.values
+ variable = condition.value.variable
+ }
+ }
+ }
+ }
+}
+
+resource "aws_sns_topic_policy" "this" {
+ count = var.create && var.create_topic_policy ? 1 : 0
+
+ arn = aws_sns_topic.this[0].arn
+ policy = data.aws_iam_policy_document.this[0].json
+}
+
+################################################################################
+# Subscription(s)
+################################################################################
+
+resource "aws_sns_topic_subscription" "this" {
+ for_each = { for k, v in var.subscriptions : k => v if var.create && var.create_subscription }
+
+ confirmation_timeout_in_minutes = try(each.value.confirmation_timeout_in_minutes, null)
+ delivery_policy = try(each.value.delivery_policy, null)
+ endpoint = each.value.endpoint
+ endpoint_auto_confirms = try(each.value.endpoint_auto_confirms, null)
+ filter_policy = try(each.value.filter_policy, null)
+ filter_policy_scope = try(each.value.filter_policy_scope, null)
+ protocol = each.value.protocol
+ raw_message_delivery = try(each.value.raw_message_delivery, null)
+ redrive_policy = try(each.value.redrive_policy, null)
+ subscription_role_arn = try(each.value.subscription_role_arn, null)
+ topic_arn = aws_sns_topic.this[0].arn
+}
diff --git a/outputs.tf b/outputs.tf
index 9c582f5..c7065c4 100644
--- a/outputs.tf
+++ b/outputs.tf
@@ -1,19 +1,32 @@
-output "sns_topic_arn" {
- description = "ARN of SNS topic"
- value = try(aws_sns_topic.this[0].arn, "")
+################################################################################
+# Topic
+################################################################################
+
+output "topic_arn" {
+ description = "The ARN of the SNS topic, as a more obvious property (clone of id)"
+ value = try(aws_sns_topic.this[0].arn, null)
+}
+
+output "topic_id" {
+ description = "The ARN of the SNS topic"
+ value = try(aws_sns_topic.this[0].id, null)
}
-output "sns_topic_name" {
- description = "NAME of SNS topic"
- value = try(aws_sns_topic.this[0].name, "")
+output "topic_name" {
+ description = "The name of the topic"
+ value = try(aws_sns_topic.this[0].name, null)
}
-output "sns_topic_id" {
- description = "ID of SNS topic"
- value = try(aws_sns_topic.this[0].id, "")
+output "topic_owner" {
+ description = "The AWS Account ID of the SNS topic owner"
+ value = try(aws_sns_topic.this[0].owner, null)
}
-output "sns_topic_owner" {
- description = "OWNER of SNS topic"
- value = try(aws_sns_topic.this[0].owner, "")
+################################################################################
+# Subscription(s)
+################################################################################
+
+output "subscriptions" {
+ description = "Map of subscriptions created and their attributes"
+ value = aws_sns_topic_subscription.this
}
diff --git a/variables.tf b/variables.tf
index b3885a2..97306c0 100644
--- a/variables.tf
+++ b/variables.tf
@@ -1,31 +1,47 @@
-variable "create_sns_topic" {
- description = "Whether to create the SNS topic"
+variable "create" {
+ description = "Determines whether resources will be created (affects all resources)"
type = bool
default = true
}
+variable "tags" {
+ description = "A map of tags to add to all resources"
+ type = map(string)
+ default = {}
+}
+
+################################################################################
+# Topic
+################################################################################
+
variable "name" {
description = "The name of the SNS topic to create"
type = string
default = null
}
-variable "name_prefix" {
- description = "The prefix name of the SNS topic to create"
- type = string
- default = null
+variable "use_name_prefix" {
+ description = "Determines whether `name` is used as a prefix"
+ type = bool
+ default = false
}
-variable "display_name" {
- description = "The display name for the SNS topic"
- type = string
- default = null
+variable "application_feedback" {
+ description = "Map of IAM role ARNs and sample rate for success and failure feedback"
+ type = map(string)
+ default = {}
+ # Example:
+ # application_feedback = {
+ # failure_role_arn = "arn:aws:iam::11111111111:role/failure"
+ # success_role_arn = "arn:aws:iam::11111111111:role/success"
+ # success_sample_rate = 75
+ # }
}
-variable "policy" {
- description = "The fully-formed AWS policy as JSON"
- type = string
- default = null
+variable "content_based_deduplication" {
+ description = "Boolean indicating whether or not to enable content-based deduplication for FIFO topics."
+ type = bool
+ default = false
}
variable "delivery_policy" {
@@ -34,116 +50,124 @@ variable "delivery_policy" {
default = null
}
-variable "application_success_feedback_role_arn" {
- description = "The IAM role permitted to receive success feedback for this topic"
- type = string
- default = null
-}
-
-variable "application_success_feedback_sample_rate" {
- description = "Percentage of success to sample"
+variable "display_name" {
+ description = "The display name for the SNS topic"
type = string
default = null
}
-variable "application_failure_feedback_role_arn" {
- description = "IAM role for failure feedback"
- type = string
- default = null
+variable "fifo_topic" {
+ description = "Boolean indicating whether or not to create a FIFO (first-in-first-out) topic"
+ type = bool
+ default = false
}
-variable "firehose_success_feedback_role_arn" {
- description = "The IAM role permitted to receive success feedback for this topic"
- type = string
- default = null
+variable "firehose_feedback" {
+ description = "Map of IAM role ARNs and sample rate for success and failure feedback"
+ type = map(string)
+ default = {}
+ # Example:
+ # application_feedback = {
+ # failure_role_arn = "arn:aws:iam::11111111111:role/failure"
+ # success_role_arn = "arn:aws:iam::11111111111:role/success"
+ # success_sample_rate = 75
+ # }
}
-variable "firehose_success_feedback_sample_rate" {
- description = "Percentage of success to sample"
- type = number
- default = null
+variable "http_feedback" {
+ description = "Map of IAM role ARNs and sample rate for success and failure feedback"
+ type = map(string)
+ default = {}
+ # Example:
+ # application_feedback = {
+ # failure_role_arn = "arn:aws:iam::11111111111:role/failure"
+ # success_role_arn = "arn:aws:iam::11111111111:role/success"
+ # success_sample_rate = 75
+ # }
}
-variable "firehose_failure_feedback_role_arn" {
- description = "IAM role for failure feedback"
+variable "kms_master_key_id" {
+ description = "The ID of an AWS-managed customer master key (CMK) for Amazon SNS or a custom CMK"
type = string
default = null
}
-variable "http_success_feedback_role_arn" {
- description = "The IAM role permitted to receive success feedback for this topic"
- type = string
- default = null
+variable "lambda_feedback" {
+ description = "Map of IAM role ARNs and sample rate for success and failure feedback"
+ type = map(string)
+ default = {}
+ # Example:
+ # application_feedback = {
+ # failure_role_arn = "arn:aws:iam::11111111111:role/failure"
+ # success_role_arn = "arn:aws:iam::11111111111:role/success"
+ # success_sample_rate = 75
+ # }
}
-variable "http_success_feedback_sample_rate" {
- description = "Percentage of success to sample"
+variable "topic_policy" {
+ description = "An externally created fully-formed AWS policy as JSON"
type = string
default = null
}
-variable "http_failure_feedback_role_arn" {
- description = "IAM role for failure feedback"
- type = string
- default = null
+variable "sqs_feedback" {
+ description = "Map of IAM role ARNs and sample rate for success and failure feedback"
+ type = map(string)
+ default = {}
+ # Example:
+ # application_feedback = {
+ # failure_role_arn = "arn:aws:iam::11111111111:role/failure"
+ # success_role_arn = "arn:aws:iam::11111111111:role/success"
+ # success_sample_rate = 75
+ # }
}
-variable "lambda_success_feedback_role_arn" {
- description = "The IAM role permitted to receive success feedback for this topic"
- type = string
- default = null
-}
+################################################################################
+# Topic Policy
+################################################################################
-variable "lambda_success_feedback_sample_rate" {
- description = "Percentage of success to sample"
- type = string
- default = null
+variable "create_topic_policy" {
+ description = "Determines whether an SNS topic policy is created"
+ type = bool
+ default = true
}
-variable "lambda_failure_feedback_role_arn" {
- description = "IAM role for failure feedback"
- type = string
- default = null
+variable "source_topic_policy_documents" {
+ description = "List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s"
+ type = list(string)
+ default = []
}
-variable "sqs_success_feedback_role_arn" {
- description = "The IAM role permitted to receive success feedback for this topic"
- type = string
- default = null
+variable "override_topic_policy_documents" {
+ description = "List of IAM policy documents that are merged together into the exported document. In merging, statements with non-blank `sid`s will override statements with the same `sid`"
+ type = list(string)
+ default = []
}
-variable "sqs_success_feedback_sample_rate" {
- description = "Percentage of success to sample"
- type = string
- default = null
+variable "enable_default_topic_policy" {
+ description = "Specifies whether to enable the default topic policy. Defaults to `true`"
+ type = bool
+ default = true
}
-variable "sqs_failure_feedback_role_arn" {
- description = "IAM role for failure feedback"
- type = string
- default = null
+variable "topic_policy_statements" {
+ description = "A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage"
+ type = any
+ default = {}
}
-variable "kms_master_key_id" {
- description = "The ID of an AWS-managed customer master key (CMK) for Amazon SNS or a custom CMK"
- type = string
- default = null
-}
+################################################################################
+# Subscription(s)
+################################################################################
-variable "fifo_topic" {
- description = "Boolean indicating whether or not to create a FIFO (first-in-first-out) topic"
+variable "create_subscription" {
+ description = "Determines whether an SNS subscription is created"
type = bool
- default = false
+ default = true
}
-variable "tags" {
- description = "A mapping of tags to assign to all resources"
- type = map(string)
+variable "subscriptions" {
+ description = "A map of subscription definitions to create"
+ type = any
default = {}
}
-
-variable "content_based_deduplication" {
- description = "Boolean indicating whether or not to enable content-based deduplication for FIFO topics."
- type = bool
- default = false
-}
diff --git a/versions.tf b/versions.tf
index d8dd1a4..fa875db 100644
--- a/versions.tf
+++ b/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 4.0"
+ version = ">= 4.40"
}
}
}
diff --git a/wrappers/README.md b/wrappers/README.md
new file mode 100644
index 0000000..75a2a78
--- /dev/null
+++ b/wrappers/README.md
@@ -0,0 +1,100 @@
+# Wrapper for the root module
+
+The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt).
+
+You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module.
+
+This wrapper does not implement any extra functionality.
+
+## Usage with Terragrunt
+
+`terragrunt.hcl`:
+
+```hcl
+terraform {
+ source = "tfr:///terraform-aws-modules/sns/aws//wrappers"
+ # Alternative source:
+ # source = "git::git@github.com:terraform-aws-modules/terraform-aws-sns.git//wrappers?ref=master"
+}
+
+inputs = {
+ defaults = { # Default values
+ create = true
+ tags = {
+ Terraform = "true"
+ Environment = "dev"
+ }
+ }
+
+ items = {
+ my-item = {
+ # omitted... can be any argument supported by the module
+ }
+ my-second-item = {
+ # omitted... can be any argument supported by the module
+ }
+ # omitted...
+ }
+}
+```
+
+## Usage with Terraform
+
+```hcl
+module "wrapper" {
+ source = "terraform-aws-modules/sns/aws//wrappers"
+
+ defaults = { # Default values
+ create = true
+ tags = {
+ Terraform = "true"
+ Environment = "dev"
+ }
+ }
+
+ items = {
+ my-item = {
+ # omitted... can be any argument supported by the module
+ }
+ my-second-item = {
+ # omitted... can be any argument supported by the module
+ }
+ # omitted...
+ }
+}
+```
+
+## Example: Manage multiple S3 buckets in one Terragrunt layer
+
+`eu-west-1/s3-buckets/terragrunt.hcl`:
+
+```hcl
+terraform {
+ source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
+ # Alternative source:
+ # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
+}
+
+inputs = {
+ defaults = {
+ force_destroy = true
+
+ attach_elb_log_delivery_policy = true
+ attach_lb_log_delivery_policy = true
+ attach_deny_insecure_transport_policy = true
+ attach_require_latest_tls_policy = true
+ }
+
+ items = {
+ bucket1 = {
+ bucket = "my-random-bucket-1"
+ }
+ bucket2 = {
+ bucket = "my-random-bucket-2"
+ tags = {
+ Secure = "probably"
+ }
+ }
+ }
+}
+```
diff --git a/wrappers/main.tf b/wrappers/main.tf
new file mode 100644
index 0000000..da5d84a
--- /dev/null
+++ b/wrappers/main.tf
@@ -0,0 +1,28 @@
+module "wrapper" {
+ source = "../"
+
+ for_each = var.items
+
+ create = try(each.value.create, var.defaults.create, true)
+ tags = try(each.value.tags, var.defaults.tags, {})
+ name = try(each.value.name, var.defaults.name, null)
+ use_name_prefix = try(each.value.use_name_prefix, var.defaults.use_name_prefix, false)
+ application_feedback = try(each.value.application_feedback, var.defaults.application_feedback, {})
+ content_based_deduplication = try(each.value.content_based_deduplication, var.defaults.content_based_deduplication, false)
+ delivery_policy = try(each.value.delivery_policy, var.defaults.delivery_policy, null)
+ display_name = try(each.value.display_name, var.defaults.display_name, null)
+ fifo_topic = try(each.value.fifo_topic, var.defaults.fifo_topic, false)
+ firehose_feedback = try(each.value.firehose_feedback, var.defaults.firehose_feedback, {})
+ http_feedback = try(each.value.http_feedback, var.defaults.http_feedback, {})
+ kms_master_key_id = try(each.value.kms_master_key_id, var.defaults.kms_master_key_id, null)
+ lambda_feedback = try(each.value.lambda_feedback, var.defaults.lambda_feedback, {})
+ topic_policy = try(each.value.topic_policy, var.defaults.topic_policy, null)
+ sqs_feedback = try(each.value.sqs_feedback, var.defaults.sqs_feedback, {})
+ create_topic_policy = try(each.value.create_topic_policy, var.defaults.create_topic_policy, true)
+ source_topic_policy_documents = try(each.value.source_topic_policy_documents, var.defaults.source_topic_policy_documents, [])
+ override_topic_policy_documents = try(each.value.override_topic_policy_documents, var.defaults.override_topic_policy_documents, [])
+ enable_default_topic_policy = try(each.value.enable_default_topic_policy, var.defaults.enable_default_topic_policy, true)
+ topic_policy_statements = try(each.value.topic_policy_statements, var.defaults.topic_policy_statements, {})
+ create_subscription = try(each.value.create_subscription, var.defaults.create_subscription, true)
+ subscriptions = try(each.value.subscriptions, var.defaults.subscriptions, {})
+}
diff --git a/wrappers/outputs.tf b/wrappers/outputs.tf
new file mode 100644
index 0000000..5da7c09
--- /dev/null
+++ b/wrappers/outputs.tf
@@ -0,0 +1,5 @@
+output "wrapper" {
+ description = "Map of outputs of a wrapper."
+ value = module.wrapper
+ # sensitive = false # No sensitive module output found
+}
diff --git a/wrappers/variables.tf b/wrappers/variables.tf
new file mode 100644
index 0000000..a6ea096
--- /dev/null
+++ b/wrappers/variables.tf
@@ -0,0 +1,11 @@
+variable "defaults" {
+ description = "Map of default values which will be used for each item."
+ type = any
+ default = {}
+}
+
+variable "items" {
+ description = "Maps of items to create a wrapper from. Values are passed through to the module."
+ type = any
+ default = {}
+}
diff --git a/wrappers/versions.tf b/wrappers/versions.tf
new file mode 100644
index 0000000..51cad10
--- /dev/null
+++ b/wrappers/versions.tf
@@ -0,0 +1,3 @@
+terraform {
+ required_version = ">= 0.13.1"
+}