Skip to content

Commit 146a310

Browse files
GokceGKFyusel
andauthored
Support control_plane attribute in ske cluster (#1236)
* #STACKITTPR-517 - support control_plane attribute in ske cluster * #STACKITTPR-517 - extend examples * update tests * update example * access scope is now computed * make access scope field immutable * use util functions in condition * fix min acc test --------- Co-authored-by: Alexander Dahmen <alexander.dahmen@inovex.de>
1 parent f4be46e commit 146a310

9 files changed

Lines changed: 165 additions & 13 deletions

File tree

docs/data-sources/ske_cluster.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,17 @@ Read-Only:
117117

118118
Read-Only:
119119

120+
- `control_plane` (Attributes) Control plane for the cluster. (see [below for nested schema](#nestedatt--network--control_plane))
120121
- `id` (String) ID of the STACKIT Network Area (SNA) network into which the cluster will be deployed.
121122

123+
<a id="nestedatt--network--control_plane"></a>
124+
### Nested Schema for `network.control_plane`
125+
126+
Read-Only:
127+
128+
- `access_scope` (String) Access scope of the control plane. It defines if the Kubernetes control plane is public or only available inside a STACKIT Network Area.Possible values are: `PUBLIC`, `SNA`. The field is immutable!
129+
130+
122131

123132
<a id="nestedatt--node_pools"></a>
124133
### Nested Schema for `node_pools`

docs/resources/ske_cluster.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ resource "stackit_ske_cluster" "example" {
3939
start = "01:00:00Z"
4040
end = "02:00:00Z"
4141
}
42+
network = {
43+
control_plane = {
44+
access_scope = "PUBLIC"
45+
}
46+
}
4247
}
4348
4449
# Only use the import statement, if you want to import an existing ske cluster
@@ -204,4 +209,12 @@ Optional:
204209

205210
Optional:
206211

212+
- `control_plane` (Attributes) Control plane for the cluster. (see [below for nested schema](#nestedatt--network--control_plane))
207213
- `id` (String) ID of the STACKIT Network Area (SNA) network into which the cluster will be deployed.
214+
215+
<a id="nestedatt--network--control_plane"></a>
216+
### Nested Schema for `network.control_plane`
217+
218+
Optional:
219+
220+
- `access_scope` (String) Access scope of the control plane. It defines if the Kubernetes control plane is public or only available inside a STACKIT Network Area.Possible values are: `PUBLIC`, `SNA`. The field is immutable!

examples/resources/stackit_ske_cluster/resource.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ resource "stackit_ske_cluster" "example" {
2121
start = "01:00:00Z"
2222
end = "02:00:00Z"
2323
}
24+
network = {
25+
control_plane = {
26+
access_scope = "PUBLIC"
27+
}
28+
}
2429
}
2530

2631
# Only use the import statement, if you want to import an existing ske cluster

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"net/http"
77

8+
sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils"
89
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
910
skeUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/ske/utils"
1011

@@ -223,6 +224,16 @@ func (r *clusterDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
223224
validate.UUID(),
224225
},
225226
},
227+
"control_plane": schema.SingleNestedAttribute{
228+
Description: "Control plane for the cluster.",
229+
Computed: true,
230+
Attributes: map[string]schema.Attribute{
231+
"access_scope": schema.StringAttribute{
232+
Description: "Access scope of the control plane. It defines if the Kubernetes control plane is public or only available inside a STACKIT Network Area." + utils.FormatPossibleValues(sdkUtils.EnumSliceToStringSlice(ske.AllowedAccessScopeEnumValues)...) + " The field is immutable!",
233+
Computed: true,
234+
},
235+
},
236+
},
226237
},
227238
},
228239

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

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,23 @@ var maintenanceTypes = map[string]attr.Type{
158158

159159
// Struct corresponding to Model.Network
160160
type network struct {
161-
ID types.String `tfsdk:"id"`
161+
ID types.String `tfsdk:"id"`
162+
ControlPlane types.Object `tfsdk:"control_plane"`
162163
}
163164

164165
// Types corresponding to network
165166
var networkTypes = map[string]attr.Type{
166-
"id": basetypes.StringType{},
167+
"id": basetypes.StringType{},
168+
"control_plane": types.ObjectType{AttrTypes: controlPlaneTypes},
169+
}
170+
171+
type controlPlane struct {
172+
AccessScope types.String `tfsdk:"access_scope"`
173+
}
174+
175+
// Types corresponding to control plane
176+
var controlPlaneTypes = map[string]attr.Type{
177+
"access_scope": basetypes.StringType{},
167178
}
168179

169180
// Struct corresponding to Model.Hibernations[i]
@@ -566,6 +577,20 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
566577
stringplanmodifier.RequiresReplace(),
567578
},
568579
},
580+
"control_plane": schema.SingleNestedAttribute{
581+
Description: "Control plane for the cluster.",
582+
Optional: true,
583+
Attributes: map[string]schema.Attribute{
584+
"access_scope": schema.StringAttribute{
585+
Description: "Access scope of the control plane. It defines if the Kubernetes control plane is public or only available inside a STACKIT Network Area." + utils.FormatPossibleValues(sdkUtils.EnumSliceToStringSlice(ske.AllowedAccessScopeEnumValues)...) + " The field is immutable!",
586+
Optional: true,
587+
Computed: true,
588+
PlanModifiers: []planmodifier.String{
589+
stringplanmodifier.RequiresReplace(),
590+
},
591+
},
592+
},
593+
},
569594
},
570595
},
571596
"hibernations": schema.ListNestedAttribute{
@@ -1367,8 +1392,21 @@ func toNetworkPayload(ctx context.Context, m *Model) (*ske.Network, error) {
13671392
return nil, fmt.Errorf("converting network object: %v", diags.Errors())
13681393
}
13691394

1395+
var networkControlPlane *ske.V2ControlPlaneNetwork
1396+
if !utils.IsUndefined(network.ControlPlane) {
1397+
networkControlPlaneModel := controlPlane{}
1398+
diags = network.ControlPlane.As(ctx, &networkControlPlaneModel, basetypes.ObjectAsOptions{})
1399+
if diags.HasError() {
1400+
return nil, fmt.Errorf("converting network control plane: %w", core.DiagsToError(diags))
1401+
}
1402+
networkControlPlane = &ske.V2ControlPlaneNetwork{
1403+
AccessScope: ske.V2ControlPlaneNetworkGetAccessScopeAttributeType(conversion.StringValueToPointer(networkControlPlaneModel.AccessScope)),
1404+
}
1405+
}
1406+
13701407
return &ske.Network{
1371-
Id: conversion.StringValueToPointer(network.ID),
1408+
Id: conversion.StringValueToPointer(network.ID),
1409+
ControlPlane: networkControlPlane,
13721410
}, nil
13731411
}
13741412

@@ -1672,12 +1710,32 @@ func mapNetwork(cl *ske.Cluster, m *Model) error {
16721710
return nil
16731711
}
16741712

1713+
var diags diag.Diagnostics
16751714
id := types.StringNull()
16761715
if cl.Network.Id != nil {
16771716
id = types.StringValue(*cl.Network.Id)
16781717
}
1718+
1719+
networkControlPlane := types.ObjectNull(controlPlaneTypes)
1720+
if cl.Network.ControlPlane != nil {
1721+
controlPlaneAccessScope := types.StringNull()
1722+
if cl.Network.ControlPlane.AccessScope != nil {
1723+
controlPlaneAccessScope = types.StringValue(string(cl.Network.ControlPlane.GetAccessScope()))
1724+
}
1725+
1726+
controlPlaneValues := map[string]attr.Value{
1727+
"access_scope": controlPlaneAccessScope,
1728+
}
1729+
1730+
networkControlPlane, diags = types.ObjectValue(controlPlaneTypes, controlPlaneValues)
1731+
if diags.HasError() {
1732+
return fmt.Errorf("creating network control plane: %w", core.DiagsToError(diags))
1733+
}
1734+
}
1735+
16791736
networkValues := map[string]attr.Value{
1680-
"id": id,
1737+
"id": id,
1738+
"control_plane": networkControlPlane,
16811739
}
16821740
networkObject, diags := types.ObjectValue(networkTypes, networkValues)
16831741
if diags.HasError() {

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ func TestMapFields(t *testing.T) {
110110
},
111111
Network: &ske.Network{
112112
Id: utils.Ptr("nid"),
113+
ControlPlane: &ske.V2ControlPlaneNetwork{
114+
AccessScope: ske.V2ControlPlaneNetworkGetAccessScopeAttributeType(utils.Ptr("SNA")),
115+
},
113116
},
114117
Name: utils.Ptr("name"),
115118
Nodepools: &[]ske.Nodepool{
@@ -231,6 +234,9 @@ func TestMapFields(t *testing.T) {
231234
}),
232235
Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
233236
"id": types.StringValue("nid"),
237+
"control_plane": types.ObjectValueMust(controlPlaneTypes, map[string]attr.Value{
238+
"access_scope": types.StringValue("SNA"),
239+
}),
234240
}),
235241
Hibernations: types.ListValueMust(
236242
types.ObjectType{AttrTypes: hibernationTypes},
@@ -560,6 +566,9 @@ func TestMapFields(t *testing.T) {
560566
},
561567
Network: &ske.Network{
562568
Id: utils.Ptr("nid"),
569+
ControlPlane: &ske.V2ControlPlaneNetwork{
570+
AccessScope: ske.V2ControlPlaneNetworkGetAccessScopeAttributeType(utils.Ptr("SNA")),
571+
},
563572
},
564573
Name: utils.Ptr("name"),
565574
Nodepools: &[]ske.Nodepool{
@@ -648,6 +657,9 @@ func TestMapFields(t *testing.T) {
648657
}),
649658
Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
650659
"id": types.StringValue("nid"),
660+
"control_plane": types.ObjectValueMust(controlPlaneTypes, map[string]attr.Value{
661+
"access_scope": types.StringValue("SNA"),
662+
}),
651663
}),
652664
Hibernations: types.ListValueMust(
653665
types.ObjectType{AttrTypes: hibernationTypes},
@@ -2239,10 +2251,16 @@ func TestToNetworkPayload(t *testing.T) {
22392251
Name: types.StringValue("name"),
22402252
Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
22412253
"id": types.StringValue("nid"),
2254+
"control_plane": types.ObjectValueMust(controlPlaneTypes, map[string]attr.Value{
2255+
"access_scope": types.StringValue("SNA"),
2256+
}),
22422257
}),
22432258
},
22442259
&ske.Network{
22452260
Id: utils.Ptr("nid"),
2261+
ControlPlane: &ske.V2ControlPlaneNetwork{
2262+
AccessScope: ske.V2ControlPlaneNetworkGetAccessScopeAttributeType(utils.Ptr("SNA")),
2263+
},
22462264
},
22472265
true,
22482266
},
@@ -2252,12 +2270,29 @@ func TestToNetworkPayload(t *testing.T) {
22522270
ProjectId: types.StringValue("pid"),
22532271
Name: types.StringValue("name"),
22542272
Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
2255-
"id": types.StringNull(),
2273+
"id": types.StringNull(),
2274+
"control_plane": types.ObjectNull(controlPlaneTypes),
22562275
}),
22572276
},
22582277
&ske.Network{},
22592278
true,
22602279
},
2280+
{
2281+
"no_control_plane",
2282+
&Model{
2283+
ProjectId: types.StringValue("pid"),
2284+
Name: types.StringValue("name"),
2285+
Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
2286+
"id": types.StringValue("nid"),
2287+
"control_plane": types.ObjectNull(controlPlaneTypes),
2288+
}),
2289+
},
2290+
&ske.Network{
2291+
Id: utils.Ptr("nid"),
2292+
ControlPlane: nil,
2293+
},
2294+
true,
2295+
},
22612296
{
22622297
"no_network",
22632298
&Model{

stackit/internal/services/ske/ske_acc_test.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ var testConfigVarsMin = config.Variables{
4949
"kubernetes_version_min": config.StringVariable(skeProviderOptions.GetCreateK8sVersion()),
5050
"maintenance_enable_machine_image_version_updates": config.StringVariable("true"),
5151
"maintenance_enable_kubernetes_version_updates": config.StringVariable("true"),
52-
"maintenance_start": config.StringVariable("02:00:00+01:00"),
53-
"maintenance_end": config.StringVariable("04:00:00+01:00"),
54-
"region": config.StringVariable(testutil.Region),
52+
"maintenance_start": config.StringVariable("02:00:00+01:00"),
53+
"maintenance_end": config.StringVariable("04:00:00+01:00"),
54+
"region": config.StringVariable(testutil.Region),
55+
"network_control_plane_access_scope": config.StringVariable("PUBLIC"),
5556
}
5657

5758
var testConfigVarsMax = config.Variables{
@@ -92,6 +93,7 @@ var testConfigVarsMax = config.Variables{
9293
"refresh_before": config.StringVariable("600"),
9394
"dns_zone_name": config.StringVariable("acc-" + acctest.RandStringFromCharSet(6, acctest.CharSetAlpha)),
9495
"dns_name": config.StringVariable("acc-" + acctest.RandStringFromCharSet(6, acctest.CharSetAlpha) + ".runs.onstackit.cloud"),
96+
"network_control_plane_access_scope": config.StringVariable("PUBLIC"),
9597
}
9698

9799
var testConfigDatasource = config.Variables{
@@ -137,12 +139,14 @@ func TestAccSKEMin(t *testing.T) {
137139
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.minimum", testutil.ConvertConfigVariable(testConfigVarsMin["nodepool_minimum"])),
138140
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.name", testutil.ConvertConfigVariable(testConfigVarsMin["nodepool_name"])),
139141
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "node_pools.0.os_version_used"),
140-
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "maintenance.enable_kubernetes_version_updates", testutil.ConvertConfigVariable(testConfigVarsMax["maintenance_enable_kubernetes_version_updates"])),
141-
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "maintenance.enable_machine_image_version_updates", testutil.ConvertConfigVariable(testConfigVarsMax["maintenance_enable_machine_image_version_updates"])),
142-
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "maintenance.start", testutil.ConvertConfigVariable(testConfigVarsMax["maintenance_start"])),
143-
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "maintenance.end", testutil.ConvertConfigVariable(testConfigVarsMax["maintenance_end"])),
144-
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "region"),
142+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "kubernetes_version_min", testutil.ConvertConfigVariable(testConfigVarsMin["kubernetes_version_min"])),
143+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "maintenance.enable_kubernetes_version_updates", testutil.ConvertConfigVariable(testConfigVarsMin["maintenance_enable_kubernetes_version_updates"])),
144+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "maintenance.enable_machine_image_version_updates", testutil.ConvertConfigVariable(testConfigVarsMin["maintenance_enable_machine_image_version_updates"])),
145+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "maintenance.start", testutil.ConvertConfigVariable(testConfigVarsMin["maintenance_start"])),
146+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "maintenance.end", testutil.ConvertConfigVariable(testConfigVarsMin["maintenance_end"])),
147+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "region", testutil.ConvertConfigVariable(testConfigVarsMin["region"])),
145148
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "kubernetes_version_used"),
149+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "network.control_plane.access_scope", testutil.ConvertConfigVariable(testConfigVarsMin["network_control_plane_access_scope"])),
146150

147151
// Kubeconfig
148152
resource.TestCheckResourceAttrPair(
@@ -182,6 +186,7 @@ func TestAccSKEMin(t *testing.T) {
182186
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "maintenance.end", testutil.ConvertConfigVariable(testConfigVarsMax["maintenance_end"])),
183187
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "region"),
184188
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster", "kubernetes_version_used"),
189+
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "network.control_plane.access_scope", testutil.ConvertConfigVariable(testConfigVarsMin["network_control_plane_access_scope"])),
185190
),
186191
},
187192
// 3) Import cluster
@@ -299,6 +304,8 @@ func TestAccSKEMax(t *testing.T) {
299304
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "pod_address_ranges.0"),
300305
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster", "kubernetes_version_used"),
301306

307+
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "network.control_plane.access_scope", testutil.ConvertConfigVariable(testConfigVarsMax["network_control_plane_access_scope"])),
308+
302309
// Kubeconfig
303310
resource.TestCheckResourceAttrPair(
304311
"stackit_ske_kubeconfig.kubeconfig", "project_id",
@@ -373,6 +380,8 @@ func TestAccSKEMax(t *testing.T) {
373380
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster", "pod_address_ranges.0"),
374381

375382
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster", "kubernetes_version_used"),
383+
384+
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "network.control_plane.access_scope", testutil.ConvertConfigVariable(testConfigVarsMax["network_control_plane_access_scope"])),
376385
),
377386
},
378387
// 3) Import cluster

stackit/internal/services/ske/testdata/resource-max.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ variable "refresh" {}
3535
variable "refresh_before" {}
3636
variable "dns_zone_name" {}
3737
variable "dns_name" {}
38+
variable "network_control_plane_access_scope" {}
3839

3940
resource "stackit_ske_cluster" "cluster" {
4041
project_id = var.project_id
@@ -92,6 +93,11 @@ resource "stackit_ske_cluster" "cluster" {
9293
end = var.maintenance_end
9394
}
9495
region = var.region
96+
network = {
97+
control_plane = {
98+
access_scope = var.network_control_plane_access_scope
99+
}
100+
}
95101
}
96102

97103
resource "stackit_ske_kubeconfig" "kubeconfig" {

stackit/internal/services/ske/testdata/resource-min.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ variable "maintenance_enable_machine_image_version_updates" {}
1111
variable "maintenance_start" {}
1212
variable "maintenance_end" {}
1313
variable "region" {}
14+
variable "network_control_plane_access_scope" {}
1415

1516

1617
resource "stackit_ske_cluster" "cluster" {
@@ -36,6 +37,11 @@ resource "stackit_ske_cluster" "cluster" {
3637
end = var.maintenance_end
3738
}
3839
region = var.region
40+
network = {
41+
control_plane = {
42+
access_scope = var.network_control_plane_access_scope
43+
}
44+
}
3945
}
4046

4147
resource "stackit_ske_kubeconfig" "kubeconfig" {

0 commit comments

Comments
 (0)