|
4 | 4 | import java.util.ArrayList;
|
5 | 5 | import java.util.Collections;
|
6 | 6 | import java.util.HashMap;
|
| 7 | +import java.util.LinkedHashMap; |
7 | 8 | import java.util.List;
|
8 | 9 | import java.util.Map;
|
9 | 10 | import java.util.Map.Entry;
|
|
33 | 34 |
|
34 | 35 | import static io.javaoperatorsdk.operator.processing.dependent.kubernetes.ResourceRequirementsSanitizer.sanitizeResourceRequirements;
|
35 | 36 |
|
| 37 | +import com.github.difflib.DiffUtils; |
| 38 | +import com.github.difflib.UnifiedDiffUtils; |
| 39 | + |
36 | 40 | /**
|
37 | 41 | * Matches the actual state on the server vs the desired state. Based on the managedFields of SSA.
|
38 | 42 | * <p>
|
@@ -107,20 +111,66 @@ public boolean matches(R actual, R desired, Context<?> context) {
|
107 | 111 |
|
108 | 112 | removeIrrelevantValues(desiredMap);
|
109 | 113 |
|
110 |
| - if (LoggingUtils.isNotSensitiveResource(desired)) { |
111 |
| - logDiff(prunedActual, desiredMap, objectMapper); |
| 114 | + var matches = prunedActual.equals(desiredMap); |
| 115 | + |
| 116 | + if (!matches && log.isDebugEnabled() && LoggingUtils.isNotSensitiveResource(desired)) { |
| 117 | + var diff = getDiff(prunedActual, desiredMap, objectMapper); |
| 118 | + log.debug( |
| 119 | + "Diff between actual and desired state for resource: {} with name: {} in namespace: {} is: \n{}", |
| 120 | + actual.getKind(), actual.getMetadata().getName(), actual.getMetadata().getNamespace(), |
| 121 | + diff); |
112 | 122 | }
|
113 | 123 |
|
114 |
| - return prunedActual.equals(desiredMap); |
| 124 | + return matches; |
115 | 125 | }
|
116 | 126 |
|
117 |
| - private void logDiff(Map<String, Object> prunedActualMap, Map<String, Object> desiredMap, |
| 127 | + private String getDiff(Map<String, Object> prunedActualMap, Map<String, Object> desiredMap, |
118 | 128 | KubernetesSerialization serialization) {
|
119 |
| - if (log.isDebugEnabled()) { |
120 |
| - var actualYaml = serialization.asYaml(prunedActualMap); |
121 |
| - var desiredYaml = serialization.asYaml(desiredMap); |
122 |
| - log.debug("Pruned actual yaml: \n {} \n desired yaml: \n {} ", actualYaml, desiredYaml); |
| 129 | + var actualYaml = serialization.asYaml(sortMap(prunedActualMap)); |
| 130 | + var desiredYaml = serialization.asYaml(sortMap(desiredMap)); |
| 131 | + if (log.isTraceEnabled()) { |
| 132 | + log.trace("Pruned actual resource: \n {} \ndesired resource: \n {} ", actualYaml, |
| 133 | + desiredYaml); |
| 134 | + } |
| 135 | + |
| 136 | + var patch = DiffUtils.diff(actualYaml.lines().toList(), desiredYaml.lines().toList()); |
| 137 | + List<String> unifiedDiff = |
| 138 | + UnifiedDiffUtils.generateUnifiedDiff("", "", actualYaml.lines().toList(), patch, 1); |
| 139 | + return String.join("\n", unifiedDiff); |
| 140 | + } |
| 141 | + |
| 142 | + @SuppressWarnings("unchecked") |
| 143 | + Map<String, Object> sortMap(Map<String, Object> map) { |
| 144 | + List<String> sortedKeys = new ArrayList<>(map.keySet()); |
| 145 | + Collections.sort(sortedKeys); |
| 146 | + |
| 147 | + Map<String, Object> sortedMap = new LinkedHashMap<>(); |
| 148 | + for (String key : sortedKeys) { |
| 149 | + Object value = map.get(key); |
| 150 | + if (value instanceof Map) { |
| 151 | + sortedMap.put(key, sortMap((Map<String, Object>) value)); |
| 152 | + } else if (value instanceof List) { |
| 153 | + sortedMap.put(key, sortListItems((List<Object>) value)); |
| 154 | + } else { |
| 155 | + sortedMap.put(key, value); |
| 156 | + } |
| 157 | + } |
| 158 | + return sortedMap; |
| 159 | + } |
| 160 | + |
| 161 | + @SuppressWarnings("unchecked") |
| 162 | + List<Object> sortListItems(List<Object> list) { |
| 163 | + List<Object> sortedList = new ArrayList<>(); |
| 164 | + for (Object item : list) { |
| 165 | + if (item instanceof Map) { |
| 166 | + sortedList.add(sortMap((Map<String, Object>) item)); |
| 167 | + } else if (item instanceof List) { |
| 168 | + sortedList.add(sortListItems((List<Object>) item)); |
| 169 | + } else { |
| 170 | + sortedList.add(item); |
| 171 | + } |
123 | 172 | }
|
| 173 | + return sortedList; |
124 | 174 | }
|
125 | 175 |
|
126 | 176 | /**
|
|
0 commit comments