Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new PodDisruptionBudget (PDB) primitive to the operator component framework, following the existing static-primitive patterns (e.g., ConfigMap) and providing a typed mutation/editor surface plus documentation and an end-to-end example.
Changes:
- Introduces
pkg/primitives/pdb(resource, builder, mutator, flavors) for managingpolicy/v1PodDisruptionBudgets. - Adds a new typed editor
PodDisruptionBudgetSpecEditorunderpkg/mutation/editorsto support structured PDB spec mutations. - Adds documentation (
docs/primitives/pdb.md, updatesdocs/primitives.md) and a runnable example (examples/pdb-primitive/*).
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pkg/primitives/pdb/resource.go | Static PDB primitive resource wrapper over the generic static resource. |
| pkg/primitives/pdb/builder.go | Fluent builder for configuring PDB field applicator, flavors, mutations, extractors. |
| pkg/primitives/pdb/mutator.go | Plan-and-apply mutator with metadata/spec edit categories. |
| pkg/primitives/pdb/flavors.go | Field-application flavors for preserving current labels/annotations. |
| pkg/primitives/pdb/*_test.go | Unit tests for builder/mutator/flavors behavior. |
| pkg/mutation/editors/pdbspec.go | New typed editor for PodDisruptionBudgetSpec. |
| pkg/mutation/editors/pdbspec_test.go | Unit tests for the new PDB spec editor. |
| docs/primitives/pdb.md | New primitive documentation page for PDB. |
| docs/primitives.md | Adds PDB primitive and editor to the docs index tables. |
| examples/pdb-primitive/* | New runnable example demonstrating the PDB primitive in a fake-client reconcile loop. |
Claude Review Cycle 1 CompleteAddressed:
Intentionally ignored:
Verification:
|
sourcehawk
left a comment
There was a problem hiding this comment.
Cycle 1: Copilot review comments addressed. Re-requesting review.
Claude Review Cycle 2 CompleteAddressed:
Intentionally ignored:
|
|
approved |
Claude Review Cycle 1 CompleteAddressed:
Intentionally ignored: <!-- claude-review-cycle --> |
Claude Review Cycle 1 CompleteAddressed:
Intentionally ignored:
<!-- claude-review-cycle --> |
Implement the PDB primitive as a Static resource following the ConfigMap pattern. Includes builder, resource, mutator (plan-and-apply with metadata and spec edit categories), field application flavors, and the typed PodDisruptionBudgetSpecEditor for mutation surfaces. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Demonstrates PodDisruptionBudget management with feature-gated mutations that switch between MinAvailable and MaxUnavailable based on runtime conditions, version labelling, and field application flavors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add docs/primitives/pdb.md covering building, mutations, editors, flavors, and guidance. Update docs/primitives.md to list the PDB primitive in the built-in primitives table and the PodDisruptionBudgetSpecEditor in the editors table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename inner parameter `p` to `pdb` in the identityFunc closure to avoid shadowing the outer NewBuilder parameter, improving readability. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Matches the fix applied to deployment and configmap mutators - initialize the plans slice inline instead of calling beginFeature(), which would create a duplicate empty feature when the generic helper also calls it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…reserveStatus Update the function comment and documentation to accurately describe that DefaultFieldApplicator preserves the Status subresource in addition to server-managed metadata and shared-controller fields. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Align with main branch change in #43 that exported BeginFeature() on the FeatureMutator interface. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d08614a to
4ad9bac
Compare
Claude Review Cycle 1 CompleteAddressed:
Intentionally ignored:
<!-- claude-review-cycle --> |
| Mutate: func(m *Mutator) error { | ||
| m.EditSpec(func(e *editors.PodDisruptionBudgetSpecEditor) error { | ||
| e.SetMaxUnavailable(intstr.FromInt32(1)) | ||
| return nil | ||
| }) | ||
| return nil | ||
| }, |
There was a problem hiding this comment.
The test mutation ignores the error returned by m.EditSpec(...). Since EditSpec can return an error (e.g., ErrNoActiveFeature), this can cause the test to pass even if the mutation failed to register. Return the result of m.EditSpec(...) (or check and propagate it) so failures are surfaced.
pkg/primitives/pdb/resource_test.go
Outdated
| m.EditObjectMetadata(func(e *editors.ObjectMetaEditor) error { | ||
| e.EnsureLabel("order", "a") | ||
| return nil | ||
| }) | ||
| return nil | ||
| }, | ||
| }). | ||
| WithMutation(Mutation{ | ||
| Name: "feature-b", | ||
| Feature: feature.NewResourceFeature("v1", nil).When(true), | ||
| Mutate: func(m *Mutator) error { | ||
| m.EditObjectMetadata(func(e *editors.ObjectMetaEditor) error { | ||
| e.EnsureLabel("order", "b") | ||
| return nil | ||
| }) | ||
| return nil |
There was a problem hiding this comment.
This mutation ignores the error returned by m.EditObjectMetadata(...). Propagating that error (instead of always returning nil) makes the test correctly fail if the mutator rejects edits or if the editor returns an error.
| m.EditObjectMetadata(func(e *editors.ObjectMetaEditor) error { | |
| e.EnsureLabel("order", "a") | |
| return nil | |
| }) | |
| return nil | |
| }, | |
| }). | |
| WithMutation(Mutation{ | |
| Name: "feature-b", | |
| Feature: feature.NewResourceFeature("v1", nil).When(true), | |
| Mutate: func(m *Mutator) error { | |
| m.EditObjectMetadata(func(e *editors.ObjectMetaEditor) error { | |
| e.EnsureLabel("order", "b") | |
| return nil | |
| }) | |
| return nil | |
| return m.EditObjectMetadata(func(e *editors.ObjectMetaEditor) error { | |
| e.EnsureLabel("order", "a") | |
| return nil | |
| }) | |
| }, | |
| }). | |
| WithMutation(Mutation{ | |
| Name: "feature-b", | |
| Feature: feature.NewResourceFeature("v1", nil).When(true), | |
| Mutate: func(m *Mutator) error { | |
| return m.EditObjectMetadata(func(e *editors.ObjectMetaEditor) error { | |
| e.EnsureLabel("order", "b") | |
| return nil | |
| }) |
docs/primitives/pdb.md
Outdated
| m.EditSpec(func(e *editors.PodDisruptionBudgetSpecEditor) error { | ||
| e.ClearMinAvailable() | ||
| e.SetMaxUnavailable(intstr.FromInt32(1)) | ||
| return nil | ||
| }) | ||
| return nil | ||
| }, |
There was a problem hiding this comment.
The documentation examples drop the error returned from m.EditSpec(...)/m.EditObjectMetadata(...) (and then return nil). Since these edit-registration calls return error, the examples should show returning/propagating that error so readers don’t accidentally ignore failures.
…nd docs Return errors from m.EditSpec() and m.EditObjectMetadata() instead of silently discarding them, so test failures and editor errors are properly surfaced. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Review Cycle 1 CompleteAddressed:
Intentionally ignored: <!-- claude-review-cycle --> |
Satisfy errcheck linter by wrapping EditSpec/EditObjectMetadata calls with require.NoError, and fix goimports grouping in resource_test.go. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Include clusterrolebinding, clusterrole, and pvc primitives from main alongside pdb primitive additions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Review Cycle 1 CompleteAddressed: Intentionally ignored:
Additionally resolved merge conflicts from main (clusterrole, clusterrolebinding, pvc primitives). <!-- claude-review-cycle --> |
| | Editor | Scope | | ||
| | ------------------------------- | --------------------------------------------------------------------------------- | | ||
| | `ContainerEditor` | Environment variables, arguments, resource limits, ports | | ||
| | `PodSpecEditor` | Volumes, tolerations, node selectors, service account, security context | | ||
| | `DeploymentSpecEditor` | Replicas, update strategy, label selectors | | ||
| | `ConfigMapDataEditor` | `.data` entries — set, remove, deep-merge YAML patches, raw access | | ||
| | `PodDisruptionBudgetSpecEditor` | MinAvailable, MaxUnavailable, selector, eviction policy | | ||
| | `PolicyRulesEditor` | `.rules` entries on Role and ClusterRole objects — add, remove, clear, raw access | | ||
| | `BindingSubjectsEditor` | Subjects on RoleBinding or ClusterRoleBinding — ensure, remove, raw | | ||
| | `PVCSpecEditor` | Access modes, storage class, volume mode, storage requests | | ||
| | `ObjectMetaEditor` | Labels and annotations on any Kubernetes object | |
There was a problem hiding this comment.
Same issue as in docs/primitives/pdb.md: the editor list table uses || which introduces an extra empty column / inconsistent rendering. Convert to standard Markdown table rows beginning with a single |.
pkg/primitives/pdb/mutator.go
Outdated
| // Unlike other primitive mutators, EditObjectMetadata and EditSpec return an | ||
| // error when called without an active feature scope, rather than silently | ||
| // succeeding. This means Mutator does not satisfy editors.ObjectMutator. |
There was a problem hiding this comment.
This comment is slightly inconsistent with the implementation: EditObjectMetadata(nil) and EditSpec(nil) return nil even when there is no active feature scope. Consider clarifying the comment to reflect that the error is returned only when a non-nil edit function is provided without BeginFeature().
The comment on the Mutator type incorrectly implied that EditObjectMetadata and EditSpec always error without an active feature scope. In reality, nil edit functions are silently ignored regardless of scope state. Updated the comment to reflect this nuance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Review Cycle 2 CompleteAddressed:
Intentionally ignored:
|
Implements the
pdbKubernetes resource primitive following the pattern established by the existingConfigMapandDeploymentprimitives.Summary
pdbprimitive package underpkg/primitives/pdb/Checklist
pdbspec) and docs entry following established patterns for new primitives