diff --git a/.github/labeler.yaml b/.github/labeler.yaml
index 356c6fc..65a6f6e 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-ip-target-group":
+- modules/lattice-ip-target-group/**/*
+
":floppy_disk: lattice-service-listener":
- modules/lattice-service-listener/**/*
diff --git a/.github/labels.yaml b/.github/labels.yaml
index da1f05b..8634cd4 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-ip-target-group module."
+ name: ":floppy_disk: lattice-ip-target-group"
- color: "fbca04"
description: "This issue or pull request is related to lattice-service-listener module."
name: ":floppy_disk: lattice-service-listener"
diff --git a/README.md b/README.md
index 4578b38..fa22088 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-ip-target-group](./modules/lattice-ip-target-group)
- [lattice-service-listener](./modules/lattice-service-listener)
- [lattice-service-network](./modules/lattice-service-network)
- [lattice-service](./modules/lattice-service)
diff --git a/modules/lattice-ip-target-group/README.md b/modules/lattice-ip-target-group/README.md
new file mode 100644
index 0000000..ea28dde
--- /dev/null
+++ b/modules/lattice-ip-target-group/README.md
@@ -0,0 +1,70 @@
+# lattice-ip-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 |
+| [ip\_address\_type](#input\_ip\_address\_type) | (Optional) The type of IP addresses used for the target group. Valid values are `IPV4` or `IPV6`. Defaults to `IPV4`. | `string` | `"IPV4"` | 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. 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) `ip_address` - This is an IP address for the target.
(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
ip_address = 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. |
+| [ip\_address\_type](#output\_ip\_address\_type) | The type of IP addresses used for 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.
`ip_address` - This is an IP address for the target.
`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-ip-target-group/main.tf b/modules/lattice-ip-target-group/main.tf
new file mode 100644
index 0000000..ffdec4e
--- /dev/null
+++ b/modules/lattice-ip-target-group/main.tf
@@ -0,0 +1,92 @@
+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
+ }
+}
+
+
+###################################################
+# IP Target Group for VPC Lattice Service
+###################################################
+
+resource "aws_vpclattice_target_group" "this" {
+ name = var.name
+ type = "IP"
+
+ config {
+ vpc_identifier = var.vpc
+
+ ip_address_type = var.ip_address_type
+ 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 IP 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.ip_address
+ port = coalesce(each.value.port, local.default_ports[var.protocol])
+ }
+}
diff --git a/modules/lattice-ip-target-group/outputs.tf b/modules/lattice-ip-target-group/outputs.tf
new file mode 100644
index 0000000..01f1581
--- /dev/null
+++ b/modules/lattice-ip-target-group/outputs.tf
@@ -0,0 +1,98 @@
+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 "ip_address_type" {
+ description = "The type of IP addresses used for the target group."
+ value = one(aws_vpclattice_target_group.this.config[*].ip_address_type)
+}
+
+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
+ ip_address = one(target.target[*].id)
+ port = one(target.target[*].port)
+ }
+ }
+}
diff --git a/modules/lattice-ip-target-group/resource-group.tf b/modules/lattice-ip-target-group/resource-group.tf
new file mode 100644
index 0000000..7487ba0
--- /dev/null
+++ b/modules/lattice-ip-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-ip-target-group/variables.tf b/modules/lattice-ip-target-group/variables.tf
new file mode 100644
index 0000000..0908d6b
--- /dev/null
+++ b/modules/lattice-ip-target-group/variables.tf
@@ -0,0 +1,220 @@
+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 "ip_address_type" {
+ description = "(Optional) The type of IP addresses used for the target group. Valid values are `IPV4` or `IPV6`. Defaults to `IPV4`."
+ type = string
+ default = "IPV4"
+ nullable = false
+
+ validation {
+ condition = contains(["IPV4", "IPV6"], var.ip_address_type)
+ error_message = "Valid values are `IPV4` or `IPV6`."
+ }
+}
+
+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-ip-target-group/versions.tf b/modules/lattice-ip-target-group/versions.tf
new file mode 100644
index 0000000..3ac74d4
--- /dev/null
+++ b/modules/lattice-ip-target-group/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.5"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 5.12"
+ }
+ }
+}
diff --git a/modules/lattice-service/outputs.tf b/modules/lattice-service/outputs.tf
index 0b10a58..fb12b0f 100644
--- a/modules/lattice-service/outputs.tf
+++ b/modules/lattice-service/outputs.tf
@@ -101,7 +101,6 @@ output "listeners" {
}
}
-
output "logging" {
description = <