fix(loadbalancer): set external_address as optional (#854)
* fix: set external_address for lb to optional * add unit tests --------- Co-authored-by: Ruben Hoenle <Ruben.Hoenle@stackit.cloud>
This commit is contained in:
parent
29f9a01633
commit
aaf29e4c19
3 changed files with 126 additions and 2 deletions
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
|
|
@ -237,6 +238,43 @@ func (r *loadBalancerResource) ModifyPlan(ctx context.Context, req resource.Modi
|
|||
}
|
||||
}
|
||||
|
||||
// ConfigValidators validates the resource configuration
|
||||
func (r *loadBalancerResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
|
||||
var model Model
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &model)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// validation is done in extracted func so it's easier to unit-test it
|
||||
validateConfig(ctx, &resp.Diagnostics, &model)
|
||||
}
|
||||
|
||||
func validateConfig(ctx context.Context, diags *diag.Diagnostics, model *Model) {
|
||||
externalAddressIsSet := !model.ExternalAddress.IsNull()
|
||||
|
||||
lbOptions, err := toOptionsPayload(ctx, model)
|
||||
if err != nil || lbOptions == nil {
|
||||
// private_network_only is not set and external_address is not set
|
||||
if !externalAddressIsSet {
|
||||
core.LogAndAddError(ctx, diags, "Error configuring load balancer", fmt.Sprintf("You need to provide either the `options.private_network_only = true` or `external_address` field. %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
if lbOptions.PrivateNetworkOnly == nil || !*lbOptions.PrivateNetworkOnly {
|
||||
// private_network_only is not set or false and external_address is not set
|
||||
if !externalAddressIsSet {
|
||||
core.LogAndAddError(ctx, diags, "Error configuring load balancer", "You need to provide either the `options.private_network_only = true` or `external_address` field.")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Both are set
|
||||
if *lbOptions.PrivateNetworkOnly && externalAddressIsSet {
|
||||
core.LogAndAddError(ctx, diags, "Error configuring load balancer", "You need to provide either the `options.private_network_only = true` or `external_address` field.")
|
||||
}
|
||||
}
|
||||
|
||||
// Configure adds the provider configured client to the resource.
|
||||
func (r *loadBalancerResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
var ok bool
|
||||
|
|
@ -327,7 +365,7 @@ The example below creates the supporting infrastructure using the STACKIT Terraf
|
|||
},
|
||||
"external_address": schema.StringAttribute{
|
||||
Description: descriptions["external_address"],
|
||||
Required: true,
|
||||
Optional: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,11 +7,16 @@ import (
|
|||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/utils"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/loadbalancer"
|
||||
)
|
||||
|
||||
const (
|
||||
testExternalAddress = "95.46.74.109"
|
||||
)
|
||||
|
||||
func TestToCreatePayload(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
|
|
@ -688,3 +693,84 @@ func TestMapFields(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_validateConfig(t *testing.T) {
|
||||
type args struct {
|
||||
ExternalAddress *string
|
||||
PrivateNetworkOnly *bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "happy case 1: private_network_only is not set and external_address is set",
|
||||
args: args{
|
||||
ExternalAddress: utils.Ptr(testExternalAddress),
|
||||
PrivateNetworkOnly: nil,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "happy case 2: private_network_only is set to false and external_address is set",
|
||||
args: args{
|
||||
ExternalAddress: utils.Ptr(testExternalAddress),
|
||||
PrivateNetworkOnly: utils.Ptr(false),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "happy case 3: private_network_only is set to true and external_address is not set",
|
||||
args: args{
|
||||
ExternalAddress: nil,
|
||||
PrivateNetworkOnly: utils.Ptr(true),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "error case 1: private_network_only and external_address are set",
|
||||
args: args{
|
||||
ExternalAddress: utils.Ptr(testExternalAddress),
|
||||
PrivateNetworkOnly: utils.Ptr(true),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error case 2: private_network_only is not set and external_address is not set",
|
||||
args: args{
|
||||
ExternalAddress: nil,
|
||||
PrivateNetworkOnly: nil,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error case 3: private_network_only is set to false and external_address is not set",
|
||||
args: args{
|
||||
ExternalAddress: nil,
|
||||
PrivateNetworkOnly: utils.Ptr(false),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
diags := diag.Diagnostics{}
|
||||
model := &Model{
|
||||
ExternalAddress: types.StringPointerValue(tt.args.ExternalAddress),
|
||||
Options: types.ObjectValueMust(optionsTypes, map[string]attr.Value{
|
||||
"acl": types.SetNull(types.StringType),
|
||||
"observability": types.ObjectNull(observabilityTypes),
|
||||
"private_network_only": types.BoolPointerValue(tt.args.PrivateNetworkOnly),
|
||||
}),
|
||||
}
|
||||
|
||||
validateConfig(ctx, &diags, model)
|
||||
|
||||
if diags.HasError() != tt.wantErr {
|
||||
t.Errorf("validateConfig() = %v, want %v", diags.HasError(), tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue