Support automatic kubernetes updates for stackit_ske_cluster (#360)
* new field kubernets_version_min and deprecate kubernetes_version * Fix lint and tests * Update acc test * Deprecate datasource field, fix checkAllowPrivilegedContainers * Update acc test, datasource and descriptions * Update acc test * Improve descriptions, fix bug * Improve docs, fix acc test * Update docs * Update docs, fix acc test * Update stackit/internal/services/ske/cluster/resource.go Co-authored-by: Diogo Ferrão <diogo.ferrao@freiheit.com> * Fix links * Default ske auto-update to true --------- Co-authored-by: Diogo Ferrão <diogo.ferrao@freiheit.com>
This commit is contained in:
parent
94fbaf765c
commit
27b008a657
8 changed files with 529 additions and 160 deletions
|
|
@ -3,37 +3,33 @@ package ske_test
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-testing/terraform"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||
"github.com/stackitcloud/stackit-sdk-go/core/utils"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/ske"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/ske/wait"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil"
|
||||
)
|
||||
|
||||
var projectResource = map[string]string{
|
||||
"project_id": testutil.ProjectId,
|
||||
}
|
||||
|
||||
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": "1.25",
|
||||
"kubernetes_version_used": "1.25.16",
|
||||
"kubernetes_version_new": "1.26",
|
||||
"kubernetes_version_used_new": "1.26.14",
|
||||
"kubernetes_version_min": "1.26",
|
||||
"kubernetes_version_used": "1.26.15",
|
||||
"kubernetes_version_min_new": "1.27",
|
||||
"kubernetes_version_used_new": "1.27.13",
|
||||
"nodepool_name": "np-acc-test",
|
||||
"nodepool_name_min": "np-acc-min-test",
|
||||
"nodepool_machine_type": "b1.2",
|
||||
"nodepool_os_version": "3760.2.0",
|
||||
"nodepool_os_version_min": "3760.2.0",
|
||||
"nodepool_os_version": "3815.2.1",
|
||||
"nodepool_os_version_min": "3815.2.1",
|
||||
"nodepool_os_name": "flatcar",
|
||||
"nodepool_minimum": "2",
|
||||
"nodepool_maximum": "3",
|
||||
|
|
@ -71,14 +67,10 @@ func getConfig(version string, maintenanceEnd *string) string {
|
|||
return fmt.Sprintf(`
|
||||
%s
|
||||
|
||||
resource "stackit_ske_project" "project" {
|
||||
project_id = "%s"
|
||||
}
|
||||
|
||||
resource "stackit_ske_cluster" "cluster" {
|
||||
project_id = stackit_ske_project.project.project_id
|
||||
project_id = "%s"
|
||||
name = "%s"
|
||||
kubernetes_version = "%s"
|
||||
kubernetes_version_min = "%s"
|
||||
node_pools = [{
|
||||
name = "%s"
|
||||
machine_type = "%s"
|
||||
|
|
@ -125,15 +117,14 @@ func getConfig(version string, maintenanceEnd *string) string {
|
|||
}
|
||||
|
||||
resource "stackit_ske_kubeconfig" "kubeconfig" {
|
||||
project_id = stackit_ske_project.project.project_id
|
||||
project_id = stackit_ske_cluster.cluster.project_id
|
||||
cluster_name = stackit_ske_cluster.cluster.name
|
||||
expiration = "%s"
|
||||
}
|
||||
|
||||
resource "stackit_ske_cluster" "cluster_min" {
|
||||
project_id = stackit_ske_project.project.project_id
|
||||
project_id = "%s"
|
||||
name = "%s"
|
||||
kubernetes_version = "%s"
|
||||
node_pools = [{
|
||||
name = "%s"
|
||||
machine_type = "%s"
|
||||
|
|
@ -151,7 +142,7 @@ func getConfig(version string, maintenanceEnd *string) string {
|
|||
}
|
||||
`,
|
||||
testutil.SKEProviderConfig(),
|
||||
projectResource["project_id"],
|
||||
clusterResource["project_id"],
|
||||
clusterResource["name"],
|
||||
version,
|
||||
clusterResource["nodepool_name"],
|
||||
|
|
@ -187,8 +178,8 @@ func getConfig(version string, maintenanceEnd *string) string {
|
|||
clusterResource["kubeconfig_expiration"],
|
||||
|
||||
// Minimal
|
||||
clusterResource["project_id"],
|
||||
clusterResource["name_min"],
|
||||
clusterResource["kubernetes_version_new"],
|
||||
clusterResource["nodepool_name_min"],
|
||||
clusterResource["nodepool_machine_type"],
|
||||
clusterResource["nodepool_os_version_min"],
|
||||
|
|
@ -210,17 +201,11 @@ func TestAccSKE(t *testing.T) {
|
|||
|
||||
// 1) Creation
|
||||
{
|
||||
Config: getConfig(clusterResource["kubernetes_version"], nil),
|
||||
Config: getConfig(clusterResource["kubernetes_version_min"], nil),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// project data
|
||||
resource.TestCheckResourceAttr("stackit_ske_project.project", "project_id", projectResource["project_id"]),
|
||||
// cluster data
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_ske_project.project", "project_id",
|
||||
"stackit_ske_cluster.cluster", "project_id",
|
||||
),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "name", clusterResource["name"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "kubernetes_version", clusterResource["kubernetes_version"]),
|
||||
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", "node_pools.0.name", clusterResource["nodepool_name"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.availability_zones.#", "1"),
|
||||
|
|
@ -270,13 +255,8 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("stackit_ske_kubeconfig.kubeconfig", "expires_at"),
|
||||
|
||||
// Minimal cluster
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_ske_project.project", "project_id",
|
||||
"stackit_ske_cluster.cluster_min", "project_id",
|
||||
),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "name", clusterResource["name_min"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "kubernetes_version", clusterResource["kubernetes_version_new"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "kubernetes_version_used", clusterResource["kubernetes_version_used_new"]),
|
||||
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster_min", "kubernetes_version_used"),
|
||||
resource.TestCheckNoResourceAttr("stackit_ske_cluster.cluster_min", "allow_privileged_containers"),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "node_pools.0.name", clusterResource["nodepool_name_min"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster_min", "node_pools.0.availability_zones.#", "1"),
|
||||
|
|
@ -299,7 +279,7 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster_min", "maintenance.enable_machine_image_version_updates"),
|
||||
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster_min", "maintenance.start"),
|
||||
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster_min", "maintenance.end"),
|
||||
resource.TestCheckResourceAttrSet("stackit_ske_cluster.cluster_min", "kube_config"),
|
||||
resource.TestCheckNoResourceAttr("stackit_ske_cluster.cluster_min", "kube_config"),
|
||||
),
|
||||
},
|
||||
// 2) Data source
|
||||
|
|
@ -307,11 +287,6 @@ func TestAccSKE(t *testing.T) {
|
|||
Config: fmt.Sprintf(`
|
||||
%s
|
||||
|
||||
data "stackit_ske_project" "project" {
|
||||
project_id = "%s"
|
||||
depends_on = [stackit_ske_project.project]
|
||||
}
|
||||
|
||||
data "stackit_ske_cluster" "cluster" {
|
||||
project_id = "%s"
|
||||
name = "%s"
|
||||
|
|
@ -325,17 +300,13 @@ func TestAccSKE(t *testing.T) {
|
|||
}
|
||||
|
||||
`,
|
||||
getConfig(clusterResource["kubernetes_version"], nil),
|
||||
projectResource["project_id"],
|
||||
getConfig(clusterResource["kubernetes_version_min"], nil),
|
||||
clusterResource["project_id"],
|
||||
clusterResource["name"],
|
||||
clusterResource["project_id"],
|
||||
clusterResource["name_min"],
|
||||
),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// project data
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_project.project", "id", projectResource["project_id"]),
|
||||
|
||||
// cluster data
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "id", fmt.Sprintf("%s,%s",
|
||||
clusterResource["project_id"],
|
||||
|
|
@ -343,7 +314,6 @@ func TestAccSKE(t *testing.T) {
|
|||
)),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "project_id", clusterResource["project_id"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "name", clusterResource["name"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "kubernetes_version", clusterResource["kubernetes_version"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "kubernetes_version_used", clusterResource["kubernetes_version_used"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.name", clusterResource["nodepool_name"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster", "node_pools.0.availability_zones.#", "1"),
|
||||
|
|
@ -380,8 +350,7 @@ func TestAccSKE(t *testing.T) {
|
|||
|
||||
// Minimal cluster
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "name", clusterResource["name_min"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "kubernetes_version", clusterResource["kubernetes_version_new"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "kubernetes_version_used", clusterResource["kubernetes_version_used_new"]),
|
||||
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster_min", "kubernetes_version_used"),
|
||||
resource.TestCheckNoResourceAttr("data.stackit_ske_cluster.cluster_min", "allow_privileged_containers"),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "node_pools.0.name", clusterResource["nodepool_name_min"]),
|
||||
resource.TestCheckResourceAttr("data.stackit_ske_cluster.cluster_min", "node_pools.0.availability_zones.#", "1"),
|
||||
|
|
@ -404,23 +373,10 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster_min", "maintenance.enable_machine_image_version_updates"),
|
||||
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster_min", "maintenance.start"),
|
||||
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster_min", "maintenance.end"),
|
||||
resource.TestCheckResourceAttrSet("data.stackit_ske_cluster.cluster_min", "kube_config"),
|
||||
resource.TestCheckNoResourceAttr("data.stackit_ske_cluster.cluster_min", "kube_config"),
|
||||
),
|
||||
},
|
||||
// 3) Import project
|
||||
{
|
||||
ResourceName: "stackit_ske_project.project",
|
||||
ImportStateIdFunc: func(s *terraform.State) (string, error) {
|
||||
_, ok := s.RootModule().Resources["stackit_ske_project.project"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("couldn't find resource stackit_ske_project.project")
|
||||
}
|
||||
return testutil.ProjectId, nil
|
||||
},
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
// 4) Import cluster
|
||||
// 3) Import cluster
|
||||
{
|
||||
ResourceName: "stackit_ske_cluster.cluster",
|
||||
ImportStateIdFunc: func(s *terraform.State) (string, error) {
|
||||
|
|
@ -441,9 +397,9 @@ 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{"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", "extensions.argus.%", "extensions.argus.argus_instance_id", "extensions.argus.enabled", "extensions.acl.enabled", "extensions.acl.allowed_cidrs", "extensions.acl.allowed_cidrs.#", "extensions.acl.%"},
|
||||
},
|
||||
// 5) Import minimal cluster
|
||||
// 4) Import minimal cluster
|
||||
{
|
||||
ResourceName: "stackit_ske_cluster.cluster_min",
|
||||
ImportStateIdFunc: func(s *terraform.State) (string, error) {
|
||||
|
|
@ -463,16 +419,16 @@ func TestAccSKE(t *testing.T) {
|
|||
},
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
ImportStateVerifyIgnore: []string{"kube_config"},
|
||||
ImportStateVerifyIgnore: []string{"kubernetes_version_min", "kube_config"},
|
||||
},
|
||||
// 6) Update kubernetes version and maximum
|
||||
// 5) Update kubernetes version and maximum
|
||||
{
|
||||
Config: getConfig(clusterResource["kubernetes_version_new"], utils.Ptr(clusterResource["maintenance_end_new"])),
|
||||
Config: getConfig(clusterResource["kubernetes_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"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "name", clusterResource["name"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "kubernetes_version", clusterResource["kubernetes_version_new"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "kubernetes_version_min", clusterResource["kubernetes_version_min_new"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "kubernetes_version_used", clusterResource["kubernetes_version_used_new"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.name", clusterResource["nodepool_name"]),
|
||||
resource.TestCheckResourceAttr("stackit_ske_cluster.cluster", "node_pools.0.availability_zones.#", "1"),
|
||||
|
|
@ -509,14 +465,14 @@ func TestAccSKE(t *testing.T) {
|
|||
resource.TestCheckNoResourceAttr("stackit_ske_cluster.cluster", "kube_config"), // when using the kubeconfig resource, the kubeconfig field becomes null
|
||||
),
|
||||
},
|
||||
// 7) Downgrade kubernetes version
|
||||
// 6) Downgrade kubernetes version
|
||||
{
|
||||
Config: getConfig(clusterResource["kubernetes_version"], utils.Ptr(clusterResource["maintenance_end_new"])),
|
||||
Config: getConfig(clusterResource["kubernetes_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", clusterResource["kubernetes_version"]),
|
||||
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"]),
|
||||
),
|
||||
},
|
||||
|
|
@ -530,9 +486,7 @@ func testAccCheckSKEDestroy(s *terraform.State) error {
|
|||
var client *ske.APIClient
|
||||
var err error
|
||||
if testutil.SKECustomEndpoint == "" {
|
||||
client, err = ske.NewAPIClient(
|
||||
config.WithRegion("eu01"),
|
||||
)
|
||||
client, err = ske.NewAPIClient()
|
||||
} else {
|
||||
client, err = ske.NewAPIClient(
|
||||
config.WithEndpoint(testutil.SKECustomEndpoint),
|
||||
|
|
@ -542,34 +496,35 @@ func testAccCheckSKEDestroy(s *terraform.State) error {
|
|||
return fmt.Errorf("creating client: %w", err)
|
||||
}
|
||||
|
||||
projectsToDestroy := []string{}
|
||||
clustersToDestroy := []string{}
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "stackit_ske_project" {
|
||||
if rs.Type != "stackit_ske_cluster" {
|
||||
continue
|
||||
}
|
||||
projectsToDestroy = append(projectsToDestroy, rs.Primary.ID)
|
||||
// cluster terraform ID: = "[project_id],[cluster_name]"
|
||||
clusterName := strings.Split(rs.Primary.ID, core.Separator)[1]
|
||||
clustersToDestroy = append(clustersToDestroy, clusterName)
|
||||
}
|
||||
for _, projectId := range projectsToDestroy {
|
||||
_, err := client.GetServiceStatus(ctx, projectId).Execute()
|
||||
if err != nil {
|
||||
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
|
||||
if !ok {
|
||||
return fmt.Errorf("could not convert error to GenericOpenApiError in acc test destruction, %w", err)
|
||||
}
|
||||
if oapiErr.StatusCode == http.StatusNotFound || oapiErr.StatusCode == http.StatusForbidden {
|
||||
// Already gone
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("getting project: %w", err)
|
||||
}
|
||||
|
||||
_, err = client.DisableServiceExecute(ctx, projectId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("destroying project %s during CheckDestroy: %w", projectId, err)
|
||||
clustersResp, err := client.ListClusters(ctx, testutil.ProjectId).Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting clustersResp: %w", err)
|
||||
}
|
||||
|
||||
items := *clustersResp.Items
|
||||
for i := range items {
|
||||
if items[i].Name == nil {
|
||||
continue
|
||||
}
|
||||
_, err = wait.DisableServiceWaitHandler(ctx, client, projectId).WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("destroying project %s during CheckDestroy: waiting for deletion %w", projectId, err)
|
||||
if utils.Contains(clustersToDestroy, *items[i].Name) {
|
||||
_, err := client.DeleteClusterExecute(ctx, testutil.ProjectId, *items[i].Name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("destroying cluster %s during CheckDestroy: %w", *items[i].Name, err)
|
||||
}
|
||||
_, err = wait.DeleteClusterWaitHandler(ctx, client, testutil.ProjectId, *items[i].Name).WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("destroying cluster %s during CheckDestroy: waiting for deletion %w", *items[i].Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue