diff --git a/README.md b/README.md index b0fb85a..8b784ec 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ This module takes one or more input sets of CIDRs and, for each set independentl The module accepts a map of lists of objects so that multiple CIDR sets can be merged (independently of one another) with a single instance of the module, which prevents a `for_each` or `count` on the module with a value that may not be known at plan time. Each list in the map contains objects that have fields for a CIDR and metadata. The output of the module includes, for each merged CIDR, the set of CIDR/metadata objects that it contains. This allows metadata such as a description (e.g. "route to database subnet") to be merged by the user to create merged metadata (e.g. a description for a merged CIDR that includes the descriptions for all of the CIDRs contained within). +The module produces two outputs: one is just the merged CIDRs in a list (mapped by the same group keys as the input), while the other contains additional metadata that may be useful. + The module works by: 1. Converting all CIDRs to use their first IP address as the prefix (e.g. `["10.0.1.0/16"]` becomes `["10.0.0.0/16"]`). 1. Removing any duplicate CIDRs. @@ -141,6 +143,18 @@ Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Outputs: merged_cidrs = { + "set-0" = [ + "1.0.0.0/14", + "1.4.0.0/15", + "1.6.0.0/17", + "192.168.0.0/21", + "192.168.8.0/24", + ] + "set-1" = [ + "0.0.0.0/0", + ] +} +merged_cidrs_with_meta = { "set-0" = [ { "cidr" = "1.0.0.0/14" @@ -164,6 +178,10 @@ merged_cidrs = { } }, ] + "first_ip" = "1.0.0.0" + "first_ip_decimal" = 16777216 + "last_ip" = "1.3.255.255" + "last_ip_decimal" = 17039359 }, { "cidr" = "1.4.0.0/15" @@ -181,6 +199,10 @@ merged_cidrs = { } }, ] + "first_ip" = "1.4.0.0" + "first_ip_decimal" = 17039360 + "last_ip" = "1.5.255.255" + "last_ip_decimal" = 17170431 }, { "cidr" = "1.6.0.0/17" @@ -198,6 +220,10 @@ merged_cidrs = { } }, ] + "first_ip" = "1.6.0.0" + "first_ip_decimal" = 17170432 + "last_ip" = "1.6.127.255" + "last_ip_decimal" = 17203199 }, { "cidr" = "192.168.0.0/21" @@ -245,6 +271,10 @@ merged_cidrs = { } }, ] + "first_ip" = "192.168.0.0" + "first_ip_decimal" = 3232235520 + "last_ip" = "192.168.7.255" + "last_ip_decimal" = 3232237567 }, { "cidr" = "192.168.8.0/24" @@ -256,6 +286,10 @@ merged_cidrs = { } }, ] + "first_ip" = "192.168.8.0" + "first_ip_decimal" = 3232237568 + "last_ip" = "192.168.8.255" + "last_ip_decimal" = 3232237823 }, ] "set-1" = [ @@ -275,6 +309,10 @@ merged_cidrs = { } }, ] + "first_ip" = "0.0.0.0" + "first_ip_decimal" = 0 + "last_ip" = "255.255.255.255" + "last_ip_decimal" = 4294967295 }, ] } diff --git a/ipv4.tf b/ipv4.tf index 83d70e1..21b3fb5 100644 --- a/ipv4.tf +++ b/ipv4.tf @@ -156,6 +156,7 @@ locals { { first_ip = cidr_data.first_ip first_ip_decimal = cidr_data.first_ip_decimal + last_ip = contiguous_set[i].last_ip last_ip_decimal = contiguous_set[i].last_ip_decimal // Calculate the prefix length as 32 minus (the number of IPs in the CIDR, log base 2) @@ -169,7 +170,6 @@ locals { // Debugging values # cidr_set = slice(contiguous_set, cidr_idx, i + 1) - # last_ip = contiguous_set[i].last_ip # ip_count = contiguous_set[i].last_ip_decimal - cidr_data.first_ip_decimal + 1 } ] @@ -261,14 +261,18 @@ locals { } // Create the final list of CIDRs, which is all of the merges from all of the contiguous sets. - final_cidrs_ipv4 = { + final_cidrs_ipv4_with_meta = { for key, group in local.merged_cidrs : key => flatten([ for contiguous_set in group : [ for merging in contiguous_set : { - cidr = "${merging.first_ip}/${merging.prefix_length}" + cidr = "${merging.first_ip}/${merging.prefix_length}" + first_ip = merging.first_ip + last_ip = merging.last_ip + first_ip_decimal = merging.first_ip_decimal + last_ip_decimal = merging.last_ip_decimal contains = [ for cidr_meta in local.cidrs_with_first_last_decimal[key] : { @@ -281,4 +285,12 @@ locals { ] ]) } + + final_cidrs_ipv4 = { + for key, group in local.final_cidrs_ipv4_with_meta : + key => [ + for cidr_data in group : + cidr_data.cidr + ] + } } diff --git a/outputs.tf b/outputs.tf index 892deff..faafb8b 100644 --- a/outputs.tf +++ b/outputs.tf @@ -13,6 +13,10 @@ output "merged_cidr_sets_ipv4" { description = "The merged CIDR sets." value = local.final_cidrs_ipv4 } +output "merged_cidr_sets_ipv4_with_meta" { + description = "The merged CIDR sets, with additional metadata including the CIDRs that were merged into this one and additional IP data." + value = local.final_cidrs_ipv4_with_meta +} //================================================== // Debugging outputs diff --git a/tests/debug.tf b/tests/debug.tf index 713a631..cad2a6c 100644 --- a/tests/debug.tf +++ b/tests/debug.tf @@ -116,3 +116,7 @@ module "cidr_merge" { output "merged_cidrs" { value = module.cidr_merge.merged_cidr_sets_ipv4 } + +output "merged_cidrs_with_meta" { + value = module.cidr_merge.merged_cidr_sets_ipv4_with_meta +} diff --git a/tests/ipv4.tftest.hcl b/tests/ipv4.tftest.hcl index aa67671..64af1ef 100644 --- a/tests/ipv4.tftest.hcl +++ b/tests/ipv4.tftest.hcl @@ -127,232 +127,44 @@ run "cidr_merge_test" { assert { condition = output.merged_cidr_sets_ipv4.set-0 == [ - { - cidr = "192.168.1.0/24", - contains = [ - { - cidr = "192.168.1.0/24", - metadata = null - } - ] - }, - { - cidr = "192.168.2.0/23", - contains = [ - { - cidr = "192.168.2.0/24", - metadata = null - }, - { - cidr = "192.168.3.0/24", - metadata = null - } - ] - }, - { - cidr = "192.168.4.0/22", - contains = [ - { - cidr = "192.168.4.0/23", - metadata = null - }, - { - cidr = "192.168.6.0/24", - metadata = null - }, - { - cidr = "192.168.7.0/24", - metadata = null - } - ] - }, - { - cidr = "192.168.8.0/24", - contains = [ - { - cidr = "192.168.8.0/24", - metadata = null - } - ] - } + "192.168.1.0/24", + "192.168.2.0/23", + "192.168.4.0/22", + "192.168.8.0/24", ] error_message = "Incorrect respose in set 0: ${jsonencode(output.merged_cidr_sets_ipv4.set-0)}" } assert { condition = output.merged_cidr_sets_ipv4.set-1 == [ - { - cidr = "192.168.0.0/23", - contains = [ - { - cidr = "192.168.0.0/24", - metadata = null - }, - { - cidr = "192.168.1.0/24", - metadata = null - } - ] - }, - { - cidr = "192.168.2.0/24", - contains = [ - { - cidr = "192.168.2.0/24", - metadata = null - } - ] - }, - { - cidr = "192.168.4.0/22", - contains = [ - { - cidr = "192.168.4.0/23", - metadata = null - }, - { - cidr = "192.168.6.0/23", - metadata = null - }, - { - cidr = "192.168.7.0/24", - metadata = null - } - ] - }, - { - cidr = "192.168.15.0/24", - contains = [ - { - cidr = "192.168.15.0/24", - metadata = null - } - ] - }, - { - cidr = "192.168.16.0/21", - contains = [ - { - cidr = "192.168.16.0/24", - metadata = null - }, - { - cidr = "192.168.17.0/24", - metadata = null - }, - { - cidr = "192.168.18.0/23", - metadata = null - }, - { - cidr = "192.168.20.0/23", - metadata = null - }, - { - cidr = "192.168.22.0/24", - metadata = null - }, - { - cidr = "192.168.23.0/24", - metadata = null - } - ] - }, - { - cidr = "192.168.24.0/24", - contains = [ - { - cidr = "192.168.24.0/24", - metadata = null - } - ] - } + "192.168.0.0/23", + "192.168.2.0/24", + "192.168.4.0/22", + "192.168.15.0/24", + "192.168.16.0/21", + "192.168.24.0/24", ] error_message = "Incorrect respose in set 1: ${jsonencode(output.merged_cidr_sets_ipv4.set-1)}" } assert { condition = output.merged_cidr_sets_ipv4.set-2 == [ - { - cidr = "0.0.0.0/0", - contains = [ - { - cidr = "1.1.1.1/23", - metadata = null - }, - { - cidr = "198.222.32.0/5", - metadata = null - }, - { - cidr = "0.0.0.0/0", - metadata = null - } - ] - } + "0.0.0.0/0", ] error_message = "Incorrect respose in set 2: ${jsonencode(output.merged_cidr_sets_ipv4.set-2)}" } assert { condition = output.merged_cidr_sets_ipv4.set-3 == [ - { - cidr = "10.0.0.0/13", - contains = [ - { - cidr = "10.6.0.0/15", - metadata = null - }, - { - cidr = "10.0.0.0/15", - metadata = null - }, - { - cidr = "10.4.0.0/15", - metadata = null - }, - { - cidr = "10.2.0.0/16", - metadata = null - }, - { - cidr = "10.3.0.0/16", - metadata = null - } - ] - }, - { - cidr = "10.8.0.0/20", - contains = [ - { - cidr = "10.8.0.0/20", - metadata = null - }, - { - cidr = "10.8.0.0/24", - metadata = null - } - ] - } + "10.0.0.0/13", + "10.8.0.0/20", ] error_message = "Incorrect respose in set 3: ${jsonencode(output.merged_cidr_sets_ipv4.set-3)}" } assert { condition = output.merged_cidr_sets_ipv4.set-4 == [ - { - cidr = "0.0.0.0/0", - contains = [ - { - cidr = "0.0.0.0/1", - metadata = null - }, - { - cidr = "128.0.0.0/1", - metadata = null - } - ] - } + "0.0.0.0/0" ] error_message = "Incorrect respose in set 4: ${jsonencode(output.merged_cidr_sets_ipv4.set-4)}" }