Skip to content

Commit e20fb50

Browse files
committed
support references that return multiple items for related resources
On-behalf-of: @SAP [email protected]
1 parent c083316 commit e20fb50

File tree

1 file changed

+50
-28
lines changed

1 file changed

+50
-28
lines changed

internal/sync/syncer_related.go

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -251,27 +251,25 @@ func resolveRelatedResourceObjects(relatedOrigin, relatedDest syncSide, relRes s
251251
func resolveRelatedResourceOriginNamespaces(relatedOrigin, relatedDest syncSide, origin syncagentv1alpha1.RelatedResourceOrigin, spec syncagentv1alpha1.RelatedResourceObjectSpec) (map[string]string, error) {
252252
switch {
253253
case spec.Reference != nil:
254-
originNamespace, err := resolveObjectReference(relatedOrigin.object, *spec.Reference)
254+
originNamespaces, err := resolveObjectReference(relatedOrigin.object, *spec.Reference)
255255
if err != nil {
256256
return nil, err
257257
}
258258

259-
if originNamespace == "" {
259+
if len(originNamespaces) == 0 {
260260
return nil, nil
261261
}
262262

263-
destNamespace, err := resolveObjectReference(relatedDest.object, *spec.Reference)
263+
destNamespaces, err := resolveObjectReference(relatedDest.object, *spec.Reference)
264264
if err != nil {
265265
return nil, err
266266
}
267267

268-
if destNamespace == "" {
269-
return nil, nil
268+
if len(destNamespaces) != len(originNamespaces) {
269+
return nil, fmt.Errorf("cannot sync related resources: found %d namespaces on the origin, but %d on the destination side", len(originNamespaces), len(destNamespaces))
270270
}
271271

272-
return map[string]string{
273-
originNamespace: destNamespace,
274-
}, nil
272+
return mapSlices(originNamespaces, destNamespaces), nil
275273

276274
case spec.Selector != nil:
277275
namespaces := &corev1.NamespaceList{}
@@ -327,6 +325,22 @@ func resolveRelatedResourceOriginNamespaces(relatedOrigin, relatedDest syncSide,
327325
}
328326
}
329327

328+
func mapSlices(a, b []string) map[string]string {
329+
mapping := map[string]string{}
330+
for i, aItem := range a {
331+
bItem := b[i]
332+
333+
// ignore any origin<->dest pair where either of the sides is empty
334+
if bItem == "" || aItem == "" {
335+
continue
336+
}
337+
338+
mapping[aItem] = bItem
339+
}
340+
341+
return mapping
342+
}
343+
330344
func resolveRelatedResourceObjectsInNamespaces(relatedOrigin, relatedDest syncSide, relRes syncagentv1alpha1.RelatedResourceSpec, spec syncagentv1alpha1.RelatedResourceObjectSpec, namespaceMap map[string]string) ([]resolvedObject, error) {
331345
result := []resolvedObject{}
332346

@@ -368,27 +382,25 @@ func resolveRelatedResourceObjectsInNamespaces(relatedOrigin, relatedDest syncSi
368382
func resolveRelatedResourceObjectsInNamespace(relatedOrigin, relatedDest syncSide, relRes syncagentv1alpha1.RelatedResourceSpec, spec syncagentv1alpha1.RelatedResourceObjectSpec, namespace string) (map[string]string, error) {
369383
switch {
370384
case spec.Reference != nil:
371-
originName, err := resolveObjectReference(relatedOrigin.object, *spec.Reference)
385+
originNames, err := resolveObjectReference(relatedOrigin.object, *spec.Reference)
372386
if err != nil {
373387
return nil, err
374388
}
375389

376-
if originName == "" {
390+
if len(originNames) == 0 {
377391
return nil, nil
378392
}
379393

380-
destName, err := resolveObjectReference(relatedDest.object, *spec.Reference)
394+
destNames, err := resolveObjectReference(relatedDest.object, *spec.Reference)
381395
if err != nil {
382396
return nil, err
383397
}
384398

385-
if destName == "" {
386-
return nil, nil
399+
if len(destNames) != len(originNames) {
400+
return nil, fmt.Errorf("cannot sync related resources: found %d names on the origin, but %d on the destination side", len(originNames), len(destNames))
387401
}
388402

389-
return map[string]string{
390-
originName: destName,
391-
}, nil
403+
return mapSlices(originNames, destNames), nil
392404

393405
case spec.Selector != nil:
394406
originObjects := &unstructured.UnstructuredList{}
@@ -447,34 +459,44 @@ func resolveRelatedResourceObjectsInNamespace(relatedOrigin, relatedDest syncSid
447459
}
448460
}
449461

450-
func resolveObjectReference(object *unstructured.Unstructured, ref syncagentv1alpha1.RelatedResourceObjectReference) (string, error) {
462+
func resolveObjectReference(object *unstructured.Unstructured, ref syncagentv1alpha1.RelatedResourceObjectReference) ([]string, error) {
451463
data, err := object.MarshalJSON()
452464
if err != nil {
453-
return "", err
465+
return nil, err
454466
}
455467

456468
return resolveReference(data, ref)
457469
}
458470

459-
func resolveReference(jsonData []byte, ref syncagentv1alpha1.RelatedResourceObjectReference) (string, error) {
460-
gval := gjson.Get(string(jsonData), ref.Path)
461-
if !gval.Exists() {
462-
return "", nil
471+
func resolveReference(jsonData []byte, ref syncagentv1alpha1.RelatedResourceObjectReference) ([]string, error) {
472+
result := gjson.Get(string(jsonData), ref.Path)
473+
if !result.Exists() {
474+
return nil, nil
463475
}
464476

465-
// this does apply some coalescing, like turning numbers into strings
466-
strVal := gval.String()
477+
var values []string
478+
if result.IsArray() {
479+
for _, elem := range result.Array() {
480+
values = append(values, strings.TrimSpace(elem.String()))
481+
}
482+
} else {
483+
values = append(values, strings.TrimSpace(result.String()))
484+
}
467485

468486
if re := ref.Regex; re != nil {
469487
var err error
470488

471-
strVal, err = applyRegularExpression(strVal, *re)
472-
if err != nil {
473-
return "", err
489+
for i, value := range values {
490+
value, err = applyRegularExpression(value, *re)
491+
if err != nil {
492+
return nil, err
493+
}
494+
495+
values[i] = value
474496
}
475497
}
476498

477-
return strVal, nil
499+
return values, nil
478500
}
479501

480502
// applyTemplate is used after a label selector has been applied and a list of namespaces or objects

0 commit comments

Comments
 (0)