Archify Sync GitOps template
A Copier template for deploying Archify Sync with Argo CD: an app-of-apps, the server's Helm chart and its values, optional secrets through External Secrets and an optional static NFS volume for PostgreSQL.
This commit is contained in:
commit
e2adb79e2d
15 files changed
+572
No files matched your search
@@ -0,0 +1,4 @@
|
|||||||
|
.env
|
||||||
|
.env-*
|
||||||
|
~*
|
||||||
|
/tmp/
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# archify-vscode-ext-sync-gitops-tmpl
|
||||||
|
|
||||||
|
A [Copier](https://copier.readthedocs.io) template for deploying [Archify Sync](https://gitea.lego-cloud.eu/vscode-extensions/archify-vscode-ext-sync) with [Argo CD](https://argo-cd.readthedocs.io). It renders an environment repository that Argo CD syncs: an app-of-apps, the server's Helm chart (taken from the server repository) and its values. Keep your answers in the environment repository; never hand-edit what Copier renders there.
|
||||||
|
|
||||||
|
```text
|
||||||
|
cluster/
|
||||||
|
├── 0000-bootstrap/0100-app-of-apps.yml.jinja # root app 0000-archify-sync-app-of-apps, applied once
|
||||||
|
├── 0300-applications/
|
||||||
|
│ ├── application.yml.jinja # the root app managing itself
|
||||||
|
│ ├── {{ '0100-archify-sync-secrets' if … }}/ # optional: secrets through External Secrets
|
||||||
|
│ ├── {{ '0150-archify-sync-storage' if … }}/ # optional: a static NFS volume for PostgreSQL
|
||||||
|
│ └── {{ '0200-archify-sync' if … }}/ # the chart from the server repo + values from here
|
||||||
|
└── 0500-resources/ # what those apps deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
Answers: `argocd` (namespace, project, the environment repository and revision) and `archify_sync` (`is_enabled`, chart source, image, host, database, single sign-on, metrics, `external_secrets`). `copier-answers.example.yml` is a complete example.
|
||||||
|
|
||||||
|
## Use it
|
||||||
|
|
||||||
|
1. **Image.** Build the server image from the server repository's Dockerfile and push it to your registry (`image.repository`, `image.tag`). For a private registry, name an image pull Secret in `image.pull_secret`.
|
||||||
|
2. **Identity provider.** Create the client and groups described in the server's README (single sign-on section).
|
||||||
|
3. **Secrets.** Without External Secrets, create the server's Secret yourself; the bundled PostgreSQL and the server read it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl create namespace archify-sync
|
||||||
|
kubectl -n archify-sync create secret generic archify-sync-secrets \
|
||||||
|
--from-literal=password="$PG_PASSWORD" \
|
||||||
|
--from-literal=url="postgres://archify:$PG_PASSWORD@archify-sync-postgresql:5432/archify" \
|
||||||
|
--from-literal=client-secret="$OIDC_CLIENT_SECRET"
|
||||||
|
```
|
||||||
|
|
||||||
|
The password goes into a URL: letters and digits only. With [External Secrets](https://external-secrets.io) installed, set `external_secrets.store` and the names of the two entries instead, and `external_secrets.image_pull` for a private registry; the template then renders the ExternalSecrets.
|
||||||
|
4. **Render.** Into a new environment repository, from your answers:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
copier copy --trust \
|
||||||
|
--data-file my-answers.yml \
|
||||||
|
https://gitea.lego-cloud.eu/vscode-extensions/archify-vscode-ext-sync-gitops-tmpl.git \
|
||||||
|
../archify-sync-gitops
|
||||||
|
```
|
||||||
|
|
||||||
|
Push it where Argo CD can read it (`argocd.repo_url`).
|
||||||
|
5. **Connect.** Give Argo CD access to the environment repository, then `kubectl apply -f cluster/0000-bootstrap/0100-app-of-apps.yml` once. After that the app-of-apps manages itself.
|
||||||
|
|
||||||
|
Behind the ingress the server needs WebSocket upgrades and long read and send timeouts; the rendered values set them for ingress-nginx.
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
task validate # render off, on, and with External Secrets into tmp/; check YAML and paths; helm lint the values
|
||||||
|
task render # a new template version: copier update in the environment repo (ENV_DIR)
|
||||||
|
task render:answers # after editing the environment repo's cluster/copier-answers.yml: copier recopy
|
||||||
|
```
|
||||||
|
|
||||||
|
`copier update` needs this repository committed and tagged; the environment repository records the template's version.
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# https://taskfile.dev
|
||||||
|
version: "3"
|
||||||
|
|
||||||
|
vars:
|
||||||
|
ENV_DIR: '{{.ENV_DIR | default "../archify-vscode-ext-sync-gitops"}}'
|
||||||
|
TMPL_URL: '{{.TMPL_URL | default "https://gitea.lego-cloud.eu/vscode-extensions/archify-vscode-ext-sync-gitops-tmpl.git"}}'
|
||||||
|
CHART_DIR: '{{.CHART_DIR | default "../archify-vscode-ext-sync/charts/archify-sync"}}'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
render:first:
|
||||||
|
desc: First render into the environment repository from the pushed template at a tag (-- REF=v0.1.0), with copier-answers.example.yml
|
||||||
|
requires:
|
||||||
|
vars: [REF]
|
||||||
|
cmds:
|
||||||
|
# From Gitea, not this folder: the answers file records where the template lives, so
|
||||||
|
# `copier update` in the environment repo finds it and its tags later.
|
||||||
|
- copier copy --trust --overwrite --defaults --vcs-ref "{{.REF}}" --data-file copier-answers.example.yml "{{.TMPL_URL}}" "{{.ENV_DIR}}"
|
||||||
|
|
||||||
|
render:
|
||||||
|
desc: Re-render the environment repository from its own cluster/copier-answers.yml (copier update)
|
||||||
|
dir: "{{.ENV_DIR}}"
|
||||||
|
cmds:
|
||||||
|
- copier update --trust --defaults --skip-answered --answers-file cluster/copier-answers.yml
|
||||||
|
|
||||||
|
render:answers:
|
||||||
|
desc: After editing the environment repository's cluster/copier-answers.yml - re-render everything from those answers (copier recopy)
|
||||||
|
dir: "{{.ENV_DIR}}"
|
||||||
|
cmds:
|
||||||
|
# copier update only carries template changes; changed answers need a recopy.
|
||||||
|
- copier recopy --trust --defaults --skip-answered --overwrite --answers-file cluster/copier-answers.yml
|
||||||
|
|
||||||
|
validate:
|
||||||
|
desc: Render the working copy (HEAD plus uncommitted changes, not the latest tag) flag off and on into tmp/, check YAML, paths and leftovers, lint the chart with the values
|
||||||
|
cmds:
|
||||||
|
- rm -rf tmp && mkdir -p tmp
|
||||||
|
- copier copy --trust --overwrite --defaults --vcs-ref HEAD . tmp/off
|
||||||
|
- test -z "$(ls tmp/off/cluster/0300-applications | grep archify-sync)"
|
||||||
|
- copier copy --trust --overwrite --defaults --vcs-ref HEAD --data-file copier-answers.example.yml . tmp/on
|
||||||
|
- test "$(find tmp -name '*.jinja' | wc -l | tr -d ' ')" = 0
|
||||||
|
- for f in $(find tmp -name '*.yml'); do yq -e 'true' "$f" >/dev/null || { echo "does not parse $f"; exit 1; }; done
|
||||||
|
- test ! -d tmp/on/cluster/0500-resources/0100-archify-sync-secrets
|
||||||
|
# With External Secrets and a private registry: ESO's own {{"{{ }}"}} must survive.
|
||||||
|
- yq '.archify_sync.external_secrets = {"store":"vault","postgres_password_key":"pg","oidc_client_secret_key":"oidc","image_pull":{"registry":"registry.example.com","username":"pull","password_key":"reg"}} | .archify_sync.image.pull_secret = "archify-sync-image-pull"' copier-answers.example.yml > tmp/eso.yml
|
||||||
|
- copier copy --trust --overwrite --defaults --vcs-ref HEAD --data-file tmp/eso.yml . tmp/eso
|
||||||
|
- test "$(find tmp/eso -name '*.jinja' | wc -l | tr -d ' ')" = 0
|
||||||
|
- grep -q '{{"{{"}} .postgresPassword }}' tmp/eso/cluster/0500-resources/0100-archify-sync-secrets/archify-sync-secrets.yml
|
||||||
|
- grep -q '"password" .password' tmp/eso/cluster/0500-resources/0100-archify-sync-secrets/archify-sync-image-pull.yml
|
||||||
|
- |
|
||||||
|
for f in $(find tmp/on/cluster/0300-applications -name '*.yml'); do
|
||||||
|
for p in $(yq '(.spec.source.path, .spec.sources[].path) | select(. != null)' "$f"); do
|
||||||
|
case "$p" in cluster/*) [ -d "tmp/on/$p" ] || { echo "$f: missing $p"; exit 1; };; esac
|
||||||
|
done
|
||||||
|
for v in $(yq '.spec.sources[].helm.valueFiles[]' "$f" 2>/dev/null); do
|
||||||
|
[ -f "tmp/on/${v#\$values/}" ] || { echo "$f: missing $v"; exit 1; }
|
||||||
|
done
|
||||||
|
done
|
||||||
|
- helm lint "{{.CHART_DIR}}" -f tmp/on/cluster/0500-resources/0200-archify-sync/archify-sync/values.yml
|
||||||
|
- echo "valid"
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{% macro render() %}
|
||||||
|
---
|
||||||
|
# Applied once by hand (or by the connect step); after that the copy in
|
||||||
|
# 0300-applications keeps it in step with git. Named apart from other
|
||||||
|
# app-of-apps that share the Argo CD namespace.
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: 0000-archify-sync-app-of-apps
|
||||||
|
namespace: {{ argocd.get('namespace', 'argocd') }}
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: {{ argocd.get('project', 'default') }}
|
||||||
|
source:
|
||||||
|
repoURL: {{ argocd.get('repo_url', 'https://git.example.com/you/archify-sync-gitops.git') }}
|
||||||
|
targetRevision: {{ argocd.get('target_revision', 'HEAD') }}
|
||||||
|
path: cluster/0300-applications
|
||||||
|
directory:
|
||||||
|
recurse: true
|
||||||
|
destination:
|
||||||
|
server: {{ argocd.get('destination_server', 'https://kubernetes.default.svc') }}
|
||||||
|
namespace: {{ argocd.get('namespace', 'argocd') }}
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
{% endmacro %}
|
||||||
|
{%- set result = render() -%}
|
||||||
|
{%- for line in result.split('\n') -%}
|
||||||
|
{% if line | trim | length != 0 -%}
|
||||||
|
{{ line }}
|
||||||
|
{% endif %}
|
||||||
|
{%- endfor %}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{% macro render() %}
|
||||||
|
---
|
||||||
|
# The app-of-apps managing itself: the bootstrap copy is applied once, then this
|
||||||
|
# one (inside the recursed tree) keeps it in step with git. Named apart from
|
||||||
|
# other app-of-apps that share the Argo CD namespace.
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: 0000-archify-sync-app-of-apps
|
||||||
|
namespace: {{ argocd.get('namespace', 'argocd') }}
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: {{ argocd.get('project', 'default') }}
|
||||||
|
source:
|
||||||
|
repoURL: {{ argocd.get('repo_url', 'https://git.example.com/you/archify-sync-gitops.git') }}
|
||||||
|
targetRevision: {{ argocd.get('target_revision', 'HEAD') }}
|
||||||
|
path: cluster/0300-applications
|
||||||
|
directory:
|
||||||
|
recurse: true
|
||||||
|
destination:
|
||||||
|
server: {{ argocd.get('destination_server', 'https://kubernetes.default.svc') }}
|
||||||
|
namespace: {{ argocd.get('namespace', 'argocd') }}
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
{% endmacro %}
|
||||||
|
{%- set result = render() -%}
|
||||||
|
{%- for line in result.split('\n') -%}
|
||||||
|
{% if line | trim | length != 0 -%}
|
||||||
|
{{ line }}
|
||||||
|
{% endif %}
|
||||||
|
{%- endfor %}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
{% macro render() %}
|
||||||
|
---
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: 0100-archify-sync-secrets
|
||||||
|
namespace: {{ argocd.get('namespace', 'argocd') }}
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
annotations:
|
||||||
|
# Before the server: its pods need the Secret this app makes.
|
||||||
|
argocd.argoproj.io/sync-wave: "0"
|
||||||
|
spec:
|
||||||
|
project: {{ argocd.get('project', 'default') }}
|
||||||
|
# The server's secrets from your secret store through External Secrets.
|
||||||
|
source:
|
||||||
|
repoURL: {{ argocd.get('repo_url', 'https://git.example.com/you/archify-sync-gitops.git') }}
|
||||||
|
targetRevision: {{ argocd.get('target_revision', 'HEAD') }}
|
||||||
|
path: cluster/0500-resources/0100-archify-sync-secrets
|
||||||
|
directory:
|
||||||
|
recurse: true
|
||||||
|
destination:
|
||||||
|
server: {{ argocd.get('destination_server', 'https://kubernetes.default.svc') }}
|
||||||
|
namespace: {{ archify_sync.get('namespace', 'archify-sync') }}
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
{% endmacro %}
|
||||||
|
{%- set result = render() -%}
|
||||||
|
{%- for line in result.split('\n') -%}
|
||||||
|
{% if line | trim | length != 0 -%}
|
||||||
|
{{ line }}
|
||||||
|
{% endif %}
|
||||||
|
{%- endfor %}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
{% macro render() %}
|
||||||
|
---
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: 0150-archify-sync-storage
|
||||||
|
namespace: {{ argocd.get('namespace', 'argocd') }}
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
annotations:
|
||||||
|
# Before the server: its database needs the claim this app makes.
|
||||||
|
argocd.argoproj.io/sync-wave: "0"
|
||||||
|
spec:
|
||||||
|
project: {{ argocd.get('project', 'default') }}
|
||||||
|
# The database volume: a static NFS volume, an export owned by uid 70.
|
||||||
|
source:
|
||||||
|
repoURL: {{ argocd.get('repo_url', 'https://git.example.com/you/archify-sync-gitops.git') }}
|
||||||
|
targetRevision: {{ argocd.get('target_revision', 'HEAD') }}
|
||||||
|
path: cluster/0500-resources/0150-archify-sync-storage
|
||||||
|
directory:
|
||||||
|
recurse: true
|
||||||
|
destination:
|
||||||
|
server: {{ argocd.get('destination_server', 'https://kubernetes.default.svc') }}
|
||||||
|
namespace: {{ archify_sync.get('namespace', 'archify-sync') }}
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
{% endmacro %}
|
||||||
|
{%- set result = render() -%}
|
||||||
|
{%- for line in result.split('\n') -%}
|
||||||
|
{% if line | trim | length != 0 -%}
|
||||||
|
{{ line }}
|
||||||
|
{% endif %}
|
||||||
|
{%- endfor %}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
{% macro render() %}
|
||||||
|
---
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: 0200-archify-sync
|
||||||
|
namespace: {{ argocd.get('namespace', 'argocd') }}
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "1"
|
||||||
|
spec:
|
||||||
|
project: {{ argocd.get('project', 'default') }}
|
||||||
|
# Archify Sync: the chart from the server repository, the values from this one.
|
||||||
|
# One pod by design (the live copy of each model is held by one server), so
|
||||||
|
# updates are Recreate; editors work offline for those seconds and catch up.
|
||||||
|
sources:
|
||||||
|
- repoURL: {{ archify_sync.get('chart_repo', 'https://gitea.lego-cloud.eu/vscode-extensions/archify-vscode-ext-sync.git') }}
|
||||||
|
targetRevision: {{ archify_sync.get('chart_revision', 'main') }}
|
||||||
|
path: {{ archify_sync.get('chart_path', 'charts/archify-sync') }}
|
||||||
|
helm:
|
||||||
|
# The release name is part of the database URL in the ExternalSecret (0100).
|
||||||
|
releaseName: archify-sync
|
||||||
|
valueFiles:
|
||||||
|
- $values/cluster/0500-resources/0200-archify-sync/archify-sync/values.yml
|
||||||
|
- repoURL: {{ argocd.get('repo_url', 'https://git.example.com/you/archify-sync-gitops.git') }}
|
||||||
|
targetRevision: {{ argocd.get('target_revision', 'HEAD') }}
|
||||||
|
ref: values
|
||||||
|
destination:
|
||||||
|
server: {{ argocd.get('destination_server', 'https://kubernetes.default.svc') }}
|
||||||
|
namespace: {{ archify_sync.get('namespace', 'archify-sync') }}
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
{% endmacro %}
|
||||||
|
{%- set result = render() -%}
|
||||||
|
{%- for line in result.split('\n') -%}
|
||||||
|
{% if line | trim | length != 0 -%}
|
||||||
|
{{ line }}
|
||||||
|
{% endif %}
|
||||||
|
{%- endfor %}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
{%- set es = archify_sync.get('external_secrets', {}) -%}
|
||||||
|
# Secret `archify-sync-secrets` from your secret store through External Secrets.
|
||||||
|
# ESO's own templating is escaped below so it reaches the cluster as written.
|
||||||
|
#
|
||||||
|
# The store needs two entries (named in external_secrets):
|
||||||
|
# postgres_password_key password of the bundled postgres role `archify`;
|
||||||
|
# letters and digits only (it goes into a URL)
|
||||||
|
# oidc_client_secret_key secret of the archify-sync client at the identity provider
|
||||||
|
#
|
||||||
|
# The URL names the chart's database Service, `<release>-postgresql`; the release is
|
||||||
|
# `archify-sync` (0200-archify-sync).
|
||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: archify-sync-secrets
|
||||||
|
namespace: {{ archify_sync.get('namespace', 'archify-sync') }}
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
name: {{ es.get('store') }}
|
||||||
|
kind: {{ es.get('store_kind', 'ClusterSecretStore') }}
|
||||||
|
target:
|
||||||
|
name: archify-sync-secrets
|
||||||
|
template:
|
||||||
|
engineVersion: v2
|
||||||
|
data:
|
||||||
|
password: "{% raw %}{{ .postgresPassword }}{% endraw %}"
|
||||||
|
url: "postgres://archify:{% raw %}{{ .postgresPassword }}{% endraw %}@archify-sync-postgresql:5432/archify"
|
||||||
|
client-secret: "{% raw %}{{ .oidcClientSecret }}{% endraw %}"
|
||||||
|
data:
|
||||||
|
- secretKey: postgresPassword
|
||||||
|
remoteRef:
|
||||||
|
key: {{ es.get('postgres_password_key', 'archify-sync-postgres-password') }}
|
||||||
|
- secretKey: oidcClientSecret
|
||||||
|
remoteRef:
|
||||||
|
key: {{ es.get('oidc_client_secret_key', 'archify-sync-oidc-client-secret') }}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
{%- set pull = archify_sync.get('external_secrets', {}).get('image_pull', {}) -%}
|
||||||
|
{%- set es = archify_sync.get('external_secrets', {}) -%}
|
||||||
|
{%- set user = pull.get('username') | tojson -%}
|
||||||
|
# The image pull secret for a private registry: its password from your secret store.
|
||||||
|
# ESO's own templating is escaped below so it reaches the cluster as written.
|
||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: {{ archify_sync.image.pull_secret }}
|
||||||
|
namespace: {{ archify_sync.get('namespace', 'archify-sync') }}
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
name: {{ es.get('store') }}
|
||||||
|
kind: {{ es.get('store_kind', 'ClusterSecretStore') }}
|
||||||
|
target:
|
||||||
|
name: {{ archify_sync.image.pull_secret }}
|
||||||
|
creationPolicy: Owner
|
||||||
|
template:
|
||||||
|
engineVersion: v2
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
|
data:
|
||||||
|
.dockerconfigjson: '{{ '{{' }} dict "auths" (dict {{ pull.get('registry') | tojson }} (dict "username" {{ user }} "password" .password "auth" (printf "{{ pull.get('username') }}:%s" .password | b64enc))) | toJson {{ '}}' }}'
|
||||||
|
data:
|
||||||
|
- secretKey: password
|
||||||
|
remoteRef:
|
||||||
|
key: {{ pull.get('password_key') }}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
{% macro render() %}
|
||||||
|
{%- set database = archify_sync.get('database', {}) %}
|
||||||
|
{%- set namespace = archify_sync.get('namespace', 'archify-sync') %}
|
||||||
|
---
|
||||||
|
# Static NFS volume: an export owned by postgres:17-alpine's uid 70 with mode 0700,
|
||||||
|
# shared with maproot. Shares that map every user to root are refused by PostgreSQL.
|
||||||
|
# Retain: deleting the app never deletes the data.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: {{ namespace }}-database
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/part-of: archify-sync
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: {{ database.get('size', '8Gi') }}
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
persistentVolumeReclaimPolicy: Retain
|
||||||
|
storageClassName: ""
|
||||||
|
nfs:
|
||||||
|
server: {{ database.get('nfs_server') }}
|
||||||
|
path: {{ database.get('nfs_path') }}
|
||||||
|
claimRef:
|
||||||
|
namespace: {{ namespace }}
|
||||||
|
name: archify-sync-database
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: archify-sync-database
|
||||||
|
namespace: {{ namespace }}
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/part-of: archify-sync
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
storageClassName: ""
|
||||||
|
volumeName: {{ namespace }}-database
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ database.get('size', '8Gi') }}
|
||||||
|
{% endmacro %}
|
||||||
|
{%- set result = render() -%}
|
||||||
|
{%- for line in result.split('\n') -%}
|
||||||
|
{% if line | trim | length != 0 -%}
|
||||||
|
{{ line }}
|
||||||
|
{% endif %}
|
||||||
|
{%- endfor %}
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
{% macro render() %}
|
||||||
|
{%- set image = archify_sync.get('image', {}) %}
|
||||||
|
{%- set database = archify_sync.get('database', {}) %}
|
||||||
|
{%- set oidc = archify_sync.get('oidc', {}) %}
|
||||||
|
{%- set metrics = archify_sync.get('metrics', {}) %}
|
||||||
|
{%- set host = archify_sync.get('host', 'archify.example.com') %}
|
||||||
|
# Values for charts/archify-sync of the server repository.
|
||||||
|
image:
|
||||||
|
repository: {{ image.get('repository', 'registry.example.com/archify-sync') }}
|
||||||
|
tag: {{ image.get('tag', '0.1.0') | string | tojson }}
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
{%- if image.get('pull_secret') %}
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: {{ image.get('pull_secret') }}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
# TLS ends at your ingress or edge proxy; people reach the server here.
|
||||||
|
publicUrl: https://{{ host }}
|
||||||
|
|
||||||
|
# The bundled PostgreSQL, its password and URL from Secret archify-sync-secrets
|
||||||
|
# (0100 with External Secrets, or made by hand).
|
||||||
|
postgresql:
|
||||||
|
enabled: true
|
||||||
|
existingSecret: archify-sync-secrets
|
||||||
|
{%- if database.get('nfs_path') %}
|
||||||
|
# The static NFS volume from 0150-archify-sync-storage.
|
||||||
|
existingClaim: archify-sync-database
|
||||||
|
{%- else %}
|
||||||
|
{%- if database.get('storage_class') %}
|
||||||
|
storageClass: {{ database.get('storage_class') }}
|
||||||
|
{%- endif %}
|
||||||
|
storage: {{ database.get('size', '8Gi') }}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
config:
|
||||||
|
name: Archify Sync
|
||||||
|
membersCanInvite: {{ archify_sync.get('members_can_invite', false) | tojson }}
|
||||||
|
logJson: true
|
||||||
|
|
||||||
|
{%- if oidc.get('is_enabled', false) %}
|
||||||
|
oidc:
|
||||||
|
enabled: true
|
||||||
|
issuer: {{ oidc.get('issuer', 'https://sso.example.com/realms/home') }}
|
||||||
|
clientId: {{ oidc.get('client_id', 'archify-sync') }}
|
||||||
|
existingSecret: archify-sync-secrets
|
||||||
|
existingSecretKey: client-secret
|
||||||
|
label: {{ oidc.get('label', 'Keycloak') | tojson }}
|
||||||
|
allowedGroups: {{ oidc.get('allowed_groups', []) | tojson }}
|
||||||
|
adminGroups: {{ oidc.get('admin_groups', []) | tojson }}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: {{ archify_sync.get('ingress_class', 'nginx') }}
|
||||||
|
host: {{ host }}
|
||||||
|
annotations:
|
||||||
|
# Edits travel over a WebSocket that stays open for hours.
|
||||||
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-body-size: 8m
|
||||||
|
|
||||||
|
metrics:
|
||||||
|
enabled: {{ metrics.get('is_enabled', true) | tojson }}
|
||||||
|
serviceMonitor:
|
||||||
|
enabled: {{ metrics.get('service_monitor', false) | tojson }}
|
||||||
|
{% endmacro %}
|
||||||
|
{%- set result = render() -%}
|
||||||
|
{%- for line in result.split('\n') -%}
|
||||||
|
{% if line | trim | length != 0 -%}
|
||||||
|
{{ line }}
|
||||||
|
{% endif %}
|
||||||
|
{%- endfor %}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# An example environment. Copy to your environment repository's
|
||||||
|
# cluster/copier-answers.yml on the first render (task render:first), then
|
||||||
|
# change values there and run `task render` (copier update).
|
||||||
|
argocd:
|
||||||
|
namespace: argocd
|
||||||
|
project: default
|
||||||
|
destination_server: https://kubernetes.default.svc
|
||||||
|
# The environment repository Argo CD reads (this template renders into it).
|
||||||
|
repo_url: https://git.example.com/you/archify-sync-gitops.git
|
||||||
|
target_revision: HEAD
|
||||||
|
|
||||||
|
archify_sync:
|
||||||
|
is_enabled: true
|
||||||
|
namespace: archify-sync
|
||||||
|
# The Helm chart lives in the server repository.
|
||||||
|
chart_repo: https://gitea.lego-cloud.eu/vscode-extensions/archify-vscode-ext-sync.git
|
||||||
|
chart_path: charts/archify-sync
|
||||||
|
chart_revision: main
|
||||||
|
image:
|
||||||
|
# Built from the server repository's Dockerfile and pushed to your registry.
|
||||||
|
repository: registry.example.com/archify-sync
|
||||||
|
tag: "0.1.4"
|
||||||
|
# For a private registry: the name of an image pull Secret in the namespace.
|
||||||
|
# pull_secret: archify-sync-image-pull
|
||||||
|
host: archify.example.com
|
||||||
|
ingress_class: nginx
|
||||||
|
database:
|
||||||
|
size: 8Gi
|
||||||
|
# The cluster's default storage class when unset. It must keep file owners:
|
||||||
|
# PostgreSQL refuses a data directory that maps every user to root.
|
||||||
|
# storage_class: standard
|
||||||
|
# Or a static NFS volume, an export owned by uid 70, mode 0700:
|
||||||
|
# nfs_server: 10.0.0.10
|
||||||
|
# nfs_path: /exports/archify-sync-database
|
||||||
|
oidc:
|
||||||
|
is_enabled: true
|
||||||
|
issuer: https://sso.example.com/realms/home
|
||||||
|
client_id: archify-sync
|
||||||
|
label: Keycloak
|
||||||
|
allowed_groups: [archify-users]
|
||||||
|
admin_groups: [archify-admins]
|
||||||
|
members_can_invite: false
|
||||||
|
metrics:
|
||||||
|
is_enabled: true
|
||||||
|
service_monitor: false
|
||||||
|
# Without external_secrets, create Secret archify-sync-secrets yourself (see
|
||||||
|
# README). With External Secrets installed, name the store and its entries:
|
||||||
|
# external_secrets:
|
||||||
|
# store: vault
|
||||||
|
# store_kind: ClusterSecretStore
|
||||||
|
# postgres_password_key: archify-sync-postgres-password
|
||||||
|
# oidc_client_secret_key: archify-sync-oidc-client-secret
|
||||||
|
# # And the image pull secret for a private registry (needs image.pull_secret):
|
||||||
|
# image_pull:
|
||||||
|
# registry: registry.example.com
|
||||||
|
# username: archify-pull
|
||||||
|
# password_key: archify-sync-registry-password
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
# Copier template for the Argo CD deployment of Archify Sync. Renders into the
|
||||||
|
# environment repository (archify-vscode-ext-sync-gitops), which Argo CD syncs.
|
||||||
|
_templates_suffix: ".jinja"
|
||||||
|
_answers_file: cluster/copier-answers.yml
|
||||||
|
_exclude:
|
||||||
|
- "~*"
|
||||||
|
- ".git"
|
||||||
|
- ".env"
|
||||||
|
- ".env-*"
|
||||||
|
- "/tmp"
|
||||||
|
- "/copier.yml"
|
||||||
|
- "/copier-answers.example.yml"
|
||||||
|
- "/Taskfile.yml"
|
||||||
|
- "/README.md"
|
||||||
|
- "/.gitignore"
|
||||||
|
|
||||||
|
argocd:
|
||||||
|
type: yaml
|
||||||
|
help: "Argo CD: namespace, project, the environment repository and its revision"
|
||||||
|
default: {}
|
||||||
|
|
||||||
|
archify_sync:
|
||||||
|
type: yaml
|
||||||
|
help: "Archify Sync: is_enabled, image, host, database, single sign-on"
|
||||||
|
default: {}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Changes here will be overwritten by Copier; run `task render` in the template repo after editing.
|
||||||
|
{{ _copier_answers|to_nice_yaml -}}
|
||||||
Reference in new issue
Block a user