diff --git a/go.mod b/go.mod index 94d7ab230..c5319ae6b 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/serviceaccount v0.12.0 github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.4.1 github.com/stackitcloud/stackit-sdk-go/services/sfs v0.6.3 - github.com/stackitcloud/stackit-sdk-go/services/ske v1.7.0 + github.com/stackitcloud/stackit-sdk-go/services/ske v1.12.0 github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.6.1 github.com/teambition/rrule-go v1.8.2 golang.org/x/mod v0.35.0 diff --git a/go.sum b/go.sum index 080ac54be..f2dac8265 100644 --- a/go.sum +++ b/go.sum @@ -728,8 +728,8 @@ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.4.1 h1:HZnZ github.com/stackitcloud/stackit-sdk-go/services/serviceenablement v1.4.1/go.mod h1:wBxlGcNeQPIh1aS4xYqJuN2z6haSHRwzne6drN5ROfM= github.com/stackitcloud/stackit-sdk-go/services/sfs v0.6.3 h1:LEdPJ6f9pbrft+HlIIzRcCQog58b7UKVm4ObiOH8H4o= github.com/stackitcloud/stackit-sdk-go/services/sfs v0.6.3/go.mod h1:qO2+XOzLy9rRTDo3IvXJd4uZsl6d1npa2cyQvaY4/Fw= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.7.0 h1:l1QjxW7sdE/6B6BZtHxbmus8XJdI9KDuXX3fwUa5fog= -github.com/stackitcloud/stackit-sdk-go/services/ske v1.7.0/go.mod h1:1Jr+ImrmPERxbYnlTy6O2aSZYNnREf2qQyysv6YC1RY= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.12.0 h1:G6iUFDlrwCkCkwSV3eLNsFpVD24h6qV7D4pm0rqftnM= +github.com/stackitcloud/stackit-sdk-go/services/ske v1.12.0/go.mod h1:cSRF2ARIB6dKmvZ12Z5h1usKQligeZJ1JOiJk6Ds3wE= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.6.1 h1:aUpKF2aF8WKsHawXPFnKsRlAcaHkRg6UL0sVjuQqB74= github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.6.1/go.mod h1:1rYtgXQWSv0ykMZ6p7vXcmccGcwR37omNh9FMKLNwck= github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g= diff --git a/stackit/internal/services/ske/cluster/datasource.go b/stackit/internal/services/ske/cluster/datasource.go index de7ac4e9c..b32a0a8c5 100644 --- a/stackit/internal/services/ske/cluster/datasource.go +++ b/stackit/internal/services/ske/cluster/datasource.go @@ -15,7 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" @@ -351,7 +351,7 @@ func (r *clusterDataSource) Read(ctx context.Context, req datasource.ReadRequest ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "name", name) ctx = tflog.SetField(ctx, "region", region) - clusterResp, err := r.client.GetCluster(ctx, projectId, region, name).Execute() + clusterResp, err := r.client.DefaultAPI.GetCluster(ctx, projectId, region, name).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/ske/cluster/resource.go b/stackit/internal/services/ske/cluster/resource.go index ae96243c1..60a00245e 100644 --- a/stackit/internal/services/ske/cluster/resource.go +++ b/stackit/internal/services/ske/cluster/resource.go @@ -20,7 +20,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int32default" "github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier" @@ -35,8 +35,9 @@ import ( sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils" "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement" enablementWait "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/wait" - "github.com/stackitcloud/stackit-sdk-go/services/ske" - skeWait "github.com/stackitcloud/stackit-sdk-go/services/ske/wait" + legacySke "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" + skeWait "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api/wait" "golang.org/x/mod/semver" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" @@ -46,13 +47,13 @@ import ( ) const ( - DefaultOSName = "flatcar" - DefaultCRI = "containerd" - DefaultVolumeType = "storage_premium_perf1" - DefaultVolumeSizeGB int64 = 20 - VersionStateSupported = "supported" - VersionStatePreview = "preview" - VersionStateDeprecated = "deprecated" + DefaultOSName = "flatcar" + DefaultCRI = "containerd" + DefaultVolumeType = "storage_premium_perf1" + DefaultVolumeSizeGB = 20 + VersionStateSupported = "supported" + VersionStatePreview = "preview" + VersionStateDeprecated = "deprecated" SKEUpdateDoc = "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/)." ) @@ -65,10 +66,6 @@ var ( _ resource.ResourceWithModifyPlan = &clusterResource{} ) -type skeClient interface { - GetClusterExecute(ctx context.Context, projectId, region, clusterName string) (*ske.Cluster, error) -} - type Model struct { Id types.String `tfsdk:"id"` // needed by TF ProjectId types.String `tfsdk:"project_id"` @@ -93,12 +90,12 @@ type nodePool struct { 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"` - MaxUnavailable types.Int64 `tfsdk:"max_unavailable"` + Minimum types.Int32 `tfsdk:"minimum"` + Maximum types.Int32 `tfsdk:"maximum"` + MaxSurge types.Int32 `tfsdk:"max_surge"` + MaxUnavailable types.Int32 `tfsdk:"max_unavailable"` VolumeType types.String `tfsdk:"volume_type"` - VolumeSize types.Int64 `tfsdk:"volume_size"` + VolumeSize types.Int32 `tfsdk:"volume_size"` Labels types.Map `tfsdk:"labels"` Taints types.List `tfsdk:"taints"` CRI types.String `tfsdk:"cri"` @@ -114,12 +111,12 @@ var nodePoolTypes = map[string]attr.Type{ "os_version_min": basetypes.StringType{}, "os_version": basetypes.StringType{}, "os_version_used": basetypes.StringType{}, - "minimum": basetypes.Int64Type{}, - "maximum": basetypes.Int64Type{}, - "max_surge": basetypes.Int64Type{}, - "max_unavailable": basetypes.Int64Type{}, + "minimum": basetypes.Int32Type{}, + "maximum": basetypes.Int32Type{}, + "max_surge": basetypes.Int32Type{}, + "max_unavailable": basetypes.Int32Type{}, "volume_type": basetypes.StringType{}, - "volume_size": basetypes.Int64Type{}, + "volume_size": basetypes.Int32Type{}, "labels": basetypes.MapType{ElemType: types.StringType}, "taints": basetypes.ListType{ElemType: types.ObjectType{AttrTypes: taintTypes}}, "cri": basetypes.StringType{}, @@ -423,20 +420,20 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re Computed: true, Default: booldefault.StaticBool(true), }, - "minimum": schema.Int64Attribute{ + "minimum": schema.Int32Attribute{ Description: "Minimum number of nodes in the pool.", Required: true, }, - "maximum": schema.Int64Attribute{ + "maximum": schema.Int32Attribute{ Description: "Maximum number of nodes in the pool.", Required: true, }, - "max_surge": schema.Int64Attribute{ + "max_surge": schema.Int32Attribute{ Description: fmt.Sprintf("%s %s", descriptions["max_surge"], descriptions["nodepool_validators"]), Optional: true, Computed: true, }, - "max_unavailable": schema.Int64Attribute{ + "max_unavailable": schema.Int32Attribute{ Description: fmt.Sprintf("%s %s", descriptions["max_unavailable"], descriptions["nodepool_validators"]), Optional: true, Computed: true, @@ -472,11 +469,11 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re Computed: true, Default: stringdefault.StaticString(DefaultVolumeType), }, - "volume_size": schema.Int64Attribute{ + "volume_size": schema.Int32Attribute{ Description: "The volume size in GB. Defaults to `20`", Optional: true, Computed: true, - Default: int64default.StaticInt64(DefaultVolumeSizeGB), + Default: int32default.StaticInt32(DefaultVolumeSizeGB), }, "labels": schema.MapAttribute{ Description: "Labels to add to each node.", @@ -828,8 +825,7 @@ func sortK8sVersions(versions []ske.KubernetesVersion) { // The k8s versions are sorted descending order, i.e. the latest versions (including previews) // are listed first func (r *clusterResource) loadAvailableVersions(ctx context.Context, region string) ([]ske.KubernetesVersion, []ske.MachineImage, error) { - c := r.skeClient - res, err := c.ListProviderOptions(ctx, region).Execute() + res, err := r.skeClient.DefaultAPI.ListProviderOptions(ctx, region).Execute() if err != nil { return nil, nil, fmt.Errorf("calling API: %w", err) } @@ -842,32 +838,27 @@ func (r *clusterResource) loadAvailableVersions(ctx context.Context, region stri return nil, nil, fmt.Errorf("API response has nil machine images") } - return *res.KubernetesVersions, *res.MachineImages, nil + return res.KubernetesVersions, res.MachineImages, nil } // 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.Region.ValueString(), m.Name.ValueString()) +func getCurrentVersions(ctx context.Context, c ske.DefaultAPI, m *Model) (kubernetesVersion *string, nodePoolMachineImages map[string]*ske.Image) { + res, err := c.GetCluster(ctx, m.ProjectId.ValueString(), m.Region.ValueString(), m.Name.ValueString()).Execute() if err != nil || res == nil { return nil, nil } - if res.Kubernetes != nil { - kubernetesVersion = res.Kubernetes.Version - } + kubernetesVersion = new(res.Kubernetes.Version) 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 + for _, nodePool := range res.Nodepools { + nodePoolMachineImages[nodePool.Name] = &nodePool.Machine.Image } return kubernetesVersion, nodePoolMachineImages @@ -884,7 +875,7 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag return } if hasDeprecatedVersion { - diags.AddWarning("Deprecated Kubernetes version", fmt.Sprintf("Version %s of Kubernetes is deprecated, please update it", *kubernetes.Version)) + diags.AddWarning("Deprecated Kubernetes version", fmt.Sprintf("Version %s of Kubernetes is deprecated, please update it", kubernetes.Version)) } nodePools, deprecatedVersionsUsed, err := toNodepoolsPayload(ctx, model, availableMachineVersions, currentMachineImages) if err != nil { @@ -918,12 +909,12 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag payload := ske.CreateOrUpdateClusterPayload{ Extensions: extensions, Hibernation: hibernations, - Kubernetes: kubernetes, + Kubernetes: *kubernetes, Maintenance: maintenance, Network: network, - Nodepools: &nodePools, + Nodepools: nodePools, } - _, err = r.skeClient.CreateOrUpdateCluster(ctx, projectId, region, name).CreateOrUpdateClusterPayload(payload).Execute() + _, err = r.skeClient.DefaultAPI.CreateOrUpdateCluster(ctx, projectId, region, name).CreateOrUpdateClusterPayload(payload).Execute() if err != nil { core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Calling API: %v", err)) return @@ -935,12 +926,12 @@ func (r *clusterResource) createOrUpdateCluster(ctx context.Context, diags *diag // Call tflog.Info here, to log the information of the updated context tflog.Info(ctx, "Triggered create/update cluster") - waitResp, err := skeWait.CreateOrUpdateClusterWaitHandler(ctx, r.skeClient, projectId, region, name).WaitWithContext(ctx) + waitResp, err := skeWait.CreateOrUpdateClusterWaitHandler(ctx, r.skeClient.DefaultAPI, projectId, region, name).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, diags, "Error creating/updating cluster", fmt.Sprintf("Cluster creation waiting: %v", err)) return } - if waitResp.Status.Error != nil && waitResp.Status.Error.Message != nil && *waitResp.Status.Error.Code == ske.RUNTIMEERRORCODE_OBSERVABILITY_INSTANCE_NOT_FOUND { + if waitResp.Status.Error != nil && waitResp.Status.Error.Message != nil && *waitResp.Status.Error.Code == string(legacySke.RUNTIMEERRORCODE_OBSERVABILITY_INSTANCE_NOT_FOUND) { core.LogAndAddWarning(ctx, diags, "Warning during creating/updating cluster", fmt.Sprintf("Cluster is in Impaired state due to an invalid observability instance id, the cluster is usable but metrics won't be forwarded: %s", *waitResp.Status.Error.Message)) } @@ -963,10 +954,7 @@ func toNodepoolsPayload(ctx context.Context, m *Model, availableMachineVersions for i := range nodePools { nodePool := nodePools[i] - name := conversion.StringValueToPointer(nodePool.Name) - if name == nil { - return nil, nil, fmt.Errorf("found nil node pool name for node_pool[%d]", i) - } + name := nodePool.Name.ValueString() // taints taintsModel := []taint{} @@ -978,8 +966,8 @@ func toNodepoolsPayload(ctx context.Context, m *Model, availableMachineVersions ts := []ske.Taint{} for _, v := range taintsModel { t := ske.Taint{ - Effect: ske.TaintGetEffectAttributeType(conversion.StringValueToPointer(v.Effect)), - Key: conversion.StringValueToPointer(v.Key), + Effect: v.Effect.ValueString(), + Key: v.Key.ValueString(), Value: conversion.StringValueToPointer(v.Value), } ts = append(ts, t) @@ -1015,14 +1003,14 @@ func toNodepoolsPayload(ctx context.Context, m *Model, availableMachineVersions zs = append(zs, s) } - cn := ske.CRI{ - Name: ske.CRIGetNameAttributeType(conversion.StringValueToPointer(nodePool.CRI)), + cn := &ske.CRI{ + Name: conversion.StringValueToPointer(nodePool.CRI), } providedVersionMin := conversion.StringValueToPointer(nodePool.OSVersionMin) if !nodePool.OSVersion.IsNull() { if providedVersionMin != nil { - return nil, nil, fmt.Errorf("both `os_version` and `os_version_min` are set for for node_pool %q. Please use `os_version_min` only, `os_version` is deprecated", *name) + return nil, nil, fmt.Errorf("both `os_version` and `os_version_min` are set for for node_pool %q. Please use `os_version_min` only, `os_version` is deprecated", name) } // os_version field deprecation // this if clause should be removed once os_version field is completely removed @@ -1030,14 +1018,11 @@ func toNodepoolsPayload(ctx context.Context, m *Model, availableMachineVersions providedVersionMin = conversion.StringValueToPointer(nodePool.OSVersion) } - machineOSName := conversion.StringValueToPointer(nodePool.OSName) - if machineOSName == nil { - return nil, nil, fmt.Errorf("found nil machine name for node_pool %q", *name) - } + machineOSName := nodePool.OSName.ValueString() - currentMachineImage := currentMachineImages[*name] + currentMachineImage := currentMachineImages[name] - machineVersion, hasDeprecatedVersion, err := latestMatchingMachineVersion(availableMachineVersions, providedVersionMin, *machineOSName, currentMachineImage) + machineVersion, hasDeprecatedVersion, err := latestMatchingMachineVersion(availableMachineVersions, providedVersionMin, machineOSName, currentMachineImage) if err != nil { return nil, nil, fmt.Errorf("getting latest matching machine image version: %w", err) } @@ -1047,25 +1032,25 @@ func toNodepoolsPayload(ctx context.Context, m *Model, availableMachineVersions cnp := ske.Nodepool{ Name: name, - Minimum: conversion.Int64ValueToPointer(nodePool.Minimum), - Maximum: conversion.Int64ValueToPointer(nodePool.Maximum), - MaxSurge: conversion.Int64ValueToPointer(nodePool.MaxSurge), - MaxUnavailable: conversion.Int64ValueToPointer(nodePool.MaxUnavailable), - Machine: &ske.Machine{ - Type: conversion.StringValueToPointer(nodePool.MachineType), - Image: &ske.Image{ + Minimum: nodePool.Minimum.ValueInt32(), + Maximum: nodePool.Maximum.ValueInt32(), + MaxSurge: conversion.Int32ValueToPointer(nodePool.MaxSurge), + MaxUnavailable: conversion.Int32ValueToPointer(nodePool.MaxUnavailable), + Machine: ske.Machine{ + Type: nodePool.MachineType.ValueString(), + Image: ske.Image{ Name: machineOSName, - Version: machineVersion, + Version: *machineVersion, }, }, - Volume: &ske.Volume{ + Volume: ske.Volume{ Type: conversion.StringValueToPointer(nodePool.VolumeType), - Size: conversion.Int64ValueToPointer(nodePool.VolumeSize), + Size: int32(nodePool.VolumeSize.ValueInt32()), }, - Taints: &ts, - Cri: &cn, + Taints: ts, + Cri: cn, Labels: ls, - AvailabilityZones: &zs, + AvailabilityZones: zs, AllowSystemComponents: conversion.BoolValueToPointer(nodePool.AllowSystemComponents), } cnps = append(cnps, cnp) @@ -1111,7 +1096,7 @@ func latestMatchingMachineVersion(availableImages []ske.MachineImage, versionMin var availableMachineVersions []ske.MachineImageVersion for _, machine := range availableImages { if machine.Name != nil && *machine.Name == osName && machine.Versions != nil { - availableMachineVersions = *machine.Versions + availableMachineVersions = machine.Versions } } @@ -1123,22 +1108,22 @@ func latestMatchingMachineVersion(availableImages []ske.MachineImage, versionMin // 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 { + if currentImage == 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 { + versionMin = ¤tImage.Version + } else if currentImage != 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 + currentVersion := "v" + currentImage.Version if semver.Compare(minimumVersion, currentVersion) == -1 { - versionMin = currentImage.Version + versionMin = ¤tImage.Version } } @@ -1235,8 +1220,8 @@ func toHibernationsPayload(ctx context.Context, m *Model) (*ske.Hibernation, err scs := []ske.HibernationSchedule{} for _, h := range hibernation { sc := ske.HibernationSchedule{ - Start: conversion.StringValueToPointer(h.Start), - End: conversion.StringValueToPointer(h.End), + Start: h.Start.ValueString(), + End: h.End.ValueString(), } if !h.Timezone.IsNull() && !h.Timezone.IsUnknown() { tz := h.Timezone.ValueString() @@ -1246,7 +1231,7 @@ func toHibernationsPayload(ctx context.Context, m *Model) (*ske.Hibernation, err } return &ske.Hibernation{ - Schedules: &scs, + Schedules: scs, }, nil } @@ -1267,7 +1252,7 @@ func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error) if diags.HasError() { return nil, fmt.Errorf("converting extensions.acl object: %v", diags.Errors()) } - aclEnabled := conversion.BoolValueToPointer(acl.Enabled) + aclEnabled := acl.Enabled.ValueBool() cidrs := []string{} diags = acl.AllowedCIDRs.ElementsAs(ctx, &cidrs, true) @@ -1276,7 +1261,7 @@ func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error) } skeAcl = &ske.ACL{ Enabled: aclEnabled, - AllowedCidrs: &cidrs, + AllowedCidrs: cidrs, } } @@ -1287,8 +1272,8 @@ func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error) if diags.HasError() { return nil, fmt.Errorf("converting extensions.observability object: %v", diags.Errors()) } - observabilityEnabled := conversion.BoolValueToPointer(observability.Enabled) - observabilityInstanceId := conversion.StringValueToPointer(observability.InstanceId) + observabilityEnabled := observability.Enabled.ValueBool() + observabilityInstanceId := observability.InstanceId.ValueString() skeObservability = &ske.Observability{ Enabled: observabilityEnabled, InstanceId: observabilityInstanceId, @@ -1299,8 +1284,8 @@ func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error) if diags.HasError() { return nil, fmt.Errorf("converting extensions.argus object: %v", diags.Errors()) } - argusEnabled := conversion.BoolValueToPointer(argus.Enabled) - argusInstanceId := conversion.StringValueToPointer(argus.ArgusInstanceId) + argusEnabled := argus.Enabled.ValueBool() + argusInstanceId := argus.ArgusInstanceId.ValueString() skeObservability = &ske.Observability{ Enabled: argusEnabled, InstanceId: argusInstanceId, @@ -1314,7 +1299,7 @@ func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error) if diags.HasError() { return nil, fmt.Errorf("converting extensions.dns object: %v", diags.Errors()) } - dnsEnabled := conversion.BoolValueToPointer(dns.Enabled) + dnsEnabled := dns.Enabled.ValueBool() zones := []string{} diags = dns.Zones.ElementsAs(ctx, &zones, true) @@ -1323,7 +1308,7 @@ func toExtensionsPayload(ctx context.Context, m *Model) (*ske.Extension, error) } skeDNS = &ske.DNS{ Enabled: dnsEnabled, - Zones: &zones, + Zones: zones, } } @@ -1353,30 +1338,30 @@ func toMaintenancePayload(ctx context.Context, m *Model) (*ske.Maintenance, erro return nil, fmt.Errorf("converting maintenance object: %v", diags.Errors()) } - var timeWindowStart *time.Time + var timeWindowStart time.Time if !(maintenance.Start.IsNull() || maintenance.Start.IsUnknown()) { tempTime, err := parseMaintenanceWindowTime(maintenance.Start.ValueString()) if err != nil { return nil, fmt.Errorf("converting maintenance object: %w", err) } - timeWindowStart = new(tempTime) + timeWindowStart = tempTime } - var timeWindowEnd *time.Time + var timeWindowEnd time.Time if !(maintenance.End.IsNull() || maintenance.End.IsUnknown()) { tempTime, err := parseMaintenanceWindowTime(maintenance.End.ValueString()) if err != nil { return nil, fmt.Errorf("converting maintenance object: %w", err) } - timeWindowEnd = new(tempTime) + timeWindowEnd = tempTime } return &ske.Maintenance{ - AutoUpdate: &ske.MaintenanceAutoUpdate{ + AutoUpdate: ske.MaintenanceAutoUpdate{ KubernetesVersion: conversion.BoolValueToPointer(maintenance.EnableKubernetesVersionUpdates), MachineImageVersion: conversion.BoolValueToPointer(maintenance.EnableMachineImageVersionUpdates), }, - TimeWindow: &ske.TimeWindow{ + TimeWindow: ske.TimeWindow{ Start: timeWindowStart, End: timeWindowEnd, }, @@ -1402,7 +1387,7 @@ func toNetworkPayload(ctx context.Context, m *Model) (*ske.Network, error) { return nil, fmt.Errorf("converting network control plane: %w", core.DiagsToError(diags)) } networkControlPlane = &ske.V2ControlPlaneNetwork{ - AccessScope: ske.V2ControlPlaneNetworkGetAccessScopeAttributeType(conversion.StringValueToPointer(networkControlPlaneModel.AccessScope)), + AccessScope: new(ske.AccessScope(networkControlPlaneModel.AccessScope.ValueString())), } } @@ -1433,9 +1418,7 @@ func mapFields(ctx context.Context, cl *ske.Cluster, m *Model, region string) er m.Id = utils.BuildInternalTerraformId(m.ProjectId.ValueString(), region, name) m.Region = types.StringValue(region) - if cl.Kubernetes != nil { - m.KubernetesVersionUsed = types.StringPointerValue(cl.Kubernetes.Version) - } + m.KubernetesVersionUsed = types.StringValue(cl.Kubernetes.Version) m.EgressAddressRanges = types.ListNull(types.StringType) if cl.Status != nil { @@ -1504,38 +1487,26 @@ func mapNodePools(ctx context.Context, cl *ske.Cluster, model *Model) error { } nodePools := []attr.Value{} - for i, nodePoolResp := range *cl.Nodepools { + for i, nodePoolResp := range cl.Nodepools { nodePool := map[string]attr.Value{ - "name": types.StringPointerValue(nodePoolResp.Name), - "machine_type": types.StringPointerValue(nodePoolResp.Machine.Type), - "os_name": 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), - "max_unavailable": types.Int64PointerValue(nodePoolResp.MaxUnavailable), - "volume_type": types.StringNull(), - "volume_size": types.Int64PointerValue(nodePoolResp.Volume.Size), + "name": types.StringValue(nodePoolResp.Name), + "machine_type": types.StringValue(nodePoolResp.Machine.Type), + "os_name": types.StringValue(nodePoolResp.Machine.Image.Name), + "os_version_min": modelNodePoolOSVersionMin[nodePoolResp.Name], + "os_version": modelNodePoolOSVersion[nodePoolResp.Name], + "os_version_used": types.StringValue(nodePoolResp.Machine.Image.Version), + "minimum": types.Int32Value(nodePoolResp.Minimum), + "maximum": types.Int32Value(nodePoolResp.Maximum), + "max_surge": types.Int32PointerValue(nodePoolResp.MaxSurge), + "max_unavailable": types.Int32PointerValue(nodePoolResp.MaxUnavailable), + "volume_type": types.StringPointerValue(nodePoolResp.Volume.Type), + "volume_size": types.Int32Value(nodePoolResp.Volume.Size), "labels": types.MapNull(types.StringType), - "cri": types.StringNull(), + "cri": types.StringPointerValue(nodePoolResp.Cri.Name), "availability_zones": types.ListNull(types.StringType), "allow_system_components": types.BoolPointerValue(nodePoolResp.AllowSystemComponents), } - if nodePoolResp.Machine != nil && nodePoolResp.Machine.Image != nil { - nodePool["os_name"] = types.StringPointerValue(nodePoolResp.Machine.Image.Name) - nodePool["os_version_used"] = types.StringPointerValue(nodePoolResp.Machine.Image.Version) - } - - if nodePoolResp.Volume != nil { - nodePool["volume_type"] = types.StringPointerValue(nodePoolResp.Volume.Type) - } - - if nodePoolResp.Cri != nil { - nodePool["cri"] = types.StringValue(string(nodePoolResp.Cri.GetName())) - } - taintsInModel := false if i < len(modelNodePools) && !modelNodePools[i].Taints.IsNull() && !modelNodePools[i].Taints.IsUnknown() { taintsInModel = true @@ -1558,7 +1529,7 @@ func mapNodePools(ctx context.Context, cl *ske.Cluster, model *Model) error { } if nodePoolResp.AvailabilityZones != nil { - elemsTF, diags := types.ListValueFrom(ctx, types.StringType, *nodePoolResp.AvailabilityZones) + elemsTF, diags := types.ListValueFrom(ctx, types.StringType, nodePoolResp.AvailabilityZones) if diags.HasError() { return fmt.Errorf("mapping index %d, field availability_zones: %w", i, core.DiagsToError(diags)) } @@ -1579,8 +1550,8 @@ func mapNodePools(ctx context.Context, cl *ske.Cluster, model *Model) error { return nil } -func mapTaints(t *[]ske.Taint, nodePool map[string]attr.Value, existInModel bool) error { - if t == nil || len(*t) == 0 { +func mapTaints(t []ske.Taint, nodePool map[string]attr.Value, existInModel bool) error { + if len(t) == 0 { if existInModel { taintsTF, diags := types.ListValue(types.ObjectType{AttrTypes: taintTypes}, []attr.Value{}) if diags.HasError() { @@ -1595,10 +1566,10 @@ func mapTaints(t *[]ske.Taint, nodePool map[string]attr.Value, existInModel bool taints := []attr.Value{} - for i, taintResp := range *t { + for i, taintResp := range t { taint := map[string]attr.Value{ "effect": types.StringValue(string(taintResp.GetEffect())), - "key": types.StringPointerValue(taintResp.Key), + "key": types.StringValue(taintResp.Key), "value": types.StringPointerValue(taintResp.Value), } taintTF, diags := basetypes.NewObjectValue(taintTypes, taint) @@ -1641,10 +1612,10 @@ func mapHibernations(cl *ske.Cluster, m *Model) error { } hibernations := []attr.Value{} - for i, hibernationResp := range *cl.Hibernation.Schedules { + for i, hibernationResp := range cl.Hibernation.Schedules { hibernation := map[string]attr.Value{ - "start": types.StringPointerValue(hibernationResp.Start), - "end": types.StringPointerValue(hibernationResp.End), + "start": types.StringValue(hibernationResp.Start), + "end": types.StringValue(hibernationResp.End), "timezone": types.StringPointerValue(hibernationResp.Timezone), } hibernationTF, diags := basetypes.NewObjectValue(hibernationTypes, hibernation) @@ -1704,8 +1675,7 @@ func mapNetwork(cl *ske.Cluster, m *Model) error { // If the network field is not provided, the SKE API returns an empty object. // If we parse that object into the terraform model, it will produce an inconsistent result after apply error - emptyNetwork := &ske.Network{} - if *cl.Network == *emptyNetwork && m.Network.IsNull() { + if skeUtils.IsEmptyNetwork(cl.Network) && m.Network.IsNull() { if m.Network.Attributes() == nil { m.Network = types.ObjectNull(networkTypes) } @@ -1748,8 +1718,8 @@ func mapNetwork(cl *ske.Cluster, m *Model) error { } func getMaintenanceTimes(ctx context.Context, cl *ske.Cluster, m *Model) (startTime, endTime string, err error) { - startTimeAPI := *cl.Maintenance.TimeWindow.Start - endTimeAPI := *cl.Maintenance.TimeWindow.End + startTimeAPI := cl.Maintenance.TimeWindow.Start + endTimeAPI := cl.Maintenance.TimeWindow.End if m.Maintenance.IsNull() || m.Maintenance.IsUnknown() { return startTimeAPI.Format("15:04:05Z07:00"), endTimeAPI.Format("15:04:05Z07:00"), nil @@ -1861,8 +1831,7 @@ func mapExtensions(ctx context.Context, cl *ske.Cluster, m *Model) error { } disabledExtensions := aclDisabled && observabilityDisabled && dnsDisabled - emptyExtensions := &ske.Extension{} - if *cl.Extensions == *emptyExtensions && (disabledExtensions || m.Extensions.IsNull()) { + if skeUtils.IsEmptyExtension(cl.Extensions) && (disabledExtensions || m.Extensions.IsNull()) { if m.Extensions.Attributes() == nil { m.Extensions = types.ObjectNull(extensionsTypes) } @@ -1871,10 +1840,7 @@ func mapExtensions(ctx context.Context, cl *ske.Cluster, m *Model) error { aclExtension := types.ObjectNull(aclTypes) if cl.Extensions.Acl != nil { - enabled := types.BoolNull() - if cl.Extensions.Acl.Enabled != nil { - enabled = types.BoolValue(*cl.Extensions.Acl.Enabled) - } + enabled := types.BoolValue(cl.Extensions.Acl.Enabled) cidrsList, diags := types.ListValueFrom(ctx, types.StringType, cl.Extensions.Acl.AllowedCidrs) if diags.HasError() { @@ -1898,15 +1864,8 @@ func mapExtensions(ctx context.Context, cl *ske.Cluster, m *Model) error { argusExtension := types.ObjectNull(argusTypes) observabilityExtension := types.ObjectNull(observabilityTypes) if cl.Extensions.Observability != nil { - enabled := types.BoolNull() - if cl.Extensions.Observability.Enabled != nil { - enabled = types.BoolValue(*cl.Extensions.Observability.Enabled) - } - - observabilityInstanceId := types.StringNull() - if cl.Extensions.Observability.InstanceId != nil { - observabilityInstanceId = types.StringValue(*cl.Extensions.Observability.InstanceId) - } + enabled := types.BoolValue(cl.Extensions.Observability.Enabled) + observabilityInstanceId := types.StringValue(cl.Extensions.Observability.InstanceId) observabilityExtensionValues := map[string]attr.Value{ "enabled": enabled, @@ -1947,10 +1906,7 @@ func mapExtensions(ctx context.Context, cl *ske.Cluster, m *Model) error { dnsExtension := types.ObjectNull(dnsTypes) if cl.Extensions.Dns != nil { - enabled := types.BoolNull() - if cl.Extensions.Dns.Enabled != nil { - enabled = types.BoolValue(*cl.Extensions.Dns.Enabled) - } + enabled := types.BoolValue(cl.Extensions.Dns.Enabled) zonesList, diags := types.ListValueFrom(ctx, types.StringType, cl.Extensions.Dns.Zones) if diags.HasError() { @@ -2001,11 +1957,11 @@ func toKubernetesPayload(m *Model, availableVersions []ske.KubernetesVersion, cu providedVersionMin := m.KubernetesVersionMin.ValueStringPointer() versionUsed, hasDeprecatedVersion, err := latestMatchingKubernetesVersion(availableVersions, providedVersionMin, currentKubernetesVersion, diags) if err != nil { - return nil, false, fmt.Errorf("getting latest matching kubernetes version: %w", err) + return kubernetesPayload, false, fmt.Errorf("getting latest matching kubernetes version: %w", err) } k := &ske.Kubernetes{ - Version: versionUsed, + Version: *versionUsed, } return k, hasDeprecatedVersion, nil } @@ -2189,7 +2145,7 @@ func (r *clusterResource) Read(ctx context.Context, req resource.ReadRequest, re ctx = tflog.SetField(ctx, "name", name) ctx = tflog.SetField(ctx, "region", region) - clResp, err := r.skeClient.GetCluster(ctx, projectId, region, name).Execute() + clResp, err := r.skeClient.DefaultAPI.GetCluster(ctx, projectId, region, 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 { @@ -2239,7 +2195,7 @@ func (r *clusterResource) Update(ctx context.Context, req resource.UpdateRequest return } - currentKubernetesVersion, currentMachineImages := getCurrentVersions(ctx, r.skeClient, &model) + currentKubernetesVersion, currentMachineImages := getCurrentVersions(ctx, r.skeClient.DefaultAPI, &model) r.createOrUpdateCluster(ctx, &resp.Diagnostics, &model, availableKubernetesVersions, availableMachines, currentKubernetesVersion, currentMachineImages) if resp.Diagnostics.HasError() { @@ -2270,8 +2226,7 @@ func (r *clusterResource) Delete(ctx context.Context, req resource.DeleteRequest ctx = tflog.SetField(ctx, "name", name) ctx = tflog.SetField(ctx, "region", region) - c := r.skeClient - _, err := c.DeleteCluster(ctx, projectId, region, name).Execute() + _, err := r.skeClient.DefaultAPI.DeleteCluster(ctx, projectId, region, name).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting cluster", fmt.Sprintf("Calling API: %v", err)) return @@ -2279,7 +2234,7 @@ func (r *clusterResource) Delete(ctx context.Context, req resource.DeleteRequest ctx = core.LogResponse(ctx) - _, err = skeWait.DeleteClusterWaitHandler(ctx, r.skeClient, projectId, region, name).WaitWithContext(ctx) + _, err = skeWait.DeleteClusterWaitHandler(ctx, r.skeClient.DefaultAPI, projectId, region, name).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting cluster", fmt.Sprintf("Cluster deletion waiting: %v", err)) return diff --git a/stackit/internal/services/ske/cluster/resource_test.go b/stackit/internal/services/ske/cluster/resource_test.go index 482dfae11..aec9a8434 100644 --- a/stackit/internal/services/ske/cluster/resource_test.go +++ b/stackit/internal/services/ske/cluster/resource_test.go @@ -3,6 +3,7 @@ package ske import ( "context" "fmt" + "net/http" "strings" "testing" "time" @@ -12,27 +13,15 @@ import ( "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" ) -type skeClientMocked struct { - returnError bool - getClusterResp *ske.Cluster -} - const testRegion = "region" -func (c *skeClientMocked) GetClusterExecute(_ context.Context, _, _, _ string) (*ske.Cluster, error) { - if c.returnError { - return nil, fmt.Errorf("get cluster failed") - } - - return c.getClusterResp, nil -} - func TestMapFields(t *testing.T) { cs := ske.ClusterStatusState("OK") tests := []struct { @@ -53,17 +42,18 @@ func TestMapFields(t *testing.T) { }, testRegion, Model{ - Id: types.StringValue("pid,region,name"), - ProjectId: types.StringValue("pid"), - Name: types.StringValue("name"), - NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}), - Maintenance: types.ObjectNull(maintenanceTypes), - Network: types.ObjectNull(networkTypes), - Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}), - Extensions: types.ObjectNull(extensionsTypes), - EgressAddressRanges: types.ListNull(types.StringType), - PodAddressRanges: types.ListNull(types.StringType), - Region: types.StringValue(testRegion), + Id: types.StringValue("pid,region,name"), + ProjectId: types.StringValue("pid"), + Name: types.StringValue("name"), + NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}), + Maintenance: types.ObjectNull(maintenanceTypes), + Network: types.ObjectNull(networkTypes), + Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}), + Extensions: types.ObjectNull(extensionsTypes), + EgressAddressRanges: types.ListNull(types.StringType), + PodAddressRanges: types.ListNull(types.StringType), + Region: types.StringValue(testRegion), + KubernetesVersionUsed: types.StringValue(""), }, true, }, @@ -74,76 +64,76 @@ func TestMapFields(t *testing.T) { &ske.Cluster{ Extensions: &ske.Extension{ Acl: &ske.ACL{ - AllowedCidrs: &[]string{"cidr1"}, - Enabled: new(true), + AllowedCidrs: []string{"cidr1"}, + Enabled: true, }, Observability: &ske.Observability{ - InstanceId: new("aid"), - Enabled: new(true), + InstanceId: "aid", + Enabled: true, }, Dns: &ske.DNS{ - Zones: &[]string{"foo.onstackit.cloud"}, - Enabled: new(true), + Zones: []string{"foo.onstackit.cloud"}, + Enabled: true, }, }, Hibernation: &ske.Hibernation{ - Schedules: &[]ske.HibernationSchedule{ + Schedules: []ske.HibernationSchedule{ { - End: new("2"), - Start: new("1"), + End: "2", + Start: "1", Timezone: new("CET"), }, }, }, - Kubernetes: &ske.Kubernetes{ - Version: new("1.2.3"), + Kubernetes: ske.Kubernetes{ + Version: "1.2.3", }, Maintenance: &ske.Maintenance{ - AutoUpdate: &ske.MaintenanceAutoUpdate{ + AutoUpdate: ske.MaintenanceAutoUpdate{ KubernetesVersion: new(true), MachineImageVersion: new(true), }, - TimeWindow: &ske.TimeWindow{ - Start: new(time.Date(0, 1, 2, 3, 4, 5, 6, time.FixedZone("UTC+6:00", 6*60*60))), - End: new(time.Date(10, 11, 12, 13, 14, 15, 0, time.UTC)), + TimeWindow: ske.TimeWindow{ + Start: time.Date(0, 1, 2, 3, 4, 5, 6, time.FixedZone("UTC+6:00", 6*60*60)), + End: time.Date(10, 11, 12, 13, 14, 15, 0, time.UTC), }, }, Network: &ske.Network{ Id: new("nid"), ControlPlane: &ske.V2ControlPlaneNetwork{ - AccessScope: ske.V2ControlPlaneNetworkGetAccessScopeAttributeType(new("SNA")), + AccessScope: ske.ACCESSSCOPE_SNA.Ptr(), }, }, Name: new("name"), - Nodepools: &[]ske.Nodepool{ + Nodepools: []ske.Nodepool{ { AllowSystemComponents: new(true), - AvailabilityZones: &[]string{"z1", "z2"}, + AvailabilityZones: []string{"z1", "z2"}, Cri: &ske.CRI{ - Name: ske.CRINAME_DOCKER.Ptr(), + Name: new("containerd"), }, Labels: &map[string]string{"k": "v"}, - Machine: &ske.Machine{ - Image: &ske.Image{ - Name: new("os"), - Version: new("os-ver"), + Machine: ske.Machine{ + Image: ske.Image{ + Name: "os", + Version: "os-ver", }, - Type: new("B"), + Type: "B", }, - MaxSurge: new(int64(3)), + MaxSurge: new(int32(3)), MaxUnavailable: nil, - Maximum: new(int64(5)), - Minimum: new(int64(1)), - Name: new("node"), - Taints: &[]ske.Taint{ + Maximum: 5, + Minimum: 1, + Name: "node", + Taints: []ske.Taint{ { - Effect: ske.TAINTEFFECT_NO_EXECUTE.Ptr(), - Key: new("key"), + Effect: "NoExecute", + Key: "key", Value: new("value"), }, }, - Volume: &ske.Volume{ - Size: new(int64(3)), + Volume: ske.Volume{ + Size: 3, Type: new("type"), }, }, @@ -152,8 +142,8 @@ func TestMapFields(t *testing.T) { Aggregated: &cs, Error: nil, Hibernated: nil, - EgressAddressRanges: &[]string{"0.0.0.0/32", "1.1.1.1/32"}, - PodAddressRanges: &[]string{"0.0.0.0/32", "1.1.1.1/32"}, + EgressAddressRanges: []string{"0.0.0.0/32", "1.1.1.1/32"}, + PodAddressRanges: []string{"0.0.0.0/32", "1.1.1.1/32"}, }, }, testRegion, @@ -188,12 +178,12 @@ func TestMapFields(t *testing.T) { "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), - "max_unavailable": types.Int64Null(), + "minimum": types.Int32Value(1), + "maximum": types.Int32Value(5), + "max_surge": types.Int32Value(3), + "max_unavailable": types.Int32Null(), "volume_type": types.StringValue("type"), - "volume_size": types.Int64Value(3), + "volume_size": types.Int32Value(3), "labels": types.MapValueMust( types.StringType, map[string]attr.Value{ @@ -206,14 +196,14 @@ func TestMapFields(t *testing.T) { types.ObjectValueMust( taintTypes, map[string]attr.Value{ - "effect": types.StringValue(string(ske.TAINTEFFECT_NO_EXECUTE)), + "effect": types.StringValue("NoExecute"), "key": types.StringValue("key"), "value": types.StringValue("value"), }, ), }, ), - "cri": types.StringValue(string(ske.CRINAME_DOCKER)), + "cri": types.StringValue("containerd"), "availability_zones": types.ListValueMust( types.StringType, []attr.Value{ @@ -284,17 +274,18 @@ func TestMapFields(t *testing.T) { }, testRegion, Model{ - Id: types.StringValue("pid,region,name"), - ProjectId: types.StringValue("pid"), - Name: types.StringValue("name"), - NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}), - Maintenance: types.ObjectNull(maintenanceTypes), - Network: types.ObjectNull(networkTypes), - Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}), - Extensions: types.ObjectNull(extensionsTypes), - EgressAddressRanges: types.ListNull(types.StringType), - PodAddressRanges: types.ListNull(types.StringType), - Region: types.StringValue(testRegion), + Id: types.StringValue("pid,region,name"), + ProjectId: types.StringValue("pid"), + Name: types.StringValue("name"), + NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}), + Maintenance: types.ObjectNull(maintenanceTypes), + Network: types.ObjectNull(networkTypes), + Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}), + Extensions: types.ObjectNull(extensionsTypes), + EgressAddressRanges: types.ListNull(types.StringType), + PodAddressRanges: types.ListNull(types.StringType), + KubernetesVersionUsed: types.StringValue(""), + Region: types.StringValue(testRegion), }, true, }, @@ -306,15 +297,15 @@ func TestMapFields(t *testing.T) { Extensions: &ske.Extension{ Acl: &ske.ACL{ AllowedCidrs: nil, - Enabled: new(true), + Enabled: true, }, Observability: &ske.Observability{ - InstanceId: nil, - Enabled: new(true), + InstanceId: "", + Enabled: true, }, Dns: &ske.DNS{ Zones: nil, - Enabled: new(true), + Enabled: true, }, }, Name: new("name"), @@ -337,14 +328,15 @@ func TestMapFields(t *testing.T) { "argus": types.ObjectNull(argusTypes), "observability": types.ObjectValueMust(observabilityTypes, map[string]attr.Value{ "enabled": types.BoolValue(true), - "instance_id": types.StringNull(), + "instance_id": types.StringValue(""), }), "dns": types.ObjectValueMust(dnsTypes, map[string]attr.Value{ "enabled": types.BoolValue(true), "zones": types.ListNull(types.StringType), }), }), - Region: types.StringValue(testRegion), + KubernetesVersionUsed: types.StringValue(""), + Region: types.StringValue(testRegion), }, true, }, @@ -395,7 +387,8 @@ func TestMapFields(t *testing.T) { "zones": types.ListNull(types.StringType), }), }), - Region: types.StringValue(testRegion), + KubernetesVersionUsed: types.StringValue(""), + Region: types.StringValue(testRegion), }, true, }, @@ -422,12 +415,12 @@ func TestMapFields(t *testing.T) { &ske.Cluster{ Extensions: &ske.Extension{ Acl: &ske.ACL{ - AllowedCidrs: &[]string{"cidr1"}, - Enabled: new(true), + AllowedCidrs: []string{"cidr1"}, + Enabled: true, }, Dns: &ske.DNS{ Zones: nil, - Enabled: new(true), + Enabled: true, }, }, Name: new("name"), @@ -459,7 +452,8 @@ func TestMapFields(t *testing.T) { "zones": types.ListNull(types.StringType), }), }), - Region: types.StringValue(testRegion), + KubernetesVersionUsed: types.StringValue(""), + Region: types.StringValue(testRegion), }, true, }, @@ -473,16 +467,17 @@ func TestMapFields(t *testing.T) { }, testRegion, Model{ - Id: types.StringValue("pid,region,name"), - ProjectId: types.StringValue("pid"), - Name: types.StringValue("name"), - NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}), - Maintenance: types.ObjectNull(maintenanceTypes), - Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}), - Extensions: types.ObjectNull(extensionsTypes), - EgressAddressRanges: types.ListNull(types.StringType), - PodAddressRanges: types.ListNull(types.StringType), - Region: types.StringValue(testRegion), + Id: types.StringValue("pid,region,name"), + ProjectId: types.StringValue("pid"), + Name: types.StringValue("name"), + NodePools: types.ListNull(types.ObjectType{AttrTypes: nodePoolTypes}), + Maintenance: types.ObjectNull(maintenanceTypes), + Hibernations: types.ListNull(types.ObjectType{AttrTypes: hibernationTypes}), + Extensions: types.ObjectNull(extensionsTypes), + EgressAddressRanges: types.ListNull(types.StringType), + PodAddressRanges: types.ListNull(types.StringType), + KubernetesVersionUsed: types.StringValue(""), + Region: types.StringValue(testRegion), }, true, }, @@ -501,12 +496,12 @@ func TestMapFields(t *testing.T) { "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), - "max_unavailable": types.Int64Null(), + "minimum": types.Int32Value(1), + "maximum": types.Int32Value(5), + "max_surge": types.Int32Value(3), + "max_unavailable": types.Int32Null(), "volume_type": types.StringValue("type"), - "volume_size": types.Int64Value(3), + "volume_size": types.Int32Value(3), "labels": types.MapValueMust( types.StringType, map[string]attr.Value{ @@ -514,7 +509,7 @@ func TestMapFields(t *testing.T) { }, ), "taints": types.ListValueMust(types.ObjectType{AttrTypes: taintTypes}, []attr.Value{}), - "cri": types.StringValue(string(ske.CRINAME_DOCKER)), + "cri": types.StringValue("containerd"), "availability_zones": types.ListValueMust( types.StringType, []attr.Value{ @@ -530,69 +525,69 @@ func TestMapFields(t *testing.T) { &ske.Cluster{ Extensions: &ske.Extension{ Acl: &ske.ACL{ - AllowedCidrs: &[]string{"cidr1"}, - Enabled: new(true), + AllowedCidrs: []string{"cidr1"}, + Enabled: true, }, Observability: &ske.Observability{ - InstanceId: new("aid"), - Enabled: new(true), + InstanceId: "aid", + Enabled: true, }, Dns: &ske.DNS{ - Zones: &[]string{"zone1"}, - Enabled: new(true), + Zones: []string{"zone1"}, + Enabled: true, }, }, Hibernation: &ske.Hibernation{ - Schedules: &[]ske.HibernationSchedule{ + Schedules: []ske.HibernationSchedule{ { - End: new("2"), - Start: new("1"), + End: "2", + Start: "1", Timezone: new("CET"), }, }, }, - Kubernetes: &ske.Kubernetes{ - Version: new("1.2.3"), + Kubernetes: ske.Kubernetes{ + Version: "1.2.3", }, Maintenance: &ske.Maintenance{ - AutoUpdate: &ske.MaintenanceAutoUpdate{ + AutoUpdate: ske.MaintenanceAutoUpdate{ KubernetesVersion: new(true), MachineImageVersion: new(true), }, - TimeWindow: &ske.TimeWindow{ - Start: new(time.Date(0, 1, 2, 3, 4, 5, 6, time.FixedZone("UTC+6:00", 6*60*60))), - End: new(time.Date(10, 11, 12, 13, 14, 15, 0, time.UTC)), + TimeWindow: ske.TimeWindow{ + Start: time.Date(0, 1, 2, 3, 4, 5, 6, time.FixedZone("UTC+6:00", 6*60*60)), + End: time.Date(10, 11, 12, 13, 14, 15, 0, time.UTC), }, }, Network: &ske.Network{ Id: new("nid"), ControlPlane: &ske.V2ControlPlaneNetwork{ - AccessScope: ske.V2ControlPlaneNetworkGetAccessScopeAttributeType(new("SNA")), + AccessScope: ske.ACCESSSCOPE_SNA.Ptr(), }, }, Name: new("name"), - Nodepools: &[]ske.Nodepool{ + Nodepools: []ske.Nodepool{ { - AvailabilityZones: &[]string{"z1", "z2"}, + AvailabilityZones: []string{"z1", "z2"}, Cri: &ske.CRI{ - Name: ske.CRINAME_DOCKER.Ptr(), + Name: new("containerd"), }, Labels: &map[string]string{"k": "v"}, - Machine: &ske.Machine{ - Image: &ske.Image{ - Name: new("os"), - Version: new("os-ver"), + Machine: ske.Machine{ + Image: ske.Image{ + Name: "os", + Version: "os-ver", }, - Type: new("B"), + Type: "B", }, - MaxSurge: new(int64(3)), + MaxSurge: new(int32(3)), MaxUnavailable: nil, - Maximum: new(int64(5)), - Minimum: new(int64(1)), - Name: new("node"), + Maximum: 5, + Minimum: 1, + Name: "node", Taints: nil, - Volume: &ske.Volume{ - Size: new(int64(3)), + Volume: ske.Volume{ + Size: 3, Type: new("type"), }, }, @@ -623,12 +618,12 @@ func TestMapFields(t *testing.T) { "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), - "max_unavailable": types.Int64Null(), + "minimum": types.Int32Value(1), + "maximum": types.Int32Value(5), + "max_surge": types.Int32Value(3), + "max_unavailable": types.Int32Null(), "volume_type": types.StringValue("type"), - "volume_size": types.Int64Value(3), + "volume_size": types.Int32Value(3), "labels": types.MapValueMust( types.StringType, map[string]attr.Value{ @@ -636,7 +631,7 @@ func TestMapFields(t *testing.T) { }, ), "taints": types.ListValueMust(types.ObjectType{AttrTypes: taintTypes}, []attr.Value{}), - "cri": types.StringValue(string(ske.CRINAME_DOCKER)), + "cri": types.StringValue("containerd"), "availability_zones": types.ListValueMust( types.StringType, []attr.Value{ @@ -1258,7 +1253,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1290,7 +1285,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1322,7 +1317,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1354,7 +1349,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1386,7 +1381,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1410,7 +1405,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1434,7 +1429,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStatePreview), @@ -1458,7 +1453,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1482,7 +1477,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1497,8 +1492,8 @@ func TestLatestMatchingMachineVersion(t *testing.T) { nil, "foo", &ske.Image{ - Name: new("foo"), - Version: new("1.19.0"), + Name: "foo", + Version: "1.19.0", }, new("1.19.0"), false, @@ -1509,7 +1504,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1524,8 +1519,8 @@ func TestLatestMatchingMachineVersion(t *testing.T) { nil, "foo", &ske.Image{ - Name: new("bar"), - Version: new("1.19.0"), + Name: "bar", + Version: "1.19.0", }, new("1.20.0"), false, @@ -1536,7 +1531,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1551,8 +1546,8 @@ func TestLatestMatchingMachineVersion(t *testing.T) { new("1.19"), "foo", &ske.Image{ - Name: new("foo"), - Version: new("1.20.0"), + Name: "foo", + Version: "1.20.0", }, new("1.20.0"), false, @@ -1563,7 +1558,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.21.0"), State: new(VersionStateSupported), @@ -1582,8 +1577,8 @@ func TestLatestMatchingMachineVersion(t *testing.T) { new("1.19"), "foo", &ske.Image{ - Name: new("foo"), - Version: new("1.20.0"), + Name: "foo", + Version: "1.20.0", }, new("1.20.0"), true, @@ -1594,7 +1589,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1609,8 +1604,8 @@ func TestLatestMatchingMachineVersion(t *testing.T) { new("1.20"), "foo", &ske.Image{ - Name: new("foo"), - Version: new("1.19.0"), + Name: "foo", + Version: "1.19.0", }, new("1.20.0"), false, @@ -1621,7 +1616,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1645,7 +1640,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{}, + Versions: []ske.MachineImageVersion{}, }, }, new("1.20"), @@ -1675,7 +1670,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: nil, - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1695,7 +1690,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("bar"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1715,7 +1710,7 @@ func TestLatestMatchingMachineVersion(t *testing.T) { []ske.MachineImage{ { Name: new("foo"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("1.20.0"), State: new(VersionStateSupported), @@ -1854,9 +1849,9 @@ func TestGetMaintenanceTimes(t *testing.T) { t.Run(tt.description, func(t *testing.T) { apiResponse := &ske.Cluster{ Maintenance: &ske.Maintenance{ - TimeWindow: &ske.TimeWindow{ - Start: new(tt.startAPI), - End: new(tt.endAPI), + TimeWindow: ske.TimeWindow{ + Start: tt.startAPI, + End: tt.endAPI, }, }, } @@ -1907,25 +1902,25 @@ func TestGetCurrentVersion(t *testing.T) { { "ok", &ske.Cluster{ - Kubernetes: &ske.Kubernetes{ - Version: new("v1.0.0"), + Kubernetes: ske.Kubernetes{ + Version: "v1.0.0", }, - Nodepools: &[]ske.Nodepool{ + Nodepools: []ske.Nodepool{ { - Name: new("foo"), - Machine: &ske.Machine{ - Image: &ske.Image{ - Name: new("foo"), - Version: new("v1.0.0"), + Name: "foo", + Machine: ske.Machine{ + Image: ske.Image{ + Name: "foo", + Version: "v1.0.0", }, }, }, { - Name: new("bar"), - Machine: &ske.Machine{ - Image: &ske.Image{ - Name: new("bar"), - Version: new("v2.0.0"), + Name: "bar", + Machine: ske.Machine{ + Image: ske.Image{ + Name: "bar", + Version: "v2.0.0", }, }, }, @@ -1934,12 +1929,12 @@ func TestGetCurrentVersion(t *testing.T) { new("v1.0.0"), map[string]*ske.Image{ "foo": { - Name: new("foo"), - Version: new("v1.0.0"), + Name: "foo", + Version: "v1.0.0", }, "bar": { - Name: new("bar"), - Version: new("v2.0.0"), + Name: "bar", + Version: "v2.0.0", }, }, false, @@ -1952,30 +1947,30 @@ func TestGetCurrentVersion(t *testing.T) { true, }, { - "nil kubernetes", + "kubernetes empty", &ske.Cluster{ - Kubernetes: nil, + Kubernetes: ske.Kubernetes{}, }, - nil, + new(""), nil, false, }, { - "nil kubernetes version", + "kubernetes version empty", &ske.Cluster{ - Kubernetes: &ske.Kubernetes{ - Version: nil, + Kubernetes: ske.Kubernetes{ + Version: "", }, }, - nil, + new(""), nil, false, }, { "nil nodepools", &ske.Cluster{ - Kubernetes: &ske.Kubernetes{ - Version: new("v1.0.0"), + Kubernetes: ske.Kubernetes{ + Version: "v1.0.0", }, Nodepools: nil, }, @@ -1984,75 +1979,85 @@ func TestGetCurrentVersion(t *testing.T) { false, }, { - "nil nodepools machine", + "empty nodepools machine", &ske.Cluster{ - Kubernetes: &ske.Kubernetes{ - Version: new("v1.0.0"), + Kubernetes: ske.Kubernetes{ + Version: "v1.0.0", }, - Nodepools: &[]ske.Nodepool{ + Nodepools: []ske.Nodepool{ { - Name: new("foo"), - Machine: nil, + Name: "foo", + Machine: ske.Machine{}, }, }, }, new("v1.0.0"), - map[string]*ske.Image{}, + map[string]*ske.Image{ + "foo": { + Name: "", + }, + }, false, }, { - "nil nodepools machine image", + "empty nodepools machine image", &ske.Cluster{ - Kubernetes: &ske.Kubernetes{ - Version: new("v1.0.0"), + Kubernetes: ske.Kubernetes{ + Version: "v1.0.0", }, - Nodepools: &[]ske.Nodepool{ + Nodepools: []ske.Nodepool{ { - Name: new("foo"), - Machine: &ske.Machine{ - Image: nil, + Name: "foo", + Machine: ske.Machine{ + Image: ske.Image{}, }, }, }, }, new("v1.0.0"), - map[string]*ske.Image{}, + map[string]*ske.Image{ + "foo": {}, + }, false, }, { - "nil nodepools machine image name", + "empty nodepools machine image name", &ske.Cluster{ - Kubernetes: &ske.Kubernetes{ - Version: new("v1.0.0"), + Kubernetes: ske.Kubernetes{ + Version: "v1.0.0", }, - Nodepools: &[]ske.Nodepool{ + Nodepools: []ske.Nodepool{ { - Name: new("foo"), - Machine: &ske.Machine{ - Image: &ske.Image{ - Name: nil, + Name: "foo", + Machine: ske.Machine{ + Image: ske.Image{ + Name: "", }, }, }, }, }, new("v1.0.0"), - map[string]*ske.Image{}, + map[string]*ske.Image{ + "foo": { + Name: "", + }, + }, false, }, { "nil nodepools machine image version", &ske.Cluster{ - Kubernetes: &ske.Kubernetes{ - Version: new("v1.0.0"), + Kubernetes: ske.Kubernetes{ + Version: "v1.0.0", }, - Nodepools: &[]ske.Nodepool{ + Nodepools: []ske.Nodepool{ { - Name: new("foo"), - Machine: &ske.Machine{ - Image: &ske.Image{ - Name: new("foo"), - Version: nil, + Name: "foo", + Machine: ske.Machine{ + Image: ske.Image{ + Name: "foo", + Version: "", }, }, }, @@ -2061,8 +2066,8 @@ func TestGetCurrentVersion(t *testing.T) { new("v1.0.0"), map[string]*ske.Image{ "foo": { - Name: new("foo"), - Version: nil, + Name: "foo", + Version: "", }, }, false, @@ -2077,9 +2082,15 @@ func TestGetCurrentVersion(t *testing.T) { } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &skeClientMocked{ - returnError: tt.getClusterFails, - getClusterResp: tt.mockedResp, + client := &ske.DefaultAPIServiceMock{ + GetClusterExecuteMock: new(func(_ ske.ApiGetClusterRequest) (*ske.Cluster, error) { + if tt.getClusterFails { + return nil, &oapierror.GenericOpenAPIError{ + StatusCode: http.StatusInternalServerError, + } + } + return tt.mockedResp, nil + }), } model := &Model{ ProjectId: types.StringValue("pid"), @@ -2259,7 +2270,7 @@ func TestToNetworkPayload(t *testing.T) { &ske.Network{ Id: new("nid"), ControlPlane: &ske.V2ControlPlaneNetwork{ - AccessScope: ske.V2ControlPlaneNetworkGetAccessScopeAttributeType(new("SNA")), + AccessScope: ske.ACCESSSCOPE_SNA.Ptr(), }, }, true, @@ -2425,10 +2436,10 @@ func TestMaintenanceWindow(t *testing.T) { t.Fatalf("cannot parse end date %q: %v", tt.wantEnd, err) } - if expected, actual := wantStart.In(startLocation), *maintenance.TimeWindow.Start; expected != actual { + if expected, actual := wantStart.In(startLocation), maintenance.TimeWindow.Start; expected != actual { t.Errorf("invalid start date. expected %s but got %s", expected, actual) } - if expected, actual := wantEnd.In(endLocation), (*maintenance.TimeWindow.End); expected != actual { + if expected, actual := wantEnd.In(endLocation), (maintenance.TimeWindow.End); expected != actual { t.Errorf("invalid End date. expected %s but got %s", expected, actual) } }) diff --git a/stackit/internal/services/ske/kubeconfig/resource.go b/stackit/internal/services/ske/kubeconfig/resource.go index d7c0907e0..cb208df78 100644 --- a/stackit/internal/services/ske/kubeconfig/resource.go +++ b/stackit/internal/services/ske/kubeconfig/resource.go @@ -28,7 +28,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" ) // Ensure the implementation satisfies the expected interfaces. @@ -312,7 +312,7 @@ func (r *kubeconfigResource) Read(ctx context.Context, req resource.ReadRequest, ctx = tflog.SetField(ctx, "kube_config_id", kubeconfigUUID) ctx = tflog.SetField(ctx, "region", region) - cluster, err := r.client.GetClusterExecute(ctx, projectId, region, clusterName) + cluster, err := r.client.DefaultAPI.GetCluster(ctx, projectId, region, clusterName).Execute() if err != nil { utils.LogError( ctx, @@ -373,7 +373,7 @@ func (r *kubeconfigResource) createKubeconfig(ctx context.Context, model *Model) return fmt.Errorf("creating API payload: %w", err) } // Create new kubeconfig - kubeconfigResp, err := r.client.CreateKubeconfig(ctx, model.ProjectId.ValueString(), model.Region.ValueString(), model.ClusterName.ValueString()).CreateKubeconfigPayload(*payload).Execute() + kubeconfigResp, err := r.client.DefaultAPI.CreateKubeconfig(ctx, model.ProjectId.ValueString(), model.Region.ValueString(), model.ClusterName.ValueString()).CreateKubeconfigPayload(*payload).Execute() if err != nil { return fmt.Errorf("calling API: %w", err) } diff --git a/stackit/internal/services/ske/kubeconfig/resource_test.go b/stackit/internal/services/ske/kubeconfig/resource_test.go index e01c25978..f4f0262f1 100644 --- a/stackit/internal/services/ske/kubeconfig/resource_test.go +++ b/stackit/internal/services/ske/kubeconfig/resource_test.go @@ -7,7 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" ) func TestMapFields(t *testing.T) { diff --git a/stackit/internal/services/ske/provideroptions/kubernetesversions/datasource.go b/stackit/internal/services/ske/provideroptions/kubernetesversions/datasource.go index ccd0e2a82..5d5afe5d0 100644 --- a/stackit/internal/services/ske/provideroptions/kubernetesversions/datasource.go +++ b/stackit/internal/services/ske/provideroptions/kubernetesversions/datasource.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" @@ -131,7 +131,7 @@ func (d *kubernetesVersionsDataSource) Read(ctx context.Context, req datasource. ctx = core.InitProviderContext(ctx) ctx = tflog.SetField(ctx, "region", region) - listProviderOptionsReq := d.client.ListProviderOptions(ctx, region) + listProviderOptionsReq := d.client.DefaultAPI.ListProviderOptions(ctx, region) if !utils.IsUndefined(model.VersionState) { listProviderOptionsReq = listProviderOptionsReq.VersionState(model.VersionState.ValueString()) @@ -191,7 +191,7 @@ func mapFields(_ context.Context, optionsResp *ske.ProviderOptions, model *Model return nil } - kvSlice := *optionsResp.KubernetesVersions + kvSlice := optionsResp.KubernetesVersions kvList := make([]attr.Value, 0, len(kvSlice)) for _, kv := range kvSlice { diff --git a/stackit/internal/services/ske/provideroptions/kubernetesversions/datasource_test.go b/stackit/internal/services/ske/provideroptions/kubernetesversions/datasource_test.go index b095c085a..402af82eb 100644 --- a/stackit/internal/services/ske/provideroptions/kubernetesversions/datasource_test.go +++ b/stackit/internal/services/ske/provideroptions/kubernetesversions/datasource_test.go @@ -8,7 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" ) func TestMapFields(t *testing.T) { @@ -35,7 +35,7 @@ func TestMapFields(t *testing.T) { { name: "multiple versions realistic payload", input: &ske.ProviderOptions{ - KubernetesVersions: &[]ske.KubernetesVersion{ + KubernetesVersions: []ske.KubernetesVersion{ { Version: new("1.31.14"), State: new("deprecated"), @@ -156,7 +156,7 @@ func TestMapFields(t *testing.T) { { name: "mixed fields with nil feature gates and nil state", input: &ske.ProviderOptions{ - KubernetesVersions: &[]ske.KubernetesVersion{ + KubernetesVersions: []ske.KubernetesVersion{ { Version: new("1.32.11"), State: new("supported"), @@ -221,7 +221,7 @@ func TestMapFields(t *testing.T) { { name: "empty kubernetes versions slice", input: &ske.ProviderOptions{ - KubernetesVersions: &[]ske.KubernetesVersion{}, + KubernetesVersions: []ske.KubernetesVersion{}, }, model: &Model{}, expected: &Model{ @@ -235,7 +235,7 @@ func TestMapFields(t *testing.T) { { name: "feature gates empty map", input: &ske.ProviderOptions{ - KubernetesVersions: &[]ske.KubernetesVersion{ + KubernetesVersions: []ske.KubernetesVersion{ { Version: new("1.33.7"), State: new("supported"), @@ -267,7 +267,7 @@ func TestMapFields(t *testing.T) { { name: "nil model", input: &ske.ProviderOptions{ - KubernetesVersions: &[]ske.KubernetesVersion{ + KubernetesVersions: []ske.KubernetesVersion{ { Version: new("1.32.11"), State: new("supported"), diff --git a/stackit/internal/services/ske/provideroptions/machineimages/datasource.go b/stackit/internal/services/ske/provideroptions/machineimages/datasource.go index 8bc09ffa6..4eca7acfe 100644 --- a/stackit/internal/services/ske/provideroptions/machineimages/datasource.go +++ b/stackit/internal/services/ske/provideroptions/machineimages/datasource.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" @@ -151,7 +151,7 @@ func (d *machineImagesDataSource) Read(ctx context.Context, req datasource.ReadR ctx = core.InitProviderContext(ctx) ctx = tflog.SetField(ctx, "region", region) - listProviderOptionsReq := d.client.ListProviderOptions(ctx, region) + listProviderOptionsReq := d.client.DefaultAPI.ListProviderOptions(ctx, region) if !utils.IsUndefined(model.VersionState) { listProviderOptionsReq = listProviderOptionsReq.VersionState(model.VersionState.ValueString()) @@ -200,17 +200,15 @@ func mapFields(ctx context.Context, optionsResp *ske.ProviderOptions, model *Mod // Machine Images miList := make([]attr.Value, 0) if optionsResp.MachineImages != nil { - for _, img := range *optionsResp.MachineImages { + for _, img := range optionsResp.MachineImages { versionsList := make([]attr.Value, 0) if img.Versions != nil { - for _, ver := range *img.Versions { + for _, ver := range img.Versions { // CRI list criList := make([]types.String, 0) - if ver.Cri != nil { - for _, cri := range *ver.Cri { - if cri.Name != nil { - criList = append(criList, types.StringValue(string(*cri.Name.Ptr()))) - } + for _, cri := range ver.Cri { + if cri.Name != nil { + criList = append(criList, types.StringValue(*cri.Name)) } } criVal, diags := types.ListValueFrom(ctx, types.StringType, criList) diff --git a/stackit/internal/services/ske/provideroptions/machineimages/datasource_test.go b/stackit/internal/services/ske/provideroptions/machineimages/datasource_test.go index 71857db90..57bed4d53 100644 --- a/stackit/internal/services/ske/provideroptions/machineimages/datasource_test.go +++ b/stackit/internal/services/ske/provideroptions/machineimages/datasource_test.go @@ -8,8 +8,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/types" - skeutils "github.com/stackitcloud/stackit-sdk-go/core/utils" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" ) func TestMapFields(t *testing.T) { @@ -31,17 +30,17 @@ func TestMapFields(t *testing.T) { { name: "single machine image single version full fields", input: &ske.ProviderOptions{ - MachineImages: &[]ske.MachineImage{ + MachineImages: []ske.MachineImage{ { Name: new("flatcar"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("4230.2.1"), State: new("supported"), ExpirationDate: ×tamp, - Cri: &[]ske.CRI{ + Cri: []ske.CRI{ { - Name: skeutils.Ptr(ske.CRINAME_CONTAINERD), + Name: new("containerd"), }, }, }, @@ -65,7 +64,7 @@ func TestMapFields(t *testing.T) { "cri": types.ListValueMust( types.StringType, []attr.Value{ - types.StringValue(string(ske.CRINAME_CONTAINERD)), + types.StringValue("containerd"), }, ), }), @@ -80,17 +79,17 @@ func TestMapFields(t *testing.T) { { name: "single machine image multiple versions mixed fields", input: &ske.ProviderOptions{ - MachineImages: &[]ske.MachineImage{ + MachineImages: []ske.MachineImage{ { Name: new("flatcar"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("4230.2.1"), State: new("supported"), ExpirationDate: ×tamp, - Cri: &[]ske.CRI{ + Cri: []ske.CRI{ { - Name: skeutils.Ptr(ske.CRINAME_CONTAINERD), + Name: new("containerd"), }, }, }, @@ -121,7 +120,7 @@ func TestMapFields(t *testing.T) { "cri": types.ListValueMust( types.StringType, []attr.Value{ - types.StringValue(string(ske.CRINAME_CONTAINERD)), + types.StringValue("containerd"), }, ), }), @@ -146,17 +145,17 @@ func TestMapFields(t *testing.T) { { name: "multiple machine images mixed versions", input: &ske.ProviderOptions{ - MachineImages: &[]ske.MachineImage{ + MachineImages: []ske.MachineImage{ { Name: new("flatcar"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("4230.2.1"), State: new("deprecated"), ExpirationDate: ×tamp, - Cri: &[]ske.CRI{ + Cri: []ske.CRI{ { - Name: skeutils.Ptr(ske.CRINAME_CONTAINERD), + Name: new("containerd"), }, }, }, @@ -164,9 +163,9 @@ func TestMapFields(t *testing.T) { Version: new("4230.2.3"), State: new("supported"), ExpirationDate: nil, // no expiration - Cri: &[]ske.CRI{ + Cri: []ske.CRI{ { - Name: skeutils.Ptr(ske.CRINAME_CONTAINERD), + Name: new("containerd"), }, }, }, @@ -174,9 +173,9 @@ func TestMapFields(t *testing.T) { Version: new("4459.2.1"), State: new("preview"), ExpirationDate: nil, - Cri: &[]ske.CRI{ + Cri: []ske.CRI{ { - Name: skeutils.Ptr(ske.CRINAME_CONTAINERD), + Name: new("containerd"), }, }, }, @@ -184,13 +183,13 @@ func TestMapFields(t *testing.T) { }, { Name: new("ubuntu"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("2204.20250728.0"), State: new("supported"), ExpirationDate: nil, // empty CRI slice - Cri: &[]ske.CRI{}, + Cri: []ske.CRI{}, }, }, }, @@ -212,7 +211,7 @@ func TestMapFields(t *testing.T) { "cri": types.ListValueMust( types.StringType, []attr.Value{ - types.StringValue(string(ske.CRINAME_CONTAINERD)), + types.StringValue("containerd"), }, ), }), @@ -223,7 +222,7 @@ func TestMapFields(t *testing.T) { "cri": types.ListValueMust( types.StringType, []attr.Value{ - types.StringValue(string(ske.CRINAME_CONTAINERD)), + types.StringValue("containerd"), }, ), }), @@ -234,7 +233,7 @@ func TestMapFields(t *testing.T) { "cri": types.ListValueMust( types.StringType, []attr.Value{ - types.StringValue(string(ske.CRINAME_CONTAINERD)), + types.StringValue("containerd"), }, ), }), @@ -281,7 +280,7 @@ func TestMapFields(t *testing.T) { { name: "empty machine images slice", input: &ske.ProviderOptions{ - MachineImages: &[]ske.MachineImage{}, + MachineImages: []ske.MachineImage{}, }, expected: &Model{ MachineImages: types.ListValueMust( @@ -294,10 +293,10 @@ func TestMapFields(t *testing.T) { { name: "version without cri and without expiration", input: &ske.ProviderOptions{ - MachineImages: &[]ske.MachineImage{ + MachineImages: []ske.MachineImage{ { Name: new("ubuntu"), - Versions: &[]ske.MachineImageVersion{ + Versions: []ske.MachineImageVersion{ { Version: new("2204.20250728.0"), State: new("supported"), diff --git a/stackit/internal/services/ske/utils/util.go b/stackit/internal/services/ske/utils/util.go index 4bf8fa87b..ef4581caa 100644 --- a/stackit/internal/services/ske/utils/util.go +++ b/stackit/internal/services/ske/utils/util.go @@ -6,7 +6,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/stackitcloud/stackit-sdk-go/core/config" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" @@ -28,3 +28,17 @@ func ConfigureClient(ctx context.Context, providerData *core.ProviderData, diags return apiClient } + +func IsEmptyNetwork(network *ske.Network) bool { + if !network.HasId() && !network.HasControlPlane() { + return true + } + return false +} + +func IsEmptyExtension(extension *ske.Extension) bool { + if !extension.HasDns() && !extension.HasAcl() && !extension.HasObservability() { + return true + } + return false +} diff --git a/stackit/internal/services/ske/utils/util_test.go b/stackit/internal/services/ske/utils/util_test.go index a52083ed0..2729e7027 100644 --- a/stackit/internal/services/ske/utils/util_test.go +++ b/stackit/internal/services/ske/utils/util_test.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/diag" sdkClients "github.com/stackitcloud/stackit-sdk-go/core/clients" "github.com/stackitcloud/stackit-sdk-go/core/config" - "github.com/stackitcloud/stackit-sdk-go/services/ske" + ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" @@ -92,3 +92,118 @@ func TestConfigureClient(t *testing.T) { }) } } + +func TestIsEmptyNetwork(t *testing.T) { + tests := []struct { + name string + input *ske.Network + want bool + }{ + { + name: "nil network", + input: nil, + want: true, + }, + { + name: "empty", + input: &ske.Network{}, + want: true, + }, + { + name: "only AdditionalProperties are set", + input: &ske.Network{ + AdditionalProperties: map[string]interface{}{ + "foo": "bar", + }, + }, + want: true, + }, + { + name: "id set", + input: &ske.Network{ + Id: new("network-id"), + }, + want: false, + }, + { + name: "control plane set", + input: &ske.Network{ + ControlPlane: &ske.V2ControlPlaneNetwork{}, + }, + want: false, + }, + { + name: "id and control plane set", + input: &ske.Network{ + Id: new("network-id"), + ControlPlane: &ske.V2ControlPlaneNetwork{ + AccessScope: ske.ACCESSSCOPE_SNA.Ptr(), + }, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsEmptyNetwork(tt.input); got != tt.want { + t.Errorf("IsEmptyNetwork() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestIsEmptyExtension(t *testing.T) { + tests := []struct { + name string + input *ske.Extension + want bool + }{ + { + name: "nil extension", + input: nil, + want: true, + }, + { + name: "empty", + input: &ske.Extension{}, + want: true, + }, + { + name: "only AdditionalProperties are set", + input: &ske.Extension{ + AdditionalProperties: map[string]interface{}{ + "foo": "bar", + }, + }, + want: true, + }, + { + name: "acl set", + input: &ske.Extension{ + Acl: ske.NewACL([]string{"1.1.1.0/24"}, true), + }, + want: false, + }, + { + name: "observability set", + input: &ske.Extension{ + Observability: ske.NewObservability(true, "instance-id"), + }, + want: false, + }, + { + name: "dns set", + input: &ske.Extension{ + Dns: ske.NewDNS(true), + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsEmptyExtension(tt.input); got != tt.want { + t.Errorf("IsEmptyExtension() = %v, want %v", got, tt.want) + } + }) + } +}