@@ -47,7 +47,7 @@ type dryRunSSAPatchInput struct {
47
47
}
48
48
49
49
// dryRunSSAPatch uses server side apply dry run to determine if the operation is going to change the actual object.
50
- func dryRunSSAPatch (ctx context.Context , dryRunCtx * dryRunSSAPatchInput ) (bool , bool , error ) {
50
+ func dryRunSSAPatch (ctx context.Context , dryRunCtx * dryRunSSAPatchInput ) (bool , bool , [] byte , error ) {
51
51
// Compute a request identifier.
52
52
// The identifier is unique for a specific request to ensure we don't have to re-run the request
53
53
// once we found out that it would not produce a diff.
@@ -56,13 +56,13 @@ func dryRunSSAPatch(ctx context.Context, dryRunCtx *dryRunSSAPatchInput) (bool,
56
56
// This ensures that we re-run the request as soon as either original or modified changes.
57
57
requestIdentifier , err := ssa .ComputeRequestIdentifier (dryRunCtx .client .Scheme (), dryRunCtx .originalUnstructured , dryRunCtx .modifiedUnstructured )
58
58
if err != nil {
59
- return false , false , err
59
+ return false , false , nil , err
60
60
}
61
61
62
62
// Check if we already ran this request before by checking if the cache already contains this identifier.
63
63
// Note: We only add an identifier to the cache if the result of the dry run was no diff.
64
64
if exists := dryRunCtx .ssaCache .Has (requestIdentifier ); exists {
65
- return false , false , nil
65
+ return false , false , nil , nil
66
66
}
67
67
68
68
// For dry run we use the same options as for the intent but with adding metadata.managedFields
@@ -74,17 +74,17 @@ func dryRunSSAPatch(ctx context.Context, dryRunCtx *dryRunSSAPatchInput) (bool,
74
74
75
75
// Add TopologyDryRunAnnotation to notify validation webhooks to skip immutability checks.
76
76
if err := unstructured .SetNestedField (dryRunCtx .originalUnstructured .Object , "" , "metadata" , "annotations" , clusterv1 .TopologyDryRunAnnotation ); err != nil {
77
- return false , false , errors .Wrap (err , "failed to add topology dry-run annotation to original object" )
77
+ return false , false , nil , errors .Wrap (err , "failed to add topology dry-run annotation to original object" )
78
78
}
79
79
if err := unstructured .SetNestedField (dryRunCtx .modifiedUnstructured .Object , "" , "metadata" , "annotations" , clusterv1 .TopologyDryRunAnnotation ); err != nil {
80
- return false , false , errors .Wrap (err , "failed to add topology dry-run annotation to modified object" )
80
+ return false , false , nil , errors .Wrap (err , "failed to add topology dry-run annotation to modified object" )
81
81
}
82
82
83
83
// Do a server-side apply dry-run with modifiedUnstructured to get the updated object.
84
84
err = dryRunCtx .client .Patch (ctx , dryRunCtx .modifiedUnstructured , client .Apply , client .DryRunAll , client .FieldOwner (TopologyManagerName ), client .ForceOwnership )
85
85
if err != nil {
86
86
// This catches errors like metadata.uid changes.
87
- return false , false , errors .Wrap (err , "server side apply dry-run failed for modified object" )
87
+ return false , false , nil , errors .Wrap (err , "server side apply dry-run failed for modified object" )
88
88
}
89
89
90
90
// Do a server-side apply dry-run with originalUnstructured to ensure the latest defaulting is applied.
@@ -109,7 +109,7 @@ func dryRunSSAPatch(ctx context.Context, dryRunCtx *dryRunSSAPatchInput) (bool,
109
109
dryRunCtx .originalUnstructured .SetManagedFields (nil )
110
110
err = dryRunCtx .client .Patch (ctx , dryRunCtx .originalUnstructured , client .Apply , client .DryRunAll , client .FieldOwner (TopologyManagerName ), client .ForceOwnership )
111
111
if err != nil {
112
- return false , false , errors .Wrap (err , "server side apply dry-run failed for original object" )
112
+ return false , false , nil , errors .Wrap (err , "server side apply dry-run failed for original object" )
113
113
}
114
114
// Restore managed fields.
115
115
dryRunCtx .originalUnstructured .SetManagedFields (originalUnstructuredManagedFieldsBeforeSSA )
@@ -124,7 +124,7 @@ func dryRunSSAPatch(ctx context.Context, dryRunCtx *dryRunSSAPatchInput) (bool,
124
124
// Please note that if other managers made changes to fields that we care about and thus ownership changed,
125
125
// this would affect our managed fields as well and we would still detect it by diffing our managed fields.
126
126
if err := cleanupManagedFieldsAndAnnotation (dryRunCtx .modifiedUnstructured ); err != nil {
127
- return false , false , errors .Wrap (err , "failed to filter topology dry-run annotation on modified object" )
127
+ return false , false , nil , errors .Wrap (err , "failed to filter topology dry-run annotation on modified object" )
128
128
}
129
129
130
130
// Also run the function for the originalUnstructured to remove the managedField
@@ -135,7 +135,7 @@ func dryRunSSAPatch(ctx context.Context, dryRunCtx *dryRunSSAPatchInput) (bool,
135
135
// Please note that if other managers made changes to fields that we care about and thus ownership changed,
136
136
// this would affect our managed fields as well and we would still detect it by diffing our managed fields.
137
137
if err := cleanupManagedFieldsAndAnnotation (dryRunCtx .originalUnstructured ); err != nil {
138
- return false , false , errors .Wrap (err , "failed to filter topology dry-run annotation on original object" )
138
+ return false , false , nil , errors .Wrap (err , "failed to filter topology dry-run annotation on original object" )
139
139
}
140
140
141
141
// Drop the other fields which are not part of our intent.
@@ -145,33 +145,48 @@ func dryRunSSAPatch(ctx context.Context, dryRunCtx *dryRunSSAPatchInput) (bool,
145
145
// Compare the output of dry run to the original object.
146
146
originalJSON , err := json .Marshal (dryRunCtx .originalUnstructured )
147
147
if err != nil {
148
- return false , false , err
148
+ return false , false , nil , err
149
149
}
150
150
modifiedJSON , err := json .Marshal (dryRunCtx .modifiedUnstructured )
151
151
if err != nil {
152
- return false , false , err
152
+ return false , false , nil , err
153
153
}
154
154
155
155
rawDiff , err := jsonpatch .CreateMergePatch (originalJSON , modifiedJSON )
156
156
if err != nil {
157
- return false , false , err
157
+ return false , false , nil , err
158
158
}
159
159
160
160
// Determine if there are changes to the spec and object.
161
161
diff := & unstructured.Unstructured {}
162
162
if err := json .Unmarshal (rawDiff , & diff .Object ); err != nil {
163
- return false , false , err
163
+ return false , false , nil , err
164
164
}
165
165
166
166
hasChanges := len (diff .Object ) > 0
167
167
_ , hasSpecChanges := diff .Object ["spec" ]
168
168
169
+ var changes []byte
170
+ if hasChanges {
171
+ // Cleanup diff by dropping .metadata.managedFields.
172
+ ssa .FilterIntent (& ssa.FilterIntentInput {
173
+ Path : contract.Path {},
174
+ Value : diff .Object ,
175
+ ShouldFilter : ssa .IsPathIgnored ([]contract.Path {[]string {"metadata" , "managedFields" }}),
176
+ })
177
+
178
+ changes , err = json .Marshal (diff .Object )
179
+ if err != nil {
180
+ return false , false , nil , errors .Wrapf (err , "failed to marshal diff" )
181
+ }
182
+ }
183
+
169
184
// If there is no diff add the request identifier to the cache.
170
185
if ! hasChanges {
171
186
dryRunCtx .ssaCache .Add (requestIdentifier )
172
187
}
173
188
174
- return hasChanges , hasSpecChanges , nil
189
+ return hasChanges , hasSpecChanges , changes , nil
175
190
}
176
191
177
192
// cleanupManagedFieldsAndAnnotation adjusts the obj to remove the topology.cluster.x-k8s.io/dry-run
0 commit comments