Skip to content

App Catalog silently non-functional in default in-cluster deployments #5066

@v0lkan

Description

@v0lkan

Describe the bug

The App Catalog feature does not function in a default in-cluster deployment, despite being described as supported since v0.37.0.

In practice, two bugs in Headlamp core plus several undocumented deployment requirements prevent the feature from working out-of-the-box.

Expected behavior:

  • Enabling config.enableHelm: true should expose an "Apps" section in the UI
  • Users should be able to browse catalogs (e.g. ArtifactHub) and perform Helm operations

Actual behavior:

  • No "Apps" section appears
  • No indication that App Catalog exists or is misconfigured
  • No user-visible errors or warnings

This results in a silent failure where the feature appears to not exist.


To Reproduce

Case 1: Default in-cluster deployment (baseline failure)

  1. Deploy Headlamp via Helm:
    helm install headlamp headlamp/headlamp --set config.enableHelm=true
  2. Access the UI
  3. Observe that no "Apps" section exists
  4. No errors or warnings are shown

Case 2: After manually enabling plugin (reveals core issues)

  1. Install app-catalog plugin via initContainer or sidecar
  2. Create a catalog Service with expected labels/annotations
  3. Attempt to access catalog UI
  4. Observe:
    • Routes may return 404 ("Not Found")
    • Helm operations fail silently (backend uses system:anonymous)
    • No actionable UI errors

Environment:

  • Installation type: Helm (in-cluster)
  • Headlamp Version: chart 0.28.1 / app v0.26.0 (also reproduced on main)
  • Auth: token-based (non-OIDC, default in-cluster)
  • Cluster: Kind v0.27.0 (reproduces on other clusters as well)

Are you able to fix this issue?

Yes (I will propose a PR; it's 2-3 files <4-5 LOC change)


Additional Context

Summary of failure modes

The issue is not a single failure but a combination of seven independent failure modes. Hitting any subset results in a non-functional App Catalog with no user-visible signal.

  • Code bug 1: helmRouteReleaseHandler conditionally skips setTokenFromCookie() in non-OIDC setups → Helm operations run as system:anonymous
  • Code bug 2: React key collision in RouteSwitcher → dynamically registered plugin routes do not mount
  • Deployment gap: app-catalog plugin not included in container image
  • Deployment gap: missing default --proxy-urls (ArtifactHub unreachable)
  • Deployment gap: no catalog Service template → plugin discovers nothing
  • Deployment gap: undocumented catalog.headlamp.dev/protocol annotation
  • Deployment gap: ExternalName Services incompatible with service proxy (TLS/SNI issues)

Result: No user-visible errors or actionable feedback in the default case.


Code Bug 1 — Helm auth guard

helmRouteReleaseHandler conditionally calls setTokenFromCookie():

if (c.UseInCluster || c.OidcUseCookie) && context.OidcConf != nil {
    setTokenFromCookie(r, clusterName)
}

In non-OIDC deployments, this prevents the Authorization header from being set.

Observation:
helmRouteRepositoryHandler calls this function unconditionally and works correctly.

Proposed fix:

setTokenFromCookie(r, clusterName)

Safe because the function is a no-op when no cookie is present.


Code Bug 2 — React key collision

All routes use the same key:

key={`${getCluster()}`}

This prevents React from mounting dynamically registered routes.

Proposed fix:

key={`${route.path}-${getCluster()}`}

Deployment gaps (recommendations)

These are differences between desktop and in-cluster behavior:

  • Container image does not include app-catalog plugin
  • Helm chart does not configure --proxy-urls
  • No catalog Service template or documentation
  • Required annotations are undocumented
  • ExternalName Services do not work with service proxy

These likely require alignment on packaging/documentation direction rather than code fixes, and likely be outside the scope of the initial (proposed) fix to this bug.


PR scope

I plan to submit a minimal PR addressing the two code issues only:

  • Remove OIDC guard in helmRouteReleaseHandler
  • Fix React key collision in RouteSwitcher

Happy to discuss approach for deployment-related gaps separately (docs, Helm chart, or packaging changes).

Metadata

Metadata

Labels

helmRelated to helm and app-catalogkind/bugCategorizes issue or PR as related to a bug.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions