Skip to content

feat: upgrade cluster-api to v1.9.11 with v1beta2 conditions#352

Closed
schegi wants to merge 31 commits into
mainfrom
feat/upgrade-cluster-api-v1.9.11
Closed

feat: upgrade cluster-api to v1.9.11 with v1beta2 conditions#352
schegi wants to merge 31 commits into
mainfrom
feat/upgrade-cluster-api-v1.9.11

Conversation

@schegi

@schegi schegi commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Bumps sigs.k8s.io/cluster-api v1.8.12 → v1.9.11, controller-runtime v0.18.7 → v0.19.6, and k8s.io packages v0.30.x → v0.31.3
  • Adopts v1beta2 conditions API on both IonosCloudCluster and IonosCloudMachine (new V1Beta2 status field + GetV1Beta2Conditions/SetV1Beta2Conditions methods); migrates all 6 v1beta1 call sites
  • Removes deprecated sigs.k8s.io/cluster-api/errors usage (FailureReason/FailureMessage fields and dead HasFailed() code)
  • Fixes predicate signatures (ResourceNotPaused, ClusterUnpaused now require scheme argument)
  • Updates e2e config CAPI component URLs to v1.9.11

Test Plan

  • Bump cluster-api v1.8.12 → v1.9.11 and controller-runtime v0.18.7 → v0.19.6
  • Add v1beta2 conditions API (V1Beta2 status field + Get/SetV1Beta2Conditions) to IonosCloudCluster and IonosCloudMachine
  • Remove deprecated FailureReason/FailureMessage fields and dead HasFailed() code
  • Migrate all conditions call sites from v1beta1 (MarkTrue/MarkFalse) to v1beta2 (conditions.Set)
  • Fix predicate signatures (ResourceNotPaused, ClusterUnpaused now require scheme argument)
  • Regenerate deepcopy and CRD manifests
  • Update e2e config CAPI component URLs to v1.9.11
  • Add meaningful Message fields to conditions.Set calls (CAPI v1beta2 best practice)

Merge

3 PRs in total (merge in that order, maybe release inbetween):

  1. v1.8 -> v1.9, this PR
  2. v1.9 -> v1.10 feat: upgrade cluster-api to v1.10.10 #353
  3. v1.10 -> v1.11 chore: upgrade cluster-api to v1.11.7 #354

schegi and others added 16 commits April 1, 2026 17:21
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ated FailureReason/FailureMessage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace v1beta1 conditions import with v1beta2 alias and update PatchObject
to use SetSummaryCondition and WithOwnedV1Beta2Conditions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ions to v1beta2

Update IonosCloudClusterReconciler to use the new predicate signatures
(scheme + logger) and replace conditions.MarkTrue with conditions.Set
using metav1.Condition for compatibility with cluster-api v1beta2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…HasFailed guard

Replace conditions import with v1beta2 alias, remove the dead HasFailed guard
(method removed in Task 7), and replace MarkFalse calls with conditions.Set
using metav1.Condition structs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Regenerate mocks after interface updates (import ordering change)
- Fix ionoscloudmachine_types_test.go: remove FailureReason/FailureMessage
  references removed from IonosCloudMachineStatus in v1.9 upgrade
- Update .golangci.yml: extend comment-spacings exclusion to allow
  //+listType and //+listMapKey controller-gen markers
- Apply gofmt/gci formatting fixes (blank line removal in machine_test.go)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@schegi

schegi commented Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot review this PR

Copilot AI commented Apr 2, 2026

Copy link
Copy Markdown

@copilot review this PR

I reviewed the PR. The upgrade is correctly implemented — all CI checks pass (Lint, Test, Verify, Build, Container Image, Codespell, License), and all unit/integration tests pass.

Changes reviewed:

  • sigs.k8s.io/cluster-api v1.8.12 → v1.9.11, controller-runtime v0.18.7 → v0.19.6, k8s.io packages v0.30.x → v0.31.3
  • ✅ v1beta2 conditions API correctly added (V1Beta2 status field + GetV1Beta2Conditions/SetV1Beta2Conditions) to both IonosCloudCluster and IonosCloudMachine
  • ✅ All 4 v1beta1 call sites correctly migrated from MarkTrue/MarkFalse to conditions.Set with metav1.Condition
  • ✅ Deprecated FailureReason/FailureMessage fields and dead HasFailed() code correctly removed
  • ✅ Predicate signatures correctly fixed (ResourceNotPaused, ClusterUnpaused now accept a scheme argument)
  • importas alias for sigs.k8s.io/cluster-api/util/conditions/v1beta2 properly configured
  • ✅ CRD manifests correctly regenerated with v1beta2 conditions nested object and failureReason/failureMessage removed
  • ✅ e2e config URLs updated to v1.9.11

One improvement applied (commit 4b756f2): The conditions.Set calls were missing the Message field. Per CAPI v1beta2 conventions (and mirroring how CAPI core itself always populates this field), I added descriptive messages:

  • "Cluster infrastructure is ready" for ClusterReady=True
  • "Waiting for cluster infrastructure to become ready" for MachineProvisioned=False
  • "Waiting for bootstrap data to become available" for MachineProvisioned=False
  • "Machine has been provisioned successfully" for MachineProvisioned=True

Note on backward compatibility: The v1beta1 Status.Conditions field is kept in the API but is no longer populated by the controllers (v1beta2 conditions are used exclusively). Existing v1beta1 conditions on clusters/machines will be cleared on the next reconcile after upgrade, as the patch helper still owns ReadyCondition (v1beta1) via WithOwnedConditions. This is an intentional migration design — worth documenting in the PR or a migration guide.

@schegi schegi marked this pull request as ready for review April 2, 2026 20:30
@schegi schegi requested a review from piepmatz as a code owner April 2, 2026 20:30
Copilot AI review requested due to automatic review settings April 2, 2026 20:30
Add v1beta1 condition writes alongside every v1beta2 conditions.Set()
call, matching the pattern used by CAPI's own controllers. The patch
helper treats both condition systems independently with no auto-mirroring.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace string(clusterv1.ReadyCondition) with the dedicated
clusterv1.ReadyV1Beta2Condition constant in SetSummaryCondition
and WithOwnedV1Beta2Conditions for semantic clarity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@piepmatz

piepmatz commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

As all this v1beta1 vs v1beta2 is quite a hassle, I read through https://github.com/kubernetes-sigs/cluster-api/blob/4a2e16a3d71d99a923b1f7f3a3efe03c299665fb/docs/proposals/20240916-improve-status-in-CAPI-resources.md.

this proposal is not going to change the fact that the Cluster API contract does not require providers to implement conditions

We have and want conditions, but good to point that out again.

Each provider can implement changes described in the following paragraphs at its own pace, but the transition must be completed before v1beta1 removal (tentative Aug 2026). [...] Starting from the CAPI release when v1beta1 removal will happen (tentative Aug 2026), providers which are implementing the v1beta1 contract will stop to work (they will work only with older versions of Cluster API).

That's soon.

Providers implementing conditions won't be required to do the transition from custom Cluster API Condition type to Kubernetes metav1.Conditions type (but this transition is recommended because it improves the consistency of each provider with Kubernetes, Cluster API and the ecosystem). [...] However, providers choosing to keep using Cluster API custom conditions should be aware that starting from the CAPI release when v1beta1 removal will happen (tentative Aug 2026), the Cluster API project will remove the Cluster API condition type, the util/conditions package, the code handling conditions in util/patch.Helper and everything related to the custom Cluster API v1beta.Condition type. (in other words, Cluster API custom condition must be replaced by provider's own custom conditions).

So even the transition is optional. But we want the transition, of course.

The V1Beta2 struct is going to be added to in v1beta1 types in order to provide a preview of changes coming with the v1beta2 types, but without impacting the semantic of existing fields. Fields in the V1Beta2 will be promoted to status top level fields in the v1beta2 types.

A preview is nice. And CAPI shipped it long before that v1beta2 switch, so it made sense.

The Deprecated struct is going to exist in v1beta2 types only until v1beta1 removal (9 months or 3 minor releases after v1beta2 is released/v1beta1 is deprecated, whichever is longer). Fields in this struct are used for supporting down conversions, thus providing users relying on v1beta1 APIs additional buffer time to pick up the new changes.

So going the same way as CAPI would not only require us to add that V1Beta2 struct, but even a Deprecated one later on. You added it in #354 for CAPI 1.11.

the contract only defines expected names for fields in a resources at YAML/JSON level

The name of the conditions field doesn't change between v1beta1 and v1beta2, just the severity is removed and the reason field will be required.

Given that

  • as an infrastructure provider we are not bound to any condition contract
  • a preview doesn't make sense anymore with only few months remaining till August
  • the difference between v1beta1 and v1beta2 conditions is quite small on the JSON level

I propose we keep it simple and just change the conditions to v1beta2/metav1 directly, without any intermediate steps. That has also worked fine in one of our internal projects when updating the CAPI libs to v1.10.

We bump our minor version, point it out in the release notes and that's it.

schegi and others added 6 commits April 9, 2026 13:11
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ter and machine types

Remove backwards compatibility with the old v1beta1 condition system by replacing
clusterv1.Conditions with []metav1.Condition directly in Status.Conditions, deleting
the V1Beta2 nested structs, and removing the old GetConditions/SetConditions accessors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
schegi and others added 2 commits April 9, 2026 14:04
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- go.opentelemetry.io/otel/sdk v1.41.0 -> v1.43.0 (CVE-2026-39883)
- github.com/cloudflare/circl v1.6.1 -> v1.6.3 (CVE-2026-1229)
- github.com/go-viper/mapstructure/v2 v2.2.1 -> v2.4.0 (CVE-2025-11065)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@schegi

schegi commented Apr 9, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Review

@sonarqubecloud

sonarqubecloud Bot commented Apr 9, 2026

Copy link
Copy Markdown

Copilot AI commented Apr 9, 2026

Copy link
Copy Markdown

Please also update the README at https://github.com/ionos-cloud/cluster-api-provider-ionoscloud?tab=readme-ov-file#cluster-api-versions

Done in commit e1f4784. Added a new column for Cluster API v1.9 and a new row for CAPIC v0.7 to the compatibility table.

@copilot Review

Review complete. The PR is in good shape. Here's a summary of the current state:

Dependencies:

  • sigs.k8s.io/cluster-api v1.9.11 (latest v1.9.x patch)
  • sigs.k8s.io/controller-runtime v0.19.7 (latest v0.19.x patch, just bumped in e1f4784)
  • k8s.io/api|apimachinery|client-go v0.31.14 (latest v0.31.x patch)

Conditions migration:

  • Status.Conditions flattened to []metav1.Condition in both IonosCloudCluster and IonosCloudMachine — no nested V1Beta2 struct, no dual-write
  • ✅ Only GetV1Beta2Conditions/SetV1Beta2Conditions interface methods are implemented (v1beta1 GetConditions/SetConditions removed)
  • ✅ All condition write sites use conditions.Set with metav1.Condition (v1beta2 package only)
  • SetSummaryCondition uses clusterv1.ReadyV1Beta2Condition; patch helper uses only WithOwnedV1Beta2Conditions

Cleanup:

  • FailureReason/FailureMessage fields and HasFailed() removed
  • ✅ Predicate signatures fixed (ResourceNotPaused, ClusterUnpaused with scheme)
  • ✅ CRD manifests regenerated with metav1.Condition schema (listType=map, listMapKey=type)
  • ✅ deepcopy regenerated correctly

Tests:

  • ✅ All unit tests pass; ionoscloudmachine_types_test.go and ionoscloudcluster_types_test.go updated to use v1beta2 API and test GetV1Beta2Conditions/SetV1Beta2Conditions

README:

  • ✅ CAPI versions table updated with CAPIC v0.7 / CAPI v1.9 row (commit e1f4784)

One minor note: the go.mod has go 1.25.0 (with patch) while the Dockerfile and image.yaml may reference a slightly different Go version — not a blocking issue for this PR.

@piepmatz

piepmatz commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

For the record: We decided to shuffle the PRs a bit. The update to CAPI v1.9 will be extracted from the PR, so that we'll have only the switch of the conditions to metav1 plus the corresponding helpers from the v1beta2 packages in here.

Merge and tag order will be the following then:

@schegi schegi closed this Apr 15, 2026
@schegi schegi mentioned this pull request Apr 15, 2026
5 tasks
@gauravgahlot gauravgahlot deleted the feat/upgrade-cluster-api-v1.9.11 branch May 29, 2026 08:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants