Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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: 0 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ linters:
- stylecheck
- tagalign
- testifylint
- tenv
Comment thread
piepmatz marked this conversation as resolved.
- typecheck
- unconvert
- unparam
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the manager binary
FROM golang:1.24.7 AS builder
FROM golang:1.25.4 AS builder
ARG TARGETOS
ARG TARGETARCH

Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ If you need help with CAPIC, please visit the [#cluster-api-ionoscloud][slack] c

## Compatibility

### Go Version

This provider requires **Go 1.25 or newer**. The exact version is specified in `go.mod`.
Comment thread
piepmatz marked this conversation as resolved.

### Cluster API Versions

This provider's versions are compatible with the following versions of Cluster API:
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/ionos-cloud/cluster-api-provider-ionoscloud

go 1.24.7
go 1.25

require (
github.com/go-logr/logr v1.4.3
Expand Down
2 changes: 1 addition & 1 deletion internal/service/cloud/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ func (s *Service) removeNICFromFailoverGroup(

// Found the NIC, remove it from the failover group
log.V(4).Info("Found NIC in failover group", "nicID", nicID)
ipFailoverConfig = append(ipFailoverConfig[:index], ipFailoverConfig[index+1:]...)
ipFailoverConfig = slices.Delete(ipFailoverConfig, index, index+1)
props := sdk.LanProperties{IpFailover: &ipFailoverConfig}

log.V(4).Info("Patching LAN failover group to remove NIC", "nicID", nicID)
Expand Down
42 changes: 33 additions & 9 deletions internal/util/locker/locker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import (
"context"
"sync"
"testing"
"testing/synctest"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -64,11 +64,12 @@ func TestLockerLock(t *testing.T) {

require.EqualValues(t, 0, lwc.count())

var wg sync.WaitGroup
chDone := make(chan struct{})
go func(t *testing.T) {
assert.NoError(t, l.Lock(context.Background(), "test"))
wg.Go(func() {
require.NoError(t, l.Lock(context.Background(), "test"))
close(chDone)
}(t)
})
Comment thread
piepmatz marked this conversation as resolved.
Outdated

chWaiting := make(chan struct{})
go func() {
Expand Down Expand Up @@ -119,13 +120,11 @@ func TestLockerConcurrency(t *testing.T) {

var wg sync.WaitGroup
for range 10_000 {
wg.Add(1)
go func(t *testing.T) {
assert.NoError(t, l.Lock(context.Background(), "test"))
wg.Go(func() {
require.NoError(t, l.Lock(context.Background(), "test"))
Comment thread
piepmatz marked this conversation as resolved.
Outdated
// If there is a concurrency issue, it will very likely become visible here.
l.Unlock("test")
wg.Done()
}(t)
})
}

withTimeout(t, wg.Wait)
Expand Down Expand Up @@ -160,3 +159,28 @@ func TestLockerContextDeadlineExceeded(t *testing.T) {

require.NotPanics(t, func() { l.Unlock("test") })
}

// TestLockerConcurrencyWithSynctest uses testing/synctest for deterministic concurrent testing.
func TestLockerConcurrencyWithSynctest(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
l := New()

var wg sync.WaitGroup
// Use a smaller number for synctest to keep test execution time reasonable
for range 100 {
wg.Go(func() {
require.NoError(t, l.Lock(context.Background(), "test"))
// If there is a concurrency issue, it will very likely become visible here.
l.Unlock("test")
})
}

// Wait for all goroutines to complete
wg.Wait()
// Ensure all goroutines in the bubble are durably blocked or finished
synctest.Wait()

// Since everything has unlocked the map should be empty.
require.Empty(t, l.locks)
})
}
Comment thread
piepmatz marked this conversation as resolved.
Outdated
8 changes: 3 additions & 5 deletions scope/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,10 +365,8 @@ func TestCurrentRequestByDatacenterAccessors(t *testing.T) {
// If there is a concurrency issue, it will very likely become visible here.
var wg sync.WaitGroup
for i := range 10_000 {
wg.Add(1)
go func(t *testing.T, id string) {
defer wg.Done()

id := strconv.Itoa(i)
wg.Go(func() {
req, exists := cluster.GetCurrentRequestByDatacenter(id)
assert.False(t, exists)
assert.Zero(t, req)
Expand All @@ -386,7 +384,7 @@ func TestCurrentRequestByDatacenterAccessors(t *testing.T) {
req, exists = cluster.GetCurrentRequestByDatacenter(id)
assert.False(t, exists)
assert.Zero(t, req)
}(t, strconv.Itoa(i))
})
}

wg.Wait()
Expand Down
Loading