From 4d7abf5503b3c3e680979bd5c06f0eedc65ae862 Mon Sep 17 00:00:00 2001 From: GokceGK Date: Mon, 10 Aug 2026 09:26:18 +0200 Subject: [PATCH 1/2] chore(iaas): remove deprecated network area region fields in network_area resource relates to STACKITTPR-694 --- docs/data-sources/network_area.md | 14 - docs/resources/network_area.md | 17 - .../internal/services/iaas/iaas_acc_test.go | 233 ++--- .../services/iaas/networkarea/datasource.go | 86 -- .../services/iaas/networkarea/resource.go | 622 +----------- .../iaas/networkarea/resource_test.go | 931 +----------------- .../testdata/resource-network-area-max.tf | 35 - .../resource-network-area-region-max.tf | 21 + 8 files changed, 137 insertions(+), 1822 deletions(-) diff --git a/docs/data-sources/network_area.md b/docs/data-sources/network_area.md index 229b58390..93002fe96 100644 --- a/docs/data-sources/network_area.md +++ b/docs/data-sources/network_area.md @@ -32,21 +32,7 @@ data "stackit_network_area" "example" { ### Read-Only -- `default_nameservers` (List of String, Deprecated) List of DNS Servers/Nameservers. -- `default_prefix_length` (Number, Deprecated) The default prefix length for networks in the network area. - `id` (String) Terraform's internal resource ID. It is structured as "`organization_id`,`network_area_id`". - `labels` (Map of String) Labels are key-value string pairs which can be attached to a resource container -- `max_prefix_length` (Number, Deprecated) The maximal prefix length for networks in the network area. -- `min_prefix_length` (Number, Deprecated) The minimal prefix length for networks in the network area. - `name` (String) The name of the network area. -- `network_ranges` (Attributes List, Deprecated) List of Network ranges. (see [below for nested schema](#nestedatt--network_ranges)) - `project_count` (Number) The amount of projects currently referencing this area. -- `transfer_network` (String, Deprecated) Classless Inter-Domain Routing (CIDR). - - -### Nested Schema for `network_ranges` - -Read-Only: - -- `network_range_id` (String) -- `prefix` (String) diff --git a/docs/resources/network_area.md b/docs/resources/network_area.md index 0848b5067..aad7cbe05 100644 --- a/docs/resources/network_area.md +++ b/docs/resources/network_area.md @@ -107,27 +107,10 @@ When the run is completed, you can remove the import-block. Run `$ terraform pla ### Optional -- `default_nameservers` (List of String, Deprecated) List of DNS Servers/Nameservers for configuration of network area for region `eu01`. -- `default_prefix_length` (Number, Deprecated) The default prefix length for networks in the network area for region `eu01`. - `labels` (Map of String) Labels are key-value string pairs which can be attached to a resource container -- `max_prefix_length` (Number, Deprecated) The maximal prefix length for networks in the network area for region `eu01`. -- `min_prefix_length` (Number, Deprecated) The minimal prefix length for networks in the network area for region `eu01`. -- `network_ranges` (Attributes List, Deprecated) List of Network ranges for configuration of network area for region `eu01`. (see [below for nested schema](#nestedatt--network_ranges)) -- `transfer_network` (String, Deprecated) Classless Inter-Domain Routing (CIDR) for configuration of network area for region `eu01`. ### Read-Only - `id` (String) Terraform's internal resource ID. It is structured as "`organization_id`,`network_area_id`". - `network_area_id` (String) The network area ID. - `project_count` (Number) The amount of projects currently referencing this area. - - -### Nested Schema for `network_ranges` - -Required: - -- `prefix` (String, Deprecated) Classless Inter-Domain Routing (CIDR). - -Read-Only: - -- `network_range_id` (String, Deprecated) diff --git a/stackit/internal/services/iaas/iaas_acc_test.go b/stackit/internal/services/iaas/iaas_acc_test.go index 24a14ea18..068c28ea8 100644 --- a/stackit/internal/services/iaas/iaas_acc_test.go +++ b/stackit/internal/services/iaas/iaas_acc_test.go @@ -345,30 +345,15 @@ var testConfigNetworkAreaVarsMinUpdated = func() config.Variables { // NETWORK AREA - MAX var testConfigNetworkAreaVarsMax = config.Variables{ - "organization_id": config.StringVariable(testutil.OrganizationId), - "name": config.StringVariable(fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlpha))), - "transfer_network": config.StringVariable("10.1.2.0/24"), - "network_ranges_prefix": config.StringVariable("10.0.0.0/16"), - "default_nameservers": config.StringVariable("1.1.1.1"), - "default_prefix_length": config.IntegerVariable(24), - "max_prefix_length": config.IntegerVariable(24), - "min_prefix_length": config.IntegerVariable(16), - "route_destination_type": config.StringVariable("cidrv4"), - "route_destination_value": config.StringVariable("1.1.1.0/24"), - "route_next_hop_type": config.StringVariable("ipv4"), - "route_next_hop_value": config.StringVariable("1.1.1.1"), - "label": config.StringVariable("label"), + "organization_id": config.StringVariable(testutil.OrganizationId), + "name": config.StringVariable(fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlpha))), + "label": config.StringVariable("label"), } var testConfigNetworkAreaVarsMaxUpdated = func() config.Variables { updatedConfig := config.Variables{} maps.Copy(updatedConfig, testConfigNetworkAreaVarsMax) updatedConfig["name"] = config.StringVariable(fmt.Sprintf("%s-updated", testutil.ConvertConfigVariable(updatedConfig["name"]))) - updatedConfig["network_ranges_prefix"] = config.StringVariable("10.0.0.0/18") - updatedConfig["default_nameservers"] = config.StringVariable("1.1.1.2") - updatedConfig["default_prefix_length"] = config.IntegerVariable(25) - updatedConfig["max_prefix_length"] = config.IntegerVariable(25) - updatedConfig["min_prefix_length"] = config.IntegerVariable(20) // TODO: enable once the IaaS API supports IPv6 // updatedConfig["route_destination_type"] = config.StringVariable("cidrv6") // updatedConfig["route_destination_value"] = config.StringVariable("2001:db8:3c4d:15::1a2b:3c4d/64") @@ -397,14 +382,19 @@ var testConfigNetworkAreaRegionVarsMinUpdated = func() config.Variables { // NETWORK AREA REGION - MAX var testConfigNetworkAreaRegionVarsMax = config.Variables{ - "organization_id": config.StringVariable(testutil.OrganizationId), - "name": config.StringVariable(fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlpha))), - "transfer_network": config.StringVariable("10.1.2.0/24"), - "network_ranges_prefix": config.StringVariable("10.0.0.0/16"), - "default_nameservers": config.StringVariable("1.1.1.1"), - "default_prefix_length": config.IntegerVariable(26), - "min_prefix_length": config.IntegerVariable(25), - "max_prefix_length": config.IntegerVariable(28), + "organization_id": config.StringVariable(testutil.OrganizationId), + "name": config.StringVariable(fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlpha))), + "transfer_network": config.StringVariable("10.1.2.0/24"), + "network_ranges_prefix": config.StringVariable("10.0.0.0/16"), + "default_nameservers": config.StringVariable("1.1.1.1"), + "default_prefix_length": config.IntegerVariable(26), + "min_prefix_length": config.IntegerVariable(25), + "max_prefix_length": config.IntegerVariable(28), + "route_destination_type": config.StringVariable("cidrv4"), + "route_destination_value": config.StringVariable("1.1.1.0/24"), + "route_next_hop_type": config.StringVariable("ipv4"), + "route_next_hop_value": config.StringVariable("1.1.1.1"), + "label": config.StringVariable("label"), } var testConfigNetworkAreaRegionVarsMaxUpdated = func() config.Variables { @@ -1273,31 +1263,7 @@ func TestAccNetworkAreaMax(t *testing.T) { resource.TestCheckResourceAttr("stackit_network_area.network_area", "organization_id", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["organization_id"])), resource.TestCheckResourceAttrSet("stackit_network_area.network_area", "network_area_id"), resource.TestCheckResourceAttr("stackit_network_area.network_area", "name", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["name"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "network_ranges.#", "1"), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "network_ranges.0.prefix", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["network_ranges_prefix"])), - resource.TestCheckResourceAttrSet("stackit_network_area.network_area", "network_ranges.0.network_range_id"), resource.TestCheckResourceAttr("stackit_network_area.network_area", "labels.acc-test", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["label"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "default_nameservers.#", "1"), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "default_nameservers.0", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["default_nameservers"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "default_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["default_prefix_length"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "max_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["max_prefix_length"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "min_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["min_prefix_length"])), - - // Network Area Route - resource.TestCheckResourceAttrPair( - "stackit_network_area_route.network_area_route", "organization_id", - "stackit_network_area.network_area", "organization_id", - ), - resource.TestCheckResourceAttrPair( - "stackit_network_area_route.network_area_route", "network_area_id", - "stackit_network_area.network_area", "network_area_id", - ), - resource.TestCheckResourceAttrSet("stackit_network_area_route.network_area_route", "network_area_route_id"), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "destination.type", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["route_destination_type"])), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "destination.value", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["route_destination_value"])), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "next_hop.type", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["route_next_hop_type"])), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "next_hop.value", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["route_next_hop_value"])), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "labels.acc-test", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["label"])), ), }, // Data source @@ -1311,12 +1277,6 @@ func TestAccNetworkAreaMax(t *testing.T) { organization_id = stackit_network_area.network_area.organization_id network_area_id = stackit_network_area.network_area.network_area_id } - - data "stackit_network_area_route" "network_area_route" { - organization_id = stackit_network_area.network_area.organization_id - network_area_id = stackit_network_area.network_area.network_area_id - network_area_route_id = stackit_network_area_route.network_area_route.network_area_route_id - } `, testutil.NewConfigBuilder().BuildProviderConfig(), resourceNetworkAreaMaxConfig, ), @@ -1329,34 +1289,7 @@ func TestAccNetworkAreaMax(t *testing.T) { "stackit_network_area.network_area", "network_area_id", ), resource.TestCheckResourceAttr("data.stackit_network_area.network_area", "name", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["name"])), - resource.TestCheckResourceAttr("data.stackit_network_area.network_area", "network_ranges.#", "1"), - resource.TestCheckResourceAttr("data.stackit_network_area.network_area", "network_ranges.0.prefix", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["network_ranges_prefix"])), - resource.TestCheckResourceAttrSet("data.stackit_network_area.network_area", "network_ranges.0.network_range_id"), resource.TestCheckResourceAttr("data.stackit_network_area.network_area", "labels.acc-test", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["label"])), - resource.TestCheckResourceAttr("data.stackit_network_area.network_area", "default_nameservers.#", "1"), - resource.TestCheckResourceAttr("data.stackit_network_area.network_area", "default_nameservers.0", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["default_nameservers"])), - resource.TestCheckResourceAttr("data.stackit_network_area.network_area", "default_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["default_prefix_length"])), - resource.TestCheckResourceAttr("data.stackit_network_area.network_area", "max_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["max_prefix_length"])), - resource.TestCheckResourceAttr("data.stackit_network_area.network_area", "min_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["min_prefix_length"])), - - // Network Area Route - resource.TestCheckResourceAttrPair( - "data.stackit_network_area_route.network_area_route", "organization_id", - "data.stackit_network_area.network_area", "organization_id", - ), - resource.TestCheckResourceAttrPair( - "data.stackit_network_area_route.network_area_route", "network_area_id", - "data.stackit_network_area.network_area", "network_area_id", - ), - resource.TestCheckResourceAttrPair( - "data.stackit_network_area_route.network_area_route", "network_area_route_id", - "stackit_network_area_route.network_area_route", "network_area_route_id", - ), - resource.TestCheckResourceAttrSet("data.stackit_network_area_route.network_area_route", "network_area_route_id"), - resource.TestCheckResourceAttr("data.stackit_network_area_route.network_area_route", "destination.type", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["route_destination_type"])), - resource.TestCheckResourceAttr("data.stackit_network_area_route.network_area_route", "destination.value", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["route_destination_value"])), - resource.TestCheckResourceAttr("data.stackit_network_area_route.network_area_route", "next_hop.type", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["route_next_hop_type"])), - resource.TestCheckResourceAttr("data.stackit_network_area_route.network_area_route", "next_hop.value", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["route_next_hop_value"])), ), }, // Import @@ -1379,38 +1312,9 @@ func TestAccNetworkAreaMax(t *testing.T) { resource.TestCheckResourceAttr("stackit_network_area.network_area", "organization_id", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["organization_id"])), resource.TestCheckResourceAttrSet("stackit_network_area.network_area", "network_area_id"), resource.TestCheckResourceAttr("stackit_network_area.network_area", "name", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["name"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "network_ranges.#", "1"), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "network_ranges.0.prefix", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["network_ranges_prefix"])), - resource.TestCheckResourceAttrSet("stackit_network_area.network_area", "network_ranges.0.network_range_id"), resource.TestCheckResourceAttr("stackit_network_area.network_area", "labels.acc-test", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["label"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "default_nameservers.#", "1"), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "default_nameservers.0", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["default_nameservers"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "default_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["default_prefix_length"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "max_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["max_prefix_length"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "min_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMax["min_prefix_length"])), ), }, - { - ConfigVariables: testConfigNetworkAreaVarsMaxUpdated, - ResourceName: "stackit_network_area_route.network_area_route", - ImportStateIdFunc: func(s *terraform.State) (string, error) { - r, ok := s.RootModule().Resources["stackit_network_area_route.network_area_route"] - if !ok { - return "", fmt.Errorf("couldn't find resource stackit_network_area_route.network_area_route") - } - networkAreaId, ok := r.Primary.Attributes["network_area_id"] - if !ok { - return "", fmt.Errorf("couldn't find attribute network_area_id") - } - networkAreaRouteId, ok := r.Primary.Attributes["network_area_route_id"] - if !ok { - return "", fmt.Errorf("couldn't find attribute network_area_route_id") - } - return fmt.Sprintf("%s,%s,%s,%s", testutil.OrganizationId, networkAreaId, testutil.Region, networkAreaRouteId), nil - }, - ImportState: true, - ImportStateVerify: true, - }, // Update { ConfigVariables: testConfigNetworkAreaVarsMaxUpdated, @@ -1420,31 +1324,7 @@ func TestAccNetworkAreaMax(t *testing.T) { resource.TestCheckResourceAttr("stackit_network_area.network_area", "organization_id", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["organization_id"])), resource.TestCheckResourceAttrSet("stackit_network_area.network_area", "network_area_id"), resource.TestCheckResourceAttr("stackit_network_area.network_area", "name", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["name"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "network_ranges.#", "1"), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "network_ranges.0.prefix", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["network_ranges_prefix"])), - resource.TestCheckResourceAttrSet("stackit_network_area.network_area", "network_ranges.0.network_range_id"), resource.TestCheckResourceAttr("stackit_network_area.network_area", "labels.acc-test", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["label"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "default_nameservers.#", "1"), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "default_nameservers.0", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["default_nameservers"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "default_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["default_prefix_length"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "max_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["max_prefix_length"])), - resource.TestCheckResourceAttr("stackit_network_area.network_area", "min_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["min_prefix_length"])), - - // Network Area Route - resource.TestCheckResourceAttrPair( - "stackit_network_area_route.network_area_route", "organization_id", - "stackit_network_area.network_area", "organization_id", - ), - resource.TestCheckResourceAttrPair( - "stackit_network_area_route.network_area_route", "network_area_id", - "stackit_network_area.network_area", "network_area_id", - ), - resource.TestCheckResourceAttrSet("stackit_network_area_route.network_area_route", "network_area_route_id"), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "destination.type", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["route_destination_type"])), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "destination.value", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["route_destination_value"])), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "next_hop.type", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["route_next_hop_type"])), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "next_hop.value", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["route_next_hop_value"])), - resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "labels.acc-test", testutil.ConvertConfigVariable(testConfigNetworkAreaVarsMaxUpdated["label"])), ), }, // Deletion is done by the framework implicitly @@ -1584,6 +1464,7 @@ func TestAccNetworkAreaRegionMax(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectResourceAction("stackit_network_area.network_area", plancheck.ResourceActionCreate), plancheck.ExpectResourceAction("stackit_network_area_region.network_area_region", plancheck.ResourceActionCreate), + plancheck.ExpectResourceAction("stackit_network_area_route.network_area_route", plancheck.ResourceActionCreate), }, }, Check: resource.ComposeAggregateTestCheckFunc( @@ -1602,6 +1483,22 @@ func TestAccNetworkAreaRegionMax(t *testing.T) { resource.TestCheckResourceAttr("stackit_network_area_region.network_area_region", "ipv4.default_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["default_prefix_length"])), resource.TestCheckResourceAttr("stackit_network_area_region.network_area_region", "ipv4.min_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["min_prefix_length"])), resource.TestCheckResourceAttr("stackit_network_area_region.network_area_region", "ipv4.max_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["max_prefix_length"])), + + // Network Area Route + resource.TestCheckResourceAttrPair( + "stackit_network_area_route.network_area_route", "organization_id", + "stackit_network_area_region.network_area_region", "organization_id", + ), + resource.TestCheckResourceAttrPair( + "stackit_network_area_route.network_area_route", "network_area_id", + "stackit_network_area_region.network_area_region", "network_area_id", + ), + resource.TestCheckResourceAttrSet("stackit_network_area_route.network_area_route", "network_area_route_id"), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "destination.type", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["route_destination_type"])), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "destination.value", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["route_destination_value"])), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "next_hop.type", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["route_next_hop_type"])), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "next_hop.value", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["route_next_hop_value"])), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "labels.acc-test", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["label"])), ), }, // Data source @@ -1615,6 +1512,12 @@ func TestAccNetworkAreaRegionMax(t *testing.T) { organization_id = stackit_network_area_region.network_area_region.organization_id network_area_id = stackit_network_area_region.network_area_region.network_area_id } + + data "stackit_network_area_route" "network_area_route" { + organization_id = stackit_network_area_region.network_area_region.organization_id + network_area_id = stackit_network_area_region.network_area_region.network_area_id + network_area_route_id = stackit_network_area_route.network_area_route.network_area_route_id + } `, testutil.NewConfigBuilder().BuildProviderConfig(), resourceNetworkAreaRegionMaxConfig, ), @@ -1622,6 +1525,7 @@ func TestAccNetworkAreaRegionMax(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectResourceAction("stackit_network_area.network_area", plancheck.ResourceActionNoop), plancheck.ExpectResourceAction("stackit_network_area_region.network_area_region", plancheck.ResourceActionNoop), + plancheck.ExpectResourceAction("stackit_network_area_route.network_area_route", plancheck.ResourceActionNoop), }, }, Check: resource.ComposeAggregateTestCheckFunc( @@ -1640,6 +1544,25 @@ func TestAccNetworkAreaRegionMax(t *testing.T) { resource.TestCheckResourceAttr("data.stackit_network_area_region.network_area_region", "ipv4.default_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["default_prefix_length"])), resource.TestCheckResourceAttr("data.stackit_network_area_region.network_area_region", "ipv4.min_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["min_prefix_length"])), resource.TestCheckResourceAttr("data.stackit_network_area_region.network_area_region", "ipv4.max_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["max_prefix_length"])), + + // Network Area Route + resource.TestCheckResourceAttrPair( + "data.stackit_network_area_route.network_area_route", "organization_id", + "data.stackit_network_area_region.network_area_region", "organization_id", + ), + resource.TestCheckResourceAttrPair( + "data.stackit_network_area_route.network_area_route", "network_area_id", + "data.stackit_network_area_region.network_area_region", "network_area_id", + ), + resource.TestCheckResourceAttrPair( + "data.stackit_network_area_route.network_area_route", "network_area_route_id", + "stackit_network_area_route.network_area_route", "network_area_route_id", + ), + resource.TestCheckResourceAttrSet("data.stackit_network_area_route.network_area_route", "network_area_route_id"), + resource.TestCheckResourceAttr("data.stackit_network_area_route.network_area_route", "destination.type", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["route_destination_type"])), + resource.TestCheckResourceAttr("data.stackit_network_area_route.network_area_route", "destination.value", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["route_destination_value"])), + resource.TestCheckResourceAttr("data.stackit_network_area_route.network_area_route", "next_hop.type", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["route_next_hop_type"])), + resource.TestCheckResourceAttr("data.stackit_network_area_route.network_area_route", "next_hop.value", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMax["route_next_hop_value"])), ), }, // Import @@ -1660,6 +1583,27 @@ func TestAccNetworkAreaRegionMax(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + ConfigVariables: testConfigNetworkAreaRegionVarsMaxUpdated, + ResourceName: "stackit_network_area_route.network_area_route", + ImportStateIdFunc: func(s *terraform.State) (string, error) { + r, ok := s.RootModule().Resources["stackit_network_area_route.network_area_route"] + if !ok { + return "", fmt.Errorf("couldn't find resource stackit_network_area_route.network_area_route") + } + networkAreaId, ok := r.Primary.Attributes["network_area_id"] + if !ok { + return "", fmt.Errorf("couldn't find attribute network_area_id") + } + networkAreaRouteId, ok := r.Primary.Attributes["network_area_route_id"] + if !ok { + return "", fmt.Errorf("couldn't find attribute network_area_route_id") + } + return fmt.Sprintf("%s,%s,%s,%s", testutil.OrganizationId, networkAreaId, testutil.Region, networkAreaRouteId), nil + }, + ImportState: true, + ImportStateVerify: true, + }, // Update { ConfigVariables: testConfigNetworkAreaRegionVarsMaxUpdated, @@ -1668,6 +1612,7 @@ func TestAccNetworkAreaRegionMax(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectResourceAction("stackit_network_area.network_area", plancheck.ResourceActionNoop), plancheck.ExpectResourceAction("stackit_network_area_region.network_area_region", plancheck.ResourceActionUpdate), + plancheck.ExpectResourceAction("stackit_network_area_route.network_area_route", plancheck.ResourceActionNoop), }, }, Check: resource.ComposeAggregateTestCheckFunc( @@ -1686,6 +1631,22 @@ func TestAccNetworkAreaRegionMax(t *testing.T) { resource.TestCheckResourceAttr("stackit_network_area_region.network_area_region", "ipv4.default_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMaxUpdated["default_prefix_length"])), resource.TestCheckResourceAttr("stackit_network_area_region.network_area_region", "ipv4.min_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMaxUpdated["min_prefix_length"])), resource.TestCheckResourceAttr("stackit_network_area_region.network_area_region", "ipv4.max_prefix_length", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMaxUpdated["max_prefix_length"])), + + // Network Area Route + resource.TestCheckResourceAttrPair( + "stackit_network_area_route.network_area_route", "organization_id", + "stackit_network_area_region.network_area_region", "organization_id", + ), + resource.TestCheckResourceAttrPair( + "stackit_network_area_route.network_area_route", "network_area_id", + "stackit_network_area_region.network_area_region", "network_area_id", + ), + resource.TestCheckResourceAttrSet("stackit_network_area_route.network_area_route", "network_area_route_id"), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "destination.type", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMaxUpdated["route_destination_type"])), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "destination.value", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMaxUpdated["route_destination_value"])), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "next_hop.type", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMaxUpdated["route_next_hop_type"])), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "next_hop.value", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMaxUpdated["route_next_hop_value"])), + resource.TestCheckResourceAttr("stackit_network_area_route.network_area_route", "labels.acc-test", testutil.ConvertConfigVariable(testConfigNetworkAreaRegionVarsMaxUpdated["label"])), ), }, // Deletion is done by the framework implicitly diff --git a/stackit/internal/services/iaas/networkarea/datasource.go b/stackit/internal/services/iaas/networkarea/datasource.go index 72b9001ff..f8e7d9de4 100644 --- a/stackit/internal/services/iaas/networkarea/datasource.go +++ b/stackit/internal/services/iaas/networkarea/datasource.go @@ -2,12 +2,9 @@ package networkarea import ( "context" - "errors" "fmt" "net/http" - "github.com/stackitcloud/stackit-sdk-go/core/oapierror" - "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" @@ -15,7 +12,6 @@ import ( iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" - "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -63,7 +59,6 @@ func (d *networkAreaDataSource) Configure(ctx context.Context, req datasource.Co // Schema defines the schema for the data source. func (d *networkAreaDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { - deprecationMsg := "Deprecated because of the IaaS API v1 -> v2 migration. Will be removed in May 2026." description := "Network area datasource schema. Must have a `region` specified in the provider configuration.\n\n" + "This datasource is for SNA, not VPC, networks." resp.Schema = schema.Schema{ @@ -105,67 +100,6 @@ func (d *networkAreaDataSource) Schema(_ context.Context, _ datasource.SchemaReq int64validator.AtLeast(0), }, }, - "default_nameservers": schema.ListAttribute{ - DeprecationMessage: deprecationMsg, - Description: "List of DNS Servers/Nameservers.", - Computed: true, - ElementType: types.StringType, - }, - "network_ranges": schema.ListNestedAttribute{ - DeprecationMessage: deprecationMsg, - Description: "List of Network ranges.", - Computed: true, - Validators: []validator.List{ - listvalidator.SizeAtLeast(1), - listvalidator.SizeAtMost(64), - }, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "network_range_id": schema.StringAttribute{ - Computed: true, - Validators: []validator.String{ - validate.UUID(), - validate.NoSeparator(), - }, - }, - "prefix": schema.StringAttribute{ - Computed: true, - }, - }, - }, - }, - "transfer_network": schema.StringAttribute{ - DeprecationMessage: deprecationMsg, - Description: "Classless Inter-Domain Routing (CIDR).", - Computed: true, - }, - "default_prefix_length": schema.Int64Attribute{ - DeprecationMessage: deprecationMsg, - Description: "The default prefix length for networks in the network area.", - Computed: true, - Validators: []validator.Int64{ - int64validator.AtLeast(24), - int64validator.AtMost(29), - }, - }, - "max_prefix_length": schema.Int64Attribute{ - DeprecationMessage: deprecationMsg, - Description: "The maximal prefix length for networks in the network area.", - Computed: true, - Validators: []validator.Int64{ - int64validator.AtLeast(24), - int64validator.AtMost(29), - }, - }, - "min_prefix_length": schema.Int64Attribute{ - DeprecationMessage: deprecationMsg, - Description: "The minimal prefix length for networks in the network area.", - Computed: true, - Validators: []validator.Int64{ - int64validator.AtLeast(22), - int64validator.AtMost(29), - }, - }, "labels": schema.MapAttribute{ Description: "Labels are key-value string pairs which can be attached to a resource container", ElementType: types.StringType, @@ -215,26 +149,6 @@ func (d *networkAreaDataSource) Read(ctx context.Context, req datasource.ReadReq return } - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionResp, err := d.client.DefaultAPI.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").Execute() - if err != nil { - var oapiErr *oapierror.GenericOpenAPIError - ok := errors.As(err, &oapiErr) - if !(ok && (oapiErr.StatusCode == http.StatusNotFound || oapiErr.StatusCode == http.StatusBadRequest)) { // TODO: iaas api returns http 400 in case network area region is not found - core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading network area region", fmt.Sprintf("Calling API: %v", err)) - return - } - - networkAreaRegionResp = &iaas.RegionalArea{} - } - - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - err = mapNetworkAreaRegionFields(ctx, networkAreaRegionResp, &model) - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading network area region", fmt.Sprintf("Processing API payload: %v", err)) - return - } - diags = resp.State.Set(ctx, model) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { diff --git a/stackit/internal/services/iaas/networkarea/resource.go b/stackit/internal/services/iaas/networkarea/resource.go index c0344dc3e..3340e3cdd 100644 --- a/stackit/internal/services/iaas/networkarea/resource.go +++ b/stackit/internal/services/iaas/networkarea/resource.go @@ -13,14 +13,10 @@ import ( resourcemanagerUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/resourcemanager/utils" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" - "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" @@ -36,29 +32,12 @@ import ( "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" ) -const ( - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - defaultValueDefaultPrefixLength = 25 - - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - defaultValueMinPrefixLength = 24 - - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - defaultValueMaxPrefixLength = 29 - - // Deprecated: Will be removed in May 2026. - deprecationWarningSummary = "Migration to new `stackit_network_area_region` resource needed" - // Deprecated: Will be removed in May 2026. - deprecationWarningDetails = "You're using deprecated features of the `stackit_network_area` resource. These will be removed in May 2026. Migrate to the new `stackit_network_area_region` resource instead." -) - // Ensure the implementation satisfies the expected interfaces. var ( - _ resource.Resource = &networkAreaResource{} - _ resource.ResourceWithConfigure = &networkAreaResource{} - _ resource.ResourceWithImportState = &networkAreaResource{} - _ resource.ResourceWithValidateConfig = &networkAreaResource{} - _ resource.ResourceWithModifyPlan = &networkAreaResource{} + _ resource.Resource = &networkAreaResource{} + _ resource.ResourceWithConfigure = &networkAreaResource{} + _ resource.ResourceWithImportState = &networkAreaResource{} + _ resource.ResourceWithModifyPlan = &networkAreaResource{} ) type Model struct { @@ -68,41 +47,6 @@ type Model struct { Name types.String `tfsdk:"name"` ProjectCount types.Int64 `tfsdk:"project_count"` Labels types.Map `tfsdk:"labels"` - - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - DefaultNameservers types.List `tfsdk:"default_nameservers"` - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - MaxPrefixLength types.Int64 `tfsdk:"max_prefix_length"` - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - NetworkRanges types.List `tfsdk:"network_ranges"` - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - TransferNetwork types.String `tfsdk:"transfer_network"` - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - DefaultPrefixLength types.Int64 `tfsdk:"default_prefix_length"` - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - MinPrefixLength types.Int64 `tfsdk:"min_prefix_length"` -} - -// Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. LegacyMode checks if any of the deprecated fields are set which now relate to the network area region API resource. -func (model *Model) LegacyMode() bool { - return !model.NetworkRanges.IsNull() || model.NetworkRanges.IsUnknown() || - !model.TransferNetwork.IsNull() || model.TransferNetwork.IsUnknown() || - !model.DefaultNameservers.IsNull() || model.DefaultNameservers.IsUnknown() || - (model.DefaultPrefixLength != types.Int64Value(int64(defaultValueDefaultPrefixLength)) && model.DefaultPrefixLength.IsUnknown()) || - (model.MinPrefixLength != types.Int64Value(int64(defaultValueMinPrefixLength)) && model.MinPrefixLength.IsUnknown()) || - (model.MaxPrefixLength != types.Int64Value(int64(defaultValueMaxPrefixLength)) && model.MaxPrefixLength.IsUnknown()) -} - -// Struct corresponding to Model.NetworkRanges[i] -type networkRange struct { - Prefix types.String `tfsdk:"prefix"` - NetworkRangeId types.String `tfsdk:"network_range_id"` -} - -// Types corresponding to networkRanges -var networkRangeTypes = map[string]attr.Type{ - "prefix": types.StringType, - "network_range_id": types.StringType, } // NewNetworkAreaResource is a helper function to simplify the provider implementation. @@ -117,34 +61,25 @@ type networkAreaResource struct { } func (r *networkAreaResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { // nolint:gocritic // function signature required by Terraform - // If the resource is being created, do nothing. - if req.State.Raw.IsNull() { + var configModel Model + // skip initial empty configuration to avoid follow-up errors + if req.Config.Raw.IsNull() { return } - - var state, plan Model - req.State.Get(ctx, &state) - req.Plan.Get(ctx, &plan) - - // Check if transferNetwork was set before and is changed to a different value - if !plan.TransferNetwork.IsNull() && !state.TransferNetwork.IsNull() && - plan.TransferNetwork.ValueString() != state.TransferNetwork.ValueString() { - // Trigger replace - resp.RequiresReplace.Append(path.Root("transfer_network")) + resp.Diagnostics.Append(req.Config.Get(ctx, &configModel)...) + if resp.Diagnostics.HasError() { + return } - // Check if no transferNetwork was set before and transferNetwork is added now - if !plan.TransferNetwork.IsNull() && state.TransferNetwork.IsNull() { - // Trigger replace - resp.RequiresReplace.Append(path.Root("transfer_network")) + var planModel Model + resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...) + if resp.Diagnostics.HasError() { + return } - // Check if deprecated fields were set before and are now removed - if !state.TransferNetwork.IsNull() && !state.NetworkRanges.IsNull() && plan.TransferNetwork.IsNull() && plan.NetworkRanges.IsNull() { - resp.Diagnostics.AddWarning("Deprecated fields removed", - fmt.Sprintf("You are removing deprecated fields from this resource. They will only be removed from the terraform state.\n"+ - "For a complete migration, please import `stackit_network_area_region` with the ID `%s,eu01`.\n"+ - "If you don't import the resource, you may run into issues.", state.Id.ValueString())) + resp.Diagnostics.Append(resp.Plan.Set(ctx, planModel)...) + if resp.Diagnostics.HasError() { + return } } @@ -173,26 +108,8 @@ func (r *networkAreaResource) Configure(ctx context.Context, req resource.Config tflog.Info(ctx, "IaaS client configured") } -// Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. -func (r *networkAreaResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) { - var resourceModel Model - resp.Diagnostics.Append(req.Config.Get(ctx, &resourceModel)...) - if resp.Diagnostics.HasError() { - return - } - - if resourceModel.NetworkRanges.IsNull() != resourceModel.TransferNetwork.IsNull() { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring network network area", "You have to either provide both the `network_ranges` and `transfer_network` fields simultaneously or none of them.") - } - - if (resourceModel.NetworkRanges.IsNull() || resourceModel.TransferNetwork.IsNull()) && (!resourceModel.DefaultNameservers.IsNull() || !resourceModel.DefaultPrefixLength.IsNull() || !resourceModel.MinPrefixLength.IsNull() || !resourceModel.MaxPrefixLength.IsNull()) { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring network network area", "You have to provide both the `network_ranges` and `transfer_network` fields when providing one of these fields: `default_nameservers`, `default_prefix_length`, `max_prefix_length`, `min_prefix_length`") - } -} - // Schema defines the schema for the resource. func (r *networkAreaResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { - deprecationMsg := "Deprecated because of the IaaS API v1 -> v2 migration. Will be removed in May 2026. Use the new `stackit_network_area_region` resource instead." description := "Network area resource schema.\n\n" + "This resource is for SNA, not VPC, networks." resp.Schema = schema.Schema{ @@ -243,82 +160,6 @@ func (r *networkAreaResource) Schema(_ context.Context, _ resource.SchemaRequest int64validator.AtLeast(0), }, }, - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - "default_nameservers": schema.ListAttribute{ - Description: "List of DNS Servers/Nameservers for configuration of network area for region `eu01`.", - DeprecationMessage: deprecationMsg, - Optional: true, - ElementType: types.StringType, - }, - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - "network_ranges": schema.ListNestedAttribute{ - Description: "List of Network ranges for configuration of network area for region `eu01`.", - DeprecationMessage: deprecationMsg, - Optional: true, - Validators: []validator.List{ - listvalidator.SizeAtLeast(1), - listvalidator.SizeAtMost(64), - }, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "network_range_id": schema.StringAttribute{ - DeprecationMessage: deprecationMsg, - Computed: true, - Validators: []validator.String{ - validate.UUID(), - validate.NoSeparator(), - }, - }, - "prefix": schema.StringAttribute{ - DeprecationMessage: deprecationMsg, - Description: "Classless Inter-Domain Routing (CIDR).", - Required: true, - }, - }, - }, - }, - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - "transfer_network": schema.StringAttribute{ - DeprecationMessage: deprecationMsg, - Description: "Classless Inter-Domain Routing (CIDR) for configuration of network area for region `eu01`.", - Optional: true, - }, - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - "default_prefix_length": schema.Int64Attribute{ - DeprecationMessage: deprecationMsg, - Description: "The default prefix length for networks in the network area for region `eu01`.", - Optional: true, - Computed: true, - Validators: []validator.Int64{ - int64validator.AtLeast(24), - int64validator.AtMost(29), - }, - Default: int64default.StaticInt64(defaultValueDefaultPrefixLength), - }, - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - "max_prefix_length": schema.Int64Attribute{ - DeprecationMessage: deprecationMsg, - Description: "The maximal prefix length for networks in the network area for region `eu01`.", - Optional: true, - Computed: true, - Validators: []validator.Int64{ - int64validator.AtLeast(24), - int64validator.AtMost(29), - }, - Default: int64default.StaticInt64(defaultValueMaxPrefixLength), - }, - // Deprecated: Will be removed in May 2026. Only kept to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - "min_prefix_length": schema.Int64Attribute{ - DeprecationMessage: deprecationMsg, - Description: "The minimal prefix length for networks in the network area for region `eu01`.", - Optional: true, - Computed: true, - Validators: []validator.Int64{ - int64validator.AtLeast(8), - int64validator.AtMost(29), - }, - Default: int64default.StaticInt64(defaultValueMinPrefixLength), - }, "labels": schema.MapAttribute{ Description: "Labels are key-value string pairs which can be attached to a resource container", ElementType: types.StringType, @@ -362,16 +203,6 @@ func (r *networkAreaResource) Create(ctx context.Context, req resource.CreateReq networkAreaId := *networkArea.Id ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - // persist state - just in case anything goes wrong while creating the network area region - ctx = utils.SetAndLogStateFields(ctx, &resp.Diagnostics, &resp.State, map[string]any{ - "organization_id": model.OrganizationId.ValueString(), - "network_area_id": networkAreaId, - }) - if resp.Diagnostics.HasError() { - return - } - // Map response body to schema err = mapFields(ctx, networkArea, &model) if err != nil { @@ -379,54 +210,6 @@ func (r *networkAreaResource) Create(ctx context.Context, req resource.CreateReq return } - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - if model.LegacyMode() { - core.LogAndAddWarning(ctx, &resp.Diagnostics, deprecationWarningSummary, deprecationWarningDetails) - - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - regionCreatePayload, err := toRegionCreatePayload(ctx, &model) - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network area region", fmt.Sprintf("Creating API payload: %v", err)) - return - } - - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionCreateResp, err := r.client.DefaultAPI.CreateNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").CreateNetworkAreaRegionPayload(*regionCreatePayload).Execute() - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network area region", fmt.Sprintf("Calling API: %v", err)) - return - } - - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - err = mapNetworkAreaRegionFields(ctx, networkAreaRegionCreateResp, &model) // map partial state - just in case anything goes wrong during the wait handler - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network area region", fmt.Sprintf("Processing API payload: %v", err)) - return - } - - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionResp, err := wait.CreateNetworkAreaRegionWaitHandler(ctx, r.client.DefaultAPI, organizationId, networkAreaId, "eu01").WaitWithContext(ctx) - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error waiting for network area region creation", fmt.Sprintf("Calling API: %v", err)) - return - } - - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - err = mapNetworkAreaRegionFields(ctx, networkAreaRegionResp, &model) - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network area region", fmt.Sprintf("Processing API payload: %v", err)) - return - } - } else { - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - model.NetworkRanges = types.ListNull(types.ObjectType{AttrTypes: networkRangeTypes}) - model.DefaultNameservers = types.ListNull(types.StringType) - model.TransferNetwork = types.StringNull() - model.DefaultPrefixLength = types.Int64Value(defaultValueDefaultPrefixLength) - model.MinPrefixLength = types.Int64Value(defaultValueMinPrefixLength) - model.MaxPrefixLength = types.Int64Value(defaultValueMaxPrefixLength) - } - // Set state to fully populated data resp.Diagnostics.Append(resp.State.Set(ctx, model)...) if resp.Diagnostics.HasError() { @@ -476,43 +259,6 @@ func (r *networkAreaResource) Read(ctx context.Context, req resource.ReadRequest return } - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - if model.LegacyMode() { - core.LogAndAddWarning(ctx, &resp.Diagnostics, deprecationWarningSummary, deprecationWarningDetails) - - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionResp, err := r.client.DefaultAPI.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").Execute() - if err != nil { - var oapiErr *oapierror.GenericOpenAPIError - if !(errors.As(err, &oapiErr) && (oapiErr.StatusCode == http.StatusNotFound || oapiErr.StatusCode == http.StatusBadRequest)) { // TODO: iaas api returns http 400 in case network area region is not found - core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading network area region", fmt.Sprintf("Calling API: %v", err)) - return - } - - model.NetworkRanges = types.ListNull(types.ObjectType{AttrTypes: networkRangeTypes}) - model.DefaultNameservers = types.ListNull(types.StringType) - model.TransferNetwork = types.StringNull() - model.DefaultPrefixLength = types.Int64Value(defaultValueDefaultPrefixLength) - model.MinPrefixLength = types.Int64Value(defaultValueMinPrefixLength) - model.MaxPrefixLength = types.Int64Value(defaultValueMaxPrefixLength) - } else { - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - err = mapNetworkAreaRegionFields(ctx, networkAreaRegionResp, &model) - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading network area region", fmt.Sprintf("Processing API payload: %v", err)) - return - } - } - } else { - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - model.NetworkRanges = types.ListNull(types.ObjectType{AttrTypes: networkRangeTypes}) - model.DefaultNameservers = types.ListNull(types.StringType) - model.TransferNetwork = types.StringNull() - model.DefaultPrefixLength = types.Int64Value(defaultValueDefaultPrefixLength) - model.MinPrefixLength = types.Int64Value(defaultValueMinPrefixLength) - model.MaxPrefixLength = types.Int64Value(defaultValueMaxPrefixLength) - } - // Set refreshed state resp.Diagnostics.Append(resp.State.Set(ctx, model)...) if resp.Diagnostics.HasError() { @@ -538,14 +284,6 @@ func (r *networkAreaResource) Update(ctx context.Context, req resource.UpdateReq ctx = tflog.SetField(ctx, "organization_id", organizationId) ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) - ranges := []networkRange{} - if !(model.NetworkRanges.IsNull() || model.NetworkRanges.IsUnknown()) { - resp.Diagnostics.Append(model.NetworkRanges.ElementsAs(ctx, &ranges, false)...) - if resp.Diagnostics.HasError() { - return - } - } - // Retrieve values from state var stateModel Model resp.Diagnostics.Append(req.State.Get(ctx, &stateModel)...) @@ -574,65 +312,6 @@ func (r *networkAreaResource) Update(ctx context.Context, req resource.UpdateReq return } - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - if model.LegacyMode() { - core.LogAndAddWarning(ctx, &resp.Diagnostics, deprecationWarningSummary, deprecationWarningDetails) - - // Deprecated: Update network area region payload creation. Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - regionUpdatePayload, err := toRegionUpdatePayload(ctx, &model) - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area region", fmt.Sprintf("Creating API payload: %v", err)) - return - } - - // Deprecated: Update network area region. Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionUpdateResp, err := r.client.DefaultAPI.UpdateNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").UpdateNetworkAreaRegionPayload(*regionUpdatePayload).Execute() - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area region", fmt.Sprintf("Calling API: %v", err)) - return - } - - // Deprecated: Update network area region. Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - err = mapNetworkAreaRegionFields(ctx, networkAreaRegionUpdateResp, &model) - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area region", fmt.Sprintf("Processing API payload: %v", err)) - return - } - - // Deprecated: Update network ranges. Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - err = updateNetworkRanges(ctx, organizationId, networkAreaId, ranges, r.client.DefaultAPI) - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area region", fmt.Sprintf("Updating Network ranges: %v", err)) - return - } - - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionResp, err := r.client.DefaultAPI.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").Execute() - if err != nil { - var oapiErr *oapierror.GenericOpenAPIError - if errors.As(err, &oapiErr) && (oapiErr.StatusCode == http.StatusNotFound || oapiErr.StatusCode == http.StatusBadRequest) { // TODO: iaas api returns http 400 in case network area region is not found - return - } - core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading network area region", fmt.Sprintf("Calling API: %v", err)) - return - } - - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - err = mapNetworkAreaRegionFields(ctx, networkAreaRegionResp, &model) - if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading network area region", fmt.Sprintf("Processing API payload: %v", err)) - return - } - } else { - // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - model.NetworkRanges = types.ListNull(types.ObjectType{AttrTypes: networkRangeTypes}) - model.DefaultNameservers = types.ListNull(types.StringType) - model.TransferNetwork = types.StringNull() - model.DefaultPrefixLength = types.Int64Value(defaultValueDefaultPrefixLength) - model.MinPrefixLength = types.Int64Value(defaultValueMinPrefixLength) - model.MaxPrefixLength = types.Int64Value(defaultValueMaxPrefixLength) - } - resp.Diagnostics.Append(resp.State.Set(ctx, model)...) if resp.Diagnostics.HasError() { return @@ -772,122 +451,6 @@ func mapFields(ctx context.Context, networkAreaResp *iaas.NetworkArea, model *Mo return nil } -// Deprecated: mapRegionFields maps the region configuration for eu01 to avoid a breaking change in the Terraform provider during the IaaS v1 -> v2 API migration. Will be removed in May 2026. -func mapNetworkAreaRegionFields(ctx context.Context, networkAreaRegionResp *iaas.RegionalArea, model *Model) error { - if model == nil { - return fmt.Errorf("model input is nil") - } - if networkAreaRegionResp == nil { - return fmt.Errorf("response input is nil") - } - - // map default nameservers - if networkAreaRegionResp.Ipv4 == nil || networkAreaRegionResp.Ipv4.DefaultNameservers == nil { - model.DefaultNameservers = types.ListNull(types.StringType) - } else { - respDefaultNameservers := networkAreaRegionResp.Ipv4.DefaultNameservers - modelDefaultNameservers, err := utils.ListValueToStringSlice(model.DefaultNameservers) - if err != nil { - return fmt.Errorf("get current network area default nameservers from model: %w", err) - } - - reconciledDefaultNameservers := utils.ReconcileStringSlices(modelDefaultNameservers, respDefaultNameservers) - - defaultNameserversTF, diags := types.ListValueFrom(ctx, types.StringType, reconciledDefaultNameservers) - if diags.HasError() { - return fmt.Errorf("map network area default nameservers: %w", core.DiagsToError(diags)) - } - - model.DefaultNameservers = defaultNameserversTF - } - - // map network ranges - if networkAreaRegionResp.Ipv4 == nil || networkAreaRegionResp.Ipv4.NetworkRanges == nil { - model.NetworkRanges = types.ListNull(types.ObjectType{AttrTypes: networkRangeTypes}) - } else { - err := mapNetworkRanges(ctx, networkAreaRegionResp.Ipv4.NetworkRanges, model) - if err != nil { - return fmt.Errorf("mapping network ranges: %w", err) - } - } - - // map remaining fields - if networkAreaRegionResp.Ipv4 != nil { - model.TransferNetwork = types.StringValue(networkAreaRegionResp.Ipv4.TransferNetwork) - model.DefaultPrefixLength = types.Int64Value(networkAreaRegionResp.Ipv4.DefaultPrefixLen) - model.MaxPrefixLength = types.Int64Value(networkAreaRegionResp.Ipv4.MaxPrefixLen) - model.MinPrefixLength = types.Int64Value(networkAreaRegionResp.Ipv4.MinPrefixLen) - } - - return nil -} - -// Deprecated: mapNetworkRanges will be removed in May 2026. Implementation won't be needed anymore because of the IaaS API v1 -> v2 migration. Func was only kept to circumvent breaking changes. -func mapNetworkRanges(ctx context.Context, networkAreaRangesList []iaas.NetworkRange, model *Model) error { - var diags diag.Diagnostics - - if networkAreaRangesList == nil { - return fmt.Errorf("nil network area ranges list") - } - if len(networkAreaRangesList) == 0 { - model.NetworkRanges = types.ListNull(types.ObjectType{AttrTypes: networkRangeTypes}) - return nil - } - - ranges := []networkRange{} - if !(model.NetworkRanges.IsNull() || model.NetworkRanges.IsUnknown()) { - diags = model.NetworkRanges.ElementsAs(ctx, &ranges, false) - if diags.HasError() { - return fmt.Errorf("map network ranges: %w", core.DiagsToError(diags)) - } - } - - modelNetworkRangePrefixes := []string{} - for _, m := range ranges { - modelNetworkRangePrefixes = append(modelNetworkRangePrefixes, m.Prefix.ValueString()) - } - - apiNetworkRangePrefixes := []string{} - for _, n := range networkAreaRangesList { - apiNetworkRangePrefixes = append(apiNetworkRangePrefixes, n.Prefix) - } - - reconciledRangePrefixes := utils.ReconcileStringSlices(modelNetworkRangePrefixes, apiNetworkRangePrefixes) - - networkRangesList := []attr.Value{} - for i, prefix := range reconciledRangePrefixes { - var networkRangeId string - for _, networkRangeElement := range networkAreaRangesList { - if networkRangeElement.Prefix == prefix { - networkRangeId = *networkRangeElement.Id - break - } - } - networkRangeMap := map[string]attr.Value{ - "prefix": types.StringValue(prefix), - "network_range_id": types.StringValue(networkRangeId), - } - - networkRangeTF, diags := types.ObjectValue(networkRangeTypes, networkRangeMap) - if diags.HasError() { - return fmt.Errorf("mapping index %d: %w", i, core.DiagsToError(diags)) - } - - networkRangesList = append(networkRangesList, networkRangeTF) - } - - networkRangesTF, diags := types.ListValue( - types.ObjectType{AttrTypes: networkRangeTypes}, - networkRangesList, - ) - if diags.HasError() { - return core.DiagsToError(diags) - } - - model.NetworkRanges = networkRangesTF - return nil -} - func toCreatePayload(ctx context.Context, model *Model) (*iaas.CreateNetworkAreaPayload, error) { if model == nil { return nil, fmt.Errorf("nil model") @@ -904,34 +467,6 @@ func toCreatePayload(ctx context.Context, model *Model) (*iaas.CreateNetworkArea }, nil } -// Deprecated: toRegionCreatePayload will be removed in May 2026. Implementation won't be needed anymore because of the IaaS API v1 -> v2 migration. Func was only introduced to circumvent breaking changes. -func toRegionCreatePayload(ctx context.Context, model *Model) (*iaas.CreateNetworkAreaRegionPayload, error) { - if model == nil { - return nil, fmt.Errorf("nil model") - } - - modelDefaultNameservers, err := toDefaultNameserversPayload(ctx, model) - if err != nil { - return nil, fmt.Errorf("converting default nameservers: %w", err) - } - - networkRangesPayload, err := toNetworkRangesPayload(ctx, model) - if err != nil { - return nil, fmt.Errorf("converting network ranges: %w", err) - } - - return &iaas.CreateNetworkAreaRegionPayload{ - Ipv4: &iaas.RegionalAreaIPv4{ - DefaultNameservers: modelDefaultNameservers, - DefaultPrefixLen: model.DefaultPrefixLength.ValueInt64(), - MaxPrefixLen: model.MaxPrefixLength.ValueInt64(), - MinPrefixLen: model.MinPrefixLength.ValueInt64(), - TransferNetwork: model.TransferNetwork.ValueString(), - NetworkRanges: networkRangesPayload, - }, - }, nil -} - func toUpdatePayload(ctx context.Context, model *Model, currentLabels types.Map) (*iaas.PartialUpdateNetworkAreaPayload, error) { if model == nil { return nil, fmt.Errorf("nil model") @@ -947,126 +482,3 @@ func toUpdatePayload(ctx context.Context, model *Model, currentLabels types.Map) Labels: labels, }, nil } - -// Deprecated: toRegionUpdatePayload will be removed in May 2026. Implementation won't be needed anymore because of the IaaS API v1 -> v2 migration. Func was only introduced to circumvent breaking changes. -func toRegionUpdatePayload(ctx context.Context, model *Model) (*iaas.UpdateNetworkAreaRegionPayload, error) { - if model == nil { - return nil, fmt.Errorf("nil model") - } - - modelDefaultNameservers, err := toDefaultNameserversPayload(ctx, model) - if err != nil { - return nil, fmt.Errorf("converting default nameservers: %w", err) - } - - return &iaas.UpdateNetworkAreaRegionPayload{ - Ipv4: &iaas.UpdateRegionalAreaIPv4{ - DefaultNameservers: modelDefaultNameservers, - DefaultPrefixLen: conversion.Int64ValueToPointer(model.DefaultPrefixLength), - MaxPrefixLen: conversion.Int64ValueToPointer(model.MaxPrefixLength), - MinPrefixLen: conversion.Int64ValueToPointer(model.MinPrefixLength), - }, - }, nil -} - -// Deprecated: toDefaultNameserversPayload will be removed in May 2026. Implementation won't be needed anymore because of the IaaS API v1 -> v2 migration. Func was only introduced to circumvent breaking changes. -func toDefaultNameserversPayload(_ context.Context, model *Model) ([]string, error) { - modelDefaultNameservers := []string{} - for _, ns := range model.DefaultNameservers.Elements() { - nameserverString, ok := ns.(types.String) - if !ok { - return nil, fmt.Errorf("type assertion failed") - } - modelDefaultNameservers = append(modelDefaultNameservers, nameserverString.ValueString()) - } - - return modelDefaultNameservers, nil -} - -// Deprecated: toNetworkRangesPayload will be removed in May 2026. Implementation won't be needed anymore because of the IaaS API v1 -> v2 migration. Func was only introduced to circumvent breaking changes. -func toNetworkRangesPayload(ctx context.Context, model *Model) ([]iaas.NetworkRange, error) { - if model.NetworkRanges.IsNull() || model.NetworkRanges.IsUnknown() { - return nil, nil - } - - networkRangesModel := []networkRange{} - diags := model.NetworkRanges.ElementsAs(ctx, &networkRangesModel, false) - if diags.HasError() { - return nil, core.DiagsToError(diags) - } - - if len(networkRangesModel) == 0 { - return nil, nil - } - - payload := []iaas.NetworkRange{} - for i := range networkRangesModel { - networkRangeModel := networkRangesModel[i] - payload = append(payload, iaas.NetworkRange{ - Prefix: networkRangeModel.Prefix.ValueString(), - }) - } - - return payload, nil -} - -// Deprecated: updateNetworkRanges creates and deletes network ranges so that network area ranges are the ones in the model. This was only kept to make the v1 -> v2 IaaS API migration non-breaking in the Terraform provider. -func updateNetworkRanges(ctx context.Context, organizationId, networkAreaId string, ranges []networkRange, client iaas.DefaultAPI) error { - // Get network ranges current state - currentNetworkRangesResp, err := client.ListNetworkAreaRanges(ctx, organizationId, networkAreaId, "eu01").Execute() - if err != nil { - return fmt.Errorf("error reading network area ranges: %w", err) - } - - type networkRangeState struct { - isInModel bool - isCreated bool - id string - } - - networkRangesState := make(map[string]*networkRangeState) - for _, nwRange := range ranges { - networkRangesState[nwRange.Prefix.ValueString()] = &networkRangeState{ - isInModel: true, - } - } - - for _, networkRange := range currentNetworkRangesResp.Items { - prefix := networkRange.Prefix - if _, ok := networkRangesState[prefix]; !ok { - networkRangesState[prefix] = &networkRangeState{} - } - networkRangesState[prefix].isCreated = true - networkRangesState[prefix].id = *networkRange.Id - } - - // Delete network ranges - for prefix, state := range networkRangesState { - if !state.isInModel && state.isCreated { - err := client.DeleteNetworkAreaRange(ctx, organizationId, networkAreaId, "eu01", state.id).Execute() - if err != nil { - return fmt.Errorf("deleting network area range '%v': %w", prefix, err) - } - } - } - - // Create network ranges - for prefix, state := range networkRangesState { - if state.isInModel && !state.isCreated { - payload := iaas.CreateNetworkAreaRangePayload{ - Ipv4: []iaas.NetworkRange{ - { - Prefix: prefix, - }, - }, - } - - _, err := client.CreateNetworkAreaRange(ctx, organizationId, networkAreaId, "eu01").CreateNetworkAreaRangePayload(payload).Execute() - if err != nil { - return fmt.Errorf("creating network range '%v': %w", prefix, err) - } - } - } - - return nil -} diff --git a/stackit/internal/services/iaas/networkarea/resource_test.go b/stackit/internal/services/iaas/networkarea/resource_test.go index ed1c0344d..e51addd84 100644 --- a/stackit/internal/services/iaas/networkarea/resource_test.go +++ b/stackit/internal/services/iaas/networkarea/resource_test.go @@ -2,29 +2,14 @@ package networkarea import ( "context" - "encoding/json" - "net/http" - "net/http/httptest" "testing" "github.com/google/go-cmp/cmp" - "github.com/google/uuid" - "github.com/gorilla/mux" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/stackitcloud/stackit-sdk-go/core/config" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" ) -var testOrganizationId = uuid.NewString() -var testAreaId = uuid.NewString() -var testRangeId1 = uuid.NewString() -var testRangeId2 = uuid.NewString() -var testRangeId3 = uuid.NewString() -var testRangeId4 = uuid.NewString() -var testRangeId5 = uuid.NewString() -var testRangeId2Repeated = uuid.NewString() - func TestMapFields(t *testing.T) { tests := []struct { description string @@ -38,17 +23,6 @@ func TestMapFields(t *testing.T) { state: Model{ OrganizationId: types.StringValue("oid"), NetworkAreaId: types.StringValue("naid"), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - }), - DefaultNameservers: types.ListNull(types.StringType), }, input: &iaas.NetworkArea{ Id: new("naid"), @@ -58,18 +32,7 @@ func TestMapFields(t *testing.T) { OrganizationId: types.StringValue("oid"), NetworkAreaId: types.StringValue("naid"), Name: types.StringValue(""), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - }), - DefaultNameservers: types.ListNull(types.StringType), - Labels: types.MapNull(types.StringType), + Labels: types.MapNull(types.StringType), }, isValid: true, }, @@ -78,17 +41,6 @@ func TestMapFields(t *testing.T) { state: Model{ OrganizationId: types.StringValue("oid"), NetworkAreaId: types.StringValue("naid"), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - }), - DefaultNameservers: types.ListNull(types.StringType), }, input: &iaas.NetworkArea{ Id: new("naid"), @@ -102,20 +54,9 @@ func TestMapFields(t *testing.T) { OrganizationId: types.StringValue("oid"), NetworkAreaId: types.StringValue("naid"), Name: types.StringValue("name"), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - }), Labels: types.MapValueMust(types.StringType, map[string]attr.Value{ "key": types.StringValue("value"), }), - DefaultNameservers: types.ListNull(types.StringType), }, isValid: true, }, @@ -124,17 +65,6 @@ func TestMapFields(t *testing.T) { state: Model{ OrganizationId: types.StringValue("oid"), NetworkAreaId: types.StringValue("naid"), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - }), - DefaultNameservers: types.ListNull(types.StringType), }, input: &iaas.NetworkArea{ Id: new("naid"), @@ -144,18 +74,7 @@ func TestMapFields(t *testing.T) { OrganizationId: types.StringValue("oid"), NetworkAreaId: types.StringValue("naid"), Name: types.StringValue(""), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - }), - Labels: types.MapNull(types.StringType), - DefaultNameservers: types.ListNull(types.StringType), + Labels: types.MapNull(types.StringType), }, isValid: true, }, @@ -195,243 +114,6 @@ func TestMapFields(t *testing.T) { } } -// Deprecated: Will be removed in May 2026. -func Test_MapNetworkRanges(t *testing.T) { - type args struct { - networkAreaRangesList []iaas.NetworkRange - model *Model - } - tests := []struct { - name string - args args - want *Model - wantErr bool - }{ - { - name: "model and response have ranges in different order", - args: args{ - model: &Model{ - OrganizationId: types.StringValue("oid"), - NetworkAreaId: types.StringValue("naid"), - DefaultNameservers: types.ListNull(types.StringType), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - }), - Labels: types.MapNull(types.StringType), - }, - networkAreaRangesList: []iaas.NetworkRange{ - { - Id: new(testRangeId2), - Prefix: "prefix-2", - }, - { - Id: new(testRangeId3), - Prefix: "prefix-3", - }, - { - Id: new(testRangeId1), - Prefix: "prefix-1", - }, - }, - }, - want: &Model{ - OrganizationId: types.StringValue("oid"), - NetworkAreaId: types.StringValue("naid"), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId3), - "prefix": types.StringValue("prefix-3"), - }), - }), - Labels: types.MapNull(types.StringType), - DefaultNameservers: types.ListNull(types.StringType), - }, - wantErr: false, - }, - { - name: "network_ranges_changed_outside_tf", - args: args{ - model: &Model{ - OrganizationId: types.StringValue("oid"), - NetworkAreaId: types.StringValue("naid"), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - }), - Labels: types.MapNull(types.StringType), - DefaultNameservers: types.ListNull(types.StringType), - }, - networkAreaRangesList: []iaas.NetworkRange{ - { - Id: new(testRangeId2), - Prefix: "prefix-2", - }, - { - Id: new(testRangeId3), - Prefix: "prefix-3", - }, - }, - }, - want: &Model{ - OrganizationId: types.StringValue("oid"), - NetworkAreaId: types.StringValue("naid"), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId3), - "prefix": types.StringValue("prefix-3"), - }), - }), - Labels: types.MapNull(types.StringType), - DefaultNameservers: types.ListNull(types.StringType), - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := mapNetworkRanges(context.Background(), tt.args.networkAreaRangesList, tt.args.model); (err != nil) != tt.wantErr { - t.Errorf("mapNetworkRanges() error = %v, wantErr %v", err, tt.wantErr) - } - - diff := cmp.Diff(tt.args.model, tt.want) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } - }) - } -} - -// Deprecated: Will be removed in May 2026. -func TestMapNetworkAreaRegionFields(t *testing.T) { - type args struct { - networkAreaRegionResp *iaas.RegionalArea - model *Model - } - tests := []struct { - name string - args args - want *Model - wantErr bool - }{ - { - name: "default", - args: args{ - model: &Model{ - Labels: types.MapNull(types.StringType), - }, - networkAreaRegionResp: &iaas.RegionalArea{ - Ipv4: &iaas.RegionalAreaIPv4{ - DefaultNameservers: []string{ - "nameserver1", - "nameserver2", - }, - TransferNetwork: "network", - DefaultPrefixLen: int64(20), - MaxPrefixLen: int64(22), - MinPrefixLen: int64(18), - NetworkRanges: []iaas.NetworkRange{ - { - Id: new(testRangeId1), - Prefix: "prefix-1", - }, - { - Id: new(testRangeId2), - Prefix: "prefix-2", - }, - }, - }, - }, - }, - want: &Model{ - DefaultNameservers: types.ListValueMust(types.StringType, []attr.Value{ - types.StringValue("nameserver1"), - types.StringValue("nameserver2"), - }), - TransferNetwork: types.StringValue("network"), - DefaultPrefixLength: types.Int64Value(20), - MaxPrefixLength: types.Int64Value(22), - MinPrefixLength: types.Int64Value(18), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId1), - "prefix": types.StringValue("prefix-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringValue(testRangeId2), - "prefix": types.StringValue("prefix-2"), - }), - }), - - Labels: types.MapNull(types.StringType), - }, - wantErr: false, - }, - { - name: "model is nil", - args: args{ - model: nil, - networkAreaRegionResp: &iaas.RegionalArea{}, - }, - want: nil, - wantErr: true, - }, - { - name: "network area region response is nil", - args: args{ - model: &Model{ - DefaultNameservers: types.ListNull(types.StringType), - NetworkRanges: types.ListNull(types.ObjectType{AttrTypes: networkRangeTypes}), - Labels: types.MapNull(types.StringType), - }, - networkAreaRegionResp: nil, - }, - want: &Model{ - DefaultNameservers: types.ListNull(types.StringType), - NetworkRanges: types.ListNull(types.ObjectType{AttrTypes: networkRangeTypes}), - Labels: types.MapNull(types.StringType), - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := mapNetworkAreaRegionFields(context.Background(), tt.args.networkAreaRegionResp, tt.args.model); (err != nil) != tt.wantErr { - t.Errorf("mapNetworkAreaRegionFields() error = %v, wantErr %v", err, tt.wantErr) - } - - diff := cmp.Diff(tt.args.model, tt.want) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } - }) - } -} - func TestToCreatePayload(t *testing.T) { tests := []struct { description string @@ -475,86 +157,6 @@ func TestToCreatePayload(t *testing.T) { } } -// Deprecated: Will be removed in May 2026. -func TestToRegionCreatePayload(t *testing.T) { - type args struct { - model *Model - } - tests := []struct { - name string - args args - want *iaas.CreateNetworkAreaRegionPayload - wantErr bool - }{ - { - name: "default_ok", - args: args{ - model: &Model{ - DefaultNameservers: types.ListValueMust(types.StringType, []attr.Value{ - types.StringValue("ns1"), - types.StringValue("ns2"), - }), - NetworkRanges: types.ListValueMust(types.ObjectType{AttrTypes: networkRangeTypes}, []attr.Value{ - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringUnknown(), - "prefix": types.StringValue("pr-1"), - }), - types.ObjectValueMust(networkRangeTypes, map[string]attr.Value{ - "network_range_id": types.StringUnknown(), - "prefix": types.StringValue("pr-2"), - }), - }), - TransferNetwork: types.StringValue("network"), - DefaultPrefixLength: types.Int64Value(20), - MaxPrefixLength: types.Int64Value(22), - MinPrefixLength: types.Int64Value(18), - }, - }, - want: &iaas.CreateNetworkAreaRegionPayload{ - Ipv4: &iaas.RegionalAreaIPv4{ - DefaultNameservers: []string{ - "ns1", - "ns2", - }, - NetworkRanges: []iaas.NetworkRange{ - { - Prefix: "pr-1", - }, - { - Prefix: "pr-2", - }, - }, - TransferNetwork: "network", - DefaultPrefixLen: int64(20), - MaxPrefixLen: int64(22), - MinPrefixLen: int64(18), - }, - }, - }, - { - name: "model is nil", - args: args{ - model: nil, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := toRegionCreatePayload(context.Background(), tt.args.model) - if (err != nil) != tt.wantErr { - t.Errorf("toRegionCreatePayload() error = %v, wantErr %v", err, tt.wantErr) - return - } - diff := cmp.Diff(got, tt.want) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } - }) - } -} - func TestToUpdatePayload(t *testing.T) { tests := []struct { description string @@ -597,532 +199,3 @@ func TestToUpdatePayload(t *testing.T) { }) } } - -// Deprecated: Will be removed in May 2026. -func TestToRegionUpdatePayload(t *testing.T) { - type args struct { - model *Model - } - tests := []struct { - name string - args args - want *iaas.UpdateNetworkAreaRegionPayload - wantErr bool - }{ - { - name: "default_ok", - args: args{ - model: &Model{ - DefaultNameservers: types.ListValueMust(types.StringType, []attr.Value{ - types.StringValue("ns1"), - types.StringValue("ns2"), - }), - DefaultPrefixLength: types.Int64Value(22), - MaxPrefixLength: types.Int64Value(24), - MinPrefixLength: types.Int64Value(20), - }, - }, - want: &iaas.UpdateNetworkAreaRegionPayload{ - Ipv4: &iaas.UpdateRegionalAreaIPv4{ - DefaultNameservers: []string{ - "ns1", - "ns2", - }, - DefaultPrefixLen: new(int64(22)), - MaxPrefixLen: new(int64(24)), - MinPrefixLen: new(int64(20)), - }, - }, - }, - { - name: "model is nil", - args: args{ - model: nil, - }, - want: nil, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := toRegionUpdatePayload(context.Background(), tt.args.model) - if (err != nil) != tt.wantErr { - t.Errorf("toRegionUpdatePayload() error = %v, wantErr %v", err, tt.wantErr) - return - } - diff := cmp.Diff(got, tt.want) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } - }) - } -} - -func TestUpdateNetworkRanges(t *testing.T) { - getAllNetworkRangesResp := iaas.NetworkRangeListResponse{ - Items: []iaas.NetworkRange{ - { - Prefix: "pr-1", - Id: new(testRangeId1), - }, - { - Prefix: "pr-2", - Id: new(testRangeId2), - }, - { - Prefix: "pr-3", - Id: new(testRangeId3), - }, - { - Prefix: "pr-2", - Id: new(testRangeId2Repeated), - }, - }, - } - getAllNetworkRangesRespBytes, err := json.Marshal(getAllNetworkRangesResp) - if err != nil { - t.Fatalf("Failed to marshal get all network ranges response: %v", err) - } - - // This is the response used whenever an API returns a failure response - failureRespBytes := []byte("{\"message\": \"Something bad happened\"") - - tests := []struct { - description string - networkRanges []networkRange - ipv4 []iaas.NetworkRange - getAllNetworkRangesFails bool - createNetworkRangesFails bool - deleteNetworkRangesFails bool - isValid bool - expectedNetworkRangesStates map[string]bool // Keys are prefix; value is true if prefix should exist at the end, false if should be deleted - }{ - { - description: "no_changes", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId2), - Prefix: types.StringValue("pr-2"), - }, - { - NetworkRangeId: types.StringValue(testRangeId3), - Prefix: types.StringValue("pr-3"), - }, - }, - expectedNetworkRangesStates: map[string]bool{ - "pr-1": true, - "pr-2": true, - "pr-3": true, - }, - isValid: true, - }, - { - description: "create_network_ranges", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId2), - Prefix: types.StringValue("pr-2"), - }, - { - NetworkRangeId: types.StringValue(testRangeId3), - Prefix: types.StringValue("pr-3"), - }, - { - NetworkRangeId: types.StringValue(testRangeId4), - Prefix: types.StringValue("pr-4"), - }, - }, - expectedNetworkRangesStates: map[string]bool{ - "pr-1": true, - "pr-2": true, - "pr-3": true, - "pr-4": true, - }, - isValid: true, - }, - { - description: "delete_network_ranges", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId3), - Prefix: types.StringValue("pr-3"), - }, - }, - expectedNetworkRangesStates: map[string]bool{ - "pr-1": true, - "pr-2": false, - "pr-3": true, - }, - isValid: true, - }, - { - description: "multiple_changes", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId3), - Prefix: types.StringValue("pr-3"), - }, - { - NetworkRangeId: types.StringValue(testRangeId4), - Prefix: types.StringValue("pr-4"), - }, - { - NetworkRangeId: types.StringValue(testRangeId5), - Prefix: types.StringValue("pr-5"), - }, - }, - expectedNetworkRangesStates: map[string]bool{ - "pr-1": true, - "pr-2": false, - "pr-3": true, - "pr-4": true, - "pr-5": true, - }, - isValid: true, - }, - { - description: "multiple_changes_repetition", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId3), - Prefix: types.StringValue("pr-3"), - }, - { - NetworkRangeId: types.StringValue(testRangeId4), - Prefix: types.StringValue("pr-4"), - }, - { - NetworkRangeId: types.StringValue(testRangeId5), - Prefix: types.StringValue("pr-5"), - }, - { - NetworkRangeId: types.StringValue(testRangeId5), - Prefix: types.StringValue("pr-5"), - }, - }, - expectedNetworkRangesStates: map[string]bool{ - "pr-1": true, - "pr-2": false, - "pr-3": true, - "pr-4": true, - "pr-5": true, - }, - isValid: true, - }, - { - description: "multiple_changes_2", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId4), - Prefix: types.StringValue("pr-4"), - }, - { - NetworkRangeId: types.StringValue(testRangeId5), - Prefix: types.StringValue("pr-5"), - }, - }, - expectedNetworkRangesStates: map[string]bool{ - "pr-1": false, - "pr-2": false, - "pr-3": false, - "pr-4": true, - "pr-5": true, - }, - isValid: true, - }, - { - description: "multiple_changes_3", - networkRanges: []networkRange{}, - expectedNetworkRangesStates: map[string]bool{ - "pr-1": false, - "pr-2": false, - "pr-3": false, - }, - isValid: true, - }, - { - description: "get_fails", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId2), - Prefix: types.StringValue("pr-2"), - }, - { - NetworkRangeId: types.StringValue(testRangeId3), - Prefix: types.StringValue("pr-3"), - }, - }, - getAllNetworkRangesFails: true, - isValid: false, - }, - { - description: "create_fails_1", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId2), - Prefix: types.StringValue("pr-2"), - }, - { - NetworkRangeId: types.StringValue(testRangeId3), - Prefix: types.StringValue("pr-3"), - }, - { - NetworkRangeId: types.StringValue(testRangeId4), - Prefix: types.StringValue("pr-4"), - }, - }, - createNetworkRangesFails: true, - isValid: false, - }, - { - description: "create_fails_2", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId2), - Prefix: types.StringValue("pr-2"), - }, - }, - createNetworkRangesFails: true, - expectedNetworkRangesStates: map[string]bool{ - "pr-1": true, - "pr-2": true, - "pr-3": false, - }, - isValid: true, - }, - { - description: "delete_fails_1", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId2), - Prefix: types.StringValue("pr-2"), - }, - }, - deleteNetworkRangesFails: true, - isValid: false, - }, - { - description: "delete_fails_2", - networkRanges: []networkRange{ - { - NetworkRangeId: types.StringValue(testRangeId1), - Prefix: types.StringValue("pr-1"), - }, - { - NetworkRangeId: types.StringValue(testRangeId2), - Prefix: types.StringValue("pr-2"), - }, - { - NetworkRangeId: types.StringValue(testRangeId3), - Prefix: types.StringValue("pr-3"), - }, - { - NetworkRangeId: types.StringValue(testRangeId4), - Prefix: types.StringValue("pr-4"), - }, - }, - deleteNetworkRangesFails: true, - expectedNetworkRangesStates: map[string]bool{ - "pr-1": true, - "pr-2": true, - "pr-3": true, - "pr-4": true, - }, - isValid: true, - }, - } - - for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - // Will be compared to tt.expectedNetworkRangesStates at the end - networkRangesStates := make(map[string]bool) - networkRangesStates["pr-1"] = true - networkRangesStates["pr-2"] = true - networkRangesStates["pr-3"] = true - - // Handler for getting all network ranges - getAllNetworkRangesHandler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("Content-Type", "application/json") - if tt.getAllNetworkRangesFails { - w.WriteHeader(http.StatusInternalServerError) - _, err := w.Write(failureRespBytes) - if err != nil { - t.Errorf("Get all network ranges handler: failed to write bad response: %v", err) - } - return - } - - _, err := w.Write(getAllNetworkRangesRespBytes) - if err != nil { - t.Errorf("Get all network ranges handler: failed to write response: %v", err) - } - }) - - // Handler for creating network range - createNetworkRangeHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - decoder := json.NewDecoder(r.Body) - var payload iaas.CreateNetworkAreaRangePayload - err := decoder.Decode(&payload) - if err != nil { - t.Errorf("Create network range handler: failed to parse payload") - return - } - if payload.Ipv4 == nil { - t.Errorf("Create network range handler: nil Ipv4") - return - } - ipv4 := payload.Ipv4 - - for _, networkRange := range ipv4 { - prefix := networkRange.Prefix - if prefixExists, prefixWasCreated := networkRangesStates[prefix]; prefixWasCreated && prefixExists { - t.Errorf("Create network range handler: attempted to create range '%v' that already exists", payload.Ipv4) - return - } - w.Header().Set("Content-Type", "application/json") - if tt.createNetworkRangesFails { - w.WriteHeader(http.StatusInternalServerError) - _, err := w.Write(failureRespBytes) - if err != nil { - t.Errorf("Create network ranges handler: failed to write bad response: %v", err) - } - return - } - - resp := iaas.NetworkRangeListResponse{ - Items: []iaas.NetworkRange{ - { - Prefix: "prefix", - Id: new("id-range"), - }, - }, - } - respBytes, err := json.Marshal(resp) - if err != nil { - t.Errorf("Create network range handler: failed to marshal response: %v", err) - return - } - _, err = w.Write(respBytes) - if err != nil { - t.Errorf("Create network range handler: failed to write response: %v", err) - } - networkRangesStates[prefix] = true - } - }) - - // Handler for deleting Network range - deleteNetworkRangeHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - networkRangeId, ok := vars["networkRangeId"] - if !ok { - t.Errorf("Delete network range handler: no range ID") - return - } - - var prefix string - for _, rangeItem := range getAllNetworkRangesResp.Items { - if *rangeItem.Id == networkRangeId { - prefix = rangeItem.Prefix - } - } - prefixExists, prefixWasCreated := networkRangesStates[prefix] - if !prefixWasCreated { - t.Errorf("Delete network range handler: attempted to delete range '%v' that wasn't created", prefix) - return - } - if prefixWasCreated && !prefixExists { - t.Errorf("Delete network range handler: attempted to delete range '%v' that was already deleted", prefix) - return - } - - w.Header().Set("Content-Type", "application/json") - if tt.deleteNetworkRangesFails { - w.WriteHeader(http.StatusInternalServerError) - _, err := w.Write(failureRespBytes) - if err != nil { - t.Errorf("Delete network range handler: failed to write bad response: %v", err) - } - return - } - - _, err = w.Write([]byte("{}")) - if err != nil { - t.Errorf("Delete network range handler: failed to write response: %v", err) - } - networkRangesStates[prefix] = false - }) - - // Setup server and client - router := mux.NewRouter() - router.HandleFunc("/v2/organizations/{organizationId}/network-areas/{areaId}/regions/{region}/network-ranges", func(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case http.MethodGet: - getAllNetworkRangesHandler(w, r) - case http.MethodPost: - createNetworkRangeHandler(w, r) - } - }) - router.HandleFunc("/v2/organizations/{organizationId}/network-areas/{areaId}/regions/{region}/network-ranges/{networkRangeId}", deleteNetworkRangeHandler) - mockedServer := httptest.NewServer(router) - defer mockedServer.Close() - client, err := iaas.NewAPIClient( - config.WithEndpoint(mockedServer.URL), - config.WithoutAuthentication(), - ) - if err != nil { - t.Fatalf("Failed to initialize client: %v", err) - } - - // Run test - err = updateNetworkRanges(context.Background(), testOrganizationId, testAreaId, tt.networkRanges, client.DefaultAPI) - if !tt.isValid && err == nil { - t.Fatalf("Should have failed") - } - if tt.isValid && err != nil { - t.Fatalf("Should not have failed: %v", err) - } - if tt.isValid { - diff := cmp.Diff(networkRangesStates, tt.expectedNetworkRangesStates) - if diff != "" { - t.Fatalf("Network range states do not match: %s", diff) - } - } - }) - } -} diff --git a/stackit/internal/services/iaas/testdata/resource-network-area-max.tf b/stackit/internal/services/iaas/testdata/resource-network-area-max.tf index 288fb0d01..2a241128e 100644 --- a/stackit/internal/services/iaas/testdata/resource-network-area-max.tf +++ b/stackit/internal/services/iaas/testdata/resource-network-area-max.tf @@ -1,49 +1,14 @@ variable "organization_id" {} variable "name" {} -variable "transfer_network" {} -variable "network_ranges_prefix" {} -variable "default_nameservers" {} -variable "default_prefix_length" {} -variable "max_prefix_length" {} -variable "min_prefix_length" {} -variable "route_destination_type" {} -variable "route_destination_value" {} -variable "route_next_hop_type" {} -variable "route_next_hop_value" {} variable "label" {} resource "stackit_network_area" "network_area" { organization_id = var.organization_id name = var.name - network_ranges = [ - { - prefix = var.network_ranges_prefix - } - ] - transfer_network = var.transfer_network - default_nameservers = [var.default_nameservers] - default_prefix_length = var.default_prefix_length - max_prefix_length = var.max_prefix_length - min_prefix_length = var.min_prefix_length labels = { "acc-test" : var.label } } -resource "stackit_network_area_route" "network_area_route" { - organization_id = stackit_network_area.network_area.organization_id - network_area_id = stackit_network_area.network_area.network_area_id - destination = { - type = var.route_destination_type - value = var.route_destination_value - } - next_hop = { - type = var.route_next_hop_type - value = var.route_next_hop_value - } - labels = { - "acc-test" : var.label - } -} \ No newline at end of file diff --git a/stackit/internal/services/iaas/testdata/resource-network-area-region-max.tf b/stackit/internal/services/iaas/testdata/resource-network-area-region-max.tf index 1d207e455..b7ed99851 100644 --- a/stackit/internal/services/iaas/testdata/resource-network-area-region-max.tf +++ b/stackit/internal/services/iaas/testdata/resource-network-area-region-max.tf @@ -7,6 +7,11 @@ variable "default_prefix_length" {} variable "min_prefix_length" {} variable "max_prefix_length" {} variable "default_nameservers" {} +variable "route_destination_type" {} +variable "route_destination_value" {} +variable "route_next_hop_type" {} +variable "route_next_hop_value" {} +variable "label" {} resource "stackit_network_area" "network_area" { organization_id = var.organization_id @@ -31,3 +36,19 @@ resource "stackit_network_area_region" "network_area_region" { ] } } + +resource "stackit_network_area_route" "network_area_route" { + organization_id = stackit_network_area.network_area.organization_id + network_area_id = stackit_network_area_region.network_area_region.network_area_id + destination = { + type = var.route_destination_type + value = var.route_destination_value + } + next_hop = { + type = var.route_next_hop_type + value = var.route_next_hop_value + } + labels = { + "acc-test" : var.label + } +} From ae5d172c9ff1cc3c9bd03afeff647e3522efe5d9 Mon Sep 17 00:00:00 2001 From: GokceGK Date: Tue, 11 Aug 2026 12:38:07 +0200 Subject: [PATCH 2/2] chore(iaas): remove obsolete modifyPlan function relates to STACKITTPR-694 --- .../services/iaas/networkarea/resource.go | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/stackit/internal/services/iaas/networkarea/resource.go b/stackit/internal/services/iaas/networkarea/resource.go index 3340e3cdd..5307fdc62 100644 --- a/stackit/internal/services/iaas/networkarea/resource.go +++ b/stackit/internal/services/iaas/networkarea/resource.go @@ -37,7 +37,6 @@ var ( _ resource.Resource = &networkAreaResource{} _ resource.ResourceWithConfigure = &networkAreaResource{} _ resource.ResourceWithImportState = &networkAreaResource{} - _ resource.ResourceWithModifyPlan = &networkAreaResource{} ) type Model struct { @@ -60,29 +59,6 @@ type networkAreaResource struct { resourceManagerClient *resourcemanager.APIClient } -func (r *networkAreaResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { // nolint:gocritic // function signature required by Terraform - var configModel Model - // skip initial empty configuration to avoid follow-up errors - if req.Config.Raw.IsNull() { - return - } - resp.Diagnostics.Append(req.Config.Get(ctx, &configModel)...) - if resp.Diagnostics.HasError() { - return - } - - var planModel Model - resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...) - if resp.Diagnostics.HasError() { - return - } - - resp.Diagnostics.Append(resp.Plan.Set(ctx, planModel)...) - if resp.Diagnostics.HasError() { - return - } -} - // Metadata returns the resource type name. func (r *networkAreaResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_network_area"