Skip to content

Normalize --namespace, validate namespace case, fix error messages/CRD text, stop echoing dockerconfigjson parse errors - #752

Merged
joaopapereira merged 5 commits into
carvel-dev:developfrom
nikhilsagotiya:fix/namespace-handling-error-messages-credential-echo
Oct 9, 2026
Merged

joaopapereira merged 5 commits into
carvel-dev:developfrom
nikhilsagotiya:fix/namespace-handling-error-messages-credential-echo

Conversation

@nikhilsagotiya

Copy link
Copy Markdown
Contributor

What this PR does

A small set of robustness and message-quality fixes, split into four independent commits so they can be reviewed (or dropped) separately.

1. fix: normalize --namespace flag and validate namespace value is lowercase

Namespace names are RFC 1123 labels, so always lowercase, but two places used the operator-supplied value verbatim:

  • --namespace flag (cmd/controller/main.go): the value is used as a controller-runtime cache key. A mixed-case value made the controller watch nothing and reconcile nothing, with no error reported. It is now lowercased and trimmed once, right after flag parsing (new normalizeNamespace helper plus a unit test). The shipped Deployment does not pass this flag, so this only affects manual or custom runs.

  • package-bundle ytt config (config/package-bundle/config/deployment.yml): data.values.namespace was substituted straight into Namespace.metadata.name. A mixed-case value rendered fine and only failed later at apply time with an API-server validation error. The config now fails at render time with a clear message:
    Validation Error: namespace must be lowercase (RFC 1123 DNS label), got 'SecretGen-Sys'

    Valid (lowercase) values are unaffected: the default render is byte-identical to before.

2. fix(error-messages): correct grammar, quoting and wording in user-facing messages

Follow-up to the earlier error-message pass. Message text only; no logic or return values change.

  • The status condition no longer leaks a Go identifier: Expected secret to have type=corev1.SecretTypeDockerConfigJson, but did not now reads Expected secret to have type 'kubernetes.io/dockerconfigjson', but it does not.
  • PEM formatted block becomes a PEM-formatted block (certificate and private key).
  • got err becomes got error; serviceaccount becomes service account.
  • Consistent lowercase input resources, and consistent single-quote style in the SecretExport validation messages, which now name the actual spec fields.
  • The token-refresh error reads token for service account 'ns/name' .... The token cache key itself is unchanged.
  • CRD descriptions shown by kubectl explain: InputResource is references ... a identifying and dynamic valid are fixed in the Go comments and in crds.yml.
  • Two hack scripts: non zero becomes non-zero with a clearer explanation, and the e2e note gets proper punctuation.

The tests that assert the old strings are updated.

3. fix(crds): strip unresolved "TODO" note from generated CRD descriptions

controller-gen copies the description of corev1.LocalObjectReference.Name verbatim, including an upstream TODO: Add other useful fields. apiVersion, kind, uid? note, which then shows up in kubectl explain for SecretTemplate status.secret and Certificate spec.caRef. hack/crd-overlay.yml now strips it so regenerating does not bring it back, and crds.yml gets the same change. I checked the overlay against the previous crds.yml: exactly those two description lines change.

4. fix(sharing): do not echo parser error when a dockerconfigjson secret is invalid

NewCombinedDockerConfigJSON put the raw json.Unmarshal error in its message. encoding/json syntax errors echo the offending input character, and this data holds registry credentials, so a secret that is not valid JSON could leak its first character into the returned error, which ends up in the resource status and the controller logs. It now returns data is not valid dockerconfigjson. Reconcile still fails the same way. A new test asserts that no part of unparseable input appears in the error.

Testing

  • golangci-lint v2.12.2 (the version CI pins) with the repo config: 0 issues.
  • hack/verify-no-dirty-files.sh (what CI runs first: go fmt, vendor, tidy, build, test compile, ytt render): passes and leaves the tree clean.
  • go test ./pkg/... ./cmd/...: pass, also with GODEBUG=fips140=only for the generator, sharing and satoken packages.
  • ytt: default render unchanged; a mixed-case namespace value is rejected with the message above.
  • Not run locally: the e2e suite (hack/test-all.sh), since it needs minikube/kapp. I'm relying on the CI job for that.

Notes for reviewers

  • config/package-bundle/config/crds.yml was edited by hand for four description lines (two typos, two TODO strips). Running hack/gen-crds.sh with the currently vendored controller-gen rewrites about 200 lines of that file (descriptions reflowed, some fields reordered). That mismatch already exists on develop and is not caused by this PR, and CI does not run the generator. It may be worth a separate PR that regenerates the CRDs.
  • The namespace check only changes behavior for a value that could never have worked: it fails earlier, with a clearer message.

Comment thread cmd/controller/main.go Outdated
Comment thread cmd/controller/main.go Outdated
@sameerforge
sameerforge force-pushed the fix/namespace-handling-error-messages-credential-echo branch from bbcfebf to 4b93559 Compare October 7, 2026 06:50
…case

Namespace names are RFC 1123 labels (always lowercase), but the --namespace
flag used the operator-supplied value verbatim. The value is used as a
controller-runtime cache key, and a mixed-case value would fail to watch
anything with no error reported.

Address reviewer feedback by changing from silent normalization to early
validation with clear error messaging:

- Update the flag description to clarify the lowercase requirement
- Change normalizeNamespace() to return (string, error) and validate instead
  of silently lowercasing the input
- Error out early with a clear message: "namespace must be lowercase
  (RFC 1123 DNS label), got 'X'" — matching the ytt template validation
- Updated tests to verify both valid and invalid namespace values

This ensures early failure with a clear error message, consistent with the
ytt template behavior and the RFC 1123 specification for namespace names.

Signed-off-by: Nikhil Sagotiya <nikhil.sagotiya@broadcom.com>
…ing messages

Follow-up to the earlier error-message pass. Only message text changes; no
logic or return values change.

- status condition no longer leaks a Go identifier: "Expected secret to have
  type=corev1.SecretTypeDockerConfigJson, but did not" now names the real type
  'kubernetes.io/dockerconfigjson'
- "PEM formatted block" -> "a PEM-formatted block" (certificate and key)
- "got err" -> "got error"; "serviceaccount" -> "service account"
- consistent lowercase "input resources"; consistent single-quote style in the
  SecretExport validation messages, which now name the actual spec fields
- token refresh error reads "token for service account 'ns/name'"; the cache
  key itself is unchanged
- CRD descriptions (kubectl explain): "InputResource is references ... a
  identifying" and "dynamic valid" fixed in the Go comments and crds.yml
- hack scripts: "non zero" -> "non-zero" with a clearer explanation, and
  punctuation in the e2e note

Tests that assert the old strings are updated.

Signed-off-by: Nikhil Sagotiya <nikhil.sagotiya@broadcom.com>
controller-gen copies the description of corev1.LocalObjectReference.Name
verbatim, including an upstream "TODO: Add other useful fields. apiVersion,
kind, uid?" note, which then shows up in kubectl explain for the SecretTemplate
status.secret and Certificate spec.caRef fields.

Strip it in hack/crd-overlay.yml so that regenerating the CRDs does not bring
it back, and apply the same change to the committed crds.yml. Checked by
applying the overlay to the previous crds.yml: exactly those two description
lines change.

Signed-off-by: Nikhil Sagotiya <nikhil.sagotiya@broadcom.com>
… is invalid

NewCombinedDockerConfigJSON included the raw json.Unmarshal error in its
message. encoding/json syntax errors echo the offending input character, and
this data holds registry credentials, so a secret that is not valid JSON could
leak its first character into the returned error, which is written to the
resource status and the controller logs.

Return a generic "data is not valid dockerconfigjson" message instead. The
reconcile still fails the same way. Adds a test asserting that no part of
unparseable input appears in the error.

Signed-off-by: Nikhil Sagotiya <nikhil.sagotiya@broadcom.com>
@sameerforge
sameerforge force-pushed the fix/namespace-handling-error-messages-credential-echo branch from 4b93559 to 3026cfc Compare October 7, 2026 06:52
…tions

- Fix comma splice in CRD reason descriptions: "Unique, this should be..." → "Unique; this should be..."
- Add hyphen to compound adjective: "machine understandable" → "machine-understandable"
- Fix redundant "error:" suffix in test error messages
  - kapp.go: Remove redundant "error:" suffix in execution error message
  - kubectl.go: Remove redundant "error:" suffix in execution error message

These changes improve message clarity and comply with grammar and formatting standards.

Signed-off-by: Sameer Khan <sameer.khan@broadcom.com>

@joaopapereira joaopapereira left a comment

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.

Lgtm

@joaopapereira
joaopapereira merged commit dde51a3 into carvel-dev:develop Oct 9, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Closed

Development

Successfully merging this pull request may close these issues.

5 participants