Skip to content
Merged
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
1 change: 1 addition & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ linters:
- importas
- ineffassign
- misspell
- modernize
- nakedret
- noctx
- nolintlint
Expand Down
36 changes: 18 additions & 18 deletions docs/machine-class.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ A MachineClass defines how STACKIT servers should be created. The ProviderSpec i

## ProviderSpec Fields

| Field | Type | Required | Description |
| --------------------- | ---------------------- | -------- | ------------------------------------------------------------- |
| `region` | string | Yes | STACKIT region (e.g., "eu01", "eu02"). |
| `machineType` | string | Yes | STACKIT server type (e.g., "c2i.2", "m2i.8"). |
| `imageId` | string | Yes\* | Image UUID. Required unless `bootVolume.source` is specified. |
| `labels` | map[string]string | No | Labels for server identification. |
| `networking` | NetworkingSpec | Yes | Network configuration (either `networkId` or `nicIds`). |
| `allowedAddresses` | []string | No | CIDR ranges allowed for anti-spoofing bypass. |
| `securityGroups` | []string | No | Security group UUIDs. |
| `userData` | string | No | Cloud-init user data (overrides Secret.userData). |
| `bootVolume` | BootVolumeSpec | No | Boot disk configuration. |
| `volumes` | []string | No | UUIDs of existing volumes to attach. |
| `keypairName` | string | No | SSH keypair name. |
| `availabilityZone` | string | No | Availability zone (e.g., "eu01-1"). |
| `affinityGroup` | string | No | UUID of affinity group. |
| `serviceAccountMails` | []string | No | Service account emails (max 1). |
| `agent` | AgentSpec | No | STACKIT agent configuration. |
| `metadata` | map[string]interface{} | No | Freeform metadata. |
| Field | Type | Required | Description |
| --------------------- | ----------------- | -------- | ------------------------------------------------------------- |
| `region` | string | Yes | STACKIT region (e.g., "eu01", "eu02"). |
| `machineType` | string | Yes | STACKIT server type (e.g., "c2i.2", "m2i.8"). |
| `imageId` | string | Yes\* | Image UUID. Required unless `bootVolume.source` is specified. |
| `labels` | map[string]string | No | Labels for server identification. |
| `networking` | NetworkingSpec | Yes | Network configuration (either `networkId` or `nicIds`). |
| `allowedAddresses` | []string | No | CIDR ranges allowed for anti-spoofing bypass. |
| `securityGroups` | []string | No | Security group UUIDs. |
| `userData` | string | No | Cloud-init user data (overrides Secret.userData). |
| `bootVolume` | BootVolumeSpec | No | Boot disk configuration. |
| `volumes` | []string | No | UUIDs of existing volumes to attach. |
| `keypairName` | string | No | SSH keypair name. |
| `availabilityZone` | string | No | Availability zone (e.g., "eu01-1"). |
| `affinityGroup` | string | No | UUID of affinity group. |
| `serviceAccountMails` | []string | No | Service account emails (max 1). |
| `agent` | AgentSpec | No | STACKIT agent configuration. |
| `metadata` | map[string]any | No | Freeform metadata. |

## NetworkingSpec

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/stackitcloud/machine-controller-manager-provider-stackit

go 1.25.0
go 1.26.1

require (
github.com/gardener/machine-controller-manager v0.61.2
Expand Down
10 changes: 5 additions & 5 deletions pkg/client/helper.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package client

// convertLabelsToSDK converts map[string]string to *map[string]interface{} for SDK
func convertLabelsToSDK(labels map[string]string) map[string]interface{} {
// convertLabelsToSDK converts map[string]string to *map[string]any for SDK
func convertLabelsToSDK(labels map[string]string) map[string]any {
if labels == nil {
return nil
}

result := make(map[string]interface{}, len(labels))
result := make(map[string]any, len(labels))
for k, v := range labels {
result[k] = v
}
return result
}

// convertLabelsFromSDK converts *map[string]interface{} from SDK to map[string]string
// convertLabelsFromSDK converts *map[string]any from SDK to map[string]string
//
//nolint:gocritic // SDK requires *map
func convertLabelsFromSDK(labels *map[string]interface{}) map[string]string {
func convertLabelsFromSDK(labels *map[string]any) map[string]string {
if labels == nil {
return nil
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/client/sdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ var _ = Describe("SDK Type Conversion Helpers", func() {
Describe("convertLabelsFromSDK", func() {
Context("with valid SDK labels", func() {
It("should convert SDK labels to string map", func() {
sdkLabels := map[string]interface{}{
sdkLabels := map[string]any{
"app": "web-server",
"team": "platform",
}
Expand All @@ -153,7 +153,7 @@ var _ = Describe("SDK Type Conversion Helpers", func() {
})

It("should convert empty SDK labels map", func() {
sdkLabels := map[string]interface{}{}
sdkLabels := map[string]any{}

result := convertLabelsFromSDK(&sdkLabels)

Expand All @@ -162,7 +162,7 @@ var _ = Describe("SDK Type Conversion Helpers", func() {
})

It("should skip non-string values", func() {
sdkLabels := map[string]interface{}{
sdkLabels := map[string]any{
"app": "web-server",
"count": 42, // not a string
"enabled": true, // not a string
Expand All @@ -180,7 +180,7 @@ var _ = Describe("SDK Type Conversion Helpers", func() {
})

It("should handle nil values in map", func() {
sdkLabels := map[string]interface{}{
sdkLabels := map[string]any{
"app": "web-server",
"team": nil,
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/client/stackit.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type CreateServerRequest struct {
AffinityGroup string `json:"affinityGroup,omitempty"`
ServiceAccountMails []string `json:"serviceAccountMails,omitempty"`
Agent *AgentRequest `json:"agent,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}

// ServerNetworkingRequest represents the networking configuration for a server
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/apis/provider_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ type ProviderSpec struct {
// Metadata is a generic JSON object for storing arbitrary key-value pairs
// Optional field. Can be used to store custom metadata that doesn't fit into other fields
// Example: {"environment": "production", "cost-center": "12345"}
Metadata map[string]interface{} `json:"metadata,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}

// AgentSpec defines the STACKIT agent configuration for a server
Expand Down
8 changes: 4 additions & 4 deletions pkg/provider/apis/validation/validation_fields_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,13 @@ var _ = Describe("ValidateProviderSpecNSecret", func() {
})

It("should succeed with empty metadata", func() {
providerSpec.Metadata = map[string]interface{}{}
providerSpec.Metadata = map[string]any{}
errors := ValidateProviderSpecNSecret(providerSpec, secret)
Expect(errors).To(BeEmpty())
})

It("should succeed with valid metadata", func() {
providerSpec.Metadata = map[string]interface{}{
providerSpec.Metadata = map[string]any{
"environment": "production",
"cost-center": "12345",
"owner": "team-a",
Expand All @@ -267,8 +267,8 @@ var _ = Describe("ValidateProviderSpecNSecret", func() {
})

It("should succeed with nested metadata objects", func() {
providerSpec.Metadata = map[string]interface{}{
"tags": map[string]interface{}{
providerSpec.Metadata = map[string]any{
"tags": map[string]any{
"env": "prod",
"tier": "backend",
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (p *Provider) createServerRequest(req *driver.CreateMachineRequest, provide
// DeleteOnTermination defaults to false in the IaaS API
// unless explicitly disabled, bootVolumes should always be cleaned up automatically
// otherwise this produces many orphaned volumes since node rolls happen frequently in k8s
DeleteOnTermination: ptr.To(ptr.Deref(providerSpec.BootVolume.DeleteOnTermination, true)),
DeleteOnTermination: new(ptr.Deref(providerSpec.BootVolume.DeleteOnTermination, true)),
PerformanceClass: providerSpec.BootVolume.PerformanceClass,
Size: providerSpec.BootVolume.Size,
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/provider/create_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ var _ = Describe("CreateMachine", func() {
NetworkID: "770e8400-e29b-41d4-a716-446655440000",
},
ImageID: "12345678-1234-1234-1234-123456789abc",
Metadata: map[string]interface{}{
Metadata: map[string]any{
"environment": "production",
"cost-center": "12345",
"count": 42,
Expand Down
5 changes: 1 addition & 4 deletions pkg/spi/spi.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ package spi

// SessionProviderInterface provides an interface to deal with cloud provider session
// Example interfaces are listed below.
type SessionProviderInterface interface {
// NewSession(*corev1.Secret, string) (*session.Session, error)
// NewEC2API(*session.Session) ec2iface.EC2API
}
type SessionProviderInterface any

// PluginSPIImpl is the real implementation of SPI interface that makes the calls to the provider SDK.
type PluginSPIImpl struct{}
10 changes: 5 additions & 5 deletions test/e2e/e2e_labels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,12 +479,12 @@ spec:
output, err := cmd.CombinedOutput()
Expect(err).NotTo(HaveOccurred())

var machineData map[string]interface{}
var machineData map[string]any
err = json.Unmarshal(output, &machineData)
Expect(err).NotTo(HaveOccurred())

// Extract spec.providerID
spec, ok := machineData["spec"].(map[string]interface{})
spec, ok := machineData["spec"].(map[string]any)
Expect(ok).To(BeTrue())
providerID, ok := spec["providerID"].(string)
Expect(ok).To(BeTrue())
Expand All @@ -496,16 +496,16 @@ spec:
output, err = cmd.CombinedOutput()
Expect(err).NotTo(HaveOccurred())

var machineClassData map[string]interface{}
var machineClassData map[string]any
err = json.Unmarshal(output, &machineClassData)
Expect(err).NotTo(HaveOccurred())

providerSpecRaw, ok := machineClassData["providerSpec"].(map[string]interface{})
providerSpecRaw, ok := machineClassData["providerSpec"].(map[string]any)
Expect(ok).To(BeTrue())

// Verify labels field is either missing or empty
if labelsField, exists := providerSpecRaw["labels"]; exists {
labels, ok := labelsField.(map[string]interface{})
labels, ok := labelsField.(map[string]any)
if ok {
Expect(labels).To(BeEmpty(), "Labels field should be empty if present")
}
Expand Down