diff --git a/docs/data-sources/ske_cluster.md b/docs/data-sources/ske_cluster.md index c0ead7d66..c85ef11fc 100644 --- a/docs/data-sources/ske_cluster.md +++ b/docs/data-sources/ske_cluster.md @@ -97,6 +97,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 b1fc8176a..d353f137c 100644 --- a/docs/resources/ske_cluster.md +++ b/docs/resources/ske_cluster.md @@ -169,6 +169,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 bd3013815..71d9c5b41 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, + }, }, }, }, diff --git a/stackit/internal/services/ske/cluster/resource.go b/stackit/internal/services/ske/cluster/resource.go index 3d4e9a594..f6b5caa39 100644 --- a/stackit/internal/services/ske/cluster/resource.go +++ b/stackit/internal/services/ske/cluster/resource.go @@ -260,14 +260,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. @@ -813,6 +815,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, + }, }, }, }, @@ -1456,6 +1463,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) @@ -1463,8 +1471,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, } } @@ -2092,6 +2101,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() { @@ -2099,8 +2109,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 f277522ac..1129914d5 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), }, }, Hibernation: &ske.Hibernation{ @@ -274,6 +275,7 @@ func TestMapFields(t *testing.T) { "zones": types.ListValueMust(types.StringType, []attr.Value{ types.StringValue("foo.onstackit.cloud"), }), + "gateway_api": types.BoolValue(true), }), }), Region: types.StringValue(testRegion), @@ -334,8 +336,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"), @@ -368,8 +371,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), }), }), KubernetesVersionUsed: types.StringValue(""), @@ -391,8 +395,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), }), }), types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}), @@ -428,8 +433,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), }), }), KubernetesVersionUsed: types.StringValue(""), @@ -453,8 +459,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), }), }), types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}), @@ -465,8 +472,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"), @@ -501,8 +509,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), }), }), KubernetesVersionUsed: types.StringValue(""), @@ -595,8 +604,9 @@ func TestMapFields(t *testing.T) { Enabled: true, }, Dns: &ske.DNS{ - Zones: []string{"zone1"}, - Enabled: true, + Zones: []string{"zone1"}, + Enabled: true, + GatewayApi: new(true), }, }, Hibernation: &ske.Hibernation{ @@ -755,6 +765,7 @@ func TestMapFields(t *testing.T) { "zones": types.ListValueMust(types.StringType, []attr.Value{ types.StringValue("zone1"), }), + "gateway_api": types.BoolValue(true), }), }), Region: types.StringValue(testRegion), diff --git a/stackit/internal/services/ske/ske_acc_test.go b/stackit/internal/services/ske/ske_acc_test.go index 2776c133b..788248db5 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"), "nodepool_hibernations1_start": config.StringVariable("0 18 * * *"), "nodepool_hibernations1_end": config.StringVariable("59 23 * * *"), "nodepool_hibernations1_timezone": config.StringVariable("Europe/Berlin"), @@ -306,6 +307,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"])), @@ -386,6 +388,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"])), @@ -477,6 +480,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"])), diff --git a/stackit/internal/services/ske/testdata/resource-max.tf b/stackit/internal/services/ske/testdata/resource-max.tf index 92377aa0e..2be8d8d13 100644 --- a/stackit/internal/services/ske/testdata/resource-max.tf +++ b/stackit/internal/services/ske/testdata/resource-max.tf @@ -21,6 +21,7 @@ variable "ext_acl_enabled" {} variable "ext_acl_allowed_cidr1" {} variable "ext_observability_enabled" {} variable "ext_dns_enabled" {} +variable "ext_dns_gateway_api" {} variable "nodepool_hibernations1_start" {} variable "nodepool_hibernations1_end" {} variable "nodepool_hibernations1_timezone" {} @@ -77,8 +78,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 } } hibernations = [{