Skip to content

Commit df42a3c

Browse files
Merge pull request #60 from aa-replicated/demo/tier5
feat: Tier 5 config screen — external DB toggle and generated password
2 parents c4d3454 + 177dc92 commit df42a3c

5 files changed

Lines changed: 712 additions & 0 deletions

File tree

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
# Tier 5 Config Screen Implementation Plan
2+
3+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4+
5+
**Goal:** Add an external database toggle with conditional fields and a generated embedded DB password to the KOTS/EC3 config screen, satisfying Tier 5 rubric items 5.0 and 5.2.
6+
7+
**Architecture:** Two files change. `kots-config.yaml` gains a `database` group with a `db_type` dropdown (embedded/external), conditional external connection fields, and a hidden `db_password_generated` item that uses `RandomString 32` to produce a stable password on first install. `helmchart.yaml` wires all new config values to the chart — `postgresql.enabled`, `postgresql.auth.password`, and the full `externalDatabase.*` block.
8+
9+
**Tech Stack:** KOTS Config custom resource (kots.io/v1beta1), KOTS HelmChart custom resource (kots.io/v1beta2), Helm chart `_helpers.tpl` (already handles embedded/external switch — no changes needed)
10+
11+
---
12+
13+
## File Map
14+
15+
| File | Change |
16+
|------|--------|
17+
| `kots-config.yaml` | Add `database` group with 7 new items |
18+
| `helmchart.yaml` | Add `postgresql.enabled`, `postgresql.auth.password`, and `externalDatabase.*` overrides |
19+
20+
---
21+
22+
## Task 1: Add the database config group to kots-config.yaml
23+
24+
**Files:**
25+
- Modify: `kots-config.yaml`
26+
27+
- [ ] **Step 1: Verify current file contents**
28+
29+
```bash
30+
cat kots-config.yaml
31+
```
32+
33+
Expected: 33 lines, two groups (`gameshelf` and `branding`), no `database` group.
34+
35+
- [ ] **Step 2: Add the database group**
36+
37+
In `kots-config.yaml`, add a new group after the closing of the `gameshelf` group (after line 19, before the `branding` group). The full file should look like this:
38+
39+
```yaml
40+
apiVersion: kots.io/v1beta1
41+
kind: Config
42+
metadata:
43+
name: gameshelf
44+
spec:
45+
groups:
46+
- name: gameshelf
47+
title: GameShelf
48+
items:
49+
- name: admin_secret
50+
title: Admin Password
51+
type: password
52+
required: true
53+
help_text: "Password for the GameShelf admin panel."
54+
- name: site_name
55+
title: Site Name
56+
type: text
57+
default: "GameShelf"
58+
help_text: "The name displayed in the browser title and header."
59+
- name: database
60+
title: Database
61+
items:
62+
- name: db_type
63+
title: Database
64+
type: select_one
65+
default: embedded
66+
help_text: "Choose Embedded to use the built-in PostgreSQL instance, or External to connect to your own PostgreSQL server."
67+
items:
68+
- name: embedded
69+
title: Embedded (recommended)
70+
- name: external
71+
title: External PostgreSQL
72+
- name: db_password_generated
73+
title: Embedded Database Password
74+
type: password
75+
hidden: true
76+
default: '{{repl RandomString 32}}'
77+
help_text: "Auto-generated password for the embedded PostgreSQL instance. Generated once at install and preserved across upgrades."
78+
- name: db_host
79+
title: Database Host
80+
type: text
81+
when: '{{repl ConfigOption "db_type" | eq "external"}}'
82+
required: true
83+
help_text: "Hostname or IP address of your PostgreSQL server (e.g. db.example.com)."
84+
- name: db_port
85+
title: Database Port
86+
type: text
87+
default: "5432"
88+
when: '{{repl ConfigOption "db_type" | eq "external"}}'
89+
help_text: "Port your PostgreSQL server listens on. Default is 5432."
90+
validation:
91+
regex:
92+
pattern: '^\d+$'
93+
message: "Must be a numeric port number."
94+
- name: db_name
95+
title: Database Name
96+
type: text
97+
default: "gameshelf"
98+
when: '{{repl ConfigOption "db_type" | eq "external"}}'
99+
help_text: "Name of the PostgreSQL database to connect to."
100+
- name: db_user
101+
title: Database Username
102+
type: text
103+
default: "gameshelf"
104+
when: '{{repl ConfigOption "db_type" | eq "external"}}'
105+
help_text: "Username for authenticating with the PostgreSQL database."
106+
- name: db_password
107+
title: Database Password
108+
type: password
109+
when: '{{repl ConfigOption "db_type" | eq "external"}}'
110+
required: true
111+
help_text: "Password for authenticating with the PostgreSQL database."
112+
- name: branding
113+
title: Branding
114+
when: '{{repl LicenseFieldValue "custom_branding_enabled" | eq "true"}}'
115+
items:
116+
- name: site_color
117+
title: Primary Color
118+
type: text
119+
default: "#3B82F6"
120+
help_text: "Primary color for the GameShelf UI (hex format, e.g. #3B82F6). Requires the Custom Branding license entitlement."
121+
validation:
122+
regex:
123+
pattern: '^#[0-9A-Fa-f]{6}$'
124+
message: "Must be a valid hex color code (e.g. #3B82F6)"
125+
```
126+
127+
- [ ] **Step 3: Verify file looks correct**
128+
129+
```bash
130+
cat kots-config.yaml
131+
```
132+
133+
Expected: ~90 lines, three groups (`gameshelf`, `database`, `branding`).
134+
135+
- [ ] **Step 4: Commit**
136+
137+
```bash
138+
git add kots-config.yaml
139+
git commit -m "feat: add external DB toggle and generated password to config screen"
140+
```
141+
142+
---
143+
144+
## Task 2: Wire database config values into helmchart.yaml
145+
146+
**Files:**
147+
- Modify: `helmchart.yaml`
148+
149+
- [ ] **Step 1: Verify current helmchart.yaml values section**
150+
151+
```bash
152+
cat helmchart.yaml
153+
```
154+
155+
Expected: `values` section has `adminSecret`, `siteName`, `siteColor`, `customBrandingEnabled`, `imageProxy`, `service`, `image`, `replicated`, `postgresql.image`, `redis.image`. No `postgresql.enabled`, no `postgresql.auth`, no `externalDatabase` block.
156+
157+
- [ ] **Step 2: Add database wiring to the values section**
158+
159+
In `helmchart.yaml`, replace the existing `postgresql:` block:
160+
161+
```yaml
162+
postgresql:
163+
image:
164+
registry: 'repl{{ ReplicatedImageRegistry "index.docker.io" }}'
165+
```
166+
167+
With:
168+
169+
```yaml
170+
postgresql:
171+
enabled: 'repl{{ ConfigOption "db_type" | eq "embedded" }}'
172+
auth:
173+
password: 'repl{{ ConfigOption "db_password_generated" }}'
174+
image:
175+
registry: 'repl{{ ReplicatedImageRegistry "index.docker.io" }}'
176+
externalDatabase:
177+
host: 'repl{{ ConfigOption "db_host" }}'
178+
port: 'repl{{ ConfigOption "db_port" }}'
179+
database: 'repl{{ ConfigOption "db_name" }}'
180+
username: 'repl{{ ConfigOption "db_user" }}'
181+
password: 'repl{{ ConfigOption "db_password" }}'
182+
```
183+
184+
- [ ] **Step 3: Verify the full helmchart.yaml looks correct**
185+
186+
```bash
187+
cat helmchart.yaml
188+
```
189+
190+
Expected full file:
191+
192+
```yaml
193+
apiVersion: kots.io/v1beta2
194+
kind: HelmChart
195+
metadata:
196+
name: gameshelf
197+
spec:
198+
chart:
199+
name: gameshelf
200+
chartVersion: "0.0.0"
201+
values:
202+
adminSecret: repl{{ ConfigOption `admin_secret`}}
203+
siteName: repl{{ ConfigOption `site_name`}}
204+
siteColor: repl{{ ConfigOption `site_color`}}
205+
customBrandingEnabled: repl{{ LicenseFieldValue `custom_branding_enabled` }}
206+
imageProxy:
207+
host: ""
208+
service:
209+
type: NodePort
210+
nodePort: 30081
211+
image:
212+
registry: 'repl{{ ReplicatedImageRegistry "ghcr.io" }}'
213+
repository: 'aa-replicated/gameshelf'
214+
pullPolicy: IfNotPresent
215+
replicated:
216+
image:
217+
registry: 'repl{{ ReplicatedImageRegistry "proxy.replicated.com" true }}'
218+
postgresql:
219+
enabled: 'repl{{ ConfigOption "db_type" | eq "embedded" }}'
220+
auth:
221+
password: 'repl{{ ConfigOption "db_password_generated" }}'
222+
image:
223+
registry: 'repl{{ ReplicatedImageRegistry "index.docker.io" }}'
224+
externalDatabase:
225+
host: 'repl{{ ConfigOption "db_host" }}'
226+
port: 'repl{{ ConfigOption "db_port" }}'
227+
database: 'repl{{ ConfigOption "db_name" }}'
228+
username: 'repl{{ ConfigOption "db_user" }}'
229+
password: 'repl{{ ConfigOption "db_password" }}'
230+
redis:
231+
image:
232+
registry: 'repl{{ ReplicatedImageRegistry "index.docker.io" }}'
233+
builder:
234+
image:
235+
registry: "ghcr.io"
236+
repository: "aa-replicated/gameshelf"
237+
replicated:
238+
image:
239+
registry: "proxy.replicated.com"
240+
repository: "library/replicated-sdk-image"
241+
postgresql:
242+
image:
243+
registry: "docker.io"
244+
redis:
245+
image:
246+
registry: "docker.io"
247+
```
248+
249+
- [ ] **Step 4: Run helm lint to confirm no structural issues**
250+
251+
```bash
252+
helm lint chart/gameshelf/
253+
```
254+
255+
Expected: `1 chart(s) linted, 0 chart(s) failed`
256+
257+
- [ ] **Step 5: Commit and push**
258+
259+
```bash
260+
git add helmchart.yaml
261+
git commit -m "feat: wire external DB toggle and generated password into helmchart.yaml"
262+
git push
263+
```
264+
265+
---
266+
267+
## Task 3: Verify and deploy
268+
269+
- [ ] **Step 1: Promote a new release in the Vendor Portal**
270+
271+
Push triggers CI which creates a new release. Promote it to the Unstable channel.
272+
273+
- [ ] **Step 2: Install with embedded DB (default)**
274+
275+
During the EC3 install config screen:
276+
- `Database` dropdown: leave as `Embedded (recommended)`
277+
- Complete install
278+
279+
Expected:
280+
- `gameshelf-postgresql-0` pod is Running
281+
- App connects successfully
282+
283+
Verify:
284+
```bash
285+
sudo k0s kubectl get pods -A | grep postgresql
286+
```
287+
288+
Expected: `gameshelf-postgresql-0 1/1 Running`
289+
290+
- [ ] **Step 3: Verify generated password is stable across upgrade**
291+
292+
After install, trigger an upgrade to a newer release (or re-deploy the same release). App should still connect to the DB without any reconfiguration. No `CrashLoopBackOff` or DB connection errors in the gameshelf pod logs:
293+
294+
```bash
295+
sudo k0s kubectl logs -l app.kubernetes.io/name=gameshelf -n <namespace> | grep -i "database\|connect\|error" | tail -20
296+
```
297+
298+
Expected: No connection errors.
299+
300+
- [ ] **Step 4: Install with external DB**
301+
302+
During the EC3 install config screen:
303+
- `Database` dropdown: select `External PostgreSQL`
304+
- Fill in host, port, name, user, password for a real external PostgreSQL instance
305+
306+
Expected:
307+
- No `gameshelf-postgresql-0` pod
308+
- App connects to the external instance
309+
310+
Verify:
311+
```bash
312+
sudo k0s kubectl get pods -A | grep postgresql
313+
```
314+
315+
Expected: no postgresql pod in the output.

0 commit comments

Comments
 (0)