core(deploy): recurse into nested diffs + unquote scalar values in DirtyStateCalculator
- compareJson now recurses when both nodes are ObjectNode, so nested maps (tracedProcessors, routeRecording, routeSamplingRates) produce deep paths like agentConfig.tracedProcessors.proc-1 instead of a blob diff - Extract nodeToString helper: value nodes use asText() (strips JSON quotes), null becomes "(none)", arrays/objects get compact JSON - Apply nodeToString in both diff-emission paths (top-level mismatch + leaf) - Add three new tests: nullAgentConfigInSnapshot, nestedAgentField_reportsDeepPath, stringField_differenceValueIsUnquoted (8 tests total, all pass) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -51,7 +51,7 @@ public class DirtyStateCalculator {
|
||||
if (!(desired instanceof ObjectNode desiredObj) || !(deployed instanceof ObjectNode deployedObj)) {
|
||||
if (!Objects.equals(desired, deployed)) {
|
||||
diffs.add(new DirtyStateResult.Difference(prefix,
|
||||
String.valueOf(desired), String.valueOf(deployed)));
|
||||
nodeToString(desired), nodeToString(deployed)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -61,10 +61,18 @@ public class DirtyStateCalculator {
|
||||
for (String key : keys) {
|
||||
JsonNode d = desiredObj.get(key);
|
||||
JsonNode p = deployedObj.get(key);
|
||||
if (!Objects.equals(d, p)) {
|
||||
diffs.add(new DirtyStateResult.Difference(prefix + "." + key,
|
||||
String.valueOf(d), String.valueOf(p)));
|
||||
if (Objects.equals(d, p)) continue;
|
||||
if (d instanceof ObjectNode && p instanceof ObjectNode) {
|
||||
compareJson(prefix + "." + key, d, p, diffs);
|
||||
} else {
|
||||
diffs.add(new DirtyStateResult.Difference(prefix + "." + key, nodeToString(d), nodeToString(p)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String nodeToString(JsonNode n) {
|
||||
if (n == null) return "(none)";
|
||||
if (n.isValueNode()) return n.asText();
|
||||
return n.toString(); // arrays/objects: compact JSON
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,4 +88,57 @@ class DirtyStateCalculatorTest {
|
||||
assertThat(result.differences()).extracting(DirtyStateResult.Difference::field)
|
||||
.contains("containerConfig.memoryLimitMb");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nullAgentConfigInSnapshot_marksAgentConfigDiff() {
|
||||
DirtyStateCalculator calc = new DirtyStateCalculator();
|
||||
ApplicationConfig desired = new ApplicationConfig();
|
||||
desired.setSamplingRate(1.0);
|
||||
UUID jarId = UUID.randomUUID();
|
||||
DeploymentConfigSnapshot snap = new DeploymentConfigSnapshot(jarId, null, Map.of());
|
||||
|
||||
DirtyStateResult result = calc.compute(jarId, desired, Map.of(), snap);
|
||||
|
||||
assertThat(result.dirty()).isTrue();
|
||||
assertThat(result.differences()).extracting(DirtyStateResult.Difference::field)
|
||||
.contains("agentConfig");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nestedAgentField_reportsDeepPath() {
|
||||
DirtyStateCalculator calc = new DirtyStateCalculator();
|
||||
|
||||
ApplicationConfig deployed = new ApplicationConfig();
|
||||
deployed.setTracedProcessors(Map.of("proc-1", "DEBUG"));
|
||||
ApplicationConfig desired = new ApplicationConfig();
|
||||
desired.setTracedProcessors(Map.of("proc-1", "TRACE"));
|
||||
UUID jarId = UUID.randomUUID();
|
||||
DeploymentConfigSnapshot snap = new DeploymentConfigSnapshot(jarId, deployed, Map.of());
|
||||
|
||||
DirtyStateResult result = calc.compute(jarId, desired, Map.of(), snap);
|
||||
|
||||
assertThat(result.dirty()).isTrue();
|
||||
assertThat(result.differences()).extracting(DirtyStateResult.Difference::field)
|
||||
.contains("agentConfig.tracedProcessors.proc-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void stringField_differenceValueIsUnquoted() {
|
||||
DirtyStateCalculator calc = new DirtyStateCalculator();
|
||||
|
||||
ApplicationConfig deployed = new ApplicationConfig();
|
||||
deployed.setApplicationLogLevel("INFO");
|
||||
ApplicationConfig desired = new ApplicationConfig();
|
||||
desired.setApplicationLogLevel("DEBUG");
|
||||
UUID jarId = UUID.randomUUID();
|
||||
DeploymentConfigSnapshot snap = new DeploymentConfigSnapshot(jarId, deployed, Map.of());
|
||||
|
||||
DirtyStateResult result = calc.compute(jarId, desired, Map.of(), snap);
|
||||
|
||||
DirtyStateResult.Difference diff = result.differences().stream()
|
||||
.filter(d -> d.field().equals("agentConfig.applicationLogLevel"))
|
||||
.findFirst().orElseThrow();
|
||||
assertThat(diff.staged()).isEqualTo("DEBUG");
|
||||
assertThat(diff.deployed()).isEqualTo("INFO");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user