Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/resources/ske_cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ Required:
<a id="nestedatt--extensions--application_load_balancer"></a>
### Nested Schema for `extensions.application_load_balancer`

Required:
Optional:

- `enabled` (Boolean) Enables the application load balancer extension. Note: This feature is in private preview. Enabling application load balancer extension is only possible for enabled accounts. Otherwise the request will be rejected.
- `enabled` (Boolean) Enables the application load balancer extension. Note: This feature is in private preview. Enabling application load balancer extension is only possible for enabled accounts. Otherwise the request will be rejected. Default value will change to true once the private preview phase is over.


<a id="nestedatt--extensions--argus"></a>
Expand Down
45 changes: 25 additions & 20 deletions stackit/internal/services/ske/cluster/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int32default"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
Expand Down Expand Up @@ -443,6 +444,7 @@ var descriptions = map[string]string{

// Schema defines the schema for the resource.
func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
extensionApplicationLoadbalancerDefault := types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{"enabled": types.BoolValue(false)})
resp.Schema = schema.Schema{
Description: fmt.Sprintf("%s\n%s", descriptions["main"], descriptions["node_pools_plan_note"]),
// Callout block: https://developer.hashicorp.com/terraform/registry/providers/docs#callouts
Expand Down Expand Up @@ -767,9 +769,14 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
"extensions": schema.SingleNestedAttribute{
Description: "A single extensions block as defined below.",
Optional: true,
PlanModifiers: []planmodifier.Object{
objectplanmodifier.UseStateForUnknown(),
},
Computed: true,
Default: objectdefault.StaticValue(types.ObjectValueMust(extensionsTypes, map[string]attr.Value{
"argus": types.ObjectNull(argusTypes),
"observability": types.ObjectNull(observabilityTypes),
"application_load_balancer": extensionApplicationLoadbalancerDefault,
"acl": types.ObjectNull(aclTypes),
"dns": types.ObjectNull(dnsTypes),
})),
Attributes: map[string]schema.Attribute{
"argus": schema.SingleNestedAttribute{
Description: "A single argus block as defined below. This field is deprecated and will be removed 06 January 2026.",
Expand Down Expand Up @@ -843,17 +850,23 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
"gateway_api": schema.BoolAttribute{
Description: "Enables Gateway API support for ExternalDNS. The CRDs must be installed by the user. Once installed, ExternalDNS will be configured at the next cluster reconcile.",
Optional: true,
Computed: true,
},
},
},
"application_load_balancer": schema.SingleNestedAttribute{
Description: "Application Load Balancer extension.",
Optional: true,
Computed: true,
Comment thread
rubenhoenle marked this conversation as resolved.
Validators: []validator.Object{
objectvalidator.AlsoRequires(path.MatchRelative().AtName("enabled")),
},
Default: objectdefault.StaticValue(extensionApplicationLoadbalancerDefault),
Attributes: map[string]schema.Attribute{
"enabled": schema.BoolAttribute{
Description: "Enables the application load balancer extension. Note: This feature is in private preview. Enabling application load balancer extension is only possible for enabled accounts. Otherwise the request will be rejected.",
Required: true,
Description: "Enables the application load balancer extension. Note: This feature is in private preview. Enabling application load balancer extension is only possible for enabled accounts. Otherwise the request will be rejected. Default value will change to true once the private preview phase is over.",
Optional: true,
Computed: true,
Default: booldefault.StaticBool(false),
},
},
},
Expand Down Expand Up @@ -1549,7 +1562,7 @@ func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error)
return nil, fmt.Errorf("converting extensions.dns object: %v", diags.Errors())
}
dnsEnabled := dns.Enabled.ValueBool()
gatewayApi := dns.GatewayApi.ValueBool()
gatewayApi := conversion.BoolValueToPointer(dns.GatewayApi)

zones := []string{}
diags = dns.Zones.ElementsAs(ctx, &zones, true)
Expand All @@ -1559,7 +1572,7 @@ func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error)
skeDNS = &ske.DNS{
Enabled: dnsEnabled,
Zones: zones,
GatewayApi: &gatewayApi,
GatewayApi: gatewayApi,
}
}

Expand Down Expand Up @@ -2103,7 +2116,7 @@ func checkDisabledExtensions(ctx context.Context, ex *extensions) (aclDisabled,
}

applicationLoadBalancer := applicationLoadBalancer{}
if ex.ApplicationLoadBalancer.IsNull() {
if utils.IsUndefined(ex.ApplicationLoadBalancer) {
applicationLoadBalancer.Enabled = types.BoolValue(false)
} else {
diags = ex.ApplicationLoadBalancer.As(ctx, &applicationLoadBalancer, basetypes.ObjectAsOptions{})
Expand All @@ -2123,7 +2136,7 @@ func mapExtensions(ctx context.Context, cl *ske.Cluster, m *Model) error {

var diags diag.Diagnostics
ex := extensions{}
if !m.Extensions.IsNull() {
if !utils.IsUndefined(m.Extensions) {
diags := m.Extensions.As(ctx, &ex, basetypes.ObjectAsOptions{})
if diags.HasError() {
return fmt.Errorf("converting extensions object: %v", diags.Errors())
Expand All @@ -2143,14 +2156,6 @@ func mapExtensions(ctx context.Context, cl *ske.Cluster, m *Model) error {
if err != nil {
return fmt.Errorf("checking if extensions are disabled: %w", err)
}
disabledExtensions := aclDisabled && observabilityDisabled && dnsDisabled && applicationLoadBalancerDisabled

if skeUtils.IsEmptyExtension(cl.Extensions) && (disabledExtensions || m.Extensions.IsNull()) {
if m.Extensions.Attributes() == nil {
m.Extensions = types.ObjectNull(extensionsTypes)
}
return nil
}

aclExtension := types.ObjectNull(aclTypes)
if cl.Extensions.Acl != nil {
Expand Down Expand Up @@ -2228,14 +2233,14 @@ func mapExtensions(ctx context.Context, cl *ske.Cluster, m *Model) error {
if diags.HasError() {
return fmt.Errorf("creating applicationLoadBalancer: %w", core.DiagsToError(diags))
}
} else if applicationLoadBalancerDisabled && !ex.ApplicationLoadBalancer.IsNull() {
} else if applicationLoadBalancerDisabled && !utils.IsUndefined(ex.ApplicationLoadBalancer) {
applicationLoadBalancerExtension = ex.ApplicationLoadBalancer
}

dnsExtension := types.ObjectNull(dnsTypes)
if cl.Extensions.Dns != nil {
enabled := types.BoolValue(cl.Extensions.Dns.Enabled)
gatewayApi := types.BoolValue(*cl.Extensions.Dns.GatewayApi)
gatewayApi := types.BoolPointerValue(cl.Extensions.Dns.GatewayApi)

zonesList, diags := types.ListValueFrom(ctx, types.StringType, cl.Extensions.Dns.Zones)
if diags.HasError() {
Expand Down
36 changes: 22 additions & 14 deletions stackit/internal/services/ske/cluster/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,8 @@ func TestMapFields(t *testing.T) {
Enabled: true,
},
Dns: &ske.DNS{
Zones: nil,
Enabled: true,
GatewayApi: new(true),
Zones: nil,
Enabled: true,
},
ApplicationLoadBalancer: &ske.ApplicationLoadBalancer{
Enabled: true,
Expand Down Expand Up @@ -382,7 +381,7 @@ func TestMapFields(t *testing.T) {
"dns": types.ObjectValueMust(dnsTypes, map[string]attr.Value{
"enabled": types.BoolValue(true),
"zones": types.ListNull(types.StringType),
"gateway_api": types.BoolValue(true),
"gateway_api": types.BoolNull(),
}),
"application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{
"enabled": types.BoolValue(true),
Expand All @@ -409,7 +408,7 @@ func TestMapFields(t *testing.T) {
"dns": types.ObjectValueMust(dnsTypes, map[string]attr.Value{
"enabled": types.BoolValue(false),
"zones": types.ListNull(types.StringType),
"gateway_api": types.BoolValue(false),
"gateway_api": types.BoolNull(),
}),
"application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{
"enabled": types.BoolValue(false),
Expand Down Expand Up @@ -450,7 +449,7 @@ func TestMapFields(t *testing.T) {
"dns": types.ObjectValueMust(dnsTypes, map[string]attr.Value{
"enabled": types.BoolValue(false),
"zones": types.ListNull(types.StringType),
"gateway_api": types.BoolValue(false),
"gateway_api": types.BoolNull(),
}),
"application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{
"enabled": types.BoolValue(false),
Expand Down Expand Up @@ -497,6 +496,9 @@ func TestMapFields(t *testing.T) {
Enabled: true,
GatewayApi: new(true),
},
ApplicationLoadBalancer: &ske.ApplicationLoadBalancer{
Enabled: true,
},
},
Name: new("name"),
Access: &ske.Access{
Expand Down Expand Up @@ -535,7 +537,7 @@ func TestMapFields(t *testing.T) {
"gateway_api": types.BoolValue(true),
}),
"application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{
"enabled": types.BoolValue(false),
"enabled": types.BoolValue(true),
}),
}),
KubernetesVersionUsed: types.StringValue(""),
Expand All @@ -560,13 +562,19 @@ func TestMapFields(t *testing.T) {
},
testRegion,
Model{
Id: types.StringValue("pid,region,name"),
ProjectId: types.StringValue("pid"),
Name: types.StringValue("name"),
NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}),
Maintenance: types.ObjectNull(maintenanceTypes),
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
Extensions: types.ObjectNull(extensionsTypes),
Id: types.StringValue("pid,region,name"),
ProjectId: types.StringValue("pid"),
Name: types.StringValue("name"),
NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}),
Maintenance: types.ObjectNull(maintenanceTypes),
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
Extensions: types.ObjectValueMust(extensionsTypes, map[string]attr.Value{
"argus": types.ObjectNull(argusTypes),
"observability": types.ObjectNull(observabilityTypes),
"application_load_balancer": types.ObjectNull(applicationLoadBalancerTypes),
"acl": types.ObjectNull(aclTypes),
"dns": types.ObjectNull(dnsTypes),
}),
EgressAddressRanges: types.ListNull(types.StringType),
PodAddressRanges: types.ListNull(types.StringType),
ServiceAccountIssuer: types.StringNull(),
Expand Down
Loading