Skip to content

Conversation

@Hazel-Datastax
Copy link
Contributor

What this PR does:
Sample program for YAML file patching abilities

Which issue(s) this PR fixes:
Fixes #NA

Checklist

  • Changes manually tested
  • Automated Tests added/updated
  • Documentation added/updated
  • CLA Signed: DataStax CLA

@Hazel-Datastax Hazel-Datastax requested a review from a team as a code owner September 25, 2025 18:56
Copy link
Contributor

@amorton amorton left a comment

Choose a reason for hiding this comment

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

ok, lets make some changes to this is more a basic JsonMerger.

We will sync on the next ticket to handle the Yaml merging

}

/** Core merge logic following the documented semantics. */
public JsonNode mergeNodes(JsonNode base, JsonNode patch) {
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we have our own logic and not using something like https://github.com/java-json-tools/json-patch ?

should add some comments.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think use JSON Patch would not help here -- it's standard for defining stand-alone patch definitions to use for merging changes (diffs) across documents, bit like unix diff and patch commands. But it would not help here where task is updating one document with another
(not sure I am explaining this well).

Renaming of second document as overrides or something (instead of patch) would help understand the difference.

}

/** Merge two YAML strings and return the merged node. */
public JsonNode mergeToNode(String baseYaml, String patchYaml) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Unused, do we need this ?

}

/** Serialize a node back to a YAML string. */
public String toYaml(JsonNode node) {
Copy link
Contributor

Choose a reason for hiding this comment

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

unused, do we need this ?

}

/** Merge two YAML strings and return the merged YAML string. */
public String mergeYamlStrings(String baseYaml, String patchYaml) {
Copy link
Contributor

Choose a reason for hiding this comment

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

thinking about this - remove the two mergeYaml* functions and rename to JsonMerger. Can also make the mergeNodes method static.

the caller will be responsble for reading the YAML and putting back to YAML.

the reason is we will want to have better control of errors when reading the yaml, e.g. what if the patch YAML is invalid ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Merging functionality is format-agnostic, too, (even if type is called JsonNode) which makes it usable for JSON, YAML and other Jackson-supported formats (XML, Avro, Protobuf...) should those ever be needed.

if (node.isObject() || node.isArray()) {
return node.deepCopy();
}
if (node instanceof ValueNode) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this feels like a future bug, when if the caller changed the vlue of the returned ValueNode ? we shoud not return any of the same objects.

Copy link
Contributor

Choose a reason for hiding this comment

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

ValueNodes are fully immutable, cannot be changed and meant to be shared/reused.
(I agree with not sharing mutable ArrayNodes and ObjectNodes of course)

return deepCopy(patch);
}

private JsonNode deepCopy(JsonNode node) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this can be cleaner using a modern switch on node.

case for null, case for ValueNode, and default is call deepCopy()


// If both are arrays, replace entirely with patch (no element-wise merging)
if (base.isArray() && patch.isArray()) {
return ((ArrayNode) patch).deepCopy();
Copy link
Contributor

Choose a reason for hiding this comment

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

for consistency, can we call our deepCopy() below ?

but we may not even need this check, because the code below calls deepCopy() anyway

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class YamlMergerTest {
Copy link
Contributor

Choose a reason for hiding this comment

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

we should simplify these tests to just be about testing the merging without the complexity of the embedding config or other faked examples or reading other config files.

so very simple tests that make it easy to see the yaml changes.

will need to load the yaml into a JsonNode in this test class because of other changes on the YamlMerger - see comments there.

Copy link
Contributor

@amorton amorton left a comment

Choose a reason for hiding this comment

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

hit wrong button, we want to make changes before merging

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.

4 participants