feat(loadbalancer): add observability options to resource and datasource (#789)
relates to STACKITTPR-124
This commit is contained in:
parent
0d71194d09
commit
6a0ccb87ee
9 changed files with 804 additions and 69 deletions
|
|
@ -79,8 +79,36 @@ Read-Only:
|
|||
Read-Only:
|
||||
|
||||
- `acl` (Set of String) Load Balancer is accessible only from an IP address in this range.
|
||||
- `observability` (Attributes) We offer Load Balancer metrics observability via ARGUS or external solutions. (see [below for nested schema](#nestedatt--options--observability))
|
||||
- `private_network_only` (Boolean) If true, Load Balancer is accessible only via a private network IP address.
|
||||
|
||||
<a id="nestedatt--options--observability"></a>
|
||||
### Nested Schema for `options.observability`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `logs` (Attributes) Observability logs configuration. (see [below for nested schema](#nestedatt--options--observability--logs))
|
||||
- `metrics` (Attributes) Observability metrics configuration. (see [below for nested schema](#nestedatt--options--observability--metrics))
|
||||
|
||||
<a id="nestedatt--options--observability--logs"></a>
|
||||
### Nested Schema for `options.observability.logs`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `credentials_ref` (String) Credentials reference for logs.
|
||||
- `push_url` (String) Credentials reference for logs.
|
||||
|
||||
|
||||
<a id="nestedatt--options--observability--metrics"></a>
|
||||
### Nested Schema for `options.observability.metrics`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `credentials_ref` (String) Credentials reference for metrics.
|
||||
- `push_url` (String) Credentials reference for metrics.
|
||||
|
||||
|
||||
|
||||
|
||||
<a id="nestedatt--target_pools"></a>
|
||||
### Nested Schema for `target_pools`
|
||||
|
|
|
|||
167
docs/guides/using_loadbalancer_with_observability.md
Normal file
167
docs/guides/using_loadbalancer_with_observability.md
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
---
|
||||
page_title: "Using the STACKIT Loadbalancer together with STACKIT Observability"
|
||||
---
|
||||
# Using the STACKIT Loadbalancer together with STACKIT Observability
|
||||
|
||||
## Overview
|
||||
|
||||
This guide explains how to configure the STACKIT Loadbalancer product to send metrics and logs to a STACKIT Observability instance.
|
||||
|
||||
1. **Set Up Providers**
|
||||
|
||||
Begin by configuring the STACKIT provider to connect to the STACKIT services.
|
||||
|
||||
```hcl
|
||||
provider "stackit" {
|
||||
default_region = "eu01"
|
||||
}
|
||||
```
|
||||
|
||||
2. **Create an Observability instance**
|
||||
|
||||
Establish a STACKIT Observability instance and its credentials.
|
||||
|
||||
```hcl
|
||||
resource "stackit_observability_instance" "observability01" {
|
||||
project_id = var.project_id_prod
|
||||
name = "example-instance"
|
||||
plan_name = "Observability-Monitoring-Medium-EU01"
|
||||
acl = ["0.0.0.0/0"]
|
||||
metrics_retention_days = 30
|
||||
metrics_retention_days_5m_downsampling = 10
|
||||
metrics_retention_days_1h_downsampling = 5
|
||||
}
|
||||
|
||||
resource "stackit_observability_credential" "observability01-credential" {
|
||||
project_id = var.project_id_prod
|
||||
instance_id = stackit_observability_instance.observability01.instance_id
|
||||
}
|
||||
```
|
||||
|
||||
3. **Create STACKIT Loadbalancer credentials reference**
|
||||
|
||||
Create a STACKIT Loadbalancer credentials which will be used in the STACKIT Loadbalancer resource as a reference.
|
||||
|
||||
```hcl
|
||||
resource "stackit_loadbalancer_observability_credential" "example" {
|
||||
project_id = var.project_id_prod
|
||||
display_name = "example-credentials"
|
||||
username = stackit_observability_credential.observability01-credential.username
|
||||
password = stackit_observability_credential.observability01-credential.password
|
||||
}
|
||||
```
|
||||
|
||||
4. **Create the STACKIT Loadbalancer**
|
||||
|
||||
```hcl
|
||||
# Create a network
|
||||
resource "stackit_network" "example_network" {
|
||||
project_id = var.project_id_prod
|
||||
name = "example-network"
|
||||
ipv4_nameservers = ["8.8.8.8"]
|
||||
ipv4_prefix = "192.168.0.0/25"
|
||||
labels = {
|
||||
"key" = "value"
|
||||
}
|
||||
routed = true
|
||||
}
|
||||
|
||||
# Create a network interface
|
||||
resource "stackit_network_interface" "nic" {
|
||||
project_id = var.project_id_prod
|
||||
network_id = stackit_network.example_network.network_id
|
||||
}
|
||||
|
||||
# Create a public IP for the load balancer
|
||||
resource "stackit_public_ip" "public-ip" {
|
||||
project_id = var.project_id_prod
|
||||
lifecycle {
|
||||
ignore_changes = [network_interface_id]
|
||||
}
|
||||
}
|
||||
|
||||
# Create a key pair for accessing the server instance
|
||||
resource "stackit_key_pair" "keypair" {
|
||||
name = "example-key-pair"
|
||||
# set the path of your public key file here
|
||||
public_key = chomp(file("/home/bob/.ssh/id_ed25519.pub"))
|
||||
}
|
||||
|
||||
# Create a server instance
|
||||
resource "stackit_server" "boot-from-image" {
|
||||
project_id = var.project_id_prod
|
||||
name = "example-server"
|
||||
boot_volume = {
|
||||
size = 64
|
||||
source_type = "image"
|
||||
source_id = "59838a89-51b1-4892-b57f-b3caf598ee2f" // Ubuntu 24.04
|
||||
}
|
||||
availability_zone = "eu01-1"
|
||||
machine_type = "g1.1"
|
||||
keypair_name = stackit_key_pair.keypair.name
|
||||
}
|
||||
|
||||
# Attach the network interface to the server
|
||||
resource "stackit_server_network_interface_attach" "nic-attachment" {
|
||||
project_id = var.project_id_prod
|
||||
server_id = stackit_server.boot-from-image.server_id
|
||||
network_interface_id = stackit_network_interface.nic.network_interface_id
|
||||
}
|
||||
|
||||
# Create a load balancer
|
||||
resource "stackit_loadbalancer" "example" {
|
||||
project_id = var.project_id_prod
|
||||
name = "example-load-balancer"
|
||||
target_pools = [
|
||||
{
|
||||
name = "example-target-pool"
|
||||
target_port = 80
|
||||
targets = [
|
||||
{
|
||||
display_name = stackit_server.boot-from-image.name
|
||||
ip = stackit_network_interface.nic.ipv4
|
||||
}
|
||||
]
|
||||
active_health_check = {
|
||||
healthy_threshold = 10
|
||||
interval = "3s"
|
||||
interval_jitter = "3s"
|
||||
timeout = "3s"
|
||||
unhealthy_threshold = 10
|
||||
}
|
||||
}
|
||||
]
|
||||
listeners = [
|
||||
{
|
||||
display_name = "example-listener"
|
||||
port = 80
|
||||
protocol = "PROTOCOL_TCP"
|
||||
target_pool = "example-target-pool"
|
||||
}
|
||||
]
|
||||
networks = [
|
||||
{
|
||||
network_id = stackit_network.example_network.network_id
|
||||
role = "ROLE_LISTENERS_AND_TARGETS"
|
||||
}
|
||||
]
|
||||
external_address = stackit_public_ip.public-ip.ip
|
||||
options = {
|
||||
private_network_only = false
|
||||
observability = {
|
||||
logs = {
|
||||
# uses the load balancer credential from the last step
|
||||
credentials_ref = stackit_loadbalancer_observability_credential.example.credentials_ref
|
||||
# uses the observability instance from step 1
|
||||
push_url = stackit_observability_instance.observability01.logs_push_url
|
||||
}
|
||||
metrics = {
|
||||
# uses the load balancer credential from the last step
|
||||
credentials_ref = stackit_loadbalancer_observability_credential.example.credentials_ref
|
||||
# uses the observability instance from step 1
|
||||
push_url = stackit_observability_instance.observability01.metrics_push_url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -218,4 +218,30 @@ Optional:
|
|||
Optional:
|
||||
|
||||
- `acl` (Set of String) Load Balancer is accessible only from an IP address in this range.
|
||||
- `observability` (Attributes) We offer Load Balancer metrics observability via ARGUS or external solutions. Not changeable after creation. (see [below for nested schema](#nestedatt--options--observability))
|
||||
- `private_network_only` (Boolean) If true, Load Balancer is accessible only via a private network IP address.
|
||||
|
||||
<a id="nestedatt--options--observability"></a>
|
||||
### Nested Schema for `options.observability`
|
||||
|
||||
Optional:
|
||||
|
||||
- `logs` (Attributes) Observability logs configuration. Not changeable after creation. (see [below for nested schema](#nestedatt--options--observability--logs))
|
||||
- `metrics` (Attributes) Observability metrics configuration. Not changeable after creation. (see [below for nested schema](#nestedatt--options--observability--metrics))
|
||||
|
||||
<a id="nestedatt--options--observability--logs"></a>
|
||||
### Nested Schema for `options.observability.logs`
|
||||
|
||||
Optional:
|
||||
|
||||
- `credentials_ref` (String) Credentials reference for logs. Not changeable after creation.
|
||||
- `push_url` (String) Credentials reference for logs. Not changeable after creation.
|
||||
|
||||
|
||||
<a id="nestedatt--options--observability--metrics"></a>
|
||||
### Nested Schema for `options.observability.metrics`
|
||||
|
||||
Optional:
|
||||
|
||||
- `credentials_ref` (String) Credentials reference for metrics. Not changeable after creation.
|
||||
- `push_url` (String) Credentials reference for metrics. Not changeable after creation.
|
||||
|
|
|
|||
|
|
@ -81,38 +81,45 @@ func (r *loadBalancerDataSource) Configure(ctx context.Context, req datasource.C
|
|||
// Schema defines the schema for the data source.
|
||||
func (r *loadBalancerDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
descriptions := map[string]string{
|
||||
"main": "Load Balancer data source schema. Must have a `region` specified in the provider configuration.",
|
||||
"id": "Terraform's internal resource ID. It is structured as \"`project_id`\",\"region\",\"`name`\".",
|
||||
"project_id": "STACKIT project ID to which the Load Balancer is associated.",
|
||||
"external_address": "External Load Balancer IP address where this Load Balancer is exposed.",
|
||||
"listeners": "List of all listeners which will accept traffic. Limited to 20.",
|
||||
"port": "Port number where we listen for traffic.",
|
||||
"protocol": "Protocol is the highest network protocol we understand to load balance.",
|
||||
"target_pool": "Reference target pool by target pool name.",
|
||||
"name": "Load balancer name.",
|
||||
"networks": "List of networks that listeners and targets reside in.",
|
||||
"network_id": "Openstack network ID.",
|
||||
"role": "The role defines how the load balancer is using the network.",
|
||||
"options": "Defines any optional functionality you want to have enabled on your load balancer.",
|
||||
"acl": "Load Balancer is accessible only from an IP address in this range.",
|
||||
"private_network_only": "If true, Load Balancer is accessible only via a private network IP address.",
|
||||
"session_persistence": "Here you can setup various session persistence options, so far only \"`use_source_ip_address`\" is supported.",
|
||||
"use_source_ip_address": "If true then all connections from one source IP address are redirected to the same target. This setting changes the load balancing algorithm to Maglev.",
|
||||
"server_name_indicators": "A list of domain names to match in order to pass TLS traffic to the target pool in the current listener",
|
||||
"server_name_indicators.name": "A domain name to match in order to pass TLS traffic to the target pool in the current listener",
|
||||
"private_address": "Transient private Load Balancer IP address. It can change any time.",
|
||||
"target_pools": "List of all target pools which will be used in the Load Balancer. Limited to 20.",
|
||||
"healthy_threshold": "Healthy threshold of the health checking.",
|
||||
"interval": "Interval duration of health checking in seconds.",
|
||||
"interval_jitter": "Interval duration threshold of the health checking in seconds.",
|
||||
"timeout": "Active health checking timeout duration in seconds.",
|
||||
"unhealthy_threshold": "Unhealthy threshold of the health checking.",
|
||||
"target_pools.name": "Target pool name.",
|
||||
"target_port": "Identical port number where each target listens for traffic.",
|
||||
"targets": "List of all targets which will be used in the pool. Limited to 1000.",
|
||||
"targets.display_name": "Target display name",
|
||||
"ip": "Target IP",
|
||||
"region": "The resource region. If not defined, the provider region is used.",
|
||||
"main": "Load Balancer data source schema. Must have a `region` specified in the provider configuration.",
|
||||
"id": "Terraform's internal resource ID. It is structured as \"`project_id`\",\"region\",\"`name`\".",
|
||||
"project_id": "STACKIT project ID to which the Load Balancer is associated.",
|
||||
"external_address": "External Load Balancer IP address where this Load Balancer is exposed.",
|
||||
"listeners": "List of all listeners which will accept traffic. Limited to 20.",
|
||||
"port": "Port number where we listen for traffic.",
|
||||
"protocol": "Protocol is the highest network protocol we understand to load balance.",
|
||||
"target_pool": "Reference target pool by target pool name.",
|
||||
"name": "Load balancer name.",
|
||||
"networks": "List of networks that listeners and targets reside in.",
|
||||
"network_id": "Openstack network ID.",
|
||||
"role": "The role defines how the load balancer is using the network.",
|
||||
"observability": "We offer Load Balancer metrics observability via ARGUS or external solutions.",
|
||||
"observability_logs": "Observability logs configuration.",
|
||||
"observability_logs_credentials_ref": "Credentials reference for logs.",
|
||||
"observability_logs_push_url": "The ARGUS/Loki remote write Push URL to ship the logs to.",
|
||||
"observability_metrics": "Observability metrics configuration.",
|
||||
"observability_metrics_credentials_ref": "Credentials reference for metrics.",
|
||||
"observability_metrics_push_url": "The ARGUS/Prometheus remote write Push URL to ship the metrics to.",
|
||||
"options": "Defines any optional functionality you want to have enabled on your load balancer.",
|
||||
"acl": "Load Balancer is accessible only from an IP address in this range.",
|
||||
"private_network_only": "If true, Load Balancer is accessible only via a private network IP address.",
|
||||
"session_persistence": "Here you can setup various session persistence options, so far only \"`use_source_ip_address`\" is supported.",
|
||||
"use_source_ip_address": "If true then all connections from one source IP address are redirected to the same target. This setting changes the load balancing algorithm to Maglev.",
|
||||
"server_name_indicators": "A list of domain names to match in order to pass TLS traffic to the target pool in the current listener",
|
||||
"server_name_indicators.name": "A domain name to match in order to pass TLS traffic to the target pool in the current listener",
|
||||
"private_address": "Transient private Load Balancer IP address. It can change any time.",
|
||||
"target_pools": "List of all target pools which will be used in the Load Balancer. Limited to 20.",
|
||||
"healthy_threshold": "Healthy threshold of the health checking.",
|
||||
"interval": "Interval duration of health checking in seconds.",
|
||||
"interval_jitter": "Interval duration threshold of the health checking in seconds.",
|
||||
"timeout": "Active health checking timeout duration in seconds.",
|
||||
"unhealthy_threshold": "Unhealthy threshold of the health checking.",
|
||||
"target_pools.name": "Target pool name.",
|
||||
"target_port": "Identical port number where each target listens for traffic.",
|
||||
"targets": "List of all targets which will be used in the pool. Limited to 1000.",
|
||||
"targets.display_name": "Target display name",
|
||||
"ip": "Target IP",
|
||||
"region": "The resource region. If not defined, the provider region is used.",
|
||||
}
|
||||
|
||||
resp.Schema = schema.Schema{
|
||||
|
|
@ -222,6 +229,40 @@ func (r *loadBalancerDataSource) Schema(_ context.Context, _ datasource.SchemaRe
|
|||
Description: descriptions["private_network_only"],
|
||||
Computed: true,
|
||||
},
|
||||
"observability": schema.SingleNestedAttribute{
|
||||
Description: descriptions["observability"],
|
||||
Computed: true,
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"logs": schema.SingleNestedAttribute{
|
||||
Description: descriptions["observability_logs"],
|
||||
Computed: true,
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"credentials_ref": schema.StringAttribute{
|
||||
Description: descriptions["observability_logs_credentials_ref"],
|
||||
Computed: true,
|
||||
},
|
||||
"push_url": schema.StringAttribute{
|
||||
Description: descriptions["observability_logs_credentials_ref"],
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"metrics": schema.SingleNestedAttribute{
|
||||
Description: descriptions["observability_metrics"],
|
||||
Computed: true,
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"credentials_ref": schema.StringAttribute{
|
||||
Description: descriptions["observability_metrics_credentials_ref"],
|
||||
Computed: true,
|
||||
},
|
||||
"push_url": schema.StringAttribute{
|
||||
Description: descriptions["observability_metrics_credentials_ref"],
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"private_address": schema.StringAttribute{
|
||||
|
|
|
|||
|
|
@ -100,14 +100,36 @@ var networkTypes = map[string]attr.Type{
|
|||
|
||||
// Struct corresponding to Model.Options
|
||||
type options struct {
|
||||
ACL types.Set `tfsdk:"acl"`
|
||||
PrivateNetworkOnly types.Bool `tfsdk:"private_network_only"`
|
||||
ACL types.Set `tfsdk:"acl"`
|
||||
PrivateNetworkOnly types.Bool `tfsdk:"private_network_only"`
|
||||
Observability types.Object `tfsdk:"observability"`
|
||||
}
|
||||
|
||||
// Types corresponding to options
|
||||
var optionsTypes = map[string]attr.Type{
|
||||
"acl": types.SetType{ElemType: types.StringType},
|
||||
"private_network_only": types.BoolType,
|
||||
"observability": types.ObjectType{AttrTypes: observabilityTypes},
|
||||
}
|
||||
|
||||
type observability struct {
|
||||
Logs types.Object `tfsdk:"logs"`
|
||||
Metrics types.Object `tfsdk:"metrics"`
|
||||
}
|
||||
|
||||
var observabilityTypes = map[string]attr.Type{
|
||||
"logs": types.ObjectType{AttrTypes: observabilityOptionTypes},
|
||||
"metrics": types.ObjectType{AttrTypes: observabilityOptionTypes},
|
||||
}
|
||||
|
||||
type observabilityOption struct {
|
||||
CredentialsRef types.String `tfsdk:"credentials_ref"`
|
||||
PushUrl types.String `tfsdk:"push_url"`
|
||||
}
|
||||
|
||||
var observabilityOptionTypes = map[string]attr.Type{
|
||||
"credentials_ref": types.StringType,
|
||||
"push_url": types.StringType,
|
||||
}
|
||||
|
||||
// Struct corresponding to Model.TargetPools[i]
|
||||
|
|
@ -257,38 +279,45 @@ func (r *loadBalancerResource) Schema(_ context.Context, _ resource.SchemaReques
|
|||
roleOptions := []string{"ROLE_UNSPECIFIED", "ROLE_LISTENERS_AND_TARGETS", "ROLE_LISTENERS", "ROLE_TARGETS"}
|
||||
|
||||
descriptions := map[string]string{
|
||||
"main": "Load Balancer resource schema.",
|
||||
"id": "Terraform's internal resource ID. It is structured as \"`project_id`\",\"region\",\"`name`\".",
|
||||
"project_id": "STACKIT project ID to which the Load Balancer is associated.",
|
||||
"external_address": "External Load Balancer IP address where this Load Balancer is exposed.",
|
||||
"listeners": "List of all listeners which will accept traffic. Limited to 20.",
|
||||
"port": "Port number where we listen for traffic.",
|
||||
"protocol": "Protocol is the highest network protocol we understand to load balance. " + utils.SupportedValuesDocumentation(protocolOptions),
|
||||
"target_pool": "Reference target pool by target pool name.",
|
||||
"name": "Load balancer name.",
|
||||
"networks": "List of networks that listeners and targets reside in.",
|
||||
"network_id": "Openstack network ID.",
|
||||
"role": "The role defines how the load balancer is using the network. " + utils.SupportedValuesDocumentation(roleOptions),
|
||||
"options": "Defines any optional functionality you want to have enabled on your load balancer.",
|
||||
"acl": "Load Balancer is accessible only from an IP address in this range.",
|
||||
"private_network_only": "If true, Load Balancer is accessible only via a private network IP address.",
|
||||
"session_persistence": "Here you can setup various session persistence options, so far only \"`use_source_ip_address`\" is supported.",
|
||||
"use_source_ip_address": "If true then all connections from one source IP address are redirected to the same target. This setting changes the load balancing algorithm to Maglev.",
|
||||
"server_name_indicators": "A list of domain names to match in order to pass TLS traffic to the target pool in the current listener",
|
||||
"server_name_indicators.name": "A domain name to match in order to pass TLS traffic to the target pool in the current listener",
|
||||
"private_address": "Transient private Load Balancer IP address. It can change any time.",
|
||||
"target_pools": "List of all target pools which will be used in the Load Balancer. Limited to 20.",
|
||||
"healthy_threshold": "Healthy threshold of the health checking.",
|
||||
"interval": "Interval duration of health checking in seconds.",
|
||||
"interval_jitter": "Interval duration threshold of the health checking in seconds.",
|
||||
"timeout": "Active health checking timeout duration in seconds.",
|
||||
"unhealthy_threshold": "Unhealthy threshold of the health checking.",
|
||||
"target_pools.name": "Target pool name.",
|
||||
"target_port": "Identical port number where each target listens for traffic.",
|
||||
"targets": "List of all targets which will be used in the pool. Limited to 1000.",
|
||||
"targets.display_name": "Target display name",
|
||||
"ip": "Target IP",
|
||||
"region": "The resource region. If not defined, the provider region is used.",
|
||||
"main": "Load Balancer resource schema.",
|
||||
"id": "Terraform's internal resource ID. It is structured as \"`project_id`\",\"region\",\"`name`\".",
|
||||
"project_id": "STACKIT project ID to which the Load Balancer is associated.",
|
||||
"external_address": "External Load Balancer IP address where this Load Balancer is exposed.",
|
||||
"listeners": "List of all listeners which will accept traffic. Limited to 20.",
|
||||
"port": "Port number where we listen for traffic.",
|
||||
"protocol": "Protocol is the highest network protocol we understand to load balance. " + utils.SupportedValuesDocumentation(protocolOptions),
|
||||
"target_pool": "Reference target pool by target pool name.",
|
||||
"name": "Load balancer name.",
|
||||
"networks": "List of networks that listeners and targets reside in.",
|
||||
"network_id": "Openstack network ID.",
|
||||
"role": "The role defines how the load balancer is using the network. " + utils.SupportedValuesDocumentation(roleOptions),
|
||||
"observability": "We offer Load Balancer metrics observability via ARGUS or external solutions. Not changeable after creation.",
|
||||
"observability_logs": "Observability logs configuration. Not changeable after creation.",
|
||||
"observability_logs_credentials_ref": "Credentials reference for logs. Not changeable after creation.",
|
||||
"observability_logs_push_url": "The ARGUS/Loki remote write Push URL to ship the logs to. Not changeable after creation.",
|
||||
"observability_metrics": "Observability metrics configuration. Not changeable after creation.",
|
||||
"observability_metrics_credentials_ref": "Credentials reference for metrics. Not changeable after creation.",
|
||||
"observability_metrics_push_url": "The ARGUS/Prometheus remote write Push URL to ship the metrics to. Not changeable after creation.",
|
||||
"options": "Defines any optional functionality you want to have enabled on your load balancer.",
|
||||
"acl": "Load Balancer is accessible only from an IP address in this range.",
|
||||
"private_network_only": "If true, Load Balancer is accessible only via a private network IP address.",
|
||||
"session_persistence": "Here you can setup various session persistence options, so far only \"`use_source_ip_address`\" is supported.",
|
||||
"use_source_ip_address": "If true then all connections from one source IP address are redirected to the same target. This setting changes the load balancing algorithm to Maglev.",
|
||||
"server_name_indicators": "A list of domain names to match in order to pass TLS traffic to the target pool in the current listener",
|
||||
"server_name_indicators.name": "A domain name to match in order to pass TLS traffic to the target pool in the current listener",
|
||||
"private_address": "Transient private Load Balancer IP address. It can change any time.",
|
||||
"target_pools": "List of all target pools which will be used in the Load Balancer. Limited to 20.",
|
||||
"healthy_threshold": "Healthy threshold of the health checking.",
|
||||
"interval": "Interval duration of health checking in seconds.",
|
||||
"interval_jitter": "Interval duration threshold of the health checking in seconds.",
|
||||
"timeout": "Active health checking timeout duration in seconds.",
|
||||
"unhealthy_threshold": "Unhealthy threshold of the health checking.",
|
||||
"target_pools.name": "Target pool name.",
|
||||
"target_port": "Identical port number where each target listens for traffic.",
|
||||
"targets": "List of all targets which will be used in the pool. Limited to 1000.",
|
||||
"targets.display_name": "Target display name",
|
||||
"ip": "Target IP",
|
||||
"region": "The resource region. If not defined, the provider region is used.",
|
||||
}
|
||||
|
||||
resp.Schema = schema.Schema{
|
||||
|
|
@ -466,6 +495,51 @@ The example below creates the supporting infrastructure using the STACKIT Terraf
|
|||
boolplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"observability": schema.SingleNestedAttribute{
|
||||
Description: descriptions["observability"],
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.Object{
|
||||
// API docs says observability options are not changeable after creation
|
||||
objectplanmodifier.RequiresReplace(),
|
||||
},
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"logs": schema.SingleNestedAttribute{
|
||||
Description: descriptions["observability_logs"],
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"credentials_ref": schema.StringAttribute{
|
||||
Description: descriptions["observability_logs_credentials_ref"],
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"push_url": schema.StringAttribute{
|
||||
Description: descriptions["observability_logs_credentials_ref"],
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"metrics": schema.SingleNestedAttribute{
|
||||
Description: descriptions["observability_metrics"],
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"credentials_ref": schema.StringAttribute{
|
||||
Description: descriptions["observability_metrics_credentials_ref"],
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"push_url": schema.StringAttribute{
|
||||
Description: descriptions["observability_metrics_credentials_ref"],
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"private_address": schema.StringAttribute{
|
||||
|
|
@ -903,6 +977,7 @@ func toOptionsPayload(ctx context.Context, model *Model) (*loadbalancer.LoadBala
|
|||
if model.Options.IsNull() || model.Options.IsUnknown() {
|
||||
return &loadbalancer.LoadBalancerOptions{
|
||||
AccessControl: &loadbalancer.LoadbalancerOptionAccessControl{},
|
||||
Observability: &loadbalancer.LoadbalancerOptionObservability{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -922,8 +997,40 @@ func toOptionsPayload(ctx context.Context, model *Model) (*loadbalancer.LoadBala
|
|||
accessControlPayload.AllowedSourceRanges = &aclModel
|
||||
}
|
||||
|
||||
observabilityPayload := &loadbalancer.LoadbalancerOptionObservability{}
|
||||
if !(optionsModel.Observability.IsNull() || optionsModel.Observability.IsUnknown()) {
|
||||
observabilityModel := observability{}
|
||||
diags := optionsModel.Observability.As(ctx, &observabilityModel, basetypes.ObjectAsOptions{})
|
||||
if diags.HasError() {
|
||||
return nil, fmt.Errorf("converting observability: %w", core.DiagsToError(diags))
|
||||
}
|
||||
|
||||
// observability logs
|
||||
observabilityLogsModel := observabilityOption{}
|
||||
diags = observabilityModel.Logs.As(ctx, &observabilityLogsModel, basetypes.ObjectAsOptions{})
|
||||
if diags.HasError() {
|
||||
return nil, fmt.Errorf("converting observability logs: %w", core.DiagsToError(diags))
|
||||
}
|
||||
observabilityPayload.Logs = &loadbalancer.LoadbalancerOptionLogs{
|
||||
CredentialsRef: observabilityLogsModel.CredentialsRef.ValueStringPointer(),
|
||||
PushUrl: observabilityLogsModel.PushUrl.ValueStringPointer(),
|
||||
}
|
||||
|
||||
// observability metrics
|
||||
observabilityMetricsModel := observabilityOption{}
|
||||
diags = observabilityModel.Metrics.As(ctx, &observabilityMetricsModel, basetypes.ObjectAsOptions{})
|
||||
if diags.HasError() {
|
||||
return nil, fmt.Errorf("converting observability metrics: %w", core.DiagsToError(diags))
|
||||
}
|
||||
observabilityPayload.Metrics = &loadbalancer.LoadbalancerOptionMetrics{
|
||||
CredentialsRef: observabilityMetricsModel.CredentialsRef.ValueStringPointer(),
|
||||
PushUrl: observabilityMetricsModel.PushUrl.ValueStringPointer(),
|
||||
}
|
||||
}
|
||||
|
||||
payload := loadbalancer.LoadBalancerOptions{
|
||||
AccessControl: accessControlPayload,
|
||||
Observability: observabilityPayload,
|
||||
PrivateNetworkOnly: conversion.BoolValueToPointer(optionsModel.PrivateNetworkOnly),
|
||||
}
|
||||
|
||||
|
|
@ -1249,6 +1356,42 @@ func mapOptions(ctx context.Context, loadBalancerResp *loadbalancer.LoadBalancer
|
|||
return fmt.Errorf("mapping field ACL: %w", err)
|
||||
}
|
||||
|
||||
observabilityLogsMap := map[string]attr.Value{
|
||||
"credentials_ref": types.StringNull(),
|
||||
"push_url": types.StringNull(),
|
||||
}
|
||||
if loadBalancerResp.Options.HasObservability() && loadBalancerResp.Options.Observability.HasLogs() {
|
||||
observabilityLogsMap["credentials_ref"] = types.StringPointerValue(loadBalancerResp.Options.Observability.Logs.CredentialsRef)
|
||||
observabilityLogsMap["push_url"] = types.StringPointerValue(loadBalancerResp.Options.Observability.Logs.PushUrl)
|
||||
}
|
||||
observabilityLogsTF, diags := types.ObjectValue(observabilityOptionTypes, observabilityLogsMap)
|
||||
if diags.HasError() {
|
||||
return core.DiagsToError(diags)
|
||||
}
|
||||
|
||||
observabilityMetricsMap := map[string]attr.Value{
|
||||
"credentials_ref": types.StringNull(),
|
||||
"push_url": types.StringNull(),
|
||||
}
|
||||
if loadBalancerResp.Options.HasObservability() && loadBalancerResp.Options.Observability.HasMetrics() {
|
||||
observabilityMetricsMap["credentials_ref"] = types.StringPointerValue(loadBalancerResp.Options.Observability.Metrics.CredentialsRef)
|
||||
observabilityMetricsMap["push_url"] = types.StringPointerValue(loadBalancerResp.Options.Observability.Metrics.PushUrl)
|
||||
}
|
||||
observabilityMetricsTF, diags := types.ObjectValue(observabilityOptionTypes, observabilityMetricsMap)
|
||||
if diags.HasError() {
|
||||
return core.DiagsToError(diags)
|
||||
}
|
||||
|
||||
observabilityMap := map[string]attr.Value{
|
||||
"logs": observabilityLogsTF,
|
||||
"metrics": observabilityMetricsTF,
|
||||
}
|
||||
observabilityTF, diags := types.ObjectValue(observabilityTypes, observabilityMap)
|
||||
if diags.HasError() {
|
||||
return core.DiagsToError(diags)
|
||||
}
|
||||
optionsMap["observability"] = observabilityTF
|
||||
|
||||
optionsTF, diags := types.ObjectValue(optionsTypes, optionsMap)
|
||||
if diags.HasError() {
|
||||
return core.DiagsToError(diags)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ func TestToCreatePayload(t *testing.T) {
|
|||
AllowedSourceRanges: nil,
|
||||
},
|
||||
PrivateNetworkOnly: nil,
|
||||
Observability: &loadbalancer.LoadbalancerOptionObservability{},
|
||||
},
|
||||
TargetPools: nil,
|
||||
},
|
||||
|
|
@ -76,6 +77,16 @@ func TestToCreatePayload(t *testing.T) {
|
|||
types.StringType,
|
||||
[]attr.Value{types.StringValue("cidr")}),
|
||||
"private_network_only": types.BoolValue(true),
|
||||
"observability": types.ObjectValueMust(observabilityTypes, map[string]attr.Value{
|
||||
"logs": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringValue("logs-credentials_ref"),
|
||||
"push_url": types.StringValue("logs-push_url"),
|
||||
}),
|
||||
"metrics": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringValue("metrics-credentials_ref"),
|
||||
"push_url": types.StringValue("metrics-push_url"),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
),
|
||||
TargetPools: types.ListValueMust(types.ObjectType{AttrTypes: targetPoolTypes}, []attr.Value{
|
||||
|
|
@ -132,6 +143,16 @@ func TestToCreatePayload(t *testing.T) {
|
|||
AllowedSourceRanges: &[]string{"cidr"},
|
||||
},
|
||||
PrivateNetworkOnly: utils.Ptr(true),
|
||||
Observability: &loadbalancer.LoadbalancerOptionObservability{
|
||||
Logs: &loadbalancer.LoadbalancerOptionLogs{
|
||||
CredentialsRef: utils.Ptr("logs-credentials_ref"),
|
||||
PushUrl: utils.Ptr("logs-push_url"),
|
||||
},
|
||||
Metrics: &loadbalancer.LoadbalancerOptionMetrics{
|
||||
CredentialsRef: utils.Ptr("metrics-credentials_ref"),
|
||||
PushUrl: utils.Ptr("metrics-push_url"),
|
||||
},
|
||||
},
|
||||
},
|
||||
TargetPools: &[]loadbalancer.TargetPool{
|
||||
{
|
||||
|
|
@ -290,6 +311,10 @@ func TestMapFields(t *testing.T) {
|
|||
AllowedSourceRanges: nil,
|
||||
},
|
||||
PrivateNetworkOnly: nil,
|
||||
Observability: &loadbalancer.LoadbalancerOptionObservability{
|
||||
Logs: &loadbalancer.LoadbalancerOptionLogs{},
|
||||
Metrics: &loadbalancer.LoadbalancerOptionMetrics{},
|
||||
},
|
||||
},
|
||||
TargetPools: nil,
|
||||
},
|
||||
|
|
@ -305,6 +330,16 @@ func TestMapFields(t *testing.T) {
|
|||
Options: types.ObjectValueMust(optionsTypes, map[string]attr.Value{
|
||||
"acl": types.SetNull(types.StringType),
|
||||
"private_network_only": types.BoolNull(),
|
||||
"observability": types.ObjectValueMust(observabilityTypes, map[string]attr.Value{
|
||||
"logs": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringNull(),
|
||||
"push_url": types.StringNull(),
|
||||
}),
|
||||
"metrics": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringNull(),
|
||||
"push_url": types.StringNull(),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
PrivateAddress: types.StringNull(),
|
||||
TargetPools: types.ListNull(types.ObjectType{AttrTypes: targetPoolTypes}),
|
||||
|
|
@ -342,6 +377,16 @@ func TestMapFields(t *testing.T) {
|
|||
}),
|
||||
Options: utils.Ptr(loadbalancer.LoadBalancerOptions{
|
||||
PrivateNetworkOnly: utils.Ptr(true),
|
||||
Observability: &loadbalancer.LoadbalancerOptionObservability{
|
||||
Logs: &loadbalancer.LoadbalancerOptionLogs{
|
||||
CredentialsRef: utils.Ptr("logs_credentials_ref"),
|
||||
PushUrl: utils.Ptr("logs_push_url"),
|
||||
},
|
||||
Metrics: &loadbalancer.LoadbalancerOptionMetrics{
|
||||
CredentialsRef: utils.Ptr("metrics_credentials_ref"),
|
||||
PushUrl: utils.Ptr("metrics_push_url"),
|
||||
},
|
||||
},
|
||||
}),
|
||||
TargetPools: utils.Ptr([]loadbalancer.TargetPool{
|
||||
{
|
||||
|
|
@ -405,6 +450,16 @@ func TestMapFields(t *testing.T) {
|
|||
map[string]attr.Value{
|
||||
"private_network_only": types.BoolValue(true),
|
||||
"acl": types.SetNull(types.StringType),
|
||||
"observability": types.ObjectValueMust(observabilityTypes, map[string]attr.Value{
|
||||
"logs": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringValue("logs_credentials_ref"),
|
||||
"push_url": types.StringValue("logs_push_url"),
|
||||
}),
|
||||
"metrics": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringValue("metrics_credentials_ref"),
|
||||
"push_url": types.StringValue("metrics_push_url"),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
),
|
||||
TargetPools: types.ListValueMust(types.ObjectType{AttrTypes: targetPoolTypes}, []attr.Value{
|
||||
|
|
@ -466,6 +521,16 @@ func TestMapFields(t *testing.T) {
|
|||
AllowedSourceRanges: utils.Ptr([]string{"cidr"}),
|
||||
},
|
||||
PrivateNetworkOnly: nil, // API sets this to nil if it's false in the request
|
||||
Observability: &loadbalancer.LoadbalancerOptionObservability{
|
||||
Logs: &loadbalancer.LoadbalancerOptionLogs{
|
||||
CredentialsRef: utils.Ptr("logs_credentials_ref"),
|
||||
PushUrl: utils.Ptr("logs_push_url"),
|
||||
},
|
||||
Metrics: &loadbalancer.LoadbalancerOptionMetrics{
|
||||
CredentialsRef: utils.Ptr("metrics_credentials_ref"),
|
||||
PushUrl: utils.Ptr("metrics_push_url"),
|
||||
},
|
||||
},
|
||||
}),
|
||||
TargetPools: utils.Ptr([]loadbalancer.TargetPool{
|
||||
{
|
||||
|
|
@ -531,6 +596,16 @@ func TestMapFields(t *testing.T) {
|
|||
types.StringType,
|
||||
[]attr.Value{types.StringValue("cidr")}),
|
||||
"private_network_only": types.BoolValue(false),
|
||||
"observability": types.ObjectValueMust(observabilityTypes, map[string]attr.Value{
|
||||
"logs": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringValue("logs_credentials_ref"),
|
||||
"push_url": types.StringValue("logs_push_url"),
|
||||
}),
|
||||
"metrics": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringValue("metrics_credentials_ref"),
|
||||
"push_url": types.StringValue("metrics_push_url"),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
),
|
||||
TargetPools: types.ListValueMust(types.ObjectType{AttrTypes: targetPoolTypes}, []attr.Value{
|
||||
|
|
@ -585,6 +660,16 @@ func TestMapFields(t *testing.T) {
|
|||
model.Options = types.ObjectValueMust(optionsTypes, map[string]attr.Value{
|
||||
"private_network_only": types.BoolValue(*tt.modelPrivateNetworkOnly),
|
||||
"acl": types.SetNull(types.StringType),
|
||||
"observability": types.ObjectValueMust(observabilityTypes, map[string]attr.Value{
|
||||
"logs": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringNull(),
|
||||
"push_url": types.StringNull(),
|
||||
}),
|
||||
"metrics": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
|
||||
"credentials_ref": types.StringNull(),
|
||||
"push_url": types.StringNull(),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
}
|
||||
err := mapFields(context.Background(), tt.input, model, tt.region)
|
||||
|
|
|
|||
|
|
@ -67,6 +67,15 @@ var testConfigVarsMax = config.Variables{
|
|||
"use_source_ip_address": config.StringVariable("true"),
|
||||
"private_network_only": config.StringVariable("false"),
|
||||
"acl": config.StringVariable("192.168.0.0/24"),
|
||||
|
||||
"observability_logs_push_url": config.StringVariable("https://logs.observability.dummy.stackit.cloud"),
|
||||
"observability_metrics_push_url": config.StringVariable("https://metrics.observability.dummy.stackit.cloud"),
|
||||
"observability_credential_logs_name": config.StringVariable(fmt.Sprintf("tf-acc-l%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))),
|
||||
"observability_credential_logs_username": config.StringVariable("obs-cred-logs-username"),
|
||||
"observability_credential_logs_password": config.StringVariable("obs-cred-logs-password"),
|
||||
"observability_credential_metrics_name": config.StringVariable(fmt.Sprintf("tf-acc-m%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))),
|
||||
"observability_credential_metrics_username": config.StringVariable("obs-cred-metrics-username"),
|
||||
"observability_credential_metrics_password": config.StringVariable("obs-cred-metrics-password"),
|
||||
}
|
||||
|
||||
func configVarsMinUpdated() config.Variables {
|
||||
|
|
@ -93,7 +102,7 @@ func TestAccLoadBalancerResourceMin(t *testing.T) {
|
|||
ConfigVariables: testConfigVarsMin,
|
||||
Config: testutil.LoadBalancerProviderConfig() + resourceMinConfig,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Load balancer instance
|
||||
// Load balancer instance resource
|
||||
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"])),
|
||||
|
|
@ -107,12 +116,17 @@ func TestAccLoadBalancerResourceMin(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "networks.0.network_id"),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "networks.0.role", testutil.ConvertConfigVariable(testConfigVarsMin["network_role"])),
|
||||
resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "external_address"),
|
||||
resource.TestCheckNoResourceAttr("stackit_loadbalancer.loadbalancer", "options.observability.logs.credentials_ref"),
|
||||
resource.TestCheckNoResourceAttr("stackit_loadbalancer.loadbalancer", "options.observability.logs.push_url"),
|
||||
resource.TestCheckNoResourceAttr("stackit_loadbalancer.loadbalancer", "options.observability.metrics.credentials_ref"),
|
||||
resource.TestCheckNoResourceAttr("stackit_loadbalancer.loadbalancer", "options.observability.metrics.push_url"),
|
||||
|
||||
// observability credentials
|
||||
// Loadbalancer observability credentials resource
|
||||
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"])),
|
||||
resource.TestCheckResourceAttrSet("stackit_loadbalancer_observability_credential.obs_credential", "credentials_ref"),
|
||||
),
|
||||
},
|
||||
// Data source
|
||||
|
|
@ -151,6 +165,10 @@ func TestAccLoadBalancerResourceMin(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "networks.0.network_id"),
|
||||
resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "networks.0.role", testutil.ConvertConfigVariable(testConfigVarsMin["network_role"])),
|
||||
resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "external_address"),
|
||||
resource.TestCheckNoResourceAttr("data.stackit_loadbalancer.loadbalancer", "options.observability.logs.credentials_ref"),
|
||||
resource.TestCheckNoResourceAttr("data.stackit_loadbalancer.loadbalancer", "options.observability.logs.push_url"),
|
||||
resource.TestCheckNoResourceAttr("data.stackit_loadbalancer.loadbalancer", "options.observability.metrics.credentials_ref"),
|
||||
resource.TestCheckNoResourceAttr("data.stackit_loadbalancer.loadbalancer", "options.observability.metrics.push_url"),
|
||||
)},
|
||||
// Import
|
||||
{
|
||||
|
|
@ -197,7 +215,7 @@ func TestAccLoadBalancerResourceMax(t *testing.T) {
|
|||
ConfigVariables: testConfigVarsMax,
|
||||
Config: testutil.LoadBalancerProviderConfig() + resourceMaxConfig,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Load balancer instance
|
||||
// Load balancer instance resource
|
||||
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"])),
|
||||
|
|
@ -222,6 +240,25 @@ func TestAccLoadBalancerResourceMax(t *testing.T) {
|
|||
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"])),
|
||||
|
||||
resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "options.observability.logs.credentials_ref"),
|
||||
resource.TestCheckResourceAttrPair("stackit_loadbalancer_observability_credential.logs", "credentials_ref", "stackit_loadbalancer.loadbalancer", "options.observability.logs.credentials_ref"),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "options.observability.logs.push_url", testutil.ConvertConfigVariable(testConfigVarsMax["observability_logs_push_url"])),
|
||||
resource.TestCheckResourceAttrSet("stackit_loadbalancer.loadbalancer", "options.observability.metrics.credentials_ref"),
|
||||
resource.TestCheckResourceAttrPair("stackit_loadbalancer_observability_credential.metrics", "credentials_ref", "stackit_loadbalancer.loadbalancer", "options.observability.metrics.credentials_ref"),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer.loadbalancer", "options.observability.metrics.push_url", testutil.ConvertConfigVariable(testConfigVarsMax["observability_metrics_push_url"])),
|
||||
|
||||
// Loadbalancer observability credential resource
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.logs", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.logs", "display_name", testutil.ConvertConfigVariable(testConfigVarsMax["observability_credential_logs_name"])),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.logs", "username", testutil.ConvertConfigVariable(testConfigVarsMax["observability_credential_logs_username"])),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.logs", "password", testutil.ConvertConfigVariable(testConfigVarsMax["observability_credential_logs_password"])),
|
||||
resource.TestCheckResourceAttrSet("stackit_loadbalancer_observability_credential.logs", "credentials_ref"),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.metrics", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.metrics", "display_name", testutil.ConvertConfigVariable(testConfigVarsMax["observability_credential_metrics_name"])),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.metrics", "username", testutil.ConvertConfigVariable(testConfigVarsMax["observability_credential_metrics_username"])),
|
||||
resource.TestCheckResourceAttr("stackit_loadbalancer_observability_credential.metrics", "password", testutil.ConvertConfigVariable(testConfigVarsMax["observability_credential_metrics_password"])),
|
||||
resource.TestCheckResourceAttrSet("stackit_loadbalancer_observability_credential.metrics", "credentials_ref"),
|
||||
),
|
||||
},
|
||||
// Data source
|
||||
|
|
@ -271,6 +308,13 @@ func TestAccLoadBalancerResourceMax(t *testing.T) {
|
|||
|
||||
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"])),
|
||||
|
||||
resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "options.observability.logs.credentials_ref"),
|
||||
resource.TestCheckResourceAttrPair("stackit_loadbalancer_observability_credential.logs", "credentials_ref", "data.stackit_loadbalancer.loadbalancer", "options.observability.logs.credentials_ref"),
|
||||
resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "options.observability.logs.push_url", testutil.ConvertConfigVariable(testConfigVarsMax["observability_logs_push_url"])),
|
||||
resource.TestCheckResourceAttrSet("data.stackit_loadbalancer.loadbalancer", "options.observability.metrics.credentials_ref"),
|
||||
resource.TestCheckResourceAttrPair("stackit_loadbalancer_observability_credential.metrics", "credentials_ref", "data.stackit_loadbalancer.loadbalancer", "options.observability.metrics.credentials_ref"),
|
||||
resource.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "options.observability.metrics.push_url", testutil.ConvertConfigVariable(testConfigVarsMax["observability_metrics_push_url"])),
|
||||
)},
|
||||
// Import
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,6 +22,15 @@ variable "use_source_ip_address" {}
|
|||
variable "private_network_only" {}
|
||||
variable "acl" {}
|
||||
|
||||
variable "observability_logs_push_url" {}
|
||||
variable "observability_metrics_push_url" {}
|
||||
variable "observability_credential_logs_name" {}
|
||||
variable "observability_credential_logs_username" {}
|
||||
variable "observability_credential_logs_password" {}
|
||||
variable "observability_credential_metrics_name" {}
|
||||
variable "observability_credential_metrics_username" {}
|
||||
variable "observability_credential_metrics_password" {}
|
||||
|
||||
resource "stackit_network" "network" {
|
||||
project_id = var.project_id
|
||||
name = var.network_name
|
||||
|
|
@ -108,6 +117,31 @@ resource "stackit_loadbalancer" "loadbalancer" {
|
|||
options = {
|
||||
private_network_only = var.private_network_only
|
||||
acl = [var.acl]
|
||||
observability = {
|
||||
logs = {
|
||||
credentials_ref = stackit_loadbalancer_observability_credential.logs.credentials_ref
|
||||
push_url = var.observability_logs_push_url
|
||||
}
|
||||
metrics = {
|
||||
credentials_ref = stackit_loadbalancer_observability_credential.metrics.credentials_ref
|
||||
push_url = var.observability_metrics_push_url
|
||||
}
|
||||
}
|
||||
}
|
||||
external_address = stackit_public_ip.public_ip.ip
|
||||
}
|
||||
|
||||
resource "stackit_loadbalancer_observability_credential" "logs" {
|
||||
project_id = var.project_id
|
||||
display_name = var.observability_credential_logs_name
|
||||
username = var.observability_credential_logs_username
|
||||
password = var.observability_credential_logs_password
|
||||
}
|
||||
|
||||
resource "stackit_loadbalancer_observability_credential" "metrics" {
|
||||
project_id = var.project_id
|
||||
display_name = var.observability_credential_metrics_name
|
||||
username = var.observability_credential_metrics_username
|
||||
password = var.observability_credential_metrics_password
|
||||
}
|
||||
|
||||
|
|
|
|||
167
templates/guides/using_loadbalancer_with_observability.md.tmpl
Normal file
167
templates/guides/using_loadbalancer_with_observability.md.tmpl
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
---
|
||||
page_title: "Using the STACKIT Loadbalancer together with STACKIT Observability"
|
||||
---
|
||||
# Using the STACKIT Loadbalancer together with STACKIT Observability
|
||||
|
||||
## Overview
|
||||
|
||||
This guide explains how to configure the STACKIT Loadbalancer product to send metrics and logs to a STACKIT Observability instance.
|
||||
|
||||
1. **Set Up Providers**
|
||||
|
||||
Begin by configuring the STACKIT provider to connect to the STACKIT services.
|
||||
|
||||
```hcl
|
||||
provider "stackit" {
|
||||
default_region = "eu01"
|
||||
}
|
||||
```
|
||||
|
||||
2. **Create an Observability instance**
|
||||
|
||||
Establish a STACKIT Observability instance and its credentials.
|
||||
|
||||
```hcl
|
||||
resource "stackit_observability_instance" "observability01" {
|
||||
project_id = var.project_id_prod
|
||||
name = "example-instance"
|
||||
plan_name = "Observability-Monitoring-Medium-EU01"
|
||||
acl = ["0.0.0.0/0"]
|
||||
metrics_retention_days = 30
|
||||
metrics_retention_days_5m_downsampling = 10
|
||||
metrics_retention_days_1h_downsampling = 5
|
||||
}
|
||||
|
||||
resource "stackit_observability_credential" "observability01-credential" {
|
||||
project_id = var.project_id_prod
|
||||
instance_id = stackit_observability_instance.observability01.instance_id
|
||||
}
|
||||
```
|
||||
|
||||
3. **Create STACKIT Loadbalancer credentials reference**
|
||||
|
||||
Create a STACKIT Loadbalancer credentials which will be used in the STACKIT Loadbalancer resource as a reference.
|
||||
|
||||
```hcl
|
||||
resource "stackit_loadbalancer_observability_credential" "example" {
|
||||
project_id = var.project_id_prod
|
||||
display_name = "example-credentials"
|
||||
username = stackit_observability_credential.observability01-credential.username
|
||||
password = stackit_observability_credential.observability01-credential.password
|
||||
}
|
||||
```
|
||||
|
||||
4. **Create the STACKIT Loadbalancer**
|
||||
|
||||
```hcl
|
||||
# Create a network
|
||||
resource "stackit_network" "example_network" {
|
||||
project_id = var.project_id_prod
|
||||
name = "example-network"
|
||||
ipv4_nameservers = ["8.8.8.8"]
|
||||
ipv4_prefix = "192.168.0.0/25"
|
||||
labels = {
|
||||
"key" = "value"
|
||||
}
|
||||
routed = true
|
||||
}
|
||||
|
||||
# Create a network interface
|
||||
resource "stackit_network_interface" "nic" {
|
||||
project_id = var.project_id_prod
|
||||
network_id = stackit_network.example_network.network_id
|
||||
}
|
||||
|
||||
# Create a public IP for the load balancer
|
||||
resource "stackit_public_ip" "public-ip" {
|
||||
project_id = var.project_id_prod
|
||||
lifecycle {
|
||||
ignore_changes = [network_interface_id]
|
||||
}
|
||||
}
|
||||
|
||||
# Create a key pair for accessing the server instance
|
||||
resource "stackit_key_pair" "keypair" {
|
||||
name = "example-key-pair"
|
||||
# set the path of your public key file here
|
||||
public_key = chomp(file("/home/bob/.ssh/id_ed25519.pub"))
|
||||
}
|
||||
|
||||
# Create a server instance
|
||||
resource "stackit_server" "boot-from-image" {
|
||||
project_id = var.project_id_prod
|
||||
name = "example-server"
|
||||
boot_volume = {
|
||||
size = 64
|
||||
source_type = "image"
|
||||
source_id = "59838a89-51b1-4892-b57f-b3caf598ee2f" // Ubuntu 24.04
|
||||
}
|
||||
availability_zone = "eu01-1"
|
||||
machine_type = "g1.1"
|
||||
keypair_name = stackit_key_pair.keypair.name
|
||||
}
|
||||
|
||||
# Attach the network interface to the server
|
||||
resource "stackit_server_network_interface_attach" "nic-attachment" {
|
||||
project_id = var.project_id_prod
|
||||
server_id = stackit_server.boot-from-image.server_id
|
||||
network_interface_id = stackit_network_interface.nic.network_interface_id
|
||||
}
|
||||
|
||||
# Create a load balancer
|
||||
resource "stackit_loadbalancer" "example" {
|
||||
project_id = var.project_id_prod
|
||||
name = "example-load-balancer"
|
||||
target_pools = [
|
||||
{
|
||||
name = "example-target-pool"
|
||||
target_port = 80
|
||||
targets = [
|
||||
{
|
||||
display_name = stackit_server.boot-from-image.name
|
||||
ip = stackit_network_interface.nic.ipv4
|
||||
}
|
||||
]
|
||||
active_health_check = {
|
||||
healthy_threshold = 10
|
||||
interval = "3s"
|
||||
interval_jitter = "3s"
|
||||
timeout = "3s"
|
||||
unhealthy_threshold = 10
|
||||
}
|
||||
}
|
||||
]
|
||||
listeners = [
|
||||
{
|
||||
display_name = "example-listener"
|
||||
port = 80
|
||||
protocol = "PROTOCOL_TCP"
|
||||
target_pool = "example-target-pool"
|
||||
}
|
||||
]
|
||||
networks = [
|
||||
{
|
||||
network_id = stackit_network.example_network.network_id
|
||||
role = "ROLE_LISTENERS_AND_TARGETS"
|
||||
}
|
||||
]
|
||||
external_address = stackit_public_ip.public-ip.ip
|
||||
options = {
|
||||
private_network_only = false
|
||||
observability = {
|
||||
logs = {
|
||||
# uses the load balancer credential from the last step
|
||||
credentials_ref = stackit_loadbalancer_observability_credential.example.credentials_ref
|
||||
# uses the observability instance from step 1
|
||||
push_url = stackit_observability_instance.observability01.logs_push_url
|
||||
}
|
||||
metrics = {
|
||||
# uses the load balancer credential from the last step
|
||||
credentials_ref = stackit_loadbalancer_observability_credential.example.credentials_ref
|
||||
# uses the observability instance from step 1
|
||||
push_url = stackit_observability_instance.observability01.metrics_push_url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue