Feature: allow system components on nodepools (#591)
* feat: allow system components on nodepools * docs: generated docs for ske * lint: sort imports * revert changes
This commit is contained in:
parent
2bf6a8dce7
commit
3ac1d50253
6 changed files with 155 additions and 59 deletions
|
|
@ -114,6 +114,7 @@ Read-Only:
|
|||
|
||||
Read-Only:
|
||||
|
||||
- `allow_system_components` (Boolean) Allow system components to run on this node pool.
|
||||
- `availability_zones` (List of String) Specify a list of availability zones.
|
||||
- `cri` (String) Specifies the container runtime.
|
||||
- `labels` (Map of String) Labels to add to each node.
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ Required:
|
|||
|
||||
Optional:
|
||||
|
||||
- `allow_system_components` (Boolean) Allow system components to run on this node pool.
|
||||
- `cri` (String) Specifies the container runtime. Defaults to `containerd`
|
||||
- `labels` (Map of String) Labels to add to each node.
|
||||
- `max_surge` (Number) Maximum number of additional VMs that are created during an update. If set (larger than 0), then it must be at least the amount of zones configured for the nodepool. The `max_surge` and `max_unavailable` fields cannot both be unset at the same time.
|
||||
|
|
|
|||
|
|
@ -202,6 +202,10 @@ func (r *clusterDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
|
|||
ElementType: types.StringType,
|
||||
Computed: true,
|
||||
},
|
||||
"allow_system_components": schema.BoolAttribute{
|
||||
Description: "Allow system components to run on this node pool.",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -82,42 +82,44 @@ type Model struct {
|
|||
|
||||
// Struct corresponding to Model.NodePools[i]
|
||||
type nodePool struct {
|
||||
Name types.String `tfsdk:"name"`
|
||||
MachineType types.String `tfsdk:"machine_type"`
|
||||
OSName types.String `tfsdk:"os_name"`
|
||||
OSVersionMin types.String `tfsdk:"os_version_min"`
|
||||
OSVersion types.String `tfsdk:"os_version"`
|
||||
OSVersionUsed types.String `tfsdk:"os_version_used"`
|
||||
Minimum types.Int64 `tfsdk:"minimum"`
|
||||
Maximum types.Int64 `tfsdk:"maximum"`
|
||||
MaxSurge types.Int64 `tfsdk:"max_surge"`
|
||||
MaxUnavailable types.Int64 `tfsdk:"max_unavailable"`
|
||||
VolumeType types.String `tfsdk:"volume_type"`
|
||||
VolumeSize types.Int64 `tfsdk:"volume_size"`
|
||||
Labels types.Map `tfsdk:"labels"`
|
||||
Taints types.List `tfsdk:"taints"`
|
||||
CRI types.String `tfsdk:"cri"`
|
||||
AvailabilityZones types.List `tfsdk:"availability_zones"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
MachineType types.String `tfsdk:"machine_type"`
|
||||
OSName types.String `tfsdk:"os_name"`
|
||||
OSVersionMin types.String `tfsdk:"os_version_min"`
|
||||
OSVersion types.String `tfsdk:"os_version"`
|
||||
OSVersionUsed types.String `tfsdk:"os_version_used"`
|
||||
Minimum types.Int64 `tfsdk:"minimum"`
|
||||
Maximum types.Int64 `tfsdk:"maximum"`
|
||||
MaxSurge types.Int64 `tfsdk:"max_surge"`
|
||||
MaxUnavailable types.Int64 `tfsdk:"max_unavailable"`
|
||||
VolumeType types.String `tfsdk:"volume_type"`
|
||||
VolumeSize types.Int64 `tfsdk:"volume_size"`
|
||||
Labels types.Map `tfsdk:"labels"`
|
||||
Taints types.List `tfsdk:"taints"`
|
||||
CRI types.String `tfsdk:"cri"`
|
||||
AvailabilityZones types.List `tfsdk:"availability_zones"`
|
||||
AllowSystemComponents types.Bool `tfsdk:"allow_system_components"`
|
||||
}
|
||||
|
||||
// Types corresponding to nodePool
|
||||
var nodePoolTypes = map[string]attr.Type{
|
||||
"name": basetypes.StringType{},
|
||||
"machine_type": basetypes.StringType{},
|
||||
"os_name": basetypes.StringType{},
|
||||
"os_version_min": basetypes.StringType{},
|
||||
"os_version": basetypes.StringType{},
|
||||
"os_version_used": basetypes.StringType{},
|
||||
"minimum": basetypes.Int64Type{},
|
||||
"maximum": basetypes.Int64Type{},
|
||||
"max_surge": basetypes.Int64Type{},
|
||||
"max_unavailable": basetypes.Int64Type{},
|
||||
"volume_type": basetypes.StringType{},
|
||||
"volume_size": basetypes.Int64Type{},
|
||||
"labels": basetypes.MapType{ElemType: types.StringType},
|
||||
"taints": basetypes.ListType{ElemType: types.ObjectType{AttrTypes: taintTypes}},
|
||||
"cri": basetypes.StringType{},
|
||||
"availability_zones": basetypes.ListType{ElemType: types.StringType},
|
||||
"name": basetypes.StringType{},
|
||||
"machine_type": basetypes.StringType{},
|
||||
"os_name": basetypes.StringType{},
|
||||
"os_version_min": basetypes.StringType{},
|
||||
"os_version": basetypes.StringType{},
|
||||
"os_version_used": basetypes.StringType{},
|
||||
"minimum": basetypes.Int64Type{},
|
||||
"maximum": basetypes.Int64Type{},
|
||||
"max_surge": basetypes.Int64Type{},
|
||||
"max_unavailable": basetypes.Int64Type{},
|
||||
"volume_type": basetypes.StringType{},
|
||||
"volume_size": basetypes.Int64Type{},
|
||||
"labels": basetypes.MapType{ElemType: types.StringType},
|
||||
"taints": basetypes.ListType{ElemType: types.ObjectType{AttrTypes: taintTypes}},
|
||||
"cri": basetypes.StringType{},
|
||||
"availability_zones": basetypes.ListType{ElemType: types.StringType},
|
||||
"allow_system_components": basetypes.BoolType{},
|
||||
}
|
||||
|
||||
// Struct corresponding to nodePool.Taints[i]
|
||||
|
|
@ -391,6 +393,12 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||
Required: true,
|
||||
ElementType: types.StringType,
|
||||
},
|
||||
"allow_system_components": schema.BoolAttribute{
|
||||
Description: "Allow system components to run on this node pool.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: booldefault.StaticBool(true),
|
||||
},
|
||||
"minimum": schema.Int64Attribute{
|
||||
Description: "Minimum number of nodes in the pool.",
|
||||
Required: true,
|
||||
|
|
@ -994,16 +1002,32 @@ func toNodepoolsPayload(ctx context.Context, m *Model, availableMachineVersions
|
|||
Type: conversion.StringValueToPointer(nodePool.VolumeType),
|
||||
Size: conversion.Int64ValueToPointer(nodePool.VolumeSize),
|
||||
},
|
||||
Taints: &ts,
|
||||
Cri: &cn,
|
||||
Labels: ls,
|
||||
AvailabilityZones: &zs,
|
||||
Taints: &ts,
|
||||
Cri: &cn,
|
||||
Labels: ls,
|
||||
AvailabilityZones: &zs,
|
||||
AllowSystemComponents: conversion.BoolValueToPointer(nodePool.AllowSystemComponents),
|
||||
}
|
||||
cnps = append(cnps, cnp)
|
||||
}
|
||||
|
||||
if err := verifySystemComponentsInNodePools(cnps); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return cnps, deprecatedVersionsUsed, nil
|
||||
}
|
||||
|
||||
// verifySystemComponentsInNodePools checks if at least one node pool has the allow_system_components attribute set to true.
|
||||
func verifySystemComponentsInNodePools(nodePools []ske.Nodepool) error {
|
||||
for _, nodePool := range nodePools {
|
||||
if nodePool.AllowSystemComponents != nil && *nodePool.AllowSystemComponents {
|
||||
return nil // A node pool allowing system components was found
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("at least one node_pool must allow system components")
|
||||
}
|
||||
|
||||
// latestMatchingMachineVersion determines the latest machine image version for the create/update payload.
|
||||
// It considers the available versions for the specified OS (OSName), the minimum version configured by the user,
|
||||
// and the current version in the cluster. The function's behavior is as follows:
|
||||
|
|
@ -1374,20 +1398,21 @@ func mapNodePools(ctx context.Context, cl *ske.Cluster, m *Model) error {
|
|||
nodePools := []attr.Value{}
|
||||
for i, nodePoolResp := range *cl.Nodepools {
|
||||
nodePool := map[string]attr.Value{
|
||||
"name": types.StringPointerValue(nodePoolResp.Name),
|
||||
"machine_type": types.StringPointerValue(nodePoolResp.Machine.Type),
|
||||
"os_name": types.StringNull(),
|
||||
"os_version_min": modelNodePoolOSVersionMin[*nodePoolResp.Name],
|
||||
"os_version": modelNodePoolOSVersion[*nodePoolResp.Name],
|
||||
"minimum": types.Int64PointerValue(nodePoolResp.Minimum),
|
||||
"maximum": types.Int64PointerValue(nodePoolResp.Maximum),
|
||||
"max_surge": types.Int64PointerValue(nodePoolResp.MaxSurge),
|
||||
"max_unavailable": types.Int64PointerValue(nodePoolResp.MaxUnavailable),
|
||||
"volume_type": types.StringNull(),
|
||||
"volume_size": types.Int64PointerValue(nodePoolResp.Volume.Size),
|
||||
"labels": types.MapNull(types.StringType),
|
||||
"cri": types.StringNull(),
|
||||
"availability_zones": types.ListNull(types.StringType),
|
||||
"name": types.StringPointerValue(nodePoolResp.Name),
|
||||
"machine_type": types.StringPointerValue(nodePoolResp.Machine.Type),
|
||||
"os_name": types.StringNull(),
|
||||
"os_version_min": modelNodePoolOSVersionMin[*nodePoolResp.Name],
|
||||
"os_version": modelNodePoolOSVersion[*nodePoolResp.Name],
|
||||
"minimum": types.Int64PointerValue(nodePoolResp.Minimum),
|
||||
"maximum": types.Int64PointerValue(nodePoolResp.Maximum),
|
||||
"max_surge": types.Int64PointerValue(nodePoolResp.MaxSurge),
|
||||
"max_unavailable": types.Int64PointerValue(nodePoolResp.MaxUnavailable),
|
||||
"volume_type": types.StringNull(),
|
||||
"volume_size": types.Int64PointerValue(nodePoolResp.Volume.Size),
|
||||
"labels": types.MapNull(types.StringType),
|
||||
"cri": types.StringNull(),
|
||||
"availability_zones": types.ListNull(types.StringType),
|
||||
"allow_system_components": types.BoolPointerValue(nodePoolResp.AllowSystemComponents),
|
||||
}
|
||||
|
||||
if nodePoolResp.Machine != nil && nodePoolResp.Machine.Image != nil {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ import (
|
|||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/utils"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/ske"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
|
||||
)
|
||||
|
||||
|
|
@ -106,7 +108,8 @@ func TestMapFields(t *testing.T) {
|
|||
Name: utils.Ptr("name"),
|
||||
Nodepools: &[]ske.Nodepool{
|
||||
{
|
||||
AvailabilityZones: &[]string{"z1", "z2"},
|
||||
AllowSystemComponents: utils.Ptr(true),
|
||||
AvailabilityZones: &[]string{"z1", "z2"},
|
||||
Cri: &ske.CRI{
|
||||
Name: utils.Ptr("cri"),
|
||||
},
|
||||
|
|
@ -195,6 +198,7 @@ func TestMapFields(t *testing.T) {
|
|||
types.StringValue("z2"),
|
||||
},
|
||||
),
|
||||
"allow_system_components": types.BoolValue(true),
|
||||
},
|
||||
),
|
||||
},
|
||||
|
|
@ -481,6 +485,7 @@ func TestMapFields(t *testing.T) {
|
|||
types.StringValue("z2"),
|
||||
},
|
||||
),
|
||||
"allow_system_components": types.BoolValue(true),
|
||||
},
|
||||
),
|
||||
},
|
||||
|
|
@ -599,6 +604,7 @@ func TestMapFields(t *testing.T) {
|
|||
types.StringValue("z2"),
|
||||
},
|
||||
),
|
||||
"allow_system_components": types.BoolNull(),
|
||||
},
|
||||
),
|
||||
},
|
||||
|
|
@ -2284,3 +2290,57 @@ func TestToNetworkPayload(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifySystemComponentNodepools(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
nodePools []ske.Nodepool
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
description: "all pools allow system components",
|
||||
nodePools: []ske.Nodepool{
|
||||
{
|
||||
AllowSystemComponents: conversion.BoolValueToPointer(basetypes.NewBoolValue(true)),
|
||||
},
|
||||
{
|
||||
AllowSystemComponents: conversion.BoolValueToPointer(basetypes.NewBoolValue(true)),
|
||||
},
|
||||
},
|
||||
isValid: true,
|
||||
},
|
||||
{
|
||||
description: "one pool allows system components",
|
||||
nodePools: []ske.Nodepool{
|
||||
{
|
||||
AllowSystemComponents: conversion.BoolValueToPointer(basetypes.NewBoolValue(true)),
|
||||
},
|
||||
{
|
||||
AllowSystemComponents: conversion.BoolValueToPointer(basetypes.NewBoolValue(false)),
|
||||
},
|
||||
},
|
||||
isValid: true,
|
||||
},
|
||||
{
|
||||
description: "no pool allows system components",
|
||||
nodePools: []ske.Nodepool{
|
||||
{
|
||||
AllowSystemComponents: conversion.BoolValueToPointer(basetypes.NewBoolValue(false)),
|
||||
},
|
||||
{
|
||||
AllowSystemComponents: conversion.BoolValueToPointer(basetypes.NewBoolValue(false)),
|
||||
},
|
||||
},
|
||||
isValid: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
err := verifySystemComponentsInNodePools(tt.nodePools)
|
||||
if (err == nil) != tt.isValid {
|
||||
t.Errorf("expected validity to be %v, but got error: %v", tt.isValid, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,17 +21,17 @@ var clusterResource = map[string]string{
|
|||
"project_id": testutil.ProjectId,
|
||||
"name": fmt.Sprintf("cl-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)),
|
||||
"name_min": fmt.Sprintf("cl-min-%s", acctest.RandStringFromCharSet(3, acctest.CharSetAlphaNum)),
|
||||
"kubernetes_version_min": "1.28",
|
||||
"kubernetes_version_used": "1.28.11",
|
||||
"kubernetes_version_min_new": "1.29",
|
||||
"kubernetes_version_used_new": "1.29.6",
|
||||
"kubernetes_version_min": "1.29",
|
||||
"kubernetes_version_used": "1.29.10",
|
||||
"kubernetes_version_min_new": "1.30",
|
||||
"kubernetes_version_used_new": "1.30.6",
|
||||
"nodepool_name": "np-acc-test",
|
||||
"nodepool_name_min": "np-acc-min-test",
|
||||
"nodepool_machine_type": "b1.2",
|
||||
"nodepool_os_version_min": "3815.2",
|
||||
"nodepool_os_version_used": "3815.2.3",
|
||||
"nodepool_os_version_min_new": "3815.2.3",
|
||||
"nodepool_os_version_used_new": "3815.2.3",
|
||||
"nodepool_os_version_min": "3975.2",
|
||||
"nodepool_os_version_used": "3975.2.0",
|
||||
"nodepool_os_version_min_new": "3975.2.1",
|
||||
"nodepool_os_version_used_new": "3975.2.1",
|
||||
"nodepool_os_name": "flatcar",
|
||||
"nodepool_minimum": "2",
|
||||
"nodepool_maximum": "3",
|
||||
|
|
@ -46,6 +46,7 @@ var clusterResource = map[string]string{
|
|||
"nodepool_taints_effect": "PreferNoSchedule",
|
||||
"nodepool_taints_key": "tkey",
|
||||
"nodepool_taints_value": "tvalue",
|
||||
"nodepool_allow_system_components": "true",
|
||||
"extensions_acl_enabled": "true",
|
||||
"extensions_acl_cidrs": "192.168.0.0/24",
|
||||
"extensions_argus_enabled": "false",
|
||||
|
|
@ -96,6 +97,7 @@ func getConfig(kubernetesVersion, nodePoolMachineOSVersion string, maintenanceEn
|
|||
key = "%s"
|
||||
value = "%s"
|
||||
}]
|
||||
allow_system_components = %s
|
||||
}]
|
||||
extensions = {
|
||||
acl = {
|
||||
|
|
@ -169,6 +171,7 @@ func getConfig(kubernetesVersion, nodePoolMachineOSVersion string, maintenanceEn
|
|||
clusterResource["nodepool_taints_effect"],
|
||||
clusterResource["nodepool_taints_key"],
|
||||
clusterResource["nodepool_taints_value"],
|
||||
clusterResource["nodepool_allow_system_components"],
|
||||
clusterResource["extensions_acl_enabled"],
|
||||
clusterResource["extensions_acl_cidrs"],
|
||||
clusterResource["extensions_argus_enabled"],
|
||||
|
|
@ -233,6 +236,7 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.taints.0.effect", clusterResource["nodepool_taints_effect"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.taints.0.key", clusterResource["nodepool_taints_key"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.taints.0.value", clusterResource["nodepool_taints_value"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.allow_system_components", clusterResource["nodepool_allow_system_components"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.cri", clusterResource["nodepool_cri"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.acl.enabled", clusterResource["extensions_acl_enabled"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "extensions.acl.allowed_cidrs.#", "1"),
|
||||
|
|
@ -343,6 +347,7 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.taints.0.effect", clusterResource["nodepool_taints_effect"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.taints.0.key", clusterResource["nodepool_taints_key"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.taints.0.value", clusterResource["nodepool_taints_value"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.allow_system_components", clusterResource["nodepool_allow_system_components"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.cri", clusterResource["nodepool_cri"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "extensions.acl.enabled", clusterResource["extensions_acl_enabled"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "extensions.acl.allowed_cidrs.#", "1"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue