Skip to content

Remove last-applied-configuration from annotations#137

Merged
aufi merged 2 commits into
migtools:mainfrom
aufi:remove-last-applied-configuration-annotation
Apr 14, 2026
Merged

Remove last-applied-configuration from annotations#137
aufi merged 2 commits into
migtools:mainfrom
aufi:remove-last-applied-configuration-annotation

Conversation

@aufi

@aufi aufi commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Current exported data contains last-applied-configuration annotation, that is not needed for migration, so should be removed.

Related to migtools/crane#253 (also more details there)

Summary by CodeRabbit

  • Improvements

    • Kubernetes resource processing now removes the kubectl last-applied-configuration annotation and robustly handles annotation names containing special characters, ensuring accurate cleanup of metadata.
  • Tests

    • Added a test case for annotation removal and updated existing expectations to verify the enhanced behavior.

Current exported data contains last-applied-configuration annotation, that is not needed for migration, so should be removed.

Related to migtools/crane#253 (also more
details there)

Signed-off-by: Marek Aufart <maufart@redhat.com>
@coderabbitai

coderabbitai Bot commented Apr 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e7312136-0fa4-4f18-90b4-179e6fd02354

📥 Commits

Reviewing files that changed from the base of the PR and between 2be624c and b0df3f1.

📒 Files selected for processing (2)
  • transform/kubernetes/kubernetes.go
  • transform/kubernetes/kubernetes_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • transform/kubernetes/kubernetes_test.go
  • transform/kubernetes/kubernetes.go

📝 Walkthrough

Walkthrough

Adds removal of the kubectl.kubernetes.io/last-applied-configuration annotation during Kubernetes object sanitization and rewrites JSON Pointer path construction to use RFC‑6901 escaping when generating remove patches.

Changes

Cohort / File(s) Summary
Kubernetes field stripping
transform/kubernetes/kubernetes.go
Detects and removes metadata.annotations["kubectl.kubernetes.io/last-applied-configuration"]; replaces previous JSON Patch path construction with RFC‑6901 escaping (escapeJSONPointer) and join-based path assembly to correctly encode / and ~ in path segments.
Tests: expectations updated / new case
transform/kubernetes/kubernetes_test.go
Adds RemoveLastAppliedConfigurationAnnotation test; updates existing nodePort removal tests to expect an additional remove operation for the last-applied annotation and normalizes expected JSON patch formatting.

Sequence Diagram(s)

(omitted — changes are limited to two files and do not involve multi-component interaction warranting a sequence diagram)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐰 I hopped through YAML, soft and quick,
Found an old annotation—gone in a click.
A JSON patch nibble, tidy and neat,
No stray config crumbs left in my seat. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Remove last-applied-configuration from annotations' directly and clearly describes the main change: removing the kubectl.kubernetes.io/last-applied-configuration annotation from exported Kubernetes data during migration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
transform/kubernetes/kubernetes.go (1)

69-77: ⚠️ Potential issue | 🔴 Critical

Escape JSON Pointer tokens in stripFields before generating patch paths.

Line 76 adds kubectl.kubernetes.io/last-applied-configuration to fields being stripped. The / in this annotation key must be escaped per RFC 6901 when constructing JSON Patch paths. Currently, stripFields at line 589 generates /metadata/annotations/kubectl.kubernetes.io/last-applied-configuration, which the json-patch library decodes as four tokens (metadataannotationskubectl.kubernetes.iolast-applied-configuration) instead of three. This causes the patch to target a non-existent nested path and fails to remove the annotation.

The same escaping issue also affects addAnnotations() and removeAnnotations() functions when handling keys with / or ~ characters.

Proposed fix
+func escapeJSONPointerToken(token string) string {
+	token = strings.ReplaceAll(token, "~", "~0")
+	return strings.ReplaceAll(token, "/", "~1")
+}
+
 func stripFields(obj unstructured.Unstructured) (jsonpatch.Patch, error) {
 	var patches jsonpatch.Patch
 	for _, field := range fieldsToStrip {
 		_, found, err := unstructured.NestedFieldNoCopy(obj.Object, field...)
 		if err != nil {
 			return patches, err
 		}
 		if found {
-			patch, err := jsonpatch.DecodePatch([]byte(fmt.Sprintf(opRemove, fmt.Sprintf(strings.Repeat("/%v", len(field)), interfaceSlice(field)...))))
+			escaped := make([]interface{}, 0, len(field))
+			for _, token := range field {
+				escaped = append(escaped, escapeJSONPointerToken(token))
+			}
+			path := fmt.Sprintf(strings.Repeat("/%v", len(field)), escaped...)
+			patch, err := jsonpatch.DecodePatch([]byte(fmt.Sprintf(opRemove, path)))
 			if err != nil {
 				return nil, err
 			}
 			patches = append(patches, patch...)
 		}
 	}
 	return patches, nil
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@transform/kubernetes/kubernetes.go` around lines 69 - 77, The patch
generation and annotation helpers (stripFields, addAnnotations,
removeAnnotations) build JSON Patch paths from raw keys but do not RFC
6901-escape JSON Pointer tokens, so keys like
"kubectl.kubernetes.io/last-applied-configuration" are split incorrectly; update
these functions to escape each token before joining into a path by replacing "~"
with "~0" and "/" with "~1" (apply this escaping when constructing paths in
stripFields and when building annotation add/remove patch ops in
addAnnotations/removeAnnotations) so patch targets the correct single annotation
key.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@transform/kubernetes/kubernetes.go`:
- Around line 69-77: The patch generation and annotation helpers (stripFields,
addAnnotations, removeAnnotations) build JSON Patch paths from raw keys but do
not RFC 6901-escape JSON Pointer tokens, so keys like
"kubectl.kubernetes.io/last-applied-configuration" are split incorrectly; update
these functions to escape each token before joining into a path by replacing "~"
with "~0" and "/" with "~1" (apply this escaping when constructing paths in
stripFields and when building annotation add/remove patch ops in
addAnnotations/removeAnnotations) so patch targets the correct single annotation
key.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cdf43b0a-856f-42b5-97f2-e39f0d337b04

📥 Commits

Reviewing files that changed from the base of the PR and between b53540d and 2be624c.

📒 Files selected for processing (2)
  • transform/kubernetes/kubernetes.go
  • transform/kubernetes/kubernetes_test.go

Comment thread transform/kubernetes/kubernetes_test.go Outdated
Signed-off-by: Marek Aufart <maufart@redhat.com>
@aufi aufi requested a review from stillalearner April 14, 2026 10:52
@stillalearner

Copy link
Copy Markdown
Contributor

yes, i observed this as well, but got ignored. Thanks @aufi

@stillalearner stillalearner 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.

lgtm

@aufi aufi merged commit a9f07d5 into migtools:main Apr 14, 2026
2 checks passed
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