diff --git a/.github/labeler.yaml b/.github/labeler.yaml index 200191a..9285ab9 100644 --- a/.github/labeler.yaml +++ b/.github/labeler.yaml @@ -8,6 +8,9 @@ ":floppy_disk: dx-private-virtual-interface": - modules/dx-private-virtual-interface/**/* +":floppy_disk: lattice-alb-target-group": +- modules/lattice-alb-target-group/**/* + ":floppy_disk: lattice-instance-target-group": - modules/lattice-instance-target-group/**/* diff --git a/.github/labels.yaml b/.github/labels.yaml index 1e70194..3563d86 100644 --- a/.github/labels.yaml +++ b/.github/labels.yaml @@ -49,6 +49,9 @@ - color: "fbca04" description: "This issue or pull request is related to dx-private-virtual-interface module." name: ":floppy_disk: dx-private-virtual-interface" +- color: "fbca04" + description: "This issue or pull request is related to lattice-alb-target-group module." + name: ":floppy_disk: lattice-alb-target-group" - color: "fbca04" description: "This issue or pull request is related to lattice-instance-target-group module." name: ":floppy_disk: lattice-instance-target-group" diff --git a/README.md b/README.md index d37bf87..bf0fece 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Terraform module which creates VPC Connectivity related resources (VPC Peering, - [dx-connection](./modules/dx-connection) - [dx-gateway](./modules/dx-gateway) - [dx-private-virtual-interface](./modules/dx-private-virtual-interface) +- [lattice-alb-target-group](./modules/lattice-alb-target-group) - [lattice-instance-target-group](./modules/lattice-instance-target-group) - [lattice-ip-target-group](./modules/lattice-ip-target-group) - [lattice-service-listener](./modules/lattice-service-listener) diff --git a/modules/lattice-alb-target-group/README.md b/modules/lattice-alb-target-group/README.md new file mode 100644 index 0000000..43b7eef --- /dev/null +++ b/modules/lattice-alb-target-group/README.md @@ -0,0 +1,68 @@ +# lattice-alb-target-group + +This module creates following resources. + +- `aws_vpclattice_target_group` +- `aws_vpclattice_target_group_attachment` (optional) + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.5 | +| [aws](#requirement\_aws) | >= 5.12 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.17.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [resource\_group](#module\_resource\_group) | tedilabs/misc/aws//modules/resource-group | ~> 0.10.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_vpclattice_target_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_target_group) | resource | +| [aws_vpclattice_target_group_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_target_group_attachment) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [name](#input\_name) | (Required) The name of the target group. The name must be unique within the account. The valid characters are a-z, 0-9, and hyphens (-). You can't use a hyphen as the first or last character, or immediately after another hyphen. | `string` | n/a | yes | +| [protocol](#input\_protocol) | (Required) The protocol to use for routing traffic to the targets. Valid values are `HTTP` and `HTTPS`. | `string` | n/a | yes | +| [vpc](#input\_vpc) | (Required) The ID of the VPC which the target group belongs to. | `string` | n/a | yes | +| [health\_check](#input\_health\_check) | (Optional) The health check configuration of the target group. The associated service periodically sends requests according to this configuration to the registered targets to test their status. `health_check` block as defined below.
(Optional) `enabled` - Whether to enable health check. Defaults to `true`.
(Optional) `protocol` - The protocol used when performing health checks on targets. Valid values are `HTTP` and `HTTPS`. Defaults to `HTTP`.
(Optional) `protocol_version` - The protocol version used when performing health checks on targets. Valid values are `HTTP1` and `HTTP2`. Defaults to `HTTP1`.
(Optional) `port` - The port used when performing health checks on targets. The default setting is the port that a target receives traffic on.
(Optional) `path` - The destination for health checks on the targets. If the protocol version is HTTP/1.1 or HTTP/2, specify a valid URI (for example, `/path?query`). Health checks are not supported if the protocol version is gRPC, however, you can choose HTTP/1.1 or HTTP/2 and specify a valid URI. The maximum length is 1024 characters. Defaults to `/`.
(Optional) `success_codes` - The HTTP codes to use when checking for a successful response from a target. You can specify multiple values (for example, `200,202`) or a range of values (for example, `200-299`). Defaults to `200-299`.
(Optional) `interval` - The approximate amount of time between health checks of an individual target. Valid value range is 5 - 300. Defaults to `30`.
(Optional) `timeout` - The amount of time, in seconds, during which no response means a failed health check. Valid value range is 1 - 120. Defaults to `5`.
(Optional) `healthy_threshold` - The number of consecutive successful health checks required before an unhealthy target is considered healthy. Valid value range is 2 - 10. Defaults to `5`.
(Optional) `unhealthy_threshold` - The number of consecutive health check failures required before considering a target unhealthy. Valid value range is 2 - 10. Defaults to `2`. |
object({
enabled = optional(bool, true)

port = optional(number)
protocol = optional(string, "HTTP")
protocol_version = optional(string, "HTTP1")
path = optional(string, "/")

success_codes = optional(string, "200-299")

interval = optional(number, 30)
timeout = optional(number, 5)

healthy_threshold = optional(number, 5)
unhealthy_threshold = optional(number, 2)
})
| `{}` | no | +| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | +| [port](#input\_port) | (Optional) The port on which the targets are listening. Valid values are from `1` to `65535`. | `number` | `null` | no | +| [protocol\_version](#input\_protocol\_version) | (Optional) The protocol version. Valid Values are `HTTP1`, `HTTP2` and `GRPC`. Defaults to `HTTP1`. | `string` | `"HTTP1"` | no | +| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | +| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | +| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [targets](#input\_targets) | (Optional) A list of targets to add to the target group. Support only single ALB as target. Each value of `targets` block as defined below.
(Required) `name` - The name of the target. This value is only used internally within Terraform code.
(Required) `alb` - The Amazon Resource Name (ARN) of the target ALB (Application Load Balancer). The target should be internal Application Load Balancer.
(Optional) `port` - The port on which the target is listening. If `port` is not specified and `protocol` is `HTTP`, the value will default to `80`. If `port` is not specified and `protocol` is `HTTPS`, the value will default to `443`. |
list(object({
name = string
alb = string
port = optional(number)
}))
| `[]` | no | +| [timeouts](#input\_timeouts) | (Optional) How long to wait for the target group to be created/deleted. |
object({
create = optional(string, "5m")
delete = optional(string, "5m")
})
| `{}` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | The ARN of the target group. | +| [health\_check](#output\_health\_check) | The health check configuration of the target group.
`enabled` - Whether to enable health check.
`protocol` - The protocol used when performing health checks on targets.
`protocol_version` - The protocol version used when performing health checks on targets.
`port` - The port used when performing health checks on targets.
`path` - The destination for health checks on the targets.
`success_codes` - The HTTP codes to use when checking for a successful response from a target.
`interval` - The approximate amount of time between health checks of an individual target.
`timeout` - The amount of time, in seconds, during which no response means a failed health check.
`healthy_threshold` - The number of consecutive successful health checks required before an unhealthy target is considered healthy.
`unhealthy_threshold` - The number of consecutive health check failures required before considering a target unhealthy. | +| [id](#output\_id) | The ID of the target group. | +| [name](#output\_name) | The name of the target group. | +| [port](#output\_port) | The port on which the targets are listening. | +| [protocol](#output\_protocol) | The protocol to use for routing traffic to the targets. | +| [protocol\_version](#output\_protocol\_version) | The protocol version. | +| [status](#output\_status) | The status of the target group. | +| [targets](#output\_targets) | The list of targets of the target group.
`name` - The name of the target. This value is only used internally within Terraform code.
`alb` - The Amazon Resource Name (ARN) of the target ALB (Application Load Balancer).
`port` - The port on which the target is listening. | +| [type](#output\_type) | The type of target group. Always `IP`. | +| [vpc](#output\_vpc) | The ID of the VPC which the target group belongs to. | + diff --git a/modules/lattice-alb-target-group/main.tf b/modules/lattice-alb-target-group/main.tf new file mode 100644 index 0000000..ba112d3 --- /dev/null +++ b/modules/lattice-alb-target-group/main.tf @@ -0,0 +1,94 @@ +locals { + metadata = { + package = "terraform-aws-vpc-connectivity" + version = trimspace(file("${path.module}/../../VERSION")) + module = basename(path.module) + name = var.name + } + module_tags = var.module_tags_enabled ? { + "module.terraform.io/package" = local.metadata.package + "module.terraform.io/version" = local.metadata.version + "module.terraform.io/name" = local.metadata.module + "module.terraform.io/full-name" = "${local.metadata.package}/${local.metadata.module}" + "module.terraform.io/instance" = local.metadata.name + } : {} +} + +locals { + default_ports = { + "HTTP" = 80 + "HTTPS" = 443 + } +} + + +################################################### +# ALB Target Group for VPC Lattice Service +################################################### + +# INFO: Not supported attributes +# - `config.ip_address_type` +# - `config.health_check` +resource "aws_vpclattice_target_group" "this" { + name = var.name + type = "ALB" + + config { + vpc_identifier = var.vpc + + port = var.port + protocol = var.protocol + protocol_version = var.protocol_version + + health_check { + enabled = var.health_check.enabled + + port = var.health_check.port + protocol = var.health_check.protocol + protocol_version = var.health_check.protocol_version + path = var.health_check.path + + matcher { + value = var.health_check.success_codes + } + + health_check_interval_seconds = var.health_check.interval + health_check_timeout_seconds = var.health_check.timeout + + healthy_threshold_count = var.health_check.healthy_threshold + unhealthy_threshold_count = var.health_check.unhealthy_threshold + } + } + + timeouts { + create = var.timeouts.create + delete = var.timeouts.delete + } + + tags = merge( + { + "Name" = local.metadata.name + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Targets for ALB Target Group +################################################### + +resource "aws_vpclattice_target_group_attachment" "this" { + for_each = { + for target in var.targets : + target.name => target + } + + target_group_identifier = aws_vpclattice_target_group.this.id + + target { + id = each.value.alb + port = coalesce(each.value.port, local.default_ports[var.protocol]) + } +} diff --git a/modules/lattice-alb-target-group/outputs.tf b/modules/lattice-alb-target-group/outputs.tf new file mode 100644 index 0000000..884ee7a --- /dev/null +++ b/modules/lattice-alb-target-group/outputs.tf @@ -0,0 +1,93 @@ +output "id" { + description = "The ID of the target group." + value = aws_vpclattice_target_group.this.id +} + +output "arn" { + description = "The ARN of the target group." + value = aws_vpclattice_target_group.this.arn +} + +output "name" { + description = "The name of the target group." + value = aws_vpclattice_target_group.this.name +} + +output "vpc" { + description = "The ID of the VPC which the target group belongs to." + value = one(aws_vpclattice_target_group.this.config[*].vpc_identifier) +} + +output "type" { + description = "The type of target group. Always `IP`." + value = aws_vpclattice_target_group.this.type +} + +output "status" { + description = "The status of the target group." + value = aws_vpclattice_target_group.this.status +} + +output "port" { + description = "The port on which the targets are listening." + value = one(aws_vpclattice_target_group.this.config[*].port) +} + +output "protocol" { + description = "The protocol to use for routing traffic to the targets." + value = one(aws_vpclattice_target_group.this.config[*].protocol) +} + +output "protocol_version" { + description = "The protocol version." + value = one(aws_vpclattice_target_group.this.config[*].protocol_version) +} + +output "health_check" { + description = < { + name = name + alb = one(target.target[*].id) + port = one(target.target[*].port) + } + } +} diff --git a/modules/lattice-alb-target-group/resource-group.tf b/modules/lattice-alb-target-group/resource-group.tf new file mode 100644 index 0000000..7487ba0 --- /dev/null +++ b/modules/lattice-alb-target-group/resource-group.tf @@ -0,0 +1,31 @@ +locals { + resource_group_name = (var.resource_group_name != "" + ? var.resource_group_name + : join(".", [ + local.metadata.package, + local.metadata.module, + replace(local.metadata.name, "/[^a-zA-Z0-9_\\.-]/", "-"), + ]) + ) +} + + +module "resource_group" { + source = "tedilabs/misc/aws//modules/resource-group" + version = "~> 0.10.0" + + count = (var.resource_group_enabled && var.module_tags_enabled) ? 1 : 0 + + name = local.resource_group_name + description = var.resource_group_description + + query = { + resource_tags = local.module_tags + } + + module_tags_enabled = false + tags = merge( + local.module_tags, + var.tags, + ) +} diff --git a/modules/lattice-alb-target-group/variables.tf b/modules/lattice-alb-target-group/variables.tf new file mode 100644 index 0000000..5bfafdf --- /dev/null +++ b/modules/lattice-alb-target-group/variables.tf @@ -0,0 +1,212 @@ +variable "name" { + description = "(Required) The name of the target group. The name must be unique within the account. The valid characters are a-z, 0-9, and hyphens (-). You can't use a hyphen as the first or last character, or immediately after another hyphen." + type = string + nullable = false +} + +variable "vpc" { + description = "(Required) The ID of the VPC which the target group belongs to." + type = string + nullable = false +} + +variable "port" { + description = "(Optional) The port on which the targets are listening. Valid values are from `1` to `65535`. " + type = number + default = null + nullable = true + + validation { + condition = (var.port != null + ? alltrue([ + var.port >= 1, + var.port <= 65535, + ]) + : true + ) + error_message = "Valid values of `port` are 1-65535." + } +} + +variable "protocol" { + description = "(Required) The protocol to use for routing traffic to the targets. Valid values are `HTTP` and `HTTPS`." + type = string + nullable = false + + validation { + condition = contains(["HTTP", "HTTPS"], var.protocol) + error_message = "Valid values are `HTTP` and `HTTPS`." + } +} + +variable "protocol_version" { + description = "(Optional) The protocol version. Valid Values are `HTTP1`, `HTTP2` and `GRPC`. Defaults to `HTTP1`." + type = string + default = "HTTP1" + nullable = false + + validation { + condition = contains(["HTTP1", "HTTP2", "GRPC"], var.protocol_version) + error_message = "Valid values are `HTTP1`, `HTTP2` and `GRPC`." + } +} + +variable "health_check" { + description = <= 5, + var.health_check.interval <= 300, + ]) + error_message = "Valid value range for `interval` is 5 - 300." + } + validation { + condition = alltrue([ + var.health_check.timeout >= 1, + var.health_check.timeout <= 120, + ]) + error_message = "Valid value range for `timeout` is 1 - 120." + } + validation { + condition = alltrue([ + var.health_check.healthy_threshold <= 10, + var.health_check.healthy_threshold >= 2, + ]) + error_message = "Valid value range for `healthy_threshold` is 2 - 10." + } + validation { + condition = alltrue([ + var.health_check.unhealthy_threshold <= 10, + var.health_check.unhealthy_threshold >= 2, + ]) + error_message = "Valid value range for `unhealthy_threshold` is 2 - 10." + } +} + +variable "targets" { + description = <= 1, + target.port <= 65535, + ]) + if target.port != null + ]) + error_message = "Valid values of `port` are 1-65535." + } +} + +variable "timeouts" { + description = "(Optional) How long to wait for the target group to be created/deleted." + type = object({ + create = optional(string, "5m") + delete = optional(string, "5m") + }) + default = {} + nullable = false +} + +variable "tags" { + description = "(Optional) A map of tags to add to all resources." + type = map(string) + default = {} + nullable = false +} + +variable "module_tags_enabled" { + description = "(Optional) Whether to create AWS Resource Tags for the module informations." + type = bool + default = true + nullable = false +} + + +################################################### +# Resource Group +################################################### + +variable "resource_group_enabled" { + description = "(Optional) Whether to create Resource Group to find and group AWS resources which are created by this module." + type = bool + default = true + nullable = false +} + +variable "resource_group_name" { + description = "(Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`." + type = string + default = "" + nullable = false +} + +variable "resource_group_description" { + description = "(Optional) The description of Resource Group." + type = string + default = "Managed by Terraform." + nullable = false +} diff --git a/modules/lattice-alb-target-group/versions.tf b/modules/lattice-alb-target-group/versions.tf new file mode 100644 index 0000000..3ac74d4 --- /dev/null +++ b/modules/lattice-alb-target-group/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.5" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.12" + } + } +}