Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ metadata:
}
}
]
createdAt: "2026-01-08T11:04:59Z"
createdAt: "2026-01-14T10:07:45Z"
description: Backstage Operator
operators.operatorframework.io/builder: operator-sdk-v1.37.0
operators.operatorframework.io/project_layout: go.kubebuilder.io/v4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ metadata:
categories: Developer Tools
certified: "true"
containerImage: registry.redhat.io/rhdh/rhdh-rhel9-operator:1.9
createdAt: "2026-01-08T11:05:00Z"
createdAt: "2026-01-14T10:07:47Z"
description: Red Hat Developer Hub is a Red Hat supported version of Backstage.
It comes with pre-built plug-ins and configuration settings, supports use of
an external database, and can help streamline the process of setting up a self-managed
Expand Down
8 changes: 8 additions & 0 deletions bundle/rhdh/manifests/rhdh-default-config_v1_configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ data:
defaultMode: 416
optional: true
secretName: dynamic-plugins-registry-auth
- name: extensions-catalog
emptyDir: {}
- emptyDir: {}
name: npmcacache
- name: temp
Expand Down Expand Up @@ -245,9 +247,13 @@ data:
# CATALOG_INDEX_IMAGE will be replaced by the value of the `RELATED_IMAGE_catalog_index` env var, if set
- name: CATALOG_INDEX_IMAGE
value: "quay.io/rhdh/plugin-catalog-index:1.9"
- name: CATALOG_ENTITIES_EXTRACT_DIR
value: '/extensions'
volumeMounts:
- mountPath: /dynamic-plugins-root
name: dynamic-plugins-root
- name: extensions-catalog
mountPath: /extensions
# TODO Configuring dynamic plugins registry auth this way is deprecated and supported only for documentation backward compatibility.
- mountPath: /opt/app-root/src/.config/containers
name: dynamic-plugins-registry-auth
Expand Down Expand Up @@ -331,6 +337,8 @@ data:
volumeMounts:
- mountPath: /opt/app-root/src/dynamic-plugins-root
name: dynamic-plugins-root
- name: extensions-catalog
mountPath: /extensions
- mountPath: /tmp
name: temp
resources:
Expand Down
8 changes: 8 additions & 0 deletions config/profile/rhdh/default-config/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ spec:
defaultMode: 416
optional: true
secretName: dynamic-plugins-registry-auth
- name: extensions-catalog
emptyDir: {}
- emptyDir: {}
name: npmcacache
- name: temp
Expand Down Expand Up @@ -69,9 +71,13 @@ spec:
# CATALOG_INDEX_IMAGE will be replaced by the value of the `RELATED_IMAGE_catalog_index` env var, if set
- name: CATALOG_INDEX_IMAGE
value: "quay.io/rhdh/plugin-catalog-index:1.9"
- name: CATALOG_ENTITIES_EXTRACT_DIR
value: '/extensions'
volumeMounts:
- mountPath: /dynamic-plugins-root
name: dynamic-plugins-root
- name: extensions-catalog
mountPath: /extensions
# TODO Configuring dynamic plugins registry auth this way is deprecated and supported only for documentation backward compatibility.
- mountPath: /opt/app-root/src/.config/containers
name: dynamic-plugins-registry-auth
Expand Down Expand Up @@ -155,6 +161,8 @@ spec:
volumeMounts:
- mountPath: /opt/app-root/src/dynamic-plugins-root
name: dynamic-plugins-root
- name: extensions-catalog
mountPath: /extensions
- mountPath: /tmp
name: temp
resources:
Expand Down
8 changes: 8 additions & 0 deletions dist/rhdh/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,8 @@ data:
defaultMode: 416
optional: true
secretName: dynamic-plugins-registry-auth
- name: extensions-catalog
emptyDir: {}
- emptyDir: {}
name: npmcacache
- name: temp
Expand Down Expand Up @@ -2097,9 +2099,13 @@ data:
# CATALOG_INDEX_IMAGE will be replaced by the value of the `RELATED_IMAGE_catalog_index` env var, if set
- name: CATALOG_INDEX_IMAGE
value: "quay.io/rhdh/plugin-catalog-index:1.9"
- name: CATALOG_ENTITIES_EXTRACT_DIR
value: '/extensions'
volumeMounts:
- mountPath: /dynamic-plugins-root
name: dynamic-plugins-root
- name: extensions-catalog
mountPath: /extensions
# TODO Configuring dynamic plugins registry auth this way is deprecated and supported only for documentation backward compatibility.
- mountPath: /opt/app-root/src/.config/containers
name: dynamic-plugins-registry-auth
Expand Down Expand Up @@ -2183,6 +2189,8 @@ data:
volumeMounts:
- mountPath: /opt/app-root/src/dynamic-plugins-root
name: dynamic-plugins-root
- name: extensions-catalog
mountPath: /extensions
- mountPath: /tmp
name: temp
resources:
Expand Down
11 changes: 10 additions & 1 deletion docs/dynamic-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,18 @@ TODO: Dynamic plugins can be configured to use container registries for authenti

The operator supports loading default plugin configurations from an OCI container image (catalog index). For general information about how the catalog index works, see [Using a Catalog Index Image for Default Plugin Configurations](https://github.com/redhat-developer/rhdh/blob/main/docs/dynamic-plugins/installing-plugins.md#using-a-catalog-index-image-for-default-plugin-configurations).

By default, the `rhdh` profile of operator [injects](../config/profile/rhdh/patches/deployment-patch.yaml#L31-L32) the `CATALOG_INDEX_IMAGE` environment variable in the RHDH `install-dynamic-plugins` init containers.
By default, the `rhdh` profile of operator [injects](../config/profile/rhdh/patches/deployment-patch.yaml#L31-L32) the `CATALOG_INDEX_IMAGE` environment variable in the RHDH `install-dynamic-plugins` init container.
To use a different catalog index image, such as a newer version or a mirrored image, use the `extraEnvs` field in your Backstage CR. See [examples/catalog-index.yaml](../examples/catalog-index.yaml) for a complete example.

### Extensions Catalog Entities

Starting from version 1.9, the `rhdh` profile of the operator instructs the RHDH `install-dynamic-plugins` init container to extract catalog entities from the catalog index image to a new `/extensions` volume mount by default.
This allows the extensions backend providers to automatically discover plugin metadata for display in the RHDH Extensions UI.

The extraction directory can be configured via the `CATALOG_ENTITIES_EXTRACT_DIR` environment variable in the `install-dynamic-plugins` init container.

More details in [Catalog Entities Extraction](https://github.com/redhat-developer/rhdh/blob/main/docs/dynamic-plugins/installing-plugins.md#catalog-entities-extraction).

## Dynamic plugins dependency management

### Overview
Expand Down
9 changes: 8 additions & 1 deletion integration_tests/rhdh-config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ var _ = When("create default rhdh", func() {
MountPath: "/opt/app-root/src/dynamic-plugins.yaml",
SubPath: "dynamic-plugins.yaml",
},
{
Name: "extensions-catalog",
MountPath: "/extensions",
},
{
Name: "temp",
MountPath: "/tmp",
Expand All @@ -106,7 +110,7 @@ var _ = When("create default rhdh", func() {
g.Expect(initCont.Env[0].Name).To(Equal("NPM_CONFIG_USERCONFIG"))
g.Expect(initCont.Env[0].Value).To(Equal("/opt/app-root/src/.npmrc.dynamic-plugins/.npmrc"))

g.Expect(deploy.PodSpec().Volumes).To(HaveLen(7))
g.Expect(deploy.PodSpec().Volumes).To(HaveLen(8))
g.Expect(deploy.PodSpec().Containers).To(HaveLen(1))
mainCont := backstageContainer(*deploy.PodSpec())
g.Expect(mainCont.Args).To(HaveLen(4))
Expand All @@ -124,6 +128,9 @@ var _ = When("create default rhdh", func() {
MountPath: "/opt/app-root/src/default.app-config.yaml",
SubPath: "default.app-config.yaml",
},
{
MountPath: "/extensions",
},
{
MountPath: "/tmp",
SubPath: "",
Expand Down
1 change: 0 additions & 1 deletion pkg/model/dynamic-plugins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ func initContainer(model *BackstageModel) *corev1.Container {
return nil
}


// TestCatalogIndexImageFromDefaultConfig verifies that the operator sets CATALOG_INDEX_IMAGE
// on the install-dynamic-plugins init container from the default config by default
func TestCatalogIndexImageFromDefaultConfig(t *testing.T) {
Expand Down