Skip to content

Commit a0c9bf7

Browse files
authored
feat: Enhance udash helm chart (#113)
* feat: Enhance udash helm chart * By default use cnpg operator to install the postgresql database * Update udash front configuration which requires version > 0.17 * Fix udash server configuration template Signed-off-by: Olivier Vernin <olivier@vernin.me> * chore: update udash-front to v0.19.0 Signed-off-by: Olivier Vernin <olivier@vernin.me> * feat: allow to customize endpoint url Signed-off-by: Olivier Vernin <olivier@vernin.me> * fix: frontend/backend path Signed-off-by: Olivier Vernin <olivier@vernin.me> * chore: update wording Signed-off-by: Olivier Vernin <olivier@vernin.me> * fix: wrong formatting Signed-off-by: Olivier Vernin <olivier@vernin.me> --------- Signed-off-by: Olivier Vernin <olivier@vernin.me>
1 parent 3939ba9 commit a0c9bf7

15 files changed

Lines changed: 566 additions & 65 deletions

charts/udash-agent/templates/argoworkflow.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ spec:
5454
key: "{{ $env }}"
5555
# {{- end }}
5656
resources:
57-
{{ - toYaml $.Values.resources | nindent 14 }}
57+
{{- toYaml $.Values.resources | nindent 14 }}
5858
args:
5959
- |
6060
cd /workspace
@@ -118,9 +118,9 @@ spec:
118118
arguments:
119119
parameters:
120120
- name: repo-url
121-
value: '{{ $workflow.url }}'
121+
value: "{{ $workflow.url }}"
122122
- name: repo-branch
123-
value: '{{ $workflow.branch }}'
123+
value: "{{ $workflow.branch }}"
124124
- name: updatecli-compose-file
125-
value: '{{ $workflow.composefile }}'
125+
value: "{{ $workflow.composefile }}"
126126
#{{ end }}

charts/udash/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ description: Udash, the Updatecli DASHboard
44
icon: https://www.updatecli.io/images/updatecli_transparent.png
55
name: udash
66
type: application
7-
version: 0.25.0
7+
version: 0.26.0

charts/udash/README.md

Lines changed: 174 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# udash
22

3-
![Version: 0.25.0](https://img.shields.io/badge/Version-0.25.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.0](https://img.shields.io/badge/AppVersion-0.1.0-informational?style=flat-square)
3+
![Version: 0.26.0](https://img.shields.io/badge/Version-0.26.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.0](https://img.shields.io/badge/AppVersion-0.1.0-informational?style=flat-square)
44

55
Udash, the Updatecli DASHboard
66

7-
[Udash](https://github.com/updatecli/udash) is the Updatecli Dashboard — a web application that collects and displays Updatecli reports, giving your team a centralised view of software update activity across all your repositories.
7+
[Udash](https://github.com/updatecli/udash) is the Updatecli Dashboard, a web application that collects and displays Updatecli reports,
8+
giving your team a centralised view of software update activity across all your repositories.
89

910
## Architecture
1011

@@ -23,7 +24,24 @@ An optional **Ingress** routes:
2324

2425
- Kubernetes 1.19+
2526
- Helm 3.x
26-
- A running **PostgreSQL** instance accessible from the cluster
27+
- **[CloudNative-PG operator](https://cloudnative-pg.io/)** (when `cnpg.enabled: true`, which is the default)
28+
29+
Install the CNPG operator before installing this chart, and use `--wait` to ensure the operator
30+
pod is fully ready (including its admission webhook) before proceeding:
31+
32+
```console
33+
helm repo add cnpg https://cloudnative-pg.github.io/charts
34+
helm upgrade --install cnpg \
35+
--namespace cnpg-system \
36+
--create-namespace \
37+
cnpg/cloudnative-pg \
38+
--wait
39+
```
40+
41+
Without `--wait`, the operator pod may not be ready when the chart creates the `Cluster` resource,
42+
causing: `failed calling webhook "mcluster.cnpg.io": no endpoints available for service "cnpg-webhook-service"`.
43+
44+
If you prefer to bring your own PostgreSQL instance, set `cnpg.enabled=false` and supply the connection URI via `secrets.database.stringdata.uri`.
2745

2846
## Get Repository Info
2947

@@ -40,12 +58,21 @@ helm install udash updatecli/udash
4058

4159
## Installing the Chart
4260

43-
### Read-only mode (default)
61+
### Default (CloudNative-PG managed PostgreSQL)
62+
63+
By default the chart provisions a CNPG `Cluster` and injects credentials automatically. Just install the CNPG operator first (see Prerequisites), then:
64+
65+
```console
66+
helm install udash updatecli/udash
67+
```
68+
69+
### Read-only mode with external PostgreSQL
4470

45-
In read-only mode the server runs without authentication (dry-run). No OAuth credentials are required.
71+
Disable CNPG and supply your own connection URI:
4672

4773
```console
4874
helm install udash updatecli/udash \
75+
--set cnpg.enabled=false \
4976
--set secrets.database.stringdata.uri="postgres://user:pass@postgres:5432/udash?sslmode=disable"
5077
```
5178

@@ -56,21 +83,141 @@ Set `readonly: false` and supply your OAuth2 provider details:
5683
```console
5784
helm install udash updatecli/udash \
5885
--set readonly=false \
59-
--set secrets.database.stringdata.uri="postgres://user:pass@postgres:5432/udash?sslmode=disable" \
6086
--set secrets.auth.stringdata.clientid="my-client-id" \
6187
--set secrets.auth.stringdata.audience="https://udash.example/api" \
6288
--set secrets.auth.stringdata.issuer="https://auth.example"
6389
```
6490

65-
### With Ingress
91+
When using an external PostgreSQL in full mode, also set `cnpg.enabled=false` and `secrets.database.stringdata.uri`.
92+
93+
### With Ingress (same host, default paths)
94+
95+
Routes `udash.example.com/` to the front and `udash.example.com/api` to the server:
6696

6797
```console
6898
helm install udash updatecli/udash \
6999
--set ingress.enabled=true \
70-
--set ingress.className=nginx \
100+
--set ingress.className=traefik \
71101
--set "ingress.hosts[0].host=udash.example.com"
72102
```
73103

104+
### With Ingress (same host, subpath)
105+
106+
Serves the front at `app.example.com/updatecli` and the API at `app.example.com/api`.
107+
The front ingress must strip the `/updatecli` prefix before forwarding to nginx so that
108+
the nginx container always receives paths starting with `/`. Configure the SPA base path
109+
to match via `front.appBasePath`.
110+
111+
**nginx ingress controller** (uses `rewrite-target` + `use-regex`):
112+
113+
```yaml
114+
ingress:
115+
enabled: true
116+
className: nginx
117+
annotations:
118+
nginx.ingress.kubernetes.io/rewrite-target: /$2
119+
nginx.ingress.kubernetes.io/use-regex: "true"
120+
hosts:
121+
- host: app.example.com
122+
paths:
123+
front: "/updatecli(/|$)(.*)" # regex captures the suffix to pass as $2
124+
server: "/api" # no rewrite needed; server handles /api natively
125+
126+
front:
127+
appBasePath: "/updatecli" # must match the path prefix (without regex)
128+
apiBaseUrl: "/api"
129+
```
130+
131+
**Traefik** — set `ingress.traefik.stripPrefix.enabled: true` and the chart creates the
132+
`StripPrefix` Middleware CR and wires its annotation into the Ingress automatically.
133+
Requires Traefik CRDs (`traefik.io/v1alpha1`) to be installed in the cluster:
134+
135+
```yaml
136+
ingress:
137+
enabled: true
138+
className: traefik
139+
hosts:
140+
- host: app.example.com
141+
paths:
142+
front: "/updatecli"
143+
server: "/api"
144+
traefik:
145+
stripPrefix:
146+
enabled: true # creates the Middleware CR and injects the router annotation
147+
148+
front:
149+
appBasePath: "/updatecli"
150+
apiBaseUrl: "/api"
151+
```
152+
153+
> **Note:** `front.appBasePath` tells the SPA JavaScript router which path prefix to use for
154+
> client-side navigation. It must always match the **un-rewritten** path (e.g. `/updatecli`).
155+
> The API server does not need a strip-prefix because it handles `/api` natively.
156+
157+
### With Ingress (split domain)
158+
159+
Routes the front and API to different hostnames. Set `front.apiBaseUrl` to the absolute API URL
160+
so the browser knows where to reach the server:
161+
162+
```yaml
163+
front:
164+
apiBaseUrl: "https://api.udash.example.com/api"
165+
166+
ingress:
167+
enabled: true
168+
className: traefik
169+
hosts:
170+
- host: udash.example.com
171+
tls:
172+
- secretName: udash-tls
173+
hosts: [udash.example.com]
174+
server:
175+
host: api.udash.example.com
176+
tls:
177+
- secretName: udash-api-tls
178+
hosts: [api.udash.example.com]
179+
```
180+
181+
### With Ingress (split domain and custom sub-paths)
182+
183+
Serves the front at `domain.example/project` and the API at `api.domain.example/updatecli`.
184+
Set `ingress.traefik.stripPrefix.enabled: true` and the chart automatically creates all needed
185+
Traefik Middlewares and wires their annotations:
186+
187+
- **Front**: `StripPrefix /project` → nginx receives `/`
188+
- **Server**: `StripPrefix /updatecli` → `AddPrefix /api` → backend receives `/api/*`
189+
190+
Requires Traefik CRDs (`traefik.io/v1alpha1`) to be installed:
191+
192+
```yaml
193+
front:
194+
appBasePath: "/project"
195+
apiBaseUrl: "https://api.domain.example/updatecli"
196+
197+
ingress:
198+
enabled: true
199+
className: traefik
200+
hosts:
201+
- host: domain.example
202+
paths:
203+
front: "/project"
204+
server: "/api"
205+
traefik:
206+
stripPrefix:
207+
enabled: true # creates Middlewares for both front and server automatically
208+
server:
209+
host: api.domain.example
210+
path: "/updatecli"
211+
```
212+
213+
The chart renders:
214+
215+
| Middleware | Type | Effect |
216+
|---|---|---|
217+
| `<release>-strip-front` | StripPrefix `/project` | strips front sub-path before nginx |
218+
| `<release>-strip-server` | StripPrefix `/updatecli` | strips external prefix on API host |
219+
| `<release>-add-server` | AddPrefix `/api` | restores the `/api` prefix the backend expects |
220+
74221
## Uninstalling the Chart
75222

76223
```console
@@ -88,23 +235,37 @@ helm uninstall udash
88235
| autoscaling.maxReplicas | int | `100` | Maximum number of replicas. |
89236
| autoscaling.minReplicas | int | `1` | Minimum number of replicas. |
90237
| autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization percentage for autoscaling. |
238+
| cnpg.database | string | `"udash"` | PostgreSQL database name created during cluster bootstrap. |
239+
| cnpg.enabled | bool | `true` | Enable CloudNative-PG managed PostgreSQL cluster. When true, the chart provisions a CNPG Cluster and injects credentials automatically. Requires the CNPG operator to be installed separately. |
240+
| cnpg.instances | int | `1` | Number of PostgreSQL instances in the CNPG cluster. |
241+
| cnpg.owner | string | `"udash"` | PostgreSQL role/owner created during cluster bootstrap. |
242+
| cnpg.storage.size | string | `"1Gi"` | Storage size for each PostgreSQL instance. |
91243
| configMap.annotations | object | `{}` | Annotations to add to the ConfigMap. |
92244
| configMap.name | string | `""` | The name of the ConfigMap used to store server/front configuration. If not set, a name is generated using the fullname template. |
245+
| front.apiBaseUrl | string | `"/api"` | API base URL used by the browser. Use a relative path (e.g. "/api") for same-host routing. Use an absolute URL (e.g. "https://api.domain.example/api") for split-domain routing. |
246+
| front.appBasePath | string | `"/"` | Base path for the SPA. Must match ingress.paths.front when using subpath routing. Example: set both ingress.paths.front and front.appBasePath to "/updatecli". |
93247
| fullnameOverride | string | `""` | Full override for the chart name used in resource names. |
94248
| imagePullSecrets | list | `[]` | Secrets for pulling images from private registries. |
95249
| images.front.pullPolicy | string | `"IfNotPresent"` | Image pull policy for the udash-front image. |
96250
| images.front.repository | string | `"ghcr.io/updatecli/udash-front"` | Repository for the udash-front image. |
97-
| images.front.tag | string | `"v0.17.0@sha256:9afa7d7b0d8a8bc70154b83fd3ded620714cd79443c9e17a72bc5d7611c22f28"` | Overrides the image tag whose default is the chart appVersion. |
251+
| images.front.tag | string | `"v0.19.0@sha256:b220b047a7536ab3bd77a5a312da10a051802a674385cd50ac7df00e652c7e5e"` | Overrides the image tag whose default is the chart appVersion. |
98252
| images.server.args | list | `["server","start"]` | Arguments for the udash-server container. |
99253
| images.server.command | list | `["udash"]` | Command override for the udash-server container. |
100254
| images.server.pullPolicy | string | `"IfNotPresent"` | Image pull policy for the udash-server image. |
101255
| images.server.repository | string | `"ghcr.io/updatecli/udash"` | Repository for the udash-server image. |
102256
| images.server.tag | string | `"v0.14.0@sha256:a52edcb9535d8c392a2e592bf7c3b4fc0c14ecd4b1360aa96639145038b5da75"` | Overrides the image tag whose default is the chart appVersion. |
103-
| ingress.annotations | object | `{}` | Annotations to add to the Ingress resource. |
257+
| ingress.annotations | object | `{}` | Annotations to add to the front Ingress resource. For subpath routing, add the strip-prefix annotation for your ingress controller. nginx example: nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/use-regex: "true" (and set ingress.paths.front to "/updatecli(/|$)(.*)") traefik example (requires a Middleware CR for stripprefix): traefik.ingress.kubernetes.io/router.middlewares: <namespace>-<middlewarename>@kubernetescrd |
104258
| ingress.className | string | `""` | IngressClass name (Kubernetes >= 1.18). |
105259
| ingress.enabled | bool | `false` | Enable Ingress resource creation. |
106-
| ingress.hosts | list | `[{"host":"udash.local"}]` | Ingress host rules. Traffic to `/` is forwarded to udash-front; traffic to `/api` is forwarded to udash-server. |
107-
| ingress.tls | list | `[]` | TLS configuration for the Ingress. |
260+
| ingress.hosts | list | `[{"host":"udash.local"}]` | Ingress host rules for the front. Traffic is forwarded according to ingress.paths. |
261+
| ingress.paths.front | string | `"/"` | Path prefix for udash-front on same-host routing. For subpath routing (e.g. "/updatecli"), also set front.appBasePath to the same value and add a strip-prefix annotation so nginx receives "/" instead of "/updatecli/...". |
262+
| ingress.paths.server | string | `"/api"` | Path prefix for udash-server on same-host routing (when ingress.server.host is empty). |
263+
| ingress.server.annotations | object | `{}` | Annotations to add to the server Ingress resource. |
264+
| ingress.server.host | string | `""` | Optional separate hostname for the API server. When empty (default): udash-server is routed via ingress.paths.server on each front host. When set: a second Ingress is created for this host routing to udash-server. |
265+
| ingress.server.path | string | `"/api"` | Path prefix for udash-server on the separate server host. |
266+
| ingress.server.tls | list | `[]` | TLS configuration for the server Ingress. |
267+
| ingress.tls | list | `[]` | TLS configuration for the front Ingress. |
268+
| ingress.traefik.stripPrefix.enabled | bool | `false` | When true, create Traefik Middleware resources and wire their annotations automatically. Front: a StripPrefix Middleware strips ingress.paths.front (useful when it is not "/"). Server: a StripPrefix + AddPrefix Middleware chain rewrites ingress.server.path to ingress.paths.server ("/api") — only rendered when ingress.server.host is set. Example: external /updatecli/* → strip /updatecli → add /api → backend sees /api/*. Requires Traefik CRDs (traefik.io/v1alpha1) to be installed in the cluster. |
108269
| nameOverride | string | `""` | Override for the chart name used in resource names. |
109270
| nodeSelector | object | `{}` | Node selector for pod scheduling. |
110271
| podAnnotations | object | `{}` | Annotations to add to all pods. |
@@ -116,7 +277,7 @@ helm uninstall udash
116277
| secrets.auth.stringdata.audience | string | `"https://udash.example/api"` | OAuth2 audience. |
117278
| secrets.auth.stringdata.clientid | string | `"xxx.example"` | OAuth2 client ID. |
118279
| secrets.auth.stringdata.issuer | string | `"https://oauth.example"` | OAuth2 issuer URL. |
119-
| secrets.auth.stringdata.mode | string | `"oauth"` | Authentication mode. Supported values: `oauth`. |
280+
| secrets.auth.stringdata.mode | string | `"none"` | Authentication mode. Supported values: `oauth`, `none`. |
120281
| secrets.database.annotations | object | `{}` | Annotations to add to the database Secret. |
121282
| secrets.database.stringdata.uri | string | `"postgres://postgres:5432/udash?sslmode=disable"` | PostgreSQL connection URI used by the udash-server. |
122283
| secrets.name | string | `""` | The name of the Secret used to store credentials. If not set, a name is generated using the fullname template. |

0 commit comments

Comments
 (0)