Support SKE OS versions auto and forceful updates (#364)
* Deprecate os_version and add os_version_used * Add os_version_min field * Draft implementation for os_version_min * Finish implementation * Fix mapFields * Update stackit/internal/services/ske/cluster/resource.go Co-authored-by: Diogo Ferrão <diogo.ferrao@freiheit.com> * Update stackit/internal/services/ske/cluster/resource.go Co-authored-by: Diogo Ferrão <diogo.ferrao@freiheit.com> * Update stackit/internal/services/ske/cluster/resource.go Co-authored-by: Diogo Ferrão <diogo.ferrao@freiheit.com> * Update stackit/internal/services/ske/cluster/resource.go Co-authored-by: Diogo Ferrão <diogo.ferrao@freiheit.com> * Improve descriptions * Improve variable names * Fix lint * Extend acc test, generate docs * Don't select automatically preview versions * Update acc test * Simplify code --------- Co-authored-by: Diogo Ferrão <diogo.ferrao@freiheit.com>
This commit is contained in:
parent
76b8e5692d
commit
e850a952bd
6 changed files with 1080 additions and 153 deletions
|
|
@ -106,6 +106,8 @@ Read-Only:
|
|||
- `name` (String) Specifies the name of the node pool.
|
||||
- `os_name` (String) The name of the OS image.
|
||||
- `os_version` (String) The OS image version.
|
||||
- `os_version_min` (String) The minimum OS image version, this field is always nil. 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). To get the current OS image version being used for the node pool, use the read-only `os_version_used` field.
|
||||
- `os_version_used` (String) Full OS image version used. For example, if 3815.2 was set in `os_version_min`, this value may result to 3815.2.2. 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).
|
||||
- `taints` (Attributes List) Specifies a taint list as defined below. (see [below for nested schema](#nestedatt--node_pools--taints))
|
||||
- `volume_size` (Number) The volume size in GB.
|
||||
- `volume_type` (String) Specifies the volume type.
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ Deprecated as of Kubernetes 1.25 and later
|
|||
- `extensions` (Attributes) A single extensions block as defined below. (see [below for nested schema](#nestedatt--extensions))
|
||||
- `hibernations` (Attributes List) One or more hibernation block as defined below. (see [below for nested schema](#nestedatt--hibernations))
|
||||
- `kubernetes_version` (String, Deprecated) Kubernetes version. Must only contain major and minor version (e.g. 1.22). This field is deprecated, use `kubernetes_version_min instead`
|
||||
- `kubernetes_version_min` (String) The minimum Kubernetes version. This field will be used to set the minimum kubernetes version on creation/update of the cluster and can only by incremented. If unset, the latest supported Kubernetes version will be used. 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). To get the current kubernetes version being used for your cluster, use the read-only `kubernetes_version_used` field.
|
||||
- `kubernetes_version_min` (String) The minimum Kubernetes version. This field will be used to set the minimum kubernetes version on creation/update of the cluster. If unset, the latest supported Kubernetes version will be used. 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). To get the current kubernetes version being used for your cluster, use the read-only `kubernetes_version_used` field.
|
||||
- `maintenance` (Attributes) A single maintenance block as defined below. (see [below for nested schema](#nestedatt--maintenance))
|
||||
|
||||
### Read-Only
|
||||
|
|
@ -72,7 +72,6 @@ Required:
|
|||
- `maximum` (Number) Maximum number of nodes in the pool.
|
||||
- `minimum` (Number) Minimum number of nodes in the pool.
|
||||
- `name` (String) Specifies the name of the node pool.
|
||||
- `os_version` (String) The OS image version.
|
||||
|
||||
Optional:
|
||||
|
||||
|
|
@ -81,10 +80,16 @@ Optional:
|
|||
- `max_surge` (Number) Maximum number of additional VMs that are created during an update.
|
||||
- `max_unavailable` (Number) Maximum number of VMs that that can be unavailable during an update.
|
||||
- `os_name` (String) The name of the OS image. E.g. `flatcar`.
|
||||
- `os_version` (String, Deprecated) This field is deprecated, use `os_version_min` to configure the version and `os_version_used` to get the currently used version instead
|
||||
- `os_version_min` (String) The minimum OS image version. This field will be used to set the minimum OS image version on creation/update of the cluster. If unset, the latest supported OS image version will be used. 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). To get the current OS image version being used for the node pool, use the read-only `os_version_used` field.
|
||||
- `taints` (Attributes List) Specifies a taint list as defined below. (see [below for nested schema](#nestedatt--node_pools--taints))
|
||||
- `volume_size` (Number) The volume size in GB. E.g. `20`
|
||||
- `volume_type` (String) Specifies the volume type. E.g. `storage_premium_perf1`.
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `os_version_used` (String) Full OS image version used. For example, if 3815.2 was set in `os_version_min`, this value may result to 3815.2.2. 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).
|
||||
|
||||
<a id="nestedatt--node_pools--taints"></a>
|
||||
### Nested Schema for `node_pools.taints`
|
||||
|
||||
|
|
@ -150,10 +155,10 @@ Optional:
|
|||
|
||||
Required:
|
||||
|
||||
- `enable_machine_image_version_updates` (Boolean) Flag to enable/disable auto-updates of the OS image version.
|
||||
- `end` (String) Time for maintenance window end. E.g. `01:23:45Z`, `05:00:00+02:00`.
|
||||
- `start` (String) Time for maintenance window start. E.g. `01:23:45Z`, `05:00:00+02:00`.
|
||||
|
||||
Optional:
|
||||
|
||||
- `enable_kubernetes_version_updates` (Boolean) Flag to enable/disable auto-updates of the Kubernetes version. Defaults to `true. 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).
|
||||
- `enable_kubernetes_version_updates` (Boolean) Flag to enable/disable auto-updates of the Kubernetes version. Defaults to `true`. 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).
|
||||
- `enable_machine_image_version_updates` (Boolean) Flag to enable/disable auto-updates of the OS image version. Defaults to `true`. 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).
|
||||
|
|
|
|||
|
|
@ -130,10 +130,18 @@ func (r *clusterDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
|
|||
Description: "The name of the OS image.",
|
||||
Computed: true,
|
||||
},
|
||||
"os_version_min": schema.StringAttribute{
|
||||
Description: "The minimum OS image version, this field is always nil. " + SKEUpdateDoc + " To get the current OS image version being used for the node pool, use the read-only `os_version_used` field.",
|
||||
Computed: true,
|
||||
},
|
||||
"os_version": schema.StringAttribute{
|
||||
Description: "The OS image version.",
|
||||
Computed: true,
|
||||
},
|
||||
"os_version_used": schema.StringAttribute{
|
||||
Description: "Full OS image version used. For example, if 3815.2 was set in `os_version_min`, this value may result to 3815.2.2. " + SKEUpdateDoc,
|
||||
Computed: true,
|
||||
},
|
||||
"minimum": schema.Int64Attribute{
|
||||
Description: "Minimum number of nodes in the pool.",
|
||||
Computed: true,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@ 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"`
|
||||
|
|
@ -101,7 +103,9 @@ 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{},
|
||||
|
|
@ -279,7 +283,7 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||
},
|
||||
},
|
||||
"kubernetes_version_min": schema.StringAttribute{
|
||||
Description: "The minimum Kubernetes version. This field will be used to set the minimum kubernetes version on creation/update of the cluster and can only by incremented. If unset, the latest supported Kubernetes version will be used. " + SKEUpdateDoc + " To get the current kubernetes version being used for your cluster, use the read-only `kubernetes_version_used` field.",
|
||||
Description: "The minimum Kubernetes version. This field will be used to set the minimum kubernetes version on creation/update of the cluster. If unset, the latest supported Kubernetes version will be used. " + SKEUpdateDoc + " To get the current kubernetes version being used for your cluster, use the read-only `kubernetes_version_used` field.",
|
||||
Optional: true,
|
||||
Validators: []validator.String{
|
||||
validate.VersionNumber(),
|
||||
|
|
@ -288,7 +292,7 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||
"kubernetes_version": schema.StringAttribute{
|
||||
Description: "Kubernetes version. Must only contain major and minor version (e.g. 1.22). This field is deprecated, use `kubernetes_version_min instead`",
|
||||
Optional: true,
|
||||
DeprecationMessage: "Use `kubernetes_version_min instead`. Setting a specific kubernetes version would cause errors when the cluster got a kubernetes version minor upgrade, either triggered by automatic or forceful updates. In those cases, this field might not represent the actual kubernetes version used in the cluster.",
|
||||
DeprecationMessage: "Use `kubernetes_version_min instead`. Setting a specific kubernetes version would cause errors during minor version upgrades due to forced updates. In those cases, this field might not represent the actual kubernetes version used in the cluster.",
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplaceIf(stringplanmodifier.RequiresReplaceIfFunc(func(ctx context.Context, sr planmodifier.StringRequest, rrifr *stringplanmodifier.RequiresReplaceIfFuncResponse) {
|
||||
if sr.StateValue.IsNull() || sr.PlanValue.IsNull() {
|
||||
|
|
@ -376,9 +380,21 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||
Computed: true,
|
||||
Default: stringdefault.StaticString(DefaultOSName),
|
||||
},
|
||||
"os_version_min": schema.StringAttribute{
|
||||
Description: "The minimum OS image version. This field will be used to set the minimum OS image version on creation/update of the cluster. If unset, the latest supported OS image version will be used. " + SKEUpdateDoc + " To get the current OS image version being used for the node pool, use the read-only `os_version_used` field.",
|
||||
Optional: true,
|
||||
Validators: []validator.String{
|
||||
validate.VersionNumber(),
|
||||
},
|
||||
},
|
||||
"os_version": schema.StringAttribute{
|
||||
Description: "The OS image version.",
|
||||
Required: true,
|
||||
Description: "This field is deprecated, use `os_version_min` to configure the version and `os_version_used` to get the currently used version instead",
|
||||
DeprecationMessage: "Use `os_version_min` to configure the version and `os_version_used` to get the currently used version instead. Setting a specific OS image version will cause errors during minor OS upgrades due to forced updates.",
|
||||
Optional: true,
|
||||
},
|
||||
"os_version_used": schema.StringAttribute{
|
||||
Description: "Full OS image version used. For example, if 3815.2 was set in `os_version_min`, this value may result to 3815.2.2. " + SKEUpdateDoc,
|
||||
Computed: true,
|
||||
},
|
||||
"volume_type": schema.StringAttribute{
|
||||
Description: "Specifies the volume type. E.g. `storage_premium_perf1`.",
|
||||
|
|
@ -442,14 +458,16 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||
},
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"enable_kubernetes_version_updates": schema.BoolAttribute{
|
||||
Description: "Flag to enable/disable auto-updates of the Kubernetes version. Defaults to `true. " + SKEUpdateDoc,
|
||||
Description: "Flag to enable/disable auto-updates of the Kubernetes version. Defaults to `true`. " + SKEUpdateDoc,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: booldefault.StaticBool(true),
|
||||
},
|
||||
"enable_machine_image_version_updates": schema.BoolAttribute{
|
||||
Description: "Flag to enable/disable auto-updates of the OS image version.",
|
||||
Required: true,
|
||||
Description: "Flag to enable/disable auto-updates of the OS image version. Defaults to `true`. " + SKEUpdateDoc,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Default: booldefault.StaticBool(true),
|
||||
},
|
||||
"start": schema.StringAttribute{
|
||||
Description: "Time for maintenance window start. E.g. `01:23:45Z`, `05:00:00+02:00`.",
|
||||
|
|
@ -549,6 +567,10 @@ func (r *clusterResource) ConfigValidators(_ context.Context) []resource.ConfigV
|
|||
path.MatchRoot("kubernetes_version"),
|
||||
path.MatchRoot("kubernetes_version_min"),
|
||||
),
|
||||
resourcevalidator.Conflicting(
|
||||
path.MatchRoot("node_pools").AtAnyListIndex().AtName("os_version_min"),
|
||||
path.MatchRoot("node_pools").AtAnyListIndex().AtName("os_version"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -618,13 +640,13 @@ func (r *clusterResource) Create(ctx context.Context, req resource.CreateRequest
|
|||
return
|
||||
}
|
||||
|
||||
availableVersions, err := r.loadAvailableVersions(ctx)
|
||||
availableKubernetesVersions, availableMachines, err := r.loadAvailableVersions(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating cluster", fmt.Sprintf("Loading available Kubernetes versions: %v", err))
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating cluster", fmt.Sprintf("Loading available Kubernetes and machine image versions: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
r.createOrUpdateCluster(ctx, &resp.Diagnostics, &model, availableVersions, nil)
|
||||
r.createOrUpdateCluster(ctx, &resp.Diagnostics, &model, availableKubernetesVersions, availableMachines, nil, nil)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
|
@ -638,40 +660,57 @@ func (r *clusterResource) Create(ctx context.Context, req resource.CreateRequest
|
|||
tflog.Info(ctx, "SKE cluster created")
|
||||
}
|
||||
|
||||
func (r *clusterResource) loadAvailableVersions(ctx context.Context) ([]ske.KubernetesVersion, error) {
|
||||
func (r *clusterResource) loadAvailableVersions(ctx context.Context) ([]ske.KubernetesVersion, []ske.MachineImage, error) {
|
||||
c := r.client
|
||||
res, err := c.ListProviderOptions(ctx).Execute()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calling API: %w", err)
|
||||
return nil, nil, fmt.Errorf("calling API: %w", err)
|
||||
}
|
||||
|
||||
if res.KubernetesVersions == nil {
|
||||
return nil, fmt.Errorf("API response has nil kubernetesVersions")
|
||||
return nil, nil, fmt.Errorf("API response has nil kubernetesVersions")
|
||||
}
|
||||
|
||||
return *res.KubernetesVersions, nil
|
||||
if res.MachineImages == nil {
|
||||
return nil, nil, fmt.Errorf("API response has nil machine images")
|
||||
}
|
||||
|
||||
return *res.KubernetesVersions, *res.MachineImages, nil
|
||||
}
|
||||
|
||||
// getCurrentKubernetesVersion makes a call to get the details of a cluster and returns the current kubernetes version
|
||||
// if the cluster doesn't exist or some error occurs, returns nil
|
||||
func getCurrentKubernetesVersion(ctx context.Context, c skeClient, m *Model) *string {
|
||||
// getCurrentVersions makes a call to get the details of a cluster and returns the current kubernetes version and a
|
||||
// a map with the machine image for each nodepool, which can be used to check the current machine image versions.
|
||||
// if the cluster doesn't exist or some error occurs, returns nil for both
|
||||
func getCurrentVersions(ctx context.Context, c skeClient, m *Model) (kubernetesVersion *string, nodePoolMachineImages map[string]*ske.Image) {
|
||||
res, err := c.GetClusterExecute(ctx, m.ProjectId.ValueString(), m.Name.ValueString())
|
||||
if err != nil {
|
||||
return nil
|
||||
if err != nil || res == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if res != nil && res.Kubernetes != nil {
|
||||
return res.Kubernetes.Version
|
||||
if res.Kubernetes != nil {
|
||||
kubernetesVersion = res.Kubernetes.Version
|
||||
}
|
||||
|
||||
return nil
|
||||
if res.Nodepools == nil {
|
||||
return kubernetesVersion, nil
|
||||
}
|
||||
|
||||
nodePoolMachineImages = map[string]*ske.Image{}
|
||||
for _, nodePool := range *res.Nodepools {
|
||||
if nodePool.Name == nil || nodePool.Machine == nil || nodePool.Machine.Image == nil || nodePool.Machine.Image.Name == nil {
|
||||
continue
|
||||
}
|
||||
nodePoolMachineImages[*nodePool.Name] = nodePool.Machine.Image
|
||||
}
|
||||
|
||||
return kubernetesVersion, nodePoolMachineImages
|
||||
}
|
||||
|
||||
func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag.Diagnostics, model *Model, availableVersions []ske.KubernetesVersion, currentKubernetesVersion *string) {
|
||||
func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag.Diagnostics, model *Model, availableKubernetesVersions []ske.KubernetesVersion, availableMachineVersions []ske.MachineImage, currentKubernetesVersion *string, currentMachineImages map[string]*ske.Image) {
|
||||
// cluster vars
|
||||
projectId := model.ProjectId.ValueString()
|
||||
name := model.Name.ValueString()
|
||||
kubernetes, hasDeprecatedVersion, err := toKubernetesPayload(model, availableVersions, currentKubernetesVersion)
|
||||
kubernetes, hasDeprecatedVersion, err := toKubernetesPayload(model, availableKubernetesVersions, currentKubernetesVersion)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Creating cluster config API payload: %v", err))
|
||||
return
|
||||
|
|
@ -679,11 +718,14 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag
|
|||
if hasDeprecatedVersion {
|
||||
diags.AddWarning("Deprecated Kubernetes version", fmt.Sprintf("Version %s of Kubernetes is deprecated, please update it", *kubernetes.Version))
|
||||
}
|
||||
nodePools, err := toNodepoolsPayload(ctx, model)
|
||||
nodePools, deprecatedVersionsUsed, err := toNodepoolsPayload(ctx, model, availableMachineVersions, currentMachineImages)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Creating node pools API payload: %v", err))
|
||||
return
|
||||
}
|
||||
if len(deprecatedVersionsUsed) != 0 {
|
||||
diags.AddWarning("Deprecated node pools OS versions used", fmt.Sprintf("The following versions of machines are deprecated, please update them: [%s]", strings.Join(deprecatedVersionsUsed, ",")))
|
||||
}
|
||||
maintenance, err := toMaintenancePayload(ctx, model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Creating maintenance API payload: %v", err))
|
||||
|
|
@ -763,14 +805,15 @@ func (r *clusterResource) getCredential(ctx context.Context, diags *diag.Diagnos
|
|||
return nil
|
||||
}
|
||||
|
||||
func toNodepoolsPayload(ctx context.Context, m *Model) ([]ske.Nodepool, error) {
|
||||
func toNodepoolsPayload(ctx context.Context, m *Model, availableMachineVersions []ske.MachineImage, currentMachineImages map[string]*ske.Image) ([]ske.Nodepool, []string, error) {
|
||||
nodePools := []nodePool{}
|
||||
diags := m.NodePools.ElementsAs(ctx, &nodePools, false)
|
||||
if diags.HasError() {
|
||||
return nil, core.DiagsToError(diags)
|
||||
return nil, nil, core.DiagsToError(diags)
|
||||
}
|
||||
|
||||
cnps := []ske.Nodepool{}
|
||||
deprecatedVersionsUsed := []string{}
|
||||
for i := range nodePools {
|
||||
nodePool := nodePools[i]
|
||||
|
||||
|
|
@ -778,7 +821,7 @@ func toNodepoolsPayload(ctx context.Context, m *Model) ([]ske.Nodepool, error) {
|
|||
taintsModel := []taint{}
|
||||
diags := nodePool.Taints.ElementsAs(ctx, &taintsModel, false)
|
||||
if diags.HasError() {
|
||||
return nil, core.DiagsToError(diags)
|
||||
return nil, nil, core.DiagsToError(diags)
|
||||
}
|
||||
|
||||
ts := []ske.Taint{}
|
||||
|
|
@ -824,8 +867,36 @@ func toNodepoolsPayload(ctx context.Context, m *Model) ([]ske.Nodepool, error) {
|
|||
cn := ske.CRI{
|
||||
Name: conversion.StringValueToPointer(nodePool.CRI),
|
||||
}
|
||||
|
||||
providedVersionMin := conversion.StringValueToPointer(nodePool.OSVersionMin)
|
||||
if !nodePool.OSVersion.IsNull() {
|
||||
// os_version field deprecation
|
||||
// this if clause should be removed once os_version field is completely removed
|
||||
// os_version field value is used as minimum os version
|
||||
providedVersionMin = conversion.StringValueToPointer(nodePool.OSVersion)
|
||||
}
|
||||
|
||||
name := conversion.StringValueToPointer(nodePool.Name)
|
||||
machineOSName := conversion.StringValueToPointer(nodePool.OSName)
|
||||
if name == nil {
|
||||
return nil, nil, fmt.Errorf("found nil node pool name for node_pool[%d]", i)
|
||||
}
|
||||
if machineOSName == nil {
|
||||
return nil, nil, fmt.Errorf("found nil machine name for node_pool %q", *name)
|
||||
}
|
||||
|
||||
currentMachineImage := currentMachineImages[*name]
|
||||
|
||||
machineVersion, hasDeprecatedVersion, err := latestMatchingMachineVersion(availableMachineVersions, providedVersionMin, *machineOSName, currentMachineImage)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("getting latest matching machine image version: %w", err)
|
||||
}
|
||||
if hasDeprecatedVersion && machineVersion != nil {
|
||||
deprecatedVersionsUsed = append(deprecatedVersionsUsed, *machineVersion)
|
||||
}
|
||||
|
||||
cnp := ske.Nodepool{
|
||||
Name: conversion.StringValueToPointer(nodePool.Name),
|
||||
Name: name,
|
||||
Minimum: conversion.Int64ValueToPointer(nodePool.Minimum),
|
||||
Maximum: conversion.Int64ValueToPointer(nodePool.Maximum),
|
||||
MaxSurge: conversion.Int64ValueToPointer(nodePool.MaxSurge),
|
||||
|
|
@ -833,8 +904,8 @@ func toNodepoolsPayload(ctx context.Context, m *Model) ([]ske.Nodepool, error) {
|
|||
Machine: &ske.Machine{
|
||||
Type: conversion.StringValueToPointer(nodePool.MachineType),
|
||||
Image: &ske.Image{
|
||||
Name: conversion.StringValueToPointer(nodePool.OSName),
|
||||
Version: conversion.StringValueToPointer(nodePool.OSVersion),
|
||||
Name: machineOSName,
|
||||
Version: machineVersion,
|
||||
},
|
||||
},
|
||||
Volume: &ske.Volume{
|
||||
|
|
@ -848,7 +919,140 @@ func toNodepoolsPayload(ctx context.Context, m *Model) ([]ske.Nodepool, error) {
|
|||
}
|
||||
cnps = append(cnps, cnp)
|
||||
}
|
||||
return cnps, nil
|
||||
return cnps, deprecatedVersionsUsed, nil
|
||||
}
|
||||
|
||||
// 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:
|
||||
//
|
||||
// 1. If the minimum version is not set:
|
||||
// - Return the current version if it exists.
|
||||
// - Otherwise, return the latest available version for the specified OS.
|
||||
//
|
||||
// 2. If the minimum version is set:
|
||||
// - If the minimum version is a downgrade, use the current version instead.
|
||||
// - If a patch is not specified for the minimum version, return the latest patch for that minor version.
|
||||
//
|
||||
// 3. For the selected version, check its state and return it, indicating if it is deprecated or not.
|
||||
func latestMatchingMachineVersion(availableImages []ske.MachineImage, versionMin *string, osName string, currentImage *ske.Image) (version *string, deprecated bool, err error) {
|
||||
deprecated = false
|
||||
|
||||
if availableImages == nil {
|
||||
return nil, false, fmt.Errorf("nil available machine versions")
|
||||
}
|
||||
|
||||
var availableMachineVersions []ske.MachineImageVersion
|
||||
for _, machine := range availableImages {
|
||||
if machine.Name != nil && *machine.Name == osName && machine.Versions != nil {
|
||||
availableMachineVersions = *machine.Versions
|
||||
}
|
||||
}
|
||||
|
||||
if len(availableImages) == 0 {
|
||||
return nil, false, fmt.Errorf("there are no available machine versions for the provided machine image name %s", osName)
|
||||
}
|
||||
|
||||
if versionMin == nil {
|
||||
// Different machine OSes have different versions.
|
||||
// If the current machine image is nil or the machine image name has been updated,
|
||||
// retrieve the latest supported version. Otherwise, use the current machine version.
|
||||
if currentImage == nil || currentImage.Name == nil || *currentImage.Name != osName {
|
||||
latestVersion, err := getLatestSupportedMachineVersion(availableMachineVersions)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("get latest supported machine image version: %w", err)
|
||||
}
|
||||
return latestVersion, false, nil
|
||||
}
|
||||
versionMin = currentImage.Version
|
||||
} else if currentImage != nil && currentImage.Name != nil && *currentImage.Name == osName {
|
||||
// If the os_version_min is set but is lower than the current version used in the cluster,
|
||||
// retain the current version to avoid downgrading.
|
||||
minimumVersion := "v" + *versionMin
|
||||
currentVersion := "v" + *currentImage.Version
|
||||
|
||||
if semver.Compare(minimumVersion, currentVersion) == -1 {
|
||||
versionMin = currentImage.Version
|
||||
}
|
||||
}
|
||||
|
||||
var fullVersion bool
|
||||
versionExp := validate.FullVersionRegex
|
||||
versionRegex := regexp.MustCompile(versionExp)
|
||||
if versionRegex.MatchString(*versionMin) {
|
||||
fullVersion = true
|
||||
}
|
||||
|
||||
providedVersionPrefixed := "v" + *versionMin
|
||||
|
||||
if !semver.IsValid(providedVersionPrefixed) {
|
||||
return nil, false, fmt.Errorf("provided version is invalid")
|
||||
}
|
||||
|
||||
var versionUsed *string
|
||||
var state *string
|
||||
var availableVersionsArray []string
|
||||
// Get the higher available version that matches the major, minor and patch version provided by the user
|
||||
for _, v := range availableMachineVersions {
|
||||
if v.State == nil || v.Version == nil {
|
||||
continue
|
||||
}
|
||||
availableVersionsArray = append(availableVersionsArray, *v.Version)
|
||||
vPreffixed := "v" + *v.Version
|
||||
|
||||
if fullVersion {
|
||||
// [MAJOR].[MINOR].[PATCH] version provided, match available version
|
||||
if semver.Compare(vPreffixed, providedVersionPrefixed) == 0 {
|
||||
versionUsed = v.Version
|
||||
state = v.State
|
||||
break
|
||||
}
|
||||
} else {
|
||||
// [MAJOR].[MINOR] version provided, get the latest patch version
|
||||
if semver.MajorMinor(vPreffixed) == semver.MajorMinor(providedVersionPrefixed) &&
|
||||
(semver.Compare(vPreffixed, providedVersionPrefixed) == 1 || semver.Compare(vPreffixed, providedVersionPrefixed) == 0) &&
|
||||
(v.State != nil && *v.State != VersionStatePreview) {
|
||||
versionUsed = v.Version
|
||||
state = v.State
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if versionUsed != nil {
|
||||
deprecated = strings.EqualFold(*state, VersionStateDeprecated)
|
||||
}
|
||||
|
||||
// Throwing error if we could not match the version with the available versions
|
||||
if versionUsed == nil {
|
||||
return nil, false, fmt.Errorf("provided version is not one of the available machine image versions, available versions are: %s", strings.Join(availableVersionsArray, ","))
|
||||
}
|
||||
|
||||
return versionUsed, deprecated, nil
|
||||
}
|
||||
|
||||
func getLatestSupportedMachineVersion(versions []ske.MachineImageVersion) (*string, error) {
|
||||
foundMachineVersion := false
|
||||
var latestVersion *string
|
||||
for i := range versions {
|
||||
version := versions[i]
|
||||
if *version.State != VersionStateSupported {
|
||||
continue
|
||||
}
|
||||
if latestVersion != nil {
|
||||
oldSemVer := fmt.Sprintf("v%s", *latestVersion)
|
||||
newSemVer := fmt.Sprintf("v%s", *version.Version)
|
||||
if semver.Compare(newSemVer, oldSemVer) != 1 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
foundMachineVersion = true
|
||||
latestVersion = version.Version
|
||||
}
|
||||
if !foundMachineVersion {
|
||||
return nil, fmt.Errorf("no supported machine version found")
|
||||
}
|
||||
return latestVersion, nil
|
||||
}
|
||||
|
||||
func toHibernationsPayload(ctx context.Context, m *Model) (*ske.Hibernation, error) {
|
||||
|
|
@ -1020,6 +1224,25 @@ func mapFields(ctx context.Context, cl *ske.Cluster, m *Model) error {
|
|||
}
|
||||
|
||||
func mapNodePools(ctx context.Context, cl *ske.Cluster, m *Model) error {
|
||||
modelNodePoolOSVersion := map[string]basetypes.StringValue{}
|
||||
modelNodePoolOSVersionMin := map[string]basetypes.StringValue{}
|
||||
|
||||
modelNodePools := []nodePool{}
|
||||
if !m.NodePools.IsNull() && !m.NodePools.IsUnknown() {
|
||||
diags := m.NodePools.ElementsAs(ctx, &modelNodePools, false)
|
||||
if diags.HasError() {
|
||||
return core.DiagsToError(diags)
|
||||
}
|
||||
}
|
||||
|
||||
for i := range modelNodePools {
|
||||
name := conversion.StringValueToPointer(modelNodePools[i].Name)
|
||||
if name != nil {
|
||||
modelNodePoolOSVersion[*name] = modelNodePools[i].OSVersion
|
||||
modelNodePoolOSVersionMin[*name] = modelNodePools[i].OSVersionMin
|
||||
}
|
||||
}
|
||||
|
||||
if cl.Nodepools == nil {
|
||||
m.NodePools = types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes})
|
||||
return nil
|
||||
|
|
@ -1031,7 +1254,8 @@ func mapNodePools(ctx context.Context, cl *ske.Cluster, m *Model) error {
|
|||
"name": types.StringPointerValue(nodePoolResp.Name),
|
||||
"machine_type": types.StringPointerValue(nodePoolResp.Machine.Type),
|
||||
"os_name": types.StringNull(),
|
||||
"os_version": 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),
|
||||
|
|
@ -1045,7 +1269,7 @@ func mapNodePools(ctx context.Context, cl *ske.Cluster, m *Model) error {
|
|||
|
||||
if nodePoolResp.Machine != nil && nodePoolResp.Machine.Image != nil {
|
||||
nodePool["os_name"] = types.StringPointerValue(nodePoolResp.Machine.Image.Name)
|
||||
nodePool["os_version"] = types.StringPointerValue(nodePoolResp.Machine.Image.Version)
|
||||
nodePool["os_version_used"] = types.StringPointerValue(nodePoolResp.Machine.Image.Version)
|
||||
}
|
||||
|
||||
if nodePoolResp.Volume != nil {
|
||||
|
|
@ -1388,11 +1612,10 @@ func toKubernetesPayload(m *Model, availableVersions []ske.KubernetesVersion, cu
|
|||
// kubernetes_version field deprecation
|
||||
// this if clause should be removed once kubernetes_version field is completely removed
|
||||
// kubernetes_version field value is used as minimum kubernetes version
|
||||
// and currenteKubernetesVersion is ignored
|
||||
providedVersionMin = conversion.StringValueToPointer(m.KubernetesVersion)
|
||||
}
|
||||
|
||||
versionUsed, hasDeprecatedVersion, err := latestMatchingVersion(availableVersions, providedVersionMin, currentKubernetesVersion)
|
||||
versionUsed, hasDeprecatedVersion, err := latestMatchingKubernetesVersion(availableVersions, providedVersionMin, currentKubernetesVersion)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("getting latest matching kubernetes version: %w", err)
|
||||
}
|
||||
|
|
@ -1404,7 +1627,7 @@ func toKubernetesPayload(m *Model, availableVersions []ske.KubernetesVersion, cu
|
|||
return k, hasDeprecatedVersion, nil
|
||||
}
|
||||
|
||||
func latestMatchingVersion(availableVersions []ske.KubernetesVersion, kubernetesVersionMin, currentKubernetesVersion *string) (version *string, deprecated bool, err error) {
|
||||
func latestMatchingKubernetesVersion(availableVersions []ske.KubernetesVersion, kubernetesVersionMin, currentKubernetesVersion *string) (version *string, deprecated bool, err error) {
|
||||
deprecated = false
|
||||
|
||||
if availableVersions == nil {
|
||||
|
|
@ -1466,9 +1689,10 @@ func latestMatchingVersion(availableVersions []ske.KubernetesVersion, kubernetes
|
|||
break
|
||||
}
|
||||
} else {
|
||||
// [MAJOR].[MINOR] version provided, get the latest patch version
|
||||
// [MAJOR].[MINOR] version provided, get the latest non-preview patch version
|
||||
if semver.MajorMinor(vPreffixed) == semver.MajorMinor(providedVersionPrefixed) &&
|
||||
(semver.Compare(vPreffixed, providedVersionPrefixed) == 1) || (semver.Compare(vPreffixed, providedVersionPrefixed) == 0) {
|
||||
(semver.Compare(vPreffixed, providedVersionPrefixed) == 1 || semver.Compare(vPreffixed, providedVersionPrefixed) == 0) &&
|
||||
(v.State != nil && *v.State != VersionStatePreview) {
|
||||
versionUsed = v.Version
|
||||
state = v.State
|
||||
}
|
||||
|
|
@ -1476,11 +1700,7 @@ func latestMatchingVersion(availableVersions []ske.KubernetesVersion, kubernetes
|
|||
}
|
||||
|
||||
if versionUsed != nil {
|
||||
if strings.EqualFold(*state, VersionStateDeprecated) {
|
||||
deprecated = true
|
||||
} else {
|
||||
deprecated = false
|
||||
}
|
||||
deprecated = strings.EqualFold(*state, VersionStateDeprecated)
|
||||
}
|
||||
|
||||
// Throwing error if we could not match the version with the available versions
|
||||
|
|
@ -1585,15 +1805,15 @@ func (r *clusterResource) Update(ctx context.Context, req resource.UpdateRequest
|
|||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
ctx = tflog.SetField(ctx, "name", clName)
|
||||
|
||||
availableVersions, err := r.loadAvailableVersions(ctx)
|
||||
availableKubernetesVersions, availableMachines, err := r.loadAvailableVersions(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating cluster", fmt.Sprintf("Loading available Kubernetes versions: %v", err))
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating cluster", fmt.Sprintf("Loading available Kubernetes and machine image versions: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
currentKubernetesVersion := getCurrentKubernetesVersion(ctx, r.client, &model)
|
||||
currentKubernetesVersion, currentMachineImages := getCurrentVersions(ctx, r.client, &model)
|
||||
|
||||
r.createOrUpdateCluster(ctx, &resp.Diagnostics, &model, availableVersions, currentKubernetesVersion)
|
||||
r.createOrUpdateCluster(ctx, &resp.Diagnostics, &model, availableKubernetesVersions, availableMachines, currentKubernetesVersion, currentMachineImages)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,7 +148,9 @@ func TestMapFields(t *testing.T) {
|
|||
"name": types.StringValue("node"),
|
||||
"machine_type": types.StringValue("B"),
|
||||
"os_name": types.StringValue("os"),
|
||||
"os_version": types.StringValue("os-ver"),
|
||||
"os_version": types.StringNull(),
|
||||
"os_version_min": types.StringNull(),
|
||||
"os_version_used": types.StringValue("os-ver"),
|
||||
"minimum": types.Int64Value(1),
|
||||
"maximum": types.Int64Value(5),
|
||||
"max_surge": types.Int64Value(3),
|
||||
|
|
@ -406,7 +408,7 @@ func TestMapFields(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestLatestMatchingVersion(t *testing.T) {
|
||||
func TestLatestMatchingKubernetesVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
availableVersions []ske.KubernetesVersion
|
||||
|
|
@ -494,6 +496,32 @@ func TestLatestMatchingVersion(t *testing.T) {
|
|||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"available_version_with_higher_preview_patch_not_selected",
|
||||
[]ske.KubernetesVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.1"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.2"),
|
||||
State: utils.Ptr(VersionStatePreview),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
nil,
|
||||
utils.Ptr("1.20.1"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"available_version_no_provided_patch_2",
|
||||
[]ske.KubernetesVersion{
|
||||
|
|
@ -530,24 +558,6 @@ func TestLatestMatchingVersion(t *testing.T) {
|
|||
true,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"deprecated_version_not_selected",
|
||||
[]ske.KubernetesVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateDeprecated),
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
nil,
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"preview_version",
|
||||
[]ske.KubernetesVersion{
|
||||
|
|
@ -560,7 +570,7 @@ func TestLatestMatchingVersion(t *testing.T) {
|
|||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
utils.Ptr("1.20.0"),
|
||||
nil,
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
|
|
@ -678,42 +688,6 @@ func TestLatestMatchingVersion(t *testing.T) {
|
|||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"deprecated_kubernetes_version_field",
|
||||
[]ske.KubernetesVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
nil,
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nil_provided_version_get_latest",
|
||||
[]ske.KubernetesVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"no_matching_available_versions",
|
||||
[]ske.KubernetesVersion{
|
||||
|
|
@ -777,7 +751,7 @@ func TestLatestMatchingVersion(t *testing.T) {
|
|||
false,
|
||||
},
|
||||
{
|
||||
"no_matching_available_versions_patch",
|
||||
"no_matching_available_versions_patch_current",
|
||||
[]ske.KubernetesVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.21.0"),
|
||||
|
|
@ -799,7 +773,7 @@ func TestLatestMatchingVersion(t *testing.T) {
|
|||
false,
|
||||
},
|
||||
{
|
||||
"no_matching_available_versions_patch_2",
|
||||
"no_matching_available_versions_patch_2_current",
|
||||
[]ske.KubernetesVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.21.2"),
|
||||
|
|
@ -859,7 +833,7 @@ func TestLatestMatchingVersion(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
versionUsed, hasDeprecatedVersion, err := latestMatchingVersion(tt.availableVersions, tt.kubernetesVersionMin, tt.currentKubernetesVersion)
|
||||
versionUsed, hasDeprecatedVersion, err := latestMatchingKubernetesVersion(tt.availableVersions, tt.kubernetesVersionMin, tt.currentKubernetesVersion)
|
||||
if !tt.isValid && err == nil {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
|
|
@ -877,6 +851,517 @@ func TestLatestMatchingVersion(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLatestMatchingMachineVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
availableVersions []ske.MachineImage
|
||||
machineVersionMin *string
|
||||
machineName string
|
||||
currentMachineImage *ske.Image
|
||||
expectedVersionUsed *string
|
||||
expectedHasDeprecatedVersion bool
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"available_version",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.1"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.2"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20.1"),
|
||||
"foo",
|
||||
nil,
|
||||
utils.Ptr("1.20.1"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"available_version_zero_patch",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.1"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.2"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20.0"),
|
||||
"foo",
|
||||
nil,
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"available_version_with_no_provided_patch",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.1"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.2"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
"foo",
|
||||
nil,
|
||||
utils.Ptr("1.20.2"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"available_version_with_higher_preview_patch_not_selected",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.1"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.2"),
|
||||
State: utils.Ptr(VersionStatePreview),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
"foo",
|
||||
nil,
|
||||
utils.Ptr("1.20.1"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"available_version_with_no_provided_patch_2",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
"foo",
|
||||
nil,
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"deprecated_version",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateDeprecated),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.19"),
|
||||
"foo",
|
||||
nil,
|
||||
utils.Ptr("1.19.0"),
|
||||
true,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"preview_version_selected",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStatePreview),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateDeprecated),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20.0"),
|
||||
"foo",
|
||||
nil,
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nil_provided_version_get_latest",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
"foo",
|
||||
nil,
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nil_provided_version_use_current",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
"foo",
|
||||
&ske.Image{
|
||||
Name: utils.Ptr("foo"),
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
},
|
||||
utils.Ptr("1.19.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nil_provided_version_os_image_update_get_latest",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
"foo",
|
||||
&ske.Image{
|
||||
Name: utils.Ptr("bar"),
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
},
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"update_lower_min_provided",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.19"),
|
||||
"foo",
|
||||
&ske.Image{
|
||||
Name: utils.Ptr("foo"),
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
},
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"update_lower_min_provided_deprecated_version",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.21.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateDeprecated),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.19"),
|
||||
"foo",
|
||||
&ske.Image{
|
||||
Name: utils.Ptr("foo"),
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
},
|
||||
utils.Ptr("1.20.0"),
|
||||
true,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"update_higher_min_provided",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
"foo",
|
||||
&ske.Image{
|
||||
Name: utils.Ptr("foo"),
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
},
|
||||
utils.Ptr("1.20.0"),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"no_matching_available_versions",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
{
|
||||
Version: utils.Ptr("1.19.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.21"),
|
||||
"foo",
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"no_available_versions",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
"foo",
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil_available_versions",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: nil,
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
"foo",
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil_name",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: nil,
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
"foo",
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"name_not_available",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("bar"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("1.20"),
|
||||
"foo",
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty_provided_version",
|
||||
[]ske.MachineImage{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Versions: &[]ske.MachineImageVersion{
|
||||
{
|
||||
Version: utils.Ptr("1.20.0"),
|
||||
State: utils.Ptr(VersionStateSupported),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr(""),
|
||||
"foo",
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
versionUsed, hasDeprecatedVersion, err := latestMatchingMachineVersion(tt.availableVersions, tt.machineVersionMin, tt.machineName, tt.currentMachineImage)
|
||||
if !tt.isValid && err == nil {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
if tt.isValid && err != nil {
|
||||
t.Fatalf("Should not have failed: %v", err)
|
||||
}
|
||||
if tt.isValid {
|
||||
if *versionUsed != *tt.expectedVersionUsed {
|
||||
t.Fatalf("Used version does not match: expecting %s, got %s", *tt.expectedVersionUsed, *versionUsed)
|
||||
}
|
||||
if tt.expectedHasDeprecatedVersion != hasDeprecatedVersion {
|
||||
t.Fatalf("hasDeprecatedVersion flag is wrong: expecting %t, got %t", tt.expectedHasDeprecatedVersion, hasDeprecatedVersion)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMaintenanceTimes(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
|
|
@ -1111,12 +1596,13 @@ func TestCheckAllowPrivilegedContainers(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetCurrentKubernetesVersion(t *testing.T) {
|
||||
func TestGetCurrentVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
mockedResp *ske.Cluster
|
||||
expected *string
|
||||
getClusterFails bool
|
||||
description string
|
||||
mockedResp *ske.Cluster
|
||||
expectedKubernetesVersion *string
|
||||
expectedMachineImages map[string]*ske.Image
|
||||
getClusterFails bool
|
||||
}{
|
||||
{
|
||||
"ok",
|
||||
|
|
@ -1124,25 +1610,46 @@ func TestGetCurrentKubernetesVersion(t *testing.T) {
|
|||
Kubernetes: &ske.Kubernetes{
|
||||
Version: utils.Ptr("v1.0.0"),
|
||||
},
|
||||
Nodepools: &[]ske.Nodepool{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Machine: &ske.Machine{
|
||||
Image: &ske.Image{
|
||||
Name: utils.Ptr("foo"),
|
||||
Version: utils.Ptr("v1.0.0"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: utils.Ptr("bar"),
|
||||
Machine: &ske.Machine{
|
||||
Image: &ske.Image{
|
||||
Name: utils.Ptr("bar"),
|
||||
Version: utils.Ptr("v2.0.0"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("v1.0.0"),
|
||||
map[string]*ske.Image{
|
||||
"foo": {
|
||||
Name: utils.Ptr("foo"),
|
||||
Version: utils.Ptr("v1.0.0"),
|
||||
},
|
||||
"bar": {
|
||||
Name: utils.Ptr("bar"),
|
||||
Version: utils.Ptr("v2.0.0"),
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"get fails",
|
||||
nil,
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nil version",
|
||||
&ske.Cluster{
|
||||
Kubernetes: &ske.Kubernetes{
|
||||
Version: nil,
|
||||
},
|
||||
},
|
||||
nil,
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nil kubernetes",
|
||||
|
|
@ -1150,12 +1657,121 @@ func TestGetCurrentKubernetesVersion(t *testing.T) {
|
|||
Kubernetes: nil,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil kubernetes version",
|
||||
&ske.Cluster{
|
||||
Kubernetes: &ske.Kubernetes{
|
||||
Version: nil,
|
||||
},
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil nodepools",
|
||||
&ske.Cluster{
|
||||
Kubernetes: &ske.Kubernetes{
|
||||
Version: utils.Ptr("v1.0.0"),
|
||||
},
|
||||
Nodepools: nil,
|
||||
},
|
||||
utils.Ptr("v1.0.0"),
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil nodepools machine",
|
||||
&ske.Cluster{
|
||||
Kubernetes: &ske.Kubernetes{
|
||||
Version: utils.Ptr("v1.0.0"),
|
||||
},
|
||||
Nodepools: &[]ske.Nodepool{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Machine: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("v1.0.0"),
|
||||
map[string]*ske.Image{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil nodepools machine image",
|
||||
&ske.Cluster{
|
||||
Kubernetes: &ske.Kubernetes{
|
||||
Version: utils.Ptr("v1.0.0"),
|
||||
},
|
||||
Nodepools: &[]ske.Nodepool{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Machine: &ske.Machine{
|
||||
Image: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("v1.0.0"),
|
||||
map[string]*ske.Image{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil nodepools machine image name",
|
||||
&ske.Cluster{
|
||||
Kubernetes: &ske.Kubernetes{
|
||||
Version: utils.Ptr("v1.0.0"),
|
||||
},
|
||||
Nodepools: &[]ske.Nodepool{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Machine: &ske.Machine{
|
||||
Image: &ske.Image{
|
||||
Name: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("v1.0.0"),
|
||||
map[string]*ske.Image{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil nodepools machine image version",
|
||||
&ske.Cluster{
|
||||
Kubernetes: &ske.Kubernetes{
|
||||
Version: utils.Ptr("v1.0.0"),
|
||||
},
|
||||
Nodepools: &[]ske.Nodepool{
|
||||
{
|
||||
Name: utils.Ptr("foo"),
|
||||
Machine: &ske.Machine{
|
||||
Image: &ske.Image{
|
||||
Name: utils.Ptr("foo"),
|
||||
Version: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.Ptr("v1.0.0"),
|
||||
map[string]*ske.Image{
|
||||
"foo": {
|
||||
Name: utils.Ptr("foo"),
|
||||
Version: nil,
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil response",
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
|
@ -1169,16 +1785,21 @@ func TestGetCurrentKubernetesVersion(t *testing.T) {
|
|||
ProjectId: types.StringValue("pid"),
|
||||
Name: types.StringValue("name"),
|
||||
}
|
||||
version := getCurrentKubernetesVersion(context.Background(), client, model)
|
||||
diff := cmp.Diff(version, tt.expected)
|
||||
kubernetesVersion, machineImageVersions := getCurrentVersions(context.Background(), client, model)
|
||||
diff := cmp.Diff(kubernetesVersion, tt.expectedKubernetesVersion)
|
||||
if diff != "" {
|
||||
t.Fatalf("Version does not match: %s", diff)
|
||||
t.Errorf("Kubernetes version does not match: %s", diff)
|
||||
}
|
||||
|
||||
diff = cmp.Diff(machineImageVersions, tt.expectedMachineImages)
|
||||
if diff != "" {
|
||||
t.Errorf("Machine images do not match: %s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLatestSupportedVersion(t *testing.T) {
|
||||
func TestGetLatestSupportedKubernetesVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
listKubernetesVersion []ske.KubernetesVersion
|
||||
|
|
@ -1246,3 +1867,72 @@ func TestGetLatestSupportedVersion(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLatestSupportedMachineVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
listMachineVersion []ske.MachineImageVersion
|
||||
isValid bool
|
||||
expectedVersion *string
|
||||
}{
|
||||
{
|
||||
description: "base",
|
||||
listMachineVersion: []ske.MachineImageVersion{
|
||||
{
|
||||
State: utils.Ptr("supported"),
|
||||
Version: utils.Ptr("1.2.3"),
|
||||
},
|
||||
{
|
||||
State: utils.Ptr("supported"),
|
||||
Version: utils.Ptr("3.2.1"),
|
||||
},
|
||||
{
|
||||
State: utils.Ptr("not-supported"),
|
||||
Version: utils.Ptr("4.4.4"),
|
||||
},
|
||||
},
|
||||
isValid: true,
|
||||
expectedVersion: utils.Ptr("3.2.1"),
|
||||
},
|
||||
{
|
||||
description: "no mchine versions 1",
|
||||
listMachineVersion: nil,
|
||||
isValid: false,
|
||||
},
|
||||
{
|
||||
description: "no machine versions 2",
|
||||
listMachineVersion: []ske.MachineImageVersion{},
|
||||
isValid: false,
|
||||
},
|
||||
{
|
||||
description: "no supported machine versions",
|
||||
listMachineVersion: []ske.MachineImageVersion{
|
||||
{
|
||||
State: utils.Ptr("not-supported"),
|
||||
Version: utils.Ptr("1.2.3"),
|
||||
},
|
||||
},
|
||||
isValid: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
version, err := getLatestSupportedMachineVersion(tt.listMachineVersion)
|
||||
|
||||
if tt.isValid && err != nil {
|
||||
t.Errorf("failed on valid input")
|
||||
}
|
||||
if !tt.isValid && err == nil {
|
||||
t.Errorf("did not fail on invalid input")
|
||||
}
|
||||
if !tt.isValid {
|
||||
return
|
||||
}
|
||||
diff := cmp.Diff(version, tt.expectedVersion)
|
||||
if diff != "" {
|
||||
t.Fatalf("Output is not as expected: %s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,10 @@ var clusterResource = map[string]string{
|
|||
"nodepool_name": "np-acc-test",
|
||||
"nodepool_name_min": "np-acc-min-test",
|
||||
"nodepool_machine_type": "b1.2",
|
||||
"nodepool_os_version": "3815.2.1",
|
||||
"nodepool_os_version_min": "3815.2.1",
|
||||
"nodepool_os_version_min": "3815.2",
|
||||
"nodepool_os_version_used": "3815.2.1",
|
||||
"nodepool_os_version_min_new": "3815.2.1",
|
||||
"nodepool_os_version_used_new": "3815.2.1",
|
||||
"nodepool_os_name": "flatcar",
|
||||
"nodepool_minimum": "2",
|
||||
"nodepool_maximum": "3",
|
||||
|
|
@ -59,7 +61,7 @@ var clusterResource = map[string]string{
|
|||
"kubeconfig_expiration": "3600",
|
||||
}
|
||||
|
||||
func getConfig(version string, maintenanceEnd *string) string {
|
||||
func getConfig(kubernetesVersion, nodePoolMachineOSVersion string, maintenanceEnd *string) string {
|
||||
maintenanceEndTF := clusterResource["maintenance_end"]
|
||||
if maintenanceEnd != nil {
|
||||
maintenanceEndTF = *maintenanceEnd
|
||||
|
|
@ -79,7 +81,7 @@ func getConfig(version string, maintenanceEnd *string) string {
|
|||
max_surge = "%s"
|
||||
max_unavailable = "%s"
|
||||
os_name = "%s"
|
||||
os_version = "%s"
|
||||
os_version_min = "%s"
|
||||
volume_size = "%s"
|
||||
volume_type = "%s"
|
||||
cri = "%s"
|
||||
|
|
@ -128,7 +130,6 @@ func getConfig(version string, maintenanceEnd *string) string {
|
|||
node_pools = [{
|
||||
name = "%s"
|
||||
machine_type = "%s"
|
||||
os_version = "%s"
|
||||
minimum = "%s"
|
||||
maximum = "%s"
|
||||
availability_zones = ["%s"]
|
||||
|
|
@ -144,7 +145,7 @@ func getConfig(version string, maintenanceEnd *string) string {
|
|||
testutil.SKEProviderConfig(),
|
||||
clusterResource["project_id"],
|
||||
clusterResource["name"],
|
||||
version,
|
||||
kubernetesVersion,
|
||||
clusterResource["nodepool_name"],
|
||||
clusterResource["nodepool_machine_type"],
|
||||
clusterResource["nodepool_minimum"],
|
||||
|
|
@ -152,7 +153,7 @@ func getConfig(version string, maintenanceEnd *string) string {
|
|||
clusterResource["nodepool_max_surge"],
|
||||
clusterResource["nodepool_max_unavailable"],
|
||||
clusterResource["nodepool_os_name"],
|
||||
clusterResource["nodepool_os_version"],
|
||||
nodePoolMachineOSVersion,
|
||||
clusterResource["nodepool_volume_size"],
|
||||
clusterResource["nodepool_volume_type"],
|
||||
clusterResource["nodepool_cri"],
|
||||
|
|
@ -182,7 +183,6 @@ func getConfig(version string, maintenanceEnd *string) string {
|
|||
clusterResource["name_min"],
|
||||
clusterResource["nodepool_name_min"],
|
||||
clusterResource["nodepool_machine_type"],
|
||||
clusterResource["nodepool_os_version_min"],
|
||||
clusterResource["nodepool_minimum"],
|
||||
clusterResource["nodepool_maximum"],
|
||||
clusterResource["nodepool_zone"],
|
||||
|
|
@ -201,7 +201,7 @@ func TestAccSKE(t *testing.T) {
|
|||
|
||||
// 1) Creation
|
||||
{
|
||||
Config: getConfig(clusterResource["kubernetes_version_min"], nil),
|
||||
Config: getConfig(clusterResource["kubernetes_version_min"], clusterResource["nodepool_os_version_min"], nil),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// cluster data
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "name", clusterResource["name"]),
|
||||
|
|
@ -211,7 +211,8 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.availability_zones.#", "1"),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.availability_zones.0", clusterResource["nodepool_zone"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_name", clusterResource["nodepool_os_name"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_version", clusterResource["nodepool_os_version"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_version_min", clusterResource["nodepool_os_version_min"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_version_used", clusterResource["nodepool_os_version_used"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.machine_type", clusterResource["nodepool_machine_type"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.minimum", clusterResource["nodepool_minimum"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.maximum", clusterResource["nodepool_maximum"]),
|
||||
|
|
@ -262,7 +263,7 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "node_pools.0.availability_zones.#", "1"),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "node_pools.0.availability_zones.0", clusterResource["nodepool_zone"]),
|
||||
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster_min", "node_pools.0.os_name"),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "node_pools.0.os_version", clusterResource["nodepool_os_version_min"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "node_pools.0.os_version_used", clusterResource["nodepool_os_version_used"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "node_pools.0.machine_type", clusterResource["nodepool_machine_type"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "node_pools.0.minimum", clusterResource["nodepool_minimum"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "node_pools.0.maximum", clusterResource["nodepool_maximum"]),
|
||||
|
|
@ -300,7 +301,7 @@ func TestAccSKE(t *testing.T) {
|
|||
}
|
||||
|
||||
`,
|
||||
getConfig(clusterResource["kubernetes_version_min"], nil),
|
||||
getConfig(clusterResource["kubernetes_version_min"], clusterResource["nodepool_os_version_min"], nil),
|
||||
clusterResource["project_id"],
|
||||
clusterResource["name"],
|
||||
clusterResource["project_id"],
|
||||
|
|
@ -319,7 +320,6 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.availability_zones.#", "1"),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.availability_zones.0", clusterResource["nodepool_zone"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.os_name", clusterResource["nodepool_os_name"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.os_version", clusterResource["nodepool_os_version"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.machine_type", clusterResource["nodepool_machine_type"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.minimum", clusterResource["nodepool_minimum"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.maximum", clusterResource["nodepool_maximum"]),
|
||||
|
|
@ -356,7 +356,6 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "node_pools.0.availability_zones.#", "1"),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "node_pools.0.availability_zones.0", clusterResource["nodepool_zone"]),
|
||||
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster_min", "node_pools.0.os_name"),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "node_pools.0.os_version", clusterResource["nodepool_os_version_min"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "node_pools.0.machine_type", clusterResource["nodepool_machine_type"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "node_pools.0.minimum", clusterResource["nodepool_minimum"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "node_pools.0.maximum", clusterResource["nodepool_maximum"]),
|
||||
|
|
@ -397,7 +396,7 @@ func TestAccSKE(t *testing.T) {
|
|||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
// The fields are not provided in the SKE API when disabled, although set actively.
|
||||
ImportStateVerifyIgnore: []string{"kubernetes_version_min", "kube_config", "extensions.argus.%", "extensions.argus.argus_instance_id", "extensions.argus.enabled", "extensions.acl.enabled", "extensions.acl.allowed_cidrs", "extensions.acl.allowed_cidrs.#", "extensions.acl.%"},
|
||||
ImportStateVerifyIgnore: []string{"kubernetes_version_min", "kube_config", "node_pools.0.os_version_min", "extensions.argus.%", "extensions.argus.argus_instance_id", "extensions.argus.enabled", "extensions.acl.enabled", "extensions.acl.allowed_cidrs", "extensions.acl.allowed_cidrs.#", "extensions.acl.%"},
|
||||
},
|
||||
// 4) Import minimal cluster
|
||||
{
|
||||
|
|
@ -419,11 +418,11 @@ func TestAccSKE(t *testing.T) {
|
|||
},
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
ImportStateVerifyIgnore: []string{"kubernetes_version_min", "kube_config"},
|
||||
ImportStateVerifyIgnore: []string{"kubernetes_version_min", "kube_config", "node_pools.0.os_version_min"},
|
||||
},
|
||||
// 5) Update kubernetes version and maximum
|
||||
// 5) Update kubernetes version, OS version and maintenance end
|
||||
{
|
||||
Config: getConfig(clusterResource["kubernetes_version_min_new"], utils.Ptr(clusterResource["maintenance_end_new"])),
|
||||
Config: getConfig(clusterResource["kubernetes_version_min_new"], clusterResource["os_version_min_new"], utils.Ptr(clusterResource["maintenance_end_new"])),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// cluster data
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "project_id", clusterResource["project_id"]),
|
||||
|
|
@ -434,7 +433,8 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.availability_zones.#", "1"),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.availability_zones.0", clusterResource["nodepool_zone"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_name", clusterResource["nodepool_os_name"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_version", clusterResource["nodepool_os_version"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_version_min", clusterResource["nodepool_os_version_min_new"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_version_used", clusterResource["nodepool_os_version_used_new"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.machine_type", clusterResource["nodepool_machine_type"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.minimum", clusterResource["nodepool_minimum"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.maximum", clusterResource["nodepool_maximum"]),
|
||||
|
|
@ -465,15 +465,17 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckNoResourceAttr("stackit_ske_cluster.cluster", "kube_config"), // when using the kubeconfig resource, the kubeconfig field becomes null
|
||||
),
|
||||
},
|
||||
// 6) Downgrade kubernetes version
|
||||
// 6) Downgrade kubernetes and nodepool machine OS version
|
||||
{
|
||||
Config: getConfig(clusterResource["kubernetes_version_min"], utils.Ptr(clusterResource["maintenance_end_new"])),
|
||||
Config: getConfig(clusterResource["kubernetes_version_min"], clusterResource["nodepool_os_version_min"], utils.Ptr(clusterResource["maintenance_end_new"])),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// cluster data
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "project_id", clusterResource["project_id"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "name", clusterResource["name"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "kubernetes_version_min", clusterResource["kubernetes_version_min"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "kubernetes_version_used", clusterResource["kubernetes_version_used"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "kubernetes_version_used", clusterResource["kubernetes_version_used_new"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_version_min", clusterResource["nodepool_os_version_min"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.os_version_used", clusterResource["nodepool_os_version_used_new"]),
|
||||
),
|
||||
},
|
||||
// Deletion is done by the framework implicitly
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue