From 6f75f3e46a42fcd2fe0e2312f061fcfa316f4105 Mon Sep 17 00:00:00 2001 From: prajwalakhuj Date: Thu, 14 Sep 2023 16:51:31 +0530 Subject: [PATCH 1/2] added basic cw alerts and slack integration support --- README.md | 27 ++++- {example => examples}/complete/README.md | 0 {example => examples}/complete/main.tf | 14 ++- {example => examples}/complete/output.tf | 0 {example => examples}/complete/provider.tf | 0 {example => examples}/complete/version.tf | 0 lambda/README.md | 60 +++++++++ lambda/data.tf | 32 +++++ lambda/iam.tf | 10 ++ lambda/main.tf | 26 ++++ lambda/outputs.tf | 19 +++ lambda/sns_slack.py | 51 ++++++++ lambda/variables.tf | 57 +++++++++ main.tf | 135 +++++++++++++++++++++ variables.tf | 54 +++++++++ 15 files changed, 480 insertions(+), 5 deletions(-) rename {example => examples}/complete/README.md (100%) rename {example => examples}/complete/main.tf (75%) rename {example => examples}/complete/output.tf (100%) rename {example => examples}/complete/provider.tf (100%) rename {example => examples}/complete/version.tf (100%) create mode 100644 lambda/README.md create mode 100644 lambda/data.tf create mode 100644 lambda/iam.tf create mode 100644 lambda/main.tf create mode 100644 lambda/outputs.tf create mode 100644 lambda/sns_slack.py create mode 100644 lambda/variables.tf diff --git a/README.md b/README.md index b5db781..2483e27 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,15 @@ module "rds-pg" { deletion_protection = false allowed_security_groups = ["sg-013cbf880"] final_snapshot_identifier_prefix = "final" + cloudwatch_metric_alarms_enabled = true + alarm_cpu_threshold_percent = 70 + disk_free_storage_space = "10000000" # in bytes + slack_username = "John" + slack_channel = "skaf-dev" + slack_webhook_url = "https://hooks/xxxxxxxx" } ``` -Refer [examples](https://github.com/squareops/terraform-aws-rds-postgresql/tree/main/example/complete) for more details. +Refer [examples](https://github.com/squareops/terraform-aws-rds-postgresql/tree/main/examples/complete) for more details. ## IAM Permissions The required IAM permissions to create resources from this module can be found [here](https://github.com/squareops/terraform-aws-rds-postgresql/blob/main/IAM.md) @@ -60,12 +66,14 @@ The required IAM permissions to create resources from this module can be found [ | Name | Version | |------|---------| +| [archive](#provider\_archive) | 2.4.0 | | [aws](#provider\_aws) | 3.43.0 | ## Modules | Name | Source | Version | |------|--------|---------| +| [cw\_sns\_slack](#module\_cw\_sns\_slack) | ./lambda | n/a | | [db](#module\_db) | terraform-aws-modules/rds/aws | ~> 3.0 | | [security\_group\_rds](#module\_security\_group\_rds) | terraform-aws-modules/security-group/aws | ~> 4 | @@ -73,8 +81,16 @@ The required IAM permissions to create resources from this module can be found [ | Name | Type | |------|------| +| [aws_cloudwatch_metric_alarm.cache_cpu](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/resources/cloudwatch_metric_alarm) | resource | +| [aws_cloudwatch_metric_alarm.disk_free_storage_space_too_low](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/resources/cloudwatch_metric_alarm) | resource | +| [aws_kms_ciphertext.slack_url](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/resources/kms_ciphertext) | resource | +| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/resources/kms_key) | resource | +| [aws_lambda_permission.sns_lambda_slack_invoke](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/resources/lambda_permission) | resource | | [aws_security_group_rule.cidr_ingress](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/resources/security_group_rule) | resource | | [aws_security_group_rule.default_ingress](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/resources/security_group_rule) | resource | +| [aws_sns_topic.slack_topic](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/resources/sns_topic) | resource | +| [aws_sns_topic_subscription.slack-endpoint](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/resources/sns_topic_subscription) | resource | +| [archive_file.lambdazip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/data-sources/availability_zones) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/3.43.0/docs/data-sources/region) | data source | @@ -83,16 +99,21 @@ The required IAM permissions to create resources from this module can be found [ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [additional\_tags](#input\_additional\_tags) | A map of additional tags to apply to the AWS resources | `map(string)` |
{
"automation": "true"
}
| no | +| [alarm\_actions](#input\_alarm\_actions) | Alarm action list | `list(string)` | `[]` | no | +| [alarm\_cpu\_threshold\_percent](#input\_alarm\_cpu\_threshold\_percent) | CPU threshold alarm level | `number` | `75` | no | | [allocated\_storage](#input\_allocated\_storage) | The allocated storage capacity for the database in gibibytes (GiB) | `number` | `20` | no | | [allowed\_cidr\_blocks](#input\_allowed\_cidr\_blocks) | A list of CIDR blocks that are allowed to access the database | `list(any)` | `[]` | no | | [allowed\_security\_groups](#input\_allowed\_security\_groups) | A list of Security Group IDs to allow access to the database | `list(any)` | `[]` | no | | [apply\_immediately](#input\_apply\_immediately) | Specifies whether any cluster modifications are applied immediately or during the next maintenance window | `bool` | `false` | no | | [backup\_retention\_period](#input\_backup\_retention\_period) | The number of days to retain backups for | `number` | `5` | no | | [backup\_window](#input\_backup\_window) | The preferred window for taking automated backups of the database | `string` | `""` | no | +| [cloudwatch\_metric\_alarms\_enabled](#input\_cloudwatch\_metric\_alarms\_enabled) | Boolean flag to enable/disable CloudWatch metrics alarms | `bool` | `false` | no | | [create\_random\_password](#input\_create\_random\_password) | Whether to create a random password for the RDS primary cluster | `bool` | `true` | no | | [create\_security\_group](#input\_create\_security\_group) | Whether to create a security group for the database | `bool` | `true` | no | +| [cw\_sns\_topic\_arn](#input\_cw\_sns\_topic\_arn) | The username to use when sending notifications to Slack. | `string` | `""` | no | | [db\_name](#input\_db\_name) | The name of the automatically created database on cluster creation | `string` | `""` | no | | [deletion\_protection](#input\_deletion\_protection) | Specifies whether accidental deletion protection is enabled | `bool` | `true` | no | +| [disk\_free\_storage\_space](#input\_disk\_free\_storage\_space) | Alarm threshold for the 'lowFreeStorageSpace' alarm | `string` | `"10000000000"` | no | | [enable\_ssl\_connection](#input\_enable\_ssl\_connection) | Whether to enable SSL connection to the database | `bool` | `false` | no | | [engine](#input\_engine) | The name of the database engine to be used for this DB cluster | `string` | `"postgres"` | no | | [engine\_version](#input\_engine\_version) | The database engine version. Updating this argument results in an outage | `string` | `""` | no | @@ -106,11 +127,15 @@ The required IAM permissions to create resources from this module can be found [ | [master\_username](#input\_master\_username) | The username for the RDS primary cluster | `string` | `""` | no | | [multi\_az](#input\_multi\_az) | Enable multi-AZ for disaster recovery | `bool` | `false` | no | | [name](#input\_name) | The name of the RDS instance | `string` | `""` | no | +| [ok\_actions](#input\_ok\_actions) | The list of actions to execute when this alarm transitions into an OK state from any other state. Each action is specified as an Amazon Resource Number (ARN) | `list(string)` | `[]` | no | | [port](#input\_port) | The port number for the database | `number` | `5432` | no | | [publicly\_accessible](#input\_publicly\_accessible) | Specifies whether the RDS instance is publicly accessible over the internet | `bool` | `false` | no | | [random\_password\_length](#input\_random\_password\_length) | The length of the randomly generated password for the RDS primary cluster (default: 10) | `number` | `10` | no | | [replicate\_source\_db](#input\_replicate\_source\_db) | Specifies that this resource is a replicate database, and uses the specified value as the source database identifier | `string` | `null` | no | | [skip\_final\_snapshot](#input\_skip\_final\_snapshot) | Determines whether a final DB snapshot is created before the DB instance is deleted. If set to true, no DB snapshot is created. If set to false, a DB snapshot is created before the DB instance is deleted, using the value from final\_snapshot\_identifier | `bool` | `true` | no | +| [slack\_channel](#input\_slack\_channel) | The Slack channel where notifications will be posted. | `string` | `""` | no | +| [slack\_username](#input\_slack\_username) | The username to use when sending notifications to Slack. | `string` | `""` | no | +| [slack\_webhook\_url](#input\_slack\_webhook\_url) | The Slack Webhook URL where notifications will be sent. | `string` | `""` | no | | [snapshot\_identifier](#input\_snapshot\_identifier) | Specifies whether to create the database from a snapshot. Use the snapshot ID found in the RDS console, e.g., rds:production-2015-06-26-06-05 | `string` | `null` | no | | [storage\_encrypted](#input\_storage\_encrypted) | Specifies whether to enable database encryption | `bool` | `true` | no | | [subnet\_ids](#input\_subnet\_ids) | A list of subnet IDs used by the database subnet group | `list(any)` | `[]` | no | diff --git a/example/complete/README.md b/examples/complete/README.md similarity index 100% rename from example/complete/README.md rename to examples/complete/README.md diff --git a/example/complete/main.tf b/examples/complete/main.tf similarity index 75% rename from example/complete/main.tf rename to examples/complete/main.tf index 2d4410f..219bd1e 100644 --- a/example/complete/main.tf +++ b/examples/complete/main.tf @@ -1,14 +1,14 @@ locals { region = "us-east-2" name = "postgresql" - vpc_id = "vpc-00ae5571c1" + vpc_id = "vpc-06861ba817a8cda10" family = "postgres15" - subnet_ids = ["subnet-0d9a8193d2a6e","subnet-0fd263dc9e73d"] + subnet_ids = ["subnet-09e8f6ea27b7e36d0","subnet-0b070110454617a90"] environment = "prod" - kms_key_arn = "arn:aws:kms:us-east-2:22222222:key/73ff9e84-83e1-fe29623338a9" + kms_key_arn = "" engine_version = "15.2" instance_class = "db.m5d.large" - allowed_security_groups = ["sg-0a680afd35"] + allowed_security_groups = ["sg-0ef14212995d67a2d"] additional_tags = { Owner = "Organization_Name" Expires = "Never" @@ -38,4 +38,10 @@ module "rds-pg" { allowed_security_groups = local.allowed_security_groups major_engine_version = local.engine_version deletion_protection = false + cloudwatch_metric_alarms_enabled = true + alarm_cpu_threshold_percent = 70 + disk_free_storage_space = "10000000" # in bytes + slack_username = "" + slack_channel = "" + slack_webhook_url = "" } diff --git a/example/complete/output.tf b/examples/complete/output.tf similarity index 100% rename from example/complete/output.tf rename to examples/complete/output.tf diff --git a/example/complete/provider.tf b/examples/complete/provider.tf similarity index 100% rename from example/complete/provider.tf rename to examples/complete/provider.tf diff --git a/example/complete/version.tf b/examples/complete/version.tf similarity index 100% rename from example/complete/version.tf rename to examples/complete/version.tf diff --git a/lambda/README.md b/lambda/README.md new file mode 100644 index 0000000..e880905 --- /dev/null +++ b/lambda/README.md @@ -0,0 +1,60 @@ +## Lambda for SNS +![squareops_avatar] + +[squareops_avatar]: https://squareops.com/wp-content/uploads/2022/12/squareops-logo.png + +### [SquareOps Technologies](https://squareops.com/) Your DevOps Partner for Accelerating cloud journey. +
+ +Here is Lambda that calls the Slack webhook and passes the alarm message as the payload. + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_log_group.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_role.lambda_exec_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.lambda_cwl_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_lambda_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_iam_policy_document.lambda_cwl_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_exec_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [artifact\_file](#input\_artifact\_file) | The path to the function's deployment package within the local filesystem | `string` | `null` | no | +| [cwl\_retention\_days](#input\_cwl\_retention\_days) | The retention time in days for the CloudWatch Logs Stream. | `number` | `30` | no | +| [description](#input\_description) | Description of what the Lambda Function does. | `string` | `null` | no | +| [environment](#input\_environment) | The Lambda environment's configuration settings. | `map(string)` | `{}` | no | +| [handler](#input\_handler) | The function entrypoint in the code. | `string` | `"index.handler"` | no | +| [memory\_size](#input\_memory\_size) | Amount of memory in MB your Lambda Function can use at runtime. | `number` | `128` | no | +| [name](#input\_name) | A unique name for the Lambda Function. | `string` | n/a | yes | +| [runtime](#input\_runtime) | The Runtime used in the Lambda Function. | `string` | n/a | yes | +| [tags](#input\_tags) | A mapping of tags to assign to the module resources. | `map(string)` | `{}` | no | +| [timeout](#input\_timeout) | The amount of time your Lambda Function has to run in seconds. | `number` | `6` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | The ARN identifying the Lambda Function. | +| [exec\_role\_id](#output\_exec\_role\_id) | The ID of the Function's IAM Role. | +| [invoke\_arn](#output\_invoke\_arn) | The ARN to be used for invoking Lambda Function from API Gateway. | +| [name](#output\_name) | The name of the Lambda Function. | + + \ No newline at end of file diff --git a/lambda/data.tf b/lambda/data.tf new file mode 100644 index 0000000..679463c --- /dev/null +++ b/lambda/data.tf @@ -0,0 +1,32 @@ +# Lambda Assume Role policy +data "aws_iam_policy_document" "lambda_exec_role_policy" { + statement { + sid = "LambdaExecRolePolicy" + effect = "Allow" + principals { + identifiers = [ + "lambda.amazonaws.com", + ] + type = "Service" + } + actions = [ + "sts:AssumeRole", + ] + } +} + +# Lambda CloudWatch Logs access +data "aws_iam_policy_document" "lambda_cwl_access" { + statement { + sid = "LambdaCreateCloudWatchLogGroup" + effect = "Allow" + actions = [ + "logs:PutLogEvents", + "logs:CreateLogStream", + "logs:CreateLogGroup" + ] + resources = [ + "arn:aws:logs:*:*:log-group:/aws/lambda/*:*:*" + ] + } +} diff --git a/lambda/iam.tf b/lambda/iam.tf new file mode 100644 index 0000000..b6e4760 --- /dev/null +++ b/lambda/iam.tf @@ -0,0 +1,10 @@ +resource "aws_iam_role" "lambda_exec_role" { + name = "${replace(title(var.name), "-", "")}LambdaExecRole" + assume_role_policy = data.aws_iam_policy_document.lambda_exec_role_policy.json +} + +resource "aws_iam_role_policy" "lambda_cwl_policy" { + name = "${replace(title(var.name), "-", "")}LambdaCWLogsPolicy" + role = aws_iam_role.lambda_exec_role.id + policy = data.aws_iam_policy_document.lambda_cwl_access.json +} diff --git a/lambda/main.tf b/lambda/main.tf new file mode 100644 index 0000000..1a845ef --- /dev/null +++ b/lambda/main.tf @@ -0,0 +1,26 @@ +resource "aws_cloudwatch_log_group" "lambda" { + name = "/aws/lambda/${var.name}" + retention_in_days = var.cwl_retention_days + tags = var.tags +} + +resource "aws_lambda_function" "this" { + function_name = var.name + description = var.description + filename = var.artifact_file + source_code_hash = var.artifact_file != null ? filebase64sha256(var.artifact_file) : null + role = aws_iam_role.lambda_exec_role.arn + handler = var.handler + runtime = var.runtime + memory_size = var.memory_size + timeout = var.timeout + + dynamic "environment" { + for_each = (length(var.environment) > 0 ? [1] : []) + content { + variables = var.environment + } + } + + tags = var.tags +} diff --git a/lambda/outputs.tf b/lambda/outputs.tf new file mode 100644 index 0000000..e97e7ec --- /dev/null +++ b/lambda/outputs.tf @@ -0,0 +1,19 @@ +output "name" { + description = "The name of the Lambda Function." + value = aws_lambda_function.this.function_name +} + +output "arn" { + description = "The ARN identifying the Lambda Function." + value = aws_lambda_function.this.arn +} + +output "invoke_arn" { + description = "The ARN to be used for invoking Lambda Function from API Gateway." + value = aws_lambda_function.this.invoke_arn +} + +output "exec_role_id" { + description = "The ID of the Function's IAM Role." + value = aws_iam_role.lambda_exec_role.id +} diff --git a/lambda/sns_slack.py b/lambda/sns_slack.py new file mode 100644 index 0000000..239e101 --- /dev/null +++ b/lambda/sns_slack.py @@ -0,0 +1,51 @@ +import json +import re +import os +import boto3 +import urllib3 + +# Lambda global variables +region = os.environ["AWS_REGION"] # from Lambda default envs +slack_url = os.environ["SLACK_URL"] +slack_channel = os.environ["SLACK_CHANNEL"] +slack_user = os.environ["SLACK_USER"] + + +http = urllib3.PoolManager() +def format_cloudwatch_alarm_message(event): + alarm_data = json.loads(event['Records'][0]['Sns']['Message']) + + alarm_name = alarm_data["AlarmName"] + alarm_description = alarm_data["AlarmDescription"] + new_state = alarm_data["NewStateValue"] + reason = alarm_data["NewStateReason"] + metric_name = alarm_data["Trigger"]["MetricName"] + threshold = alarm_data["Trigger"]["Threshold"] + + message = f"*:exclamation: CloudWatch Alarm Alert :exclamation:*\n\n" + message += f" *Alarm Name:* {alarm_name}\n" + message += f" *Description:* _{alarm_description}_\n" + message += f" *New State:* {new_state}\n" + message += f" *Reason:* _{reason}_\n" + message += f" *Metric Name:* {metric_name}\n" + message += f" *Threshold:* {threshold}\n" + + return message + +def lambda_handler(event, context): + url = slack_url + msg = { + "channel": slack_channel, + "username": slack_user, + "text": format_cloudwatch_alarm_message(event), + "icon_emoji": ":cloudwatch:" + } + + encoded_msg = json.dumps(msg).encode('utf-8') + resp = http.request('POST', url, body=encoded_msg) + + print({ + "message": msg, + "status_code": resp.status, + "response": resp.data + }) \ No newline at end of file diff --git a/lambda/variables.tf b/lambda/variables.tf new file mode 100644 index 0000000..ba1013b --- /dev/null +++ b/lambda/variables.tf @@ -0,0 +1,57 @@ +variable "artifact_file" { + type = string + description = "The path to the function's deployment package within the local filesystem" + default = null +} + +variable "handler" { + type = string + description = "The function entrypoint in the code." + default = "index.handler" +} + +variable "memory_size" { + type = number + description = "Amount of memory in MB your Lambda Function can use at runtime." + default = 128 +} + +variable "timeout" { + type = number + description = "The amount of time your Lambda Function has to run in seconds." + default = 6 +} + +variable "description" { + type = string + description = "Description of what the Lambda Function does." + default = null +} + +variable "environment" { + type = map(string) + description = "The Lambda environment's configuration settings." + default = {} +} + +variable "cwl_retention_days" { + type = number + description = "The retention time in days for the CloudWatch Logs Stream." + default = 30 +} + +variable "tags" { + description = "A mapping of tags to assign to the module resources." + type = map(string) + default = {} +} + +variable "name" { + type = string + description = "A unique name for the Lambda Function." +} + +variable "runtime" { + type = string + description = "The Runtime used in the Lambda Function." +} diff --git a/main.tf b/main.tf index 32b5830..475d572 100644 --- a/main.tf +++ b/main.tf @@ -102,3 +102,138 @@ module "security_group_rds" { local.tags, ) } + +# Cloudwatch alarms +resource "aws_cloudwatch_metric_alarm" "cache_cpu" { + count = var.cloudwatch_metric_alarms_enabled ? 1 : 0 + alarm_name = format("%s-%s-%s", var.environment, var.name, "cpu-utilization") + alarm_description = "Redis cluster CPU utilization" + comparison_operator = "GreaterThanThreshold" + evaluation_periods = "1" + metric_name = "CPUUtilization" + namespace = "AWS/RDS" + period = "300" + statistic = "Average" + + threshold = var.alarm_cpu_threshold_percent + + dimensions = { + DBInstanceIdentifier = module.db.db_instance_id + } + + alarm_actions = [aws_sns_topic.slack_topic[0].arn] + ok_actions = [aws_sns_topic.slack_topic[0].arn] + depends_on = [aws_sns_topic.slack_topic] + + tags = merge( + { "Name" = format("%s-%s-%s", var.environment, var.name, "cpu_metric") }, + local.tags, + ) +} + +resource "aws_cloudwatch_metric_alarm" "disk_free_storage_space_too_low" { + count = var.cloudwatch_metric_alarms_enabled ? 1 : 0 + alarm_name = format("%s-%s-%s", var.environment, var.name, "free-storage-space") + alarm_description = "Redis cluster freeable memory" + comparison_operator = "LessThanThreshold" + evaluation_periods = "1" + metric_name = "FreeStorageSpace" + namespace = "AWS/RDS" + period = "60" + statistic = "Average" + + threshold = var.disk_free_storage_space + + dimensions = { + DBInstanceIdentifier = module.db.db_instance_id + } + + alarm_actions = [aws_sns_topic.slack_topic[0].arn] + ok_actions = [aws_sns_topic.slack_topic[0].arn] + depends_on = [aws_sns_topic.slack_topic] + + tags = merge( + { "Name" = format("%s-%s-%s", var.environment, var.name, "free-storage-space") }, + local.tags, + ) +} + +resource "aws_kms_key" "this" { + count = var.cloudwatch_metric_alarms_enabled ? 1 : 0 + description = "KMS key for notify-slack test" +} + +resource "aws_kms_ciphertext" "slack_url" { + count = var.cloudwatch_metric_alarms_enabled ? 1 : 0 + plaintext = var.slack_webhook_url + key_id = aws_kms_key.this[0].arn +} + +resource "aws_sns_topic" "slack_topic" { + count = var.cloudwatch_metric_alarms_enabled ? 1 : 0 + depends_on = [module.db] + name = format("%s-%s-%s", var.environment, var.name, "slack-topic") + delivery_policy = < Date: Fri, 15 Sep 2023 14:39:15 +0530 Subject: [PATCH 2/2] updated the README.md --- README.md | 1 + examples/complete/README.md | 2 +- lambda/README.md | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2483e27..dc9b7f4 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ This Terraform module provisions an Amazon RDS PostgreSQL database on AWS. Amazo 6. Supports encryption at rest using AWS Key Management Service (KMS) for enhanced security. 7. Enables fine-grained control over network access through security groups and VPC settings. 8. Offers customizable tags for resource categorization and management. + 9. CloudWatch Alerts: Set up CloudWatch alarms to monitor the health and performance of your Redis cluster. Integrate these alarms with AWS Simple Notification Service (SNS) to receive real-time alerts. Use AWS Lambda functions to customize your alerting logic, and send notifications to Slack channels for immediate visibility into your RDS POstgresql status. ## Usage Examples ```hcl diff --git a/examples/complete/README.md b/examples/complete/README.md index 8dfe471..333f3ca 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -24,7 +24,7 @@ No providers. | Name | Source | Version | |------|--------|---------| -| [rds-pg](#module\_rds-pg) | squareops/postgresql-rds/aws | n/a | +| [rds-pg](#module\_rds-pg) | squareops/rds-postgresql/aws | n/a | ## Resources diff --git a/lambda/README.md b/lambda/README.md index e880905..abc66a5 100644 --- a/lambda/README.md +++ b/lambda/README.md @@ -16,7 +16,7 @@ No requirements. | Name | Version | |------|---------| -| [aws](#provider\_aws) | n/a | +| [aws](#provider\_aws) | 5.17.0 | ## Modules @@ -56,5 +56,4 @@ No modules. | [exec\_role\_id](#output\_exec\_role\_id) | The ID of the Function's IAM Role. | | [invoke\_arn](#output\_invoke\_arn) | The ARN to be used for invoking Lambda Function from API Gateway. | | [name](#output\_name) | The name of the Lambda Function. | - \ No newline at end of file