Move SKE Enable/Disable to the Service Enablement API (#467)

This commit is contained in:
Diogo Ferrão 2024-07-16 13:42:01 +01:00 committed by GitHub
parent e3da2ebbb4
commit 02c4ad72b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 72 additions and 42 deletions

1
go.mod
View file

@ -28,6 +28,7 @@ require (
github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.9.0
github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0
github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0
github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0
github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0
github.com/teambition/rrule-go v1.8.2

2
go.sum
View file

@ -178,6 +178,8 @@ github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0 h1:pJBG455
github.com/stackitcloud/stackit-sdk-go/services/secretsmanager v0.8.0/go.mod h1:LX0Mcyr7/QP77zf7e05fHCJO38RMuTxr7nEDUDZ3oPQ=
github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0 h1:fYCBNvh4tqE+DXYDfbJEjC3n/I78zTZajdcPTPB/yig=
github.com/stackitcloud/stackit-sdk-go/services/serverbackup v0.1.0/go.mod h1:ZYI3wj/NnhhWi25ugbdcniwnY/7mF6zN582c5HPe00o=
github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0 h1:HAEFciLgeCY+kIcGcb+/zFUF3zt3z326v6JCen6fSjs=
github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v0.2.0/go.mod h1:z6XdA+ndaWzcPW/P0QrUIcTXJzKlajxgGZ5+EwXNS+c=
github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0 h1:4S3MwNmpMfjzBz9JtKbXvkos7j+7hGeFMf7XsjMLL/g=
github.com/stackitcloud/stackit-sdk-go/services/ske v0.17.0/go.mod h1:0fFs4R7kg+gU7FNAIzzFvlCZJz6gyZ8CFhbK3eSrAwQ=
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v0.2.0 h1:aIXxXx6u4+6C02MPb+hdItigeKeen7m+hEEG+Ej9sNs=

View file

@ -14,28 +14,29 @@ import (
const Separator = ","
type ProviderData struct {
RoundTripper http.RoundTripper
ServiceAccountEmail string
Region string
ArgusCustomEndpoint string
DnsCustomEndpoint string
IaaSCustomEndpoint string
LoadBalancerCustomEndpoint string
LogMeCustomEndpoint string
MariaDBCustomEndpoint string
MongoDBFlexCustomEndpoint string
ObjectStorageCustomEndpoint string
OpenSearchCustomEndpoint string
PostgresFlexCustomEndpoint string
PostgreSQLCustomEndpoint string
RabbitMQCustomEndpoint string
RedisCustomEndpoint string
ResourceManagerCustomEndpoint string
SecretsManagerCustomEndpoint string
SQLServerFlexCustomEndpoint string
ServerBackupCustomEndpoint string
SKECustomEndpoint string
EnableBetaResources bool
RoundTripper http.RoundTripper
ServiceAccountEmail string
Region string
ArgusCustomEndpoint string
DnsCustomEndpoint string
IaaSCustomEndpoint string
LoadBalancerCustomEndpoint string
LogMeCustomEndpoint string
MariaDBCustomEndpoint string
MongoDBFlexCustomEndpoint string
ObjectStorageCustomEndpoint string
OpenSearchCustomEndpoint string
PostgresFlexCustomEndpoint string
PostgreSQLCustomEndpoint string
RabbitMQCustomEndpoint string
RedisCustomEndpoint string
ResourceManagerCustomEndpoint string
SecretsManagerCustomEndpoint string
SQLServerFlexCustomEndpoint string
ServerBackupCustomEndpoint string
SKECustomEndpoint string
ServiceEnablementCustomEndpoint string
EnableBetaResources bool
}
// DiagsToError Converts TF diagnostics' errors into an error with a human-readable description.

View file

@ -29,11 +29,13 @@ import (
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/serviceenablement"
"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/conversion"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
"golang.org/x/mod/semver"
)
@ -214,7 +216,8 @@ func NewClusterResource() resource.Resource {
// clusterResource is the resource implementation.
type clusterResource struct {
client *ske.APIClient
skeClient *ske.APIClient
enablementClient *serviceenablement.APIClient
}
// Metadata returns the resource type name.
@ -235,27 +238,46 @@ func (r *clusterResource) Configure(ctx context.Context, req resource.ConfigureR
return
}
var apiClient *ske.APIClient
var skeClient *ske.APIClient
var enablementClient *serviceenablement.APIClient
var err error
if providerData.SKECustomEndpoint != "" {
apiClient, err = ske.NewAPIClient(
skeClient, err = ske.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
config.WithEndpoint(providerData.SKECustomEndpoint),
)
} else {
apiClient, err = ske.NewAPIClient(
skeClient, err = ske.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
config.WithRegion(providerData.Region),
)
}
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration", err))
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring SKE API client", fmt.Sprintf("Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration", err))
return
}
r.client = apiClient
tflog.Info(ctx, "SKE cluster client configured")
if providerData.ServiceEnablementCustomEndpoint != "" {
enablementClient, err = serviceenablement.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
config.WithEndpoint(providerData.ServiceEnablementCustomEndpoint),
)
} else {
enablementClient, err = serviceenablement.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
config.WithRegion(providerData.Region),
)
}
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring Service Enablement API client", fmt.Sprintf("Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration", err))
return
}
r.skeClient = skeClient
r.enablementClient = enablementClient
tflog.Info(ctx, "SKE cluster clients configured")
}
// Schema defines the schema for the resource.
@ -641,13 +663,13 @@ func (r *clusterResource) Create(ctx context.Context, req resource.CreateRequest
ctx = tflog.SetField(ctx, "name", clusterName)
// If SKE functionality is not enabled, enable it
_, err := r.client.EnableService(ctx, projectId).Execute()
err := r.enablementClient.EnableService(ctx, projectId, utils.SKEServiceId).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating cluster", fmt.Sprintf("Calling API to enable SKE: %v", err))
return
}
_, err = wait.EnableServiceWaitHandler(ctx, r.client, projectId).WaitWithContext(ctx)
_, err = wait.EnableServiceWaitHandler(ctx, r.skeClient, projectId).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating cluster", fmt.Sprintf("Wait for SKE enablement: %v", err))
return
@ -674,7 +696,7 @@ func (r *clusterResource) Create(ctx context.Context, req resource.CreateRequest
}
func (r *clusterResource) loadAvailableVersions(ctx context.Context) ([]ske.KubernetesVersion, []ske.MachineImage, error) {
c := r.client
c := r.skeClient
res, err := c.ListProviderOptions(ctx).Execute()
if err != nil {
return nil, nil, fmt.Errorf("calling API: %w", err)
@ -768,13 +790,13 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag
Network: network,
Nodepools: &nodePools,
}
_, err = r.client.CreateOrUpdateCluster(ctx, projectId, name).CreateOrUpdateClusterPayload(payload).Execute()
_, err = r.skeClient.CreateOrUpdateCluster(ctx, projectId, name).CreateOrUpdateClusterPayload(payload).Execute()
if err != nil {
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Calling API: %v", err))
return
}
waitResp, err := wait.CreateOrUpdateClusterWaitHandler(ctx, r.client, projectId, name).WaitWithContext(ctx)
waitResp, err := wait.CreateOrUpdateClusterWaitHandler(ctx, r.skeClient, projectId, name).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Cluster creation waiting: %v", err))
return
@ -798,7 +820,7 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag
}
func (r *clusterResource) getCredential(ctx context.Context, diags *diag.Diagnostics, model *Model) error {
c := r.client
c := r.skeClient
// for kubernetes with version >= 1.27, the deprecated endpoint will not work, so we set kubeconfig to nil
if semver.Compare(fmt.Sprintf("v%s", model.KubernetesVersion.ValueString()), "v1.27") >= 0 {
core.LogAndAddWarning(ctx, diags, "The kubelogin field is set to null", "Kubernetes version is 1.27 or higher, you must use the stackit_ske_kubeconfig resource instead.")
@ -1172,7 +1194,7 @@ func toMaintenancePayload(ctx context.Context, m *Model) (*ske.Maintenance, erro
var timeWindowStart *string
if !(maintenance.Start.IsNull() || maintenance.Start.IsUnknown()) {
// API expects RFC3339 datetime
timeWindowStart = utils.Ptr(
timeWindowStart = sdkUtils.Ptr(
fmt.Sprintf("0000-01-01T%s", maintenance.Start.ValueString()),
)
}
@ -1180,7 +1202,7 @@ func toMaintenancePayload(ctx context.Context, m *Model) (*ske.Maintenance, erro
var timeWindowEnd *string
if !(maintenance.End.IsNull() || maintenance.End.IsUnknown()) {
// API expects RFC3339 datetime
timeWindowEnd = utils.Ptr(
timeWindowEnd = sdkUtils.Ptr(
fmt.Sprintf("0000-01-01T%s", maintenance.End.ValueString()),
)
}
@ -1833,7 +1855,7 @@ func (r *clusterResource) Read(ctx context.Context, req resource.ReadRequest, re
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "name", name)
clResp, err := r.client.GetCluster(ctx, projectId, name).Execute()
clResp, err := r.skeClient.GetCluster(ctx, projectId, name).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 && oapiErr.StatusCode == http.StatusNotFound {
@ -1896,7 +1918,7 @@ func (r *clusterResource) Update(ctx context.Context, req resource.UpdateRequest
return
}
currentKubernetesVersion, currentMachineImages := getCurrentVersions(ctx, r.client, &model)
currentKubernetesVersion, currentMachineImages := getCurrentVersions(ctx, r.skeClient, &model)
r.createOrUpdateCluster(ctx, &resp.Diagnostics, &model, availableKubernetesVersions, availableMachines, currentKubernetesVersion, currentMachineImages)
if resp.Diagnostics.HasError() {
@ -1922,13 +1944,13 @@ func (r *clusterResource) Delete(ctx context.Context, req resource.DeleteRequest
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "name", name)
c := r.client
c := r.skeClient
_, err := c.DeleteCluster(ctx, projectId, name).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting cluster", fmt.Sprintf("Calling API: %v", err))
return
}
_, err = wait.DeleteClusterWaitHandler(ctx, r.client, projectId, name).WaitWithContext(ctx)
_, err = wait.DeleteClusterWaitHandler(ctx, r.skeClient, projectId, name).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting cluster", fmt.Sprintf("Cluster deletion waiting: %v", err))
return

View file

@ -10,6 +10,10 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
)
const (
SKEServiceId = "cloud.stackit.ske"
)
// ReconcileStringSlices reconciles two string lists by removing elements from the
// first list that are not in the second list and appending elements from the
// second list that are not in the first list.