Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default secrets #609

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/v1alpha3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ metadata:
categories: Developer Tools
certified: "true"
containerImage: registry-proxy.engineering.redhat.com/rh-osbs/rhdh-rhdh-rhel9-operator:1.3
createdAt: "2024-12-13T14:46:16Z"
createdAt: "2024-12-19T17:20:07Z"
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
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ data:
type: RuntimeDefault
capabilities:
drop:
- ALL
- ALL
env:
- name: NPM_CONFIG_USERCONFIG
value: /opt/app-root/src/.npmrc.dynamic-plugins
Expand Down
2 changes: 1 addition & 1 deletion config/profile/rhdh/default-config/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ spec:
type: RuntimeDefault
capabilities:
drop:
- ALL
- ALL
env:
- name: NPM_CONFIG_USERCONFIG
value: /opt/app-root/src/.npmrc.dynamic-plugins
Expand Down
105 changes: 82 additions & 23 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ The Default Configuration defines the structure of all Backstage instances withi

### Default Configuration Files

| Key/File Name | Object Kind | Object Name | Mandatory | Multi| Version | Notes |
|-----------------------------|------------------------------|-------------------------------------|--------------|-----|---------|----------------------------------------------------------|
| deployment.yaml | appsv1.Deployment | backstage-<cr-name> | Yes | No | >=0.1.x | Backstage deployment |
| service.yaml | corev1.Service | backstage-<cr-name> | Yes | No | >=0.1.x | Backstage Service |
| db-statefulset.yaml | appsv1.StatefulSet | backstage-psql-<cr-name> | For local DB | No | >=0.1.x | PostgreSQL StatefulSet |
| db-service.yaml | corev1.Service | backstage-psql-<cr-name> | For local DB | No | >=0.1.x | PostgreSQL Service |
| db-secret.yaml | corev1.Secret | backstage-psql-secret-<cr-name> | For local DB | No | >=0.1.x | Secret to connect Backstage to PGSQL |
| route.yaml | openshift.Route | backstage-<cr-name> | No (for OCP) | No | >=0.1.x | Route exposing Backstage service |
| app-config.yaml | corev1.ConfigMap | backstage-appconfig-<cr-name> | No | No | >=0.2.x | Backstage app-config.yaml |
| configmap-files.yaml | corev1.ConfigMap | backstage-files-<cr-name> | No | No | >=0.2.x | Backstage config file inclusions from configMap |
| configmap-envs.yaml | corev1.ConfigMap | backstage-envs-<cr-name> | No | No | >=0.2.x | Backstage environment variables from ConfigMap |
| secret-files.yaml | corev1.Secret | backstage-files-<cr-name> | No | No | >=0.2.x | Backstage config file inclusions from Secret |
| secret-envs.yaml | corev1.Secret | backstage-envs-<cr-name> | No | No | >=0.2.x | Backstage environment variables from Secret |
| dynamic-plugins.yaml | corev1.ConfigMap | backstage-dynamic-plugins-<cr-name> | No | No | >=0.2.x | Dynamic plugins configuration |
| pvcs.yaml | corev1.PersistentVolumeClaim | backstage-&lt;cr-name&gt;-&lt;pvc-name&gt; | No | Yes | >=0.4.x | List of PVC objects to be mounted to Backstage container |
| Key/File Name | Object Kind | Object Name | Mandatory | Multi | Version | Notes |
|----------------------|--------------------------------|--------------------------------------------|--------------|-------|---------|-------------------------------------------------|
| deployment.yaml | appsv1.Deployment | backstage-<cr-name> | Yes | No | >=0.1.x | Backstage deployment |
| service.yaml | corev1.Service | backstage-<cr-name> | Yes | No | >=0.1.x | Backstage Service |
| db-statefulset.yaml | appsv1.StatefulSet | backstage-psql-<cr-name> | For local DB | No | >=0.1.x | PostgreSQL StatefulSet |
| db-service.yaml | corev1.Service | backstage-psql-<cr-name> | For local DB | No | >=0.1.x | PostgreSQL Service |
| db-secret.yaml | corev1.Secret | backstage-psql-secret-<cr-name> | For local DB | No | >=0.1.x | Secret to connect Backstage to PGSQL |
| route.yaml | openshift.Route | backstage-<cr-name> | No (for OCP) | No | >=0.1.x | Route exposing Backstage service |
| app-config.yaml | corev1.ConfigMap | backstage-appconfig-<cr-name> | No | No | >=0.2.x | Backstage app-config.yaml |
| configmap-files.yaml | corev1.ConfigMap | backstage-files-<cr-name> | No | No | >=0.2.x | Backstage config file inclusions from configMap |
| configmap-envs.yaml | corev1.ConfigMap | backstage-envs-<cr-name> | No | No | >=0.2.x | Backstage environment variables from ConfigMap |
| secret-files.yaml | []corev1.Secret | backstage-files-<cr-name> | No | Yes | >=0.2.x | Backstage config file inclusions from Secret |
| secret-envs.yaml | []corev1.Secret | backstage-envs-<cr-name> | No | Yes | >=0.2.x | Backstage environment variables from Secret |
| dynamic-plugins.yaml | corev1.ConfigMap | backstage-dynamic-plugins-<cr-name> | No | No | >=0.2.x | Dynamic plugins configuration |
| pvcs.yaml | []corev1.PersistentVolumeClaim | backstage-&lt;cr-name&gt;-&lt;pvc-name&gt; | No | Yes | >=0.4.x | List of PVC objects to be mounted to containers |

**Meanings of "Mandatory" Column:**
- **Yes** - Must be configured; deployment will fail otherwise.
Expand All @@ -36,14 +36,24 @@ The Default Configuration defines the structure of all Backstage instances withi

You can see examples of default configurations as part of the [Operator Profiles](../config/profile) in the **default-config** directory.

#### Default mount path
### Default mount path

Some objects, such as: app-config, configmap-files, secret-files, dynamic-plugins, pvcs, are mounted to the Backstage Container as files or directories. Default mount path is Container's WorkingDir, if not defined it falls to "/opt/app-root/src".

#### Object annotation for mounting a volume to a specific path
### Annotations

Using **rhdh.redhat.com/mount-path** annotation it is possible to define the directory where **PersistentVolumeClaim** object will be mounted to Backstage Container.
We use annotations to configure some objects. The following annotations are supported:

#### rhdh.redhat.com/mount-path to configure mount path.

If specified, the object will be mounted to the specified path, otherwise [Default mount path](#default-mount-path) will ve used.
It is possible to specify relative path, which will be appended to the default mount path.

Supported objects: **pvcs, secret-files**.

Examples:

_**pvcs.yaml**_
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
Expand All @@ -56,6 +66,55 @@ metadata:

In the example above the PVC called **myclaim** will be mounted to **/mount/path/from/annotation** directory

_**secret-files.yaml**_
```yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
annotations:
rhdh.redhat.com/mount-path: /mount/path/from/annotation
...
```
In the example above the Secret called **mysecret** will be mounted to **/mount/path/from/annotation** directory

#### rhdh.redhat.com/containers for mounting volume to specific container(s)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR seems to be built on top of https://github.com/redhat-developer/rhdh-operator/pull/582/files#diff-17ed18489a956f326ec0fe4040850c5bc9261d4631fb42da4c52891d74a59180, right?
In this case, to make it easier to review the diff, I'd suggest marking this as draft (and update it once #582 is merged).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, do not merge it before 582. Put on hold label


Supported objects: **pvcs, secret-files, secret-envs**.

Options:

* No or empty annotation: the volume will be mounted to the Backstage container only
* \* (asterisk): the volume will be mounted to all the containers
* Otherwise, container names separated by commas will be used

Examples:

_**pvcs.yaml**_
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
annotations:
rhdh.redhat.com/containers: "init-dynamic-plugins,backstage-backend"
...
```
In the example above the PVC called **myclaim** will be mounted to **init-dynamic-plugins** and **backstage-backend** containers

_**secret-envs.yaml**_

```yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
annotations:
rhdh.redhat.com/containers: "*"
...
```
In the example above the PVC called **myclaim** will be mounted to all the containers

### Metadata Generation

For Backstage to function consistently at runtime, certain metadata values need to be predictable. Therefore, the Operator generates values according to the following rules. Any value for these fields specified in either Default or Raw Configuration will be replaced by the generated values.
Expand Down Expand Up @@ -114,7 +173,7 @@ spec:
The desired state of resources created by the Backstage Operator is defined in the Backstage Custom Resource Spec. Here’s an example of a simple Backstage CR:

```yaml
apiVersion: rhdh.redhat.com/v1alpha2
apiVersion: rhdh.redhat.com/v1alpha3
kind: Backstage
metadata:
name: mybackstage
Expand All @@ -136,7 +195,7 @@ For API version **v1alpha2** (Operator version **0.3.x**), the Backstage CR Spec

* [application](#application-configuration)
* [deployment](#deployment-configuration)
* [database](#local-database-configuration)
* [database](#database-configuration)
* [rawRuntimeConfig](#raw-configuration)

### Application Configuration
Expand Down Expand Up @@ -185,7 +244,7 @@ The ConfigMap key/value defines the file name and content, and this app-config w
**Note**: It is possible to define several **app-config** files inside one ConfigMap (even if there are no visible reasons for it) but since it is a Map, the order of how they are applied is not guaranteed.
On the other hand, Backstage application merges the chain of **app-config** files from first to last, so order is important. Taking this into account, keeping several **app-config** files inside one ConfigMap is **NOT recommended**. For this case consider defining several one-entry ConfigMaps instead.

[Includes and Dynamic Data](https://backstage.io/docs/conf/writing/#includes-and-dynamic-data) (including [extra files](#extra-files) and [extra environment variables](#extra-env-variables)) support configuring additional ConfigMaps and Secrets.
[Includes and Dynamic Data](https://backstage.io/docs/conf/writing/#includes-and-dynamic-data) (including [extra files](#extra-files) and [extra environment variables](#extra-environment-variables)) support configuring additional ConfigMaps and Secrets.

#### Extra Files

Expand Down Expand Up @@ -393,7 +452,7 @@ MY_VAR = my-value

#### Dynamic Plugins

The Operator can configure [Dynamic Plugins](https://github.com/janus-idp/backstage-showcase/blob/main/docs/dynamic-plugins.md). To support Dynamic Plugins, the Backstage deployment should contain a dedicated initContainer called **install-dynamic-plugins** (see [RHDH deployment.yaml](../config/manager/default-config/deployment.yaml)). To enable the Operator to configure Dynamic Plugins for a specific Backstage instance (CR), the user must create a ConfigMap with an entry called **dynamic-plugins.yaml**.
The Operator can configure [Dynamic Plugins](https://github.com/janus-idp/backstage-showcase/blob/main/docs/dynamic-plugins.md). To support Dynamic Plugins, the Backstage deployment should contain a dedicated initContainer called **install-dynamic-plugins** (see [RHDH deployment.yaml](../config/profile/rhdh/default-config/deployment.yaml)). To enable the Operator to configure Dynamic Plugins for a specific Backstage instance (CR), the user must create a ConfigMap with an entry called **dynamic-plugins.yaml**.

For example, the **dynamic-plugins-config** ConfigMap contains a simple Dynamic Plugins configuration, which includes predefined default plugins in **dynamic-plugins.default.yaml** and the GitHub plugin provided in the package located at `./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic`.

Expand Down Expand Up @@ -519,7 +578,7 @@ This is dictated by the following configuration:
```yaml
spec:
database:
enableLocalDb: [true]|false
enableLocalDb: [true] or false
```

If local DB is enabled (which is simpler but not recommended for production), the Operator will:
Expand Down
14 changes: 6 additions & 8 deletions pkg/model/appconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (

"golang.org/x/exp/maps"

appsv1 "k8s.io/api/apps/v1"

"sigs.k8s.io/controller-runtime/pkg/client"

"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -46,8 +44,8 @@ func addAppConfigsFromSpec(spec bsv1.BackstageSpec, model *BackstageModel) error

for _, specCm := range spec.Application.AppConfig.ConfigMaps {
mp, wSubpath := model.backstageDeployment.mountPath(specCm.MountPath, specCm.Key, spec.Application.AppConfig.MountPath)
updatePodWithAppConfig(model.backstageDeployment.deployment, model.backstageDeployment.container(), specCm.Name,
mp, specCm.Key, wSubpath /*model.ExternalConfig.AppConfigs[specCm.Name].Data*/, model.ExternalConfig.AppConfigKeys[specCm.Name])
updatePodWithAppConfig(model.backstageDeployment, model.backstageDeployment.container(), specCm.Name,
mp, specCm.Key, wSubpath, model.ExternalConfig.AppConfigKeys[specCm.Name])
}
return nil
}
Expand Down Expand Up @@ -80,8 +78,8 @@ func (b *AppConfig) addToModel(model *BackstageModel, _ bsv1.Backstage) (bool, e
}

// implementation of RuntimeObject interface
func (b *AppConfig) updateAndValidate(m *BackstageModel, backstage bsv1.Backstage) error {
updatePodWithAppConfig(m.backstageDeployment.deployment, m.backstageDeployment.container(), b.ConfigMap.Name, m.backstageDeployment.defaultMountPath(), "", true, maps.Keys(b.ConfigMap.Data))
func (b *AppConfig) updateAndValidate(m *BackstageModel, _ bsv1.Backstage) error {
updatePodWithAppConfig(m.backstageDeployment, m.backstageDeployment.container(), b.ConfigMap.Name, m.backstageDeployment.defaultMountPath(), "", true, maps.Keys(b.ConfigMap.Data))
return nil
}

Expand All @@ -91,8 +89,8 @@ func (b *AppConfig) setMetaInfo(backstage bsv1.Backstage, scheme *runtime.Scheme
}

// updatePodWithAppConfig contrubutes to Volumes, container.VolumeMounts and contaiter.Args
func updatePodWithAppConfig(deployment *appsv1.Deployment, container *corev1.Container, cmName, mountPath, key string, withSubPath bool, cmData []string) {
utils.MountFilesFrom(&deployment.Spec.Template.Spec, container, utils.ConfigMapObjectKind,
func updatePodWithAppConfig(bsd *BackstageDeployment, container *corev1.Container, cmName, mountPath, key string, withSubPath bool, cmData []string) {
bsd.mountFilesFrom([]string{container.Name}, ConfigMapObjectKind,
cmName, mountPath, key, withSubPath, cmData)

for _, file := range cmData {
Expand Down
1 change: 0 additions & 1 deletion pkg/model/appconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ var (

func TestDefaultAppConfig(t *testing.T) {

//bs := simpleTestBackstage()
bs := *appConfigTestBackstage.DeepCopy()

testObj := createBackstageTest(bs).withDefaultConfig(true).addToDefaultConfig("app-config.yaml", "raw-app-config.yaml")
Expand Down
4 changes: 2 additions & 2 deletions pkg/model/configmapenvs.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func addConfigMapEnvsFromSpec(spec bsv1.BackstageSpec, model *BackstageModel) {
}

for _, specCm := range spec.Application.ExtraEnvs.ConfigMaps {
utils.AddEnvVarsFrom(model.backstageDeployment.container(), utils.ConfigMapObjectKind, specCm.Name, specCm.Key)
model.backstageDeployment.addEnvVarsFrom([]string{BackstageContainerName()}, ConfigMapObjectKind, specCm.Name, specCm.Key)
}
}

Expand Down Expand Up @@ -63,7 +63,7 @@ func (p *ConfigMapEnvs) addToModel(model *BackstageModel, _ bsv1.Backstage) (boo

// implementation of RuntimeObject interface
func (p *ConfigMapEnvs) updateAndValidate(m *BackstageModel, _ bsv1.Backstage) error {
utils.AddEnvVarsFrom(m.backstageDeployment.container(), utils.ConfigMapObjectKind,
m.backstageDeployment.addEnvVarsFrom([]string{BackstageContainerName()}, ConfigMapObjectKind,
p.ConfigMap.Name, "")
return nil
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/model/configmapfiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func addConfigMapFilesFromSpec(spec bsv1.BackstageSpec, model *BackstageModel) e

mp, wSubpath := model.backstageDeployment.mountPath(specCm.MountPath, specCm.Key, spec.Application.ExtraFiles.MountPath)
keys := model.ExternalConfig.ExtraFileConfigMapKeys[specCm.Name].All()
utils.MountFilesFrom(&model.backstageDeployment.deployment.Spec.Template.Spec, model.backstageDeployment.container(), utils.ConfigMapObjectKind,
model.backstageDeployment.mountFilesFrom([]string{BackstageContainerName()}, ConfigMapObjectKind,
specCm.Name, mp, specCm.Key, wSubpath, keys)
}
return nil
Expand Down Expand Up @@ -70,7 +70,7 @@ func (p *ConfigMapFiles) addToModel(model *BackstageModel, _ bsv1.Backstage) (bo
func (p *ConfigMapFiles) updateAndValidate(m *BackstageModel, _ bsv1.Backstage) error {

keys := append(maps.Keys(p.ConfigMap.Data), maps.Keys(p.ConfigMap.BinaryData)...)
utils.MountFilesFrom(&m.backstageDeployment.deployment.Spec.Template.Spec, m.backstageDeployment.container(), utils.ConfigMapObjectKind,
m.backstageDeployment.mountFilesFrom([]string{BackstageContainerName()}, ConfigMapObjectKind,
p.ConfigMap.Name, m.backstageDeployment.defaultMountPath(), "", true, keys)

return nil
Expand Down
12 changes: 10 additions & 2 deletions pkg/model/db-statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ func (b *DbStatefulSet) updateAndValidate(model *BackstageModel, backstage bsv1.
}

if backstage.Spec.IsAuthSecretSpecified() {
utils.SetDbSecretEnvVar(b.container(), backstage.Spec.Database.AuthSecretName)
b.setDbSecretEnvVar(b.container(), backstage.Spec.Database.AuthSecretName)
} else if model.LocalDbSecret != nil {
utils.SetDbSecretEnvVar(b.container(), model.LocalDbSecret.secret.Name)
b.setDbSecretEnvVar(b.container(), model.LocalDbSecret.secret.Name)
}
return nil
}
Expand All @@ -112,3 +112,11 @@ func (b *DbStatefulSet) container() *corev1.Container {
func (b *DbStatefulSet) podSpec() *corev1.PodSpec {
return &b.statefulSet.Spec.Template.Spec
}

func (b *DbStatefulSet) setDbSecretEnvVar(container *corev1.Container, secretName string) {
//AddEnvVarsFrom(container, SecretObjectKind, secretName, "")
envFromSrc := corev1.EnvFromSource{}
envFromSrc.SecretRef = &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{Name: secretName}}
container.EnvFrom = append(container.EnvFrom, envFromSrc)
}
Loading
Loading