Summary
When core.helm.local_charts: true is set AND the component chart under /tmp/sdcore-helm-charts/5g-control-plane/ has no charts/ subdirectory (i.e. helm dep up has never been run), the task at deps/5gc/roles/core/tasks/install.yml:170 (require manual 5gc-cp helm dependency update when charts are missing) fails with a cryptic Jinja error instead of the intended "missing deps" message.
Reproduce
- Clone a fresh
sdcore-helm-charts into the configured local_sd_core_chart_root.
- Do NOT run
helm dep up — leave 5g-control-plane/charts/ absent.
- Set
core.helm.local_charts: true and core.helm.chart_ref: <local-path> in vars/main.yml.
- Run
make aether-5gc-install.
Observed behaviour
TASK [core : check local 5gc-cp chart dependencies] ***
skipping: [localhost] => (item=mongodb)
skipping: [localhost] => (item=kafka)
skipping: [localhost]
TASK [core : require manual 5gc-cp helm dependency update when charts are missing] ***
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'matched'. 'dict object' has no attribute 'matched'\n\nThe error appears to be in 'deps/5gc/roles/core/tasks/install.yml': line 170, column 3..."}
Root cause
Preceding task at line 157 (check local 5gc-cp chart dependencies, a find with loop: core_cp_dependency_names) has when: core_cp_charts_dir.stat.exists. When charts/ does not exist, every loop iteration is skipped. The register (core_cp_chart_dependencies) ends up as a dict with a results list of skipped-loop-item dicts — each lacks the matched field that a successful find populates.
The next task (install.yml:170) then evaluates:
core_cp_chart_dependencies.results | default([]) | selectattr('matched', 'equalto', 0) | list | length
selectattr('matched', ...) blows up evaluating the skipped-item dicts because matched is absent. The not core_cp_charts_dir.stat.exists short-circuit in the surrounding or doesn't save us because Jinja eagerly evaluates both operands.
Proposed fix
Guard the selectattr so it only runs over items that actually have a matched key (i.e. non-skipped find results). One option:
when:
- inventory_hostname in groups['master_nodes']
- core.helm.local_charts
- >
not core_cp_charts_dir.stat.exists
or (core_cp_chart_dependencies.results | default([])
| rejectattr('skipped', 'defined')
| selectattr('matched', 'equalto', 0)
| list | length) > 0
Same rejectattr('skipped', 'defined') should be applied to the msg: expression a few lines above (which has the same filter chain and will also throw if reached under similar conditions).
Workaround
Pre-populate each component chart's charts/ subdir at bundle/build time via helm dep up, so the find task has something to iterate and the skipped-item branch is never hit. This is what aether-ops-bootstrap (downstream) is now doing to unblock its airgap flow.
Context
Surfaced while moving an aether-ops / aether-onramp deploy to fully-airgap operation. Happy to open a PR with the rejectattr('skipped', 'defined') fix if helpful.
Summary
When
core.helm.local_charts: trueis set AND the component chart under/tmp/sdcore-helm-charts/5g-control-plane/has nocharts/subdirectory (i.e.helm dep uphas never been run), the task atdeps/5gc/roles/core/tasks/install.yml:170(require manual 5gc-cp helm dependency update when charts are missing) fails with a cryptic Jinja error instead of the intended "missing deps" message.Reproduce
sdcore-helm-chartsinto the configuredlocal_sd_core_chart_root.helm dep up— leave5g-control-plane/charts/absent.core.helm.local_charts: trueandcore.helm.chart_ref: <local-path>invars/main.yml.make aether-5gc-install.Observed behaviour
Root cause
Preceding task at line 157 (
check local 5gc-cp chart dependencies, afindwithloop: core_cp_dependency_names) haswhen: core_cp_charts_dir.stat.exists. Whencharts/does not exist, every loop iteration is skipped. The register (core_cp_chart_dependencies) ends up as a dict with aresultslist of skipped-loop-item dicts — each lacks thematchedfield that a successfulfindpopulates.The next task (
install.yml:170) then evaluates:core_cp_chart_dependencies.results | default([]) | selectattr('matched', 'equalto', 0) | list | lengthselectattr('matched', ...)blows up evaluating the skipped-item dicts becausematchedis absent. Thenot core_cp_charts_dir.stat.existsshort-circuit in the surroundingordoesn't save us because Jinja eagerly evaluates both operands.Proposed fix
Guard the
selectattrso it only runs over items that actually have amatchedkey (i.e. non-skippedfindresults). One option:Same
rejectattr('skipped', 'defined')should be applied to themsg:expression a few lines above (which has the same filter chain and will also throw if reached under similar conditions).Workaround
Pre-populate each component chart's
charts/subdir at bundle/build time viahelm dep up, so thefindtask has something to iterate and the skipped-item branch is never hit. This is what aether-ops-bootstrap (downstream) is now doing to unblock its airgap flow.Context
Surfaced while moving an aether-ops / aether-onramp deploy to fully-airgap operation. Happy to open a PR with the
rejectattr('skipped', 'defined')fix if helpful.