# How to invoke an AWS Lambda Function at scheduled intervals with AWS EventBridge Rule using Terraform

[**Amazon EventBridge**](https://aws.amazon.com/eventbridge/) is a serverless event bus service that you can use to connect your applications with data from a variety of sources. Events are central to EventBridge and the events are observable. Event bridge also supports integration with many SAAS-based applications and third-party applications. It also supports sending events to other AWS services like Lambda functions, step functions.

In this blog, we will set up a **rule** to run the lambda function on schedule every 2 minutes using [**Terraform**](https://www.terraform.io/).

## Project Structure

- Create a new directory and move to the directory
```sh
mkdir lambda-schedule-event-bridge && cd lambda-schedule-event-bridge
```

- Create a resource folder to store the code for lambda
```sh
mkdir resources
```

## Create a Lambda

Create a folder **profile-generator-lambda** in the **resources** folder and add the **index.js** file with the below content. Also, initialize the node project and install the dependencies.

```sh
mkdir profile-generator-lambda && cd profile-generator-lambda
touch index.js
npm init -y
npm install faker
```
```javascript
const faker = require("faker/locale/en_IND");

exports.handler = async (event, context) => {
  let firstName = faker.name.firstName();
  let lastName = faker.name.lastName();
  let phoneNumber = faker.phone.phoneNumber();
  let vehicleType = faker.vehicle.vehicle();

  let response = {
    firstName: firstName,
    lastName: lastName,
    phoneNumber: phoneNumber,
    vehicleType: vehicleType,
  };

  return {
    statusCode: 200,
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      profile: response,
    }),
  };
};
```
## Terraform Providers

Now, we will write the terraform scripts in HCL language where we will utilize the AWS provider. Create a main.tf file in the root directory of the project and add the below content.
```sh
touch main.tf
```

```sh
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "3.50.0"
    }
  }
}

provider "aws" {
  # Configuration options
  region                  = var.region
  profile                 = var.aws_profile
  shared_credentials_file = var.shared_credentials_file
  default_tags {
    tags = var.tags
  }
}
```

- Each Terraform module must declare which providers it requires so that Terraform can install and use them. Provider requirements are declared in a _requiredproviders block.

- AWS providers require configurations like cloud regions, profiles, credential_files to be available before they can be used.

- All the values will be provided from the variables parameters.

Let's create **variables.tf** in the root directory of the project and add the below content.
```sh
touch variables.tf
```
```sh
variable "region" {
  description = "Deployment Region"
  default     = "ap-south-1"
}

variable "aws_profile" {
  description = "Given name in the credential file"
  type        = string
  default     = "rahul-admin"
}

variable "shared_credentials_file" {
  description = "Profile file with credentials to the AWS account"
  type        = string
  default     = "~/.aws/credentials"
}

variable "tags" {
  description = "A map of tags to add to all resources."
  type        = map(string)
  default = {
    application = "Learning-Tutor"
    env         = "Test"
  }
}
```
Each input variable accepted by a module must be declared using a variable block. The label after the variable keyword is a name for the variable, which must be unique among all variables in the same module.
- A default value makes the variable optional.
- A Type indicates what value types are accepted for the variable.
- A description specifies the input variable's documentation.

## Terraform Modules

Now, we will use the module terraform-aws-modules/lambda/aws to create lambda and lambda layer infrastructure.

Create the files lambda.tf in the root directory of the project and add the below content.

```sh
touch lambda.tf
```
```sh
module "profile_generator_lambda" {
  source  = "terraform-aws-modules/lambda/aws"
  version = "2.7.0"
  # insert the 28 required variables here
  function_name = "profile-generator-lambda"
  description   = "Generates a new profiles"
  handler       = "index.handler"
  runtime       = "nodejs14.x"
  source_path   = "${path.module}/resources/profile-generator-lambda"

  tags = {
    Name = "profile-generator-lambda"
  }
}
```

## EventBridge Rule

Create the files **event_bridge.tf** in the root directory of the project and add the below content.

```sh
touch event_bridge.tf
```

```sh
resource "aws_cloudwatch_event_rule" "profile_generator_lambda_event_rule" {
  name = "profile-generator-lambda-event-rule"
  description = "retry scheduled every 2 min"
  schedule_expression = "rate(2 minutes)"
}

resource "aws_cloudwatch_event_target" "profile_generator_lambda_target" {
  arn = module.profile_generator_lambda.lambda_function_arn
  rule = aws_cloudwatch_event_rule.profile_generator_lambda_event_rule.name
}

resource "aws_lambda_permission" "allow_cloudwatch_to_call_rw_fallout_retry_step_deletion_lambda" {
  statement_id = "AllowExecutionFromCloudWatch"
  action = "lambda:InvokeFunction"
  function_name = module.profile_generator_lambda.lambda_function_name
  principal = "events.amazonaws.com"
  source_arn = aws_cloudwatch_event_rule.profile_generator_lambda_event_rule.arn
}
```

As can be seen above, the **schedule_expression** attribute has a rate of 2 minutes. It means, it triggers the lambda function which is in the target using the resource **aws_cloudwatch_event_target.profile_generator_lambda_target**. We also give lambda permission, so that, the event will be able to invoke the function.

## Run Terraform scripts
Let us run the 3 basic commands of terraform to create the resources in AWS.

- Initialize the Terraform which will download all the providers and modules used in the configuration.

```sh
terraform init
```

- Check if a plan matches the expectation and also store the plan in output file plan-out

```sh
terraform plan -out  "plan-out"
```

- Once the plan is verified, apply the changes to get the desired infrastructure components.

```sh
terraform apply "plan-out"
```

## Verify the infrastructure on AWS

- Lambda with Event Bridge


![event-bridge-1.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631108515528/ke3rRgKIg.png)

If you check the cloud watch logs, you can see that the lambda function is getting invoked every 2 minutes.

![event-bridge-2.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631108595881/OI3SrcL6t.png)

## Delete the resources 

We can delete the resources created by terraform by issuing the below command so that we do not get billed for the resources.

```sh
terraform destroy
```

## Conclusion

In this blog post, we saw how to create a lambda function and event bridge rule using terraform. We also saw, how to schedule the lambda function every 2 minutes by creating an event bus rule.

**Github Repository** : [https://github.com/rahulmlokurte/aws-usage/tree/main/terraform/lambda-schedule-event-bridge](https://github.com/rahulmlokurte/aws-usage/tree/main/terraform/lambda-schedule-event-bridge)
