@@ -18,23 +18,30 @@ import (
1818 "fmt"
1919
2020 "emperror.dev/errors"
21- jsonpatch "github.com/evanphx/json-patch"
2221 json "github.com/json-iterator/go"
2322 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2423 "k8s.io/apimachinery/pkg/runtime"
25- "k8s.io/apimachinery/pkg/util/jsonmergepatch"
26- "k8s.io/apimachinery/pkg/util/strategicpatch"
2724)
2825
29- var DefaultPatchMaker = NewPatchMaker (DefaultAnnotator )
26+ var DefaultPatchMaker = NewPatchMaker (DefaultAnnotator , & K8sStrategicMergePatcher {}, & BaseJSONMergePatcher {})
27+
28+ type Maker interface {
29+ Calculate (currentObject , modifiedObject runtime.Object , opts ... CalculateOption ) (* PatchResult , error )
30+ }
3031
3132type PatchMaker struct {
3233 annotator * Annotator
34+
35+ strategicMergePatcher StrategicMergePatcher
36+ jsonMergePatcher JSONMergePatcher
3337}
3438
35- func NewPatchMaker (annotator * Annotator ) * PatchMaker {
39+ func NewPatchMaker (annotator * Annotator , strategicMergePatcher StrategicMergePatcher , jsonMergePatcher JSONMergePatcher ) Maker {
3640 return & PatchMaker {
3741 annotator : annotator ,
42+
43+ strategicMergePatcher : strategicMergePatcher ,
44+ jsonMergePatcher : jsonMergePatcher ,
3845 }
3946}
4047
@@ -75,28 +82,24 @@ func (p *PatchMaker) Calculate(currentObject, modifiedObject runtime.Object, opt
7582
7683 switch currentObject .(type ) {
7784 default :
78- lookupPatchMeta , err := strategicpatch .NewPatchMetaFromStruct (currentObject )
79- if err != nil {
80- return nil , errors .WrapWithDetails (err , "Failed to lookup patch meta" , "current object" , currentObject )
81- }
82- patch , err = strategicpatch .CreateThreeWayMergePatch (original , modified , current , lookupPatchMeta , true )
85+ patch , err = p .strategicMergePatcher .CreateThreeWayMergePatch (original , modified , current , currentObject )
8386 if err != nil {
8487 return nil , errors .Wrap (err , "Failed to generate strategic merge patch" )
8588 }
8689 // $setElementOrder can make it hard to decide whether there is an actual diff or not.
8790 // In cases like that trying to apply the patch locally on current will make it clear.
8891 if string (patch ) != "{}" {
89- patchCurrent , err := strategicpatch .StrategicMergePatch (current , patch , currentObject )
92+ patchCurrent , err := p . strategicMergePatcher .StrategicMergePatch (current , patch , currentObject )
9093 if err != nil {
9194 return nil , errors .Wrap (err , "Failed to apply patch again to check for an actual diff" )
9295 }
93- patch , err = strategicpatch .CreateTwoWayMergePatch (current , patchCurrent , currentObject )
96+ patch , err = p . strategicMergePatcher .CreateTwoWayMergePatch (current , patchCurrent , currentObject )
9497 if err != nil {
9598 return nil , errors .Wrap (err , "Failed to create patch again to check for an actual diff" )
9699 }
97100 }
98101 case * unstructured.Unstructured :
99- patch , err = unstructuredJsonMergePatch (original , modified , current )
102+ patch , err = p . unstructuredJsonMergePatch (original , modified , current )
100103 if err != nil {
101104 return nil , errors .Wrap (err , "Failed to generate merge patch" )
102105 }
@@ -110,38 +113,38 @@ func (p *PatchMaker) Calculate(currentObject, modifiedObject runtime.Object, opt
110113 }, nil
111114}
112115
113- type PatchResult struct {
114- Patch []byte
115- Current []byte
116- Modified []byte
117- Original []byte
118- }
119-
120- func (p * PatchResult ) IsEmpty () bool {
121- return string (p .Patch ) == "{}"
122- }
123-
124- func (p * PatchResult ) String () string {
125- return fmt .Sprintf ("\n Patch: %s \n Current: %s\n Modified: %s\n Original: %s\n " , p .Patch , p .Current , p .Modified , p .Original )
126- }
127-
128- func unstructuredJsonMergePatch (original , modified , current []byte ) ([]byte , error ) {
129- patch , err := jsonmergepatch .CreateThreeWayJSONMergePatch (original , modified , current )
116+ func (p * PatchMaker ) unstructuredJsonMergePatch (original , modified , current []byte ) ([]byte , error ) {
117+ patch , err := p .jsonMergePatcher .CreateThreeWayJSONMergePatch (original , modified , current )
130118 if err != nil {
131119 return nil , errors .Wrap (err , "Failed to generate merge patch" )
132120 }
133121 // Apply the patch to the current object and create a merge patch to see if there has any effective changes been made
134122 if string (patch ) != "{}" {
135123 // apply the patch
136- patchedCurrent , err := jsonpatch .MergePatch (current , patch )
124+ patchedCurrent , err := p . jsonMergePatcher .MergePatch (current , patch )
137125 if err != nil {
138126 return nil , errors .Wrap (err , "Failed to merge generated patch to current object" )
139127 }
140128 // create the patch again, but now between the current and the patched version of the current object
141- patch , err = jsonpatch .CreateMergePatch (current , patchedCurrent )
129+ patch , err = p . jsonMergePatcher .CreateMergePatch (current , patchedCurrent )
142130 if err != nil {
143131 return nil , errors .Wrap (err , "Failed to create patch between the current and patched current object" )
144132 }
145133 }
146134 return patch , err
147135}
136+
137+ type PatchResult struct {
138+ Patch []byte
139+ Current []byte
140+ Modified []byte
141+ Original []byte
142+ }
143+
144+ func (p * PatchResult ) IsEmpty () bool {
145+ return string (p .Patch ) == "{}"
146+ }
147+
148+ func (p * PatchResult ) String () string {
149+ return fmt .Sprintf ("\n Patch: %s \n Current: %s\n Modified: %s\n Original: %s\n " , p .Patch , p .Current , p .Modified , p .Original )
150+ }
0 commit comments