From cffb03d7a5470019a2e63d558eaf7d9b314ccc1c Mon Sep 17 00:00:00 2001 From: Jordan-Williams2 Date: Fri, 19 Jan 2024 01:33:20 +0000 Subject: [PATCH 1/8] feat: add reserved ip submodule --- README.md | 15 ++-- common-dev-assets | 2 +- examples/default/main.tf | 1 - examples/reserved-ips/README.md | 15 ++++ examples/reserved-ips/main.tf | 96 ++++++++++++++++++++++ examples/reserved-ips/outputs.tf | 25 ++++++ examples/reserved-ips/provider.tf | 4 + examples/reserved-ips/variables.tf | 83 +++++++++++++++++++ examples/reserved-ips/versions.tf | 15 ++++ main.tf | 16 ++-- modules/reserved-ips/README.md | 115 ++++++++++++++++++++++++++ modules/reserved-ips/main.tf | 46 +++++++++++ modules/reserved-ips/outputs.tf | 13 +++ modules/reserved-ips/variables.tf | 124 +++++++++++++++++++++++++++++ modules/reserved-ips/versions.tf | 16 ++++ moved.tf | 5 ++ tests/other_test.go | 40 ++++++++++ variables.tf | 12 ++- 18 files changed, 625 insertions(+), 18 deletions(-) create mode 100644 examples/reserved-ips/README.md create mode 100644 examples/reserved-ips/main.tf create mode 100644 examples/reserved-ips/outputs.tf create mode 100644 examples/reserved-ips/provider.tf create mode 100644 examples/reserved-ips/variables.tf create mode 100644 examples/reserved-ips/versions.tf create mode 100644 modules/reserved-ips/README.md create mode 100644 modules/reserved-ips/main.tf create mode 100644 modules/reserved-ips/outputs.tf create mode 100644 modules/reserved-ips/variables.tf create mode 100644 modules/reserved-ips/versions.tf create mode 100644 tests/other_test.go diff --git a/README.md b/README.md index c64079d3..575de42d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This module creates and configures virtual private endpoint gateways (https://cl The module supports the following actions: - Create virtual private endpoint gateways - Create reserved IP addresses -- Attach endpoint gateways to reserved IP addresses +- Attach endpoint gateways to reserved IP addresses. ### Known provider issues @@ -21,9 +21,12 @@ An IBM Provider [issue](https://github.com/IBM-Cloud/terraform-provider-ibm/issu ## Overview * [terraform-ibm-vpe-gateway](#terraform-ibm-vpe-gateway) +* [Submodules](./modules) + * [reserved-ips](./modules/reserved-ips) * [Examples](./examples) * [End-to-end example](./examples/default) * [Every multi-tenant VPE](./examples/every-mt-vpe) + * [Existing Reserved IPs example](./examples/reserved-ips) * [Contributing](#contributing) @@ -99,13 +102,14 @@ You need the following permissions to run this module. ### Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| [ip](#module\_ip) | ./modules/reserved-ips | n/a | ### Resources | Name | Type | |------|------| -| [ibm_is_subnet_reserved_ip.ip](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/is_subnet_reserved_ip) | resource | | [ibm_is_virtual_endpoint_gateway.vpe](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/is_virtual_endpoint_gateway) | resource | | [ibm_is_virtual_endpoint_gateway_ip.endpoint_gateway_ip](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/is_virtual_endpoint_gateway_ip) | resource | | [ibm_is_virtual_endpoint_gateway.vpe](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/is_virtual_endpoint_gateway) | data source | @@ -116,14 +120,15 @@ No modules. |------|-------------|------|---------|:--------:| | [cloud\_service\_by\_crn](#input\_cloud\_service\_by\_crn) | List of cloud service CRNs. The keys are the CRN. The values (all optional) give some level of control on the created VPEs. Each CRN will have a unique endpoint gateways created. For a list of supported services, see the docs [here](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). |
set(
object({
crn = string
vpe_name = optional(string) # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
service_name = optional(string) # Name of the service used to compute the name of the VPE. If not specified, the service name will be obtained from the crn.
allow_dns_resolution_binding = optional(bool, true)
})
)
| `[]` | no | | [cloud\_services](#input\_cloud\_services) | List of cloud services to create an endpoint gateway. The keys are the service names, the values (all optional) give some level of control on the created VPEs. |
set(object({
service_name = string
vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
allow_dns_resolution_binding = optional(bool, false)
}))
| `[]` | no | -| [prefix](#input\_prefix) | The prefix that you would like to append to your resources | `string` | `"vpe"` | no | +| [prefix](#input\_prefix) | The prefix that you would like to append to your resources. Value is only used if no value is passed for the `vpe_name` option in the `cloud_services` input variable. | `string` | `"vpe"` | no | | [region](#input\_region) | The region where VPC and services are deployed | `string` | `"us-south"` | no | +| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. If you wish to create your reserved ips independently and not create new ones you can first run the `reserved-ips` submodule and then copy the output `reserved_ip_map` here. |
object({
name = optional(string) # endpoint gateway IP ID
})
| `{}` | no | | [resource\_group\_id](#input\_resource\_group\_id) | ID of the resource group where endpoint gateways will be provisioned | `string` | `null` | no | | [security\_group\_ids](#input\_security\_group\_ids) | List of security group ids to attach to each endpoint gateway. | `list(string)` | `null` | no | | [service\_endpoints](#input\_service\_endpoints) | Service endpoints to use to create endpoint gateways. Can be `public`, or `private`. | `string` | `"private"` | no | | [subnet\_zone\_list](#input\_subnet\_zone\_list) | List of subnets in the VPC where gateways and reserved IPs will be provisioned. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation. |
list(
object({
name = string
id = string
zone = optional(string)
cidr = optional(string)
})
)
| `[]` | no | | [vpc\_id](#input\_vpc\_id) | ID of the VPC where the Endpoint Gateways will be created | `string` | `null` | no | -| [vpc\_name](#input\_vpc\_name) | Name of the VPC where the Endpoint Gateways will be created. This value is used to dynamically generate VPE names. | `string` | `"vpc"` | no | +| [vpc\_name](#input\_vpc\_name) | Name of the VPC where the Endpoint Gateways will be created. This value is used to dynamically generate VPE names. Value is only used if no value is passed for the `vpe_name` option in the `cloud_services` input variable. | `string` | `"vpc"` | no | ### Outputs diff --git a/common-dev-assets b/common-dev-assets index a426d22a..48ae740f 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit a426d22a4a993b113faa7a9c725d515b3b8ead0a +Subproject commit 48ae740ffbb355eb75812923d1e1675e445831b1 diff --git a/examples/default/main.tf b/examples/default/main.tf index 7b49bf73..b878f0e4 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -91,7 +91,6 @@ module "vpes" { { service_name = "cloud-object-storage" } - ] cloud_service_by_crn = [ { diff --git a/examples/reserved-ips/README.md b/examples/reserved-ips/README.md new file mode 100644 index 00000000..686ef62e --- /dev/null +++ b/examples/reserved-ips/README.md @@ -0,0 +1,15 @@ +# Existing Reserved IPs example + +This example creates reserved ips in the example and passes those values to the main modules `reserved_ips` variable which will use those existing reserved ips instead of creating new values. + +This example creates the following infrastructure: +- A resource group, if one is not passed in. +- A VPC, if one is not passed in. + - The VPC is created with three subnets across the three availability zones of the region that is passed as input. +- A security group in the VPC. + - The security group is created with a single inbound rule that allows traffic from resources that are attached to the default VPC security group. This rule is added as an example. +- The reserved IPs are created. These are later passed to the gateway as an example of how the reserved IPs module could be used. +- Two virtual private endpoint (VPE) gateways. By default, one VPE to COS and another VPE to Key Protect are created. You can change the defaults by using the `service_endpoints` input. + - Each of the two virtual private endpoint gateways are attached to the three VPC subnets. + - The new security group is attached to the two VPE gateways. + - Passes existing reserved ip values to be used instead of creating new ones. diff --git a/examples/reserved-ips/main.tf b/examples/reserved-ips/main.tf new file mode 100644 index 00000000..f3012d70 --- /dev/null +++ b/examples/reserved-ips/main.tf @@ -0,0 +1,96 @@ +############################################################################## +# Resource Group +############################################################################## +module "resource_group" { + source = "terraform-ibm-modules/resource-group/ibm" + version = "1.0.6" + # if an existing resource group is not set (null) create a new one using prefix + resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null + existing_resource_group_name = var.resource_group +} + +############################################################################## +# Create a VPC for this example using defaults from terraform-ibm-landing-zone-vpc +# ( 3 subnets across the 3 AZs in the region ) +############################################################################## + +module "vpc" { + count = var.vpc_id != null ? 0 : 1 + source = "terraform-ibm-modules/landing-zone-vpc/ibm" + version = "7.5.0" + resource_group_id = module.resource_group.resource_group_id + region = var.region + prefix = var.prefix + name = var.vpc_name + tags = var.resource_tags +} + +############################################################################## +# Demonstrate how to create a custom security group that is applied to the VPEs +# This examples allow all workload associated with the default VPC security group +# to interact with the VPEs +############################################################################## + +data "ibm_is_vpc" "vpc" { + # Explicit depends as the vpc_name is known prior to VPC creation + depends_on = [ + module.vpc + ] + name = var.vpc_id != null ? var.vpc_id : module.vpc[0].vpc_name +} + +data "ibm_is_security_group" "default_sg" { + name = data.ibm_is_vpc.vpc.default_security_group_name +} + +module "vpe_security_group" { + source = "terraform-ibm-modules/security-group/ibm" + version = "2.0.0" + security_group_name = "${var.prefix}-vpe-sg" + add_ibm_cloud_internal_rules = false # No need for the internal ibm cloud rules for SG associated with VPEs + + security_group_rules = [{ + name = "allow-all-default-sg-inbound" + direction = "inbound" + remote = data.ibm_is_security_group.default_sg.id + }] + + resource_group = module.resource_group.resource_group_id + vpc_id = var.vpc_id != null ? var.vpc_id : module.vpc[0].vpc_id +} + +############################################################################## +# Create Reserved IPs in the VPC +############################################################################## +module "ips" { + source = "../../modules/reserved-ips" + region = var.region + subnet_zone_list = var.vpc_id != null ? var.subnet_zone_list : module.vpc[0].subnet_zone_list + reserved_ips = {} + reserved_ip_cloud_services = [ + { + service_name = "kms" + }, + { + service_name = "cloud-object-storage" + } + ] +} + +############################################################################## +# Create VPEs in the VPC +############################################################################## +module "vpes" { + source = "../../" + region = var.region + prefix = var.prefix + vpc_name = var.vpc_name + vpc_id = var.vpc_id != null ? var.vpc_id : module.vpc[0].vpc_id + subnet_zone_list = var.vpc_id != null ? var.subnet_zone_list : module.vpc[0].subnet_zone_list + resource_group_id = module.resource_group.resource_group_id + security_group_ids = var.security_group_ids != null ? var.security_group_ids : [module.vpe_security_group.security_group_id] + service_endpoints = var.service_endpoints + reserved_ips = module.ips.reserved_ip_map +} + +############################################################################## diff --git a/examples/reserved-ips/outputs.tf b/examples/reserved-ips/outputs.tf new file mode 100644 index 00000000..bbd38156 --- /dev/null +++ b/examples/reserved-ips/outputs.tf @@ -0,0 +1,25 @@ +output "vpe_ips" { + description = "The endpoint gateway reserved ips" + value = module.vpes.vpe_ips +} + +output "crn" { + description = "The CRN of the endpoint gateway" + value = module.vpes.crn +} + + +output "reserved_ips" { + description = "The map of reserved ips created in the example" + value = module.ips.reserved_ip_map +} + +output "endpoint_ip_list" { + description = "The endpoint ip list created in the example" + value = module.ips.endpoint_ip_list +} + +output "subnet_zone_list" { + description = "The subnet zone list created in the example" + value = var.vpc_id != null ? var.subnet_zone_list : module.vpc[0].subnet_zone_list +} diff --git a/examples/reserved-ips/provider.tf b/examples/reserved-ips/provider.tf new file mode 100644 index 00000000..df45ef50 --- /dev/null +++ b/examples/reserved-ips/provider.tf @@ -0,0 +1,4 @@ +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region +} diff --git a/examples/reserved-ips/variables.tf b/examples/reserved-ips/variables.tf new file mode 100644 index 00000000..9e3e4692 --- /dev/null +++ b/examples/reserved-ips/variables.tf @@ -0,0 +1,83 @@ +variable "ibmcloud_api_key" { + type = string + description = "The IBM Cloud API Key" + sensitive = true +} + +variable "region" { + description = "The region where VPC and services are deployed" + type = string + default = "us-south" +} + +variable "prefix" { + description = "The prefix that you would like to append to your resources" + type = string + default = "vpe" +} + +variable "resource_group" { + type = string + description = "An existing resource group name to use for this example, if unset a new resource group will be created" + default = null +} + +############################################################################## +# VPC Variables +############################################################################## + +variable "vpc_name" { + description = "Name of the VPC where the Endpoint Gateways will be created. This value is used to dynamically generate VPE names. It is also used to create a VPC when the vpc_id input is set to null." + type = string + default = "vpc-instance" +} + +variable "vpc_id" { + description = "ID of the VPC where the Endpoint Gateways will be created. Creates a VPC if set to null." + type = string + default = null +} + +############################################################################## + +############################################################################## +# VPE Variables +############################################################################## + +variable "subnet_zone_list" { + description = "List of subnets in the VPC where gateways and reserved IPs will be provisioned. This value is intended to use the `subnet_zone_list` output from the ICSE VPC Subnet Module (https://github.com/Cloud-Schematics/vpc-subnet-module) or from templates using that module for subnet creation." + type = list( + object({ + name = string + id = string + zone = optional(string) + cidr = optional(string) + }) + ) + default = [] +} + +variable "security_group_ids" { + description = "List of security group ids to attach to each endpoint gateway." + type = list(string) + default = null +} + +variable "service_endpoints" { + description = "Service endpoints to use to create endpoint gateways. Can be `public`, or `private`." + type = string + default = "private" + + validation { + error_message = "Service endpoints can only be `public` or `private`." + condition = contains(["public", "private"], var.service_endpoints) + } +} + +variable "resource_tags" { + type = list(string) + description = "Optional list of tags to be added to created resources" + default = [] +} + +############################################################################## diff --git a/examples/reserved-ips/versions.tf b/examples/reserved-ips/versions.tf new file mode 100644 index 00000000..ee92dded --- /dev/null +++ b/examples/reserved-ips/versions.tf @@ -0,0 +1,15 @@ +############################################################################## +# Terraform Providers +############################################################################## + +terraform { + required_version = ">= 1.3.0" + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + version = ">= 1.58.0" + } + } +} + +############################################################################## diff --git a/main.tf b/main.tf index c9055c56..1137f17e 100644 --- a/main.tf +++ b/main.tf @@ -65,14 +65,12 @@ locals { # Create Reserved IPs ############################################################################## -resource "ibm_is_subnet_reserved_ip" "ip" { - for_each = { - # Create a map based on endpoint IP name - for gateway_ip in local.endpoint_ip_list : - (gateway_ip.ip_name) => gateway_ip - } - name = each.value.name - subnet = each.value.subnet_id +module "ip" { + source = "./modules/reserved-ips" + endpoint_ip_list = local.endpoint_ip_list + reserved_ips = var.reserved_ips + prefix = var.prefix + vpc_name = var.vpc_name } ############################################################################## @@ -113,7 +111,7 @@ resource "ibm_is_virtual_endpoint_gateway_ip" "endpoint_gateway_ip" { (gateway_ip.ip_name) => gateway_ip } gateway = local.vpe_map[each.value.gateway_name].id - reserved_ip = ibm_is_subnet_reserved_ip.ip[each.key].reserved_ip + reserved_ip = lookup(var.reserved_ips, each.value.name, module.ip.reserved_ip_map[each.value.name]) } ############################################################################## diff --git a/modules/reserved-ips/README.md b/modules/reserved-ips/README.md new file mode 100644 index 00000000..3e3b0fbe --- /dev/null +++ b/modules/reserved-ips/README.md @@ -0,0 +1,115 @@ +# Reserved IP's Module + +The module creates reserved IPs (https://cloud.ibm.com/docs/vpc?topic=vpc-managing-ip-addresses) on existing subnets. Reserved IPs can be assigned to your resources, for example VPE endpoint gateways. + +The module supports the following actions: +- Create reserved IP addresses + +### Usage + +```hcl +provider "ibm" { + ibmcloud_api_key = "XXXXXXXXXX" # pragma: allowlist secret + region = "us-south" +} + +# - Reserved IP +module "ip" { + source = "terraform-ibm-modules/vpe-gateway/ibm//modules/reserved-ips" + cloud_services = [ + { + service_name = "kms" + }, + { + service_name = "cloud-object-storage" + } + ] + subnet_zone_list = [ + [ + { + "id" = "0717-6ff0a6fb-e180-4048-9daf-a2f99f8740cd" + "name" = "vpe-vpc-instance-subnet-a" + "zone" = "us-south-1" + } + ], + [ + { + "id" = "0727-c402f19e-ee68-41b6-90f0-a17d51f629ff" + "name" = "vpe-vpc-instance-subnet-b" + "zone" = "us-south-2" + } + ], + [ + { + "id" = "0737-323dc004-19c5-4d27-b5bc-028b1189a316" + "name" = "vpe-vpc-instance-subnet-c" + "zone" = "us-south-3" + } + ], + ] + region = "us-south" + prefix = "vpe-default" + vpc_name = "vpc-instance" +} +``` + +The above will create 6 new reserved ips as such and output them: +``` + reserved_ips = { + "vpe-vpc-cloud-object-storage-1" = "0717-13bea57a-61cd-4c91-bc17-77e0a1088283" + "vpe-vpc-cloud-object-storage-2" = "0727-5d84bf9a-20ca-4592-9f8c-b8c2d0e7f5ac" + "vpe-vpc-cloud-object-storage-3" = "0737-6a6a353d-16d0-4aaf-a46f-14f312363a62" + "vpe-vpc-kms-1" = "0717-d00e85c2-4e6a-43ef-81a7-58f69ecc70af" + "vpe-vpc-kms-2" = "0727-bd171da2-f4d6-4f12-906f-8157f16a03ad" + "vpe-vpc-kms-3" = "0737-8e2485dd-9ca9-4818-bfc7-9a5861901de3" + } +``` + +### Required IAM access policies +You need the following permissions to run this module. + +- Account Management + - **Resource Group** service + - `Viewer` platform access +- IAM Services + - **VPC Infrastructure Services** service + - `Editor` platform access + + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >=1.3, <1.6 | +| [ibm](#requirement\_ibm) | >= 1.58.0, <2.0.0 | + +### Modules + +No modules. + +### Resources + +| Name | Type | +|------|------| +| [ibm_is_subnet_reserved_ip.ip](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/is_subnet_reserved_ip) | resource | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [cloud\_service\_by\_crn](#input\_cloud\_service\_by\_crn) | List of cloud service CRNs. Each CRN will have a unique endpoint gateways created. For a list of supported services, see the docs [here](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). |
list(
object({
name = string # service name
crn = string # service crn
})
)
| `[]` | no | +| [endpoint\_ip\_list](#input\_endpoint\_ip\_list) | List of IPs to create. Each object contains an ip name and subnet id |
list(
object({
ip_name = string # reserved ip name
subnet_id = string # subnet id
gateway_name = string # gateway name
name = string # ip name
})
)
| `[]` | no | +| [prefix](#input\_prefix) | The prefix that you would like to append to your resources. Value is only used if no value is passed for the `vpe_name` option in the `reserved_ip_cloud_services` input variable. | `string` | `"vpe"` | no | +| [region](#input\_region) | The region to be used in the reserved ip naming convention. | `string` | `"us-south"` | no | +| [reserved\_ip\_cloud\_services](#input\_reserved\_ip\_cloud\_services) | List of cloud services to create reserved ips for. The keys are the service names, the values (all optional) give some level of control on the created VPEs. |
set(object({
service_name = string
vpe_name = optional(string),
}))
| `[]` | no | +| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used in the main module in which a user passes their existing reserved ips created here so as to not attempt to recreate them. |
object({
name = optional(string) # endpoint gateway IP ID
})
| `{}` | no | +| [subnet\_zone\_list](#input\_subnet\_zone\_list) | List of subnets in the VPC where reserved IPs will be provisioned. `name`, and `zone` are used in the naming convention of the reserved ip's which are then assigned to the subnet `id`. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation. |
list(
object({
name = string
id = string
zone = optional(string)
})
)
| `[]` | no | +| [vpc\_name](#input\_vpc\_name) | Name of the VPC that will be used in naming the newly created reserved ip(s). Value is only used if no value is passed for the `vpe_name` option in the `reserved_ip_cloud_services` input variable. | `string` | `"vpc"` | no | + +### Outputs + +| Name | Description | +|------|-------------| +| [endpoint\_ip\_list](#output\_endpoint\_ip\_list) | The endpoint gateway reserved ips | +| [reserved\_ip\_map](#output\_reserved\_ip\_map) | The endpoint gateway reserved ips | + diff --git a/modules/reserved-ips/main.tf b/modules/reserved-ips/main.tf new file mode 100644 index 00000000..0ff80282 --- /dev/null +++ b/modules/reserved-ips/main.tf @@ -0,0 +1,46 @@ +############################################################################## +# VPE Locals +############################################################################## + +locals { + # List of IPs to create + endpoint_ip_list = length(var.endpoint_ip_list) == 0 ? flatten([ + # Create object for each subnet + for subnet in var.subnet_zone_list : + concat([ + for service in var.reserved_ip_cloud_services : + { + ip_name = "${subnet.name}-${service.service_name}-gateway-${replace(subnet.zone, "/${var.region}-/", "")}-ip" + subnet_id = subnet.id + name = service.vpe_name != null ? "${service.vpe_name}-${replace(subnet.zone, "/${var.region}-/", "")}" : "${var.prefix}-${var.vpc_name}-${service.service_name}-${replace(subnet.zone, "/${var.region}-/", "")}" + } + ], + [ + for service in var.cloud_service_by_crn : + { + ip_name = service.vpe_name != null ? "${subnet.name}-${service.vpe_name}-gateway-${replace(subnet.zone, "/${var.region}-/", "")}-ip" : "${subnet.name}-${service.service_name != null ? service.service_name : element(split(":", service.crn), 4)}-gateway-${replace(subnet.zone, "/${var.region}-/", "")}-ip" + subnet_id = subnet.id + name = service.vpe_name != null ? "${service.vpe_name}-${replace(subnet.zone, "/${var.region}-/", "")}" : "${var.prefix}-${var.vpc_name}-${service.service_name != null ? service.service_name : element(split(":", service.crn), 4)}-${replace(subnet.zone, "/${var.region}-/", "")}" + } + ]) + ]) : var.endpoint_ip_list + +} + +############################################################################## + +############################################################################## +# Create Reserved IPs +############################################################################## + +resource "ibm_is_subnet_reserved_ip" "ip" { + for_each = { + # Create a map based on endpoint IP name + for gateway_ip in local.endpoint_ip_list : + (gateway_ip.ip_name) => gateway_ip + if lookup(var.reserved_ips, gateway_ip.name, null) == null + } + name = each.value.name + subnet = each.value.subnet_id + +} diff --git a/modules/reserved-ips/outputs.tf b/modules/reserved-ips/outputs.tf new file mode 100644 index 00000000..b02eb8db --- /dev/null +++ b/modules/reserved-ips/outputs.tf @@ -0,0 +1,13 @@ +output "reserved_ip_map" { + description = "The endpoint gateway reserved ips" + value = { + for reserved_ip in ibm_is_subnet_reserved_ip.ip : + # Create object for each reservedIP + (reserved_ip.name) => reserved_ip.reserved_ip + } +} + +output "endpoint_ip_list" { + description = "The endpoint gateway reserved ips" + value = local.endpoint_ip_list +} diff --git a/modules/reserved-ips/variables.tf b/modules/reserved-ips/variables.tf new file mode 100644 index 00000000..3119a4bc --- /dev/null +++ b/modules/reserved-ips/variables.tf @@ -0,0 +1,124 @@ +############################################################################## +# VPC Variables +############################################################################## + +variable "prefix" { + description = "The prefix that you would like to append to your resources. Value is only used if no value is passed for the `vpe_name` option in the `reserved_ip_cloud_services` input variable." + type = string + default = "vpe" +} + +variable "vpc_name" { + description = "Name of the VPC that will be used in naming the newly created reserved ip(s). Value is only used if no value is passed for the `vpe_name` option in the `reserved_ip_cloud_services` input variable." + type = string + default = "vpc" +} + +############################################################################## +# SUBNET Variables +############################################################################## + +variable "subnet_zone_list" { + description = "List of subnets in the VPC where reserved IPs will be provisioned. `name`, and `zone` are used in the naming convention of the reserved ip's which are then assigned to the subnet `id`. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation." + type = list( + object({ + name = string + id = string + zone = optional(string) + }) + ) + default = [] +} + + +############################################################################## +# VPE Variables +############################################################################## + +variable "region" { + description = "The region to be used in the reserved ip naming convention." + type = string + default = "us-south" +} + +variable "reserved_ip_cloud_services" { + description = "List of cloud services to create reserved ips for. The keys are the service names, the values (all optional) give some level of control on the created VPEs." + type = set(object({ + service_name = string + vpe_name = optional(string), + })) + default = [] + validation { + error_message = "Currently the service you're trying to add is not supported. Any other VPE services must be added using `cloud_service_by_crn`." + condition = length(var.reserved_ip_cloud_services) == 0 ? true : length([ + for service in var.reserved_ip_cloud_services : + service.service_name if !contains([ + "account-management", + "billing", + "cloud-object-storage", + "cloud-object-storage-config", + "codeengine", + "container-registry", + "containers-kubernetes", + "context-based-restrictions", + "directlink", + "dns-svcs", + "enterprise", + "global-search-tagging", + "globalcatalog", + "hs-crypto", + "hs-crypto-cert-mgr", + "hs-crypto-ep11", + "hs-crypto-ep11-az1", + "hs-crypto-ep11-az2", + "hs-crypto-ep11-az3", + "hs-crypto-kmip", + "hs-crypto-tke", + "hyperp-dbaas-mongodb", + "hyperp-dbaas-postgresql", + "iam-svcs", + "is", + "kms", + "messaging", + "resource-controller", + "support-center", + "transit", + "user-management", + "vmware", + "ntp" + ], service.service_name) + ]) == 0 + } +} + +variable "cloud_service_by_crn" { + description = "List of cloud service CRNs. Each CRN will have a unique endpoint gateways created. For a list of supported services, see the docs [here](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services)." + type = list( + object({ + name = string # service name + crn = string # service crn + }) + ) + default = [] +} + +variable "endpoint_ip_list" { + description = "List of IPs to create. Each object contains an ip name and subnet id" + type = list( + object({ + ip_name = string # reserved ip name + subnet_id = string # subnet id + gateway_name = string # gateway name + name = string # ip name + }) + ) + default = [] +} + +variable "reserved_ips" { + description = "Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used in the main module in which a user passes their existing reserved ips created here so as to not attempt to recreate them." + type = object({ + name = optional(string) # endpoint gateway IP ID + }) + default = {} +} diff --git a/modules/reserved-ips/versions.tf b/modules/reserved-ips/versions.tf new file mode 100644 index 00000000..cdfd0f63 --- /dev/null +++ b/modules/reserved-ips/versions.tf @@ -0,0 +1,16 @@ +############################################################################## +# Terraform Providers +############################################################################## + +terraform { + # Use "greater than or equal to" range in modules + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + version = ">= 1.58.0, <2.0.0" + } + } + required_version = ">=1.3, <1.6" +} + +############################################################################## diff --git a/moved.tf b/moved.tf index 52af53a9..0bcb05ae 100644 --- a/moved.tf +++ b/moved.tf @@ -7,3 +7,8 @@ moved { from = ibm_is_virtual_endpoint_gateway.vpe["vpc-instance-kms"] to = ibm_is_virtual_endpoint_gateway.vpe[0] } + +moved { + from = ibm_is_subnet_reserved_ip.ip + to = module.ip.ibm_is_subnet_reserved_ip.ip +} diff --git a/tests/other_test.go b/tests/other_test.go new file mode 100644 index 00000000..9b6801be --- /dev/null +++ b/tests/other_test.go @@ -0,0 +1,40 @@ +// Tests in this file are run in the PR pipeline +package test + +import ( + "fmt" + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" + "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper" +) + +const reservedIpExampleTerraformDir = "examples/reserved-ips" + +func TestRunReservedIpExample(t *testing.T) { + t.Parallel() + + options := setupOptions(t, "res-ips", reservedIpExampleTerraformDir) + options.SkipTestTearDown = true + output, err := options.RunTestConsistency() + assert.Nil(t, err, "This should not have errored") + assert.NotNil(t, output, "Expected some output") + // checking vpe_ips to exist + outputs := terraform.OutputAll(options.Testing, options.TerraformOptions) + expectedOutputs := []string{"vpe_ips"} + _, outputErr := testhelper.ValidateTerraformOutputs(outputs, expectedOutputs...) + assert.NoErrorf(t, outputErr, "Some outputs not found or nil") + // checking vpe_ips to contain a set on not empty slices as expected + mapToValidate, ok := outputs["vpe_ips"].(map[string]interface{}) + var outputErrMap error + if !ok { + outputErrMap = fmt.Errorf("Output: Failed to read value of key %s\n", "vpe_ips") + } else { + _, outputErrMap = ValidateOutputMapOfSlicesContent(mapToValidate) + } + + assert.NoErrorf(t, outputErr, "Some outputs not found or nil") + assert.NoErrorf(t, outputErrMap, "Some outputs not having the expected structure") + options.TestTearDown() +} diff --git a/variables.tf b/variables.tf index 222b6244..a322d7ce 100644 --- a/variables.tf +++ b/variables.tf @@ -9,13 +9,13 @@ variable "region" { } variable "prefix" { - description = "The prefix that you would like to append to your resources" + description = "The prefix that you would like to append to your resources. Value is only used if no value is passed for the `vpe_name` option in the `cloud_services` input variable." type = string default = "vpe" } variable "vpc_name" { - description = "Name of the VPC where the Endpoint Gateways will be created. This value is used to dynamically generate VPE names." + description = "Name of the VPC where the Endpoint Gateways will be created. This value is used to dynamically generate VPE names. Value is only used if no value is passed for the `vpe_name` option in the `cloud_services` input variable." type = string default = "vpc" } @@ -133,4 +133,12 @@ variable "service_endpoints" { } } +variable "reserved_ips" { + description = "Map of existing reserved IP names and values. If you wish to create your reserved ips independently and not create new ones you can first run the `reserved-ips` submodule and then copy the output `reserved_ip_map` here." + type = object({ + name = optional(string) # endpoint gateway IP ID + }) + default = {} +} + ############################################################################## From 2593d503468977a4d5aada05314a1a3a3d4f32a9 Mon Sep 17 00:00:00 2001 From: Jordan-Williams2 Date: Sun, 21 Jan 2024 22:14:47 +0000 Subject: [PATCH 2/8] fix: pre-commit --- common-dev-assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common-dev-assets b/common-dev-assets index 48ae740f..cde71895 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit 48ae740ffbb355eb75812923d1e1675e445831b1 +Subproject commit cde718957a58556de40981a01657d34339d792f9 From 258991540c13f2e7a703028120f7828164cafe58 Mon Sep 17 00:00:00 2001 From: Jordan-Williams2 Date: Wed, 24 Jan 2024 02:45:49 +0000 Subject: [PATCH 3/8] fix: disable dns-svc for time being --- common-dev-assets | 2 +- examples/every-mt-vpe/main.tf | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/common-dev-assets b/common-dev-assets index cde71895..6eb04f44 160000 --- a/common-dev-assets +++ b/common-dev-assets @@ -1 +1 @@ -Subproject commit cde718957a58556de40981a01657d34339d792f9 +Subproject commit 6eb04f44a7baf0c6abe98531a9a62fcfe2839b41 diff --git a/examples/every-mt-vpe/main.tf b/examples/every-mt-vpe/main.tf index f0d9c613..6af73215 100644 --- a/examples/every-mt-vpe/main.tf +++ b/examples/every-mt-vpe/main.tf @@ -69,9 +69,10 @@ module "vpes" { { service_name = "directlink" }, - { - service_name = "dns-svcs" - }, + # Disabling dns-svcs till we fix test failure. + # { + # service_name = "dns-svcs" + # }, { service_name = "enterprise" }, From 8c25580f7dbc79e05f7c6802066a0f055f8553a8 Mon Sep 17 00:00:00 2001 From: Jordan-Williams2 Date: Tue, 3 Sep 2024 00:25:25 +0100 Subject: [PATCH 4/8] fix: pre-commit --- modules/reserved-ips/versions.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/reserved-ips/versions.tf b/modules/reserved-ips/versions.tf index cdfd0f63..2cac6069 100644 --- a/modules/reserved-ips/versions.tf +++ b/modules/reserved-ips/versions.tf @@ -10,7 +10,7 @@ terraform { version = ">= 1.58.0, <2.0.0" } } - required_version = ">=1.3, <1.6" + required_version = ">=1.3" } ############################################################################## From b5322f4dbdbdedd7b96e5183cdc707194ffa1104 Mon Sep 17 00:00:00 2001 From: Jordan-Williams2 Date: Tue, 3 Sep 2024 00:33:27 +0100 Subject: [PATCH 5/8] fix: pre-commit --- modules/reserved-ips/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/reserved-ips/README.md b/modules/reserved-ips/README.md index 3e3b0fbe..109301a6 100644 --- a/modules/reserved-ips/README.md +++ b/modules/reserved-ips/README.md @@ -80,7 +80,7 @@ You need the following permissions to run this module. | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >=1.3, <1.6 | +| [terraform](#requirement\_terraform) | >=1.3 | | [ibm](#requirement\_ibm) | >= 1.58.0, <2.0.0 | ### Modules From 3ca474cd16339ec1cefc831dc9fe2a1c1e28d059 Mon Sep 17 00:00:00 2001 From: Jordan-Williams2 Date: Mon, 7 Oct 2024 13:33:02 +0100 Subject: [PATCH 6/8] fix: readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ac2f2d0d..c879af3c 100644 --- a/README.md +++ b/README.md @@ -122,15 +122,15 @@ You need the following permissions to run this module. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [cloud\_service\_by\_crn](#input\_cloud\_service\_by\_crn) | The list of cloud service CRNs used to create endpoint gateways. Use this list to identify services that are not supported by service name in the `cloud_services` variable. For a list of supported services, see [VPE-enabled services](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). If `service_name` is not specified, the CRN is used to find the name. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. |
set(
object({
crn = string
vpe_name = optional(string) # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
service_name = optional(string) # Name of the service used to compute the name of the VPE. If not specified, the service name will be obtained from the crn.
allow_dns_resolution_binding = optional(bool, true)
})
)
| `[]` | no | -| [cloud\_services](#input\_cloud\_services) | The list of cloud services used to create endpoint gateways. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. |
set(object({
service_name = string
vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
allow_dns_resolution_binding = optional(bool, false)
}))
| `[]` | no | -| [prefix](#input\_prefix) | The prefix that you would like to append to your resources | `string` | `"vpe"` | no | +| [cloud\_service\_by\_crn](#input\_cloud\_service\_by\_crn) | The list of cloud service CRNs used to create endpoint gateways. Use this list to identify services that are not supported by service name in the `cloud_services` variable. For a list of supported services, see [VPE-enabled services](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). If `service_name` is not specified, the CRN is used to find the name. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. |
set(
object({
crn = string
vpe_name = optional(string) # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
service_name = optional(string) # Name of the service used to compute the name of the VPE. If not specified, the service name will be obtained from the crn.
allow_dns_resolution_binding = optional(bool, true)
})
)
| `[]` | no | +| [cloud\_services](#input\_cloud\_services) | The list of cloud services used to create endpoint gateways. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. |
set(object({
service_name = string
vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
allow_dns_resolution_binding = optional(bool, false)
}))
| `[]` | no | +| [prefix](#input\_prefix) | The prefix that you would like to append to your resources. Value is only used if no value is passed for the `vpe_name` option in the `cloud_services` input variable. | `string` | `"vpe"` | no | | [region](#input\_region) | The region where VPC and services are deployed | `string` | `"us-south"` | no | | [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. If you wish to create your reserved ips independently and not create new ones you can first run the `reserved-ips` submodule and then copy the output `reserved_ip_map` here. |
object({
name = optional(string) # endpoint gateway IP ID
})
| `{}` | no | | [resource\_group\_id](#input\_resource\_group\_id) | ID of the resource group where endpoint gateways will be provisioned | `string` | `null` | no | | [security\_group\_ids](#input\_security\_group\_ids) | List of security group ids to attach to each endpoint gateway. | `list(string)` | `null` | no | | [service\_endpoints](#input\_service\_endpoints) | Service endpoints to use to create endpoint gateways. Can be `public`, or `private`. | `string` | `"private"` | no | -| [subnet\_zone\_list](#input\_subnet\_zone\_list) | List of subnets in the VPC where gateways and reserved IPs will be provisioned. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation. |
list(
object({
name = string
id = string
zone = string
cidr = optional(string)
})
)
| `[]` | no | +| [subnet\_zone\_list](#input\_subnet\_zone\_list) | List of subnets in the VPC where gateways and reserved IPs will be provisioned. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation. |
list(
object({
name = string
id = string
zone = string
cidr = optional(string)
})
)
| `[]` | no | | [vpc\_id](#input\_vpc\_id) | ID of the VPC where the Endpoint Gateways will be created | `string` | `null` | no | | [vpc\_name](#input\_vpc\_name) | A label that can be used as a short name for virtual private endpoints. If `vpe_name` is not specified in the `cloud_services` or `cloud_service_by_crn` input variable lists, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. | `string` | `"vpc"` | no | From 1f990f796124fb4171dbb8d2451b55131402f660 Mon Sep 17 00:00:00 2001 From: Jordan-Williams2 Date: Tue, 8 Oct 2024 13:49:34 +0100 Subject: [PATCH 7/8] fix: docs --- README.md | 8 ++++---- modules/reserved-ips/README.md | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c879af3c..73c441fc 100644 --- a/README.md +++ b/README.md @@ -122,15 +122,15 @@ You need the following permissions to run this module. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [cloud\_service\_by\_crn](#input\_cloud\_service\_by\_crn) | The list of cloud service CRNs used to create endpoint gateways. Use this list to identify services that are not supported by service name in the `cloud_services` variable. For a list of supported services, see [VPE-enabled services](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). If `service_name` is not specified, the CRN is used to find the name. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. |
set(
object({
crn = string
vpe_name = optional(string) # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
service_name = optional(string) # Name of the service used to compute the name of the VPE. If not specified, the service name will be obtained from the crn.
allow_dns_resolution_binding = optional(bool, true)
})
)
| `[]` | no | -| [cloud\_services](#input\_cloud\_services) | The list of cloud services used to create endpoint gateways. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. |
set(object({
service_name = string
vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
allow_dns_resolution_binding = optional(bool, false)
}))
| `[]` | no | +| [cloud\_service\_by\_crn](#input\_cloud\_service\_by\_crn) | The list of cloud service CRNs used to create endpoint gateways. Use this list to identify services that are not supported by service name in the `cloud_services` variable. For a list of supported services, see [VPE-enabled services](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). If `service_name` is not specified, the CRN is used to find the name. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. |
set(
object({
crn = string
vpe_name = optional(string) # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
service_name = optional(string) # Name of the service used to compute the name of the VPE. If not specified, the service name will be obtained from the crn.
allow_dns_resolution_binding = optional(bool, true)
})
)
| `[]` | no | +| [cloud\_services](#input\_cloud\_services) | The list of cloud services used to create endpoint gateways. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. |
set(object({
service_name = string
vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
allow_dns_resolution_binding = optional(bool, false)
}))
| `[]` | no | | [prefix](#input\_prefix) | The prefix that you would like to append to your resources. Value is only used if no value is passed for the `vpe_name` option in the `cloud_services` input variable. | `string` | `"vpe"` | no | | [region](#input\_region) | The region where VPC and services are deployed | `string` | `"us-south"` | no | -| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. If you wish to create your reserved ips independently and not create new ones you can first run the `reserved-ips` submodule and then copy the output `reserved_ip_map` here. |
object({
name = optional(string) # endpoint gateway IP ID
})
| `{}` | no | +| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. If you wish to create your reserved ips independently and not create new ones you can first run the `reserved-ips` submodule and then copy the output `reserved_ip_map` here. |
object({
name = optional(string) # endpoint gateway IP ID
})
| `{}` | no | | [resource\_group\_id](#input\_resource\_group\_id) | ID of the resource group where endpoint gateways will be provisioned | `string` | `null` | no | | [security\_group\_ids](#input\_security\_group\_ids) | List of security group ids to attach to each endpoint gateway. | `list(string)` | `null` | no | | [service\_endpoints](#input\_service\_endpoints) | Service endpoints to use to create endpoint gateways. Can be `public`, or `private`. | `string` | `"private"` | no | -| [subnet\_zone\_list](#input\_subnet\_zone\_list) | List of subnets in the VPC where gateways and reserved IPs will be provisioned. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation. |
list(
object({
name = string
id = string
zone = string
cidr = optional(string)
})
)
| `[]` | no | +| [subnet\_zone\_list](#input\_subnet\_zone\_list) | List of subnets in the VPC where gateways and reserved IPs will be provisioned. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation. |
list(
object({
name = string
id = string
zone = string
cidr = optional(string)
})
)
| `[]` | no | | [vpc\_id](#input\_vpc\_id) | ID of the VPC where the Endpoint Gateways will be created | `string` | `null` | no | | [vpc\_name](#input\_vpc\_name) | A label that can be used as a short name for virtual private endpoints. If `vpe_name` is not specified in the `cloud_services` or `cloud_service_by_crn` input variable lists, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. | `string` | `"vpc"` | no | diff --git a/modules/reserved-ips/README.md b/modules/reserved-ips/README.md index 109301a6..280769bc 100644 --- a/modules/reserved-ips/README.md +++ b/modules/reserved-ips/README.md @@ -97,13 +97,13 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [cloud\_service\_by\_crn](#input\_cloud\_service\_by\_crn) | List of cloud service CRNs. Each CRN will have a unique endpoint gateways created. For a list of supported services, see the docs [here](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). |
list(
object({
name = string # service name
crn = string # service crn
})
)
| `[]` | no | -| [endpoint\_ip\_list](#input\_endpoint\_ip\_list) | List of IPs to create. Each object contains an ip name and subnet id |
list(
object({
ip_name = string # reserved ip name
subnet_id = string # subnet id
gateway_name = string # gateway name
name = string # ip name
})
)
| `[]` | no | +| [cloud\_service\_by\_crn](#input\_cloud\_service\_by\_crn) | List of cloud service CRNs. Each CRN will have a unique endpoint gateways created. For a list of supported services, see the docs [here](https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-supported-services). |
list(
object({
name = string # service name
crn = string # service crn
})
)
| `[]` | no | +| [endpoint\_ip\_list](#input\_endpoint\_ip\_list) | List of IPs to create. Each object contains an ip name and subnet id |
list(
object({
ip_name = string # reserved ip name
subnet_id = string # subnet id
gateway_name = string # gateway name
name = string # ip name
})
)
| `[]` | no | | [prefix](#input\_prefix) | The prefix that you would like to append to your resources. Value is only used if no value is passed for the `vpe_name` option in the `reserved_ip_cloud_services` input variable. | `string` | `"vpe"` | no | | [region](#input\_region) | The region to be used in the reserved ip naming convention. | `string` | `"us-south"` | no | -| [reserved\_ip\_cloud\_services](#input\_reserved\_ip\_cloud\_services) | List of cloud services to create reserved ips for. The keys are the service names, the values (all optional) give some level of control on the created VPEs. |
set(object({
service_name = string
vpe_name = optional(string),
}))
| `[]` | no | -| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used in the main module in which a user passes their existing reserved ips created here so as to not attempt to recreate them. |
object({
name = optional(string) # endpoint gateway IP ID
})
| `{}` | no | -| [subnet\_zone\_list](#input\_subnet\_zone\_list) | List of subnets in the VPC where reserved IPs will be provisioned. `name`, and `zone` are used in the naming convention of the reserved ip's which are then assigned to the subnet `id`. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation. |
list(
object({
name = string
id = string
zone = optional(string)
})
)
| `[]` | no | +| [reserved\_ip\_cloud\_services](#input\_reserved\_ip\_cloud\_services) | List of cloud services to create reserved ips for. The keys are the service names, the values (all optional) give some level of control on the created VPEs. |
set(object({
service_name = string
vpe_name = optional(string),
}))
| `[]` | no | +| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used in the main module in which a user passes their existing reserved ips created here so as to not attempt to recreate them. |
object({
name = optional(string) # endpoint gateway IP ID
})
| `{}` | no | +| [subnet\_zone\_list](#input\_subnet\_zone\_list) | List of subnets in the VPC where reserved IPs will be provisioned. `name`, and `zone` are used in the naming convention of the reserved ip's which are then assigned to the subnet `id`. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation. |
list(
object({
name = string
id = string
zone = optional(string)
})
)
| `[]` | no | | [vpc\_name](#input\_vpc\_name) | Name of the VPC that will be used in naming the newly created reserved ip(s). Value is only used if no value is passed for the `vpe_name` option in the `reserved_ip_cloud_services` input variable. | `string` | `"vpc"` | no | ### Outputs From 23249a44a331cd1088f07d49ede4e0ed6e54b3b4 Mon Sep 17 00:00:00 2001 From: Jordan-Williams2 Date: Tue, 22 Oct 2024 22:27:49 +0100 Subject: [PATCH 8/8] fix: address comments --- README.md | 2 +- modules/reserved-ips/README.md | 2 +- modules/reserved-ips/main.tf | 2 +- modules/reserved-ips/variables.tf | 43 +------------------------------ variables.tf | 2 +- 5 files changed, 5 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 73c441fc..9fc95f1d 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ You need the following permissions to run this module. | [cloud\_services](#input\_cloud\_services) | The list of cloud services used to create endpoint gateways. If `vpe_name` is not specified in the list, VPE names are created in the format `--`. The value that you specify for `vpc_name` must be known at Terraform plan time. |
set(object({
service_name = string
vpe_name = optional(string), # Full control on the VPE name. If not specified, the VPE name will be computed based on prefix, vpc name and service name.
allow_dns_resolution_binding = optional(bool, false)
}))
| `[]` | no | | [prefix](#input\_prefix) | The prefix that you would like to append to your resources. Value is only used if no value is passed for the `vpe_name` option in the `cloud_services` input variable. | `string` | `"vpe"` | no | | [region](#input\_region) | The region where VPC and services are deployed | `string` | `"us-south"` | no | -| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. If you wish to create your reserved ips independently and not create new ones you can first run the `reserved-ips` submodule and then copy the output `reserved_ip_map` here. |
object({
name = optional(string) # endpoint gateway IP ID
})
| `{}` | no | +| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. If you wish to create your reserved ips independently and not create new ones you can first run the `reserved-ips` submodule and then copy the output `reserved_ip_map` here. |
object({
name = optional(string) # reserved ip name
})
| `{}` | no | | [resource\_group\_id](#input\_resource\_group\_id) | ID of the resource group where endpoint gateways will be provisioned | `string` | `null` | no | | [security\_group\_ids](#input\_security\_group\_ids) | List of security group ids to attach to each endpoint gateway. | `list(string)` | `null` | no | | [service\_endpoints](#input\_service\_endpoints) | Service endpoints to use to create endpoint gateways. Can be `public`, or `private`. | `string` | `"private"` | no | diff --git a/modules/reserved-ips/README.md b/modules/reserved-ips/README.md index 280769bc..05ed064b 100644 --- a/modules/reserved-ips/README.md +++ b/modules/reserved-ips/README.md @@ -102,7 +102,7 @@ No modules. | [prefix](#input\_prefix) | The prefix that you would like to append to your resources. Value is only used if no value is passed for the `vpe_name` option in the `reserved_ip_cloud_services` input variable. | `string` | `"vpe"` | no | | [region](#input\_region) | The region to be used in the reserved ip naming convention. | `string` | `"us-south"` | no | | [reserved\_ip\_cloud\_services](#input\_reserved\_ip\_cloud\_services) | List of cloud services to create reserved ips for. The keys are the service names, the values (all optional) give some level of control on the created VPEs. |
set(object({
service_name = string
vpe_name = optional(string),
}))
| `[]` | no | -| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used in the main module in which a user passes their existing reserved ips created here so as to not attempt to recreate them. |
object({
name = optional(string) # endpoint gateway IP ID
})
| `{}` | no | +| [reserved\_ips](#input\_reserved\_ips) | Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used in the main module in which a user passes their existing reserved ips created here so as to not attempt to recreate them. |
object({
name = optional(string) # reserved ip name
})
| `{}` | no | | [subnet\_zone\_list](#input\_subnet\_zone\_list) | List of subnets in the VPC where reserved IPs will be provisioned. `name`, and `zone` are used in the naming convention of the reserved ip's which are then assigned to the subnet `id`. This value is intended to use the `subnet_zone_list` output from the Landing Zone VPC Subnet Module (https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone-vpc) or from templates using that module for subnet creation. |
list(
object({
name = string
id = string
zone = optional(string)
})
)
| `[]` | no | | [vpc\_name](#input\_vpc\_name) | Name of the VPC that will be used in naming the newly created reserved ip(s). Value is only used if no value is passed for the `vpe_name` option in the `reserved_ip_cloud_services` input variable. | `string` | `"vpc"` | no | diff --git a/modules/reserved-ips/main.tf b/modules/reserved-ips/main.tf index 0ff80282..6f8bfe03 100644 --- a/modules/reserved-ips/main.tf +++ b/modules/reserved-ips/main.tf @@ -35,7 +35,7 @@ locals { resource "ibm_is_subnet_reserved_ip" "ip" { for_each = { - # Create a map based on endpoint IP name + # Create a map based on reserved IP name for gateway_ip in local.endpoint_ip_list : (gateway_ip.ip_name) => gateway_ip if lookup(var.reserved_ips, gateway_ip.name, null) == null diff --git a/modules/reserved-ips/variables.tf b/modules/reserved-ips/variables.tf index 3119a4bc..fd45a25c 100644 --- a/modules/reserved-ips/variables.tf +++ b/modules/reserved-ips/variables.tf @@ -48,47 +48,6 @@ variable "reserved_ip_cloud_services" { vpe_name = optional(string), })) default = [] - validation { - error_message = "Currently the service you're trying to add is not supported. Any other VPE services must be added using `cloud_service_by_crn`." - condition = length(var.reserved_ip_cloud_services) == 0 ? true : length([ - for service in var.reserved_ip_cloud_services : - service.service_name if !contains([ - "account-management", - "billing", - "cloud-object-storage", - "cloud-object-storage-config", - "codeengine", - "container-registry", - "containers-kubernetes", - "context-based-restrictions", - "directlink", - "dns-svcs", - "enterprise", - "global-search-tagging", - "globalcatalog", - "hs-crypto", - "hs-crypto-cert-mgr", - "hs-crypto-ep11", - "hs-crypto-ep11-az1", - "hs-crypto-ep11-az2", - "hs-crypto-ep11-az3", - "hs-crypto-kmip", - "hs-crypto-tke", - "hyperp-dbaas-mongodb", - "hyperp-dbaas-postgresql", - "iam-svcs", - "is", - "kms", - "messaging", - "resource-controller", - "support-center", - "transit", - "user-management", - "vmware", - "ntp" - ], service.service_name) - ]) == 0 - } } variable "cloud_service_by_crn" { @@ -118,7 +77,7 @@ variable "endpoint_ip_list" { variable "reserved_ips" { description = "Map of existing reserved IP names and values. Leave this value as default if you want to create new reserved ips, this value is used in the main module in which a user passes their existing reserved ips created here so as to not attempt to recreate them." type = object({ - name = optional(string) # endpoint gateway IP ID + name = optional(string) # reserved ip name }) default = {} } diff --git a/variables.tf b/variables.tf index b2d561d8..d5c5c719 100644 --- a/variables.tf +++ b/variables.tf @@ -136,7 +136,7 @@ variable "service_endpoints" { variable "reserved_ips" { description = "Map of existing reserved IP names and values. If you wish to create your reserved ips independently and not create new ones you can first run the `reserved-ips` submodule and then copy the output `reserved_ip_map` here." type = object({ - name = optional(string) # endpoint gateway IP ID + name = optional(string) # reserved ip name }) default = {} }