Skip to content

[Fix] Add SanitizePattern to trim whitespace and fix YAML manifest exports - #1037

Open
YASHMAHAKAL wants to merge 2 commits into
meshery:masterfrom
YASHMAHAKAL:fix/sanitize-pattern-whitespace
Open

[Fix] Add SanitizePattern to trim whitespace and fix YAML manifest exports#1037
YASHMAHAKAL wants to merge 2 commits into
meshery:masterfrom
YASHMAHAKAL:fix/sanitize-pattern-whitespace

Conversation

@YASHMAHAKAL

@YASHMAHAKAL YASHMAHAKAL commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Description

This PR introduces a robust server-side sanitization utility designed to prevent YAML quoting artifacts in exported Kubernetes manifests.

When users accidentally type trailing whitespace in the UI, yaml.v3 strictly preserves it upon export by wrapping keys and values in single quotes (e.g., 'storage ': 1Gi), which causes the manifest to fail Kubernetes validation. This PR adds a data-scrubbing step that can be called at the persistence boundary to prevent this dirty data from ever reaching the database.

Changes Made:

  • Added SanitizePattern alongside helper functions (sanitizeConfigMap, sanitizeConfigValue) to recursively traverse a pattern's Configuration map.
  • Automatically trims leading and trailing whitespace from all string keys and string values, as well as the component DisplayName.
  • Explicitly passes bool, int64, float64, and nil through unchanged to guarantee type safety and prevent schema data corruption.
  • Added 6 comprehensive unit tests covering edge cases (nil maps, empty components, type-preservation, and value-trimming).

Related Issue:
Fixes #1036

Signed commits

  • Yes, I signed my commits.

…iguration

When a Meshery design is exported as a Kubernetes manifest (or Helm chart),
gopkg.in/yaml.v3 quotes map keys and string values that contain leading or
trailing whitespace. This produces invalid-looking output such as:

  'storage ': 2Gi   (should be: storage: 2Gi)
  name: 'test-volume ' (should be: name: test-volume)

The root cause is that whitespace entered via the RJSF form (particularly the
additionalProperties key editor) is stored verbatim in comp.Configuration and
then passed through the K8s converter unchanged.

SanitizePattern recursively trims every string key and string value inside
each component's Configuration map, and also trims DisplayName. Non-string
leaves (bool, int, float64, nil) are passed through unchanged to preserve
schema-typed fields.

Callers: invoke SanitizePattern at the design-save boundary in
meshery/server alongside DehydratePattern (handlePatternPOST).

Signed-off-by: Yash Mahajan <mahajanyash.02@gmail.com>
Signed-off-by: YASHMAHAKAL <yvsst01@gmail.com>

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces the SanitizePattern function and associated helper functions to recursively trim leading and trailing whitespace from component display names and configuration map keys and values, preventing unwanted YAML quoting issues. It also includes comprehensive unit tests for these changes. The review feedback highlights a potential nil pointer dereference in SanitizePattern if the input pattern or any of its components are nil, and suggests adding defensive checks to ensure robustness.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread models/patterns/pattern.go
…afety

Add defensive nil checks to SanitizePattern:
- Guard against nil *PatternFile pointer (p == nil -> return)
- Guard against nil component pointers in p.Components slice (comp == nil -> continue)

The current Meshery call site at handlePatternPOST always passes a
non-nil pointer (&requestPayload.DesignFile), so these guards do not
change behaviour for the existing consumer. They are added as a public
library API contract so that any future caller is safe regardless of
input.

Added two new unit tests:
- TestSanitizePattern_NilPatternFileIsNoop
- TestSanitizePattern_NilComponentInSliceIsSkipped

Signed-off-by: Yash Mahajan <mahajanyash.02@gmail.com>
Signed-off-by: YASHMAHAKAL <yvsst01@gmail.com>
@leecalcote

Copy link
Copy Markdown
Member

Work outside of relationship definitions is on-hold for @YASHMAHAKAL.

@leecalcote leecalcote added the pr/on hold PR/Issue on hold label Jun 26, 2026
@YASHMAHAKAL

Copy link
Copy Markdown
Contributor Author

Work outside of relationship definitions is on-hold for @YASHMAHAKAL.

sure, i'll focus on relationship definitions for now

@yi-nuo426
yi-nuo426 requested a review from Copilot July 7, 2026 04:21
@yi-nuo426 yi-nuo426 removed the pr/on hold PR/Issue on hold label Jul 7, 2026

@yi-nuo426 yi-nuo426 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.

It seems like this could be done more efficiently and with less custom-written code.

Copilot AI 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.

Pull request overview

This PR adds a patterns-level sanitization utility in MeshKit to prevent YAML export/serialization issues caused by incidental leading/trailing whitespace in design configuration keys/values (and component display names), along with unit tests validating the sanitizer’s behavior.

Changes:

  • Added SanitizePattern plus recursive helpers to trim whitespace in component Configuration maps and DisplayName.
  • Implemented recursive traversal for nested map[string]interface{} and []interface{} while passing through non-string leaf types unchanged.
  • Added unit tests covering display name trimming, nested key/value trimming, nil/no-op behavior, and non-string leaf preservation.

Reviewed changes

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

File Description
models/patterns/pattern.go Introduces SanitizePattern and recursive sanitization helpers for configuration maps/values.
models/patterns/pattern_sanitize_test.go Adds unit tests to validate trimming behavior and type preservation.

Comment on lines +111 to +120
func sanitizeConfigMap(m map[string]interface{}) map[string]interface{} {
if m == nil {
return nil
}
result := make(map[string]interface{}, len(m))
for k, v := range m {
result[strings.TrimSpace(k)] = sanitizeConfigValue(v)
}
return result
}
Comment on lines +77 to +100
func TestSanitizePattern_PreservesNonStringLeaves(t *testing.T) {
// bool, int, float, nil must pass through unchanged.
p := makePatternFile("comp", map[string]interface{}{
"replicas": 3,
"enabled": true,
"ratio": 1.5,
"optionNil": nil,
})
patterns.SanitizePattern(p)

cfg := p.Components[0].Configuration
if cfg["replicas"] != 3 {
t.Errorf("replicas changed: %v", cfg["replicas"])
}
if cfg["enabled"] != true {
t.Errorf("enabled changed: %v", cfg["enabled"])
}
if cfg["ratio"] != 1.5 {
t.Errorf("ratio changed: %v", cfg["ratio"])
}
if cfg["optionNil"] != nil {
t.Errorf("optionNil changed: %v", cfg["optionNil"])
}
}
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.

[Feature]: Add recursive whitespace sanitizer to prevent YAML quoting artifacts

4 participants