diff --git a/docs/resources/dhcp_fixed_address.md b/docs/resources/dhcp_fixed_address.md index 06102c9a..2a926fc7 100644 --- a/docs/resources/dhcp_fixed_address.md +++ b/docs/resources/dhcp_fixed_address.md @@ -45,6 +45,13 @@ resource "bloxone_ipam_subnet" "example" { } } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + + resource "bloxone_dhcp_fixed_address" "example_fixed_address" { name = "example_fixed_address" address = "192.168.1.1" @@ -55,6 +62,14 @@ resource "bloxone_dhcp_fixed_address" "example_fixed_address" { tags = { location = "site1" } + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] depends_on = [bloxone_ipam_subnet.example] } diff --git a/docs/resources/dhcp_server.md b/docs/resources/dhcp_server.md index de0fa844..cee65d32 100644 --- a/docs/resources/dhcp_server.md +++ b/docs/resources/dhcp_server.md @@ -20,6 +20,12 @@ resource "bloxone_dhcp_server" "example" { name = "example_dhcp_server" } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + resource "bloxone_dhcp_server" "example_with_options" { name = "example_dhcp_server_with_options" @@ -28,6 +34,15 @@ resource "bloxone_dhcp_server" "example_with_options" { tags = { site = "Site A" } + + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } ``` diff --git a/docs/resources/ipam_address_block.md b/docs/resources/ipam_address_block.md index 9b57db11..8a977021 100644 --- a/docs/resources/ipam_address_block.md +++ b/docs/resources/ipam_address_block.md @@ -23,11 +23,26 @@ resource "bloxone_ipam_ip_space" "example" { } } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + resource "bloxone_ipam_address_block" "example" { address = "192.168.1.0" cidr = 24 name = "example_address_block" space = bloxone_ipam_ip_space.example.id + + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } resource "bloxone_ipam_address_block" "example_tags" { diff --git a/docs/resources/ipam_ip_space.md b/docs/resources/ipam_ip_space.md index 271a8f26..c1651d7c 100644 --- a/docs/resources/ipam_ip_space.md +++ b/docs/resources/ipam_ip_space.md @@ -20,12 +20,27 @@ resource "bloxone_ipam_ip_space" "example" { name = "example_ip_space" } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + resource "bloxone_ipam_ip_space" "example_tags" { name = "example_ip_space_tags" comment = "Example IP space with tags created by the terraform provider" tags = { location = "site1" } + + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } ``` diff --git a/docs/resources/ipam_range.md b/docs/resources/ipam_range.md index adaac7e9..38849cb6 100644 --- a/docs/resources/ipam_range.md +++ b/docs/resources/ipam_range.md @@ -24,6 +24,12 @@ resource "bloxone_ipam_ip_space" "example" { } } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + resource "bloxone_ipam_subnet" "example" { name = "example" space = bloxone_ipam_ip_space.example.id @@ -33,6 +39,15 @@ resource "bloxone_ipam_subnet" "example" { tags = { location = "site1" } + + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } resource "bloxone_ipam_range" "example" { diff --git a/docs/resources/ipam_subnet.md b/docs/resources/ipam_subnet.md index aa8038a9..cd739588 100644 --- a/docs/resources/ipam_subnet.md +++ b/docs/resources/ipam_subnet.md @@ -26,6 +26,12 @@ resource "bloxone_ipam_address_block" "example" { space = bloxone_ipam_ip_space.example.id } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + # Static address resource "bloxone_ipam_subnet" "example" { address = "10.0.0.0" @@ -38,6 +44,14 @@ resource "bloxone_ipam_subnet" "example" { tags = { site = "Site A" } + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } # Next available subnet diff --git a/examples/resources/bloxone_dhcp_fixed_address/resource.tf b/examples/resources/bloxone_dhcp_fixed_address/resource.tf index 9791c7c5..7af91d27 100644 --- a/examples/resources/bloxone_dhcp_fixed_address/resource.tf +++ b/examples/resources/bloxone_dhcp_fixed_address/resource.tf @@ -27,6 +27,13 @@ resource "bloxone_ipam_subnet" "example" { } } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + + resource "bloxone_dhcp_fixed_address" "example_fixed_address" { name = "example_fixed_address" address = "192.168.1.1" @@ -37,6 +44,14 @@ resource "bloxone_dhcp_fixed_address" "example_fixed_address" { tags = { location = "site1" } + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] depends_on = [bloxone_ipam_subnet.example] } diff --git a/examples/resources/bloxone_dhcp_server/resource.tf b/examples/resources/bloxone_dhcp_server/resource.tf index fdfd7cf0..cb093087 100644 --- a/examples/resources/bloxone_dhcp_server/resource.tf +++ b/examples/resources/bloxone_dhcp_server/resource.tf @@ -2,6 +2,12 @@ resource "bloxone_dhcp_server" "example" { name = "example_dhcp_server" } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + resource "bloxone_dhcp_server" "example_with_options" { name = "example_dhcp_server_with_options" @@ -10,4 +16,13 @@ resource "bloxone_dhcp_server" "example_with_options" { tags = { site = "Site A" } + + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } diff --git a/examples/resources/bloxone_ipam_address_block/resource.tf b/examples/resources/bloxone_ipam_address_block/resource.tf index ac5557e0..cd530bd7 100644 --- a/examples/resources/bloxone_ipam_address_block/resource.tf +++ b/examples/resources/bloxone_ipam_address_block/resource.tf @@ -5,11 +5,26 @@ resource "bloxone_ipam_ip_space" "example" { } } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + resource "bloxone_ipam_address_block" "example" { address = "192.168.1.0" cidr = 24 name = "example_address_block" space = bloxone_ipam_ip_space.example.id + + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } resource "bloxone_ipam_address_block" "example_tags" { diff --git a/examples/resources/bloxone_ipam_ip_space/resource.tf b/examples/resources/bloxone_ipam_ip_space/resource.tf index ff82961a..209cf5bb 100644 --- a/examples/resources/bloxone_ipam_ip_space/resource.tf +++ b/examples/resources/bloxone_ipam_ip_space/resource.tf @@ -2,10 +2,25 @@ resource "bloxone_ipam_ip_space" "example" { name = "example_ip_space" } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + resource "bloxone_ipam_ip_space" "example_tags" { name = "example_ip_space_tags" comment = "Example IP space with tags created by the terraform provider" tags = { location = "site1" } + + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } diff --git a/examples/resources/bloxone_ipam_range/resource.tf b/examples/resources/bloxone_ipam_range/resource.tf index ce49d2a1..225593ba 100644 --- a/examples/resources/bloxone_ipam_range/resource.tf +++ b/examples/resources/bloxone_ipam_range/resource.tf @@ -6,6 +6,12 @@ resource "bloxone_ipam_ip_space" "example" { } } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + resource "bloxone_ipam_subnet" "example" { name = "example" space = bloxone_ipam_ip_space.example.id @@ -15,6 +21,15 @@ resource "bloxone_ipam_subnet" "example" { tags = { location = "site1" } + + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } resource "bloxone_ipam_range" "example" { diff --git a/examples/resources/bloxone_ipam_subnet/resource.tf b/examples/resources/bloxone_ipam_subnet/resource.tf index ced2c5fa..4d9351f6 100644 --- a/examples/resources/bloxone_ipam_subnet/resource.tf +++ b/examples/resources/bloxone_ipam_subnet/resource.tf @@ -8,6 +8,12 @@ resource "bloxone_ipam_address_block" "example" { space = bloxone_ipam_ip_space.example.id } +data "bloxone_dhcp_option_codes" "option_code" { + filters = { + name = "domain-name-servers" + } +} + # Static address resource "bloxone_ipam_subnet" "example" { address = "10.0.0.0" @@ -20,6 +26,14 @@ resource "bloxone_ipam_subnet" "example" { tags = { site = "Site A" } + //dhcp options + dhcp_options = [ + { + option_code = data.bloxone_dhcp_option_codes.option_code.results.0.id + option_value = "10.0.0.1" + type = "option" + } + ] } # Next available subnet diff --git a/internal/service/ipam/api_address_block_resource_test.go b/internal/service/ipam/api_address_block_resource_test.go index e91b3b97..667d1dd4 100644 --- a/internal/service/ipam/api_address_block_resource_test.go +++ b/internal/service/ipam/api_address_block_resource_test.go @@ -485,6 +485,37 @@ func TestAccAddressBlockResource_DhcpConfig(t *testing.T) { }) } +func TestAccAddressBlockResource_DhcpOptions(t *testing.T) { + var resourceName = "bloxone_ipam_address_block.test_dhcp_options" + var v1 ipam.IpamsvcAddressBlock + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create and Read + { + Config: testAccAddressBlockDhcpOptionOption("192.168.0.0", "16", "option", "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAddressBlockExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.0.option_value", "true"), + resource.TestCheckResourceAttrPair(resourceName, "dhcp_options.0.option_code", "bloxone_dhcp_option_code.test", "id"), + ), + }, + // Update and Read + { + Config: testAccAddressBlockDhcpOptionsGroup("192.168.0.0", "16", "group"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAddressBlockExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + func TestAccAddressBlockResource_HeaderOptionFilename(t *testing.T) { var resourceName = "bloxone_ipam_address_block.test_header_option_filename" var v ipam.IpamsvcAddressBlock @@ -987,6 +1018,41 @@ resource "bloxone_ipam_address_block" "test_ddns_domain" { return strings.Join([]string{testAccBaseWithIPSpace(), config}, "") } +func testAccAddressBlockDhcpOptionOption(name string, cidr string, type_, optValue string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_address_block" "test_dhcp_options" { + address = %q + cidr = %q + space = bloxone_ipam_ip_space.test.id + dhcp_options = [ + { + type = %q + option_code = bloxone_dhcp_option_code.test.id + option_value = %q + } + ] +} +`, name, cidr, type_, optValue) + return strings.Join([]string{testAccBaseWithIPSpace(), testAccBaseWithOptionSpaceAndCode(), config}, "") +} + +func testAccAddressBlockDhcpOptionsGroup(name string, cidr string, type_ string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_address_block" "test_dhcp_options" { + address = %q + cidr = %q + space = bloxone_ipam_ip_space.test.id + dhcp_options = [ + { + type = %q + group = bloxone_dhcp_option_group.test.id + } + ] +} +`, name, cidr, type_) + return strings.Join([]string{testAccBaseWithIPSpace(), testAccBaseWithOptionSpaceAndCode(), config}, "") +} + func testAccAddressBlockDdnsGenerateName(address string, cidr string, ddnsGenerateName string) string { config := fmt.Sprintf(` resource "bloxone_ipam_address_block" "test_ddns_generate_name" { diff --git a/internal/service/ipam/api_fixed_address_resource_test.go b/internal/service/ipam/api_fixed_address_resource_test.go index 3ef3e940..28e8a340 100644 --- a/internal/service/ipam/api_fixed_address_resource_test.go +++ b/internal/service/ipam/api_fixed_address_resource_test.go @@ -165,6 +165,37 @@ func TestAccFixedAddressResource_DisableDhcp(t *testing.T) { }) } +func TestAccFixedAddressResource_DhcpOptions(t *testing.T) { + var resourceName = "bloxone_dhcp_fixed_address.test_dhcp_options" + var v1 ipam.IpamsvcFixedAddress + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create and Read + { + Config: testAccFixedAddressDhcpOptionsOption("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "Fixed_address_dhcp_option", "option", "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckFixedAddressExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.0.option_value", "true"), + resource.TestCheckResourceAttrPair(resourceName, "dhcp_options.0.option_code", "bloxone_dhcp_option_code.test", "id"), + ), + }, + // Update and Read + { + Config: testAccFixedAddressDhcpOptionsGroup("10.0.0.10", "mac", "aa:aa:aa:aa:aa:aa", "Fixed_address_dhcp_option", "group"), + Check: resource.ComposeTestCheckFunc( + testAccCheckFixedAddressExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + func TestAccFixedAddressResource_HeaderOptionFilename(t *testing.T) { var resourceName = "bloxone_dhcp_fixed_address.test_header_option_filename" var v ipam.IpamsvcFixedAddress @@ -631,6 +662,47 @@ resource "bloxone_dhcp_fixed_address" "test_disable_dhcp" { return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "") } +func testAccFixedAddressDhcpOptionsOption(address string, matchType string, matchValue string, name, type_, optValue string) string { + config := fmt.Sprintf(` +resource "bloxone_dhcp_fixed_address" "test_dhcp_options" { + ip_space = bloxone_ipam_ip_space.test.id + address = %q + match_type = %q + match_value = %q + name = %q + depends_on = [bloxone_ipam_subnet.test] + dhcp_options = [ + { + type = %q + option_code = bloxone_dhcp_option_code.test.id + option_value = %q + } + ] +} +`, address, matchType, matchValue, name, type_, optValue) + return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), testAccBaseWithOptionSpaceAndCode(), config}, "") +} + +func testAccFixedAddressDhcpOptionsGroup(address string, matchType string, matchValue string, name, type_ string) string { + config := fmt.Sprintf(` +resource "bloxone_dhcp_fixed_address" "test_dhcp_options" { + ip_space = bloxone_ipam_ip_space.test.id + address = %q + match_type = %q + match_value = %q + name = %q + depends_on = [bloxone_ipam_subnet.test] + dhcp_options = [ + { + type = %q + group = bloxone_dhcp_option_group.test.id + } + ] +} +`, address, matchType, matchValue, name, type_) + return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), testAccBaseWithOptionSpaceAndCode(), config}, "") +} + func testAccFixedAddressHeaderOptionFilename(address string, matchType string, matchValue string, headerOptionFilename string) string { config := fmt.Sprintf(` resource "bloxone_dhcp_fixed_address" "test_header_option_filename" { diff --git a/internal/service/ipam/api_ip_space_resource_test.go b/internal/service/ipam/api_ip_space_resource_test.go index 87f48580..6625a47c 100644 --- a/internal/service/ipam/api_ip_space_resource_test.go +++ b/internal/service/ipam/api_ip_space_resource_test.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "strings" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -312,6 +313,68 @@ func TestAccIpSpaceResource_DdnsGeneratedPrefix(t *testing.T) { }) } +func TestAccIpSpaceResource_DhcpOptions(t *testing.T) { + var resourceName = "bloxone_ipam_ip_space.test_dhcp_options" + var v1 ipam.IpamsvcIPSpace + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create and Read + { + Config: testAccIpSpaceDhcpOptionsOption("ipspace_dhcp_options_test", "option", "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckIpSpaceExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.0.option_value", "true"), + resource.TestCheckResourceAttrPair(resourceName, "dhcp_options.0.option_code", "bloxone_dhcp_option_code.test", "id"), + ), + }, + // Update and Read + { + Config: testAccIpSpaceDhcpOptionsGroup("ipspace_dhcp_options_test", "group"), + Check: resource.ComposeTestCheckFunc( + testAccCheckIpSpaceExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + +func TestAccIpSpaceResource_DhcpOptionsV6(t *testing.T) { + var resourceName = "bloxone_ipam_ip_space.test_dhcp_options_v6" + var v1 ipam.IpamsvcIPSpace + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create and Read + { + Config: testAccIpSpaceDhcpOptionsOptionV6("ipspace_dhcp_options_test", "option", "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckIpSpaceExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options_v6.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dhcp_options_v6.0.option_value", "true"), + resource.TestCheckResourceAttrPair(resourceName, "dhcp_options_v6.0.option_code", "bloxone_dhcp_option_code.test", "id"), + ), + }, + // Update and Read + { + Config: testAccIpSpaceDhcpOptionsGroupV6("ipspace_dhcp_options_test", "group"), + Check: resource.ComposeTestCheckFunc( + testAccCheckIpSpaceExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options_v6.#", "1"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + func TestAccIpSpaceResource_DdnsSendUpdates(t *testing.T) { var resourceName = "bloxone_ipam_ip_space.test_ddns_send_updates" var v ipam.IpamsvcIPSpace @@ -909,6 +972,70 @@ resource "bloxone_ipam_ip_space" "test_dhcp_config" { `, name, abandonedReclaimTime, abandonedReclaimTimeV6, allowUnknown, allowUnknownV6, ignoreClientUid, leaseTime, leaseTimeV6) } +func testAccIpSpaceDhcpOptionsOption(name string, type_, optValue string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_ip_space" "test_dhcp_options" { + name = %q + dhcp_options = [ + { + type = %q + option_code = bloxone_dhcp_option_code.test.id + option_value = %q + } + ] +} +`, name, type_, optValue) + return strings.Join([]string{testAccBaseWithOptionSpaceAndCode(), config}, "") + +} + +func testAccIpSpaceDhcpOptionsGroup(name string, type_ string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_ip_space" "test_dhcp_options" { + name = %q + dhcp_options = [ + { + type = %q + group = bloxone_dhcp_option_group.test.id + } + ] +} +`, name, type_) + return strings.Join([]string{testAccBaseWithOptionSpaceAndCode(), config}, "") + +} + +func testAccIpSpaceDhcpOptionsOptionV6(name string, type_, optValue string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_ip_space" "test_dhcp_options_v6" { + name = %q + dhcp_options_v6 = [ + { + type = %q + option_code = bloxone_dhcp_option_code.test.id + option_value = %q + } + ] +} +`, name, type_, optValue) + return strings.Join([]string{testAccBaseWithV6OptionSpaceAndCode(), config}, "") +} + +func testAccIpSpaceDhcpOptionsGroupV6(name string, type_ string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_ip_space" "test_dhcp_options_v6" { + name = %q + dhcp_options_v6 = [ + { + type = %q + group = bloxone_dhcp_option_group.test.id + } + ] +} +`, name, type_) + return strings.Join([]string{testAccBaseWithV6OptionSpaceAndCode(), config}, "") +} + func testAccIpSpaceHeaderOptionFilename(name, headerOptionFilename string) string { return fmt.Sprintf(` resource "bloxone_ipam_ip_space" "test_header_option_filename" { diff --git a/internal/service/ipam/api_range_resource_test.go b/internal/service/ipam/api_range_resource_test.go index f9f7fabd..d32a2055 100644 --- a/internal/service/ipam/api_range_resource_test.go +++ b/internal/service/ipam/api_range_resource_test.go @@ -132,6 +132,37 @@ func TestAccRangeResource_DisableDhcp(t *testing.T) { }) } +func TestAccRangeResource_DhcpOptions(t *testing.T) { + var resourceName = "bloxone_ipam_range.test_dhcp_options" + var v1 ipam.IpamsvcRange + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create and Read + { + Config: testAccRangeDhcpOptionsOption("10.0.0.10", "10.0.0.20", "option", "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckRangeExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.0.option_value", "true"), + resource.TestCheckResourceAttrPair(resourceName, "dhcp_options.0.option_code", "bloxone_dhcp_option_code.test", "id"), + ), + }, + // Update and Read + { + Config: testAccRangeDhcpOptionsGroup("10.0.0.10", "10.0.0.20", "group"), + Check: resource.ComposeTestCheckFunc( + testAccCheckRangeExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + func TestAccRangeResource_End(t *testing.T) { var resourceName = "bloxone_ipam_range.test_end" var v ipam.IpamsvcRange @@ -252,7 +283,7 @@ func TestAccRangeResource_Name(t *testing.T) { func TestAccRangeResource_Space(t *testing.T) { var resourceName = "bloxone_ipam_range.test_space" - var v1, v2 ipam.IpamsvcRange + var v1 ipam.IpamsvcRange resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, @@ -270,8 +301,7 @@ func TestAccRangeResource_Space(t *testing.T) { { Config: testAccRangeSpace("10.0.0.8", "10.0.0.20", "bloxone_ipam_ip_space.one"), Check: resource.ComposeTestCheckFunc( - testAccCheckRangeDestroy(context.Background(), &v1), - testAccCheckRangeExists(context.Background(), resourceName, &v2), + testAccCheckRangeExists(context.Background(), resourceName, &v1), resource.TestCheckResourceAttrPair(resourceName, "space", "bloxone_ipam_ip_space.one", "id"), ), }, @@ -435,6 +465,47 @@ resource "bloxone_ipam_range" "test_disable_dhcp" { return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), config}, "") } +func testAccRangeDhcpOptionsOption(start string, end string, type_, optValue string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_range" "test_dhcp_options" { + space = bloxone_ipam_ip_space.test.id + start = %q + end = %q + dhcp_options = [ + { + type = %q + option_code = bloxone_dhcp_option_code.test.id + option_value = %q + } + ] + depends_on = [bloxone_ipam_subnet.test] +} +`, start, end, type_, optValue) + + return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), testAccBaseWithOptionSpaceAndCode(), config}, "") + +} + +func testAccRangeDhcpOptionsGroup(start string, end string, type_ string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_range" "test_dhcp_options" { + space = bloxone_ipam_ip_space.test.id + start = %q + end = %q + dhcp_options = [ + { + type = %q + group = bloxone_dhcp_option_group.test.id + } + ] + depends_on = [bloxone_ipam_subnet.test] +} +`, start, end, type_) + + return strings.Join([]string{testAccBaseWithIPSpaceAndSubnet(), testAccBaseWithOptionSpaceAndCode(), config}, "") + +} + func testAccRangeEnd(start, end string) string { config := fmt.Sprintf(` resource "bloxone_ipam_range" "test_end" { diff --git a/internal/service/ipam/api_server_resource_test.go b/internal/service/ipam/api_server_resource_test.go index 36f55bff..cd997786 100644 --- a/internal/service/ipam/api_server_resource_test.go +++ b/internal/service/ipam/api_server_resource_test.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "strings" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -148,7 +149,6 @@ func TestAccServerResource_DdnsClientUpdate(t *testing.T) { }) } -// issue func TestAccServerResource_DdnsConflictResolutionMode(t *testing.T) { var resourceName = "bloxone_dhcp_server.test_ddns_conflict_resolution_mode" var v ipam.IpamsvcServer @@ -211,6 +211,68 @@ func TestAccServerResource_DdnsDomain(t *testing.T) { }) } +func TestAccServerResource_DhcpOptions(t *testing.T) { + var resourceName = "bloxone_dhcp_server.test_dhcp_options" + var v1 ipam.IpamsvcServer + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create and Read + { + Config: testAccServerDhcpOptionsOption("server_dhcp_options", "option", "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckServerExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.0.option_value", "true"), + resource.TestCheckResourceAttrPair(resourceName, "dhcp_options.0.option_code", "bloxone_dhcp_option_code.test", "id"), + ), + }, + // Update and Read + { + Config: testAccServerDhcpOptionsGroup("server_dhcp_options", "group"), + Check: resource.ComposeTestCheckFunc( + testAccCheckServerExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + +func TestAccServerResource_DhcpOptionsV6(t *testing.T) { + var resourceName = "bloxone_dhcp_server.test_dhcp_options" + var v1 ipam.IpamsvcServer + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create and Read + { + Config: testAccServerDhcpOptionsOptionV6("server_dhcp_options", "option", "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckServerExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options_v6.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dhcp_options_v6.0.option_value", "true"), + resource.TestCheckResourceAttrPair(resourceName, "dhcp_options_v6.0.option_code", "bloxone_dhcp_option_code.test", "id"), + ), + }, + // Update and Read + { + Config: testAccServerDhcpOptionsGroupV6("server_dhcp_options", "group"), + Check: resource.ComposeTestCheckFunc( + testAccCheckServerExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options_v6.#", "1"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + func TestAccServerResource_DdnsEnabled(t *testing.T) { var resourceName = "bloxone_dhcp_server.test_ddns_enabled" var v ipam.IpamsvcServer @@ -391,7 +453,6 @@ func TestAccServerResource_DdnsUpdateOnRenew(t *testing.T) { }) } -// issue func TestAccServerResource_DdnsUseConflictResolution(t *testing.T) { var resourceName = "bloxone_dhcp_server.test_ddns_use_conflict_resolution" var v ipam.IpamsvcServer @@ -424,7 +485,6 @@ func TestAccServerResource_DdnsUseConflictResolution(t *testing.T) { }) } -// list func TestAccServerResource_DdnsZones(t *testing.T) { var resourceName = "bloxone_dhcp_server.test_ddns_zones" var v ipam.IpamsvcServer @@ -969,6 +1029,68 @@ resource "bloxone_dhcp_server" "test_ddns_domain" { `, name, ddnsDomain) } +func testAccServerDhcpOptionsOption(name string, type_, optValue string) string { + config := fmt.Sprintf(` +resource "bloxone_dhcp_server" "test_dhcp_options" { + name = %q + dhcp_options = [ + { + type = %q + option_code = bloxone_dhcp_option_code.test.id + option_value = %q + } + ] +} +`, name, type_, optValue) + return strings.Join([]string{testAccBaseWithOptionSpaceAndCode(), config}, "") +} + +func testAccServerDhcpOptionsGroup(name string, type_ string) string { + config := fmt.Sprintf(` +resource "bloxone_dhcp_server" "test_dhcp_options" { + name = %q + dhcp_options = [ + { + type = %q + group = bloxone_dhcp_option_group.test.id + } + ] +} +`, name, type_) + return strings.Join([]string{testAccBaseWithOptionSpaceAndCode(), config}, "") +} + +func testAccServerDhcpOptionsOptionV6(name string, type_, optValue string) string { + config := fmt.Sprintf(` +resource "bloxone_dhcp_server" "test_dhcp_options" { + name = %q + dhcp_options_v6 = [ + { + type = %q + option_code = bloxone_dhcp_option_code.test.id + option_value = %q + } + ] +} +`, name, type_, optValue) + return strings.Join([]string{testAccBaseWithV6OptionSpaceAndCode(), config}, "") +} + +func testAccServerDhcpOptionsGroupV6(name string, type_ string) string { + config := fmt.Sprintf(` +resource "bloxone_dhcp_server" "test_dhcp_options" { + name = %q + dhcp_options_v6 = [ + { + type = %q + group = bloxone_dhcp_option_group.test.id + } + ] +} +`, name, type_) + return strings.Join([]string{testAccBaseWithV6OptionSpaceAndCode(), config}, "") +} + func testAccServerDdnsEnabled(name string, ddnsEnabled string) string { return fmt.Sprintf(` resource "bloxone_dhcp_server" "test_ddns_enabled" { diff --git a/internal/service/ipam/api_subnet_resource_test.go b/internal/service/ipam/api_subnet_resource_test.go index c1779478..87020031 100644 --- a/internal/service/ipam/api_subnet_resource_test.go +++ b/internal/service/ipam/api_subnet_resource_test.go @@ -403,6 +403,37 @@ func TestAccSubnetResource_DdnsGeneratedPrefix(t *testing.T) { }) } +func TestAccSubnetResource_DhcpOptions(t *testing.T) { + var resourceName = "bloxone_ipam_subnet.test_dhcp_options" + var v1 ipam.IpamsvcSubnet + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Create and Read + { + Config: testAccSubnetDhcpOptionsOption("10.0.0.0", 24, "option_group_test", "option", "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSubnetExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.0.option_value", "true"), + resource.TestCheckResourceAttrPair(resourceName, "dhcp_options.0.option_code", "bloxone_dhcp_option_code.test", "id"), + ), + }, + // Update and Read + { + Config: testAccSubnetDhcpOptionsGroup("10.0.0.0", 24, "option_group_test", "group"), + Check: resource.ComposeTestCheckFunc( + testAccCheckSubnetExists(context.Background(), resourceName, &v1), + resource.TestCheckResourceAttr(resourceName, "dhcp_options.#", "1"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + func TestAccSubnetResource_DdnsSendUpdates(t *testing.T) { var resourceName = "bloxone_ipam_subnet.test_ddns_send_updates" var v ipam.IpamsvcSubnet @@ -1059,6 +1090,77 @@ resource "bloxone_ipam_subnet" "test_ddns_conflict_resolution_mode" { return strings.Join([]string{testAccBaseWithIPSpace(), config}, "") } +func testAccSubnetDhcpOptionsOption(address string, cidr int, name, type_, optValue string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_subnet" "test_dhcp_options" { + address = %q + cidr = %d + space = bloxone_ipam_ip_space.test.id + name = %q + dhcp_options = [ + { + type = %q + option_code = bloxone_dhcp_option_code.test.id + option_value = %q + } + ] +} +`, address, cidr, name, type_, optValue) + + return strings.Join([]string{testAccBaseWithIPSpace(), testAccBaseWithOptionSpaceAndCode(), config}, "") +} + +func testAccSubnetDhcpOptionsGroup(address string, cidr int, name, type_ string) string { + config := fmt.Sprintf(` +resource "bloxone_ipam_subnet" "test_dhcp_options" { + address = %q + cidr = %d + space = bloxone_ipam_ip_space.test.id + name = %q + dhcp_options = [ + { + type = %q + group = bloxone_dhcp_option_group.test.id + } + ] +} +`, address, cidr, name, type_) + + return strings.Join([]string{testAccBaseWithIPSpace(), testAccBaseWithOptionSpaceAndCode(), config}, "") +} + +func testAccBaseWithOptionSpaceAndCode() string { + config := ` +resource "bloxone_dhcp_option_group" "test" { + name = "option_group_test" + protocol = "ip4" +} +resource "bloxone_dhcp_option_code" "test" { + code = "234" + name = "test_dhcp_option_code" + option_space = bloxone_dhcp_option_space.test.id + type = "boolean" +} +` + return strings.Join([]string{testAccOptionSpace("test_option_space", "ip4"), config}, "") +} + +func testAccBaseWithV6OptionSpaceAndCode() string { + config := ` +resource "bloxone_dhcp_option_group" "test" { + name = "option_group_test" + protocol = "ip6" +} +resource "bloxone_dhcp_option_code" "test" { + code = "59" + name = "test_dhcp_option_code" + option_space = bloxone_dhcp_option_space.test.id + type = "text" +} +` + return strings.Join([]string{testAccOptionSpace("test_option_space", "ip6"), config}, "") +} + func testAccSubnetDdnsDomain(address string, cidr int, ddnsDomain string) string { config := fmt.Sprintf(` resource "bloxone_ipam_subnet" "test_ddns_domain" {