Skip to content

Commit

Permalink
feat(module/vmseries): Adding IPv6 support to the module (#35)
Browse files Browse the repository at this point in the history
Co-authored-by: michalbil <[email protected]>
  • Loading branch information
pavelrn and michalbil authored Sep 18, 2024
1 parent 0673ed6 commit 56aa606
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 11 deletions.
6 changes: 5 additions & 1 deletion modules/vmseries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ No modules.
| Name | Type |
|------|------|
| [google_compute_address.private](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_address) | resource |
| [google_compute_address.private_ipv6](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_address) | resource |
| [google_compute_address.public](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_address) | resource |
| [google_compute_address.public_ipv6](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_address) | resource |
| [google_compute_instance.this](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance) | resource |
| [google_compute_instance_group.this](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance_group) | resource |
| [null_resource.dependency_getter](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
Expand All @@ -56,7 +58,7 @@ No modules.
| <a name="input_min_cpu_platform"></a> [min\_cpu\_platform](#input\_min\_cpu\_platform) | Minimum CPU platform for the compute instance. Up to date version can be found [here](https://cloud.google.com/compute/docs/instances/specify-min-cpu-platform). | `string` | `"Intel Cascade Lake"` | no |
| <a name="input_name"></a> [name](#input\_name) | Name of the VM-Series instance. | `string` | n/a | yes |
| <a name="input_named_ports"></a> [named\_ports](#input\_named\_ports) | The list of named ports to create in the instance group:<pre>named_ports = [<br> {<br> name = "http"<br> port = "80"<br> },<br> {<br> name = "app42"<br> port = "4242"<br> },<br>]</pre>The name identifies the backend port to receive the traffic from the global load balancers.<br>Practically, tcp port 80 named "http" works even when not defined here, but it's not a documented provider's behavior. | `list` | `[]` | no |
| <a name="input_network_interfaces"></a> [network\_interfaces](#input\_network\_interfaces) | List of the network interface specifications.<br>Available options:<br>- `subnetwork` - (Required\|string) Self-link of a subnetwork to create interface in.<br>- `private_ip_name` - (Optional\|string) Name for a private address to reserve.<br>- `private_ip` - (Optional\|string) Private address to reserve.<br>- `create_public_ip` - (Optional\|boolean) Whether to reserve public IP for the interface. Ignored if `public_ip` is provided. Defaults to 'false'.<br>- `public_ip_name` - (Optional\|string) Name for a public address to reserve.<br>- `public_ip` - (Optional\|string) Existing public IP to use.<br>- `public_ptr_domain_name` - (Optional\|string) Existing public PTR name to use.<br>- `alias_ip_ranges` - (Optional\|list) List of objects that define additional IP ranges for an interface, as specified [here](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#ip_cidr_range) | `list(any)` | n/a | yes |
| <a name="input_network_interfaces"></a> [network\_interfaces](#input\_network\_interfaces) | List of the network interface specifications.<br>Available options:<br>- `subnetwork` - (Required\|string) Self-link of a subnetwork to create interface in.<br>- `stack_type` - (Optional\|string) IP stack to use: IPV4\_ONLY (default) or IPV4\_IPV6.<br>- `private_ip_name` - (Optional\|string) Name for a private IPv4 address to reserve.<br>- `private_ip` - (Optional\|string) Private IPv4 address to reserve.<br>- `create_public_ip` - (Optional\|boolean) Whether to reserve public IPv4 address for the interface. Ignored if `public_ip` is provided. Defaults to 'false'.<br>- `public_ip_name` - (Optional\|string) Name for a public IPv4 address to reserve.<br>- `public_ip` - (Optional\|string) Existing public IPv4 address to use.<br>- `public_ptr_domain_name` - (Optional\|string) Existing public IPv4 address PTR name to use.<br>- `alias_ip_ranges` - (Optional\|list) List of objects that define additional IP ranges for an interface, as specified [here](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#ip_cidr_range)<br>- `create_public_ipv6` - (Optional\|boolean) Whether to reserve public IPv6 address for the interface. Ignored if `public_ipv6` is provided. Defaults to 'false'.<br>- `private_ipv6_name` - (Optional\|string) Name for a private IPv6 address to reserve. Is relevant when a VPC has IPv6 ULA range.<br>- `create_private_ipv6` - (Optional\|boolean) Whether to reserve private IPv6 address for the interface. Is relevant when a VPC has IPv6 ULA range. If 'false' an ephemeral IPv6 address is assigned to the interface. Default is 'true'.<br>- `public_ipv6_name` - (Optional\|string) Name for a public IPv6 address to reserve.<br>- `public_ipv6` - (Optional\|string) Existing public IPv6 address to use. Specify address with a netmask, for example: 2600:1900:4020:bd2:8000:1::/96.<br>- `public_ipv6_ptr_domain_name` - (Optional\|string) Existing public IPv6 address PTR name to use. | `list(any)` | n/a | yes |
| <a name="input_project"></a> [project](#input\_project) | n/a | `string` | `null` | no |
| <a name="input_resource_policies"></a> [resource\_policies](#input\_resource\_policies) | n/a | `list(string)` | `[]` | no |
| <a name="input_scopes"></a> [scopes](#input\_scopes) | n/a | `list(string)` | <pre>[<br> "https://www.googleapis.com/auth/compute.readonly",<br> "https://www.googleapis.com/auth/cloud.useraccounts.readonly",<br> "https://www.googleapis.com/auth/devstorage.read_only",<br> "https://www.googleapis.com/auth/logging.write",<br> "https://www.googleapis.com/auth/monitoring.write"<br>]</pre> | no |
Expand All @@ -73,6 +75,8 @@ No modules.
| <a name="output_instance"></a> [instance](#output\_instance) | n/a |
| <a name="output_instance_group"></a> [instance\_group](#output\_instance\_group) | n/a |
| <a name="output_instance_group_self_link"></a> [instance\_group\_self\_link](#output\_instance\_group\_self\_link) | n/a |
| <a name="output_ipv6_private_ips"></a> [ipv6\_private\_ips](#output\_ipv6\_private\_ips) | n/a |
| <a name="output_ipv6_public_ips"></a> [ipv6\_public\_ips](#output\_ipv6\_public\_ips) | n/a |
| <a name="output_private_ips"></a> [private\_ips](#output\_private\_ips) | n/a |
| <a name="output_public_ips"></a> [public\_ips](#output\_public\_ips) | n/a |
| <a name="output_self_link"></a> [self\_link](#output\_self\_link) | n/a |
Expand Down
54 changes: 52 additions & 2 deletions modules/vmseries/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ locals {
}
if try(v.public_ip, null) != null || local.create_public_ip[k]
}
create_public_ipv6 = {
for k, v in var.network_interfaces : k => try(v.create_public_ipv6, false)
}
ipv6_access_configs = {
for k, v in var.network_interfaces : k => {
external_ipv6 = try(split("/", v.public_ipv6)[0], google_compute_address.public_ipv6[k].address, null)
external_ipv6_prefix_length = try(split("/", v.public_ipv6)[1], google_compute_address.public_ipv6[k].prefix_length, null)
public_ptr_domain_name = try(v.public_ipv6_ptr_domain_name, null)
}
if try(v.public_ipv6, null) != null || local.create_public_ipv6[k]
}
}

data "google_compute_image" "vmseries" {
Expand Down Expand Up @@ -41,6 +52,21 @@ resource "google_compute_address" "private" {
region = data.google_compute_subnetwork.this[each.key].region
}

resource "google_compute_address" "private_ipv6" {
for_each = { for k, v in var.network_interfaces : k => v if
try(v.stack_type, "IPV4_ONLY") == "IPV4_IPV6" &&
try(v.create_private_ipv6, true) == true &&
local.create_public_ipv6[k] == false
}

name = try(each.value.private_ipv6_name, "${var.name}-${each.key}-private-ipv6")
address_type = "INTERNAL"
ip_version = "IPV6"
project = var.project
subnetwork = each.value.subnetwork
region = data.google_compute_subnetwork.this[each.key].region
}

resource "google_compute_address" "public" {
for_each = { for k, v in var.network_interfaces : k => v if local.create_public_ip[k] && try(v.public_ip, null) == null }

Expand All @@ -50,6 +76,18 @@ resource "google_compute_address" "public" {
region = data.google_compute_subnetwork.this[each.key].region
}

resource "google_compute_address" "public_ipv6" {
for_each = { for k, v in var.network_interfaces : k => v if local.create_public_ipv6[k] && try(v.public_ipv6, null) == null }

name = try(each.value.public_ipv6_name, "${var.name}-${each.key}-public-ipv6")
address_type = "EXTERNAL"
ip_version = "IPV6"
ipv6_endpoint_type = "VM"
subnetwork = each.value.subnetwork
project = var.project
region = data.google_compute_subnetwork.this[each.key].region
}

resource "google_compute_instance" "this" {

name = var.name
Expand Down Expand Up @@ -82,8 +120,10 @@ resource "google_compute_instance" "this" {
for_each = var.network_interfaces

content {
network_ip = google_compute_address.private[network_interface.key].address
subnetwork = network_interface.value.subnetwork
stack_type = try(network_interface.value.stack_type, "IPV4_ONLY")
network_ip = google_compute_address.private[network_interface.key].address
ipv6_address = try(google_compute_address.private_ipv6[network_interface.key].address, null)
subnetwork = network_interface.value.subnetwork

dynamic "access_config" {
for_each = try(local.access_configs[network_interface.key] != null, false) ? ["one"] : []
Expand All @@ -100,6 +140,16 @@ resource "google_compute_instance" "this" {
subnetwork_range_name = try(alias_ip_range.value.subnetwork_range_name, null)
}
}

dynamic "ipv6_access_config" {
for_each = try(local.ipv6_access_configs[network_interface.key] != null, false) ? ["one"] : []
content {
external_ipv6 = try(local.ipv6_access_configs[network_interface.key].external_ipv6, null)
external_ipv6_prefix_length = try(local.ipv6_access_configs[network_interface.key].external_ipv6_prefix_length, null)
network_tier = "PREMIUM"
public_ptr_domain_name = try(local.ipv6_access_configs[network_interface.key].public_ptr_domain_name, null)
}
}
}
}

Expand Down
10 changes: 10 additions & 0 deletions modules/vmseries/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ output "private_ips" {
value = { for k, v in google_compute_instance.this.network_interface : k => v.network_ip }
}

output "ipv6_private_ips" {
value = { for k, v in google_compute_instance.this.network_interface : k => v.ipv6_address }
}

output "public_ips" {
value = { for k, v in google_compute_instance.this.network_interface : k => v.access_config[0].nat_ip if length(v.access_config) != 0 }
}

output "ipv6_public_ips" {
value = { for k, v in google_compute_instance.this.network_interface :
k => "${v.ipv6_access_config[0].external_ipv6}/${v.ipv6_access_config[0].external_ipv6_prefix_length}" if length(v.ipv6_access_config) != 0
}
}
23 changes: 15 additions & 8 deletions modules/vmseries/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,21 @@ variable "network_interfaces" {
description = <<-EOF
List of the network interface specifications.
Available options:
- `subnetwork` - (Required|string) Self-link of a subnetwork to create interface in.
- `private_ip_name` - (Optional|string) Name for a private address to reserve.
- `private_ip` - (Optional|string) Private address to reserve.
- `create_public_ip` - (Optional|boolean) Whether to reserve public IP for the interface. Ignored if `public_ip` is provided. Defaults to 'false'.
- `public_ip_name` - (Optional|string) Name for a public address to reserve.
- `public_ip` - (Optional|string) Existing public IP to use.
- `public_ptr_domain_name` - (Optional|string) Existing public PTR name to use.
- `alias_ip_ranges` - (Optional|list) List of objects that define additional IP ranges for an interface, as specified [here](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#ip_cidr_range)
- `subnetwork` - (Required|string) Self-link of a subnetwork to create interface in.
- `stack_type` - (Optional|string) IP stack to use: IPV4_ONLY (default) or IPV4_IPV6.
- `private_ip_name` - (Optional|string) Name for a private IPv4 address to reserve.
- `private_ip` - (Optional|string) Private IPv4 address to reserve.
- `create_public_ip` - (Optional|boolean) Whether to reserve public IPv4 address for the interface. Ignored if `public_ip` is provided. Defaults to 'false'.
- `public_ip_name` - (Optional|string) Name for a public IPv4 address to reserve.
- `public_ip` - (Optional|string) Existing public IPv4 address to use.
- `public_ptr_domain_name` - (Optional|string) Existing public IPv4 address PTR name to use.
- `alias_ip_ranges` - (Optional|list) List of objects that define additional IP ranges for an interface, as specified [here](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#ip_cidr_range)
- `create_public_ipv6` - (Optional|boolean) Whether to reserve public IPv6 address for the interface. Ignored if `public_ipv6` is provided. Defaults to 'false'.
- `private_ipv6_name` - (Optional|string) Name for a private IPv6 address to reserve. Is relevant when a VPC has IPv6 ULA range.
- `create_private_ipv6` - (Optional|boolean) Whether to reserve private IPv6 address for the interface. Is relevant when a VPC has IPv6 ULA range. If 'false' an ephemeral IPv6 address is assigned to the interface. Default is 'true'.
- `public_ipv6_name` - (Optional|string) Name for a public IPv6 address to reserve.
- `public_ipv6` - (Optional|string) Existing public IPv6 address to use. Specify address with a netmask, for example: 2600:1900:4020:bd2:8000:1::/96.
- `public_ipv6_ptr_domain_name` - (Optional|string) Existing public IPv6 address PTR name to use.
EOF
type = list(any)
}
Expand Down

0 comments on commit 56aa606

Please sign in to comment.