Skip to content

Deprecate the ServerMaintenance resource#1001

Closed
nagadeesh-nagaraja wants to merge 5 commits into
ironcore-dev:mainfrom
nagadeesh-nagaraja:SMmove
Closed

Deprecate the ServerMaintenance resource#1001
nagadeesh-nagaraja wants to merge 5 commits into
ironcore-dev:mainfrom
nagadeesh-nagaraja:SMmove

Conversation

@nagadeesh-nagaraja

@nagadeesh-nagaraja nagadeesh-nagaraja commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Fixes #

Summary by CodeRabbit

  • API Updates

    • Deprecated the legacy metal.ironcore.dev/v1alpha1 ServerMaintenance API.
    • Use servermaintenance.metal.ironcore.dev/v1alpha1 for new resources.
  • Behavior Changes

    • Pending resources using the deprecated API are removed for recreation under the new API.
    • Existing in-progress maintenance continues through completion.
  • Documentation

    • Updated migration guidance, workflow details, labels, and deprecated API examples.
  • Bug Fixes

    • Improved handling and tracking of ServerMaintenance resources during server lifecycle operations.

@github-actions github-actions Bot added size/L api-change documentation Improvements or additions to documentation labels Jul 13, 2026
Signed-off-by: Nagadeesh Nagaraja <nagdeesh@gmail.com>
Signed-off-by: Nagadeesh Nagaraja <nagdeesh@gmail.com>
Signed-off-by: Nagadeesh Nagaraja <nagdeesh@gmail.com>
Signed-off-by: Nagadeesh Nagaraja <nagdeesh@gmail.com>
@github-actions github-actions Bot added size/XXL and removed size/L labels Jul 15, 2026
@nagadeesh-nagaraja
nagadeesh-nagaraja marked this pull request as ready for review July 15, 2026 11:00
@nagadeesh-nagaraja
nagadeesh-nagaraja requested a review from a team as a code owner July 15, 2026 11:00
@nagadeesh-nagaraja nagadeesh-nagaraja moved this to In Progress in Roadmap Jul 15, 2026
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

ServerMaintenance in the old API group is deprecated in favor of the maintenance-operator API. Pending deprecated resources are deleted, existing maintenance resources retain cleanup behavior, and controllers/tests are updated to use unstructured resources and external CRDs.

Changes

ServerMaintenance deprecation and migration

Layer / File(s) Summary
API deprecation and migration contract
api/v1alpha1/servermaintenance_types.go, config/crd/bases/..., docs/concepts/servermaintenance.md, go.mod
The old API version is marked deprecated, migration guidance is documented, and the maintenance-operator dependency is added.
Unstructured ServerMaintenance integration
cmd/main.go, internal/controller/index_fields.go, internal/controller/server_controller.go
Manager caching, field indexing, and maintenance lookups use the replacement ServerMaintenance GVK and unstructured field access.
Deprecated reconciler behavior and coverage
internal/controller/servermaintenance_controller.go, internal/controller/servermaintenance_controller_test.go, internal/controller/server_controller_test.go
Pending deprecated objects are deleted, the obsolete server-reference helper is removed, and tests cover InMaintenance cleanup and pending-object handling.
Test environment and controller transition
internal/controller/suite_test.go, internal/webhook/v1alpha1/webhook_suite_test.go, internal/controller/*_test.go
Envtest loads CRDs from the maintenance-operator module, enables unstructured caching, disables dependent controller wiring, and ignores affected legacy tests by default.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ServerMaintenanceReconciler
  participant Server
  Client->>ServerMaintenanceReconciler: Create deprecated ServerMaintenance
  ServerMaintenanceReconciler->>ServerMaintenanceReconciler: Reconcile API-group resource
  ServerMaintenanceReconciler->>Client: Delete Pending resource
  Client->>ServerMaintenanceReconciler: Delete InMaintenance resource
  ServerMaintenanceReconciler->>Server: Clear maintenance reference and LED
  ServerMaintenanceReconciler-->>Client: Complete finalizer cleanup
Loading

Possibly related PRs

Suggested labels: deprecation, chore, area/metal-automation

Suggested reviewers: afritzler, stefanhipfel

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Most of #1013 is addressed, but the requested removal timeline/follow-up plan is not present in the reviewed changes. Add a tracked removal timeline/version and a follow-up issue or plan for deleting the type, CRD, RBAC roles, and controller after migration.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description is incomplete and only contains a placeholder Fixes line instead of the required proposed changes section. Add the required Proposed Changes section with brief bullet points describing the main changes, then keep the Fixes # reference.
✅ Passed checks (2 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed The diff stays focused on ServerMaintenance deprecation and related test, CRD, and docs updates.
Title check ✅ Passed The title clearly summarizes the main change: deprecating the ServerMaintenance resource.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
internal/controller/index_fields.go (1)

61-76: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated ServerMaintenance GVK literal across files.

The same schema.GroupVersionKind{Group: "servermaintenance.metal.ironcore.dev", Version: "v1alpha1", Kind: "ServerMaintenance"} literal is hardcoded independently in both files (and per graph evidence, in internal/controller/suite_test.go too). Extracting a single exported schema.GroupVersionKind var avoids drift if the group/version/kind ever changes.

  • internal/controller/index_fields.go#L61-L76: define a package-level var ServerMaintenanceGVK = schema.GroupVersionKind{...} here and use it when building smObj.
  • cmd/main.go#L385-L412: import and reuse controller.ServerMaintenanceGVK instead of redefining the literal.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/index_fields.go` around lines 61 - 76, Centralize the
ServerMaintenance GVK to prevent duplicated literals: in
internal/controller/index_fields.go#L61-L76, define the exported package-level
ServerMaintenanceGVK and use it when configuring smObj; in
cmd/main.go#L385-L412, import the controller package and reuse
controller.ServerMaintenanceGVK instead of redefining the
schema.GroupVersionKind literal.
internal/controller/suite_test.go (1)

86-100: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Capture stderr from go list -m for better CI diagnostics.

cmd.Output() discards stderr; if module resolution fails (e.g., proxy/module-cache issues in CI), the wrapped error won't show why.

♻️ Proposed fix to include stderr in the error
 func maintenanceOperatorCRDDir() (string, error) {
 	const modulePath = "github.com/ironcore-dev/metal-maintenance-operator"

-	out, err := exec.Command("go", "list", "-m", "-f", "{{.Dir}}", modulePath).Output()
-	if err != nil {
-		return "", fmt.Errorf("failed to resolve module dir for %s: %w", modulePath, err)
-	}
+	cmd := exec.Command("go", "list", "-m", "-f", "{{.Dir}}", modulePath)
+	var stderr bytes.Buffer
+	cmd.Stderr = &stderr
+	out, err := cmd.Output()
+	if err != nil {
+		return "", fmt.Errorf("failed to resolve module dir for %s: %w (stderr: %s)", modulePath, err, stderr.String())
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/suite_test.go` around lines 86 - 100, Update
maintenanceOperatorCRDDir to capture stderr from the go list -m command, using
the command execution API that returns combined output or otherwise preserves
stderr. Include that captured diagnostic output in the wrapped error returned
when module resolution fails.
internal/controller/biossettings_controller_test.go (1)

4-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Five legacy controller test files disabled via //go:build ignore with no tracking reference. All share the same root cause: they're excluded from go build/go test because their controllers still depend on the now-external ServerMaintenance API (per suite_test.go's explanatory comment), but none carry a TODO/issue reference for re-enabling once those controllers migrate — risking silent bit-rot (undetected compile breakage) until someone remembers to lift the tag.

  • internal/controller/biossettings_controller_test.go#L4-L5: add a // TODO(#<issue>): re-enable once BIOSSettings migrates to servermaintenance.metal.ironcore.dev note next to the build tag.
  • internal/controller/biossettingsset_controller_test.go#L4-L5: same tracking note for BIOSSettingsSet.
  • internal/controller/biosversionset_controller_test.go#L4-L5: same tracking note for BIOSVersionSet.
  • internal/controller/bmcsettings_controller_test.go#L4-L5: same tracking note for BMCSettings.
  • internal/controller/bmcsettingsset_controller_test.go#L4-L5: same tracking note for BMCSettingsSet.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/biossettings_controller_test.go` around lines 4 - 5, Add
a TODO with an issue reference beside the //go:build ignore tag in
internal/controller/biossettings_controller_test.go:4-5,
internal/controller/biossettingsset_controller_test.go:4-5,
internal/controller/biosversionset_controller_test.go:4-5,
internal/controller/bmcsettings_controller_test.go:4-5, and
internal/controller/bmcsettingsset_controller_test.go:4-5, identifying that each
test should be re-enabled after its corresponding controller migrates to
servermaintenance.metal.ironcore.dev.
docs/concepts/servermaintenance.md (1)

3-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Deprecation notice lacks a concrete removal target.

"Will be removed in a future release" doesn't give consumers an actionable timeline. The PR's own objective calls for defining a removal timeline; consider naming a target version/date (or linking the tracking issue) so downstream consumers can plan migration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/concepts/servermaintenance.md` around lines 3 - 5, Update the
deprecation notice near the ServerMaintenance API documentation to specify a
concrete removal target, such as the planned release version or date, or link
the relevant tracking issue. Preserve the existing replacement API and operator
guidance.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/main.go`:
- Around line 385-412: Make manager startup tolerate the ServerMaintenance CRD
being absent: update RegisterIndexFields and its startup call path to handle
RESTMapping/informer initialization errors for
servermaintenance.metal.ironcore.dev/v1alpha1 without exiting main, while still
registering the index when the CRD is available. Preserve normal controller
startup and ensure later availability can be handled through the existing
registration/retry mechanism if one exists.

In `@internal/webhook/v1alpha1/webhook_suite_test.go`:
- Around line 68-99: Update the ctrl.NewManager configuration in the webhook
test suite to mirror production’s unstructured ServerMaintenance cache settings:
configure Cache.Options.ByObject for the servermaintenance.metal.ironcore.dev
GVK and enable Client.Options.Cache.Unstructured. Keep RegisterIndexFields using
the same GVK so webhook unstructured List calls exercise the cache-backed
indexer.

---

Nitpick comments:
In `@docs/concepts/servermaintenance.md`:
- Around line 3-5: Update the deprecation notice near the ServerMaintenance API
documentation to specify a concrete removal target, such as the planned release
version or date, or link the relevant tracking issue. Preserve the existing
replacement API and operator guidance.

In `@internal/controller/biossettings_controller_test.go`:
- Around line 4-5: Add a TODO with an issue reference beside the //go:build
ignore tag in internal/controller/biossettings_controller_test.go:4-5,
internal/controller/biossettingsset_controller_test.go:4-5,
internal/controller/biosversionset_controller_test.go:4-5,
internal/controller/bmcsettings_controller_test.go:4-5, and
internal/controller/bmcsettingsset_controller_test.go:4-5, identifying that each
test should be re-enabled after its corresponding controller migrates to
servermaintenance.metal.ironcore.dev.

In `@internal/controller/index_fields.go`:
- Around line 61-76: Centralize the ServerMaintenance GVK to prevent duplicated
literals: in internal/controller/index_fields.go#L61-L76, define the exported
package-level ServerMaintenanceGVK and use it when configuring smObj; in
cmd/main.go#L385-L412, import the controller package and reuse
controller.ServerMaintenanceGVK instead of redefining the
schema.GroupVersionKind literal.

In `@internal/controller/suite_test.go`:
- Around line 86-100: Update maintenanceOperatorCRDDir to capture stderr from
the go list -m command, using the command execution API that returns combined
output or otherwise preserves stderr. Include that captured diagnostic output in
the wrapped error returned when module resolution fails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 88193c72-75a7-4248-8b41-c22542994c0d

📥 Commits

Reviewing files that changed from the base of the PR and between 9bc5784 and 6736065.

⛔ Files ignored due to path filters (2)
  • dist/chart/templates/crd/metal.ironcore.dev_servermaintenances.yaml is excluded by !**/dist/**
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (20)
  • api/v1alpha1/servermaintenance_types.go
  • cmd/main.go
  • config/crd/bases/metal.ironcore.dev_servermaintenances.yaml
  • docs/concepts/servermaintenance.md
  • go.mod
  • internal/controller/biossettings_controller_test.go
  • internal/controller/biossettingsset_controller_test.go
  • internal/controller/biosversion_controller_test.go
  • internal/controller/biosversionset_controller_test.go
  • internal/controller/bmcsettings_controller_test.go
  • internal/controller/bmcsettingsset_controller_test.go
  • internal/controller/bmcversion_controller_test.go
  • internal/controller/bmcversionset_controller_test.go
  • internal/controller/index_fields.go
  • internal/controller/server_controller.go
  • internal/controller/server_controller_test.go
  • internal/controller/servermaintenance_controller.go
  • internal/controller/servermaintenance_controller_test.go
  • internal/controller/suite_test.go
  • internal/webhook/v1alpha1/webhook_suite_test.go

Comment thread cmd/main.go
Comment on lines +385 to +412
smU := &unstructured.Unstructured{}
smU.SetGroupVersionKind(schema.GroupVersionKind{
Group: "servermaintenance.metal.ironcore.dev",
Version: "v1alpha1",
Kind: "ServerMaintenance",
})
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: metricsServerOptions,
WebhookServer: webhookServer,
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "f26702e4.ironcore.dev",
Cache: cache.Options{
ByObject: map[client.Object]cache.ByObject{
smU: {},
},
},
Client: client.Options{
Cache: &client.CacheOptions{
// ServerMaintenance is only available as an unstructured type in this
// repo (its Go types now live in maintenance-operator). Unstructured
// Get/List calls bypass the cache by default, which would send field
// selectors (e.g. spec.serverRef.name) directly to the API server,
// which CRDs don't support. Enable caching so the field indexer is used.
Unstructured: true,
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== cmd/main.go slice ==\n'
sed -n '360,450p' cmd/main.go

printf '\n== internal/controller/index_fields.go ==\n'
cat -n internal/controller/index_fields.go

printf '\n== references to ServerMaintenance ==\n'
rg -n "ServerMaintenance|servermaintenance\.metal\.ironcore\.dev|RegisterIndexFields|IndexField" -S .

Repository: ironcore-dev/metal-operator

Length of output: 50384


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== internal/controller/suite_test.go (relevant slice) ==\n'
sed -n '70,210p' internal/controller/suite_test.go

printf '\n== internal/webhook/v1alpha1/webhook_suite_test.go (relevant slice) ==\n'
sed -n '60,170p' internal/webhook/v1alpha1/webhook_suite_test.go

printf '\n== docs / manifests mentioning maintenance-operator ==\n'
rg -n "maintenance-operator|servermaintenance\.metal\.ironcore\.dev|install.*CRD|CRD.*install" -S README.md docs config internal cmd api .github . || true

Repository: ironcore-dev/metal-operator

Length of output: 19874


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== go env =='
go env GOPATH GOMODCACHE GOPROXY | sed 's/^/  /'

echo '== controller-runtime module versions in go.mod =='
rg -n 'sigs.k8s.io/controller-runtime|k8s.io/apimachinery' go.mod

echo '== locate controller-runtime source in module cache =='
modcache="$(go env GOMODCACHE)"
fd 'indexer.go|cache.go|informer.go|delegating_client.go|field_index' "$modcache/sigs.k8s.io/controller-runtime*" -a | head -n 50

echo '== search for RESTMapping / GetInformer / IndexField in controller-runtime =='
rg -n "RESTMapping|GetInformer|IndexField|Unstructured" "$modcache/sigs.k8s.io/controller-runtime*" -g '*.go' | head -n 200

Repository: ironcore-dev/metal-operator

Length of output: 586


🏁 Script executed:

#!/bin/bash
set -euo pipefail

modcache="$(go env GOMODCACHE)"

echo '== controller-runtime cache entries =='
find "$modcache/sigs.k8s.io" -maxdepth 2 -type d | sed -n '1,80p'

echo '== controller-runtime files of interest =='
find "$modcache/sigs.k8s.io" -path '*controller-runtime*' -type f \( \
  -name '*.go' -o -name 'README*' -o -name '*.md' \
\) | rg 'cache|informer|field|client' | sed -n '1,120p'

Repository: ironcore-dev/metal-operator

Length of output: 8605


🏁 Script executed:

#!/bin/bash
set -euo pipefail

modcache="$(go env GOMODCACHE)"
cr="$modcache/sigs.k8s.io/controller-runtime@v0.24.1"

printf '\n== pkg/cache/internal/informers.go ==\n'
cat -n "$cr/pkg/cache/internal/informers.go" | sed -n '1,260p'

printf '\n== pkg/cache/informer_cache.go ==\n'
cat -n "$cr/pkg/cache/informer_cache.go" | sed -n '1,260p'

printf '\n== pkg/client/apiutil/restmapper.go ==\n'
cat -n "$cr/pkg/client/apiutil/restmapper.go" | sed -n '1,260p'

printf '\n== search for IndexField implementation ==\n'
rg -n "func .*IndexField|IndexField\\(" "$cr/pkg" -g '*.go' | sed -n '1,120p'

Repository: ironcore-dev/metal-operator

Length of output: 35173


🏁 Script executed:

#!/bin/bash
set -euo pipefail

cr="$(go env GOMODCACHE)/sigs.k8s.io/controller-runtime@v0.24.1"

printf '\n== pkg/cache/internal/informers.go (Get and cache creation) ==\n'
rg -n "^func \\(ip \\*Informers\\) Get|^func \\(ip \\*Informers\\) get|newCache|RESTMapping|ResourceFor|mapToGVK|unstructured" "$cr/pkg/cache/internal/informers.go" -n
echo
sed -n '260,520p' "$cr/pkg/cache/internal/informers.go"

printf '\n== cache test around TestIndexFieldDoesNotBlock ==\n'
sed -n '2720,2795p' "$cr/pkg/cache/cache_test.go"

Repository: ironcore-dev/metal-operator

Length of output: 10408


Manager startup now hard-depends on the external maintenance-operator CRD

RegisterIndexFields() eagerly creates the unstructured informer and calls RESTMapping for servermaintenance.metal.ironcore.dev/v1alpha1. If that CRD is not installed yet, manager setup fails and main() exits before any controller starts. Document the install order for maintenance-operator, or make the index registration tolerate a missing CRD instead of crashing startup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/main.go` around lines 385 - 412, Make manager startup tolerate the
ServerMaintenance CRD being absent: update RegisterIndexFields and its startup
call path to handle RESTMapping/informer initialization errors for
servermaintenance.metal.ironcore.dev/v1alpha1 without exiting main, while still
registering the index when the CRD is available. Preserve normal controller
startup and ensure later availability can be handled through the existing
registration/retry mechanism if one exists.

Comment on lines +68 to +99
// maintenanceOperatorCRDDir returns the config/crd/bases directory of the
// github.com/ironcore-dev/metal-maintenance-operator module (e.g. for the
// ServerMaintenance CRD), resolved from the local Go module cache/proxy via
// the go.mod requirement rather than a relative path to a sibling checkout.
func maintenanceOperatorCRDDir() (string, error) {
const modulePath = "github.com/ironcore-dev/metal-maintenance-operator"

out, err := exec.Command("go", "list", "-m", "-f", "{{.Dir}}", modulePath).Output()
if err != nil {
return "", fmt.Errorf("failed to resolve module dir for %s: %w", modulePath, err)
}

dir := strings.TrimSpace(string(out))
if dir == "" {
return "", fmt.Errorf("empty module dir for %s", modulePath)
}

return filepath.Join(dir, "config", "crd", "bases"), nil
}

var _ = BeforeSuite(func() {
ctx, cancel = context.WithCancel(context.TODO())

By("bootstrapping test environment")
maintenanceCRDDir, err := maintenanceOperatorCRDDir()
Expect(err).NotTo(HaveOccurred())

testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")},
CRDDirectoryPaths: []string{
filepath.Join("..", "..", "..", "config", "crd", "bases"),
maintenanceCRDDir,
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Manager here doesn't mirror the unstructured ServerMaintenance cache config added in cmd/main.go.

This block wires up loading the maintenance-operator CRDs into envtest, but the ctrl.NewManager call later in this file (~line 137) still lacks the Cache.Options.ByObject/Client.Options.Cache.Unstructured=true config that cmd/main.go and internal/controller/suite_test.go add for the same unstructured servermaintenance.metal.ironcore.dev GVK. RegisterIndexFields (Line 148) will still succeed at registering the indexer now that the CRD is loaded, but any unstructured List call against this GVK from webhook code would bypass the cache here (unlike production), since that flag controls whether unstructured Get/List go through the cache-backed field indexer or hit the API server directly with an unsupported field selector.

Run this to check whether any webhook code performs field-selector-based List calls on the unstructured ServerMaintenance type (which would surface this gap):

#!/bin/bash
rg -nP -C3 'serverRefField|unstructured\.Unstructured' internal/webhook -g '*.go'
🔧 Suggested fix to mirror cmd/main.go's manager config
+	smU := &unstructured.Unstructured{}
+	smU.SetGroupVersionKind(k8sschema.GroupVersionKind{
+		Group:   "servermaintenance.metal.ironcore.dev",
+		Version: "v1alpha1",
+		Kind:    "ServerMaintenance",
+	})
 	mgr, err := ctrl.NewManager(cfg, ctrl.Options{
 		Scheme: scheme,
 		WebhookServer: webhook.NewServer(webhook.Options{
 			Host:    webhookInstallOptions.LocalServingHost,
 			Port:    webhookInstallOptions.LocalServingPort,
 			CertDir: webhookInstallOptions.LocalServingCertDir,
 		}),
 		LeaderElection: false,
 		Metrics:        metricsserver.Options{BindAddress: "0"},
+		Cache: cache.Options{
+			ByObject: map[client.Object]cache.ByObject{
+				smU: {},
+			},
+		},
+		Client: client.Options{
+			Cache: &client.CacheOptions{
+				Unstructured: true,
+			},
+		},
 	})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/webhook/v1alpha1/webhook_suite_test.go` around lines 68 - 99, Update
the ctrl.NewManager configuration in the webhook test suite to mirror
production’s unstructured ServerMaintenance cache settings: configure
Cache.Options.ByObject for the servermaintenance.metal.ironcore.dev GVK and
enable Client.Options.Cache.Unstructured. Keep RegisterIndexFields using the
same GVK so webhook unstructured List calls exercise the cache-backed indexer.

@afritzler

Copy link
Copy Markdown
Member

I would suggest that in this PR we only mark the resource/types as deprecated and do the removal in a separate one.

@afritzler afritzler changed the title deprecate ServerMaintenance controller and API Deprecate the ServerMaintenance resource Jul 16, 2026
@afritzler

Copy link
Copy Markdown
Member

Can we please only do the deprecation of the resource in this PR similar to: #1019 The migration logic (deletion etc.) and a smooth transition will be the next PR. For version v0.8.0 we can then remove the types and controller code.

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:shortName=sm
// +kubebuilder:deprecatedversion:warning="metal.ironcore.dev/v1alpha1 ServerMaintenance is deprecated; use servermaintenance.metal.ironcore.dev/v1alpha1 instead"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave out the alternative usage.

Comment thread cmd/main.go
Comment on lines +385 to +390
smU := &unstructured.Unstructured{}
smU.SetGroupVersionKind(schema.GroupVersionKind{
Group: "servermaintenance.metal.ironcore.dev",
Version: "v1alpha1",
Kind: "ServerMaintenance",
})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That part should be not in this PR.

Comment thread cmd/main.go
Comment on lines +398 to +412
Cache: cache.Options{
ByObject: map[client.Object]cache.ByObject{
smU: {},
},
},
Client: client.Options{
Cache: &client.CacheOptions{
// ServerMaintenance is only available as an unstructured type in this
// repo (its Go types now live in maintenance-operator). Unstructured
// Get/List calls bypass the cache by default, which would send field
// selectors (e.g. spec.serverRef.name) directly to the API server,
// which CRDs don't support. Enable caching so the field indexer is used.
Unstructured: true,
},
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should only do the deprecation announcement in this PR.

Comment on lines +4 to +5
//go:build ignore

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should still keep the current codeline + tests intact.

Comment on lines +61 to +68
smObj := &unstructured.Unstructured{}
smObj.SetGroupVersionKind(schema.GroupVersionKind{
Group: "servermaintenance.metal.ironcore.dev",
Version: "v1alpha1",
Kind: "ServerMaintenance",
})
if err := indexer.IndexField(ctx, smObj, serverRefField, func(rawObj client.Object) []string {
item, ok := rawObj.(*unstructured.Unstructured)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No functional changes on the indexing needed here.

@afritzler

Copy link
Copy Markdown
Member

Closing in favor of #1024

@afritzler afritzler closed this Jul 16, 2026
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Roadmap Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-change deprecation documentation Improvements or additions to documentation size/XXL

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants