Deprecate kubeconfig field and add stackit_ske_kubeconfig resource (#256)
* Implement kubeconfig resource * Update acc test, skip get credentials * Update acc test * Add warning on Create * Add option to refresh * Fix lint * Add comment, generate docs * Update stackit/internal/services/ske/cluster/resource.go Co-authored-by: João Palet <joao.palet@outlook.com> * Update stackit/internal/services/ske/kubeconfig/resource.go Co-authored-by: João Palet <joao.palet@outlook.com> * Changes after review * Fix schema * Gen docs * Rename * Credentials handling in datasource, update acc test * Fix datasource * Update descriptions --------- Co-authored-by: João Palet <joao.palet@outlook.com>
This commit is contained in:
parent
91b2c42a19
commit
bde1fc55e4
9 changed files with 618 additions and 39 deletions
|
|
@ -3,6 +3,7 @@ package ske
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
|
|
@ -11,9 +12,11 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"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/services/ske"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
|
|
@ -269,9 +272,10 @@ func (r *clusterDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
|
|||
},
|
||||
},
|
||||
"kube_config": schema.StringAttribute{
|
||||
Description: "Kube config file used for connecting to the cluster",
|
||||
Sensitive: true,
|
||||
Computed: true,
|
||||
Description: "Kube config file used for connecting to the cluster. This field will be empty for clusters with Kubernetes v1.27+, or if you have obtained the kubeconfig or performed credentials rotation using the new process, either through the Portal or the SKE API. Use the stackit_ske_kubeconfig resource instead. For more information, see How to rotate SKE credentials (https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html).",
|
||||
Sensitive: true,
|
||||
Computed: true,
|
||||
DeprecationMessage: "This field will be empty for clusters with Kubernetes v1.27+, or if you have obtained the kubeconfig or performed credentials rotation using the new process, either through the Portal or the SKE API. Use the stackit_ske_kubeconfig resource instead. For more information, see How to rotate SKE credentials (https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html).",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -301,7 +305,12 @@ func (r *clusterDataSource) Read(ctx context.Context, req datasource.ReadRequest
|
|||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading cluster", fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
}
|
||||
r.getCredential(ctx, &diags, &state)
|
||||
// Handle credential
|
||||
err = r.getCredential(ctx, &resp.Diagnostics, &state)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading cluster", fmt.Sprintf("Getting credential: %v", err))
|
||||
return
|
||||
}
|
||||
// Set refreshed state
|
||||
diags = resp.State.Set(ctx, state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
|
@ -311,12 +320,29 @@ func (r *clusterDataSource) Read(ctx context.Context, req datasource.ReadRequest
|
|||
tflog.Info(ctx, "SKE cluster read")
|
||||
}
|
||||
|
||||
func (r *clusterDataSource) getCredential(ctx context.Context, diags *diag.Diagnostics, model *Model) {
|
||||
func (r *clusterDataSource) getCredential(ctx context.Context, diags *diag.Diagnostics, model *Model) error {
|
||||
c := r.client
|
||||
// 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.")
|
||||
model.KubeConfig = types.StringPointerValue(nil)
|
||||
return nil
|
||||
}
|
||||
res, err := c.GetCredentials(ctx, model.ProjectId.ValueString(), model.Name.ValueString()).Execute()
|
||||
if err != nil {
|
||||
diags.AddError("failed fetching cluster credentials for data source", err.Error())
|
||||
return
|
||||
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("fetch cluster credentials: could not convert error to oapierror.GenericOpenAPIError")
|
||||
}
|
||||
if oapiErr.StatusCode == http.StatusBadRequest {
|
||||
// deprecated endpoint will return 400 if the new endpoints have been used
|
||||
// if that's the case, we set the field to null
|
||||
core.LogAndAddWarning(ctx, diags, "The kubelogin field is set to null", "The call to GetCredentials failed, which means the new credentials rotation flow might already been triggered for this cluster. If you are already using the stackit_ske_kubeconfig resource you can ignore this warning. If not, you must start using it.")
|
||||
model.KubeConfig = types.StringPointerValue(nil)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("fetching cluster credentials: %w", err)
|
||||
}
|
||||
model.KubeConfig = types.StringPointerValue(res.Kubeconfig)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package ske
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -27,6 +28,7 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"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"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/ske"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/ske/wait"
|
||||
|
|
@ -497,9 +499,10 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||
},
|
||||
},
|
||||
"kube_config": schema.StringAttribute{
|
||||
Description: "Kube config file used for connecting to the cluster",
|
||||
Sensitive: true,
|
||||
Computed: true,
|
||||
Description: "Static token kubeconfig used for connecting to the cluster. This field will be empty for clusters with Kubernetes v1.27+, or if you have obtained the kubeconfig or performed credentials rotation using the new process, either through the Portal or the SKE API. Use the stackit_ske_kubeconfig resource instead. For more information, see How to rotate SKE credentials (https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html).",
|
||||
Sensitive: true,
|
||||
Computed: true,
|
||||
DeprecationMessage: "This field will be empty for clusters with Kubernetes v1.27+, or if you have obtained the kubeconfig or performed credentials rotation using the new process, either through the Portal or the SKE API. Use the stackit_ske_kubeconfig resource instead. For more information, see How to rotate SKE credentials (https://docs.stackit.cloud/stackit/en/how-to-rotate-ske-credentials-200016334.html).",
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
|
|
@ -648,17 +651,34 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag
|
|||
}
|
||||
|
||||
// Handle credential
|
||||
err = r.getCredential(ctx, model)
|
||||
err = r.getCredential(ctx, diags, model)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Getting credential: %v", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (r *clusterResource) getCredential(ctx context.Context, model *Model) error {
|
||||
func (r *clusterResource) getCredential(ctx context.Context, diags *diag.Diagnostics, model *Model) error {
|
||||
c := r.client
|
||||
// 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.")
|
||||
model.KubeConfig = types.StringPointerValue(nil)
|
||||
return nil
|
||||
}
|
||||
res, err := c.GetCredentials(ctx, model.ProjectId.ValueString(), model.Name.ValueString()).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("fetch cluster credentials: could not convert error to oapierror.GenericOpenAPIError")
|
||||
}
|
||||
if oapiErr.StatusCode == http.StatusBadRequest {
|
||||
// deprecated endpoint will return 400 if the new endpoints have been used
|
||||
// if that's the case, we set the field to null
|
||||
core.LogAndAddWarning(ctx, diags, "The kubelogin field is set to null", "The call to GetCredentials failed, which means the new credentials rotation flow might already been triggered for this cluster. If you are already using the stackit_ske_kubeconfig resource you can ignore this warning. If not, you must start using it.")
|
||||
model.KubeConfig = types.StringPointerValue(nil)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("fetching cluster credentials: %w", err)
|
||||
}
|
||||
model.KubeConfig = types.StringPointerValue(res.Kubeconfig)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue