diff --git a/docs/data-sources/ske_cluster.md b/docs/data-sources/ske_cluster.md index d04e765f2..2687bb5cf 100644 --- a/docs/data-sources/ske_cluster.md +++ b/docs/data-sources/ske_cluster.md @@ -106,6 +106,7 @@ Read-Only: Read-Only: - `enabled` (Boolean) Flag to enable/disable DNS extensions +- `gateway_api` (Boolean) 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. - `zones` (List of String) Specify a list of domain filters for externalDNS (e.g., `foo.runs.onstackit.cloud`) diff --git a/docs/resources/ske_cluster.md b/docs/resources/ske_cluster.md index 218be5e4c..b34254d9e 100644 --- a/docs/resources/ske_cluster.md +++ b/docs/resources/ske_cluster.md @@ -178,6 +178,7 @@ Required: Optional: +- `gateway_api` (Boolean) 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. - `zones` (List of String) Specify a list of domain filters for externalDNS (e.g., `foo.runs.onstackit.cloud`) diff --git a/stackit/internal/services/ske/cluster/datasource.go b/stackit/internal/services/ske/cluster/datasource.go index 51ce810d6..dae8717b4 100644 --- a/stackit/internal/services/ske/cluster/datasource.go +++ b/stackit/internal/services/ske/cluster/datasource.go @@ -325,6 +325,10 @@ func (r *clusterDataSource) Schema(_ context.Context, _ datasource.SchemaRequest Computed: true, ElementType: types.StringType, }, + "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.", + Computed: true, + }, }, }, "application_load_balancer": schema.SingleNestedAttribute{ diff --git a/stackit/internal/services/ske/cluster/resource.go b/stackit/internal/services/ske/cluster/resource.go index ce850dc01..c2d2051ec 100644 --- a/stackit/internal/services/ske/cluster/resource.go +++ b/stackit/internal/services/ske/cluster/resource.go @@ -272,14 +272,16 @@ var observabilityTypes = map[string]attr.Type{ // Struct corresponding to extensions.DNS type dns struct { - Enabled types.Bool `tfsdk:"enabled"` - Zones types.List `tfsdk:"zones"` + Enabled types.Bool `tfsdk:"enabled"` + Zones types.List `tfsdk:"zones"` + GatewayApi types.Bool `tfsdk:"gateway_api"` } // Types corresponding to DNS var dnsTypes = map[string]attr.Type{ - "enabled": basetypes.BoolType{}, - "zones": basetypes.ListType{ElemType: types.StringType}, + "enabled": basetypes.BoolType{}, + "zones": basetypes.ListType{ElemType: types.StringType}, + "gateway_api": basetypes.BoolType{}, } // NewClusterResource is a helper function to simplify the provider implementation. @@ -825,6 +827,11 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re // API response (empty list). Default: listdefault.StaticValue(types.ListValueMust(types.StringType, []attr.Value{})), }, + "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{ @@ -1491,6 +1498,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() zones := []string{} diags = dns.Zones.ElementsAs(ctx, &zones, true) @@ -1498,8 +1506,9 @@ func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error) return nil, fmt.Errorf("converting extensions.dns.zones object: %v", diags.Errors()) } skeDNS = &ske.DNS{ - Enabled: dnsEnabled, - Zones: zones, + Enabled: dnsEnabled, + Zones: zones, + GatewayApi: &gatewayApi, } } @@ -2152,6 +2161,7 @@ func mapExtensions(ctx context.Context, cl *ske.Cluster, m *Model) error { dnsExtension := types.ObjectNull(dnsTypes) if cl.Extensions.Dns != nil { enabled := types.BoolValue(cl.Extensions.Dns.Enabled) + gatewayApi := types.BoolValue(*cl.Extensions.Dns.GatewayApi) zonesList, diags := types.ListValueFrom(ctx, types.StringType, cl.Extensions.Dns.Zones) if diags.HasError() { @@ -2159,8 +2169,9 @@ func mapExtensions(ctx context.Context, cl *ske.Cluster, m *Model) error { } dnsValues := map[string]attr.Value{ - "enabled": enabled, - "zones": zonesList, + "enabled": enabled, + "zones": zonesList, + "gateway_api": gatewayApi, } dnsExtension, diags = types.ObjectValue(dnsTypes, dnsValues) diff --git a/stackit/internal/services/ske/cluster/resource_test.go b/stackit/internal/services/ske/cluster/resource_test.go index 81add8be3..ec6ad006e 100644 --- a/stackit/internal/services/ske/cluster/resource_test.go +++ b/stackit/internal/services/ske/cluster/resource_test.go @@ -80,8 +80,9 @@ func TestMapFields(t *testing.T) { Enabled: true, }, Dns: &ske.DNS{ - Zones: []string{"foo.onstackit.cloud"}, - Enabled: true, + Zones: []string{"foo.onstackit.cloud"}, + Enabled: true, + GatewayApi: new(true), }, ApplicationLoadBalancer: &ske.ApplicationLoadBalancer{ Enabled: true, @@ -277,6 +278,7 @@ func TestMapFields(t *testing.T) { "zones": types.ListValueMust(types.StringType, []attr.Value{ types.StringValue("foo.onstackit.cloud"), }), + "gateway_api": types.BoolValue(true), }), "application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{ "enabled": types.BoolValue(true), @@ -340,8 +342,9 @@ func TestMapFields(t *testing.T) { Enabled: true, }, Dns: &ske.DNS{ - Zones: nil, - Enabled: true, + Zones: nil, + Enabled: true, + GatewayApi: new(true), }, ApplicationLoadBalancer: &ske.ApplicationLoadBalancer{ Enabled: true, @@ -377,8 +380,9 @@ func TestMapFields(t *testing.T) { "instance_id": types.StringValue(""), }), "dns": types.ObjectValueMust(dnsTypes, map[string]attr.Value{ - "enabled": types.BoolValue(true), - "zones": types.ListNull(types.StringType), + "enabled": types.BoolValue(true), + "zones": types.ListNull(types.StringType), + "gateway_api": types.BoolValue(true), }), "application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{ "enabled": types.BoolValue(true), @@ -403,8 +407,9 @@ func TestMapFields(t *testing.T) { "instance_id": types.StringNull(), }), "dns": types.ObjectValueMust(dnsTypes, map[string]attr.Value{ - "enabled": types.BoolValue(false), - "zones": types.ListNull(types.StringType), + "enabled": types.BoolValue(false), + "zones": types.ListNull(types.StringType), + "gateway_api": types.BoolValue(false), }), "application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{ "enabled": types.BoolValue(false), @@ -443,8 +448,9 @@ func TestMapFields(t *testing.T) { "instance_id": types.StringNull(), }), "dns": types.ObjectValueMust(dnsTypes, map[string]attr.Value{ - "enabled": types.BoolValue(false), - "zones": types.ListNull(types.StringType), + "enabled": types.BoolValue(false), + "zones": types.ListNull(types.StringType), + "gateway_api": types.BoolValue(false), }), "application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{ "enabled": types.BoolValue(false), @@ -471,8 +477,9 @@ func TestMapFields(t *testing.T) { "instance_id": types.StringValue("id"), }), "dns": types.ObjectValueMust(dnsTypes, map[string]attr.Value{ - "enabled": types.BoolValue(true), - "zones": types.ListNull(types.StringType), + "enabled": types.BoolValue(true), + "zones": types.ListNull(types.StringType), + "gateway_api": types.BoolValue(true), }), "application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{ "enabled": types.BoolValue(false), @@ -486,8 +493,9 @@ func TestMapFields(t *testing.T) { Enabled: true, }, Dns: &ske.DNS{ - Zones: nil, - Enabled: true, + Zones: nil, + Enabled: true, + GatewayApi: new(true), }, }, Name: new("name"), @@ -522,8 +530,9 @@ func TestMapFields(t *testing.T) { "instance_id": types.StringValue("id"), }), "dns": types.ObjectValueMust(dnsTypes, map[string]attr.Value{ - "enabled": types.BoolValue(true), - "zones": types.ListNull(types.StringType), + "enabled": types.BoolValue(true), + "zones": types.ListNull(types.StringType), + "gateway_api": types.BoolValue(true), }), "application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{ "enabled": types.BoolValue(false), @@ -619,8 +628,9 @@ func TestMapFields(t *testing.T) { Enabled: true, }, Dns: &ske.DNS{ - Zones: []string{"zone1"}, - Enabled: true, + Zones: []string{"zone1"}, + Enabled: true, + GatewayApi: new(true), }, ApplicationLoadBalancer: &ske.ApplicationLoadBalancer{ Enabled: true, @@ -782,6 +792,7 @@ func TestMapFields(t *testing.T) { "zones": types.ListValueMust(types.StringType, []attr.Value{ types.StringValue("zone1"), }), + "gateway_api": types.BoolValue(true), }), "application_load_balancer": types.ObjectValueMust(applicationLoadBalancerTypes, map[string]attr.Value{ "enabled": types.BoolValue(true), diff --git a/stackit/internal/services/ske/ske_acc_test.go b/stackit/internal/services/ske/ske_acc_test.go index f6a745227..b898f9df6 100644 --- a/stackit/internal/services/ske/ske_acc_test.go +++ b/stackit/internal/services/ske/ske_acc_test.go @@ -78,6 +78,7 @@ var testConfigVarsMax = config.Variables{ "ext_acl_allowed_cidr1": config.StringVariable("10.0.100.0/24"), "ext_observability_enabled": config.StringVariable("false"), "ext_dns_enabled": config.StringVariable("true"), + "ext_dns_gateway_api": config.StringVariable("true"), "ext_application_load_balancer_enabled": config.StringVariable("true"), "nodepool_hibernations1_start": config.StringVariable("0 18 * * *"), "nodepool_hibernations1_end": config.StringVariable("59 23 * * *"), @@ -308,6 +309,7 @@ func TestAccSKEMax(t *testing.T) { resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.acl.allowed_cidrs.0", testutil.ConvertConfigVariable(testConfigVarsMax["ext_acl_allowed_cidr1"])), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.observability.enabled", testutil.ConvertConfigVariable(testConfigVarsMax["ext_observability_enabled"])), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.dns.enabled", testutil.ConvertConfigVariable(testConfigVarsMax["ext_dns_enabled"])), + resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.dns.gateway_api", testutil.ConvertConfigVariable(testConfigVarsMax["ext_dns_gateway_api"])), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.dns.zones.#", "1"), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.dns.zones.0", testutil.ConvertConfigVariable(testConfigVarsMax["dns_name"])), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.application_load_balancer.enabled", testutil.ConvertConfigVariable(testConfigVarsMax["ext_application_load_balancer_enabled"])), @@ -389,6 +391,7 @@ func TestAccSKEMax(t *testing.T) { resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "extensions.acl.allowed_cidrs.0", testutil.ConvertConfigVariable(testConfigVarsMax["ext_acl_allowed_cidr1"])), // no check for observability, as it was disabled in the setup resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "extensions.dns.enabled", testutil.ConvertConfigVariable(testConfigVarsMax["ext_dns_enabled"])), + resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "extensions.dns.gateway_api", testutil.ConvertConfigVariable(testConfigVarsMax["ext_dns_gateway_api"])), resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "extensions.dns.zones.#", "1"), resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "extensions.dns.zones.0", testutil.ConvertConfigVariable(testConfigVarsMax["dns_name"])), resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "extensions.application_load_balancer.enabled", testutil.ConvertConfigVariable(testConfigVarsMax["ext_application_load_balancer_enabled"])), @@ -481,6 +484,7 @@ func TestAccSKEMax(t *testing.T) { resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.acl.allowed_cidrs.0", testutil.ConvertConfigVariable(configVarsMaxUpdated()["ext_acl_allowed_cidr1"])), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.observability.enabled", testutil.ConvertConfigVariable(configVarsMaxUpdated()["ext_observability_enabled"])), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.dns.enabled", testutil.ConvertConfigVariable(configVarsMaxUpdated()["ext_dns_enabled"])), + resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.dns.gateway_api", testutil.ConvertConfigVariable(configVarsMaxUpdated()["ext_dns_gateway_api"])), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.dns.zones.#", "1"), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.dns.zones.0", testutil.ConvertConfigVariable(configVarsMaxUpdated()["dns_name"])), resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.application_load_balancer.enabled", testutil.ConvertConfigVariable(configVarsMaxUpdated()["ext_application_load_balancer_enabled"])), diff --git a/stackit/internal/services/ske/testdata/resource-max.tf b/stackit/internal/services/ske/testdata/resource-max.tf index 8d6450088..54ac080a7 100644 --- a/stackit/internal/services/ske/testdata/resource-max.tf +++ b/stackit/internal/services/ske/testdata/resource-max.tf @@ -22,6 +22,7 @@ variable "ext_acl_allowed_cidr1" {} variable "ext_observability_enabled" {} variable "ext_application_load_balancer_enabled" {} variable "ext_dns_enabled" {} +variable "ext_dns_gateway_api" {} variable "nodepool_hibernations1_start" {} variable "nodepool_hibernations1_end" {} variable "nodepool_hibernations1_timezone" {} @@ -78,8 +79,9 @@ resource "stackit_ske_cluster" "cluster" { enabled = var.ext_observability_enabled } dns = { - enabled = var.ext_dns_enabled - zones = [stackit_dns_zone.dns-zone.dns_name] + enabled = var.ext_dns_enabled + zones = [stackit_dns_zone.dns-zone.dns_name] + gateway_api = var.ext_dns_gateway_api } application_load_balancer = { enabled = var.ext_application_load_balancer_enabled