Skip to content

feat: implement secret primitive#29

Open
sourcehawk wants to merge 19 commits intomainfrom
feature/secret-primitive
Open

feat: implement secret primitive#29
sourcehawk wants to merge 19 commits intomainfrom
feature/secret-primitive

Conversation

@sourcehawk
Copy link
Owner

@sourcehawk sourcehawk commented Mar 22, 2026

Implements the secret Kubernetes resource primitive following the pattern established by the existing ConfigMap and Deployment primitives.

Summary

  • Adds secret primitive package under pkg/primitives/secret/
  • Implements required lifecycle interfaces
  • Includes editors, mutator, flavors, and builder
  • Adds SecretDataEditor to shared pkg/mutation/editors/ (follows existing ConfigMapDataEditor pattern)
  • Updates shared documentation (docs/primitives.md) to include the new primitive in the index

Checklist

  • Compiles cleanly
  • Tests pass
  • Follows naming conventions in CONTEXT.md
  • Shared file modifications are intentional and minimal (documentation index + new editor)

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new secret primitive to the operator component framework, mirroring the existing static primitives (e.g., configmap) with builder/resource APIs, mutation + flavor pipelines, hashing utilities, tests, docs, and an end-to-end example.

Changes:

  • Introduces pkg/primitives/secret (resource, builder, mutator, flavors, and hash utilities) with comprehensive unit tests.
  • Adds a new shared editor SecretDataEditor under pkg/mutation/editors to support typed .data / .stringData mutations.
  • Adds documentation for the secret primitive plus a runnable examples/secret-primitive showcasing composition via feature-gated mutations and flavors.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
pkg/primitives/secret/resource.go Implements Secret Resource wrapper around internal generic static resource.
pkg/primitives/secret/resource_test.go Tests identity/object deep-copy/mutation/data extraction behavior.
pkg/primitives/secret/mutator.go Implements plan-and-apply mutator API for Secret metadata and data edits.
pkg/primitives/secret/mutator_test.go Tests mutator editing helpers, ordering, and interface implementation.
pkg/primitives/secret/hash.go Adds DataHash and Resource.DesiredHash utilities.
pkg/primitives/secret/hash_test.go Tests determinism/sensitivity and DesiredHash behavior.
pkg/primitives/secret/flavors.go Adds Secret-specific field application flavors incl. preserving external .data entries.
pkg/primitives/secret/flavors_test.go Tests flavors and builder integration with Mutate.
pkg/primitives/secret/builder.go Adds fluent builder API over internal generic static builder.
pkg/primitives/secret/builder_test.go Tests builder validation and registration behavior.
pkg/mutation/editors/secretdata.go Adds a shared typed editor for Secret .data and .stringData.
pkg/mutation/editors/secretdata_test.go Tests SecretDataEditor behavior and nil-handling.
examples/secret-primitive/resources/secret.go Example resource factory wiring mutations/flavors/extractors.
examples/secret-primitive/README.md Example documentation and run instructions.
examples/secret-primitive/main.go Runnable example using fake client + multiple reconciliation steps.
examples/secret-primitive/features/mutations.go Example feature-gated Secret mutations using SetStringData + metadata edits.
examples/secret-primitive/features/flavors.go Example flavor wrapper for preserving external entries.
examples/secret-primitive/app/controller.go Example controller wiring component + Secret resource.
docs/primitives/secret.md New user-facing documentation for the secret primitive (builder, ordering, flavors, hashing).

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

@sourcehawk
Copy link
Owner Author

Claude Review Cycle 1 Complete

Addressed:

  • examples/secret-primitive/resources/secret.go: Data extractor no longer prints secret values. Now prints only key names and value lengths, with a comment warning against logging secret values in production controllers.

Intentionally ignored:

  • docs/primitives/secret.md table format: The comment claims the capabilities table uses double leading/trailing pipes, but the actual file already uses standard single-pipe | Capability | Detail | format, consistent with docs/primitives/configmap.md. No change needed.

Copilot AI review requested due to automatic review settings March 22, 2026 19:48
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

@sourcehawk
Copy link
Owner Author

Claude Review Cycle 1 Complete

Addressed:

  • Added pkg/primitives/secret (Static) to the Built-in Primitives table in docs/primitives.md
  • Added SecretDataEditor to the Mutation Editors table in docs/primitives.md

Intentionally ignored:
None

<!-- claude-review-cycle -->

@sourcehawk
Copy link
Owner Author

approved

Copilot AI review requested due to automatic review settings March 23, 2026 03:00
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

@sourcehawk
Copy link
Owner Author

Claude Review Cycle 1 Complete

Addressed:

  • Updated PR description/checklist to acknowledge shared file modifications (docs/primitives.md index update and new SecretDataEditor in pkg/mutation/editors/). Replaced misleading "Does not modify shared files" checkbox with accurate description of intentional, minimal shared file changes.

Intentionally ignored:
None

<!-- claude-review-cycle -->

Copilot AI review requested due to automatic review settings March 23, 2026 16:43
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.

@sourcehawk
Copy link
Owner Author

Claude Review Cycle 1 Complete

Addressed:

  • docs/primitives/secret.md:122 — Narrowed ordering guarantee language to describe per-mutation edit ordering rather than claiming cross-feature boundaries. Also updated the Apply() doc comment in mutator.go to match.

Intentionally ignored:

  • pkg/primitives/secret/mutator_test.go:146 (remove beginFeature() test) — This is a valid unit test of the mutator's internal plan-splitting logic. The configmap primitive has an identical test (TestMutator_MultipleFeatures). Removing it would leave the beginFeature() method untested while keeping the method itself.
  • pkg/primitives/secret/mutator.go:50 (remove beginFeature() / feature plan infrastructure) — This is a framework-level concern: the sealed FeatureMutator interface affects all primitives equally (deployment, configmap, and secret all have the same pattern). Removing the infrastructure from secret alone would create inconsistency. The fix belongs in the framework (exporting the boundary hook), not in individual primitives.

<!-- claude-review-cycle -->

sourcehawk and others added 10 commits March 23, 2026 20:17
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, and hash

Implements the Secret primitive following the same pattern as the ConfigMap
primitive. Includes full test coverage for builder validation, mutator
operations, field application flavors, and data hashing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Demonstrates building a Secret resource with base credentials, version
labels, and feature-gated tracing/metrics tokens using the secret primitive.

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

- hash.go: Merge .stringData into a copy of .data before hashing to match
  Kubernetes API-server write semantics. Ensures DesiredHash reflects content
  set via SetStringData.
- flavors.go: PreserveExternalEntries now treats keys present in
  applied.StringData as owned, preventing incorrect preservation of cluster
  values that the operator intends to overwrite via .stringData.
- secret.md: Add nil-check for current.Data in the custom field applicator
  example to prevent panic. Update DataHash documentation to describe the
  merged hash semantics.
- example secret.go: Remove misleading StringData iteration from the data
  extractor since .stringData is write-only and never returned by the API
  server on read.
- Add tests for StringData-aware hash and flavor behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Print only key names and value lengths instead of base64-encoded values
to prevent credential leakage if the example is copied into production.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Secret to the Built-in Primitives table and SecretDataEditor
to the Mutation Editors table in docs/primitives.md so the new
primitive is discoverable from the main index page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Aligns with the fix applied to deployment and configmap mutators in #42.
The constructor now initializes the plans slice directly instead of calling
beginFeature(), preventing an empty feature plan when mutate_helper.go
calls fm.beginFeature() before each mutation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sourcehawk and others added 2 commits March 23, 2026 20:17
…ng guarantees

The FeatureMutator interface in internal/generic uses an unexported
beginFeature() method (sealed interface pattern), so primitive mutators
outside that package cannot satisfy it today. Update the secret docs
and Apply() doc comment to accurately describe per-mutation ordering
rather than claiming cross-feature boundaries that the framework does
not currently enforce for primitives.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 23, 2026 21:38
@sourcehawk sourcehawk force-pushed the feature/secret-primitive branch from 61d430c to c856ea6 Compare March 23, 2026 21:38
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.

sourcehawk and others added 3 commits March 24, 2026 00:29
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update DesiredHash godoc, SecretDataEditor index entry, and hash section
intro to accurately reflect that hashing includes .stringData merged into
.data, and that the editor exposes SetString/RemoveString/RawStringData.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 24, 2026 00:33
@sourcehawk
Copy link
Owner Author

Claude Review Cycle 1 Complete

Addressed:

  • pkg/primitives/secret/hash.go:65 — Updated DesiredHash godoc to mention .stringData merged into .data matching DataHash semantics, instead of only referencing .data.
  • docs/primitives.md:133 — Expanded SecretDataEditor index entry to mention SetString/RemoveString and RawStringData() alongside existing operations.
  • docs/primitives/secret.md:246 — Changed hash section intro from ".data field" to "effective data content (.data plus .stringData merged using Kubernetes API-server semantics)".

Intentionally ignored:
None

<!-- claude-review-cycle -->

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

sourcehawk and others added 2 commits March 24, 2026 00:49
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Kubernetes API server merges .stringData into .data on write and
never returns .stringData on reads. When controllerutil.CreateOrUpdate
diffs the post-mutate object against the server-populated object,
leftover .stringData entries cause an Update on every reconcile.

After applying all mutations, merge .stringData entries into .data
(stringData keys take precedence) and clear .stringData so the
mutated object matches the server-persisted form.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 24, 2026 01:13
@sourcehawk
Copy link
Owner Author

Claude Review Cycle 1 Complete

Addressed:

  • pkg/primitives/secret/mutator.go:148 — StringData normalization: After Apply(), .stringData entries are now merged into .data (stringData keys take precedence) and .stringData is cleared. This matches the Kubernetes API server's write semantics and prevents controllerutil.CreateOrUpdate from issuing spurious Updates on every reconcile when SetStringData/EditData(SetString/RawStringData) is used. Updated corresponding tests to assert on .Data instead of .StringData.

Intentionally ignored:
None

<!-- claude-review-cycle -->

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.

sourcehawk and others added 2 commits March 24, 2026 17:51
Do not initialize an empty feature plan in NewMutator — require
BeginFeature before registering mutations, matching the convention
established in configmap and deployment primitives. Add constructor
and feature-plan invariant tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

2 participants