Skip to content

Commit

Permalink
feat(jinja2/filters): add builtin filter for merge_strategic
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon McLean committed Jan 13, 2025
1 parent feb5016 commit 9c77a7b
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
4 changes: 4 additions & 0 deletions docs/pages/input_types/jinja.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ We support the following custom filters for use in Jinja2 templates:
=== "`reveal_maybe`"
!!! example "reveal `ref/secret` tag only if `compile --reveal` flag is set"
`{{ "?{base64:my_ref}" | reveal_maybe}}`
=== "Struct"
=== "`merge_strategic`"
!!! example "traverse object(s) and merge lists based on common `name`"
`{{ data | merge_strategic | yaml | trim | indent(6)}}`

!!! tip
You can also provide path to your custom filter modules in CLI. By default, you can put your filters in `lib/jinja2_filters.py` and they will automatically get loaded.
28 changes: 27 additions & 1 deletion kapitan/jinja2_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def load_jinja2_filters(env):
env.filters["reveal_maybe"] = reveal_maybe
env.filters["ternary"] = ternary
env.filters["shuffle"] = randomize_list

env.filters["merge_strategic"] = merge_strategic

def load_module_from_path(env, path):
"""
Expand Down Expand Up @@ -221,3 +221,29 @@ def randomize_list(mylist, seed=None):
except Exception:
pass
return mylist

def merge_strategic(data):
"""
Recursively traverse the input data structure.
- If encountering a list of dicts each with a 'name' key, merge them by name.
- Process nested dictionaries and lists recursively.
"""
if not isinstance(data, (list, dict)):
return data

if isinstance(data, list):
processed_list = [merge_strategic(item) for item in data]

if all(isinstance(item, dict) and 'name' in item for item in processed_list):
merged = {}
for item in processed_list:
key = item['name']
if key not in merged:
merged[key] = {}
merged[key].update(item)
return list(merged.values())
else:
return processed_list

if isinstance(data, dict):
return {key: merge_strategic(value) for key, value in data.items()}

0 comments on commit 9c77a7b

Please sign in to comment.