Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new clusterrole primitive to the operator-component-framework so controllers can manage Kubernetes rbac.authorization.k8s.io/v1 ClusterRole objects using the same builder/mutator/flavor patterns as existing primitives.
Changes:
- Introduces
pkg/primitives/clusterrolewithResource,Builder,Mutator, and field-application flavors for ClusterRole-specific behavior. - Adds a new shared mutation editor
PolicyRulesEditorunderpkg/mutation/editorsto support typed.rulesmutation. - Adds an end-to-end example (
examples/clusterrole-primitive) and full primitive documentation (docs/primitives/clusterrole.md).
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/primitives/clusterrole/resource.go | Defines the ClusterRole Resource wrapper and default field applicator. |
| pkg/primitives/clusterrole/mutator.go | Implements plan-and-apply mutator for metadata, rules, and aggregationRule. |
| pkg/primitives/clusterrole/builder.go | Provides fluent builder API and validation/workarounds for cluster-scoped objects. |
| pkg/primitives/clusterrole/flavors.go | Adds flavors to preserve labels/annotations and externally-added rules. |
| pkg/primitives/clusterrole/*_test.go | Adds unit tests for builder, mutator, and flavors. |
| pkg/mutation/editors/policyrules.go | Adds a reusable PolicyRulesEditor for Role/ClusterRole rules mutation. |
| pkg/mutation/editors/policyrules_test.go | Adds tests for PolicyRulesEditor. |
| examples/clusterrole-primitive/* | Adds a runnable example demonstrating mutation composition and reconciliation. |
| docs/primitives/clusterrole.md | Adds user-facing documentation for the new primitive API and usage patterns. |
Claude Review Cycle 1 CompleteAddressed:
Intentionally ignored: <!-- claude-review-cycle --> |
|
approved but wait until last |
102978d to
a1d3fca
Compare
Claude Review Cycle 1 CompleteAddressed:
Intentionally ignored:
<!-- claude-review-cycle --> |
Claude Review Cycle 1 CompleteAddressed:
Intentionally ignored: <!-- claude-review-cycle --> |
Claude Review Cycle 1 CompleteAddressed:
Intentionally ignored: <!-- claude-review-cycle --> |
Introduces a typed editor for mutating the .rules field of Role and ClusterRole resources, following the same pattern as existing editors (ConfigMapDataEditor, ObjectMetaEditor). Provides AddRule, RemoveRuleByIndex, Clear, and Raw escape hatch operations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the ClusterRole primitive as a Static, cluster-scoped resource. Includes builder (with name-only validation, no namespace required), resource, mutator (EditObjectMetadata, EditRules, AddRule, SetAggregationRule), and flavors (PreserveCurrentLabels, PreserveCurrentAnnotations, PreserveExternalRules). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documents the ClusterRole primitive API, mutation system, editors, flavors, aggregation rule support, and usage patterns. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ot set semantics The docs claimed slice fields were compared as "unordered sets" but the implementation treats duplicates as significant (multiset equality). Updated comments to accurately describe the behavior rather than changing the comparison logic. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Review Cycle 2 CompleteAddressed:
Intentionally ignored: <!-- claude-review-cycle --> |
Align with configmap and deployment mutators — NewMutator no longer creates an initial feature plan. BeginFeature must be called before registering any mutations. Updates all tests accordingly and adds constructor/plan invariant tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tive Align with the framework's move to Server-Side Apply. Remove DefaultFieldApplicator, WithCustomFieldApplicator, WithFieldApplicationFlavor, the flavors.go file, and all associated tests. Update builder to use the new generic constructor signature (without defaultApplicator). Update Mutate tests to use Object() output instead of empty structs. Strip field applicator and flavor sections from primitive docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| | `pkg/primitives/deployment` | Workload | [deployment.md](primitives/deployment.md) | | ||
| | `pkg/primitives/configmap` | Static | [configmap.md](primitives/configmap.md) | | ||
| | `pkg/primitives/clusterrole` | Static | [clusterrole.md](primitives/clusterrole.md) | | ||
|
|
There was a problem hiding this comment.
make run-examples currently runs a hard-coded list of examples and does not include the new clusterrole-primitive example (verified in Makefile:122-126). To keep CI/local smoke runs covering all examples, add go run ./examples/clusterrole-primitive/. to the run-examples target (or update docs/README to clarify it’s intentionally excluded).
| The `clusterrole` primitive is exercised by the `examples/clusterrole-primitive` example. Because it requires | |
| cluster-scoped RBAC and may need elevated permissions, it is intentionally not included in the default | |
| `make run-examples` target used for CI/local smoke runs. |
| // Builder is a configuration helper for creating and customizing a ClusterRole Resource. | ||
| // | ||
| // It provides a fluent API for registering mutations and data extractors. | ||
| // Build() validates the configuration and returns an initialized Resource | ||
| // ready for use in a reconciliation loop. | ||
| type Builder struct { | ||
| base *generic.StaticBuilder[*rbacv1.ClusterRole, *Mutator] | ||
| } |
There was a problem hiding this comment.
The PR description says the clusterrole primitive includes “flavors”, but there’s no flavor-related API/implementation in pkg/primitives/clusterrole (no Flavor references, and the builder only exposes mutations/data extractors). Either update the PR description to match what’s implemented or add the intended flavor support so the change set aligns with the stated scope.
| func (e *PolicyRulesEditor) RemoveRuleByIndex(index int) { | ||
| if index < 0 || index >= len(*e.rules) { | ||
| return | ||
| } | ||
| *e.rules = append((*e.rules)[:index], (*e.rules)[index+1:]...) | ||
| } |
There was a problem hiding this comment.
RemoveRuleByIndex uses the append(slice[:i], slice[i+1:]...) pattern, which can keep the removed element’s backing array referenced (and thus retain memory for any nested slices in rbacv1.PolicyRule). Since this repo already uses the slices package elsewhere, prefer slices.Delete(*e.rules, index, index+1) (or explicitly zero the removed slot) to avoid accidental retention and keep deletion semantics consistent.
Implements the
clusterroleKubernetes resource primitive following the pattern established by the existingConfigMapandDeploymentprimitives.Summary
clusterroleprimitive package underpkg/primitives/clusterrole/PolicyRulesEditortopkg/mutation/editors/(reusable for Role and ClusterRole)internal/generic/builder_base.goChecklist
internal/generic/builder_base.go) and a newPolicyRulesEditor(pkg/mutation/editors/)