Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/data-sources/ske_cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ data "stackit_ske_cluster" "example" {
### Read-Only

- `access` (Attributes) Configure access to the cluster (see [below for nested schema](#nestedatt--access))
- `audit` (Attributes) Cluster audit log forwarding configuration. This feature is in private preview. Enabling audit logging is only possible for enabled accounts. (see [below for nested schema](#nestedatt--audit))
- `egress_address_ranges` (List of String) The outgoing network ranges (in CIDR notation) of traffic originating from workload on the cluster.
- `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))
Expand Down Expand Up @@ -63,6 +64,14 @@ Read-Only:



<a id="nestedatt--audit"></a>
### Nested Schema for `audit`

Read-Only:

- `enabled` (Boolean) Enable cluster audit log forwarding to a Telemetry Router.


<a id="nestedatt--extensions"></a>
### Nested Schema for `extensions`

Expand Down
14 changes: 14 additions & 0 deletions docs/resources/ske_cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ resource "stackit_ske_cluster" "example" {
access_scope = "PUBLIC"
}
}
# Cluster audit log forwarding to a Telemetry Router.
# Private preview: only configurable for enabled accounts.
audit = {
enabled = true
}
}
```

Expand All @@ -60,6 +65,7 @@ To keep your Terraform plans clean and readable, always append new node pools to
### Optional

- `access` (Attributes) Configure access to the cluster (see [below for nested schema](#nestedatt--access))
- `audit` (Attributes) Cluster audit log forwarding configuration. This feature is in private preview. Enabling audit logging is only possible for enabled accounts. (see [below for nested schema](#nestedatt--audit))
- `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_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 [General information for Kubernetes & OS updates](https://docs.stackit.cloud/products/runtime/kubernetes-engine/basics/version-updates/). To get the current kubernetes version being used for your cluster, use the read-only `kubernetes_version_used` field.
Expand Down Expand Up @@ -135,6 +141,14 @@ Optional:



<a id="nestedatt--audit"></a>
### Nested Schema for `audit`

Required:

- `enabled` (Boolean) Enable cluster audit log forwarding to a Telemetry Router.


<a id="nestedatt--extensions"></a>
### Nested Schema for `extensions`

Expand Down
5 changes: 5 additions & 0 deletions examples/resources/stackit_ske_cluster/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@ resource "stackit_ske_cluster" "example" {
access_scope = "PUBLIC"
}
}
# Cluster audit log forwarding to a Telemetry Router.
# Private preview: only configurable for enabled accounts.
audit = {
enabled = true
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ require (
github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.20.0
github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.7.0
github.com/stackitcloud/stackit-sdk-go/services/sfs v0.11.0
github.com/stackitcloud/stackit-sdk-go/services/ske v1.18.0
github.com/stackitcloud/stackit-sdk-go/services/ske v1.19.0
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.16.0
github.com/stackitcloud/stackit-sdk-go/services/telemetrylink v0.2.0
github.com/stackitcloud/stackit-sdk-go/services/telemetryrouter v0.3.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -732,8 +732,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.7.0 h1:TNZH
github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.7.0/go.mod h1:fXq3TmVLb4JMSve989NFFViMFoYa83s7M3hJWgN6mdQ=
github.com/stackitcloud/stackit-sdk-go/services/sfs v0.11.0 h1:YhQ2GF+AyHVUps1iEjLj7z6OlzBzMGyD5nwHaZ0pXus=
github.com/stackitcloud/stackit-sdk-go/services/sfs v0.11.0/go.mod h1:jMlBoXqrPNX5nXbo6oT7exalqilw1jiLPoIp4Cn0CdI=
github.com/stackitcloud/stackit-sdk-go/services/ske v1.18.0 h1:6Umom7V12bVa7D3dnMJAKj/GWg7wqR9FpqmZ8TjsO1Q=
github.com/stackitcloud/stackit-sdk-go/services/ske v1.18.0/go.mod h1:TbqmZhLMofmfl+HhVl6oHYcI3zvXTm1vRjN3A/fOkM4=
github.com/stackitcloud/stackit-sdk-go/services/ske v1.19.0 h1:/SNc1zedje1HNhMCWf+IRx2eKpFXeGdmCRCIZ4PCrhs=
github.com/stackitcloud/stackit-sdk-go/services/ske v1.19.0/go.mod h1:TbqmZhLMofmfl+HhVl6oHYcI3zvXTm1vRjN3A/fOkM4=
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.16.0 h1:A6zN5JUz5DOTigTxAyAC+4p5VpJzaYDftx2yIH0mgn8=
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.16.0/go.mod h1:AiUoMAqQcOlMgDtkVJlqI7P/VGD5xjN3dYjERGnwN/M=
github.com/stackitcloud/stackit-sdk-go/services/telemetrylink v0.2.0 h1:U1mQoCk0TXc8NsSc/Sl9PKMdEyJpWNU2zLnsqmx6wEc=
Expand Down
10 changes: 10 additions & 0 deletions stackit/internal/services/ske/cluster/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@ func (r *clusterDataSource) Schema(_ context.Context, _ datasource.SchemaRequest
},
},
},
"audit": schema.SingleNestedAttribute{
Description: descriptions["audit"],
Computed: true,
Attributes: map[string]schema.Attribute{
"enabled": schema.BoolAttribute{
Description: descriptions["audit_enabled"],
Computed: true,
},
},
},
"region": schema.StringAttribute{
// the region cannot be found, so it has to be passed
Optional: true,
Expand Down
93 changes: 93 additions & 0 deletions stackit/internal/services/ske/cluster/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ type Model struct {
Network types.Object `tfsdk:"network"`
Hibernations types.List `tfsdk:"hibernations"`
Extensions types.Object `tfsdk:"extensions"`
Audit types.Object `tfsdk:"audit"`
EgressAddressRanges types.List `tfsdk:"egress_address_ranges"`
PodAddressRanges types.List `tfsdk:"pod_address_ranges"`
ServiceAccountIssuer types.String `tfsdk:"service_account_issuer"`
Expand Down Expand Up @@ -270,6 +271,16 @@ var dnsTypes = map[string]attr.Type{
"zones": basetypes.ListType{ElemType: types.StringType},
}

// Struct corresponding to Model.Audit
type audit struct {
Enabled types.Bool `tfsdk:"enabled"`
}

// Types corresponding to audit
var auditTypes = map[string]attr.Type{
"enabled": basetypes.BoolType{},
}

// NewClusterResource is a helper function to simplify the provider implementation.
func NewClusterResource() resource.Resource {
return &clusterResource{}
Expand Down Expand Up @@ -412,6 +423,8 @@ var descriptions = map[string]string{
"access_idp": "Configure IDP",
"access_idp_enabled": "Enable IDP integration for the cluster.",
"access_idp_type": "The IDP type. Possible values: 'stackit'.",
"audit": "Cluster audit log forwarding configuration. This feature is in private preview. Enabling audit logging is only possible for enabled accounts.",
"audit_enabled": "Enable cluster audit log forwarding to a Telemetry Router.",
}

// Schema defines the schema for the resource.
Expand Down Expand Up @@ -817,6 +830,19 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
},
},
},
"audit": schema.SingleNestedAttribute{
Description: descriptions["audit"],
Optional: true,
PlanModifiers: []planmodifier.Object{
objectplanmodifier.UseStateForUnknown(),
},
Attributes: map[string]schema.Attribute{
"enabled": schema.BoolAttribute{
Description: descriptions["audit_enabled"],
Required: true,
},
},
},
"region": schema.StringAttribute{
Optional: true,
// must be computed to allow for storing the override value from the provider
Expand Down Expand Up @@ -1055,13 +1081,19 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Creating extension API payload: %v", err))
return
}
audit, err := toAuditPayload(ctx, model)
if err != nil {
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Creating audit API payload: %v", err))
return
}
access, err := toAccessPayload(ctx, model)
if err != nil {
core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Creating access API payload: %v", err))
return
}

payload := ske.CreateOrUpdateClusterPayload{
Audit: audit,
Extensions: extensions,
Hibernation: hibernations,
Kubernetes: *kubernetes,
Expand Down Expand Up @@ -1391,6 +1423,22 @@ func toHibernationsPayload(ctx context.Context, m *Model) (*ske.Hibernation, err
}, nil
}

func toAuditPayload(ctx context.Context, m *Model) (*ske.Audit, error) {
if utils.IsUndefined(m.Audit) {
return nil, nil
}

auditModel := audit{}
diags := m.Audit.As(ctx, &auditModel, basetypes.ObjectAsOptions{})
if diags.HasError() {
return nil, fmt.Errorf("converting audit object: %v", diags.Errors())
}

return &ske.Audit{
Enabled: auditModel.Enabled.ValueBool(),
}, nil
}

func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error) {
if m.Extensions.IsNull() || m.Extensions.IsUnknown() {
return nil, nil
Expand Down Expand Up @@ -1635,6 +1683,10 @@ func mapFields(ctx context.Context, cl *ske.Cluster, m *Model, region string) er
if err != nil {
return fmt.Errorf("map hibernations: %w", err)
}
err = mapAudit(ctx, cl, m)
if err != nil {
return fmt.Errorf("map audit: %w", err)
}
err = mapExtensions(ctx, cl, m)
if err != nil {
return fmt.Errorf("map extensions: %w", err)
Expand Down Expand Up @@ -1943,6 +1995,47 @@ func getMaintenanceTimes(ctx context.Context, cl *ske.Cluster, m *Model) (startT
return startTime, endTime, nil
}

func mapAudit(ctx context.Context, cl *ske.Cluster, m *Model) error {
// The API may omit the audit block entirely (e.g. when audit logging is not
// enabled or not available for the account). In that case we must decide what
// to keep in the Terraform state without producing a spurious plan diff:
if cl.Audit == nil {
// No audit configured on either side (or the value is still unknown): normalize to null.
if m.Audit.IsNull() || m.Audit.IsUnknown() || m.Audit.Attributes() == nil {
m.Audit = types.ObjectNull(auditTypes)
return nil
}

auditModel := audit{}
diags := m.Audit.As(ctx, &auditModel, basetypes.ObjectAsOptions{})
if diags.HasError() {
return fmt.Errorf("converting audit object: %v", diags.Errors())
}

// The user explicitly configured `audit = { enabled = false }`. The API does
// not echo a disabled audit config back, so we keep the configured value to
// avoid a permanent diff between config and state.
if !auditModel.Enabled.IsUnknown() && !auditModel.Enabled.ValueBool() {
return nil
}

// Otherwise (configured enabled=true, but API returned nothing) fall back to
// null so the next plan reflects the actual API state.
m.Audit = types.ObjectNull(auditTypes)
return nil
}

auditValues := map[string]attr.Value{
"enabled": types.BoolValue(cl.Audit.Enabled),
}
auditObject, diags := types.ObjectValue(auditTypes, auditValues)
if diags.HasError() {
return fmt.Errorf("creating audit object: %w", core.DiagsToError(diags))
}
m.Audit = auditObject
return nil
}

func checkDisabledExtensions(ctx context.Context, ex *extensions) (aclDisabled, observabilityDisabled, dnsDisabled bool, err error) {
var diags diag.Diagnostics
acl := acl{}
Expand Down
Loading
Loading