feat(loadbalancer): support service plan attribute (#858)
relates to STACKITLB-250 Co-authored-by: Christian Hamm <Christian.Hamm@mail.schwarz> Co-authored-by: Ruben Hönle <git@hoenle.xyz>
This commit is contained in:
parent
3255f1e28d
commit
ab232d6cb7
8 changed files with 174 additions and 0 deletions
|
|
@ -38,6 +38,7 @@ data "stackit_loadbalancer" "example" {
|
|||
- `listeners` (Attributes List) List of all listeners which will accept traffic. Limited to 20. (see [below for nested schema](#nestedatt--listeners))
|
||||
- `networks` (Attributes List) List of networks that listeners and targets reside in. (see [below for nested schema](#nestedatt--networks))
|
||||
- `options` (Attributes) Defines any optional functionality you want to have enabled on your load balancer. (see [below for nested schema](#nestedatt--options))
|
||||
- `plan_id` (String) The service plan ID. If not defined, the default service plan is `p10`. Possible values are: `p10`, `p50`, `p250`, `p750`.
|
||||
- `private_address` (String) Transient private Load Balancer IP address. It can change any time.
|
||||
- `target_pools` (Attributes List) List of all target pools which will be used in the Load Balancer. Limited to 20. (see [below for nested schema](#nestedatt--target_pools))
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ resource "stackit_server" "boot-from-image" {
|
|||
resource "stackit_loadbalancer" "example" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-load-balancer"
|
||||
plan_id = "p10"
|
||||
target_pools = [
|
||||
{
|
||||
name = "example-target-pool"
|
||||
|
|
@ -125,6 +126,7 @@ resource "stackit_loadbalancer" "example" {
|
|||
|
||||
- `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))
|
||||
- `plan_id` (String) The service plan ID. If not defined, the default service plan is `p10`. Possible values are: `p10`, `p50`, `p250`, `p750`.
|
||||
- `region` (String) The resource region. If not defined, the provider region is used.
|
||||
|
||||
### Read-Only
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ resource "stackit_server" "boot-from-image" {
|
|||
resource "stackit_loadbalancer" "example" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "example-load-balancer"
|
||||
plan_id = "p10"
|
||||
target_pools = [
|
||||
{
|
||||
name = "example-target-pool"
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ 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) {
|
||||
servicePlanOptions := []string{"p10", "p50", "p250", "p750"}
|
||||
|
||||
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`\".",
|
||||
|
|
@ -72,6 +74,7 @@ func (r *loadBalancerDataSource) Schema(_ context.Context, _ datasource.SchemaRe
|
|||
"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.",
|
||||
"plan_id": "The service plan ID. If not defined, the default service plan is `p10`. " + utils.FormatPossibleValues(servicePlanOptions...),
|
||||
"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.",
|
||||
|
|
@ -122,6 +125,10 @@ func (r *loadBalancerDataSource) Schema(_ context.Context, _ datasource.SchemaRe
|
|||
Description: descriptions["external_address"],
|
||||
Computed: true,
|
||||
},
|
||||
"plan_id": schema.StringAttribute{
|
||||
Description: descriptions["plan_id"],
|
||||
Computed: true,
|
||||
},
|
||||
"listeners": schema.ListNestedAttribute{
|
||||
Description: descriptions["listeners"],
|
||||
Computed: true,
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ type Model struct {
|
|||
ExternalAddress types.String `tfsdk:"external_address"`
|
||||
Listeners types.List `tfsdk:"listeners"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
PlanId types.String `tfsdk:"plan_id"`
|
||||
Networks types.List `tfsdk:"networks"`
|
||||
Options types.Object `tfsdk:"options"`
|
||||
PrivateAddress types.String `tfsdk:"private_address"`
|
||||
|
|
@ -295,6 +296,7 @@ func (r *loadBalancerResource) Configure(ctx context.Context, req resource.Confi
|
|||
func (r *loadBalancerResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
protocolOptions := []string{"PROTOCOL_UNSPECIFIED", "PROTOCOL_TCP", "PROTOCOL_UDP", "PROTOCOL_TCP_PROXY", "PROTOCOL_TLS_PASSTHROUGH"}
|
||||
roleOptions := []string{"ROLE_UNSPECIFIED", "ROLE_LISTENERS_AND_TARGETS", "ROLE_LISTENERS", "ROLE_TARGETS"}
|
||||
servicePlanOptions := []string{"p10", "p50", "p250", "p750"}
|
||||
|
||||
descriptions := map[string]string{
|
||||
"main": "Load Balancer resource schema.",
|
||||
|
|
@ -306,6 +308,7 @@ func (r *loadBalancerResource) Schema(_ context.Context, _ resource.SchemaReques
|
|||
"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.",
|
||||
"plan_id": "The service plan ID. If not defined, the default service plan is `p10`. " + utils.FormatPossibleValues(servicePlanOptions...),
|
||||
"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),
|
||||
|
|
@ -370,6 +373,14 @@ The example below creates the supporting infrastructure using the STACKIT Terraf
|
|||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"plan_id": schema.StringAttribute{
|
||||
Description: descriptions["plan_id"],
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"listeners": schema.ListNestedAttribute{
|
||||
Description: descriptions["listeners"],
|
||||
Required: true,
|
||||
|
|
@ -899,6 +910,7 @@ func toCreatePayload(ctx context.Context, model *Model) (*loadbalancer.CreateLoa
|
|||
ExternalAddress: conversion.StringValueToPointer(model.ExternalAddress),
|
||||
Listeners: listenersPayload,
|
||||
Name: conversion.StringValueToPointer(model.Name),
|
||||
PlanId: conversion.StringValueToPointer(model.PlanId),
|
||||
Networks: networksPayload,
|
||||
Options: optionsPayload,
|
||||
TargetPools: targetPoolsPayload,
|
||||
|
|
@ -1206,6 +1218,7 @@ func mapFields(ctx context.Context, lb *loadbalancer.LoadBalancer, m *Model, reg
|
|||
m.Name = types.StringValue(name)
|
||||
m.Id = utils.BuildInternalTerraformId(m.ProjectId.ValueString(), m.Region.ValueString(), name)
|
||||
|
||||
m.PlanId = types.StringPointerValue(lb.PlanId)
|
||||
m.ExternalAddress = types.StringPointerValue(lb.ExternalAddress)
|
||||
m.PrivateAddress = types.StringPointerValue(lb.PrivateAddress)
|
||||
|
||||
|
|
|
|||
|
|
@ -184,6 +184,149 @@ func TestToCreatePayload(t *testing.T) {
|
|||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"service_plan_ok",
|
||||
&Model{
|
||||
PlanId: types.StringValue("p10"),
|
||||
ExternalAddress: types.StringValue("external_address"),
|
||||
Listeners: types.ListValueMust(types.ObjectType{AttrTypes: listenerTypes}, []attr.Value{
|
||||
types.ObjectValueMust(listenerTypes, map[string]attr.Value{
|
||||
"display_name": types.StringValue("display_name"),
|
||||
"port": types.Int64Value(80),
|
||||
"protocol": types.StringValue(string(loadbalancer.LISTENERPROTOCOL_TCP)),
|
||||
"server_name_indicators": types.ListValueMust(types.ObjectType{AttrTypes: serverNameIndicatorTypes}, []attr.Value{
|
||||
types.ObjectValueMust(
|
||||
serverNameIndicatorTypes,
|
||||
map[string]attr.Value{
|
||||
"name": types.StringValue("domain.com"),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
"target_pool": types.StringValue("target_pool"),
|
||||
}),
|
||||
}),
|
||||
Name: types.StringValue("name"),
|
||||
Networks: types.ListValueMust(types.ObjectType{AttrTypes: networkTypes}, []attr.Value{
|
||||
types.ObjectValueMust(networkTypes, map[string]attr.Value{
|
||||
"network_id": types.StringValue("network_id"),
|
||||
"role": types.StringValue(string(loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS)),
|
||||
}),
|
||||
types.ObjectValueMust(networkTypes, map[string]attr.Value{
|
||||
"network_id": types.StringValue("network_id_2"),
|
||||
"role": types.StringValue(string(loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS)),
|
||||
}),
|
||||
}),
|
||||
Options: types.ObjectValueMust(
|
||||
optionsTypes,
|
||||
map[string]attr.Value{
|
||||
"acl": types.SetValueMust(
|
||||
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{
|
||||
types.ObjectValueMust(targetPoolTypes, map[string]attr.Value{
|
||||
"active_health_check": types.ObjectValueMust(activeHealthCheckTypes, map[string]attr.Value{
|
||||
"healthy_threshold": types.Int64Value(1),
|
||||
"interval": types.StringValue("2s"),
|
||||
"interval_jitter": types.StringValue("3s"),
|
||||
"timeout": types.StringValue("4s"),
|
||||
"unhealthy_threshold": types.Int64Value(5),
|
||||
}),
|
||||
"name": types.StringValue("name"),
|
||||
"target_port": types.Int64Value(80),
|
||||
"targets": types.ListValueMust(types.ObjectType{AttrTypes: targetTypes}, []attr.Value{
|
||||
types.ObjectValueMust(targetTypes, map[string]attr.Value{
|
||||
"display_name": types.StringValue("display_name"),
|
||||
"ip": types.StringValue("ip"),
|
||||
}),
|
||||
}),
|
||||
"session_persistence": types.ObjectValueMust(sessionPersistenceTypes, map[string]attr.Value{
|
||||
"use_source_ip_address": types.BoolValue(true),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
&loadbalancer.CreateLoadBalancerPayload{
|
||||
PlanId: utils.Ptr("p10"),
|
||||
ExternalAddress: utils.Ptr("external_address"),
|
||||
Listeners: &[]loadbalancer.Listener{
|
||||
{
|
||||
DisplayName: utils.Ptr("display_name"),
|
||||
Port: utils.Ptr(int64(80)),
|
||||
Protocol: loadbalancer.LISTENERPROTOCOL_TCP.Ptr(),
|
||||
ServerNameIndicators: &[]loadbalancer.ServerNameIndicator{
|
||||
{
|
||||
Name: utils.Ptr("domain.com"),
|
||||
},
|
||||
},
|
||||
TargetPool: utils.Ptr("target_pool"),
|
||||
},
|
||||
},
|
||||
Name: utils.Ptr("name"),
|
||||
Networks: &[]loadbalancer.Network{
|
||||
{
|
||||
NetworkId: utils.Ptr("network_id"),
|
||||
Role: loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS.Ptr(),
|
||||
},
|
||||
{
|
||||
NetworkId: utils.Ptr("network_id_2"),
|
||||
Role: loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS.Ptr(),
|
||||
},
|
||||
},
|
||||
Options: &loadbalancer.LoadBalancerOptions{
|
||||
AccessControl: &loadbalancer.LoadbalancerOptionAccessControl{
|
||||
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{
|
||||
{
|
||||
ActiveHealthCheck: &loadbalancer.ActiveHealthCheck{
|
||||
HealthyThreshold: utils.Ptr(int64(1)),
|
||||
Interval: utils.Ptr("2s"),
|
||||
IntervalJitter: utils.Ptr("3s"),
|
||||
Timeout: utils.Ptr("4s"),
|
||||
UnhealthyThreshold: utils.Ptr(int64(5)),
|
||||
},
|
||||
Name: utils.Ptr("name"),
|
||||
TargetPort: utils.Ptr(int64(80)),
|
||||
Targets: &[]loadbalancer.Target{
|
||||
{
|
||||
DisplayName: utils.Ptr("display_name"),
|
||||
Ip: utils.Ptr("ip"),
|
||||
},
|
||||
},
|
||||
SessionPersistence: &loadbalancer.SessionPersistence{
|
||||
UseSourceIpAddress: utils.Ptr(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nil_model",
|
||||
nil,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ var resourceMaxConfig string
|
|||
|
||||
var testConfigVarsMin = config.Variables{
|
||||
"project_id": config.StringVariable(testutil.ProjectId),
|
||||
"plan_id": config.StringVariable("p10"),
|
||||
"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))),
|
||||
|
|
@ -47,6 +48,7 @@ var testConfigVarsMin = config.Variables{
|
|||
|
||||
var testConfigVarsMax = config.Variables{
|
||||
"project_id": config.StringVariable(testutil.ProjectId),
|
||||
"plan_id": config.StringVariable("p10"),
|
||||
"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))),
|
||||
|
|
@ -146,6 +148,7 @@ func TestAccLoadBalancerResourceMin(t *testing.T) {
|
|||
// Load balancer instance
|
||||
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.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "plan_id", testutil.ConvertConfigVariable(testConfigVarsMin["plan_id"])),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"data.stackit_loadbalancer.loadbalancer", "project_id",
|
||||
"stackit_loadbalancer.loadbalancer", "project_id",
|
||||
|
|
@ -218,6 +221,7 @@ func TestAccLoadBalancerResourceMax(t *testing.T) {
|
|||
// 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", "plan_id", testutil.ConvertConfigVariable(testConfigVarsMax["plan_id"])),
|
||||
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"])),
|
||||
|
|
@ -278,6 +282,7 @@ func TestAccLoadBalancerResourceMax(t *testing.T) {
|
|||
// 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.TestCheckResourceAttr("data.stackit_loadbalancer.loadbalancer", "plan_id", testutil.ConvertConfigVariable(testConfigVarsMax["plan_id"])),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"data.stackit_loadbalancer.loadbalancer", "project_id",
|
||||
"stackit_loadbalancer.loadbalancer", "project_id",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ variable "network_name" {}
|
|||
variable "server_name" {}
|
||||
|
||||
variable "loadbalancer_name" {}
|
||||
variable "plan_id" {}
|
||||
variable "target_pool_name" {}
|
||||
variable "target_port" {}
|
||||
variable "target_display_name" {}
|
||||
|
|
@ -73,6 +74,7 @@ resource "stackit_server" "server" {
|
|||
resource "stackit_loadbalancer" "loadbalancer" {
|
||||
project_id = var.project_id
|
||||
name = var.loadbalancer_name
|
||||
plan_id = var.plan_id
|
||||
target_pools = [
|
||||
{
|
||||
name = var.target_pool_name
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue