Skip to content

Commit 2d8a298

Browse files
Christian HammChristian Hamm
authored andcommitted
Added support for the plan_id field used to create or change a load balancer's plan to a higher one (e.g. p250, p750, ...).
1 parent c693715 commit 2d8a298

6 files changed

Lines changed: 164 additions & 0 deletions

File tree

docs/data-sources/loadbalancer.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ data "stackit_loadbalancer" "example" {
3838
- `listeners` (Attributes List) List of all listeners which will accept traffic. Limited to 20. (see [below for nested schema](#nestedatt--listeners))
3939
- `networks` (Attributes List) List of networks that listeners and targets reside in. (see [below for nested schema](#nestedatt--networks))
4040
- `options` (Attributes) Defines any optional functionality you want to have enabled on your load balancer. (see [below for nested schema](#nestedatt--options))
41+
- `plan_id` (String) The service plan ID. Defaults to p10. See the API docs for a list of available plans at: https://docs.api.stackit.cloud/documentation/load-balancer/version/v1#tag/APIService/operation/APIService_ListPlans
4142
- `private_address` (String) Transient private Load Balancer IP address. It can change any time.
4243
- `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))
4344

docs/resources/loadbalancer.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ resource "stackit_server_network_interface_attach" "nic-attachment" {
7474
resource "stackit_loadbalancer" "example" {
7575
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
7676
name = "example-load-balancer"
77+
plan_id = "p10"
7778
target_pools = [
7879
{
7980
name = "example-target-pool"
@@ -129,6 +130,7 @@ resource "stackit_loadbalancer" "example" {
129130
### Optional
130131

131132
- `options` (Attributes) Defines any optional functionality you want to have enabled on your load balancer. (see [below for nested schema](#nestedatt--options))
133+
- `plan_id` (String) The service plan ID. Defaults to p10. See the API docs for a list of available plans at: https://docs.api.stackit.cloud/documentation/load-balancer/version/v1#tag/APIService/operation/APIService_ListPlans
132134
- `region` (String) The resource region. If not defined, the provider region is used.
133135

134136
### Read-Only

examples/resources/stackit_loadbalancer/resource.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ resource "stackit_server_network_interface_attach" "nic-attachment" {
5555
resource "stackit_loadbalancer" "example" {
5656
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
5757
name = "example-load-balancer"
58+
plan_id = "p10"
5859
target_pools = [
5960
{
6061
name = "example-target-pool"

stackit/internal/services/loadbalancer/loadbalancer/datasource.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ func (r *loadBalancerDataSource) Schema(_ context.Context, _ datasource.SchemaRe
7272
"protocol": "Protocol is the highest network protocol we understand to load balance.",
7373
"target_pool": "Reference target pool by target pool name.",
7474
"name": "Load balancer name.",
75+
"plan_id": "The service plan ID. Defaults to p10. See the API docs for a list of available plans at: https://docs.api.stackit.cloud/documentation/load-balancer/version/v1#tag/APIService/operation/APIService_ListPlans",
7576
"networks": "List of networks that listeners and targets reside in.",
7677
"network_id": "Openstack network ID.",
7778
"role": "The role defines how the load balancer is using the network.",
@@ -122,6 +123,10 @@ func (r *loadBalancerDataSource) Schema(_ context.Context, _ datasource.SchemaRe
122123
Description: descriptions["external_address"],
123124
Computed: true,
124125
},
126+
"plan_id": schema.StringAttribute{
127+
Description: descriptions["plan_id"],
128+
Computed: true,
129+
},
125130
"listeners": schema.ListNestedAttribute{
126131
Description: descriptions["listeners"],
127132
Computed: true,

stackit/internal/services/loadbalancer/loadbalancer/resource.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type Model struct {
5252
ExternalAddress types.String `tfsdk:"external_address"`
5353
Listeners types.List `tfsdk:"listeners"`
5454
Name types.String `tfsdk:"name"`
55+
PlanId types.String `tfsdk:"plan_id"`
5556
Networks types.List `tfsdk:"networks"`
5657
Options types.Object `tfsdk:"options"`
5758
PrivateAddress types.String `tfsdk:"private_address"`
@@ -268,6 +269,7 @@ func (r *loadBalancerResource) Schema(_ context.Context, _ resource.SchemaReques
268269
"protocol": "Protocol is the highest network protocol we understand to load balance. " + utils.SupportedValuesDocumentation(protocolOptions),
269270
"target_pool": "Reference target pool by target pool name.",
270271
"name": "Load balancer name.",
272+
"plan_id": "The service plan ID. Defaults to p10. See the API docs for a list of available plans at: https://docs.api.stackit.cloud/documentation/load-balancer/version/v1#tag/APIService/operation/APIService_ListPlans",
271273
"networks": "List of networks that listeners and targets reside in.",
272274
"network_id": "Openstack network ID.",
273275
"role": "The role defines how the load balancer is using the network. " + utils.SupportedValuesDocumentation(roleOptions),
@@ -332,6 +334,14 @@ The example below creates the supporting infrastructure using the STACKIT Terraf
332334
stringplanmodifier.RequiresReplace(),
333335
},
334336
},
337+
"plan_id": schema.StringAttribute{
338+
Description: descriptions["plan_id"],
339+
Optional: true,
340+
Computed: true,
341+
PlanModifiers: []planmodifier.String{
342+
stringplanmodifier.RequiresReplace(),
343+
},
344+
},
335345
"listeners": schema.ListNestedAttribute{
336346
Description: descriptions["listeners"],
337347
Required: true,
@@ -864,6 +874,7 @@ func toCreatePayload(ctx context.Context, model *Model) (*loadbalancer.CreateLoa
864874
ExternalAddress: conversion.StringValueToPointer(model.ExternalAddress),
865875
Listeners: listenersPayload,
866876
Name: conversion.StringValueToPointer(model.Name),
877+
PlanId: conversion.StringValueToPointer(model.PlanId),
867878
Networks: networksPayload,
868879
Options: optionsPayload,
869880
TargetPools: targetPoolsPayload,
@@ -1178,6 +1189,7 @@ func mapFields(ctx context.Context, lb *loadbalancer.LoadBalancer, m *Model, reg
11781189
strings.Join(idParts, core.Separator),
11791190
)
11801191

1192+
m.PlanId = types.StringPointerValue(lb.PlanId)
11811193
m.ExternalAddress = types.StringPointerValue(lb.ExternalAddress)
11821194
m.PrivateAddress = types.StringPointerValue(lb.PrivateAddress)
11831195

stackit/internal/services/loadbalancer/loadbalancer/resource_test.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,149 @@ func TestToCreatePayload(t *testing.T) {
179179
},
180180
true,
181181
},
182+
{
183+
"service_plan_ok",
184+
&Model{
185+
PlanId: types.StringValue("p10"),
186+
ExternalAddress: types.StringValue("external_address"),
187+
Listeners: types.ListValueMust(types.ObjectType{AttrTypes: listenerTypes}, []attr.Value{
188+
types.ObjectValueMust(listenerTypes, map[string]attr.Value{
189+
"display_name": types.StringValue("display_name"),
190+
"port": types.Int64Value(80),
191+
"protocol": types.StringValue(string(loadbalancer.LISTENERPROTOCOL_TCP)),
192+
"server_name_indicators": types.ListValueMust(types.ObjectType{AttrTypes: serverNameIndicatorTypes}, []attr.Value{
193+
types.ObjectValueMust(
194+
serverNameIndicatorTypes,
195+
map[string]attr.Value{
196+
"name": types.StringValue("domain.com"),
197+
},
198+
),
199+
},
200+
),
201+
"target_pool": types.StringValue("target_pool"),
202+
}),
203+
}),
204+
Name: types.StringValue("name"),
205+
Networks: types.ListValueMust(types.ObjectType{AttrTypes: networkTypes}, []attr.Value{
206+
types.ObjectValueMust(networkTypes, map[string]attr.Value{
207+
"network_id": types.StringValue("network_id"),
208+
"role": types.StringValue(string(loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS)),
209+
}),
210+
types.ObjectValueMust(networkTypes, map[string]attr.Value{
211+
"network_id": types.StringValue("network_id_2"),
212+
"role": types.StringValue(string(loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS)),
213+
}),
214+
}),
215+
Options: types.ObjectValueMust(
216+
optionsTypes,
217+
map[string]attr.Value{
218+
"acl": types.SetValueMust(
219+
types.StringType,
220+
[]attr.Value{types.StringValue("cidr")}),
221+
"private_network_only": types.BoolValue(true),
222+
"observability": types.ObjectValueMust(observabilityTypes, map[string]attr.Value{
223+
"logs": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
224+
"credentials_ref": types.StringValue("logs-credentials_ref"),
225+
"push_url": types.StringValue("logs-push_url"),
226+
}),
227+
"metrics": types.ObjectValueMust(observabilityOptionTypes, map[string]attr.Value{
228+
"credentials_ref": types.StringValue("metrics-credentials_ref"),
229+
"push_url": types.StringValue("metrics-push_url"),
230+
}),
231+
}),
232+
},
233+
),
234+
TargetPools: types.ListValueMust(types.ObjectType{AttrTypes: targetPoolTypes}, []attr.Value{
235+
types.ObjectValueMust(targetPoolTypes, map[string]attr.Value{
236+
"active_health_check": types.ObjectValueMust(activeHealthCheckTypes, map[string]attr.Value{
237+
"healthy_threshold": types.Int64Value(1),
238+
"interval": types.StringValue("2s"),
239+
"interval_jitter": types.StringValue("3s"),
240+
"timeout": types.StringValue("4s"),
241+
"unhealthy_threshold": types.Int64Value(5),
242+
}),
243+
"name": types.StringValue("name"),
244+
"target_port": types.Int64Value(80),
245+
"targets": types.ListValueMust(types.ObjectType{AttrTypes: targetTypes}, []attr.Value{
246+
types.ObjectValueMust(targetTypes, map[string]attr.Value{
247+
"display_name": types.StringValue("display_name"),
248+
"ip": types.StringValue("ip"),
249+
}),
250+
}),
251+
"session_persistence": types.ObjectValueMust(sessionPersistenceTypes, map[string]attr.Value{
252+
"use_source_ip_address": types.BoolValue(true),
253+
}),
254+
}),
255+
}),
256+
},
257+
&loadbalancer.CreateLoadBalancerPayload{
258+
PlanId: utils.Ptr("p10"),
259+
ExternalAddress: utils.Ptr("external_address"),
260+
Listeners: &[]loadbalancer.Listener{
261+
{
262+
DisplayName: utils.Ptr("display_name"),
263+
Port: utils.Ptr(int64(80)),
264+
Protocol: loadbalancer.LISTENERPROTOCOL_TCP.Ptr(),
265+
ServerNameIndicators: &[]loadbalancer.ServerNameIndicator{
266+
{
267+
Name: utils.Ptr("domain.com"),
268+
},
269+
},
270+
TargetPool: utils.Ptr("target_pool"),
271+
},
272+
},
273+
Name: utils.Ptr("name"),
274+
Networks: &[]loadbalancer.Network{
275+
{
276+
NetworkId: utils.Ptr("network_id"),
277+
Role: loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS.Ptr(),
278+
},
279+
{
280+
NetworkId: utils.Ptr("network_id_2"),
281+
Role: loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS.Ptr(),
282+
},
283+
},
284+
Options: &loadbalancer.LoadBalancerOptions{
285+
AccessControl: &loadbalancer.LoadbalancerOptionAccessControl{
286+
AllowedSourceRanges: &[]string{"cidr"},
287+
},
288+
PrivateNetworkOnly: utils.Ptr(true),
289+
Observability: &loadbalancer.LoadbalancerOptionObservability{
290+
Logs: &loadbalancer.LoadbalancerOptionLogs{
291+
CredentialsRef: utils.Ptr("logs-credentials_ref"),
292+
PushUrl: utils.Ptr("logs-push_url"),
293+
},
294+
Metrics: &loadbalancer.LoadbalancerOptionMetrics{
295+
CredentialsRef: utils.Ptr("metrics-credentials_ref"),
296+
PushUrl: utils.Ptr("metrics-push_url"),
297+
},
298+
},
299+
},
300+
TargetPools: &[]loadbalancer.TargetPool{
301+
{
302+
ActiveHealthCheck: &loadbalancer.ActiveHealthCheck{
303+
HealthyThreshold: utils.Ptr(int64(1)),
304+
Interval: utils.Ptr("2s"),
305+
IntervalJitter: utils.Ptr("3s"),
306+
Timeout: utils.Ptr("4s"),
307+
UnhealthyThreshold: utils.Ptr(int64(5)),
308+
},
309+
Name: utils.Ptr("name"),
310+
TargetPort: utils.Ptr(int64(80)),
311+
Targets: &[]loadbalancer.Target{
312+
{
313+
DisplayName: utils.Ptr("display_name"),
314+
Ip: utils.Ptr("ip"),
315+
},
316+
},
317+
SessionPersistence: &loadbalancer.SessionPersistence{
318+
UseSourceIpAddress: utils.Ptr(true),
319+
},
320+
},
321+
},
322+
},
323+
true,
324+
},
182325
{
183326
"nil_model",
184327
nil,

0 commit comments

Comments
 (0)