* Finish implementation for CRUD functionality * Register resource in the provider * Adjustments to resource * Implement data source * Unregister resource and data source from provider * Fix external_address schema field * Remove oneOf validators from datasource
419 lines
11 KiB
Go
419 lines
11 KiB
Go
package loadbalancer
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
|
"github.com/stackitcloud/stackit-sdk-go/core/utils"
|
|
"github.com/stackitcloud/stackit-sdk-go/services/loadbalancer"
|
|
)
|
|
|
|
func TestToCreatePayload(t *testing.T) {
|
|
tests := []struct {
|
|
description string
|
|
input *Model
|
|
expected *loadbalancer.CreateLoadBalancerPayload
|
|
isValid bool
|
|
}{
|
|
{
|
|
"default_values_ok",
|
|
&Model{},
|
|
&loadbalancer.CreateLoadBalancerPayload{
|
|
ExternalAddress: nil,
|
|
Listeners: nil,
|
|
Name: nil,
|
|
Networks: nil,
|
|
Options: &loadbalancer.LoadBalancerOptions{
|
|
AccessControl: &loadbalancer.LoadbalancerOptionAccessControl{
|
|
AllowedSourceRanges: nil,
|
|
},
|
|
PrivateNetworkOnly: nil,
|
|
},
|
|
TargetPools: nil,
|
|
},
|
|
true,
|
|
},
|
|
{
|
|
"simple_values_ok",
|
|
&Model{
|
|
ExternalAddress: types.StringValue("external_address"),
|
|
Listeners: []Listener{
|
|
{
|
|
DisplayName: types.StringValue("display_name"),
|
|
Port: types.Int64Value(80),
|
|
Protocol: types.StringValue("protocol"),
|
|
TargetPool: types.StringValue("target_pool"),
|
|
},
|
|
},
|
|
Name: types.StringValue("name"),
|
|
Networks: []Network{
|
|
{
|
|
NetworkId: types.StringValue("network_id"),
|
|
Role: types.StringValue("role"),
|
|
},
|
|
{
|
|
NetworkId: types.StringValue("network_id_2"),
|
|
Role: types.StringValue("role_2"),
|
|
},
|
|
},
|
|
Options: types.ObjectValueMust(
|
|
optionsTypes,
|
|
map[string]attr.Value{
|
|
"acl": types.SetValueMust(
|
|
types.StringType,
|
|
[]attr.Value{types.StringValue("cidr")}),
|
|
"private_network_only": types.BoolValue(true),
|
|
},
|
|
),
|
|
TargetPools: []TargetPool{
|
|
{
|
|
ActiveHealthCheck: 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"),
|
|
TargetPort: types.Int64Value(80),
|
|
Targets: []Target{
|
|
{
|
|
DisplayName: types.StringValue("display_name"),
|
|
Ip: types.StringValue("ip"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
&loadbalancer.CreateLoadBalancerPayload{
|
|
ExternalAddress: utils.Ptr("external_address"),
|
|
Listeners: utils.Ptr([]loadbalancer.Listener{
|
|
{
|
|
DisplayName: utils.Ptr("display_name"),
|
|
Port: utils.Ptr(int64(80)),
|
|
Protocol: utils.Ptr("protocol"),
|
|
TargetPool: utils.Ptr("target_pool"),
|
|
},
|
|
}),
|
|
Name: utils.Ptr("name"),
|
|
Networks: utils.Ptr([]loadbalancer.Network{
|
|
{
|
|
NetworkId: utils.Ptr("network_id"),
|
|
Role: utils.Ptr("role"),
|
|
},
|
|
{
|
|
NetworkId: utils.Ptr("network_id_2"),
|
|
Role: utils.Ptr("role_2"),
|
|
},
|
|
}),
|
|
Options: utils.Ptr(loadbalancer.LoadBalancerOptions{
|
|
AccessControl: &loadbalancer.LoadbalancerOptionAccessControl{
|
|
AllowedSourceRanges: utils.Ptr([]string{"cidr"}),
|
|
},
|
|
PrivateNetworkOnly: utils.Ptr(true),
|
|
}),
|
|
TargetPools: utils.Ptr([]loadbalancer.TargetPool{
|
|
{
|
|
ActiveHealthCheck: utils.Ptr(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: utils.Ptr([]loadbalancer.Target{
|
|
{
|
|
DisplayName: utils.Ptr("display_name"),
|
|
Ip: utils.Ptr("ip"),
|
|
},
|
|
}),
|
|
},
|
|
}),
|
|
},
|
|
true,
|
|
},
|
|
{
|
|
"nil_model",
|
|
nil,
|
|
nil,
|
|
false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.description, func(t *testing.T) {
|
|
output, err := toCreatePayload(context.Background(), tt.input)
|
|
if !tt.isValid && err == nil {
|
|
t.Fatalf("Should have failed")
|
|
}
|
|
if tt.isValid && err != nil {
|
|
t.Fatalf("Should not have failed: %v", err)
|
|
}
|
|
if tt.isValid {
|
|
diff := cmp.Diff(output, tt.expected)
|
|
if diff != "" {
|
|
t.Fatalf("Data does not match: %s", diff)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestToTargetPoolUpdatePayload(t *testing.T) {
|
|
tests := []struct {
|
|
description string
|
|
input *TargetPool
|
|
expected *loadbalancer.UpdateTargetPoolPayload
|
|
isValid bool
|
|
}{
|
|
{
|
|
"default_values_ok",
|
|
&TargetPool{},
|
|
&loadbalancer.UpdateTargetPoolPayload{},
|
|
true,
|
|
},
|
|
{
|
|
"simple_values_ok",
|
|
&TargetPool{
|
|
ActiveHealthCheck: 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"),
|
|
TargetPort: types.Int64Value(80),
|
|
Targets: []Target{
|
|
{
|
|
DisplayName: types.StringValue("display_name"),
|
|
Ip: types.StringValue("ip"),
|
|
},
|
|
},
|
|
},
|
|
&loadbalancer.UpdateTargetPoolPayload{
|
|
ActiveHealthCheck: utils.Ptr(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: utils.Ptr([]loadbalancer.Target{
|
|
{
|
|
DisplayName: utils.Ptr("display_name"),
|
|
Ip: utils.Ptr("ip"),
|
|
},
|
|
}),
|
|
},
|
|
true,
|
|
},
|
|
{
|
|
"nil_target_pool",
|
|
nil,
|
|
nil,
|
|
false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.description, func(t *testing.T) {
|
|
output, err := toTargetPoolUpdatePayload(context.Background(), tt.input)
|
|
if !tt.isValid && err == nil {
|
|
t.Fatalf("Should have failed")
|
|
}
|
|
if tt.isValid && err != nil {
|
|
t.Fatalf("Should not have failed: %v", err)
|
|
}
|
|
if tt.isValid {
|
|
diff := cmp.Diff(output, tt.expected)
|
|
if diff != "" {
|
|
t.Fatalf("Data does not match: %s", diff)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMapFields(t *testing.T) {
|
|
tests := []struct {
|
|
description string
|
|
input *loadbalancer.LoadBalancer
|
|
expected *Model
|
|
isValid bool
|
|
}{
|
|
{
|
|
"default_values_ok",
|
|
&loadbalancer.LoadBalancer{
|
|
ExternalAddress: nil,
|
|
Listeners: nil,
|
|
Name: utils.Ptr("name"),
|
|
Networks: nil,
|
|
Options: &loadbalancer.LoadBalancerOptions{
|
|
AccessControl: &loadbalancer.LoadbalancerOptionAccessControl{
|
|
AllowedSourceRanges: nil,
|
|
},
|
|
PrivateNetworkOnly: nil,
|
|
},
|
|
TargetPools: nil,
|
|
},
|
|
&Model{
|
|
Id: types.StringValue("pid,name"),
|
|
ProjectId: types.StringValue("pid"),
|
|
Name: types.StringValue("name"),
|
|
},
|
|
true,
|
|
},
|
|
|
|
{
|
|
"simple_values_ok",
|
|
&loadbalancer.LoadBalancer{
|
|
ExternalAddress: utils.Ptr("external_address"),
|
|
Listeners: utils.Ptr([]loadbalancer.Listener{
|
|
{
|
|
DisplayName: utils.Ptr("display_name"),
|
|
Port: utils.Ptr(int64(80)),
|
|
Protocol: utils.Ptr("protocol"),
|
|
TargetPool: utils.Ptr("target_pool"),
|
|
},
|
|
}),
|
|
Name: utils.Ptr("name"),
|
|
Networks: utils.Ptr([]loadbalancer.Network{
|
|
{
|
|
NetworkId: utils.Ptr("network_id"),
|
|
Role: utils.Ptr("role"),
|
|
},
|
|
{
|
|
NetworkId: utils.Ptr("network_id_2"),
|
|
Role: utils.Ptr("role_2"),
|
|
},
|
|
}),
|
|
Options: utils.Ptr(loadbalancer.LoadBalancerOptions{
|
|
AccessControl: &loadbalancer.LoadbalancerOptionAccessControl{
|
|
AllowedSourceRanges: utils.Ptr([]string{"cidr"}),
|
|
},
|
|
PrivateNetworkOnly: utils.Ptr(true),
|
|
}),
|
|
TargetPools: utils.Ptr([]loadbalancer.TargetPool{
|
|
{
|
|
ActiveHealthCheck: utils.Ptr(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: utils.Ptr([]loadbalancer.Target{
|
|
{
|
|
DisplayName: utils.Ptr("display_name"),
|
|
Ip: utils.Ptr("ip"),
|
|
},
|
|
}),
|
|
},
|
|
}),
|
|
},
|
|
&Model{
|
|
Id: types.StringValue("pid,name"),
|
|
ProjectId: types.StringValue("pid"),
|
|
Name: types.StringValue("name"),
|
|
ExternalAddress: types.StringValue("external_address"),
|
|
Listeners: []Listener{
|
|
{
|
|
DisplayName: types.StringValue("display_name"),
|
|
Port: types.Int64Value(80),
|
|
Protocol: types.StringValue("protocol"),
|
|
TargetPool: types.StringValue("target_pool"),
|
|
},
|
|
},
|
|
Networks: []Network{
|
|
{
|
|
NetworkId: types.StringValue("network_id"),
|
|
Role: types.StringValue("role"),
|
|
},
|
|
{
|
|
NetworkId: types.StringValue("network_id_2"),
|
|
Role: types.StringValue("role_2"),
|
|
},
|
|
},
|
|
Options: types.ObjectValueMust(
|
|
optionsTypes,
|
|
map[string]attr.Value{
|
|
"acl": types.SetValueMust(
|
|
types.StringType,
|
|
[]attr.Value{types.StringValue("cidr")}),
|
|
"private_network_only": types.BoolValue(true),
|
|
},
|
|
),
|
|
TargetPools: []TargetPool{
|
|
{
|
|
ActiveHealthCheck: 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"),
|
|
TargetPort: types.Int64Value(80),
|
|
Targets: []Target{
|
|
{
|
|
DisplayName: types.StringValue("display_name"),
|
|
Ip: types.StringValue("ip"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
true,
|
|
},
|
|
{
|
|
"nil_response",
|
|
nil,
|
|
&Model{},
|
|
false,
|
|
},
|
|
{
|
|
"no_name",
|
|
&loadbalancer.LoadBalancer{},
|
|
&Model{},
|
|
false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.description, func(t *testing.T) {
|
|
model := &Model{
|
|
ProjectId: tt.expected.ProjectId,
|
|
}
|
|
err := mapFields(context.Background(), tt.input, model)
|
|
if !tt.isValid && err == nil {
|
|
t.Fatalf("Should have failed")
|
|
}
|
|
if tt.isValid && err != nil {
|
|
t.Fatalf("Should not have failed: %v", err)
|
|
}
|
|
if tt.isValid {
|
|
diff := cmp.Diff(model, tt.expected)
|
|
if diff != "" {
|
|
t.Fatalf("Data does not match: %s", diff)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|