diff --git a/.gitignore b/.gitignore
index 397af322..58ccfdb1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,6 @@ override.tf.json
# Ignore CLI configuration files
.terraformrc
terraform.rc
+
+.idea/
+.vscode/
diff --git a/README.md b/README.md
index 2657fff2..776b2a90 100644
--- a/README.md
+++ b/README.md
@@ -243,7 +243,6 @@ No modules.
| [placement\_group](#input\_placement\_group) | The Placement Group to start the instance in | `string` | `null` | no |
| [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | Customize the private DNS name options of the instance | `map(string)` | `{}` | no |
| [private\_ip](#input\_private\_ip) | Private IP address to associate with the instance in a VPC | `string` | `null` | no |
-| [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no |
| [root\_block\_device](#input\_root\_block\_device) | Customize details about the root block device of the instance. See Block Devices below for details | `list(any)` | `[]` | no |
| [secondary\_private\_ips](#input\_secondary\_private\_ips) | A list of secondary private IPv4 addresses to assign to the instance's primary network interface (eth0) in a VPC. Can only be assigned to the primary network interface (eth0) attached at instance creation, not a pre-existing network interface i.e. referenced in a `network_interface block` | `list(string)` | `null` | no |
| [source\_dest\_check](#input\_source\_dest\_check) | Controls if traffic is routed to the instance when the destination address does not match the instance. Used for NAT or VPNs | `bool` | `null` | no |
diff --git a/custom.tf b/custom.tf
new file mode 100644
index 00000000..52df05cd
--- /dev/null
+++ b/custom.tf
@@ -0,0 +1,206 @@
+variable "alarm_info_sns_topic_arn" {
+ type = string
+ description = "The ARN of the SNS topic to notify when on info alerts"
+}
+
+variable "alarm_sns_topic_arn" {
+ type = string
+ description = "The ARN of the SNS topic to notify when on critical alerts"
+}
+
+variable "environment" {
+ type = string
+ description = "The environment tag to apply to all resources. eg: production, testing, staging, etc"
+
+ validation {
+ condition = var.environment == null || can(regex("^(production|testing|staging|development)$", var.environment))
+ error_message = "environment must be lowercase alphanumeric with hyphens only."
+ }
+}
+
+variable "service" {
+ type = string
+ description = "Service hosted on this instance. eg: squadstack, metabase, grafana, etc"
+
+ validation {
+ condition = var.service == null || can(regex("^[a-z-]+$", var.service))
+ error_message = "service_component must be lowercase alphabets with hyphens only."
+ }
+}
+
+variable "service_component" {
+ type = string
+ default = null
+ description = "[optional] Service Group within a service. eg: app, api, celery, etc"
+
+ validation {
+ condition = var.service_component == null || can(regex("^[a-z0-9-]+$", var.service_component))
+ error_message = "If provided, service_component must be lowercase alphanumeric with hyphens only."
+ }
+}
+
+variable "backup_for_disaster_recovery" {
+ type = bool
+ default = false
+ description = "If we need to keep backup of this instance's ami in other region"
+}
+
+variable "backup_frequency_days" {
+ type = number
+ default = 7
+ description = "The number of days after which the backup should be taken of the ami"
+}
+
+variable "ssm_access_type" {
+ type = string
+ default = ""
+ description = "ssm access type"
+}
+
+variable "owner_team" {
+ type = string
+ description = "Owner of this ec2. eg: platform, supply, demand, ds, etc"
+
+ validation {
+ condition = var.owner_team == null || can(regex("^(platform|supply|demand|integrations|data-science)$", var.owner_team))
+ error_message = "owner_team must be amongst platform, supply, demand, integrations, data-science."
+ }
+}
+
+resource "aws_cloudwatch_metric_alarm" "ec2_cpuutilization_alert_info" {
+ alarm_name = "${var.name}_high_cpu_alert"
+ comparison_operator = "GreaterThanOrEqualToThreshold"
+ evaluation_periods = "5"
+ datapoints_to_alarm = "4"
+ treat_missing_data = "ignore"
+ metric_name = "CPUUtilization"
+ namespace = "AWS/EC2"
+ period = "120"
+ statistic = "Average"
+ threshold = "85"
+ alarm_description = "This metric monitors ec2 CPU Utilization"
+ alarm_actions = [var.alarm_info_sns_topic_arn]
+ unit = "Percent"
+ dimensions = {
+ InstanceId = try(
+ aws_instance.this[0].id,
+ aws_instance.ignore_ami[0].id,
+ )
+ }
+}
+
+
+
+resource "aws_cloudwatch_metric_alarm" "ec2_cpuutilization_alert_warning" {
+ alarm_name = "${var.name}_critical_cpu_alert"
+ comparison_operator = "GreaterThanOrEqualToThreshold"
+ evaluation_periods = "15"
+ datapoints_to_alarm = "12"
+ treat_missing_data = "ignore"
+ metric_name = "CPUUtilization"
+ namespace = "AWS/EC2"
+ period = "120"
+ statistic = "Maximum"
+ threshold = "95"
+ alarm_description = "This metric monitors ec2 CPU Utilization"
+ alarm_actions = [var.alarm_sns_topic_arn]
+ unit = "Percent"
+ dimensions = {
+ InstanceId = try(
+ aws_instance.this[0].id,
+ aws_instance.ignore_ami[0].id,
+ )
+ }
+}
+
+resource "aws_cloudwatch_metric_alarm" "ec2_memory_utilization_alert_info" {
+ alarm_name = "${var.name}_high_memory_alert"
+ comparison_operator = "GreaterThanOrEqualToThreshold"
+ evaluation_periods = "5"
+ datapoints_to_alarm = "4"
+ treat_missing_data = "ignore"
+ metric_name = "MemoryUtilization"
+ namespace = "CWAgent"
+ period = "120"
+ statistic = "Average"
+ threshold = "85"
+ alarm_description = "This metric monitors EC2 memory utilization"
+ alarm_actions = [var.alarm_info_sns_topic_arn]
+ unit = "Percent"
+ dimensions = {
+ InstanceId = try(
+ aws_instance.this[0].id,
+ aws_instance.ignore_ami[0].id
+ )
+ }
+}
+
+resource "aws_cloudwatch_metric_alarm" "ec2_memory_utilization_alert_warning" {
+ alarm_name = "${var.name}_critical_memory_alert"
+ comparison_operator = "GreaterThanOrEqualToThreshold"
+ evaluation_periods = "15"
+ datapoints_to_alarm = "12"
+ treat_missing_data = "ignore"
+ metric_name = "MemoryUtilization"
+ namespace = "CWAgent"
+ period = "120"
+ statistic = "Maximum"
+ threshold = "95"
+ alarm_description = "This metric monitors EC2 memory utilization"
+ alarm_actions = [var.alarm_sns_topic_arn]
+ unit = "Percent"
+ dimensions = {
+ InstanceId = try(
+ aws_instance.this[0].id,
+ aws_instance.ignore_ami[0].id,
+ )
+ }
+}
+
+resource "aws_cloudwatch_metric_alarm" "ec2_disk_utilization_alert_info" {
+ alarm_name = "${var.name}_high_disk_alert"
+ comparison_operator = "GreaterThanOrEqualToThreshold"
+ evaluation_periods = "5"
+ datapoints_to_alarm = "4"
+ treat_missing_data = "ignore"
+ metric_name = "DiskSpaceUtilization"
+ namespace = "CWAgent"
+ period = "120"
+ statistic = "Average"
+ threshold = "85"
+ alarm_description = "This metric monitors EC2 disk space utilization"
+ alarm_actions = [var.alarm_info_sns_topic_arn]
+ unit = "Percent"
+ dimensions = {
+ InstanceId = try(
+ aws_instance.this[0].id,
+ aws_instance.ignore_ami[0].id,
+ )
+ MountPath = "/"
+ Filesystem = "ext4"
+ }
+}
+
+resource "aws_cloudwatch_metric_alarm" "ec2_disk_utilization_alert_warning" {
+ alarm_name = "${var.name}_critical_disk_alert"
+ comparison_operator = "GreaterThanOrEqualToThreshold"
+ evaluation_periods = "15"
+ datapoints_to_alarm = "12"
+ treat_missing_data = "ignore"
+ metric_name = "DiskSpaceUtilization"
+ namespace = "CWAgent"
+ period = "120"
+ statistic = "Maximum"
+ threshold = "95"
+ alarm_description = "This metric monitors EC2 disk space utilization"
+ alarm_actions = [var.alarm_sns_topic_arn]
+ unit = "Percent"
+ dimensions = {
+ InstanceId = try(
+ aws_instance.this[0].id,
+ aws_instance.ignore_ami[0].id,
+ )
+ MountPath = "/"
+ Filesystem = "ext4"
+ }
+}
diff --git a/main.tf b/main.tf
index 749e67d4..c651f8c2 100644
--- a/main.tf
+++ b/main.tf
@@ -1,7 +1,7 @@
data "aws_partition" "current" {}
locals {
- create = var.create && var.putin_khuylo
+ create = var.create
is_t_instance_type = replace(var.instance_type, "/^t(2|3|3a|4g){1}\\..*$/", "1") == "1" ? true : false
@@ -188,7 +188,23 @@ resource "aws_instance" "this" {
delete = try(var.timeouts.delete, null)
}
- tags = merge({ "Name" = var.name }, var.instance_tags, var.tags)
+ lifecycle {
+ ignore_changes = [
+ key_name,
+ instance_type,
+ ]
+ }
+
+ tags = merge({
+ "Name" = var.name,
+ "Environment" = var.environment,
+ "Service" = var.service,
+ "ServiceComponent" = var.service_component,
+ "OwnerTeam" = var.owner_team,
+ env_type_ssm = var.ssm_access_type,
+ disaster-recovery-backup = var.backup_for_disaster_recovery,
+ backup-frequency = var.backup_frequency_days
+ }, var.instance_tags, var.tags)
volume_tags = var.enable_volume_tags ? merge({ "Name" = var.name }, var.volume_tags) : null
}
diff --git a/variables.tf b/variables.tf
index 38a1b5b2..a95dbd81 100644
--- a/variables.tf
+++ b/variables.tf
@@ -160,7 +160,8 @@ variable "metadata_options" {
default = {
"http_endpoint" = "enabled"
"http_put_response_hop_limit" = 1
- "http_tokens" = "optional"
+ "http_tokens" = "required"
+ "instance_metadata_tags" = "disabled"
}
}
@@ -351,11 +352,7 @@ variable "disable_api_stop" {
default = null
}
-variable "putin_khuylo" {
- description = "Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo!"
- type = bool
- default = true
-}
+
################################################################################
# IAM Role / Instance Profile
diff --git a/wrappers/main.tf b/wrappers/main.tf
index 9ba0cdb4..c6b517dd 100644
--- a/wrappers/main.tf
+++ b/wrappers/main.tf
@@ -56,7 +56,6 @@ module "wrapper" {
placement_group = try(each.value.placement_group, var.defaults.placement_group, null)
private_dns_name_options = try(each.value.private_dns_name_options, var.defaults.private_dns_name_options, {})
private_ip = try(each.value.private_ip, var.defaults.private_ip, null)
- putin_khuylo = try(each.value.putin_khuylo, var.defaults.putin_khuylo, true)
root_block_device = try(each.value.root_block_device, var.defaults.root_block_device, [])
secondary_private_ips = try(each.value.secondary_private_ips, var.defaults.secondary_private_ips, null)
source_dest_check = try(each.value.source_dest_check, var.defaults.source_dest_check, null)