From ff131eb904358d7956d3941bae691ca710daa838 Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sun, 1 Oct 2023 14:15:00 +0200 Subject: [PATCH] feat: Add support for EventBridge Pipes (#92) --- .pre-commit-config.yaml | 2 +- README.md | 31 +- examples/complete/README.md | 13 +- examples/complete/main.tf | 3 +- examples/complete/outputs.tf | 57 ++++ examples/with-pipes/README.md | 77 +++++ examples/with-pipes/main.tf | 475 +++++++++++++++++++++++++++++++ examples/with-pipes/outputs.tf | 32 +++ examples/with-pipes/variables.tf | 0 examples/with-pipes/versions.tf | 18 ++ iam.tf | 10 +- iam_pipes.tf | 397 ++++++++++++++++++++++++++ main.tf | 183 ++++++++++++ outputs.tf | 79 +++++ variables.tf | 18 ++ 15 files changed, 1386 insertions(+), 9 deletions(-) create mode 100644 examples/with-pipes/README.md create mode 100644 examples/with-pipes/main.tf create mode 100644 examples/with-pipes/outputs.tf create mode 100644 examples/with-pipes/variables.tf create mode 100644 examples/with-pipes/versions.tf create mode 100644 iam_pipes.tf diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0f34283..b5adebd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.81.0 + rev: v1.83.4 hooks: - id: terraform_fmt - id: terraform_validate diff --git a/README.md b/README.md index 9262527..6947b3f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Terraform module to create EventBridge resources. ## Supported Features -- Creates AWS EventBridge Resources (bus, rules, targets, permissions, connections, destinations, schedules and schedule groups) +- Creates AWS EventBridge Resources (bus, rules, targets, permissions, connections, destinations, pipes, schedules and schedule groups) - Attach resources to an existing EventBridge bus - Support AWS EventBridge Archives and Replays - Conditional creation for many types of resources @@ -345,6 +345,7 @@ module "eventbridge" { create_api_destinations = false # to control creation of EventBridge Destination resources create_schedule_groups = false # to control creation of EventBridge Schedule Group resources create_schedules = false # to control creation of EventBridge Schedule resources + create_pipes = false # to control creation of EventBridge Pipes resources attach_cloudwatch_policy = false attach_ecs_policy = false @@ -371,6 +372,7 @@ module "eventbridge" { * [ECS Scheduling Events](https://github.com/terraform-aws-modules/terraform-aws-eventbridge/tree/master/examples/with-ecs-scheduling) - Use default bus to schedule events on ECS. * [Lambda Scheduling Events](https://github.com/terraform-aws-modules/terraform-aws-eventbridge/tree/master/examples/with-lambda-scheduling) - Trigger Lambda functions on schedule (works only with default bus). * [API Destination](https://github.com/terraform-aws-modules/terraform-aws-eventbridge/tree/master/examples/with-api-destination) - Control access to EventBridge using API destinations. +* [Pipes](https://github.com/terraform-aws-modules/terraform-aws-eventbridge/tree/master/examples/with-pipes) - EventBridge Pipes with lots of configurations. @@ -411,6 +413,7 @@ No modules. | [aws_iam_policy.kinesis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.kinesis_firehose](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.sfn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | @@ -424,29 +427,37 @@ No modules. | [aws_iam_policy_attachment.kinesis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | | [aws_iam_policy_attachment.kinesis_firehose](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | | [aws_iam_policy_attachment.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | +| [aws_iam_policy_attachment.service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | | [aws_iam_policy_attachment.sfn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | | [aws_iam_policy_attachment.sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | | [aws_iam_policy_attachment.sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | | [aws_iam_policy_attachment.tracing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | | [aws_iam_role.eventbridge](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.eventbridge_pipe](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy_attachment.additional_many](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.additional_one](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_pipes_pipe.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/pipes_pipe) | resource | | [aws_scheduler_schedule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/scheduler_schedule) | resource | | [aws_scheduler_schedule_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/scheduler_schedule_group) | resource | | [aws_schemas_discoverer.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/schemas_discoverer) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_cloudwatch_event_bus.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/cloudwatch_event_bus) | data source | | [aws_iam_policy.tracing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) | data source | | [aws_iam_policy_document.additional_inline](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.api_destination](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.assume_role_pipe](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.ecs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.kinesis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.kinesis_firehose](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.sfn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs @@ -455,6 +466,7 @@ No modules. | [api\_destinations](#input\_api\_destinations) | A map of objects with EventBridge Destination definitions. | `map(any)` | `{}` | no | | [append\_connection\_postfix](#input\_append\_connection\_postfix) | Controls whether to append '-connection' to the name of the connection | `bool` | `true` | no | | [append\_destination\_postfix](#input\_append\_destination\_postfix) | Controls whether to append '-destination' to the name of the destination | `bool` | `true` | no | +| [append\_pipe\_postfix](#input\_append\_pipe\_postfix) | Controls whether to append '-pipe' to the name of the pipe | `bool` | `true` | no | | [append\_rule\_postfix](#input\_append\_rule\_postfix) | Controls whether to append '-rule' to the name of the rule | `bool` | `true` | no | | [append\_schedule\_group\_postfix](#input\_append\_schedule\_group\_postfix) | Controls whether to append '-group' to the name of the schedule group | `bool` | `true` | no | | [append\_schedule\_postfix](#input\_append\_schedule\_postfix) | Controls whether to append '-schedule' to the name of the schedule | `bool` | `true` | no | @@ -483,6 +495,7 @@ No modules. | [create\_bus](#input\_create\_bus) | Controls whether EventBridge Bus resource should be created | `bool` | `true` | no | | [create\_connections](#input\_create\_connections) | Controls whether EventBridge Connection resources should be created | `bool` | `false` | no | | [create\_permissions](#input\_create\_permissions) | Controls whether EventBridge Permission resources should be created | `bool` | `true` | no | +| [create\_pipes](#input\_create\_pipes) | Controls whether EventBridge Pipes resources should be created | `bool` | `true` | no | | [create\_role](#input\_create\_role) | Controls whether IAM roles should be created | `bool` | `true` | no | | [create\_rules](#input\_create\_rules) | Controls whether EventBridge Rule resources should be created | `bool` | `true` | no | | [create\_schedule\_groups](#input\_create\_schedule\_groups) | Controls whether EventBridge Schedule Group resources should be created | `bool` | `true` | no | @@ -497,6 +510,7 @@ No modules. | [number\_of\_policies](#input\_number\_of\_policies) | Number of policies to attach to IAM role | `number` | `0` | no | | [number\_of\_policy\_jsons](#input\_number\_of\_policy\_jsons) | Number of policies JSON to attach to IAM role | `number` | `0` | no | | [permissions](#input\_permissions) | A map of objects with EventBridge Permission definitions. | `map(any)` | `{}` | no | +| [pipes](#input\_pipes) | A map of objects with EventBridge Pipe definitions. | `any` | `{}` | no | | [policies](#input\_policies) | List of policy statements ARN to attach to IAM role | `list(string)` | `[]` | no | | [policy](#input\_policy) | An additional policy document ARN to attach to IAM role | `string` | `null` | no | | [policy\_json](#input\_policy\_json) | An additional policy document as JSON to attach to IAM role | `string` | `null` | no | @@ -525,21 +539,36 @@ No modules. | Name | Description | |------|-------------| | [eventbridge\_api\_destination\_arns](#output\_eventbridge\_api\_destination\_arns) | The EventBridge API Destination ARNs | +| [eventbridge\_api\_destinations](#output\_eventbridge\_api\_destinations) | The EventBridge API Destinations created and their attributes | | [eventbridge\_archive\_arns](#output\_eventbridge\_archive\_arns) | The EventBridge Archive ARNs | +| [eventbridge\_archives](#output\_eventbridge\_archives) | The EventBridge Archives created and their attributes | +| [eventbridge\_bus](#output\_eventbridge\_bus) | The EventBridge Bus created and their attributes | | [eventbridge\_bus\_arn](#output\_eventbridge\_bus\_arn) | The EventBridge Bus ARN | | [eventbridge\_bus\_name](#output\_eventbridge\_bus\_name) | The EventBridge Bus Name | | [eventbridge\_connection\_arns](#output\_eventbridge\_connection\_arns) | The EventBridge Connection Arns | | [eventbridge\_connection\_ids](#output\_eventbridge\_connection\_ids) | The EventBridge Connection IDs | +| [eventbridge\_connections](#output\_eventbridge\_connections) | The EventBridge Connections created and their attributes | +| [eventbridge\_iam\_roles](#output\_eventbridge\_iam\_roles) | The EventBridge IAM roles created and their attributes | | [eventbridge\_permission\_ids](#output\_eventbridge\_permission\_ids) | The EventBridge Permission IDs | +| [eventbridge\_permissions](#output\_eventbridge\_permissions) | The EventBridge Permissions created and their attributes | +| [eventbridge\_pipe\_arns](#output\_eventbridge\_pipe\_arns) | The EventBridge Pipes ARNs | +| [eventbridge\_pipe\_ids](#output\_eventbridge\_pipe\_ids) | The EventBridge Pipes IDs | +| [eventbridge\_pipe\_role\_arns](#output\_eventbridge\_pipe\_role\_arns) | The ARNs of the IAM role created for EventBridge Pipes | +| [eventbridge\_pipe\_role\_names](#output\_eventbridge\_pipe\_role\_names) | The names of the IAM role created for EventBridge Pipes | +| [eventbridge\_pipes](#output\_eventbridge\_pipes) | The EventBridge Pipes created and their attributes | +| [eventbridge\_pipes\_iam\_roles](#output\_eventbridge\_pipes\_iam\_roles) | The EventBridge Pipes IAM roles created and their attributes | | [eventbridge\_role\_arn](#output\_eventbridge\_role\_arn) | The ARN of the IAM role created for EventBridge | | [eventbridge\_role\_name](#output\_eventbridge\_role\_name) | The name of the IAM role created for EventBridge | | [eventbridge\_rule\_arns](#output\_eventbridge\_rule\_arns) | The EventBridge Rule ARNs | | [eventbridge\_rule\_ids](#output\_eventbridge\_rule\_ids) | The EventBridge Rule IDs | +| [eventbridge\_rules](#output\_eventbridge\_rules) | The EventBridge Rules created and their attributes | | [eventbridge\_schedule\_arns](#output\_eventbridge\_schedule\_arns) | The EventBridge Schedule ARNs created | | [eventbridge\_schedule\_group\_arns](#output\_eventbridge\_schedule\_group\_arns) | The EventBridge Schedule Group ARNs | | [eventbridge\_schedule\_group\_ids](#output\_eventbridge\_schedule\_group\_ids) | The EventBridge Schedule Group IDs | | [eventbridge\_schedule\_group\_states](#output\_eventbridge\_schedule\_group\_states) | The EventBridge Schedule Group states | +| [eventbridge\_schedule\_groups](#output\_eventbridge\_schedule\_groups) | The EventBridge Schedule Groups created and their attributes | | [eventbridge\_schedule\_ids](#output\_eventbridge\_schedule\_ids) | The EventBridge Schedule IDs created | +| [eventbridge\_schedules](#output\_eventbridge\_schedules) | The EventBridge Schedules created and their attributes | ## Authors diff --git a/examples/complete/README.md b/examples/complete/README.md index 9c9e34b..e4f7780 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -39,7 +39,7 @@ Note that this example may create resources which cost money. Run `terraform des | [disabled](#module\_disabled) | ../../ | n/a | | [ecs](#module\_ecs) | terraform-aws-modules/ecs/aws | ~> 3.0 | | [eventbridge](#module\_eventbridge) | ../../ | n/a | -| [lambda](#module\_lambda) | terraform-aws-modules/lambda/aws | ~> 2.0 | +| [lambda](#module\_lambda) | terraform-aws-modules/lambda/aws | ~> 6.0 | | [step\_function](#module\_step\_function) | terraform-aws-modules/step-functions/aws | ~> 2.0 | ## Resources @@ -66,7 +66,18 @@ No inputs. | Name | Description | |------|-------------| +| [eventbridge\_api\_destinations](#output\_eventbridge\_api\_destinations) | The EventBridge API Destinations created and their attributes | +| [eventbridge\_archives](#output\_eventbridge\_archives) | The EventBridge Archives created and their attributes | +| [eventbridge\_bus](#output\_eventbridge\_bus) | The EventBridge Bus created and their attributes | | [eventbridge\_bus\_arn](#output\_eventbridge\_bus\_arn) | The EventBridge Bus ARN | +| [eventbridge\_connections](#output\_eventbridge\_connections) | The EventBridge Connections created and their attributes | +| [eventbridge\_iam\_roles](#output\_eventbridge\_iam\_roles) | The EventBridge IAM roles created and their attributes | +| [eventbridge\_permissions](#output\_eventbridge\_permissions) | The EventBridge Permissions created and their attributes | +| [eventbridge\_pipes](#output\_eventbridge\_pipes) | The EventBridge Pipes created and their attributes | +| [eventbridge\_pipes\_iam\_roles](#output\_eventbridge\_pipes\_iam\_roles) | The EventBridge Pipes IAM roles created and their attributes | | [eventbridge\_rule\_arns](#output\_eventbridge\_rule\_arns) | The EventBridge Rule ARNs | | [eventbridge\_rule\_ids](#output\_eventbridge\_rule\_ids) | The EventBridge Rule IDs | +| [eventbridge\_rules](#output\_eventbridge\_rules) | The EventBridge Rules created and their attributes | +| [eventbridge\_schedule\_groups](#output\_eventbridge\_schedule\_groups) | The EventBridge Schedule Groups created and their attributes | +| [eventbridge\_schedules](#output\_eventbridge\_schedules) | The EventBridge Schedules created and their attributes | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 7e7c9d1..cf2ff10 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -5,7 +5,6 @@ provider "aws" { skip_metadata_api_check = true skip_region_validation = true skip_credentials_validation = true - skip_requesting_account_id = true } module "eventbridge" { @@ -338,7 +337,7 @@ EOF module "lambda" { source = "terraform-aws-modules/lambda/aws" - version = "~> 2.0" + version = "~> 6.0" function_name = "${random_pet.this.id}-lambda" handler = "index.lambda_handler" diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index 89ca939..2fb6bf8 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -12,3 +12,60 @@ output "eventbridge_rule_arns" { description = "The EventBridge Rule ARNs" value = module.eventbridge.eventbridge_rule_arns } + +# Resources +output "eventbridge_bus" { + description = "The EventBridge Bus created and their attributes" + value = module.eventbridge.eventbridge_bus +} + +output "eventbridge_archives" { + description = "The EventBridge Archives created and their attributes" + value = module.eventbridge.eventbridge_archives +} + +output "eventbridge_permissions" { + description = "The EventBridge Permissions created and their attributes" + value = module.eventbridge.eventbridge_permissions +} + +output "eventbridge_connections" { + description = "The EventBridge Connections created and their attributes" + value = module.eventbridge.eventbridge_connections +} + +output "eventbridge_api_destinations" { + description = "The EventBridge API Destinations created and their attributes" + value = module.eventbridge.eventbridge_api_destinations +} + +output "eventbridge_rules" { + description = "The EventBridge Rules created and their attributes" + value = module.eventbridge.eventbridge_rules +} + +output "eventbridge_schedule_groups" { + description = "The EventBridge Schedule Groups created and their attributes" + value = module.eventbridge.eventbridge_schedule_groups +} + +output "eventbridge_schedules" { + description = "The EventBridge Schedules created and their attributes" + value = module.eventbridge.eventbridge_schedules +} + +output "eventbridge_pipes" { + description = "The EventBridge Pipes created and their attributes" + value = module.eventbridge.eventbridge_pipes +} + +# IAM Roles +output "eventbridge_pipes_iam_roles" { + description = "The EventBridge Pipes IAM roles created and their attributes" + value = module.eventbridge.eventbridge_pipes_iam_roles +} + +output "eventbridge_iam_roles" { + description = "The EventBridge IAM roles created and their attributes" + value = module.eventbridge.eventbridge_iam_roles +} diff --git a/examples/with-pipes/README.md b/examples/with-pipes/README.md new file mode 100644 index 0000000..a0b5258 --- /dev/null +++ b/examples/with-pipes/README.md @@ -0,0 +1,77 @@ +# EventBridge Pipes Example + +Configuration in this directory creates EventBridge Pipes in multiple configurations. + +## Usage + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.64 | +| [null](#requirement\_null) | >= 2.0 | +| [random](#requirement\_random) | >= 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 4.64 | +| [null](#provider\_null) | >= 2.0 | +| [random](#provider\_random) | >= 3.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [eventbridge](#module\_eventbridge) | ../../ | n/a | +| [lambda\_target](#module\_lambda\_target) | terraform-aws-modules/lambda/aws | ~> 6.0 | +| [step\_function\_target](#module\_step\_function\_target) | terraform-aws-modules/step-functions/aws | ~> 2.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_event_api_destination.external](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_api_destination) | resource | +| [aws_cloudwatch_event_bus.target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_bus) | resource | +| [aws_cloudwatch_event_connection.external](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_connection) | resource | +| [aws_cloudwatch_log_group.target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_stream.target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_stream) | resource | +| [aws_dynamodb_table.source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | +| [aws_iam_role.eventbridge_pipe](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.pipe](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_kinesis_stream.source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kinesis_stream) | resource | +| [aws_sqs_queue.dlq](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue.source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue.target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [null_resource.download_package](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | +| [aws_iam_policy_document.assume_role_pipe](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [eventbridge\_pipe\_arns](#output\_eventbridge\_pipe\_arns) | The EventBridge Pipes ARNs | +| [eventbridge\_pipe\_ids](#output\_eventbridge\_pipe\_ids) | The EventBridge Pipes IDs | +| [eventbridge\_pipe\_role\_arns](#output\_eventbridge\_pipe\_role\_arns) | The ARNs of the IAM role created for EventBridge Pipes | +| [eventbridge\_pipe\_role\_names](#output\_eventbridge\_pipe\_role\_names) | The names of the IAM role created for EventBridge Pipes | +| [eventbridge\_pipes](#output\_eventbridge\_pipes) | The EventBridge Pipes created and their attributes | +| [eventbridge\_pipes\_iam\_roles](#output\_eventbridge\_pipes\_iam\_roles) | The EventBridge Pipes IAM roles created and their attributes | + diff --git a/examples/with-pipes/main.tf b/examples/with-pipes/main.tf new file mode 100644 index 0000000..08ded36 --- /dev/null +++ b/examples/with-pipes/main.tf @@ -0,0 +1,475 @@ +provider "aws" { + region = "eu-west-1" + + # Make it faster by skipping something + skip_metadata_api_check = true + skip_region_validation = true + skip_credentials_validation = true +} + +module "eventbridge" { + source = "../../" + + create_bus = true + bus_name = "example" + + create_api_destinations = true + create_connections = true + + connections = { + smee = { + authorization_type = "API_KEY" + auth_parameters = { + api_key = { + key = "x-signature-id" + value = random_pet.this.id + } + } + } + } + + api_destinations = { + smee = { # This key should match the key inside "connections" + description = "my smee endpoint" + invocation_endpoint = "https://smee.io/6hx6fuQaVUKLfALn" + http_method = "POST" + invocation_rate_limit_per_second = 200 + } + } + + pipes = { + # With enrichment via API Destination + enrichment = { + source = aws_sqs_queue.source.arn + target = aws_sqs_queue.target.arn + + enrichment = "smee" # This key should match the key inside "api_destinations" + enrichment_parameters = { + input_template = jsonencode({ input : "yes" }) + + http_parameters = { + path_parameter_values = ["example-path-param"] + + header_parameters = { + "example-header" = "example-value" + "second-example-header" = "second-example-value" + } + + query_string_parameters = { + "example-query-string" = "example-value" + "second-example-query-string" = "second-example-value" + } + } + } + + tags = { + Pipe = "enrichment" + } + } + + # With enrichment via API Destination created outside of the module + external_enrichment = { + source = aws_sqs_queue.source.arn + target = aws_sqs_queue.target.arn + + enrichment = aws_cloudwatch_event_api_destination.external.arn + + tags = { + Pipe = "external_enrichment" + } + } + + # With SQS source/target parameters and filtering + sqs_source_sqs_target = { + source = aws_sqs_queue.source.arn + target = aws_sqs_queue.target.arn + + source_parameters = { + # Filter criteria (max 5 filters) + filter_criteria = { + filter1 = { + pattern = jsonencode({ source = ["event-source1"] }) + } + filter2 = { + pattern = jsonencode({ source = ["event-source2"] }) + } + } + + sqs_queue_parameters = { + batch_size = 2 + maximum_batching_window_in_seconds = 61 + } + } + + # target_parameters = { + # # Only supported for target FIFO SQS Queues + # sqs_queue_parameters = { + # message_deduplication_id = "deduplication-id" + # message_group_id = "group1" + # } + # } + + tags = { + Pipe = "sqs_source_sqs_target" + } + } + + # With DynamoDB Stream source and SQS target + dynamodb_stream_source_sqs_target = { + source = aws_dynamodb_table.source.stream_arn + target = aws_sqs_queue.target.arn + + source_parameters = { + dynamodb_stream_parameters = { + batch_size = 10 + maximum_batching_window_in_seconds = 50 + maximum_record_age_in_seconds = 100 + maximum_retry_attempts = 300 + on_partial_batch_item_failure = "AUTOMATIC_BISECT" + parallelization_factor = 5 + starting_position = "LATEST" + dead_letter_config = { + arn = aws_sqs_queue.dlq.arn + } + } + } + + tags = { + Pipe = "dynamodb_stream_source_sqs_target" + } + } + + # With Kinesis Stream source and CloudWatch Log + kinesis_source_cloudwatch_target = { + source = aws_kinesis_stream.source.arn + target = aws_cloudwatch_log_group.target.arn + + source_parameters = { + kinesis_stream_parameters = { + batch_size = 7 + maximum_batching_window_in_seconds = 90 + maximum_record_age_in_seconds = 100 + maximum_retry_attempts = 4 + on_partial_batch_item_failure = "AUTOMATIC_BISECT" + parallelization_factor = 5 + starting_position = "TRIM_HORIZON" + starting_position_timestamp = null + dead_letter_config = { + arn = aws_sqs_queue.dlq.arn + } + } + } + + target_parameters = { + cloudwatch_logs_parameters = { + log_stream_name = aws_cloudwatch_log_stream.target.arn + } + } + + tags = { + Pipe = "kinesis_source_cloudwatch_target" + } + } + + # With SQS Queue source and EventBridge target + sqs_source_eventbridge_target = { + source = aws_sqs_queue.source.arn + target = aws_cloudwatch_event_bus.target.arn + + target_parameters = { + eventbridge_event_bus_parameters = { + detail_type = "my-target" + endpoint_id = "endpoint.com" + resources = [] + source = 20 + } + } + + tags = { + Pipe = "sqs_source_eventbridge_target" + } + } + + # With SQS Queue source and Lambda target + sqs_source_lambda_target = { + source = aws_sqs_queue.source.arn + target = module.lambda_target.lambda_function_arn + + target_parameters = { + lambda_function_parameters = { + invocation_type = "REQUEST_RESPONSE" + } + } + + tags = { + Pipe = "sqs_source_lambda_target" + } + } + + # With SQS Queue source and StepFunction target + sqs_source_step_function_target = { + source = aws_sqs_queue.source.arn + target = module.step_function_target.state_machine_arn + + target_parameters = { + step_function_state_machine_parameters = { + invocation_type = "FIRE_AND_FORGET" + } + } + + tags = { + Pipe = "sqs_source_step_function_target" + } + } + + # With SQS Queue source and HTTP target + sqs_source_http_target = { + source = aws_sqs_queue.source.arn + target = aws_cloudwatch_event_api_destination.external.arn + + target_parameters = { + http_parameters = { + header_parameters = { + "x-my-header" = "my-value" + } + path_parameter_values = ["user1"] + query_string_parameters = { + "key1" = "value1" + } + } + } + + tags = { + Pipe = "sqs_source_http_target" + } + } + + # Minimal with specific IAM role name to create + minimal_role_name_prefix = { + role_name_prefix = "something" + + source = aws_sqs_queue.source.arn + target = aws_sqs_queue.target.arn + + role_tags = { + MyRoleTag = "TagValue" + } + + tags = { + Pipe = "minimal_role_name_prefix" + } + } + + # Minimal with IAM role created outside of the module + minimal_external_role = { + create_role = false + role_arn = aws_iam_role.eventbridge_pipe.arn + + source = aws_sqs_queue.source.arn + target = aws_sqs_queue.target.arn + + tags = { + Pipe = "minimal_external_role" + } + } + + # No filtering, source/target parameters, enrichment + minimal = { + source = aws_sqs_queue.source.arn + target = aws_sqs_queue.target.arn + + tags = { + Pipe = "minimal" + } + } + } +} + +################## +# Extra resources +################## + +resource "random_pet" "this" { + length = 2 +} + + +############################### +# API Destination / Connection +############################### + +resource "aws_cloudwatch_event_api_destination" "external" { + name = "${random_pet.this.id}-external" + invocation_endpoint = "https://smee.io/6hx6fuQaVUKLfALn" + http_method = "POST" + connection_arn = aws_cloudwatch_event_connection.external.arn +} + +resource "aws_cloudwatch_event_connection" "external" { + name = "${random_pet.this.id}-external" + authorization_type = "API_KEY" + + auth_parameters { + api_key { + key = "x-signature" + value = "1234" + } + } +} + +################################# +# IAM role for EventBridge Pipes +################################# + +data "aws_iam_policy_document" "assume_role_pipe" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["pipes.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "eventbridge_pipe" { + name = "${random_pet.this.id}-pipe" + assume_role_policy = data.aws_iam_policy_document.assume_role_pipe.json +} + +# PowerUserAccess policy is used here just for testing purposes +resource "aws_iam_role_policy_attachment" "pipe" { + role = aws_iam_role.eventbridge_pipe.name + policy_arn = "arn:aws:iam::aws:policy/PowerUserAccess" +} + +############# +# SQS Queues +############# + +resource "aws_sqs_queue" "source" { + name = "${random_pet.this.id}-source" +} + +resource "aws_sqs_queue" "target" { + name = "${random_pet.this.id}-target" +} + +resource "aws_sqs_queue" "dlq" { + name = "${random_pet.this.id}-dlq" +} + +############################# +# DynamoDB Table with Stream +############################# + +resource "aws_dynamodb_table" "source" { + name = "${random_pet.this.id}-source" + + hash_key = "id" + range_key = "title" + table_class = "STANDARD" + read_capacity = 1 + write_capacity = 1 + + stream_enabled = true + stream_view_type = "NEW_AND_OLD_IMAGES" + + attribute { + name = "id" + type = "N" + } + + attribute { + name = "title" + type = "S" + } +} + +################# +# Kinesis Stream +################# + +resource "aws_kinesis_stream" "source" { + name = "${random_pet.this.id}-source" + + shard_count = 1 +} + +################################## +# CloudWatch Log Group and Stream +################################## + +resource "aws_cloudwatch_log_group" "target" { + name = "${random_pet.this.id}-target" +} + +resource "aws_cloudwatch_log_stream" "target" { + log_group_name = aws_cloudwatch_log_group.target.name + name = "${random_pet.this.id}-target" +} + +################## +# EventBridge Bus +################## + +resource "aws_cloudwatch_event_bus" "target" { + name = "${random_pet.this.id}-target" +} + +############################################# +# Using packaged function from Lambda module +############################################# + +module "lambda_target" { + source = "terraform-aws-modules/lambda/aws" + version = "~> 6.0" + + function_name = "${random_pet.this.id}-lambda" + handler = "index.lambda_handler" + runtime = "python3.8" + + create_package = false + local_existing_package = local.downloaded +} + +locals { + package_url = "https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-lambda/master/examples/fixtures/python3.8-zip/existing_package.zip" + downloaded = "downloaded_package_${md5(local.package_url)}.zip" +} + +resource "null_resource" "download_package" { + triggers = { + downloaded = local.downloaded + } + + provisioner "local-exec" { + command = "curl -L -o ${local.downloaded} ${local.package_url}" + } +} + +#################### +# AWS Step Function +#################### + +module "step_function_target" { + source = "terraform-aws-modules/step-functions/aws" + version = "~> 2.0" + + name = "${random_pet.this.id}-target" + + definition = < merge(v, { + role_name = try(v.role_name_prefix, v.name), + service_integrations = { + # Source only + dynamodb = { + values = [v.source] + matching_services = ["dynamodb"] + }, + mq = { + values = [v.source] + matching_services = ["mq"] + }, + msk = { + values = [v.source], + matching_services = ["kafka"] + }, + sqs_source = { + values = [v.source], + matching_services = ["sqs"] + }, + kinesis_source = { + values = [v.source], + matching_services = ["kinesis"] + }, + + # Enrichment / Target + lambda = { + values = [v.target, try(aws_cloudwatch_event_api_destination.this[v.enrichment].arn, null)], + matching_services = ["lambda"] + }, + step_functions = { + values = [v.target, try(aws_cloudwatch_event_api_destination.this[v.enrichment].arn, null)], + matching_services = ["states"] + }, + api_gateway = { + values = [v.target, try(aws_cloudwatch_event_api_destination.this[v.enrichment].arn, null)], + matching_services = ["execute-api"] + }, + api_destination = { # Sample ARN of API Destination: "arn:aws:events:eu-west-1:835367859851:api-destination/proud-worm-external" + values = [v.target, try(aws_cloudwatch_event_api_destination.this[v.enrichment].arn, null)], + matching_services = ["events"] + matching_resource_startswith = "api-destination/" + }, + + # Target + sqs_target = { + values = [v.target], + matching_services = ["sqs"] + }, + kinesis_target = { + values = [v.target], + matching_services = ["kinesis"] + }, + batch = { + values = [v.target], + matching_services = ["batch"] + }, + logs = { + values = [v.target], + matching_services = ["logs"] + }, + ecs = { + values = [replace(v.target, "/:\\d+$/", ":*")], + matching_services = ["ecs"] + }, + ecs_iam_passrole = { + values = ["*"], + matching_values = [v.target], + matching_services = ["ecs"] + }, + eventbridge = { # Sample ARN of EventBridge Bus: "arn:aws:events:eu-west-1:835367859851:event-bus/default" + values = [v.target], + matching_services = ["events"] + matching_resource_startswith = "event-bus/" + }, + firehose = { + values = [v.target], + matching_services = ["firehose"] + }, + inspector = { + values = [v.target], + matching_services = ["inspector"] + }, + redshift = { + values = [v.target], + matching_services = ["redshift"] + }, + sagemaker = { + values = [v.target], + matching_services = ["sagemaker"] + }, + sns = { + values = [v.target], + matching_services = ["sns"] + }, + + # Dead-letter queue (DLQ) for DynamoDB Streams and Kinesis Streams + sqs_dlq = { + values = [ + try(v.source_parameters.dynamodb_stream_parameters.dead_letter_config.arn, null), + try(v.source_parameters.kinesis_stream_parameters.dead_letter_config.arn, null) + ], + matching_services = ["sqs"] + }, + + } + }) + if local.create_role_for_pipes && try(v.create_role, true) + } + + service_integrations_for_pipes = { + for k, v in local.role_for_pipes : + k => { + for s_k, s_v in v.service_integrations : + # s_k - is a key in aws_service_policies + # value - is a list of matched ARNs + # Sample ARNs: + # arn:aws:kafka:eu-west-1:835367859851:cluster/cluster-name/cluster-uuid + # arn:aws:events:eu-west-1:835367859851:api-destination/proud-worm-external + + s_k => [ + for arn in compact(try(s_v.matching_values, s_v.values)) : arn + if(arn == "*" || try(contains(s_v.matching_services, split(":", arn)[2]), true)) && try(startswith(split(":", arn)[5], s_v.matching_resource_startswith), true) + ] + } + } + + # Map of all available IAM policies constructs for AWS services + # + # See more - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-permissions.html + # + # Notes: + # * `effect` - "Allow" or "Deny" in policy statement (default: Allow) + # * `actions` - list of actions in policy statement + # * `condition` - list of condition in policy statement + + aws_service_policies = { + sqs_source = { + actions = [ + "sqs:ReceiveMessage", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes" + ] + } + + sqs_target = { + actions = [ + "sqs:SendMessage" + ] + } + + sqs_dlq = { + actions = [ + "sqs:SendMessage" # ??? Not sure which IAM policy to use for DLQ + ] + } + + dynamodb = { + actions = [ + "dynamodb:DescribeStream", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:ListStreams" + ] + } + + kinesis_source = { + actions = [ + "kinesis:DescribeStream", + "kinesis:DescribeStreamSummary", + "kinesis:GetRecords", + "kinesis:GetShardIterator", + "kinesis:ListShards", + "kinesis:ListStreams", + "kinesis:SubscribeToShard" + ] + } + + kinesis_target = { + actions = [ + "kinesis:PutRecord" + ] + } + + mq = { + actions = [ + "mq:DescribeBroker", + "secretsmanager:GetSecretValue", + "ec2:CreateNetworkInterface", + "ec2:DeleteNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + } + + msk = { + # Read this for more: https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-msk.html#pipes-msk-permissions-iam-policy + actions = [ + "kafka:DescribeClusterV2", + "kafka:GetBootstrapBrokers", + "ec2:CreateNetworkInterface", + "ec2:DeleteNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + } + + lambda = { + actions = [ + "lambda:InvokeFunction" + ] + } + + step_functions = { + actions = [ + "states:StartExecution" + ] + } + + api_gateway = { + actions = [ + "execute-api:Invoke" + ] + } + + api_destination = { + actions = [ + "events:InvokeApiDestination" + ] + } + + batch = { + actions = [ + "batch:SubmitJob" + ] + } + + logs = { + actions = [ + "logs:DescribeLogGroups", + "logs:DescribeLogStreams", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + } + + ecs = { + actions = [ + "ecs:RunTask" + ] + } + + ecs_iam_passrole = { + actions = [ + "iam:PassRole" + ] + } + + eventbridge = { + actions = [ + "events:PutEvents" + ] + } + + firehose = { + actions = [ + "firehose:PutRecord" + ] + } + + inspector = { + actions = [ + "inspector:CreateAssessmentTemplate" # ??? + ] + } + + redshift = { + actions = [ + "redshift-data:ExecuteStatement" # ??? + ] + } + + sagemaker = { + actions = [ + "sagemaker:CreatePipeline" # ??? + ] + } + + sns = { + actions = [ + "sns:Publish" + ] + } + } +} + +################################# +# IAM role for EventBridge Pipes +################################# + +data "aws_iam_policy_document" "assume_role_pipe" { + for_each = local.role_for_pipes + + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["pipes.${data.aws_partition.current.dns_suffix}"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceAccount" + values = [data.aws_caller_identity.current.account_id] + } + + condition { + test = "StringEquals" + variable = "aws:SourceArn" + values = ["arn:aws:pipes:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:pipe/${each.value.Name}"] + } + } +} + +resource "aws_iam_role" "eventbridge_pipe" { + for_each = local.role_for_pipes + + name_prefix = each.value.role_name + + description = try(each.value.role_description, null) + path = try(each.value.role_path, null) + force_detach_policies = try(each.value.role_force_detach_policies, null) + permissions_boundary = try(each.value.role_permissions_boundary, null) + assume_role_policy = data.aws_iam_policy_document.assume_role_pipe[each.key].json + + tags = merge({ Name = each.value.role_name }, try(each.value.role_tags, {}), var.tags) +} + + +############################## +# Predefined service policies +############################## + +data "aws_iam_policy_document" "service" { + for_each = { for k, v in local.service_integrations_for_pipes : k => v if try(v.attach_policies_for_integrations, true) } + + dynamic "statement" { + for_each = { for s_k, s_v in each.value : s_k => s_v if length(compact(s_v)) > 0 } + + content { + effect = lookup(local.aws_service_policies[statement.key], "effect", "Allow") + sid = replace(replace(title(replace("${each.key}${title(statement.key)}", "/[_-]/", " ")), " ", ""), "/[^0-9A-Za-z]*/", "") + actions = local.aws_service_policies[statement.key]["actions"] + resources = tolist(statement.value) + + dynamic "condition" { + for_each = lookup(local.aws_service_policies[statement.key], "condition", []) + content { + test = condition.value.test + variable = condition.value.variable + values = condition.value.values + } + } + } + } +} + +resource "aws_iam_policy" "service" { + for_each = { for k, v in local.role_for_pipes : k => v if try(v.attach_policies_for_integrations, true) } + + name = "${aws_iam_role.eventbridge_pipe[each.key].name}-${each.key}" + policy = data.aws_iam_policy_document.service[each.key].json +} + +resource "aws_iam_policy_attachment" "service" { + for_each = { for k, v in local.role_for_pipes : k => v if try(v.attach_policies_for_integrations, true) } + + name = "${aws_iam_role.eventbridge_pipe[each.key].name}-${each.key}" + roles = [aws_iam_role.eventbridge_pipe[each.key].name] + policy_arn = aws_iam_policy.service[each.key].arn +} diff --git a/main.tf b/main.tf index 6fddaee..c814852 100644 --- a/main.tf +++ b/main.tf @@ -1,3 +1,7 @@ +data "aws_region" "current" {} +data "aws_caller_identity" "current" {} +data "aws_partition" "current" {} + locals { eventbridge_rules = flatten([ for index, rule in var.rules : @@ -42,6 +46,13 @@ locals { "Name" = var.append_schedule_postfix ? "${replace(index, "_", "-")}-schedule" : index }) ]) + eventbridge_pipes = flatten([ + for index, pipe in var.pipes : + merge(pipe, { + "name" = index + "Name" = var.append_pipe_postfix ? "${replace(index, "_", "-")}-pipe" : index + }) + ]) } data "aws_cloudwatch_event_bus" "this" { @@ -594,3 +605,175 @@ resource "aws_scheduler_schedule" "this" { } } } + +resource "aws_pipes_pipe" "this" { + for_each = { for k, v in local.eventbridge_pipes : v.name => v if local.create_pipes } + + name = each.value.Name + + role_arn = try(each.value.role_arn, aws_iam_role.eventbridge_pipe[each.key].arn) + + source = each.value.source + target = each.value.target + + description = lookup(each.value, "description", null) + desired_state = lookup(each.value, "desired_state", null) + + dynamic "source_parameters" { + for_each = try([each.value.source_parameters], []) + + content { + dynamic "filter_criteria" { + for_each = try([source_parameters.value.filter_criteria], []) + + content { + dynamic "filter" { + for_each = try(filter_criteria.value, []) + + content { + pattern = filter.value.pattern + } + } + } + } + + dynamic "sqs_queue_parameters" { + for_each = try([source_parameters.value.sqs_queue_parameters], []) + + content { + batch_size = try(sqs_queue_parameters.value.batch_size, null) + maximum_batching_window_in_seconds = try(sqs_queue_parameters.value.maximum_batching_window_in_seconds, null) + } + } + + dynamic "dynamodb_stream_parameters" { + for_each = try([source_parameters.value.dynamodb_stream_parameters], []) + + content { + batch_size = try(dynamodb_stream_parameters.value.batch_size, null) + maximum_batching_window_in_seconds = try(dynamodb_stream_parameters.value.maximum_batching_window_in_seconds, null) + maximum_record_age_in_seconds = try(dynamodb_stream_parameters.value.maximum_record_age_in_seconds, null) + maximum_retry_attempts = try(dynamodb_stream_parameters.value.maximum_retry_attempts, null) + on_partial_batch_item_failure = try(dynamodb_stream_parameters.value.on_partial_batch_item_failure, null) + parallelization_factor = try(dynamodb_stream_parameters.value.parallelization_factor, null) + starting_position = try(dynamodb_stream_parameters.value.starting_position, null) + + dynamic "dead_letter_config" { + for_each = try([dynamodb_stream_parameters.value.dead_letter_config], []) + + content { + arn = dead_letter_config.value.arn + } + } + } + } + + dynamic "kinesis_stream_parameters" { + for_each = try([source_parameters.value.kinesis_stream_parameters], []) + + content { + batch_size = try(kinesis_stream_parameters.value.batch_size, null) + maximum_batching_window_in_seconds = try(kinesis_stream_parameters.value.maximum_batching_window_in_seconds, null) + maximum_record_age_in_seconds = try(kinesis_stream_parameters.value.maximum_record_age_in_seconds, null) + maximum_retry_attempts = try(kinesis_stream_parameters.value.maximum_retry_attempts, null) + on_partial_batch_item_failure = try(kinesis_stream_parameters.value.on_partial_batch_item_failure, null) + parallelization_factor = try(kinesis_stream_parameters.value.parallelization_factor, null) + starting_position = try(kinesis_stream_parameters.value.starting_position, null) + starting_position_timestamp = try(kinesis_stream_parameters.value.starting_position_timestamp, null) + + dynamic "dead_letter_config" { + for_each = try([kinesis_stream_parameters.value.dead_letter_config], []) + + content { + arn = dead_letter_config.value.arn + } + } + } + } + } + } + + dynamic "target_parameters" { + for_each = try([each.value.target_parameters], []) + + content { + dynamic "sqs_queue_parameters" { + for_each = try([target_parameters.value.sqs_queue_parameters], []) + + content { + message_deduplication_id = try(sqs_queue_parameters.value.message_deduplication_id, null) + message_group_id = try(sqs_queue_parameters.value.message_group_id, null) + } + } + + dynamic "cloudwatch_logs_parameters" { + for_each = try([target_parameters.value.cloudwatch_logs_parameters], []) + + content { + log_stream_name = try(cloudwatch_logs_parameters.value.log_stream_name, null) + timestamp = try(cloudwatch_logs_parameters.value.timestamp, null) + } + } + + dynamic "lambda_function_parameters" { + for_each = try([target_parameters.value.lambda_function_parameters], []) + + content { + invocation_type = try(lambda_function_parameters.value.invocation_type, null) + } + } + + dynamic "step_function_state_machine_parameters" { + for_each = try([target_parameters.value.step_function_state_machine_parameters], []) + + content { + invocation_type = try(step_function_state_machine_parameters.value.invocation_type, null) + } + } + + dynamic "eventbridge_event_bus_parameters" { + for_each = try([target_parameters.value.eventbridge_event_bus_parameters], []) + + content { + detail_type = try(eventbridge_event_bus_parameters.value.detail_type, null) + endpoint_id = try(eventbridge_event_bus_parameters.value.endpoint_id, null) + resources = try(eventbridge_event_bus_parameters.value.resources, null) + source = try(eventbridge_event_bus_parameters.value.source, null) + time = try(eventbridge_event_bus_parameters.value.time, null) + } + } + + dynamic "http_parameters" { + for_each = try([target_parameters.value.http_parameters], []) + + content { + header_parameters = try(http_parameters.value.header_parameters, null) + path_parameter_values = try(http_parameters.value.path_parameter_values, null) + query_string_parameters = try(http_parameters.value.query_string_parameters, null) + } + } + } + } + + enrichment = try(aws_cloudwatch_event_api_destination.this[each.value.enrichment].arn, each.value.enrichment, null) + + dynamic "enrichment_parameters" { + for_each = try([each.value.enrichment_parameters], []) + + content { + input_template = try(each.value.enrichment_parameters.input_template, null) + + dynamic "http_parameters" { + for_each = try([each.value.enrichment_parameters.http_parameters], []) + + content { + path_parameter_values = try(http_parameters.value.path_parameter_values, null) + header_parameters = try(http_parameters.value.header_parameters, null) + query_string_parameters = try(http_parameters.value.query_string_parameters, null) + } + } + } + } + + tags = merge(var.tags, try(each.value.tags, {})) +} diff --git a/outputs.tf b/outputs.tf index 0261ceb..4908ae1 100644 --- a/outputs.tf +++ b/outputs.tf @@ -86,3 +86,82 @@ output "eventbridge_role_name" { description = "The name of the IAM role created for EventBridge" value = try(aws_iam_role.eventbridge[0].name, "") } + +# EventBridge Pipes +output "eventbridge_pipe_ids" { + description = "The EventBridge Pipes IDs" + value = { for k, v in aws_pipes_pipe.this : k => v.id } +} + +output "eventbridge_pipe_arns" { + description = "The EventBridge Pipes ARNs" + value = { for k, v in aws_pipes_pipe.this : k => v.arn } +} + +# IAM Role for EventBridge Pipes +output "eventbridge_pipe_role_arns" { + description = "The ARNs of the IAM role created for EventBridge Pipes" + value = { for k, v in aws_iam_role.eventbridge_pipe : k => v.arn } +} + +output "eventbridge_pipe_role_names" { + description = "The names of the IAM role created for EventBridge Pipes" + value = { for k, v in aws_iam_role.eventbridge_pipe : k => v.name } +} + +# Resources +output "eventbridge_bus" { + description = "The EventBridge Bus created and their attributes" + value = aws_cloudwatch_event_bus.this +} + +output "eventbridge_archives" { + description = "The EventBridge Archives created and their attributes" + value = aws_cloudwatch_event_archive.this +} + +output "eventbridge_permissions" { + description = "The EventBridge Permissions created and their attributes" + value = aws_cloudwatch_event_permission.this +} + +output "eventbridge_connections" { + description = "The EventBridge Connections created and their attributes" + value = aws_cloudwatch_event_connection.this +} + +output "eventbridge_api_destinations" { + description = "The EventBridge API Destinations created and their attributes" + value = aws_cloudwatch_event_api_destination.this +} + +output "eventbridge_rules" { + description = "The EventBridge Rules created and their attributes" + value = aws_cloudwatch_event_rule.this +} + +output "eventbridge_schedule_groups" { + description = "The EventBridge Schedule Groups created and their attributes" + value = aws_scheduler_schedule_group.this +} + +output "eventbridge_schedules" { + description = "The EventBridge Schedules created and their attributes" + value = aws_scheduler_schedule.this +} + +output "eventbridge_pipes" { + description = "The EventBridge Pipes created and their attributes" + value = aws_pipes_pipe.this +} + +# IAM Roles +output "eventbridge_pipes_iam_roles" { + description = "The EventBridge Pipes IAM roles created and their attributes" + value = aws_iam_role.eventbridge_pipe +} + +output "eventbridge_iam_roles" { + description = "The EventBridge IAM roles created and their attributes" + value = aws_iam_role.eventbridge +} diff --git a/variables.tf b/variables.tf index c130322..ee786ce 100644 --- a/variables.tf +++ b/variables.tf @@ -40,6 +40,12 @@ variable "append_schedule_postfix" { default = true } +variable "append_pipe_postfix" { + description = "Controls whether to append '-pipe' to the name of the pipe" + type = bool + default = true +} + variable "create_bus" { description = "Controls whether EventBridge Bus resource should be created" type = bool @@ -100,6 +106,12 @@ variable "create_schedules" { default = true } +variable "create_pipes" { + description = "Controls whether EventBridge Pipes resources should be created" + type = bool + default = true +} + ####################### variable "bus_name" { @@ -168,6 +180,12 @@ variable "schedules" { default = {} } +variable "pipes" { + description = "A map of objects with EventBridge Pipe definitions." + type = any + default = {} +} + variable "tags" { description = "A map of tags to assign to resources." type = map(string)