feat: Render Helm ValuesObject as YAML in log output instead of binary (#18342)#27649
Conversation
Signed-off-by: subhramit <subhramit.bb@live.in>
❌ Preview Environment deleted from BunnyshellAvailable commands (reply to this comment):
|
Signed-off-by: subhramit <subhramit.bb@live.in>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #27649 +/- ##
==========================================
+ Coverage 64.04% 64.08% +0.04%
==========================================
Files 422 422
Lines 57828 57865 +37
==========================================
+ Hits 37037 37084 +47
+ Misses 17305 17295 -10
Partials 3486 3486 ☔ View full report in Codecov by Sentry. |
|
ccing @agaudreault for a review, if this approach makes sense. |
There was a problem hiding this comment.
Pull request overview
This PR addresses repo-server log bloat caused by Helm valuesObject being rendered as raw byte arrays in manifest-cache log messages. It adds log-specific formatting for application sources so cache-related repo-server logs emit readable values text instead of binary-looking output.
Changes:
- Add
LogString()helpers forApplicationSourceHelmandApplicationSourceto render HelmValuesObjectthrough the existing values helpers. - Update manifest cache hit/miss/error log statements in
reposerver/repository/repository.goto use the new log formatter. - Add unit tests covering the new logging string behavior for Helm/application sources.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| reposerver/repository/repository.go | Swaps manifest-cache log messages over to the new log-specific source formatter. |
| pkg/apis/application/v1alpha1/values.go | Adds LogString() helpers that rewrite ValuesObject into log-friendly text. |
| pkg/apis/application/v1alpha1/values_test.go | Adds unit tests for the new LogString() behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if s.Helm == nil || s.Helm.ValuesObject == nil { | ||
| return s.String() | ||
| } | ||
| sourceCopy := s.DeepCopy() |
| log.Infof("manifest error cache miss: %s/%s", q.ApplicationSource.LogString(), cacheKey) | ||
| return false, res.ManifestResponse, nil | ||
| } | ||
|
|
||
| log.Infof("manifest cache hit: %s/%s", q.ApplicationSource.String(), cacheKey) | ||
| log.Infof("manifest cache hit: %s/%s", q.ApplicationSource.LogString(), cacheKey) |
There was a problem hiding this comment.
This has merit, but was not introduced as a regression in this PR.
Happy to address separately in another PR, if that's fine? @agaudreault
| err = s.cache.DeleteManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, refSourceCommitSHAs, q.InstallationID) | ||
| if err != nil { | ||
| log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.String(), cacheKey, err) | ||
| log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.LogString(), cacheKey, err) |
There was a problem hiding this comment.
This wording is also pre-existing, hence out of the PR's scope.
But I think the concern is valid.
Edit: this was a tiny one, so addressed in 0fd6f6b
| err = s.cache.DeleteManifests(cacheKey, q.ApplicationSource, q.RefSources, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, refSourceCommitSHAs, q.InstallationID) | ||
| if err != nil { | ||
| log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.String(), cacheKey, err) | ||
| log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.LogString(), cacheKey, err) |
There was a problem hiding this comment.
Same as #27649 (comment)
Addressed in 0fd6f6b
| helmCopy := *h | ||
| helmCopy.Values = h.ValuesString() | ||
| helmCopy.ValuesObject = nil |
Signed-off-by: subhramit <subhramit.bb@live.in>
Signed-off-by: subhramit <subhramit.bb@live.in>
Signed-off-by: subhramit <subhramit.bb@live.in>
|
Hi, Switching reposerver cache logs from Severity: remediation recommended | Category: security How to fix: Redact/truncate logged Helm values Agent prompt to fix - you can give this to your LLM of choice:
Found by Qodo. Free code review for open-source maintainers. |
The information was disclosed previously as well, just in a different format and also trivially decodable into JSON back. Truncation/security concerns can be raised as a separate issue.
I don't agree - it would miss everything that doesn't match the wordlist. Helm values are user-defined arbitrary YAML which we should not concern ourselves with. It would also produce false positives that destroy debuggability. For example
This may be a reasonable thing to consider but is pre-existing and orthogonal to this fix. |
| // LogString returns a human-readable string representation of ApplicationSourceHelm | ||
| // suitable for logging. It renders ValuesObject as its YAML equivalent instead of | ||
| // raw bytes, preventing binary data from flooding log output. | ||
| func (h *ApplicationSourceHelm) LogString() string { |
There was a problem hiding this comment.
Why not using the String function directly? This makes it error prone since most people will not think of using LogString
| // LogString returns a human-readable string representation of ApplicationSourceHelm | |
| // suitable for logging. It renders ValuesObject as its YAML equivalent instead of | |
| // raw bytes, preventing binary data from flooding log output. | |
| func (h *ApplicationSourceHelm) LogString() string { | |
| func (h ApplicationSourceHelm) String() string { |
There was a problem hiding this comment.
I had also thought about it, but generated.pb.go already has func (this *ApplicationSourceHelm) String() string. Since go doesn't allow value-receiver and pointer-receiver methods with the same name on a single type, it will not compile.
IMO in hindsight, chances are non-zero, but unlikely that developers make that mistake with today's AI-assisted code suggestions, development tools and code reviews.
There was a problem hiding this comment.
Out of curiosity, I dug a little deeper - there seems to be no workaround for this except proto suppression protobuf.options.(gogoproto.goproto_stringer)=false, which IMO is not clean at all.
There was a problem hiding this comment.
@agaudreault just a gentle ping in case you can go through the above and think the current state is good to go.
(Whenever you get time - I know you may be busy, I'm an OSS maintainer myself, but looking at the sheer number of PRs open I'd prefer this doesn't get buried if it adds value)
There was a problem hiding this comment.
I think setting the stringer=false annotation is best, so you can provide an implementation that prints the RawExtension type correctly.
Signed-off-by: subhramit <subhramit.bb@live.in>
Signed-off-by: subhramit-suki <sbasu@suki.ai>
Signed-off-by: subhramit-suki <sbasu@suki.ai>
Signed-off-by: subhramit-suki <sbasu@suki.ai>
Signed-off-by: subhramit <subhramit.bb@live.in>
Signed-off-by: subhramit <subhramit.bb@live.in>
This comment was marked as resolved.
This comment was marked as resolved.
| // only observable difference is the ValuesObject rendering. If new fields are | ||
| // added to ApplicationSourceHelm, they must be added here as well - there is | ||
| // no codegen for this method. | ||
| func (h *ApplicationSourceHelm) String() string { |
There was a problem hiding this comment.
All the additional "syntactical" differences from the codegen implementation are enhancements to satisfy the linters.
Semantically it's exactly the same (except for our fix on ValuesObject).
Signed-off-by: subhramit <subhramit.bb@live.in>
| "v1alpha1ApplicationSourceHelm": { | ||
| "type": "object", | ||
| "title": "ApplicationSourceHelm holds helm specific options", | ||
| "title": "ApplicationSourceHelm holds helm specific options\n+protobuf.options.(gogoproto.goproto_stringer)=false", |
agaudreault
left a comment
There was a problem hiding this comment.
LGTM, but it might be better if we can wrap the RawExtension type
Closes #18342
I have used a different approach compared to #23717 by keeping the fix entirely server-side.
In short,
ValuesObjectdumped raw bytes like[123 34 ...]which was both unreadable and large.So by rendering it as YAML instead, the output is human-readable and compact, so it stops flooding Loki storage.
This was achieved by suppressing the stringer at proto-level and providing a custom implementation for
String().Also fixed some wrong log texts in
repository.gowhere cache was being cleared instead of set (and the wording conveyed otherwise).Checklist: