Skip to content

Add IPv6 Support #140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/terraformoptions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
| create_nat_gateway | Whether to create an NAT gateway. | bool | false|
| create_service_gateway | Whether to create a service gateway to use Oracle Services. | bool | false|
| enable_ipv6 | (Updatable) Whether IPv6 is enabled for the VCN. If enabled, Oracle will assign the VCN a IPv6 /56 CIDR block. | bool | false|
| igw_ngw_mixed_route_table_display_name | (Updatable) Name of the Mixed Route Table (NGW for IPv4, IGW for IPv6). Does not have to be unique. | string | igw-ngw-mixed-gateway |
| internet_gateway_display_name | (Updatable) Name of Internet Gateway. Does not have to be unique.| string | internet-gateway|
| internet_gateway_route_rules | (Updatable) List of routing rules to add to Internet Gateway Route Table.| list(map(string)) | null|
| local_peering_gateways | Map of Local Peering Gateways to attach to the VCN | map(any) | null|
Expand All @@ -32,8 +33,11 @@
| nat_gateway_public_ip_id | OCID of reserved IP address for NAT gateway. If default value "none" is used, then a public IP address is selected from Oracle’s public IP pool. | string | none|
| nat_gateway_route_rules | (Updatable) List of routing rules to add to NAT Gateway Route Table | list(map(string)) | null|
| service_gateway_display_name | (Updatable) Name of Service Gateway. Does not have to be unique. | string | service-gateway|
| vcn_byoipv6cidr_details | (Optional)List of BYOIPv6 CIDR blocks to be used for the VCN. | list(object) | [] |
| vcn_cidrs | (Updatable) The list of IPv4 CIDR blocks the VCN will use. The CIDR block specified for the VCN must not overlap with the CIDR block of another network. | string | ["10.0.0.0/16"]|
| vcn_dns_label | (Optional)A DNS label for the VCN, used in conjunction with the VNIC’s hostname and subnet’s DNS label to form a fully qualified domain name (FQDN) for each VNIC within this subnet. DNS resolution for hostnames in the VCN is disabled if null. | string | vcnmodule|
| vcn_ipv6private_cidr_blocks | (Optional)List of IPv6 private CIDR blocks to be used for the VCN. | list(string) | []|
| vcn_is_oracle_gua_allocation_enabled | (Optional)If Oracle will assign the VCN a IPv6 /56 CIDR block when IPv6 is enabled. | bool | true|
| vcn_name | (Optional)(Updatable) The name of the VCN that will be appended to the label_prefix. | string | vcn|

### Subnets
Expand Down
4 changes: 4 additions & 0 deletions docs/terraformoptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
| create_nat_gateway | Whether to create an NAT gateway. | bool | false|
| create_service_gateway | Whether to create a service gateway to use Oracle Services. | bool | false|
| enable_ipv6 | (Updatable) Whether IPv6 is enabled for the VCN. If enabled, Oracle will assign the VCN a IPv6 /56 CIDR block. | bool | false|
| igw_ngw_mixed_route_table_display_name | (Updatable) Name of the Mixed Route Table (NGW for IPv4, IGW for IPv6). Does not have to be unique. | string | igw-ngw-mixed-gateway |
| internet_gateway_display_name | (Updatable) Name of Internet Gateway. Does not have to be unique.| string | internet-gateway|
| internet_gateway_route_rules | (Updatable) List of routing rules to add to Internet Gateway Route Table.| list(map(string)) | null|
| local_peering_gateways | Map of Local Peering Gateways to attach to the VCN | map(any) | null|
Expand All @@ -32,8 +33,11 @@
| nat_gateway_public_ip_id | OCID of reserved IP address for NAT gateway. If default value "none" is used, then a public IP address is selected from Oracle’s public IP pool. | string | none|
| nat_gateway_route_rules | (Updatable) List of routing rules to add to NAT Gateway Route Table | list(map(string)) | null|
| service_gateway_display_name | (Updatable) Name of Service Gateway. Does not have to be unique. | string | service-gateway|
| vcn_byoipv6cidr_details | (Optional)List of BYOIPv6 CIDR blocks to be used for the VCN. | list(object) | [] |
| vcn_cidrs | (Updatable) The list of IPv4 CIDR blocks the VCN will use. The CIDR block specified for the VCN must not overlap with the CIDR block of another network. | string | ["10.0.0.0/16"]|
| vcn_dns_label | (Optional)A DNS label for the VCN, used in conjunction with the VNIC’s hostname and subnet’s DNS label to form a fully qualified domain name (FQDN) for each VNIC within this subnet. DNS resolution for hostnames in the VCN is disabled if null. | string | vcnmodule|
| vcn_ipv6private_cidr_blocks | (Optional)List of IPv6 private CIDR blocks to be used for the VCN. | list(string) | []|
| vcn_is_oracle_gua_allocation_enabled | (Optional)If Oracle will assign the VCN a IPv6 /56 CIDR block when IPv6 is enabled. | bool | true|
| vcn_name | (Optional)(Updatable) The name of the VCN that will be appended to the label_prefix. | string | vcn|

### Subnets
Expand Down
2 changes: 1 addition & 1 deletion examples/drg/version.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
oci = {
source = "oracle/oci"
version = ">=4.67.3"
version = ">=6.32.0"
}
}
required_version = ">= 1.0.0"
Expand Down
2 changes: 1 addition & 1 deletion examples/hub-spoke/version.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
oci = {
source = "oracle/oci"
version = ">=4.67.3"
version = ">=6.32.0"
}
}
required_version = ">= 1.0.0"
Expand Down
6 changes: 6 additions & 0 deletions examples/module_composition/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ module "vcn" {
vcn_name = var.vcn_name
lockdown_default_seclist = var.lockdown_default_seclist
attached_drg_id = var.attached_drg_id

# IPv6 parameters (Optional)
vcn_is_oracle_gua_allocation_enabled = var.vcn_is_oracle_gua_allocation_enabled # Enable Global Unicast Address (GUA) VCN allocation
vcn_ipv6private_cidr_blocks = var.vcn_ipv6private_cidr_blocks # List with IPv6 private CIDR blocks
vcn_byoipv6cidr_details = var.vcn_byoipv6cidr_details # List with BYOIPv6 CIDR blocks
ipv6_private_subnet_route_table_display_name = var.ipv6_private_subnet_route_table_display_name # Name of the route table used for private subnets
}
```

Expand Down
28 changes: 16 additions & 12 deletions examples/module_composition/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,24 @@ module "vcn" {
defined_tags = var.defined_tags

# vcn parameters
create_internet_gateway = var.create_internet_gateway # boolean: true or false
lockdown_default_seclist = var.lockdown_default_seclist # boolean: true or false
create_nat_gateway = var.create_nat_gateway # boolean: true or false
create_service_gateway = var.create_service_gateway # boolean: true or false
enable_ipv6 = var.enable_ipv6
vcn_cidrs = var.vcn_cidrs # List of IPv4 CIDRs
vcn_dns_label = var.vcn_dns_label
vcn_name = var.vcn_name
create_internet_gateway = var.create_internet_gateway # boolean: true or false
lockdown_default_seclist = var.lockdown_default_seclist # boolean: true or false
create_nat_gateway = var.create_nat_gateway # boolean: true or false
create_service_gateway = var.create_service_gateway # boolean: true or false
enable_ipv6 = var.enable_ipv6
vcn_cidrs = var.vcn_cidrs # List of IPv4 CIDRs
vcn_dns_label = var.vcn_dns_label
vcn_name = var.vcn_name
vcn_is_oracle_gua_allocation_enabled = var.vcn_is_oracle_gua_allocation_enabled # boolean: true or false
vcn_ipv6private_cidr_blocks = var.vcn_ipv6private_cidr_blocks # List of IPv6 private CIDRs
vcn_byoipv6cidr_details = var.vcn_byoipv6cidr_details # List of IPv6 BYO CIDR details

# gateways parameters
internet_gateway_display_name = var.internet_gateway_display_name
nat_gateway_display_name = var.nat_gateway_display_name
service_gateway_display_name = var.service_gateway_display_name
attached_drg_id = var.attached_drg_id
internet_gateway_display_name = var.internet_gateway_display_name
nat_gateway_display_name = var.nat_gateway_display_name
service_gateway_display_name = var.service_gateway_display_name
igw_ngw_mixed_route_table_display_name = var.igw_ngw_mixed_route_table_display_name
attached_drg_id = var.attached_drg_id
}

# Outputs
Expand Down
26 changes: 26 additions & 0 deletions examples/module_composition/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,29 @@ variable "service_gateway_display_name" {
default = "sgw"
}

variable "vcn_is_oracle_gua_allocation_enabled" {
description = "If Oracle will assign the VCN a IPv6 /56 CIDR block when IPv6 is enabled."
type = bool
default = false
}

variable "vcn_ipv6private_cidr_blocks" {
description = "List of private IPv6 CIDR blocks to be used for the VCN."
type = list(string)
default = []
}

variable "vcn_byoipv6cidr_details" {
description = "List of BYOIPv6 CIDR blocks to be used for the VCN."
type = list(object({
byoipv6range_id = string
ipv6cidr_block = string
}))
default = []
}

variable "igw_ngw_mixed_route_table_display_name" {
description = "(Updatable) Name of Route Table. Does not have to be unique."
type = string
default = "igw-ngw-mixed-gateway"
}
2 changes: 1 addition & 1 deletion examples/module_composition/version.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
oci = {
source = "oracle/oci"
version = ">=4.67.3"
version = ">=6.32.0"
}
}
required_version = ">= 1.0.0"
Expand Down
32 changes: 19 additions & 13 deletions modules/subnet/subnet.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

locals {
dhcp_default_options = data.oci_core_dhcp_options.dhcp_options.options.0.id
// Tenancy-specific availability domains in region
// Tenancy-specific availability domains in region
// Common reference for data source re-used throughout module
ads = data.oci_identity_availability_domains.all.availability_domains

// Map of parsed availability domain numbers to tenancy-specific names
// Used by resources with AD placement for generic selection
ad_numbers_to_names = local.ads != null ? {
for ad in local.ads : parseint(substr(ad.name, -1, -1), 10) => ad.name
for ad in local.ads : parseint(substr(ad.name, -1, -1), 10) => ad.name
} : { -1 : "" } # Fallback handles failure when unavailable but not required

// List of availability domain numbers in region
Expand All @@ -23,24 +23,30 @@ data "oci_identity_availability_domains" "all" {
}

resource "oci_core_subnet" "vcn_subnet" {
for_each = var.subnets
cidr_block = each.value.cidr_block
compartment_id = var.compartment_id
vcn_id = var.vcn_id
for_each = var.subnets

cidr_block = each.value.cidr_block
compartment_id = var.compartment_id
vcn_id = var.vcn_id
availability_domain = lookup(each.value, "availability_domain", null) != null ? local.ad_numbers_to_names[each.value.availability_domain] : null

defined_tags = var.defined_tags
dhcp_options_id = local.dhcp_default_options
display_name = lookup(each.value, "name", each.key)
dns_label = lookup(each.value, "dns_label", null)
freeform_tags = var.freeform_tags
#commented for IPV6 support
#ipv6cidr_block = var.enable_ipv6 == false ? null : each.value.ipv6cidr_block
#ipv6cidr_blocks = var.enable_ipv6 == false ? null : [each.value.ipv6cidr_block]
#prohibit_internet_ingress = var.enable_ipv6 && lookup(each.value,"type","public") == "public" ? each.value.prohibit_internet_ingress : false
prohibit_public_ip_on_vnic = lookup(each.value, "type", "public") == "public" ? false : true
route_table_id = lookup(each.value, "type", "public") == "public" ? var.ig_route_id : var.nat_route_id
security_list_ids = null
# ipv6cidr_block = var.enable_ipv6 == false ? null : each.value.ipv6cidr_block
ipv6cidr_blocks = var.enable_ipv6 == false ? null : each.value.ipv6cidr_blocks
prohibit_internet_ingress = lookup(each.value, "type", "public") == "public" ? false : true
# prohibit_public_ip_on_vnic = lookup(each.value, "type", "public") == "public" ? false : true
route_table_id = lookup(each.value, "type", "public") == "public" ? (
lookup(each.value, "igw_ngw_mixed_rt", false) == true ?
var.igw_ngw_mixed_route_id :
var.ig_route_id
) : var.nat_route_id

security_list_ids = null

lifecycle {
ignore_changes = [defined_tags, dns_label, freeform_tags]
Expand Down
6 changes: 6 additions & 0 deletions modules/subnet/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ variable "nat_route_id" {
type = string
}

variable "igw_ngw_mixed_route_id" {
description = "IPv6 route table id with IGW for IPv6 and NGW for IPv4."
type = string
default = null
}

variable "defined_tags" {
description = "predefined and scoped to a namespace to tag the resources created using defined tags."
type = map(string)
Expand Down
2 changes: 1 addition & 1 deletion modules/subnet/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ terraform {
required_providers {
oci = {
source = "oracle/oci"
version = ">=4.67.3"
version = ">=6.32.0"
}
}
required_version = ">= 1.0.0"
Expand Down
6 changes: 6 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ output "ig_route_id" {
value = join(",", oci_core_route_table.ig[*].id)
}

output "igw_ngw_mixed_route_id" {
description = "id of the internet gateway & nat gateway mixed route table"
value = one(oci_core_route_table.igw_ngw_mixed_route_id[*].id)
}

output "nat_route_id" {
description = "id of VCN NAT gateway route table"
value = join(",", oci_core_route_table.nat[*].id)
Expand All @@ -37,6 +42,7 @@ output "sgw_route_id" {
value = join(",", oci_core_route_table.service_gw[*].id)
}


# New complete outputs for each resources with provider parity. Auto-updating.
# Usefull for module composition.

Expand Down
9 changes: 9 additions & 0 deletions terraform.tfvars.example
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ attached_drg_id = null
# sub3 = {cidr_block="10.0.6.0/24",availability_domain=1}
#}

#Subnets when `enable_ipv6 = true`
## Supported notation for ipv6cidr_blocks is "newbits, netnum" or "IPv6_CIDR"
## E.g.: ipv6cidr_blocks=["8, 0", "FC00::/64"]
#subnets = {
# sub1 = {name = "subnet1", type="public", cidr_block = "10.0.4.0/24"}
# sub2 = {cidr_block="10.0.5.0/24",ipv6cidr_blocks=["8, 0"], igw_ngw_mixed_rt=true}
# sub3 = {cidr_block="10.0.7.0/24",type="private",ipv6cidr_blocks=["8, 1"]}
#}

#Logging
#enable_vcn_logging = true
#log_retention_duration = 30
32 changes: 32 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,27 @@ variable "enable_ipv6" {
default = false
}

variable "vcn_is_oracle_gua_allocation_enabled" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does gua stand for something?

description = "If Oracle will assign the VCN a IPv6 /56 CIDR block when IPv6 is enabled."
type = bool
default = true
}

variable "vcn_ipv6private_cidr_blocks" {
description = "List of IPv6 private CIDR blocks to be used for the VCN."
type = list(string)
default = []
}

variable "vcn_byoipv6cidr_details" {
description = "List of BYOIPv6 CIDR blocks to be used for the VCN."
type = list(object({
byoipv6range_id = string
ipv6cidr_block = string
}))
default = []
}

variable "lockdown_default_seclist" {
description = "whether to remove all default security rules from the VCN Default Security List"
default = true
Expand Down Expand Up @@ -143,6 +164,17 @@ variable "service_gateway_display_name" {
}
}

variable "igw_ngw_mixed_route_table_display_name" {
description = "(Updatable) Name of the Mixed Route Table (NGW for IPv4, IGW for IPv6). Does not have to be unique."
type = string
default = "igw-ngw-mixed-gateway"

validation {
condition = length(var.igw_ngw_mixed_route_table_display_name) > 0
error_message = "The igw_ngw_mixed_route_table_display_name value cannot be an empty string."
}
}

variable "internet_gateway_route_rules" {
description = "(Updatable) List of routing rules to add to Internet Gateway Route Table"
type = list(map(string))
Expand Down
48 changes: 35 additions & 13 deletions vcn.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,42 @@
resource "oci_core_vcn" "vcn" {
# We still allow module users to declare a cidr using `vcn_cidr` instead of the now recommended `vcn_cidrs`, but internally we map both to `cidr_blocks`
# The module always use the new list of string structure and let the customer update his module definition block at his own pace.
cidr_blocks = var.vcn_cidrs[*]
compartment_id = var.compartment_id
display_name = var.label_prefix == "none" ? var.vcn_name : "${var.label_prefix}-${var.vcn_name}"
dns_label = var.vcn_dns_label
is_ipv6enabled = var.enable_ipv6
cidr_blocks = var.vcn_cidrs[*]
compartment_id = var.compartment_id
display_name = var.label_prefix == "none" ? var.vcn_name : "${var.label_prefix}-${var.vcn_name}"
dns_label = var.vcn_dns_label
is_ipv6enabled = var.enable_ipv6
is_oracle_gua_allocation_enabled = var.enable_ipv6 ? var.vcn_is_oracle_gua_allocation_enabled : null
ipv6private_cidr_blocks = var.enable_ipv6 ? var.vcn_ipv6private_cidr_blocks : null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ipv6private_cidr_blocks is a crappy and thoughtless variable name and is not consistent with what vcn uses for ipv4 (not your fault) in the oci provider.

I'm willing to make a breaking change and release a new major version so we can handle this better:

  • instead of var.vcn_cidrs, we can use vcn_cidrs4 or vcn_cidrs_ipv4
  • instead of var.vcn_ipv6private_cidr_blocks, we can use vcn_cidrs6 or vcn_cidrs_ipv6

Or something along that line i.e. don't make the parameters gouge the eyes of developers who are going to use them.

Since we are thinking of making a breaking change, consider renaming other variables accordingly.


dynamic "byoipv6cidr_details" {
for_each = var.enable_ipv6 ? var.vcn_byoipv6cidr_details : []
content {
byoipv6range_id = byoipv6cidr_details.value.byoipv6range_id
ipv6cidr_block = byoipv6cidr_details.value.ipv6cidr_block
}
}

freeform_tags = var.freeform_tags
defined_tags = var.defined_tags

lifecycle {
ignore_changes = [defined_tags, dns_label, freeform_tags]
ignore_changes = [defined_tags, dns_label, freeform_tags, is_ipv6enabled, is_oracle_gua_allocation_enabled]
}
}

#Module for Subnet
module "subnet" {
source = "./modules/subnet"

compartment_id = var.compartment_id
tenancy_id = var.tenancy_id
subnets = var.subnets
enable_ipv6 = var.enable_ipv6
vcn_id = oci_core_vcn.vcn.id
ig_route_id = var.create_internet_gateway ? oci_core_route_table.ig[0].id : null
nat_route_id = var.create_nat_gateway ? oci_core_route_table.nat[0].id : null
compartment_id = var.compartment_id
tenancy_id = var.tenancy_id
subnets = local.enriched_subnets
enable_ipv6 = var.enable_ipv6
vcn_id = oci_core_vcn.vcn.id
ig_route_id = var.create_internet_gateway ? oci_core_route_table.ig[0].id : null
nat_route_id = var.create_nat_gateway ? oci_core_route_table.nat[0].id : null
igw_ngw_mixed_route_id = var.enable_ipv6 && var.create_internet_gateway && var.create_nat_gateway ? oci_core_route_table.igw_ngw_mixed_route_id[0].id : null

freeform_tags = var.freeform_tags

Expand All @@ -41,6 +52,17 @@ locals {
subnet = {
for key, value in var.subnets : key => contains(keys(value), "name") ? value.name : key
}

subnet_ipv6_cidr_blocks = var.enable_ipv6 ? {
for key, value in var.subnets : key => contains(keys(value), "ipv6cidr_blocks") ?
{ "ipv6cidr_blocks" : [for entry in value["ipv6cidr_blocks"] : length(regexall("^\\d+,[ ]?\\d+$", entry)) > 0 ? cidrsubnet(coalesce([for cidr in oci_core_vcn.vcn.ipv6cidr_blocks : cidr]...), tonumber(split(",", entry)[0]), tonumber(trim(split(",", entry)[1], " "))) : entry] } :
{ "ipv6cidr_blocks" : [] }
} : {}

enriched_subnets = { for k, v in var.subnets :
k => merge(v, lookup(local.subnet_ipv6_cidr_blocks, k, null))
}

service_logdef = { for k in local.subnet : format("%s_%s", k, "log") => { loggroup = "loggrp", service = "flowlogs", resource = k } }
}

Expand Down
Loading