A l w a y s S u n n y
A l w a y s S u n n y

Reputation: 38502

Terraform aws eventbridge schedule with API destination using eventbridge module

I need to create a terraform script for aws eventbridge api destination, for that, I need this

2 different API destinations with 1 or 2 different connections, 2 rules with 2 different targets using the "default" event bus,

I need to make sure that my rules have -

  1. Rule name, Rule type to "Schedule" using "default" Event bus where I can set the Schedule pattern using cron expression and
  2. In the Target section I can set the Target type to "EventBridge API destination", and set the Api Destination, Api destination endpoint using an existing or new rule. I need to create one or two connections and 2 different Api destinations.

I was following this GitHub repo for the terraform script, https://github.com/terraform-aws-modules/terraform-aws-eventbridge/tree/master/examples/with-api-destination. This is my current eventbridge.tf file structure and I am using the iam.tf, main.tf, output.tf, variables.tf from this path: https://github.com/terraform-aws-modules/terraform-aws-eventbridge/tree/master

eventbridge.tf

module "eventbridge" {
  source = "./modules/eventbridge"

  create_bus              = false
  create_connections      = true
  create_api_destinations = true

  attach_api_destination_policy = true

  rules = {
    "test_room_price_${var.env_level}" = {
      description   = "Trigger test room price cron"
      schedule_expression = "cron(20 4 * * ? *)"
      enabled       = true
      event_pattern        = null 
    }
    "test_room_details_${var.env_level}" = {
      description   = "Trigger test room details cron"
      schedule_expression = "cron(50 3 * * ? *)"
      enabled       = true
      event_pattern        = null 
    }
  }

  targets = {
    "test_room_price_${var.env_level}" = [
      {
        name            = "send-request-to-test-room-price-${var.env_level}"
        destination     = "test_room_price_${var.env_level}"
        attach_role_arn = true
      }
    ]
    "test_room_details_${var.env_level}" = [
      {
        name            = "send-request-to-test-room-details-${var.env_level}"
        destination     = "test_room_details_${var.env_level}"
        attach_role_arn = true
      }
    ]
  }

  connections = {
    "test_room_price_${var.env_level}" = {
      authorization_type = "API_KEY"
      auth_parameters = {
        api_key = {
          key   = "Authorization"
          value = "Bearer testtoken"
        }
      }
    }
    "test_room_details_${var.env_level}" = {
      authorization_type = "API_KEY"
      auth_parameters = {
        api_key = {
          key   = "Authorization"
          value = "Bearer testtoken"
        }
      }
    }
  }

  api_destinations = {
    "test_room_price_${var.env_level}" = {
      description                      = "my test room price endpoint"
      invocation_endpoint              = "http://example.com/generate_cts/*"
      http_method                      = "POST"
      invocation_rate_limit_per_second = 10
    }
    "test_room_details_${var.env_level}" = {
      description                      = "my test room details endpoint"
      invocation_endpoint              = "http://example.com/generate_tst/test/*"
      http_method                      = "POST"
      invocation_rate_limit_per_second = 10
    }
  }
}

resource "random_pet" "this" {
  length = 2
}

resource "aws_iam_role" "eventbridge" {
  name               = "${random_pet.this.id}-role"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

data "aws_iam_policy_document" "assume_role" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["events.amazonaws.com"]
    }
  }
}

Question I have now:

When I run terraform plan or terraform validate it has no issue but I am not sure how this will create one connection, two destinations and two rules with two different targets respectively because this line seems create two target for the same rule: https://github.com/terraform-aws-modules/terraform-aws-eventbridge/blob/c72cd4757bd4fc828f69fc9a92daa643e0938d42/main.tf#L10

Correct me If I am missing something here.

How I did it in the AWS console manually and which is working fine as expected,

  1. Create a connection
  2. Create 2 different API destinations with my specific endpoint urls, HTTP method, and Invocation rate limit using the connection in step 1.
  3. Create 2 different rules using the "default" event bus where I set the event rule name, rule type to "Schedule", set Cron expression, set target type to "EventBridge API destination",set existing Api destination from step step 2, set path params, execution role

Upvotes: 1

Views: 2233

Answers (1)

alex
alex

Reputation: 297

I am not entirely sure why you are using the module directly from the GIT repository (normally, you use the code from the Terraform module repository). I fixed the code so it works so we can take it from here:

module "eventbridge" {
    // I fixed the code to pull from the Terraform modules registry (so you need to run terraform init before you start)
    source = "terraform-aws-modules/eventbridge/aws"

    create_bus              = false
    create_connections      = true
    create_api_destinations = true

    attach_api_destination_policy = true

    rules = {
        // you have two rules here, you can see the rules point at the targets below
        "test_room_price_${var.env_level}" = {
            description         = "Trigger test room price cron"
            schedule_expression = "cron(20 4 * * ? *)"
            enabled             = true
            event_pattern       = null
        }
        "test_room_details_${var.env_level}" = {
            description         = "Trigger test room details cron"
            schedule_expression = "cron(50 3 * * ? *)"
            enabled             = true
            event_pattern       = null
        }
    }

    targets = {
        // you have two targets here, you can see the targets point at the api_destinations below
        "test_room_price_${var.env_level}" = [
            {
                name            = "send-request-to-test-room-price-${var.env_level}"
                destination     = "test_room_price_${var.env_level}"
                attach_role_arn = true
            }
            // note this is an array so you could add more targets here so you could have a single target that sends to multiple destinations
        ]
        "test_room_details_${var.env_level}" = [
            {
                name            = "send-request-to-test-room-details-${var.env_level}"
                destination     = "test_room_details_${var.env_level}"
                attach_role_arn = true
            }
        ]
    }

    connections = {
        // you could consolidate this into one connection, but for the sake of example, we'll add two connections
        "test_room_price_${var.env_level}" = {
            authorization_type = "API_KEY"
            auth_parameters = {
                api_key = {
                key   = "Authorization"
                value = "Bearer testtoken"
                }
            }
        }
        "test_room_details_${var.env_level}" = {
            authorization_type = "API_KEY"
            auth_parameters = {
                api_key = {
                key   = "Authorization"
                value = "Bearer testtoken"
                }
            }
        }
    }

    api_destinations = {
        // you need two destinations here, so we add two destinations
        "test_room_price_${var.env_level}" = {
            description                      = "my test room price endpoint"
            invocation_endpoint              = "http://example.com/generate_cts/*"
            http_method                      = "POST"
            invocation_rate_limit_per_second = 10
        },
        "test_room_details_${var.env_level}" = {
            description                      = "XXX"
            invocation_endpoint              = "http://example.com/generate_cts/*"
            http_method                      = "POST"
            invocation_rate_limit_per_second = 10
        }    
    }
}

How this module works is it looks at the keys for the rules / targets and it matches them by name. So, for example you have a target destination, named XXX this target destination must also appear in the api_destinations with the key XXX (otherwise you will get the error The given key does not identify an element in this collection value).

You need to look at this module in the context of creating a single setup for your code. So you could also use this module twice, see this gist for an example: https://gist.github.com/alexjeen/799c90704ef955f1906d1ada6a69699d

That should make it easier for you to manage as well!

Upvotes: 2

Related Questions