Skip to content

Commit 04a3436

Browse files
authored
feat: add pod_address_ranges to ske resource/datasource (#888)
* feat: add pod_address_ranges to ske resource/datasource Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> * review changes Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> * review changes 2 Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud> --------- Signed-off-by: Mauritz Uphoff <mauritz.uphoff@stackit.cloud>
1 parent 2f06bc5 commit 04a3436

7 files changed

Lines changed: 174 additions & 15 deletions

File tree

docs/data-sources/ske_cluster.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ This should be used with care since it also disables a couple of other features
4646
- `maintenance` (Attributes) A single maintenance block as defined below (see [below for nested schema](#nestedatt--maintenance))
4747
- `network` (Attributes) Network block as defined below. (see [below for nested schema](#nestedatt--network))
4848
- `node_pools` (Attributes List) One or more `node_pool` block as defined below. (see [below for nested schema](#nestedatt--node_pools))
49+
- `pod_address_ranges` (List of String) The network ranges (in CIDR notation) used by pods of the cluster.
4950

5051
<a id="nestedatt--extensions"></a>
5152
### Nested Schema for `extensions`

docs/resources/ske_cluster.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Deprecated as of Kubernetes 1.25 and later
6666
- `egress_address_ranges` (List of String) The outgoing network ranges (in CIDR notation) of traffic originating from workload on the cluster.
6767
- `id` (String) Terraform's internal resource ID. It is structured as "`project_id`,`region`,`name`".
6868
- `kubernetes_version_used` (String) Full Kubernetes version used. For example, if 1.22 was set in `kubernetes_version_min`, this value may result to 1.22.15. SKE automatically updates the cluster Kubernetes version if you have set `maintenance.enable_kubernetes_version_updates` to true or if there is a mandatory update, as described in [Updates for Kubernetes versions and Operating System versions in SKE](https://docs.stackit.cloud/stackit/en/version-updates-in-ske-10125631.html).
69+
- `pod_address_ranges` (List of String) The network ranges (in CIDR notation) used by pods of the cluster.
6970

7071
<a id="nestedatt--node_pools"></a>
7172
### Nested Schema for `node_pools`

stackit/internal/services/ske/cluster/datasource.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ func (r *clusterDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
9898
Computed: true,
9999
ElementType: types.StringType,
100100
},
101+
"pod_address_ranges": schema.ListAttribute{
102+
Description: "The network ranges (in CIDR notation) used by pods of the cluster.",
103+
Computed: true,
104+
ElementType: types.StringType,
105+
},
101106
"node_pools": schema.ListNestedAttribute{
102107
Description: "One or more `node_pool` block as defined below.",
103108
Computed: true,

stackit/internal/services/ske/cluster/resource.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ type Model struct {
8383
Hibernations types.List `tfsdk:"hibernations"`
8484
Extensions types.Object `tfsdk:"extensions"`
8585
EgressAddressRanges types.List `tfsdk:"egress_address_ranges"`
86+
PodAddressRanges types.List `tfsdk:"pod_address_ranges"`
8687
Region types.String `tfsdk:"region"`
8788
}
8889

@@ -384,6 +385,11 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
384385
Computed: true,
385386
ElementType: types.StringType,
386387
},
388+
"pod_address_ranges": schema.ListAttribute{
389+
Description: "The network ranges (in CIDR notation) used by pods of the cluster.",
390+
Computed: true,
391+
ElementType: types.StringType,
392+
},
387393
"node_pools": schema.ListNestedAttribute{
388394
Description: "One or more `node_pool` block as defined below.",
389395
Required: true,
@@ -1378,6 +1384,15 @@ func mapFields(ctx context.Context, cl *ske.Cluster, m *Model, region string) er
13781384
}
13791385
}
13801386

1387+
m.PodAddressRanges = types.ListNull(types.StringType)
1388+
if cl.Status != nil {
1389+
var diags diag.Diagnostics
1390+
m.PodAddressRanges, diags = types.ListValueFrom(ctx, types.StringType, cl.Status.PodAddressRanges)
1391+
if diags.HasError() {
1392+
return fmt.Errorf("map podAddressRanges: %w", core.DiagsToError(diags))
1393+
}
1394+
}
1395+
13811396
err := mapNodePools(ctx, cl, m)
13821397
if err != nil {
13831398
return fmt.Errorf("map node_pools: %w", err)

stackit/internal/services/ske/cluster/resource_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func TestMapFields(t *testing.T) {
6363
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
6464
Extensions: types.ObjectNull(extensionsTypes),
6565
EgressAddressRanges: types.ListNull(types.StringType),
66+
PodAddressRanges: types.ListNull(types.StringType),
6667
Region: types.StringValue(testRegion),
6768
},
6869
true,
@@ -151,6 +152,7 @@ func TestMapFields(t *testing.T) {
151152
Error: nil,
152153
Hibernated: nil,
153154
EgressAddressRanges: &[]string{"0.0.0.0/32", "1.1.1.1/32"},
155+
PodAddressRanges: &[]string{"0.0.0.0/32", "1.1.1.1/32"},
154156
},
155157
},
156158
testRegion,
@@ -168,6 +170,13 @@ func TestMapFields(t *testing.T) {
168170
types.StringValue("1.1.1.1/32"),
169171
},
170172
),
173+
PodAddressRanges: types.ListValueMust(
174+
types.StringType,
175+
[]attr.Value{
176+
types.StringValue("0.0.0.0/32"),
177+
types.StringValue("1.1.1.1/32"),
178+
},
179+
),
171180
NodePools: types.ListValueMust(
172181
types.ObjectType{AttrTypes: nodePoolTypes},
173182
[]attr.Value{
@@ -283,6 +292,7 @@ func TestMapFields(t *testing.T) {
283292
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
284293
Extensions: types.ObjectNull(extensionsTypes),
285294
EgressAddressRanges: types.ListNull(types.StringType),
295+
PodAddressRanges: types.ListNull(types.StringType),
286296
Region: types.StringValue(testRegion),
287297
},
288298
true,
@@ -319,6 +329,7 @@ func TestMapFields(t *testing.T) {
319329
Maintenance: types.ObjectNull(maintenanceTypes),
320330
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
321331
EgressAddressRanges: types.ListNull(types.StringType),
332+
PodAddressRanges: types.ListNull(types.StringType),
322333
Extensions: types.ObjectValueMust(extensionsTypes, map[string]attr.Value{
323334
"acl": types.ObjectValueMust(aclTypes, map[string]attr.Value{
324335
"enabled": types.BoolValue(true),
@@ -369,6 +380,7 @@ func TestMapFields(t *testing.T) {
369380
Maintenance: types.ObjectNull(maintenanceTypes),
370381
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
371382
EgressAddressRanges: types.ListNull(types.StringType),
383+
PodAddressRanges: types.ListNull(types.StringType),
372384
Extensions: types.ObjectValueMust(extensionsTypes, map[string]attr.Value{
373385
"acl": types.ObjectValueMust(aclTypes, map[string]attr.Value{
374386
"enabled": types.BoolValue(false),
@@ -430,6 +442,7 @@ func TestMapFields(t *testing.T) {
430442
Maintenance: types.ObjectNull(maintenanceTypes),
431443
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
432444
EgressAddressRanges: types.ListNull(types.StringType),
445+
PodAddressRanges: types.ListNull(types.StringType),
433446
Extensions: types.ObjectValueMust(extensionsTypes, map[string]attr.Value{
434447
"acl": types.ObjectValueMust(aclTypes, map[string]attr.Value{
435448
"enabled": types.BoolValue(true),
@@ -470,6 +483,7 @@ func TestMapFields(t *testing.T) {
470483
Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}),
471484
Extensions: types.ObjectNull(extensionsTypes),
472485
EgressAddressRanges: types.ListNull(types.StringType),
486+
PodAddressRanges: types.ListNull(types.StringType),
473487
Region: types.StringValue(testRegion),
474488
},
475489
true,
@@ -598,6 +612,7 @@ func TestMapFields(t *testing.T) {
598612
KubernetesVersionUsed: types.StringValue("1.2.3"),
599613
AllowPrivilegedContainers: types.BoolValue(true),
600614
EgressAddressRanges: types.ListNull(types.StringType),
615+
PodAddressRanges: types.ListNull(types.StringType),
601616
NodePools: types.ListValueMust(
602617
types.ObjectType{AttrTypes: nodePoolTypes},
603618
[]attr.Value{

stackit/internal/services/ske/ske_acc_test.go

Lines changed: 134 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
1313
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
1414
"github.com/hashicorp/terraform-plugin-testing/terraform"
15-
core_config "github.com/stackitcloud/stackit-sdk-go/core/config"
15+
coreConfig "github.com/stackitcloud/stackit-sdk-go/core/config"
1616
"github.com/stackitcloud/stackit-sdk-go/core/utils"
1717
"github.com/stackitcloud/stackit-sdk-go/services/ske"
1818
"github.com/stackitcloud/stackit-sdk-go/services/ske/wait"
@@ -33,27 +33,29 @@ var (
3333
resourceMax string
3434
)
3535

36+
var skeProviderOptions = NewSkeProviderOptions("flatcar")
37+
3638
var testConfigVarsMin = config.Variables{
3739
"project_id": config.StringVariable(testutil.ProjectId),
3840
"name": config.StringVariable(minTestName),
39-
"nodepool_availability_zone1": config.StringVariable("eu01-m"),
41+
"nodepool_availability_zone1": config.StringVariable(fmt.Sprintf("%s-1", testutil.Region)),
4042
"nodepool_machine_type": config.StringVariable("g1.2"),
4143
"nodepool_minimum": config.StringVariable("1"),
4244
"nodepool_maximum": config.StringVariable("2"),
4345
"nodepool_name": config.StringVariable("np-acc-test"),
44-
"kubernetes_version_min": config.StringVariable("1.31.8"),
46+
"kubernetes_version_min": config.StringVariable(skeProviderOptions.GetCreateK8sVersion()),
4547
"maintenance_enable_machine_image_version_updates": config.StringVariable("true"),
4648
"maintenance_enable_kubernetes_version_updates": config.StringVariable("true"),
4749
"maintenance_start": config.StringVariable("02:00:00+01:00"),
4850
"maintenance_end": config.StringVariable("04:00:00+01:00"),
49-
"region": config.StringVariable("eu01"),
51+
"region": config.StringVariable(testutil.Region),
5052
}
5153

5254
var testConfigVarsMax = config.Variables{
5355
"project_id": config.StringVariable(testutil.ProjectId),
5456
"organization_id": config.StringVariable(testutil.OrganizationId),
5557
"name": config.StringVariable(maxTestName),
56-
"nodepool_availability_zone1": config.StringVariable("eu01-m"),
58+
"nodepool_availability_zone1": config.StringVariable(fmt.Sprintf("%s-1", testutil.Region)),
5759
"nodepool_machine_type": config.StringVariable("g1.2"),
5860
"nodepool_minimum": config.StringVariable("1"),
5961
"nodepool_maximum": config.StringVariable("2"),
@@ -63,8 +65,8 @@ var testConfigVarsMax = config.Variables{
6365
"nodepool_label_value": config.StringVariable("value"),
6466
"nodepool_max_surge": config.StringVariable("1"),
6567
"nodepool_max_unavailable": config.StringVariable("1"),
66-
"nodepool_os_name": config.StringVariable("flatcar"),
67-
"nodepool_os_version_min": config.StringVariable("4152.2.1"),
68+
"nodepool_os_name": config.StringVariable(skeProviderOptions.nodePoolOsName),
69+
"nodepool_os_version_min": config.StringVariable(skeProviderOptions.GetCreateMachineVersion()),
6870
"nodepool_taints_effect": config.StringVariable("PreferNoSchedule"),
6971
"nodepool_taints_key": config.StringVariable("tkey"),
7072
"nodepool_taints_value": config.StringVariable("tvalue"),
@@ -77,33 +79,34 @@ var testConfigVarsMax = config.Variables{
7779
"nodepool_hibernations1_start": config.StringVariable("0 18 * * *"),
7880
"nodepool_hibernations1_end": config.StringVariable("59 23 * * *"),
7981
"nodepool_hibernations1_timezone": config.StringVariable("Europe/Berlin"),
80-
"kubernetes_version_min": config.StringVariable("1.31.8"),
82+
"kubernetes_version_min": config.StringVariable(skeProviderOptions.GetCreateK8sVersion()),
8183
"maintenance_enable_machine_image_version_updates": config.StringVariable("true"),
8284
"maintenance_enable_kubernetes_version_updates": config.StringVariable("true"),
8385
"maintenance_start": config.StringVariable("02:00:00+01:00"),
8486
"maintenance_end": config.StringVariable("04:00:00+01:00"),
85-
"region": config.StringVariable("eu01"),
87+
"region": config.StringVariable(testutil.Region),
8688
"expiration": config.StringVariable("3600"),
8789
"refresh": config.StringVariable("true"),
8890
"dns_zone_name": config.StringVariable("acc-" + acctest.RandStringFromCharSet(6, acctest.CharSetAlpha)),
8991
"dns_name": config.StringVariable("acc-" + acctest.RandStringFromCharSet(6, acctest.CharSetAlpha) + ".runs.onstackit.cloud"),
9092
}
9193

9294
func configVarsMinUpdated() config.Variables {
93-
updatedConfig := maps.Clone(testConfigVarsMax)
94-
updatedConfig["kubernetes_version_min"] = config.StringVariable("1.31")
95+
updatedConfig := maps.Clone(testConfigVarsMin)
96+
updatedConfig["kubernetes_version_min"] = config.StringVariable(skeProviderOptions.GetUpdateK8sVersion())
9597

9698
return updatedConfig
9799
}
98100

99101
func configVarsMaxUpdated() config.Variables {
100102
updatedConfig := maps.Clone(testConfigVarsMax)
101-
updatedConfig["kubernetes_version_min"] = config.StringVariable("1.31")
102-
updatedConfig["nodepool_os_version_min"] = config.StringVariable("4152.2.1")
103+
updatedConfig["kubernetes_version_min"] = config.StringVariable(skeProviderOptions.GetUpdateK8sVersion())
104+
updatedConfig["nodepool_os_version_min"] = config.StringVariable(skeProviderOptions.GetUpdateMachineVersion())
103105
updatedConfig["maintenance_end"] = config.StringVariable("03:03:03+00:00")
104106

105107
return updatedConfig
106108
}
109+
107110
func TestAccSKEMin(t *testing.T) {
108111
resource.Test(t, resource.TestCase{
109112
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
@@ -285,6 +288,8 @@ func TestAccSKEMax(t *testing.T) {
285288

286289
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "egress_address_ranges.#", "1"),
287290
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "egress_address_ranges.0"),
291+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "pod_address_ranges.#", "1"),
292+
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "pod_address_ranges.0"),
288293
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "kubernetes_version_used"),
289294

290295
// Kubeconfig
@@ -355,6 +360,9 @@ func TestAccSKEMax(t *testing.T) {
355360

356361
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "egress_address_ranges.#", "1"),
357362
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster", "egress_address_ranges.0"),
363+
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "pod_address_ranges.#", "1"),
364+
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster", "pod_address_ranges.0"),
365+
358366
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster", "kubernetes_version_used"),
359367
),
360368
},
@@ -435,6 +443,8 @@ func TestAccSKEMax(t *testing.T) {
435443

436444
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "egress_address_ranges.#", "1"),
437445
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "egress_address_ranges.0"),
446+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "pod_address_ranges.#", "1"),
447+
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "pod_address_ranges.0"),
438448
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "kubernetes_version_used"),
439449
),
440450
},
@@ -449,11 +459,11 @@ func testAccCheckSKEDestroy(s *terraform.State) error {
449459
var err error
450460
if testutil.SKECustomEndpoint == "" {
451461
client, err = ske.NewAPIClient(
452-
core_config.WithRegion("eu01"),
462+
coreConfig.WithRegion(testutil.Region),
453463
)
454464
} else {
455465
client, err = ske.NewAPIClient(
456-
core_config.WithEndpoint(testutil.SKECustomEndpoint),
466+
coreConfig.WithEndpoint(testutil.SKECustomEndpoint),
457467
)
458468
}
459469
if err != nil {
@@ -493,3 +503,112 @@ func testAccCheckSKEDestroy(s *terraform.State) error {
493503
}
494504
return nil
495505
}
506+
507+
type SkeProviderOptions struct {
508+
options *ske.ProviderOptions
509+
nodePoolOsName string
510+
}
511+
512+
// NewSkeProviderOptions fetches the latest available options from SKE.
513+
func NewSkeProviderOptions(nodePoolOs string) *SkeProviderOptions {
514+
// skip if TF_ACC=1 is not set
515+
if !testutil.E2ETestsEnabled {
516+
return &SkeProviderOptions{
517+
options: nil,
518+
nodePoolOsName: nodePoolOs,
519+
}
520+
}
521+
522+
ctx := context.Background()
523+
524+
var client *ske.APIClient
525+
var err error
526+
527+
if testutil.SKECustomEndpoint == "" {
528+
client, err = ske.NewAPIClient(coreConfig.WithRegion("eu01"))
529+
} else {
530+
client, err = ske.NewAPIClient(coreConfig.WithEndpoint(testutil.SKECustomEndpoint))
531+
}
532+
533+
if err != nil {
534+
panic("failed to create SKE client: " + err.Error())
535+
}
536+
537+
options, err := client.ListProviderOptions(ctx).Execute()
538+
if err != nil {
539+
panic("failed to fetch SKE provider options: " + err.Error())
540+
}
541+
542+
return &SkeProviderOptions{
543+
options: options,
544+
nodePoolOsName: nodePoolOs,
545+
}
546+
}
547+
548+
// getMachineVersionAt returns the N-th supported version for the specified machine image.
549+
func (s *SkeProviderOptions) getMachineVersionAt(position int) string {
550+
// skip if TF_ACC=1 is not set
551+
if !testutil.E2ETestsEnabled {
552+
return ""
553+
}
554+
555+
if s.options == nil || s.options.MachineImages == nil {
556+
panic(fmt.Sprintf("no supported machine version found at position %d", position))
557+
}
558+
559+
for _, mi := range *s.options.MachineImages {
560+
if mi.Name != nil && *mi.Name == s.nodePoolOsName && mi.Versions != nil {
561+
count := 0
562+
for _, v := range *mi.Versions {
563+
if v.State != nil && v.Version != nil {
564+
if count == position {
565+
return *v.Version
566+
}
567+
count++
568+
}
569+
}
570+
}
571+
}
572+
573+
panic(fmt.Sprintf("no supported machine version found at position %d", position))
574+
}
575+
576+
// getK8sVersionAt returns the N-th supported Kubernetes version.
577+
func (s *SkeProviderOptions) getK8sVersionAt(position int) string {
578+
// skip if TF_ACC=1 is not set
579+
if !testutil.E2ETestsEnabled {
580+
return ""
581+
}
582+
583+
if s.options == nil || s.options.KubernetesVersions == nil {
584+
panic(fmt.Sprintf("no supported k8s version found at position %d", position))
585+
}
586+
587+
count := 0
588+
for _, v := range *s.options.KubernetesVersions {
589+
if v.State != nil && *v.State == "supported" && v.Version != nil {
590+
if count == position {
591+
return *v.Version
592+
}
593+
count++
594+
}
595+
}
596+
597+
panic(fmt.Sprintf("no supported k8s version found at position %d", position))
598+
}
599+
600+
func (s *SkeProviderOptions) GetCreateMachineVersion() string {
601+
return s.getMachineVersionAt(0)
602+
}
603+
604+
func (s *SkeProviderOptions) GetUpdateMachineVersion() string {
605+
return s.getMachineVersionAt(1)
606+
}
607+
608+
func (s *SkeProviderOptions) GetCreateK8sVersion() string {
609+
return s.getK8sVersionAt(0)
610+
}
611+
612+
func (s *SkeProviderOptions) GetUpdateK8sVersion() string {
613+
return s.getK8sVersionAt(1)
614+
}

0 commit comments

Comments
 (0)