Skip to content

Fix reconcile crash when Keycloak detection tasks are skipped#2

Open
fabianvf wants to merge 2 commits into
jortel:oidcfrom
fabianvf:fix-federated-idp-issuer
Open

Fix reconcile crash when Keycloak detection tasks are skipped#2
fabianvf wants to merge 2 commits into
jortel:oidcfrom
fabianvf:fix-federated-idp-issuer

Conversation

@fabianvf
Copy link
Copy Markdown

@fabianvf fabianvf commented May 28, 2026

Problem

The llm-proxy-test CI on konveyor#562 fails during reconcile (run 26526639422). The Tackle CR never becomes ready, and no hub/ui/kai-db/llm-proxy workloads are created — the playbook aborts early:

TASK [Set federated IDP issuer based on detection or explicit config]
fatal: [localhost]: FAILED! => "'dict object' has no attribute 'resources'"
.../roles/tackle/tasks/main.yml:575

Root cause

The Set federated IDP issuer set_fact guards the conditionally-registered rhsso_keycloak_cr / rhbk_keycloak_cr vars with is defined. Those two k8s_info tasks only run when: app_profile == 'mta'. On other profiles (CI runs the konveyor profile) they are skipped — but a skipped task still registers a result dict, one that has no .resources key.

So rhsso_keycloak_cr is defined is True (it's the skip-result dict), the template proceeds to evaluate .resources, and Jinja raises 'dict object' has no attribute 'resources'. The earlier branches are all false in CI (keycloak_sso_url/rhbk_url empty, no standalone Keycloak service), so execution always reaches the broken elif.

Fix

Keep the is defined guard — it short-circuits a genuinely undefined var (and and short-circuits in Jinja, so .resources is never evaluated in that case) — and add default([]) on the attribute so the skipped-register case (defined dict, missing .resources) collapses to an empty list:

{% elif rhsso_keycloak_cr is defined and rhsso_keycloak_cr.resources | default([]) | length > 0 %}
{% elif rhbk_keycloak_cr is defined and rhbk_keycloak_cr.resources | default([]) | length > 0 %}

(default([]) alone is not enough: it only rescues the missing-attribute case. If the base var were ever fully undefined, evaluating .resources on it would raise before the filter runs — hence keeping is defined.)

standalone_keycloak_svc needs no change — that task always runs, so it always has .resources.

Test plan

fabianvf added 2 commits May 28, 2026 13:45
The "Set federated IDP issuer" set_fact guarded the conditionally-
registered rhsso_keycloak_cr / rhbk_keycloak_cr vars with `is defined`.
Those k8s_info tasks only run `when: app_profile == 'mta'`; on other
profiles they are skipped, but a skipped task still registers a result
dict that has no `.resources` key. `is defined` is True for that dict,
so the template then evaluated `.resources` and failed with
"'dict object' has no attribute 'resources'", aborting the reconcile
before any workloads were created.

Keep the `is defined` guard (short-circuits a genuinely undefined var)
and add `default([])` on `.resources` so the skipped-register case
(defined dict, missing attribute) collapses to an empty list.

Signed-off-by: Fabian von Feilitzsch <fabian@fabianism.us>
"Set app base URL from UI Ingress" (and the matching Hub OIDC issuer
task) read ui_ingress_info.resources[0].spec.rules[0].host, guarded
only by `resources | length > 0`. The default UI Ingress
(ingress-ui.yml.j2) defines a host-less rule (`- http:` with no
`host:`), so on any non-OpenShift cluster (e.g. minikube CI) the rule
exists but has no `host` key, and the template failed with
"'dict object' has no attribute 'host'", aborting the reconcile before
llm-proxy / kai-db were created.

Add a `...rules[0].host is defined` guard to both tasks so a host-less
Ingress leaves app_base_url / hub_oidc_issuer at their defaults instead
of crashing.

Signed-off-by: Fabian von Feilitzsch <fabian@fabianism.us>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant