diff --git a/docs/resources/loadbalancer.md b/docs/resources/loadbalancer.md index 9d0136d7..7a6c9125 100644 --- a/docs/resources/loadbalancer.md +++ b/docs/resources/loadbalancer.md @@ -119,6 +119,7 @@ resource "stackit_loadbalancer" "example" { ### Required +- `external_address` (String) External Load Balancer IP address where this Load Balancer is exposed. - `listeners` (Attributes List) List of all listeners which will accept traffic. Limited to 20. (see [below for nested schema](#nestedatt--listeners)) - `name` (String) Load balancer name. - `networks` (Attributes List) List of networks that listeners and targets reside in. (see [below for nested schema](#nestedatt--networks)) @@ -127,7 +128,6 @@ resource "stackit_loadbalancer" "example" { ### Optional -- `external_address` (String) External Load Balancer IP address where this Load Balancer is exposed. - `options` (Attributes) Defines any optional functionality you want to have enabled on your load balancer. (see [below for nested schema](#nestedatt--options)) - `region` (String) The resource region. If not defined, the provider region is used. @@ -139,13 +139,16 @@ resource "stackit_loadbalancer" "example" { ### Nested Schema for `listeners` +Required: + +- `port` (Number) Port number where we listen for traffic. +- `protocol` (String) Protocol is the highest network protocol we understand to load balance. Supported values are: `PROTOCOL_UNSPECIFIED`, `PROTOCOL_TCP`, `PROTOCOL_UDP`, `PROTOCOL_TCP_PROXY`, `PROTOCOL_TLS_PASSTHROUGH`. +- `target_pool` (String) Reference target pool by target pool name. + Optional: - `display_name` (String) -- `port` (Number) Port number where we listen for traffic. -- `protocol` (String) Protocol is the highest network protocol we understand to load balance. Supported values are: `PROTOCOL_UNSPECIFIED`, `PROTOCOL_TCP`, `PROTOCOL_UDP`, `PROTOCOL_TCP_PROXY`, `PROTOCOL_TLS_PASSTHROUGH`. - `server_name_indicators` (Attributes List) A list of domain names to match in order to pass TLS traffic to the target pool in the current listener (see [below for nested schema](#nestedatt--listeners--server_name_indicators)) -- `target_pool` (String) Reference target pool by target pool name. ### Nested Schema for `listeners.server_name_indicators` @@ -162,9 +165,6 @@ Optional: Required: - `network_id` (String) Openstack network ID. - -Optional: - - `role` (String) The role defines how the load balancer is using the network. Supported values are: `ROLE_UNSPECIFIED`, `ROLE_LISTENERS_AND_TARGETS`, `ROLE_LISTENERS`, `ROLE_TARGETS`. diff --git a/stackit/internal/services/loadbalancer/loadbalancer/resource.go b/stackit/internal/services/loadbalancer/loadbalancer/resource.go index 79d36386..3496b709 100644 --- a/stackit/internal/services/loadbalancer/loadbalancer/resource.go +++ b/stackit/internal/services/loadbalancer/loadbalancer/resource.go @@ -318,7 +318,7 @@ The example below creates the supporting infrastructure using the STACKIT Terraf }, "external_address": schema.StringAttribute{ Description: descriptions["external_address"], - Optional: true, + Required: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), }, @@ -345,8 +345,7 @@ The example below creates the supporting infrastructure using the STACKIT Terraf }, "port": schema.Int64Attribute{ Description: descriptions["port"], - Optional: true, - Computed: true, + Required: true, PlanModifiers: []planmodifier.Int64{ int64planmodifier.RequiresReplace(), int64planmodifier.UseStateForUnknown(), @@ -354,8 +353,7 @@ The example below creates the supporting infrastructure using the STACKIT Terraf }, "protocol": schema.StringAttribute{ Description: descriptions["protocol"], - Optional: true, - Computed: true, + Required: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), stringplanmodifier.UseStateForUnknown(), @@ -378,8 +376,7 @@ The example below creates the supporting infrastructure using the STACKIT Terraf }, "target_pool": schema.StringAttribute{ Description: descriptions["target_pool"], - Optional: true, - Computed: true, + Required: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), stringplanmodifier.UseStateForUnknown(), @@ -424,8 +421,7 @@ The example below creates the supporting infrastructure using the STACKIT Terraf }, "role": schema.StringAttribute{ Description: descriptions["role"], - Optional: true, - Computed: true, + Required: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), stringplanmodifier.UseStateForUnknown(), diff --git a/stackit/internal/services/loadbalancer/loadbalancer_acc_test.go b/stackit/internal/services/loadbalancer/loadbalancer_acc_test.go index 6f79ec40..d99854b7 100644 --- a/stackit/internal/services/loadbalancer/loadbalancer_acc_test.go +++ b/stackit/internal/services/loadbalancer/loadbalancer_acc_test.go @@ -2,271 +2,136 @@ package loadbalancer_test import ( "context" + _ "embed" "fmt" "strings" "testing" + "github.com/hashicorp/terraform-plugin-testing/config" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer/wait" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" - "github.com/stackitcloud/stackit-sdk-go/core/config" + "maps" + + stackitSdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/core/utils" "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil" ) -// Instance resource data -var loadBalancerResource = map[string]string{ - "project_id": testutil.ProjectId, - "name": fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum)), - "target_pool_name": "example-target-pool", - "target_port": "5432", - "target_port_updated": "5431", - "target_display_name": "example-target", - "healthy_threshold": "3", - "interval": "10s", - "interval_jitter": "5s", - "timeout": "10s", - "unhealthy_threshold": "3", - "use_source_ip_address": "true", - "listener_display_name": "example-listener", - "listener_port": "5432", - "listener_protocol": "PROTOCOL_TLS_PASSTHROUGH", - "network_role": "ROLE_LISTENERS_AND_TARGETS", - "private_network_only": "false", +//go:embed testfiles/resource-min.tf +var resourceMinConfig string + +//go:embed testfiles/resource-max.tf +var resourceMaxConfig string + +var testConfigVarsMin = config.Variables{ + "project_id": config.StringVariable(testutil.ProjectId), + "network_name": config.StringVariable(fmt.Sprintf("tf-acc-n%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))), + "server_name": config.StringVariable(fmt.Sprintf("tf-acc-s%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))), + "loadbalancer_name": config.StringVariable(fmt.Sprintf("tf-acc-l%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))), + "target_pool_name": config.StringVariable("example-target-pool"), + "target_port": config.StringVariable("5432"), + "target_display_name": config.StringVariable("example-target"), + "listener_port": config.StringVariable("5432"), + "listener_protocol": config.StringVariable("PROTOCOL_TLS_PASSTHROUGH"), + "network_role": config.StringVariable("ROLE_LISTENERS_AND_TARGETS"), + + "obs_display_name": config.StringVariable("obs-user"), + "obs_username": config.StringVariable("obs-username"), + "obs_password": config.StringVariable("obs-password1"), } -// Network resource data -var networkResource = map[string]string{ - "project_id": testutil.ProjectId, - "name": fmt.Sprintf("acc-test-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)), - "nameserver0": "8.8.8.8", - "ipv4_prefix": "192.168.0.0/25", - "routed": "true", +var testConfigVarsMax = config.Variables{ + "project_id": config.StringVariable(testutil.ProjectId), + "network_name": config.StringVariable(fmt.Sprintf("tf-acc-n%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))), + "server_name": config.StringVariable(fmt.Sprintf("tf-acc-s%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))), + "loadbalancer_name": config.StringVariable(fmt.Sprintf("tf-acc-l%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))), + "target_pool_name": config.StringVariable("example-target-pool"), + "target_port": config.StringVariable("5432"), + "target_display_name": config.StringVariable("example-target"), + "listener_port": config.StringVariable("5432"), + "listener_protocol": config.StringVariable("PROTOCOL_TLS_PASSTHROUGH"), + "network_role": config.StringVariable("ROLE_LISTENERS_AND_TARGETS"), + + "listener_display_name": config.StringVariable("example-listener"), + "listener_server_name_indicators": config.StringVariable("acc-test.runs.onstackit.cloud"), + "healthy_threshold": config.StringVariable("3"), + "health_interval": config.StringVariable("10s"), + "health_interval_jitter": config.StringVariable("5s"), + "health_timeout": config.StringVariable("10s"), + "unhealthy_threshold": config.StringVariable("3"), + "use_source_ip_address": config.StringVariable("true"), + "private_network_only": config.StringVariable("false"), + "acl": config.StringVariable("192.168.0.0/24"), } -// Server resource data -var serverResource = map[string]string{ - "project_id": testutil.ProjectId, - "availability_zone": "eu01-1", - "size": "32", - "source_type": "image", - "source_id": testutil.IaaSImageId, - "name": fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlpha)), - "machine_type": "t1.1", - "user_data": "#!/bin/bash", - "delete_on_termination": "true", +func configVarsMinUpdated() config.Variables { + tempConfig := make(config.Variables, len(testConfigVarsMin)) + maps.Copy(tempConfig, testConfigVarsMin) + tempConfig["target_port"] = config.StringVariable("5431") + return tempConfig } -// Public ip resource data -var publicIpResource = map[string]string{ - "project_id": testutil.ProjectId, - "network_interface_id": "stackit_network_interface.network_interface.network_interface_id", +func configVarsMaxUpdated() config.Variables { + tempConfig := make(config.Variables, len(testConfigVarsMax)) + maps.Copy(tempConfig, testConfigVarsMax) + tempConfig["target_port"] = config.StringVariable("5431") + return tempConfig } -func publicIpResourceConfig() string { - return fmt.Sprintf(` - resource "stackit_public_ip" "public_ip" { - project_id = "%s" - network_interface_id = %s - lifecycle { - ignore_changes = [ - network_interface_id - ] - } - } - `, - publicIpResource["project_id"], - publicIpResource["network_interface_id"], - ) -} - -func networkResourceConfig() string { - return fmt.Sprintf(` - resource "stackit_network" "network" { - project_id = "%s" - name = "%s" - ipv4_nameservers = ["%s"] - ipv4_prefix = "%s" - routed = "%s" - } - `, - networkResource["project_id"], - networkResource["name"], - networkResource["nameserver0"], - networkResource["ipv4_prefix"], - networkResource["routed"], - ) -} - -func networkInterfaceResourceConfig() string { - return ` - resource "stackit_network_interface" "network_interface" { - project_id = stackit_network.network.project_id - network_id = stackit_network.network.network_id - name = "name" - } - ` -} - -// server config -func serverResourceConfig() string { - return fmt.Sprintf(` - resource "stackit_server" "server" { - project_id = "%s" - availability_zone = "%s" - name = "%s" - machine_type = "%s" - boot_volume = { - size = %s - source_type = "%s" - source_id = "%s" - delete_on_termination = "%s" - } - network_interfaces = [stackit_network_interface.network_interface.network_interface_id] - user_data = "%s" - } - `, - serverResource["project_id"], - serverResource["availability_zone"], - serverResource["name"], - serverResource["machine_type"], - serverResource["size"], - serverResource["source_type"], - serverResource["source_id"], - serverResource["delete_on_termination"], - serverResource["user_data"], - ) -} - -// loadbalancer config -func loadbalancerResourceConfig(targetPort string) string { - return fmt.Sprintf(` - %s - - %s - - %s - - %s - - %s - - resource "stackit_loadbalancer" "loadbalancer" { - project_id = "%s" - name = "%s" - target_pools = [ - { - name = "%s" - target_port = %s - targets = [ - { - display_name = "%s" - ip = stackit_network_interface.network_interface.ipv4 - } - ] - active_health_check = { - healthy_threshold = %s - interval = "%s" - interval_jitter = "%s" - timeout = "%s" - unhealthy_threshold = %s - } - } - ] - listeners = [ - { - display_name = "%s" - port = %s - protocol = "%s" - target_pool = "%s" - } - ] - networks = [ - { - network_id = stackit_network.network.network_id - role = "%s" - } - ] - external_address = stackit_public_ip.public_ip.ip - options = { - private_network_only = %s - } - } - `, - testutil.LoadBalancerProviderConfig(), - networkResourceConfig(), - networkInterfaceResourceConfig(), - publicIpResourceConfig(), - serverResourceConfig(), - loadBalancerResource["project_id"], - loadBalancerResource["name"], - loadBalancerResource["target_pool_name"], - targetPort, - loadBalancerResource["target_display_name"], - loadBalancerResource["healthy_threshold"], - loadBalancerResource["interval"], - loadBalancerResource["interval_jitter"], - loadBalancerResource["timeout"], - loadBalancerResource["unhealthy_threshold"], - loadBalancerResource["listener_display_name"], - loadBalancerResource["listener_port"], - loadBalancerResource["listener_protocol"], - loadBalancerResource["target_pool_name"], - loadBalancerResource["network_role"], - loadBalancerResource["private_network_only"], - ) -} - -func TestAccLoadBalancerResource(t *testing.T) { - resource.Test(t, resource.TestCase{ +func TestAccLoadBalancerResourceMin(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories, CheckDestroy: testAccCheckLoadBalancerDestroy, Steps: []resource.TestStep{ // Creation { - Config: loadbalancerResourceConfig(loadBalancerResource["target_port"]), + ConfigVariables: testConfigVarsMin, + Config: testutil.LoadBalancerProviderConfig() + resourceMinConfig, Check: resource.ComposeAggregateTestCheckFunc( // Load balancer instance - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "project_id", loadBalancerResource["project_id"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "name", loadBalancerResource["name"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.name", loadBalancerResource["target_pool_name"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.target_port", loadBalancerResource["target_port"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.display_name", loadBalancerResource["target_display_name"]), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "name", testutil.ConvertConfigVariable(testConfigVarsMin["loadbalancer_name"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.name", testutil.ConvertConfigVariable(testConfigVarsMin["target_pool_name"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.target_port", testutil.ConvertConfigVariable(testConfigVarsMin["target_port"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.display_name", testutil.ConvertConfigVariable(testConfigVarsMin["target_display_name"])), resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.ip"), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.healthy_threshold", loadBalancerResource["healthy_threshold"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.interval", loadBalancerResource["interval"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.interval_jitter", loadBalancerResource["interval_jitter"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.timeout", loadBalancerResource["timeout"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.unhealthy_threshold", loadBalancerResource["unhealthy_threshold"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.display_name", loadBalancerResource["listener_display_name"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.port", loadBalancerResource["listener_port"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.protocol", loadBalancerResource["listener_protocol"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.target_pool", loadBalancerResource["target_pool_name"]), + resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "listeners.0.display_name"), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.port", testutil.ConvertConfigVariable(testConfigVarsMin["listener_port"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.protocol", testutil.ConvertConfigVariable(testConfigVarsMin["listener_protocol"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.target_pool", testutil.ConvertConfigVariable(testConfigVarsMin["target_pool_name"])), resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "networks.0.network_id"), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "networks.0.role", loadBalancerResource["network_role"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "options.private_network_only", loadBalancerResource["private_network_only"]), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "networks.0.role", testutil.ConvertConfigVariable(testConfigVarsMin["network_role"])), + resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "external_address"), + + // observability credentials + resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.obs_credential", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])), + resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.obs_credential", "display_name", testutil.ConvertConfigVariable(testConfigVarsMin["obs_display_name"])), + resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.obs_credential", "username", testutil.ConvertConfigVariable(testConfigVarsMin["obs_username"])), + resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.obs_credential", "password", testutil.ConvertConfigVariable(testConfigVarsMin["obs_password"])), ), }, // Data source { + ConfigVariables: testConfigVarsMin, Config: fmt.Sprintf(` - %s + %s - data "stackit_loadbalancer" "loadbalancer" { - project_id = stackit_loadbalancer.loadbalancer.project_id - name = stackit_loadbalancer.loadbalancer.name - } - `, - loadbalancerResourceConfig(loadBalancerResource["target_port"]), + data "stackit_loadbalancer" "loadbalancer" { + project_id = stackit_loadbalancer.loadbalancer.project_id + name = stackit_loadbalancer.loadbalancer.name + } + `, + testutil.LoadBalancerProviderConfig()+resourceMinConfig, ), Check: resource.ComposeAggregateTestCheckFunc( // Load balancer instance - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "project_id", loadBalancerResource["project_id"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "name", loadBalancerResource["name"]), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "name", testutil.ConvertConfigVariable(testConfigVarsMin["loadbalancer_name"])), resource.TestCheckResourceAttrPair( "data.stackit_loadbalancer.loadbalancer", "project_id", "stackit_loadbalancer.loadbalancer", "project_id", @@ -275,27 +140,22 @@ func TestAccLoadBalancerResource(t *testing.T) { "data.stackit_loadbalancer.loadbalancer", "name", "stackit_loadbalancer.loadbalancer", "name", ), - - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.name", loadBalancerResource["target_pool_name"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.target_port", loadBalancerResource["target_port"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.display_name", loadBalancerResource["target_display_name"]), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.name", testutil.ConvertConfigVariable(testConfigVarsMin["target_pool_name"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.target_port", testutil.ConvertConfigVariable(testConfigVarsMin["target_port"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.display_name", testutil.ConvertConfigVariable(testConfigVarsMin["target_display_name"])), resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.ip"), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.healthy_threshold", loadBalancerResource["healthy_threshold"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.interval", loadBalancerResource["interval"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.interval_jitter", loadBalancerResource["interval_jitter"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.timeout", loadBalancerResource["timeout"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.unhealthy_threshold", loadBalancerResource["unhealthy_threshold"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.display_name", loadBalancerResource["listener_display_name"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.port", loadBalancerResource["listener_port"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.protocol", loadBalancerResource["listener_protocol"]), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.target_pool", loadBalancerResource["target_pool_name"]), + resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "listeners.0.display_name"), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.port", testutil.ConvertConfigVariable(testConfigVarsMin["listener_port"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.protocol", testutil.ConvertConfigVariable(testConfigVarsMin["listener_protocol"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.target_pool", testutil.ConvertConfigVariable(testConfigVarsMin["target_pool_name"])), resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "networks.0.network_id"), - resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "networks.0.role", loadBalancerResource["network_role"]), - ), - }, + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "networks.0.role", testutil.ConvertConfigVariable(testConfigVarsMin["network_role"])), + resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "external_address"), + )}, // Import { - ResourceName: "stackit_loadbalancer.loadbalancer", + ConfigVariables: testConfigVarsMin, + ResourceName: "stackit_loadbalancer.loadbalancer", ImportStateIdFunc: func(s *terraform.State) (string, error) { r, ok := s.RootModule().Resources["stackit_loadbalancer.loadbalancer"] if !ok { @@ -314,11 +174,132 @@ func TestAccLoadBalancerResource(t *testing.T) { }, // Update { - Config: loadbalancerResourceConfig(loadBalancerResource["target_port_updated"]), + ConfigVariables: configVarsMinUpdated(), + Config: testutil.LoadBalancerProviderConfig() + resourceMinConfig, Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "project_id", loadBalancerResource["project_id"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "name", loadBalancerResource["name"]), - resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.target_port", loadBalancerResource["target_port_updated"]), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "name", testutil.ConvertConfigVariable(testConfigVarsMin["loadbalancer_name"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.target_port", testutil.ConvertConfigVariable(configVarsMinUpdated()["target_port"])), + ), + }, + // Deletion is done by the framework implicitly + }, + }) +} + +func TestAccLoadBalancerResourceMax(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories, + CheckDestroy: testAccCheckLoadBalancerDestroy, + Steps: []resource.TestStep{ + // Creation + { + ConfigVariables: testConfigVarsMax, + Config: testutil.LoadBalancerProviderConfig() + resourceMaxConfig, + Check: resource.ComposeAggregateTestCheckFunc( + // Load balancer instance + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "project_id", testutil.ConvertConfigVariable(testConfigVarsMax["project_id"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "name", testutil.ConvertConfigVariable(testConfigVarsMax["loadbalancer_name"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.name", testutil.ConvertConfigVariable(testConfigVarsMax["target_pool_name"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.target_port", testutil.ConvertConfigVariable(testConfigVarsMax["target_port"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.display_name", testutil.ConvertConfigVariable(testConfigVarsMax["target_display_name"])), + resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.ip"), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.display_name", testutil.ConvertConfigVariable(testConfigVarsMax["listener_display_name"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.port", testutil.ConvertConfigVariable(testConfigVarsMax["listener_port"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.protocol", testutil.ConvertConfigVariable(testConfigVarsMax["listener_protocol"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.target_pool", testutil.ConvertConfigVariable(testConfigVarsMax["target_pool_name"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "listeners.0.server_name_indicators.0.name", testutil.ConvertConfigVariable(testConfigVarsMax["listener_server_name_indicators"])), + resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "networks.0.network_id"), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "networks.0.role", testutil.ConvertConfigVariable(testConfigVarsMax["network_role"])), + resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "external_address"), + + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.healthy_threshold", testutil.ConvertConfigVariable(testConfigVarsMax["healthy_threshold"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.interval", testutil.ConvertConfigVariable(testConfigVarsMax["health_interval"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.interval_jitter", testutil.ConvertConfigVariable(testConfigVarsMax["health_interval_jitter"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.timeout", testutil.ConvertConfigVariable(testConfigVarsMax["health_timeout"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.unhealthy_threshold", testutil.ConvertConfigVariable(testConfigVarsMax["unhealthy_threshold"])), + + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.session_persistence.use_source_ip_address", testutil.ConvertConfigVariable(testConfigVarsMax["use_source_ip_address"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "options.private_network_only", testutil.ConvertConfigVariable(testConfigVarsMax["private_network_only"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "options.acl.0", testutil.ConvertConfigVariable(testConfigVarsMax["acl"])), + ), + }, + // Data source + { + ConfigVariables: testConfigVarsMax, + Config: fmt.Sprintf(` + %s + + data "stackit_loadbalancer" "loadbalancer" { + project_id = stackit_loadbalancer.loadbalancer.project_id + name = stackit_loadbalancer.loadbalancer.name + } + `, + testutil.LoadBalancerProviderConfig()+resourceMaxConfig, + ), + Check: resource.ComposeAggregateTestCheckFunc( + // Load balancer instance + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "project_id", testutil.ConvertConfigVariable(testConfigVarsMax["project_id"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "name", testutil.ConvertConfigVariable(testConfigVarsMax["loadbalancer_name"])), + resource.TestCheckResourceAttrPair( + "data.stackit_loadbalancer.loadbalancer", "project_id", + "stackit_loadbalancer.loadbalancer", "project_id", + ), + resource.TestCheckResourceAttrPair( + "data.stackit_loadbalancer.loadbalancer", "name", + "stackit_loadbalancer.loadbalancer", "name", + ), + // Load balancer instance + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.name", testutil.ConvertConfigVariable(testConfigVarsMax["target_pool_name"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.target_port", testutil.ConvertConfigVariable(testConfigVarsMax["target_port"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.display_name", testutil.ConvertConfigVariable(testConfigVarsMax["target_display_name"])), + resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "target_pools.0.targets.0.ip"), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.display_name", testutil.ConvertConfigVariable(testConfigVarsMax["listener_display_name"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.port", testutil.ConvertConfigVariable(testConfigVarsMax["listener_port"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.protocol", testutil.ConvertConfigVariable(testConfigVarsMax["listener_protocol"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.target_pool", testutil.ConvertConfigVariable(testConfigVarsMax["target_pool_name"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "listeners.0.server_name_indicators.0.name", testutil.ConvertConfigVariable(testConfigVarsMax["listener_server_name_indicators"])), + resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "networks.0.network_id"), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "networks.0.role", testutil.ConvertConfigVariable(testConfigVarsMax["network_role"])), + resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "external_address"), + + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.healthy_threshold", testutil.ConvertConfigVariable(testConfigVarsMax["healthy_threshold"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.interval", testutil.ConvertConfigVariable(testConfigVarsMax["health_interval"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.interval_jitter", testutil.ConvertConfigVariable(testConfigVarsMax["health_interval_jitter"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.timeout", testutil.ConvertConfigVariable(testConfigVarsMax["health_timeout"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.active_health_check.unhealthy_threshold", testutil.ConvertConfigVariable(testConfigVarsMax["unhealthy_threshold"])), + + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "target_pools.0.session_persistence.use_source_ip_address", testutil.ConvertConfigVariable(testConfigVarsMax["use_source_ip_address"])), + resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "options.acl.0", testutil.ConvertConfigVariable(testConfigVarsMax["acl"])), + )}, + // Import + { + ConfigVariables: testConfigVarsMax, + ResourceName: "stackit_loadbalancer.loadbalancer", + ImportStateIdFunc: func(s *terraform.State) (string, error) { + r, ok := s.RootModule().Resources["stackit_loadbalancer.loadbalancer"] + if !ok { + return "", fmt.Errorf("couldn't find resource stackit_loadbalancer.loadbalancer") + } + name, ok := r.Primary.Attributes["name"] + if !ok { + return "", fmt.Errorf("couldn't find attribute name") + } + + return fmt.Sprintf("%s,%s,%s", testutil.ProjectId, testutil.Region, name), nil + }, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"options.private_network_only"}, + }, + // Update + { + ConfigVariables: configVarsMaxUpdated(), + Config: testutil.LoadBalancerProviderConfig() + resourceMaxConfig, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "project_id", testutil.ConvertConfigVariable(testConfigVarsMax["project_id"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "name", testutil.ConvertConfigVariable(testConfigVarsMax["loadbalancer_name"])), + resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "target_pools.0.target_port", testutil.ConvertConfigVariable(configVarsMaxUpdated()["target_port"])), ), }, // Deletion is done by the framework implicitly @@ -334,7 +315,7 @@ func testAccCheckLoadBalancerDestroy(s *terraform.State) error { client, err = loadbalancer.NewAPIClient() } else { client, err = loadbalancer.NewAPIClient( - config.WithEndpoint(testutil.LoadBalancerCustomEndpoint), + stackitSdkConfig.WithEndpoint(testutil.LoadBalancerCustomEndpoint), ) } if err != nil { diff --git a/stackit/internal/services/loadbalancer/testfiles/resource-max.tf b/stackit/internal/services/loadbalancer/testfiles/resource-max.tf new file mode 100644 index 00000000..4fc7aefb --- /dev/null +++ b/stackit/internal/services/loadbalancer/testfiles/resource-max.tf @@ -0,0 +1,113 @@ + +variable "project_id" {} +variable "network_name" {} +variable "server_name" {} + +variable "loadbalancer_name" {} +variable "target_pool_name" {} +variable "target_port" {} +variable "target_display_name" {} +variable "listener_port" {} +variable "listener_protocol" {} +variable "network_role" {} + +variable "listener_display_name" {} +variable "listener_server_name_indicators" {} +variable "healthy_threshold" {} +variable "health_interval" {} +variable "health_interval_jitter" {} +variable "health_timeout" {} +variable "unhealthy_threshold" {} +variable "use_source_ip_address" {} +variable "private_network_only" {} +variable "acl" {} + +resource "stackit_network" "network" { + project_id = var.project_id + name = var.network_name + ipv4_nameservers = ["8.8.8.8"] + ipv4_prefix = "192.168.3.0/25" + routed = "true" +} + +resource "stackit_network_interface" "network_interface" { + project_id = stackit_network.network.project_id + network_id = stackit_network.network.network_id + name = "name" +} + +resource "stackit_public_ip" "public_ip" { + project_id = var.project_id + network_interface_id = stackit_network_interface.network_interface.network_interface_id + lifecycle { + ignore_changes = [ + network_interface_id + ] + } +} + +resource "stackit_server" "server" { + project_id = var.project_id + availability_zone = "eu01-1" + name = var.server_name + machine_type = "t1.1" + boot_volume = { + size = 32 + source_type = "image" + source_id = "59838a89-51b1-4892-b57f-b3caf598ee2f" + delete_on_termination = "true" + } + network_interfaces = [stackit_network_interface.network_interface.network_interface_id] + user_data = "#!/bin/bash" +} + +resource "stackit_loadbalancer" "loadbalancer" { + project_id = var.project_id + name = var.loadbalancer_name + target_pools = [ + { + name = var.target_pool_name + target_port = var.target_port + targets = [ + { + display_name = var.target_display_name + ip = stackit_network_interface.network_interface.ipv4 + } + ] + active_health_check = { + healthy_threshold = var.healthy_threshold + interval = var.health_interval + interval_jitter = var.health_interval_jitter + timeout = var.health_timeout + unhealthy_threshold = var.unhealthy_threshold + } + session_persistence = { + use_source_ip_address = var.use_source_ip_address + } + } + ] + listeners = [ + { + display_name = var.listener_display_name + port = var.listener_port + protocol = var.listener_protocol + target_pool = var.target_pool_name + server_name_indicators = [ + { + name = var.listener_server_name_indicators + } + ] + } + ] + networks = [ + { + network_id = stackit_network.network.network_id + role = var.network_role + } + ] + options = { + private_network_only = var.private_network_only + acl = [var.acl] + } + external_address = stackit_public_ip.public_ip.ip +} diff --git a/stackit/internal/services/loadbalancer/testfiles/resource-min.tf b/stackit/internal/services/loadbalancer/testfiles/resource-min.tf new file mode 100644 index 00000000..2b6d6579 --- /dev/null +++ b/stackit/internal/services/loadbalancer/testfiles/resource-min.tf @@ -0,0 +1,93 @@ + +variable "project_id" {} +variable "network_name" {} +variable "server_name" {} + +variable "loadbalancer_name" {} +variable "target_pool_name" {} +variable "target_port" {} +variable "target_display_name" {} +variable "listener_port" {} +variable "listener_protocol" {} +variable "network_role" {} + +variable "obs_display_name" {} +variable "obs_username" {} +variable "obs_password" {} + +resource "stackit_network" "network" { + project_id = var.project_id + name = var.network_name + ipv4_nameservers = ["8.8.8.8"] + ipv4_prefix = "192.168.2.0/25" + routed = "true" +} + +resource "stackit_network_interface" "network_interface" { + project_id = stackit_network.network.project_id + network_id = stackit_network.network.network_id + name = "name" +} + +resource "stackit_public_ip" "public_ip" { + project_id = var.project_id + network_interface_id = stackit_network_interface.network_interface.network_interface_id + lifecycle { + ignore_changes = [ + network_interface_id + ] + } +} + +resource "stackit_server" "server" { + project_id = var.project_id + availability_zone = "eu01-1" + name = var.server_name + machine_type = "t1.1" + boot_volume = { + size = 32 + source_type = "image" + source_id = "59838a89-51b1-4892-b57f-b3caf598ee2f" + delete_on_termination = "true" + } + network_interfaces = [stackit_network_interface.network_interface.network_interface_id] + user_data = "#!/bin/bash" +} + +resource "stackit_loadbalancer" "loadbalancer" { + project_id = var.project_id + name = var.loadbalancer_name + target_pools = [ + { + name = var.target_pool_name + target_port = var.target_port + targets = [ + { + display_name = var.target_display_name + ip = stackit_network_interface.network_interface.ipv4 + } + ] + } + ] + listeners = [ + { + port = var.listener_port + protocol = var.listener_protocol + target_pool = var.target_pool_name + } + ] + networks = [ + { + network_id = stackit_network.network.network_id + role = var.network_role + } + ] + external_address = stackit_public_ip.public_ip.ip +} + +resource "stackit_loadbalancer_observability_credential" "obs_credential" { + project_id = var.project_id + display_name = var.obs_display_name + username = var.obs_username + password = var.obs_password +}