Skip to content

Commit 3b19b70

Browse files
committed
Refactor GitOps structure and documentation for clarity; remove deprecated files and update references to the kafka-selfservice-gitops repository.
1 parent ba23325 commit 3b19b70

21 files changed

Lines changed: 304 additions & 281 deletions

File tree

.github/workflows/validate.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ on:
44
pull_request:
55
paths:
66
- "platform/**"
7-
- "gitops/**"
87
- "catalog/**"
98
- "backstage/**"
109
push:
@@ -21,16 +20,15 @@ jobs:
2120
pip install yamllint
2221
# Skeletons contain Nunjucks (${{ ... }}) and are not valid YAML on their own.
2322
yamllint -d relaxed \
24-
$(git ls-files 'platform/**/*.yaml' 'gitops/**/*.yaml' 'catalog/**/*.yaml') || true
23+
$(git ls-files 'platform/**/*.yaml' 'catalog/**/*.yaml') || true
2524
2625
- name: Validate rendered manifests against Kubernetes + CRD schemas
2726
run: |
2827
curl -sL https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz | tar xz
2928
# -ignore-missing-schemas because Kong Operator / Strimzi CRDs aren't in the
3029
# default schema set. For strict CRD validation, add -schema-location pointing
3130
# at your extracted CRD OpenAPI schemas.
32-
./kubeconform -ignore-missing-schemas -summary \
33-
platform gitops/apps
31+
./kubeconform -ignore-missing-schemas -summary platform
3432
3533
asyncapi:
3634
runs-on: ubuntu-latest

README.md

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ Operator** on Kubernetes.
1010
> The first request delivers everything (control plane, data plane, credentials,
1111
> ACLs, routing). Later requests usually just update the ACLs to add more topics.
1212
13+
> **Two repos.** This is the **portal/platform** repo (catalog, templates, platform
14+
> bootstrap). Tenant GitOps config lives in a companion repo,
15+
> [`kafka-selfservice-gitops`](https://github.com/your-org/kafka-selfservice-gitops):
16+
> the templates open PRs there and Argo CD watches it. See
17+
> [`docs/repositories.md`](docs/repositories.md).
18+
1319
## Why it's interesting
1420

1521
- **Zero broker changes to grant access.** Credentials are terminated at the gateway
@@ -36,15 +42,14 @@ Operator** on Kubernetes.
3642
│ ├── networking/ # GatewayClass/Config, Gateway, TLS cert
3743
│ ├── backstage/ # in-cluster Backstage: Deployment, Service, Postgres, config
3844
│ └── kafka/ # Strimzi Kafka cluster + topics
39-
├── gitops/
40-
│ ├── argocd/ # platform App + tenants ApplicationSet
41-
│ └── apps/ # one dir per onboarded app (Backstage writes here)
42-
│ └── fraud-analytics/ # worked example (rendered output)
4345
├── examples/kafka-client/ # SCRAM client config + test commands
4446
├── scripts/ # bootstrap, cert, validate
45-
└── docs/ # architecture.md, flows.md
47+
└── docs/ # architecture, flows, prerequisites, secrets, repositories
4648
```
4749

50+
Tenant config (the `apps/*` directories Backstage writes to, plus the Argo CD
51+
`ApplicationSet`) lives in the companion **`kafka-selfservice-gitops`** repo, not here.
52+
4853
## Prerequisites
4954

5055
- A Kubernetes cluster (minikube is fine) with **Kong Operator**, **Strimzi**,
@@ -64,12 +69,15 @@ The essentials:
6469
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
6570
```
6671

67-
**Argo CD** — reconciles `platform/` and auto-onboards each `gitops/apps/*` tenant:
72+
**Argo CD** — reconciles `platform/` (this repo) and auto-onboards each tenant from
73+
the companion repo's `apps/*`:
6874

6975
```bash
7076
kubectl create namespace argocd
7177
kubectl apply -n argocd --server-side --force-conflicts \
7278
-f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
79+
# then apply argocd/platform-app.yaml + argocd/tenants-appset.yaml from
80+
# the kafka-selfservice-gitops repo (edit repoURLs first).
7381
```
7482

7583
**Backstage** — runs in-cluster; build the image once, then deploy the manifests:
@@ -100,25 +108,27 @@ Kong Operator + Strimzi install commands (and the AsyncAPI page wiring) are also
100108
export KONNECT_PAT=kpat_xxx
101109
./scripts/bootstrap.sh
102110

103-
# 2) Either let Argo CD manage tenants...
104-
kubectl apply -f gitops/argocd/ # edit repoURL first
105-
# ...or apply the worked example directly:
106-
kubectl apply -k gitops/apps/fraud-analytics/kong/
111+
# 2) Tenants come from the companion repo (kafka-selfservice-gitops):
112+
# let Argo CD manage them...
113+
kubectl apply -f ../kafka-selfservice-gitops/argocd/ # edit repoURLs first
114+
# ...or apply the worked example directly:
115+
kubectl apply -k ../kafka-selfservice-gitops/apps/fraud-analytics/kong/
107116

108117
# 3) Expose the gateway locally and test
109118
minikube tunnel &
110119
cat examples/kafka-client/test-commands.md
111120
```
112121

113-
To wire up the portal, register `catalog-info.yaml` in Backstage and merge
114-
`backstage/app-config.snippet.yaml` into your `app-config.yaml`.
122+
To wire up the portal, point the in-cluster Backstage `catalog.locations` at this
123+
repo's `catalog-info.yaml` (see `platform/backstage/app-config.configmap.yaml`).
115124

116125
## The self-service experience
117126

118127
1. A developer opens the **Retail Banking NY** or **Wealth Management LA** API in the
119128
Backstage catalog and reads the AsyncAPI channels (topics).
120129
2. They run **Consume Kafka Topics**, name their app, pick topics, and choose SCRAM or
121-
OAuth. Backstage opens a PR under `gitops/apps/<app>/`.
130+
OAuth. Backstage opens a PR adding `apps/<app>/` to the `kafka-selfservice-gitops`
131+
repo.
122132
3. On merge, Argo CD + Kong Operator provision the virtual cluster, credentials, ACLs
123133
and route. The app connects to `bootstrap.<app>.127-0-0-1.sslip.io:9092`.
124134
4. Need more topics later? **Add Topics to Application** changes only the ACL policy.
@@ -139,9 +149,9 @@ See [`docs/flows.md`](docs/flows.md) for sequence diagrams and
139149
CRDs in *your* operator version: the SCRAM principal **password secret-ref** shape,
140150
and whether ACLs are a separate `EventGatewayVirtualClusterPolicy` or inline on the
141151
virtual cluster (`spec.apiSpec.clusterPolicies`). Both are called out in comments.
142-
- SCRAM passwords are placeholders (`REPLACE_ME`). For real use, generate them with a
143-
custom scaffolder action and store via SealedSecrets / External Secrets — never
144-
commit plaintext.
152+
- SCRAM passwords (and the Backstage/Konnect secrets) are placeholders (`REPLACE_ME`).
153+
For real use, generate them and store via Sealed Secrets or External Secrets — never
154+
commit plaintext. [`docs/secrets.md`](docs/secrets.md) shows worked manifests for both.
145155
- The `platform/` Kafka + Event Gateway manifests are adapted from the
146156
`kong-event-gw-kubernetes` reference.
147157

backstage/templates/add-topics-to-app/template.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ spec:
7676
required: [repoUrl]
7777
properties:
7878
repoUrl:
79-
title: GitOps repository
79+
title: GitOps config repository
8080
type: string
81+
description: The kafka-selfservice-gitops repo (Argo CD watches its apps/*).
8182
ui:field: RepoUrlPicker
8283
ui:options:
8384
allowedHosts:
@@ -89,7 +90,7 @@ spec:
8990
action: fetch:template
9091
input:
9192
url: ./skeleton
92-
targetPath: gitops/apps/${{ parameters.appName }}
93+
targetPath: apps/${{ parameters.appName }}
9394
values:
9495
appName: ${{ parameters.appName }}
9596
businessUnit: ${{ parameters.businessUnit }}

backstage/templates/consume-kafka-topics/template.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,11 @@ spec:
105105
required: [repoUrl]
106106
properties:
107107
repoUrl:
108-
title: GitOps repository
108+
title: GitOps config repository
109109
type: string
110-
description: Repository that Argo CD watches for tenant manifests.
110+
description: >
111+
The kafka-selfservice-gitops repo (Argo CD watches its apps/*). PRs from
112+
this template land there, not in the portal/platform repo.
111113
ui:field: RepoUrlPicker
112114
ui:options:
113115
allowedHosts:
@@ -119,7 +121,7 @@ spec:
119121
action: fetch:template
120122
input:
121123
url: ./skeleton
122-
targetPath: gitops/apps/${{ parameters.appName }}
124+
targetPath: apps/${{ parameters.appName }}
123125
values:
124126
appName: ${{ parameters.appName }}
125127
owner: ${{ parameters.owner }}
@@ -155,7 +157,7 @@ spec:
155157
action: catalog:register
156158
input:
157159
repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
158-
catalogInfoPath: /gitops/apps/${{ parameters.appName }}/catalog-info.yaml
160+
catalogInfoPath: /apps/${{ parameters.appName }}/catalog-info.yaml
159161
optional: true
160162

161163
output:

docs/architecture.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
| Layer | What it is | In this repo |
66
|-------|------------|--------------|
77
| Developer portal | Backstage (in-cluster) — catalog of streams (AsyncAPI) + self-service templates | `catalog/`, `backstage/`, deployed via `platform/backstage/` |
8-
| Delivery | Git + Argo CD (ApplicationSet per tenant) | `gitops/` |
9-
| Control | Kong Operator reconciling Konnect + data plane from CRDs | `platform/`, `gitops/apps/*/kong/` |
8+
| Delivery | Git + Argo CD (ApplicationSet per tenant) | `kafka-selfservice-gitops` repo |
9+
| Control | Kong Operator reconciling Konnect + data plane from CRDs | `platform/`, config repo `apps/*/kong/` |
1010
| Data | Kong Event Gateway data plane (KNEP) fronting Kafka | `platform/event-gateway/`, `platform/networking/` |
1111
| Backing store | Strimzi-managed Apache Kafka (`northwind`) | `platform/kafka/` |
1212

@@ -15,7 +15,7 @@
1515
```mermaid
1616
flowchart LR
1717
dev([App developer]) -->|browse AsyncAPI, pick topics| bs[Backstage template]
18-
bs -->|opens PR: gitops/apps/&lt;app&gt;/| git[(Git repo)]
18+
bs -->|opens PR: apps/&lt;app&gt;/| git[(config repo)]
1919
git -->|ApplicationSet syncs| argo[Argo CD]
2020
argo -->|applies CRDs| ko[Kong Operator]
2121
ko -->|configures| konnect[(Konnect control plane)]

docs/flows.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ sequenceDiagram
1818
participant KO as Kong Operator
1919
participant KEG as Event Gateway
2020
Dev->>BS: Pick provider + topics + auth (SCRAM)
21-
BS->>Git: PR adds gitops/apps/<app>/ (VC, ACL, TLSRoute, Secret)
21+
BS->>Git: PR adds apps/<app>/ to config repo (VC, ACL, TLSRoute, Secret)
2222
Dev->>Git: Review + merge
2323
Git->>Argo: ApplicationSet detects new tenant dir
2424
Argo->>KO: Apply CRDs
@@ -36,7 +36,7 @@ What "deliver everything" covers:
3636
## Flow 2 — Add topics later ("just update the ACLs")
3737

3838
Template: **Add Topics to Application**. Regenerates only
39-
`gitops/apps/<app>/kong/acl-policy.yaml`. The virtual cluster, credentials and route
39+
`apps/<app>/kong/acl-policy.yaml` (in the config repo). The virtual cluster, credentials and route
4040
are untouched, so the app keeps the same bootstrap endpoint and the same credential.
4141

4242
```mermaid

docs/prerequisites.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ This repo's `platform/networking/tls-certificate.yaml` then creates a self-signe
3030

3131
## 2. Argo CD
3232

33-
Drives GitOps: it reconciles `platform/` and auto-onboards each tenant under
34-
`gitops/apps/*` via the ApplicationSet.
33+
Drives GitOps: it reconciles this repo's `platform/` and auto-onboards each tenant
34+
from the companion `kafka-selfservice-gitops` repo's `apps/*` via the ApplicationSet.
35+
See [`repositories.md`](repositories.md) for the two-repo layout.
3536

3637
```bash
3738
kubectl create namespace argocd
@@ -52,16 +53,17 @@ kubectl -n argocd get secret argocd-initial-admin-secret \
5253
-o jsonpath='{.data.password}' | base64 -d; echo
5354
```
5455

55-
Then point Argo CD at your fork and let it manage everything:
56+
Then apply the Argo manifests **from the `kafka-selfservice-gitops` repo** and let it
57+
manage everything:
5658

5759
```bash
58-
# Edit the repoURL in these files first, then:
59-
kubectl apply -f gitops/argocd/platform-app.yaml # reconciles platform/
60-
kubectl apply -f gitops/argocd/tenants-appset.yaml # one App per gitops/apps/*
60+
# In your clone of kafka-selfservice-gitops (edit the repoURLs in these files first):
61+
kubectl apply -f argocd/platform-app.yaml # reconciles the portal repo's platform/
62+
kubectl apply -f argocd/tenants-appset.yaml # one App per apps/* in the config repo
6163
```
6264

63-
If you're not using Argo CD, apply the platform and tenants directly instead:
64-
`kubectl apply -k platform/` and `kubectl apply -k gitops/apps/<app>/kong/`.
65+
If you're not using Argo CD, apply directly instead: `kubectl apply -k platform/`
66+
(portal repo) and `kubectl apply -k apps/<app>/kong/` (config repo).
6567

6668
## 3. Backstage (in-cluster)
6769

@@ -115,8 +117,9 @@ Edit two files in `platform/backstage/`:
115117

116118
- `backstage-secrets.yaml` — set `POSTGRES_PASSWORD`, `GITHUB_TOKEN` (PAT/App token
117119
with `repo` + PR scope, since the templates open pull requests), and
118-
`BACKEND_SECRET` (`openssl rand -base64 32`). Use SealedSecrets / External Secrets
119-
for anything real — don't commit plaintext.
120+
`BACKEND_SECRET` (`openssl rand -base64 32`). The stub is plaintext for the demo;
121+
for anything real, replace it with a Sealed Secret or External Secret —
122+
[`docs/secrets.md`](secrets.md) has worked manifests for both.
120123
- `app-config.configmap.yaml` — point `catalog.locations[].target` at your fork's
121124
`catalog-info.yaml`. This is what the in-cluster app reads (it replaces
122125
`backstage/app-config.snippet.yaml`, which remains as a reference for the config

docs/repositories.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Repository topology
2+
3+
This demo uses **two repositories**. They can be collapsed into one, but the split is
4+
the more production-realistic setup and is how the templates are wired.
5+
6+
## The two repos
7+
8+
### `kafka-selfservice-backstage` (this repo) — portal / platform
9+
10+
Owned by the platform team; changes rarely.
11+
12+
- `catalog/` — AsyncAPI specs + Backstage catalog entities (the "available topics")
13+
- `backstage/templates/` — the self-service scaffolder templates
14+
- `platform/` — the bootstrap: Konnect control plane, Event Gateway data plane,
15+
Kafka, networking, and in-cluster Backstage
16+
- `docs/`, `scripts/`, `examples/`
17+
18+
Backstage's `catalog.locations` points at **this repo's** `catalog-info.yaml` to load
19+
the templates and the AsyncAPI APIs.
20+
21+
### `kafka-selfservice-gitops` — GitOps config
22+
23+
Written to constantly, by app teams via Backstage PRs.
24+
25+
- `apps/<app>/` — one directory per onboarded application (virtual cluster, ACLs,
26+
route, credentials)
27+
- `argocd/` — the platform `Application` and the tenants `ApplicationSet`
28+
29+
Argo CD watches **this repo's** `apps/*`.
30+
31+
## Who points where
32+
33+
```mermaid
34+
flowchart LR
35+
subgraph portal[kafka-selfservice-backstage]
36+
cat[catalog + templates]
37+
plat[platform/]
38+
end
39+
subgraph cfg[kafka-selfservice-gitops]
40+
apps[apps/*]
41+
appset[argocd/ApplicationSet]
42+
end
43+
bs[Backstage in-cluster] -->|catalog.locations| cat
44+
bs -->|scaffolder PR| apps
45+
argo[Argo CD] -->|platform-app -> path platform| plat
46+
argo -->|tenants-appset -> apps/*| apps
47+
```
48+
49+
- **Backstage → portal repo**: reads catalog + templates (`catalog.locations` in
50+
`platform/backstage/app-config.configmap.yaml`).
51+
- **Backstage → config repo**: the templates' `RepoUrlPicker` targets it; PRs add
52+
`apps/<app>/`. Nothing is committed back to the portal repo at runtime.
53+
- **Argo CD → portal repo**: `platform-app.yaml` deploys `platform/`.
54+
- **Argo CD → config repo**: `tenants-appset.yaml` deploys each `apps/<app>/kong/`.
55+
56+
## Wiring checklist
57+
58+
When you fork/clone, update these to your org's URLs:
59+
60+
| File | Repo | Set to |
61+
|------|------|--------|
62+
| `platform/backstage/app-config.configmap.yaml` (`catalog.locations[].target`) | portal | portal repo `catalog-info.yaml` |
63+
| `argocd/platform-app.yaml` (`spec.source.repoURL`) | config | portal repo |
64+
| `argocd/tenants-appset.yaml` (both `repoURL`s) | config | config repo |
65+
| Template runs (`RepoUrlPicker` selection) || config repo, chosen per run |
66+
67+
## Prefer a single repo?
68+
69+
Collapse them by putting `apps/` and `argocd/` back into this repo, pointing all the
70+
`repoURL`s and the templates at this one repo. The trade-off: onboarding-PR churn and
71+
app-team write access land in the same repo as your platform code. Fine for a solo
72+
demo; less so once multiple teams onboard.

0 commit comments

Comments
 (0)