@@ -48,9 +48,8 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []*
4848
4949 for _ , p := range e .JSONPatches {
5050 var (
51- resourceJSON []byte
52- dest cachetypes.Resource
53- err error
51+ dests []cachetypes.Resource
52+ err error
5453 )
5554
5655 if err := p .Operation .Validate (); err != nil {
@@ -96,61 +95,80 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []*
9695 continue
9796 }
9897
99- // find the resource to patch and convert it to JSON
100- dest , err = findXdsResource (tCtx , p )
98+ // find the resources to patch and convert it to JSON
99+ dests , err = findXdsResources (tCtx , p )
101100 if err != nil {
102- if errors .Is (err , errResourceNotFound ) {
103- tn := typedName {p .Type , p .Name }
104- notFoundResources = append (notFoundResources , tn .String ())
105- continue
106- }
107-
108101 tErrs = errors .Join (tErrs , err )
109102 continue
110103 }
111104
112- resourceJSON , err = jsonMarshalOpts .Marshal (dest )
113- if err != nil {
114- tErr := fmt .Errorf ("unable to marshal xds resource %s, err: %w" , p .Type , err )
115- tErrs = errors .Join (tErrs , tErr )
105+ if len (dests ) == 0 {
106+ tn := typedName {p .Type , p .Name }
107+ notFoundResources = append (notFoundResources , tn .String ())
116108 continue
117109 }
118110
119- modifiedJSON , err := jsonpatch .ApplyJSONPatches (resourceJSON , p .Operation )
120- if err != nil {
121- tErrs = errors .Join (tErrs , err )
122- continue
123- }
111+ var destsError error
112+ var destsPatched bool
113+ for _ , dest := range dests {
114+ var (
115+ resourceJSON []byte
116+ modifiedJSON []byte
117+ )
124118
125- // Unmarshal back to typed resource
126- // Use a temp staging variable that can be marshalled
127- // into and validated before saving it into the xds output resource
128- temp , err := getXdsResourceType (p .Type )
129- if err != nil {
130- tErrs = errors .Join (tErrs , err )
131- continue
132- }
119+ resourceJSON , err = jsonMarshalOpts .Marshal (dest )
120+ if err != nil {
121+ tErr := fmt .Errorf ("unable to marshal xds resource %s, err: %w" , p .Type , err )
122+ destsError = errors .Join (destsError , tErr )
123+ continue
124+ }
133125
134- if err = protojson . Unmarshal ( modifiedJSON , temp ); err != nil {
135- tErr := errors . New ( unmarshalErrorMessage ( err , string ( modifiedJSON )))
136- tErrs = errors .Join (tErrs , tErr )
137- continue
138- }
126+ modifiedJSON , err = jsonpatch . ApplyJSONPatches ( resourceJSON , p . Operation )
127+ if err != nil {
128+ destsError = errors .Join (destsError , err )
129+ continue
130+ }
139131
140- // Validate the patched resource
141- validator , ok := temp .(interface { Validate () error })
142- if ok {
143- if err = validator .Validate (); err != nil {
144- tErr := fmt .Errorf ("validation failed for xds resource %s, err:%s" , p .Type , err .Error ())
145- tErrs = errors .Join (tErrs , tErr )
132+ // Unmarshal back to typed resource
133+ // Use a temp staging variable that can be marshalled
134+ // into and validated before saving it into the xds output resource
135+ temp , err := getXdsResourceType (p .Type )
136+ if err != nil {
137+ destsError = errors .Join (destsError , err )
138+ continue
139+ }
140+
141+ if err = protojson .Unmarshal (modifiedJSON , temp ); err != nil {
142+ tErr := errors .New (unmarshalErrorMessage (err , string (modifiedJSON )))
143+ destsError = errors .Join (destsError , tErr )
144+ continue
145+ }
146+
147+ // Validate the patched resource
148+ validator , ok := temp .(interface { Validate () error })
149+ if ok {
150+ if err = validator .Validate (); err != nil {
151+ tErr := fmt .Errorf ("validation failed for xds resource %s, err:%s" , p .Type , err .Error ())
152+ destsError = errors .Join (destsError , tErr )
153+ continue
154+ }
155+ }
156+
157+ if err = deepCopyPtr (temp , dest ); err != nil {
158+ tErr := fmt .Errorf ("unable to copy xds resource %s, err: %w" , p .Type , err )
159+ destsError = errors .Join (destsError , tErr )
146160 continue
147161 }
162+
163+ // Mark that at least one dest has been patched successfully,
164+ // so that we can report partial success if there are multiple dests and some of them fail
165+ destsPatched = true
148166 }
149167
150- if err = deepCopyPtr ( temp , dest ); err != nil {
151- tErr := fmt . Errorf ( "unable to copy xds resource %s, err: %w" , p . Type , err )
152- tErrs = errors . Join ( tErrs , tErr )
153- continue
168+ // If there are multiple dests and some of them fail,
169+ // consider it as successful and ignore the failures to patch other dests.
170+ if ! destsPatched && destsError != nil {
171+ tErrs = errors . Join ( tErrs , destsError )
154172 }
155173 }
156174
@@ -192,42 +210,28 @@ func getXdsResourceType(resourceType string) (cachetypes.Resource, error) {
192210 }
193211}
194212
195- var (
196- errResourceNotFound = errors .New ("resource not found" )
197- jsonMarshalOpts = protojson.MarshalOptions {
198- UseProtoNames : true ,
199- }
200- )
213+ var jsonMarshalOpts = protojson.MarshalOptions {
214+ UseProtoNames : true ,
215+ }
201216
202- // findXdsResource return the XDS resource to patch
203- // TODO: return multiple resources
204- func findXdsResource (tCtx * types.ResourceVersionTable , p * ir.JSONPatchConfig ) (cachetypes.Resource , error ) {
217+ func findXdsResources (tCtx * types.ResourceVersionTable , p * ir.JSONPatchConfig ) ([]cachetypes.Resource , error ) {
218+ var resources []cachetypes.Resource
205219 switch p .Type {
206220 case resourcev3 .ListenerType :
207- if r := findXdsListener (tCtx , p .Name ); r != nil {
208- return r , nil
209- }
221+ resources = findXdsListeners (tCtx , p .Name )
210222 case resourcev3 .RouteType :
211- if r := findXdsRouteConfig (tCtx , p .Name ); r != nil {
212- return r , nil
213- }
223+ resources = findXdsRouteConfigs (tCtx , p .Name )
214224 case resourcev3 .ClusterType :
215- if r := findXdsCluster (tCtx , p .Name ); r != nil {
216- return r , nil
217- }
225+ resources = findXdsClusters (tCtx , p .Name )
218226 case resourcev3 .EndpointType :
219- if r := findXdsEndpoint (tCtx , p .Name ); r != nil {
220- return r , nil
221- }
227+ resources = findXdsEndpoints (tCtx , p .Name )
222228 case resourcev3 .SecretType :
223- if r := findXdsSecret (tCtx , p .Name ); r != nil {
224- return r , nil
225- }
229+ resources = findXdsSecrets (tCtx , p .Name )
226230 default :
227231 return nil , fmt .Errorf ("unsupported patch type %s" , p .Type )
228232 }
229233
230- return nil , errResourceNotFound
234+ return resources , nil
231235}
232236
233237var unescaper = strings .NewReplacer (" " , " " )
0 commit comments