Skip to content
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

feat: added prefix filter option #544

Merged
merged 20 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from 15 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
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This module includes the `terraform-ibm-transit-gateway-action` [approval action
* [terraform-ibm-transit-gateway-action](./modules/terraform-ibm-transit-gateway-action)
* [Examples](./examples)
* [ Example transit gateway that connects two VPCs in two accounts](./examples/crossaccounts)
* [ Example transit gateway that connects two VPCs with prefix filtering](./examples/add-prefix-filter)
* [ Example transit gateway that connects two VPCs](./examples/two-vpcs)
* [Example basic transit gateway](./examples/basic)
* [Contributing](#contributing)
Expand Down Expand Up @@ -65,7 +66,7 @@ You need the following permissions to run this module.
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >= 1.52.0, < 2.0.0 |
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >= 1.69.0, < 2.0.0 |

### Modules

Expand All @@ -77,14 +78,17 @@ No modules.
|------|------|
| [ibm_tg_connection.classic_connections](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/tg_connection) | resource |
| [ibm_tg_connection.vpc_connections](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/tg_connection) | resource |
| [ibm_tg_connection_prefix_filter.add_prefix_filter](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/tg_connection_prefix_filter) | resource |
| [ibm_tg_gateway.tg_gw_instance](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/tg_gateway) | resource |
| [ibm_tg_gateway.existing_tg_gw_instance](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/tg_gateway) | data source |

### Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_add_prefix_filters"></a> [add\_prefix\_filters](#input\_add\_prefix\_filters) | Map of VPC CRN to optionally add prefix filter to set an ordered list of filters that determine the routes that transit gateway should accept or deny. Connections are denied or permitted based on the order of the filters passed. See https://cloud.ibm.com/docs/transit-gateway?topic=transit-gateway-adding-prefix-filters&interface=ui | <pre>list(object({<br/> action = string<br/> prefix = string<br/> le = optional(number)<br/> ge = optional(number)<br/> before = optional(string)<br/> connection = string<br/> }))</pre> | `[]` | no |
| <a name="input_classic_connections_count"></a> [classic\_connections\_count](#input\_classic\_connections\_count) | Number of classic connections to add. | `number` | n/a | yes |
| <a name="input_default_prefix_filter"></a> [default\_prefix\_filter](#input\_default\_prefix\_filter) | Adjust the default filter. By default accepts all prefixes after entries in the prefix filter list are processed. Deny prefixes denies all prefixes after entries in the prefix filter list are processed. See https://cloud.ibm.com/docs/transit-gateway?topic=transit-gateway-adding-prefix-filters&interface=ui | `string` | `"permit"` | no |
| <a name="input_delete_timeout"></a> [delete\_timeout](#input\_delete\_timeout) | Deleting timeout value of the ibm\_tg\_gateway | `string` | `"45m"` | no |
| <a name="input_existing_transit_gateway_name"></a> [existing\_transit\_gateway\_name](#input\_existing\_transit\_gateway\_name) | Name of an existing transit gateway to connect VPCs. If null a new Transit Gateway will be created (transit\_gateway\_name and region required) | `string` | `null` | no |
| <a name="input_global_routing"></a> [global\_routing](#input\_global\_routing) | Gateways with global routing (true) to connect to the networks outside their associated region | `bool` | `false` | no |
Expand All @@ -99,6 +103,7 @@ No modules.
| Name | Description |
|------|-------------|
| <a name="output_classic_conn_ids"></a> [classic\_conn\_ids](#output\_classic\_conn\_ids) | List of classic connection IDs |
| <a name="output_filter_ids"></a> [filter\_ids](#output\_filter\_ids) | Prefix filter IDs |
| <a name="output_tg_crn"></a> [tg\_crn](#output\_tg\_crn) | CRN of the gateway |
| <a name="output_tg_id"></a> [tg\_id](#output\_tg\_id) | The ID of the transit gateway |
| <a name="output_vpc_conn_ids"></a> [vpc\_conn\_ids](#output\_vpc\_conn\_ids) | List of VPC connection IDs |
Expand Down
5 changes: 5 additions & 0 deletions examples/add-prefix-filter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Example transit gateway that connects two VPCs with prefix filtering

This example provisions two VPCs and a transit gateway that configures connectivity between them.

Add prefix filtering that determine the routes that transit gateway should accept or deny.
83 changes: 83 additions & 0 deletions examples/add-prefix-filter/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
##############################################################################
# Resource Group
##############################################################################

module "resource_group" {
source = "terraform-ibm-modules/resource-group/ibm"
version = "1.1.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
}

##############################################################################
# 2 VPCs
##############################################################################

module "vpc_1" {
source = "terraform-ibm-modules/landing-zone-vpc/ibm"
version = "7.19.0"
resource_group_id = module.resource_group.resource_group_id
region = var.region
prefix = var.prefix
tags = var.resource_tags
name = "${var.prefix}-vpc1"
use_public_gateways = {
zone-1 = false
zone-2 = false
zone-3 = false
}
}

module "vpc_2" {
source = "terraform-ibm-modules/landing-zone-vpc/ibm"
version = "7.19.0"
resource_group_id = module.resource_group.resource_group_id
region = var.region
prefix = var.prefix
tags = var.resource_tags
name = "${var.prefix}-vpc2"
use_public_gateways = {
zone-1 = false
zone-2 = false
zone-3 = false
}
}

##############################################################################
# Transit Gateway connects the 2 VPCs with prefix filters
##############################################################################

module "tg_gateway_connection" {
source = "../.."
transit_gateway_name = var.transit_gateway_name
region = var.region
global_routing = false
resource_tags = var.resource_tags
resource_group_id = module.resource_group.resource_group_id
vpc_connections = [module.vpc_1.vpc_crn, module.vpc_2.vpc_crn]
classic_connections_count = 0
add_prefix_filters = [
{
action = "permit"
prefix = "10.10.10.0/24"
le = 24
ge = 24
connection = module.vpc_1.vpc_crn
},
{
action = "deny"
prefix = "10.20.10.0/24"
le = 24
ge = 24
connection = module.vpc_1.vpc_crn
},
{
action = "deny"
prefix = "10.20.10.0/24"
le = 24
ge = 24
connection = module.vpc_2.vpc_crn
}
]
}
13 changes: 13 additions & 0 deletions examples/add-prefix-filter/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
##############################################################################
# Outputs
##############################################################################

output "tg_id" {
description = "The ID of the transit gateway"
value = module.tg_gateway_connection.tg_id
}

output "filter_ids" {
description = "Prefix filter IDs"
value = module.tg_gateway_connection.filter_ids
}
4 changes: 4 additions & 0 deletions examples/add-prefix-filter/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
provider "ibm" {
ibmcloud_api_key = var.ibmcloud_api_key
region = var.region
}
32 changes: 32 additions & 0 deletions examples/add-prefix-filter/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
variable "ibmcloud_api_key" {
description = "API key that is associated with the account to provision resources to"
type = string
sensitive = true
}

variable "prefix" {
description = "The prefix to append to your resources"
type = string
}

variable "transit_gateway_name" {
description = "Name of the transit gateway"
type = string
}

variable "region" {
description = "Location of the transit gateway."
type = string
}

variable "resource_group" {
type = string
description = "An existing resource group name to use for this example. If not set, a new resource group is created."
default = null
}

variable "resource_tags" {
type = list(string)
description = "List of tags"
default = null
}
11 changes: 11 additions & 0 deletions examples/add-prefix-filter/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
terraform {
required_version = ">= 1.0.0"
# Ensure that there is always 1 example locked into the lowest provider version of the range defined in the main
# module's version.tf (basic), and 1 example that will always use the latest provider version.
required_providers {
ibm = {
source = "IBM-Cloud/ibm"
version = ">= 1.69.0"
}
}
}
2 changes: 1 addition & 1 deletion examples/basic/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ terraform {
required_providers {
ibm = {
source = "IBM-Cloud/ibm"
version = "1.52.0"
version = "1.69.0"
}
}
}
2 changes: 1 addition & 1 deletion examples/crossaccounts/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ terraform {
required_providers {
ibm = {
source = "IBM-Cloud/ibm"
version = ">= 1.52.0"
version = ">= 1.69.0"
}
}
}
2 changes: 1 addition & 1 deletion examples/two-vpcs/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ terraform {
required_providers {
ibm = {
source = "IBM-Cloud/ibm"
version = ">= 1.52.0"
version = ">= 1.69.0"
}
}
}
41 changes: 30 additions & 11 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,37 @@ resource "ibm_tg_gateway" "tg_gw_instance" {
}

resource "ibm_tg_connection" "vpc_connections" {
count = length(var.vpc_connections)

gateway = local.transit_gateway_id
network_type = "vpc"
name = "vpc_conn_inst${count.index}"
network_id = var.vpc_connections[count.index]
count = length(var.vpc_connections)
gateway = local.transit_gateway_id
network_type = "vpc"
name = "vpc_conn_inst${count.index + 1}"
network_id = var.vpc_connections[count.index]
default_prefix_filter = var.default_prefix_filter
}
locals {
filter_list = flatten([
for conn in ibm_tg_connection.vpc_connections :
[
for filter in var.add_prefix_filters :
merge(filter, { connection_id = conn.connection_id
gateway = conn.gateway }) if filter.connection == conn.network_id
]
])
}

resource "ibm_tg_connection" "classic_connections" {
count = var.classic_connections_count
count = var.classic_connections_count
gateway = local.transit_gateway_id
network_type = "classic"
name = "classic_conn_inst${count.index}"
default_prefix_filter = var.default_prefix_filter
}

gateway = local.transit_gateway_id
network_type = "classic"
name = "classic_conn_inst${count.index}"
resource "ibm_tg_connection_prefix_filter" "add_prefix_filter" {
count = length(var.add_prefix_filters) > 0 ? length(var.add_prefix_filters) : 0
gateway = local.filter_list[count.index].gateway
connection_id = local.filter_list[count.index].connection_id
action = local.filter_list[count.index].action
prefix = local.filter_list[count.index].prefix
le = local.filter_list[count.index].le
ge = local.filter_list[count.index].ge
}
2 changes: 1 addition & 1 deletion modules/terraform-ibm-transit-gateway-action/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ module "tg_gateway_connection_crossaccounts_approve" {
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >= 1.52.0, < 2.0.0 |
| <a name="requirement_ibm"></a> [ibm](#requirement\_ibm) | >= 1.69.0, < 2.0.0 |

### Modules

Expand Down
2 changes: 1 addition & 1 deletion modules/terraform-ibm-transit-gateway-action/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ terraform {
# Use "greater than or equal to" range in modules
ibm = {
source = "IBM-Cloud/ibm"
version = ">= 1.52.0, < 2.0.0"
version = ">= 1.69.0, < 2.0.0"
}
}
}
5 changes: 5 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ output "classic_conn_ids" {
description = "List of classic connection IDs"
value = { for k, v in ibm_tg_connection.classic_connections : v.network_id => v.connection_id }
}

output "filter_ids" {
description = "Prefix filter IDs"
value = ibm_tg_connection_prefix_filter.add_prefix_filter[*].filter_id
}
38 changes: 38 additions & 0 deletions tests/pr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,34 @@ func setupOptions2VpcsExample(t *testing.T, prefix string) *testhelper.TestOptio
return options
}

func setupOptions2VpcsPrefixFilterExample(t *testing.T, prefix string) *testhelper.TestOptions {
const PrefixExampleTerraformDir = "examples/add-prefix-filter"

options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{
Testing: t,
Prefix: prefix,
ResourceGroup: resourceGroup,
CloudInfoService: sharedInfoSvc, // use pointer to shared info svc to keep track of region selections
DefaultRegion: "us-south",
TerraformDir: PrefixExampleTerraformDir,
IgnoreUpdates: testhelper.Exemptions{ // Ignore for consistency check
List: []string{
// to skip update error due to updated in-place for ibm_tg_connection_prefix_filter, tracking provider issue https://github.com/IBM-Cloud/terraform-provider-ibm/issues/5885
"module.tg_gateway_connection.ibm_tg_connection_prefix_filter.add_prefix_filter[0]",
"module.tg_gateway_connection.ibm_tg_connection_prefix_filter.add_prefix_filter[1]",
},
},
})

terraformVars := map[string]interface{}{
"transit_gateway_name": fmt.Sprintf("%s-%s", options.Prefix, "tg"),
}

maps.Copy(options.TerraformVars, terraformVars)

return options
}

// func setupOptionsCrossaccountsExample(t *testing.T, prefix string) *testhelper.TestOptions {
// const TwoVpcsExampleTerraformDir = "examples/crossaccounts"

Expand Down Expand Up @@ -143,6 +171,16 @@ func TestRun2VpcsExample(t *testing.T) {
assert.NotNil(t, output, "Expected some output")
}

func TestRun2VpcsPrefixFilterExample(t *testing.T) {
t.Parallel()

options := setupOptions2VpcsPrefixFilterExample(t, "prefix-tg")

output, err := options.RunTestConsistency()
assert.Nil(t, err, "This should not have errored")
assert.NotNil(t, output, "Expected some output")
}

// The account that this test was using has been removed so disabling the test until we decide what account can be used

// func TestRunCrossaccountsExample(t *testing.T) {
Expand Down
37 changes: 37 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,40 @@ variable "delete_timeout" {
description = "Deleting timeout value of the ibm_tg_gateway"
default = "45m"
}

variable "default_prefix_filter" {
type = string
description = "Adjust the default filter. By default accepts all prefixes after entries in the prefix filter list are processed. Deny prefixes denies all prefixes after entries in the prefix filter list are processed. See https://cloud.ibm.com/docs/transit-gateway?topic=transit-gateway-adding-prefix-filters&interface=ui"
validation {
condition = contains(["permit", "deny"], var.default_prefix_filter)
error_message = "Valid values to set default prefix filter is `permit` or `deny`"
}
default = "permit"
}

variable "add_prefix_filters" {
description = "Map of VPC CRN to optionally add prefix filter to set an ordered list of filters that determine the routes that transit gateway should accept or deny. Connections are denied or permitted based on the order of the filters passed. See https://cloud.ibm.com/docs/transit-gateway?topic=transit-gateway-adding-prefix-filters&interface=ui"
type = list(object({
action = string
prefix = string
le = optional(number)
ge = optional(number)
before = optional(string)
connection = string
}))
validation {
condition = alltrue([
for filter in var.add_prefix_filters :
filter.le >= 0 && filter.le <= 32 && filter.ge >= 0 && filter.ge <= 32
])
error_message = "Both 'le' and 'ge' must be between 0 and 32."
}
validation {
condition = alltrue([
for filter in var.add_prefix_filters :
filter.action == "permit" || filter.action == "deny"
])
error_message = "Valid values for 'action' are 'permit' or 'deny'."
}
default = []
}
Loading