OneLab Kubernetes GitOps (Argo CD)
- Helm charts: onelab app + observability (Loki/Promtail/Grafana) - Values under gitops/values/ with public-safe placeholders - Argo CD Application (spec.sources, 2.6+) Made-with: Cursor
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
*.local.yaml
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
11
README.md
Normal file
11
README.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# OneLab (Kubernetes)
|
||||||
|
|
||||||
|
Deploy OneLab with **Argo CD** and Helm using the manifests under [`gitops/`](gitops/).
|
||||||
|
|
||||||
|
**Documentation:** [gitops/README.md](gitops/README.md) — prerequisites, configuration, bootstrap, and troubleshooting.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f gitops/argocd/application.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit `gitops/argocd/application.yaml` (`repoURL`, `targetRevision`) and `gitops/values/*.yaml` before syncing in production.
|
||||||
223
gitops/README.md
Normal file
223
gitops/README.md
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
# OneLab GitOps (Argo CD)
|
||||||
|
|
||||||
|
This directory is the **declarative source** for OneLab on Kubernetes. [Argo CD](https://argo-cd.readthedocs.io/) applies **two Helm-based sources** from Git (Argo invokes Helm; you do not use Helm CLI as the primary install path for the cluster).
|
||||||
|
|
||||||
|
This repository is **GitOps-only**: everything required to deploy OneLab on Kubernetes lives under **`gitops/`**.
|
||||||
|
|
||||||
|
## What gets deployed
|
||||||
|
|
||||||
|
| Helm release | Chart path | Namespace | Role |
|
||||||
|
|--------------|------------|-----------|------|
|
||||||
|
| `onelab` | [`charts/onelab`](charts/onelab) | `onelab` | Application workloads, Postgres, Redis, RabbitMQ, revproxy, ingress hooks |
|
||||||
|
| `onelab-obs` | [`observability/`](observability/) | `onelab` | Loki, Promtail, Grafana (logs) |
|
||||||
|
|
||||||
|
Both are wired by a single Argo CD [`Application`](argocd/application.yaml) using **`spec.sources`** (requires **Argo CD 2.6+**).
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
subgraph git [Git repository]
|
||||||
|
V[gitops/values]
|
||||||
|
C[charts/onelab]
|
||||||
|
O[observability]
|
||||||
|
end
|
||||||
|
subgraph argo [Argo CD]
|
||||||
|
App[Application onelab]
|
||||||
|
end
|
||||||
|
subgraph cluster [Kubernetes cluster]
|
||||||
|
NS[namespace onelab]
|
||||||
|
end
|
||||||
|
V --> App
|
||||||
|
C --> App
|
||||||
|
O --> App
|
||||||
|
App --> NS
|
||||||
|
```
|
||||||
|
|
||||||
|
1. You commit changes under **`gitops/values/`** (and optionally edit `repoURL` / `targetRevision` in the Application).
|
||||||
|
2. Argo reconciles: Helm renders `onelab` + `onelab-obs` into namespace **`onelab`**.
|
||||||
|
3. Sync waves order StatefulSets and app Deployments (Postgres → Redis/Rabbit/config → apps).
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
| Path | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| [`charts/onelab`](charts/onelab) | OneLab Helm chart — **Argo source 1** |
|
||||||
|
| [`values/`](values/) | **Operator entry point**: [`values/env-example.yaml`](values/env-example.yaml), [`values/observability.yaml`](values/observability.yaml), templates — see [`values/README.md`](values/README.md) |
|
||||||
|
| [`observability/`](observability/) | Loki / Promtail / Grafana umbrella chart — **Argo source 2** (`releaseName: onelab-obs`) |
|
||||||
|
| [`argocd/application.yaml`](argocd/application.yaml) | `Application` manifest (`spec.sources`, destination namespace `onelab`) |
|
||||||
|
| [`argocd/jsonpatch-multisource.json`](argocd/jsonpatch-multisource.json) | One-time JSON patch if a live `Application` still has legacy `spec.source` only |
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. **Kubernetes** (e.g. k3s) with a default **StorageClass** for Postgres/Rabbit/Loki/Grafana PVCs (e.g. `local-path`).
|
||||||
|
2. **Container images** from `hub.andrewalliance.com` (or your mirror): registry credentials via Helm values or a pre-created `docker-registry` Secret — see [Private registry credentials](#private-registry-credentials).
|
||||||
|
3. **RabbitMQ TLS** before RabbitMQ starts: Kubernetes Secret `onelab-rabbit-tls`, or `rabbitmq.tls.embed` in private values — see [RabbitMQ TLS](#rabbitmq-tls).
|
||||||
|
4. **Host paths** when using `persistence.mode: hostPath`: `/opt/onelab/data` and `/opt/onelab/logs` on nodes that run those pods (aligned with Promtail in [`values/observability.yaml`](values/observability.yaml)), or use RWX storage for multi-node.
|
||||||
|
|
||||||
|
## Configuration (single place to edit)
|
||||||
|
|
||||||
|
- **OneLab app / ingress / DB / tokens / registry**: [`values/env-example.yaml`](values/env-example.yaml) — copy patterns, replace **`REPLACE_*`** placeholders, or overlay a gitignored file; see [`values/secrets.example.yaml`](values/secrets.example.yaml) and [`values/README.md`](values/README.md).
|
||||||
|
- **Observability**: [`values/observability.yaml`](values/observability.yaml) — Grafana password (**`REPLACE_GRAFANA_ADMIN_PASSWORD`**), ingress host, Promtail log hostPath.
|
||||||
|
- **Argo Git coordinates**: [`argocd/application.yaml`](argocd/application.yaml) — set `repoURL`, `targetRevision`, and `helm.valueFiles` if you add e.g. `secrets.local.yaml`.
|
||||||
|
|
||||||
|
The chart default [`charts/onelab/values.yaml`](charts/onelab/values.yaml) holds non-secret structure and safe placeholders only; **do not rely on it for production secrets**.
|
||||||
|
|
||||||
|
## Bootstrap checklist
|
||||||
|
|
||||||
|
1. Fork or clone this repository and push it to a Git remote your cluster can reach.
|
||||||
|
2. Edit [`argocd/application.yaml`](argocd/application.yaml): **`repoURL`** → your remote, **`targetRevision`** → your branch/tag.
|
||||||
|
3. Edit [`values/env-example.yaml`](values/env-example.yaml): DNS hostnames, TLS secret names, cert-manager issuer, and all **`REPLACE_*`** values (or use a gitignored overlay).
|
||||||
|
4. Edit [`values/observability.yaml`](values/observability.yaml): Grafana host/password aligned with your DNS and TLS.
|
||||||
|
5. If the Git repo is **private**, register it in Argo CD (see below).
|
||||||
|
6. Ensure **RabbitMQ TLS** Secret exists (or use embedded TLS in private values).
|
||||||
|
7. Apply the Application:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f gitops/argocd/application.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
8. In Argo UI or CLI, confirm sync to namespace **`onelab`** and fix any `ImagePullBackOff` / TLS issues using the sections below.
|
||||||
|
|
||||||
|
**Single controller:** Use **only** this Argo CD `Application` for `onelab` / `onelab-obs`. Do not manage the same namespace with a parallel **Helm CLI** release.
|
||||||
|
|
||||||
|
## Private registry credentials
|
||||||
|
|
||||||
|
Set `registry.username` / `registry.password` in values (prefer a **gitignored** file merged last), or create the Secret manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl create secret docker-registry hub-andrewalliance -n onelab \
|
||||||
|
--docker-server=hub.andrewalliance.com \
|
||||||
|
--docker-username='YOUR_USER' \
|
||||||
|
--docker-password='YOUR_PASSWORD'
|
||||||
|
```
|
||||||
|
|
||||||
|
…then set `registry.createPullSecret: false` and keep `imagePullSecrets: [{ name: hub-andrewalliance }]` in values.
|
||||||
|
|
||||||
|
### StatefulSet pods still get `401 Unauthorized` / `ImagePullBackOff` after enabling registry auth
|
||||||
|
|
||||||
|
If `db-0` / `rabbitmq-0` were created **before** `imagePullSecrets` existed, delete those pods once so they pick up the new Pod spec:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete pod -n onelab db-0 rabbitmq-0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argo CD private Git repository
|
||||||
|
|
||||||
|
If the Application shows `authentication required: Unauthorized`, register the repo (use a deploy token or PAT with read access):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
argocd repo add https://github.com/YOUR_ORG/YOUR_REPO.git \
|
||||||
|
--username git \
|
||||||
|
--password YOUR_TOKEN
|
||||||
|
```
|
||||||
|
|
||||||
|
## RabbitMQ TLS
|
||||||
|
|
||||||
|
Secret **`onelab-rabbit-tls`** must exist in namespace **`onelab`** before RabbitMQ starts (keys: typically `tls.crt`, `tls.key`, and optionally chain). **PEM material is not shipped in this GitOps tree** — generate certs or use your PKI, then:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl create secret tls onelab-rabbit-tls -n onelab \
|
||||||
|
--cert=path/to/fullchain.pem \
|
||||||
|
--key=path/to/key.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, set `rabbitmq.tls.embed: true` and supply `rabbitmq.tls.crt` / `rabbitmq.tls.key` / `rabbitmq.tls.fullchain` via a **private** values file (never commit real keys).
|
||||||
|
|
||||||
|
## Deploy with Argo CD (details)
|
||||||
|
|
||||||
|
**Requirements:** Argo CD **2.6+** (`spec.sources`).
|
||||||
|
|
||||||
|
Each entry under `spec.sources` has its own `helm.releaseName` and `helm.valueFiles` (paths are **relative to that source’s `path`**):
|
||||||
|
|
||||||
|
- Source `gitops/charts/onelab` → e.g. `../../values/env-example.yaml`, optionally `../../values/secrets.local.yaml`
|
||||||
|
- Source `gitops/observability` → e.g. `../../values/observability.yaml`
|
||||||
|
|
||||||
|
### Migrating `spec.source` → `spec.sources`
|
||||||
|
|
||||||
|
If the `onelab` `Application` was created earlier with **`spec.source` only**, a plain `kubectl apply` may **not** remove `spec.source`, and Argo will not reconcile the observability chart.
|
||||||
|
|
||||||
|
Check:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get application onelab -n argocd -o jsonpath='{.spec.source}{"\n"}{.spec.sources}{"\n"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
If `source` is set and `sources` is empty, patch once (edit `repoURL` in the patch file to match your remote):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl patch application onelab -n argocd --type json --patch-file gitops/argocd/jsonpatch-multisource.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Observability (Loki / Promtail / Grafana)
|
||||||
|
|
||||||
|
The umbrella chart under [`observability/`](observability/) deploys:
|
||||||
|
|
||||||
|
- **Loki** — log storage (SingleBinary, filesystem PVC; retention from [`values/observability.yaml`](values/observability.yaml)).
|
||||||
|
- **Promtail** — DaemonSet: Kubernetes pod logs plus **OneLab file logs** from the host path configured in [`values/observability.yaml`](values/observability.yaml) (keep in sync with OneLab `persistence.hostPath.logs`).
|
||||||
|
- **Grafana** — Explore; datasource points at this release’s Loki gateway.
|
||||||
|
|
||||||
|
### First-time setup
|
||||||
|
|
||||||
|
1. Set a strong **`grafana.adminPassword`** in [`values/observability.yaml`](values/observability.yaml) (or use `admin.existingSecret` per the upstream Grafana chart).
|
||||||
|
2. Align **Grafana ingress host** with `grafana.ini.server.domain` / `root_url` in the same file.
|
||||||
|
3. **Multi-node** — with `hostPath` logs, each node only sees its own files; Promtail runs on every node.
|
||||||
|
|
||||||
|
### OneLab-only ingestion
|
||||||
|
|
||||||
|
Promtail **`extraRelabelConfigs`** keep only pods in namespace **`onelab`**. Host file logs are tagged **`namespace: onelab`**, **`component: host-logs`**.
|
||||||
|
|
||||||
|
### Dashboard: **OneLab logs**
|
||||||
|
|
||||||
|
Grafana sidecar loads the dashboard from `observability/dashboards/onelab-logs.json` (`uid` `onelab-logs`).
|
||||||
|
|
||||||
|
#### Grafana pod: `init-chown-data` CrashLoopBackOff
|
||||||
|
|
||||||
|
This repo sets **`grafana.initChownData.enabled: false`** with **`fsGroup: 472`** for Pod Security–friendly clusters. If Grafana cannot write to the PVC, delete the Grafana PVC once after changing values or adjust Pod Security for namespace `onelab`.
|
||||||
|
|
||||||
|
### Access Grafana
|
||||||
|
|
||||||
|
Ingress **`grafana-onelab`** is defined in `observability/templates/ingress-grafana-onelab.yaml`. Defaults use example hosts in [`values/observability.yaml`](values/observability.yaml) (`grafana.onelab.example.com`); change to your DNS and TLS Secret name.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n onelab port-forward svc/onelab-obs-grafana 3000:80
|
||||||
|
```
|
||||||
|
|
||||||
|
### Maintainers: vendored chart dependencies
|
||||||
|
|
||||||
|
From `gitops/observability/`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm dependency update
|
||||||
|
```
|
||||||
|
|
||||||
|
Commit updated `Chart.lock` and `charts/*.tgz` so Argo can render without live Helm repo access at sync time.
|
||||||
|
|
||||||
|
## Application configuration (`configurations.yml`)
|
||||||
|
|
||||||
|
For Kubernetes you do **not** need a separate `configurations.yml` in Git. The OneLab chart renders it from [`charts/onelab/files/configurations.gotmpl`](charts/onelab/files/configurations.gotmpl) into Secret **`onelab-configurations`**.
|
||||||
|
|
||||||
|
1. **Values (recommended)** — set `onelab.compliance`, `onelab.ldap`, etc. See [`values/instance-overrides.example.yaml`](values/instance-overrides.example.yaml) and add paths under **`spec.sources[].helm.valueFiles`** for the `gitops/charts/onelab` source.
|
||||||
|
2. **Bring your own Secret** — set `configuration.existingSecretName`; the Secret must contain key **`configurations.yml`**.
|
||||||
|
|
||||||
|
## Ingress (web UI)
|
||||||
|
|
||||||
|
Set `ingress.enabled`, `ingress.host`, and optional TLS in [`values/env-example.yaml`](values/env-example.yaml). Traffic goes to Service **`revproxy`**. On k3s, `ingress.className: traefik` matches the default controller. For cert-manager, set `ingress.certManager.clusterIssuer` and TLS secret name; DNS for `ingress.host` must resolve before ACME completes.
|
||||||
|
|
||||||
|
## Security notes for public repositories
|
||||||
|
|
||||||
|
- Never commit real passwords, tokens, or TLS private keys. Use **`REPLACE_*`** in tracked files and a **`*.local.yaml`** overlay (ignored at repo root) for secrets.
|
||||||
|
- If this repo ever contained real credentials, **rotate** them after sanitizing Git history or publishing a clean fork.
|
||||||
|
|
||||||
|
## kubectl / credentials
|
||||||
|
|
||||||
|
If `kubectl` reports *You must be logged in*, refresh your kubeconfig before applying manifests.
|
||||||
|
|
||||||
|
## Developer note (local render)
|
||||||
|
|
||||||
|
Running **`helm template` on Windows** against some paths can return empty `.Files.Get` content; the OneLab chart uses `fromYaml (.Files.AsConfig)` where needed. **Argo CD runs on Linux** and renders the same charts in-cluster.
|
||||||
|
|
||||||
|
## Not covered by this chart
|
||||||
|
|
||||||
|
- **Edge proxy** in front of the cluster — use **Ingress** + `revproxy` and optional cert-manager.
|
||||||
|
- **Non-Kubernetes** install paths — not included; use Kubernetes Secrets or external secret operators as needed.
|
||||||
38
gitops/argocd/application.yaml
Normal file
38
gitops/argocd/application.yaml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Syncs OneLab app + observability (Loki/Promtail/Grafana) into namespace onelab.
|
||||||
|
# Requires Argo CD 2.6+ (spec.sources). Ensure repoURL matches your remote.
|
||||||
|
#
|
||||||
|
# If you already had this Application with spec.source only, kubectl apply may not drop
|
||||||
|
# source — see gitops/README.md (Migrating spec.source → spec.sources) and jsonpatch-multisource.json.
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: onelab
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
sources:
|
||||||
|
- repoURL: https://github.com/YOUR_ORG/YOUR_REPO.git
|
||||||
|
targetRevision: main
|
||||||
|
path: gitops/charts/onelab
|
||||||
|
helm:
|
||||||
|
releaseName: onelab
|
||||||
|
valueFiles:
|
||||||
|
- ../../values/env-example.yaml
|
||||||
|
- repoURL: https://github.com/YOUR_ORG/YOUR_REPO.git
|
||||||
|
targetRevision: main
|
||||||
|
path: gitops/observability
|
||||||
|
helm:
|
||||||
|
releaseName: onelab-obs
|
||||||
|
valueFiles:
|
||||||
|
- ../../values/observability.yaml
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: onelab
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
23
gitops/argocd/jsonpatch-multisource.json
Normal file
23
gitops/argocd/jsonpatch-multisource.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[
|
||||||
|
{"op": "remove", "path": "/spec/source"},
|
||||||
|
{"op": "add", "path": "/spec/sources", "value": [
|
||||||
|
{
|
||||||
|
"repoURL": "https://github.com/YOUR_ORG/YOUR_REPO.git",
|
||||||
|
"targetRevision": "main",
|
||||||
|
"path": "gitops/charts/onelab",
|
||||||
|
"helm": {
|
||||||
|
"releaseName": "onelab",
|
||||||
|
"valueFiles": ["../../values/env-example.yaml"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"repoURL": "https://github.com/YOUR_ORG/YOUR_REPO.git",
|
||||||
|
"targetRevision": "main",
|
||||||
|
"path": "gitops/observability",
|
||||||
|
"helm": {
|
||||||
|
"releaseName": "onelab-obs",
|
||||||
|
"valueFiles": ["../../values/observability.yaml"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
]
|
||||||
6
gitops/charts/onelab/Chart.yaml
Normal file
6
gitops/charts/onelab/Chart.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: onelab
|
||||||
|
description: OneLab stack for Kubernetes (migrated from Docker Swarm compose)
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: "1.27.0"
|
||||||
5
gitops/charts/onelab/files/advanced.conf
Normal file
5
gitops/charts/onelab/files/advanced.conf
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
{rabbit, [
|
||||||
|
{tcp_listeners, []}
|
||||||
|
]}
|
||||||
|
].
|
||||||
133
gitops/charts/onelab/files/configurations.gotmpl
Normal file
133
gitops/charts/onelab/files/configurations.gotmpl
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
onelab:
|
||||||
|
domain: {{ .Values.onelab.domain | quote }}
|
||||||
|
logs:
|
||||||
|
path: "/logs"
|
||||||
|
level: info
|
||||||
|
assets:
|
||||||
|
purge: 1d
|
||||||
|
shared:
|
||||||
|
inputs:
|
||||||
|
path: "./data/shared/inputs"
|
||||||
|
archive_path: "./data/shared/archived"
|
||||||
|
security:
|
||||||
|
cors: '*'
|
||||||
|
auth:
|
||||||
|
token:
|
||||||
|
expiration: 5m
|
||||||
|
key: {{ .Values.onelab.secrets.authTokenKey | quote }}
|
||||||
|
password:
|
||||||
|
expiration: 90d
|
||||||
|
min_length: 8
|
||||||
|
prevent_reuse: 5
|
||||||
|
allow_list: []
|
||||||
|
block_list: []
|
||||||
|
authentifier: "email"
|
||||||
|
ratelimit:
|
||||||
|
ip:
|
||||||
|
max: 1000
|
||||||
|
duration: 1d
|
||||||
|
auth:
|
||||||
|
max: 5
|
||||||
|
duration: 5m
|
||||||
|
delay_after: 2
|
||||||
|
delay_ms: 1000
|
||||||
|
devices:
|
||||||
|
cors: '*'
|
||||||
|
monitoring:
|
||||||
|
token: {{ .Values.onelab.secrets.monitoringToken | quote }}
|
||||||
|
params:
|
||||||
|
session:
|
||||||
|
idle: 45m
|
||||||
|
remember_me: true
|
||||||
|
lab:
|
||||||
|
creation_policy: many
|
||||||
|
{{- if .Values.onelab.compliance.enabled }}
|
||||||
|
compliance:
|
||||||
|
require_electronic_signature: {{ .Values.onelab.compliance.requireElectronicSignature }}
|
||||||
|
execution_operator_restriction_policy: {{ .Values.onelab.compliance.executionOperatorRestrictionPolicy | quote }}
|
||||||
|
execution_admin_expert_restriction_policy: {{ .Values.onelab.compliance.executionAdminExpertRestrictionPolicy | quote }}
|
||||||
|
prevent_csv_import: {{ .Values.onelab.compliance.preventCsvImport }}
|
||||||
|
prevent_manual_metadata_edit: {{ .Values.onelab.compliance.preventManualMetadataEdit }}
|
||||||
|
device_restart: {{ .Values.onelab.compliance.deviceRestart }}
|
||||||
|
{{- end }}
|
||||||
|
signup: false
|
||||||
|
{{- if .Values.onelab.intercom.appid }}
|
||||||
|
intercom:
|
||||||
|
appid: {{ .Values.onelab.intercom.appid | quote }}
|
||||||
|
secret: {{ .Values.onelab.intercom.secret | quote }}
|
||||||
|
{{- end }}
|
||||||
|
mailer:
|
||||||
|
noreply: {{ .Values.onelab.mailer.noreply | quote }}
|
||||||
|
queue:
|
||||||
|
scheduling: 15
|
||||||
|
maxsize: 50
|
||||||
|
error:
|
||||||
|
maxtries: 3
|
||||||
|
timeout: 60
|
||||||
|
ldap:
|
||||||
|
enabled: {{ if or .Values.onelab.ldap.enabled .Values.features.ldapWorker }}true{{ else }}false{{ end }}
|
||||||
|
{{- if or .Values.onelab.ldap.enabled .Values.features.ldapWorker }}
|
||||||
|
{{- if .Values.onelab.ldap.timeout }}
|
||||||
|
timeout: {{ .Values.onelab.ldap.timeout | int }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.onelab.ldap.encryption }}
|
||||||
|
encryption: {{ .Values.onelab.ldap.encryption | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.onelab.ldap.policy }}
|
||||||
|
policy: {{ .Values.onelab.ldap.policy | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if kindIs "bool" .Values.onelab.ldap.verifyCertificates }}
|
||||||
|
verify_certificates: {{ .Values.onelab.ldap.verifyCertificates }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if or .Values.onelab.ldap.tlsCaPath .Values.onelab.ldap.tlsCertPath .Values.onelab.ldap.tlsKeyPath .Values.onelab.ldap.tlsCiphers .Values.onelab.ldap.tlsSslVersion }}
|
||||||
|
tls:
|
||||||
|
{{- if .Values.onelab.ldap.tlsCaPath }}
|
||||||
|
ca: {{ .Values.onelab.ldap.tlsCaPath | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.onelab.ldap.tlsCertPath }}
|
||||||
|
cert: {{ .Values.onelab.ldap.tlsCertPath | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.onelab.ldap.tlsKeyPath }}
|
||||||
|
key: {{ .Values.onelab.ldap.tlsKeyPath | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.onelab.ldap.tlsCiphers }}
|
||||||
|
ciphers: {{ .Values.onelab.ldap.tlsCiphers | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.onelab.ldap.tlsSslVersion }}
|
||||||
|
ssl_version: {{ .Values.onelab.ldap.tlsSslVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
host: db
|
||||||
|
database: postgres
|
||||||
|
username: postgres
|
||||||
|
password: {{ .Values.postgresql.auth.password | quote }}
|
||||||
|
schema: onelab
|
||||||
|
redis:
|
||||||
|
host: redis
|
||||||
|
port: "6379"
|
||||||
|
rabbit:
|
||||||
|
url: rabbitmq
|
||||||
|
port: 5671
|
||||||
|
token: {{ .Values.onelab.secrets.rabbitToken | quote }}
|
||||||
|
api:
|
||||||
|
replicas: {{ .Values.replicas.api }}
|
||||||
|
apidevice:
|
||||||
|
replicas: {{ .Values.replicas.apidevice }}
|
||||||
|
apirabbit:
|
||||||
|
replicas: {{ .Values.replicas.apirabbit }}
|
||||||
|
devices:
|
||||||
|
replicas: {{ .Values.replicas.devices }}
|
||||||
|
experiments:
|
||||||
|
replicas: {{ .Values.replicas.experiments }}
|
||||||
|
images:
|
||||||
|
replicas: {{ .Values.replicas.images }}
|
||||||
|
manual:
|
||||||
|
replicas: {{ .Values.replicas.manual }}
|
||||||
|
website:
|
||||||
|
ssr: {{ .Values.website.ssr }}
|
||||||
|
ws:
|
||||||
|
replicas: {{ .Values.replicas.ws }}
|
||||||
1
gitops/charts/onelab/files/enable_plugins
Normal file
1
gitops/charts/onelab/files/enable_plugins
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[rabbitmq_auth_backend_http, rabbitmq_auth_backend_cache, rabbitmq_management, rabbitmq_event_exchange].
|
||||||
98
gitops/charts/onelab/files/error-404.html
Normal file
98
gitops/charts/onelab/files/error-404.html
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>OneLab - Page Not Found</title>
|
||||||
|
<meta name="description" content="The page you are looking for does not exist or has been moved.">
|
||||||
|
<meta name="robots" content="noindex, nofollow">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: "Open Sans", sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
padding: 128px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
width: 360px;
|
||||||
|
max-width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 64px;
|
||||||
|
font-stretch: normal;
|
||||||
|
font-style: normal;
|
||||||
|
line-height: normal;
|
||||||
|
letter-spacing: normal;
|
||||||
|
text-align: center;
|
||||||
|
color: #4a4a4a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
color: #888;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub {
|
||||||
|
margin-top: 24px;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.47;
|
||||||
|
color: #4a4a4a;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.login-btn {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 32px;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 1000px;
|
||||||
|
background: #6cb644;
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, .15);
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.login-btn:hover,
|
||||||
|
a.login-btn:focus {
|
||||||
|
background: #3a8611;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="page" role="main" aria-labelledby="title">
|
||||||
|
<div class="content">
|
||||||
|
<div class="img">
|
||||||
|
<img
|
||||||
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALsAAAAvCAQAAAARbnO0AAAABGdBTUEAALGPC/xhBQAAC7VJREFUeNrtW3l0FdUdHgIkCAiyb1ZEkH1TREQRBVzqgrIVkCMFpbREPEKAIgoRxIWlilatuIRzEMUcN5YgtYYeEFRA+b47bxKeiX0algAqYFDZpDVMzyx3Zt7+XhJSqLn3n7yZO3f57u/+7vdboii/suLrIgYZlZ3O2Ait2EuvoVQVb+Eb0M2adWb6xxSWQqemXpDUZ3oKrxJzkMUc/pPZfJZ3a00rHxz1RjxtVD58bsEeSOMpq3/OTHyxF2A+vren5VSexiZxXeXCjkx79KJzC3bUxi9W/2JOohMazyOhkHvA/7toUgV7Av0/bva+x988gcb+VL4UHXK7FvuurII9gSv1Mt5eeH4i+rwasz3wHuZLYrjvSq0rBjCDH3kk/qjvsirYK24qizx6fGGgXsjba/mFA/0BXBQTrsZqT7bz100A2Mais9Y1v5lerSJh9zf0dUGf/GYxxl0ZCru/oeiRdwlqVxianTiw+Lz4APThaXsqJ8UdEe/nesh1Nmad58sx+Nqo3KAoHMzNLLHblFLDQ9EoFLsji/ud/r7Da2rP8sMeqIdMao54/ISPOVJP4TP2DJ8Ih31XLTGBW/GD/fsXbhXTEoArThFzzFUF0Dje7myTks5R0dpodQhnSTc5Q0yynxzi1giX8H70Ce1nVy0uczbZy5VeDDYwkoUdQ3gwwgwCKLD/eiUM9q9xOML9dUC9tTygF5+H/9gjxqa+am9nkitiXhTtZYdYHwZ7NPZzRL3Y20deA3wWtfV6L/DJwS4mGSZKzJmEwx6tZSkeKDvsu2rh33ZPs2LL+hNS4oIhiiBRWXbLU/Ke9sLO0/RhJefyBXzsebrKc3FXx4fO881iNDuhLQcjy5H+BWWDHQMkV4bOEm7gEj7O91DgPVWRYWcpduJtzOez2Iif3JWIEeXQ7DPNcQv8DWM3s9UDP4/b4c1yYuKWUNi5w6tQ1FtxSC5Mu9BZ8ANO68lB5+16y7JjKTomD3sgDcUOkFmo7+n3aqgxYf/Ey8tEE77lvPmhoFE5WFhb9AukxWu0x57Y3+J1l9fAmdYfQmAv0lNCjv1Yp+0YqfX4nf3kqbA5PGTPYVnysPN+RxgmhRHj6pIKhMPOVeEcSs4DOhedafL4sz3UIwns47+DDV8H9i/DLQFnOxfb4wyW3D+cqqG+rZsPSSiSgF2e1g8izvjNUNhj8XY9xbFS9sRxo1yv3umuA/041DWQeBWHuSyOvcQI9+yIHvid6eNyfDAL44JeU2pLZsSDXVH4j2AJxnPSyaB1CK/40t7QzsnBXni+1OuRLehw2MN5exCc10h5Vy+Na3IVWhYOlpoj7LLA5WKLxYmW5rtHzF8H8y4x8ZpmEQ3RWaHfHujNBHSWPM6jE4BdOhvetr9eE9f5YCz2xuRgR0fJunfVKr+0m0TZ5kQcGJVMt/EqW9HEUUxTvd8jU1H0GjjpPfPSrsFShe/ZLw6G6uewJdzngNMzAdhfsPt91/69JRHYpeWQKOyir/3d7ihzTlLa3btODI+KQwuHI40xFKQ8b/yT4duSQGOGobSkMcZ5JgbSSHxawThHhkfE8cP7QpeYFOw5dtu93Bq9ikHJwc5OFSvtgTRpnYgbYow6zwCeG1DTHGOGKeGfWBYu0o0eCFsBjTNZWr6lgMQInDDQEi2Vgkbmn6ZNF8uX4iGLi8oCO160235Yka6wQD3nUPepCGnH5c4qYwb9fK3YyWVCaOHr4uoKranWVa/u+p7QzTUE8xqwu7VZCh5zhspxm4eAfp0TNSlxDYFkYBfDHbPs0or0QDp27/sVIe2OJ/ZAZBddBRatDvY62jU3knUlRssTAR33RTgBCcBeeL5zoeSHO8kwJNgXkgSBnOoIzT0R3q6NytuzI2zSGKev58tByW8W98bygXp9gj86Ax5khssz9Wq8ius8l96rERVPArB7jRF8hm5B3v6JPMVSPFQW2IvPwzeO33OJ14OodZAkNqK061zHdkH9LHS8Tics+lcm0C0G9308V4sF4A085vVVEFiNlcjFt0E8Y1WwnzA52P2p/NTjDVnJybiJQznbdddyfCjsLOHD0apWxx7pt673hfv4FmdzKl/mFscpFd0nc4qbsRRTOJvZHheDyUnKVvx1HdtmXmKhqC7SZIlC7U5zXqi+Sw52RfE39wRMIngJPZdUZnyy6R5kZoQ7k8vqgUzEcIxpUkrxnZJ4oGCBV+aDpr0tUu5AsrCbLDei2cSD4l7vpiYHu6KIu5xwhbcWoTAq7HsjrZXHxIRyhjnGmsx9U1LRKtFEPIhN3uOJYmS5gY3ywm75M7CGRz0KbTOm5DWIwmQShF0xiPBCBlz1AYFxeo1YBNLfUMzxqhbswVMJXYVxKUr+b8oaI2kr+opB7B477UCvodUxaqRQmD/VehfZBepPRUfRX/Rnu8hSgZrW17FqJIqnXaj2xgCtjSTCgTSrrT/VNYiCn/jrsjtuE/0tr0lVOUeLnsJRYprWpgqJSi2WEuNRrUMVFpVWAvUcTjW/Co3KUzHVHUZ1XxUalVg41MwkXeNe4lWlkiQ+NK8u/l7Ni5vNpOgpvvZn9aXW7Zw74DgeH1K1J44nf4Q4kj7kcVE013IFHvNR3PF/CLthciTbr3opDovOqMkPwtMqfrWwq735OrZzlRiOExbs6MM3uA0r2Uux0i+mYBO34U31TiOygnfsBd6Mt7Gd2RzMtYalymViBJZjO9dxaAgUt2ON6U6YEO7JRm3Mx0Z8iBnGSeBU/tn+5losN0J1HMhsbsNyJ6ugJjOwHhvFo8aYYpo7FlbnN+N4gke4lmvZXVFwEZbyU67isLPv7h3FI5iu9lZv5bvQDdjFcO7GEFwk7sDXor+icDI3oI+vi/g9Bxt+bJw0Fzkd33Aie6l3YiN04xrhPpAj2UtM4jGjpdfXgyI0zm/GHer1YY6InXxG66B1xWvGdhY0wlcYZ8bnvzHyCMQEfCluEa05EntEDzPauR3rcZOxKXzZME/kNikKS7U2ojUy+YXoK/qiPjriW6SrF6vXYHt5MhvPQPGnsgS3eZWMnoJv0c9eyGB8oihcwuddD4gFu785jhvypFj/82TDrl5jw/xoqAsMT6GIO2Qan+f5LJknqaeg0IiI+rrgkLgFOw3XqVYHP0op53jmmJknuU4SU81w2L1KBuudjJ6W+CF51XgmFUxPlgTrdrZjKV/nCqPiHRzXq+U3Qy6K+boYa0zdgh23UXP6CId9eLB+xXL6OJc+w8OHtt44EnP4uTUWV3CXxUHEHdCx3FJ2OOG8zeE+ReFHMr1PGuPRYWcJ18mvcdwb0fqfF197nPDEuY/72ouW+EUMUq+W1ZItf3NxF1ZT86dasIu+KI4OO4ZAeKDphx+NWJC4CzvRllu9iobZfMkdy9fKorE8ys8NvY5uPMZr5VvjLOB9/jFIRS5z0wjDYN+HdLfvhP6fqPI8ZigwUmkUywn6s6HboXK2LbWtvTFBPQWHzdS5k6aOLZRSK3rEhl0M4m5ra8VonpJZkfa7sfjK8rbr1Yx7xLDzcEBrY8ipmVdVhHRHQFqYmSf/skLg/rpGDgJncou8JSzYMURm8vAVrLaFpq5FDs4m0ng592M1ZnAxAzxtwK725H7mMINLjKvVlL43kC5GI4uaXkNeqVpXFBB4FeuNTCqTc0SB3Z/KLcgV9zIDecjCV8HeOa7gPvEoZvEjrgqkaV35nbjCAAoqppsn5RDf4lQ8x91W8hL+imI+gUz6jXilvyH3IRfTuchIKzRhb8FjeBHp2oV5DSC4gzPxGAqkIJ1NwNfnRC7iVF8rPmxlDeQ14EQs4HgrToLaHIZM/oUTDVVR0EguIZDGgbyHA3k7d5kAZsi4CjoGh4H16hyG+cww5FNcFxrDEYM4VzyIAZb0y+xDXysxxxhPa4p0LODdbshFXMGZnCvDjOoFvJ+Leb/WFI9Y50D0EE9iljGKXkOMFk9y8lml18tXRGsriR/dUFjlb6s8vn8PdqIIe6HKfzOoKomW/wIUYeDeIwVFgwAAAABJRU5ErkJggg=="
|
||||||
|
alt="OneLab logo">
|
||||||
|
</div>
|
||||||
|
<div class="main" id="title">Page not found</div>
|
||||||
|
<div class="code">Error 404</div>
|
||||||
|
<div class="sub">The page you requested doesn’t exist, was removed, or is temporarily unavailable. You can return
|
||||||
|
to the application by logging in again.</div>
|
||||||
|
<a href="/login" class="login-btn" aria-label="Go to login page">Go to Home page</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
337
gitops/charts/onelab/files/nginx.conf.tpl
Normal file
337
gitops/charts/onelab/files/nginx.conf.tpl
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
|
||||||
|
worker_processes 4;
|
||||||
|
|
||||||
|
events { worker_connections 1024; }
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
|
||||||
|
client_max_body_size 2m;
|
||||||
|
|
||||||
|
# don't send the nginx version number in error pages and Server header
|
||||||
|
server_tokens off;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
|
||||||
|
upstream website {
|
||||||
|
server website:4000;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream main {
|
||||||
|
server main:80;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream api {
|
||||||
|
server api:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream api-device {
|
||||||
|
server api-device:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream api-rabbit {
|
||||||
|
server api-rabbit:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream designer {
|
||||||
|
server designer:80;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream runner {
|
||||||
|
server runner:80;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream static {
|
||||||
|
server static:80;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream websocket-worker {
|
||||||
|
server websocket-worker:3030;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restore the real client IP from the upstream reverse proxy
|
||||||
|
# Trust all RFC 1918 private ranges (covers any Docker network config)
|
||||||
|
set_real_ip_from 10.0.0.0/8;
|
||||||
|
set_real_ip_from 172.16.0.0/12;
|
||||||
|
set_real_ip_from 192.168.0.0/16;
|
||||||
|
real_ip_header X-Real-IP;
|
||||||
|
|
||||||
|
limit_req_zone $binary_remote_addr zone=auth:10m rate=1r/s;
|
||||||
|
limit_req_zone $binary_remote_addr zone=website:10m rate=5r/s;
|
||||||
|
limit_req_zone $binary_remote_addr zone=global:10m rate=10r/s;
|
||||||
|
|
||||||
|
# redirect all http traffic to https
|
||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
{{- if .Values.revproxy.ipv6Listen }}
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
{{- end }}
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 10240;
|
||||||
|
gzip_proxied expired no-cache no-store private auth;
|
||||||
|
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||||
|
gzip_disable "MSIE [1-6]\.";
|
||||||
|
|
||||||
|
root /data/;
|
||||||
|
|
||||||
|
location ^~ /lab/ {
|
||||||
|
rewrite ^/lab/(.*?) /app/lab/$1 last;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /assets/ {
|
||||||
|
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
|
||||||
|
expires 1M;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
|
||||||
|
try_files $uri $uri/ /error-404.html =404;
|
||||||
|
}
|
||||||
|
expires -1;
|
||||||
|
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
|
||||||
|
|
||||||
|
try_files $uri $uri/ /error-404.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /static/ {
|
||||||
|
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
|
||||||
|
expires 1M;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
|
||||||
|
proxy_pass http://static;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
expires -1;
|
||||||
|
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
|
||||||
|
|
||||||
|
proxy_pass http://static;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /sitemap.xml {
|
||||||
|
limit_req zone=global burst=10 nodelay;
|
||||||
|
|
||||||
|
proxy_pass http://api;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /robots.txt {
|
||||||
|
limit_req zone=global burst=10 nodelay;
|
||||||
|
|
||||||
|
proxy_pass http://api;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /api/ {
|
||||||
|
limit_req zone=global burst=10 nodelay;
|
||||||
|
|
||||||
|
proxy_pass http://api;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /api/v1/auth/ {
|
||||||
|
# apply rate limiting
|
||||||
|
limit_req zone=auth burst=5 nodelay;
|
||||||
|
|
||||||
|
proxy_pass http://api;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /api/v1/firmwares {
|
||||||
|
limit_req zone=global burst=10 nodelay;
|
||||||
|
|
||||||
|
client_max_body_size 600M;
|
||||||
|
|
||||||
|
proxy_pass http://api;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /api/v1/rmq/ {
|
||||||
|
proxy_pass http://api-rabbit;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /device-api/ {
|
||||||
|
limit_req zone=global burst=10 nodelay;
|
||||||
|
client_max_body_size 600m;
|
||||||
|
|
||||||
|
proxy_pass http://api-device;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /app/designer/ {
|
||||||
|
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
|
||||||
|
expires 1M;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
|
||||||
|
proxy_pass http://designer;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
expires -1;
|
||||||
|
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
|
||||||
|
|
||||||
|
proxy_pass http://designer;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /app/runner/ {
|
||||||
|
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
|
||||||
|
expires 1M;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
|
||||||
|
proxy_pass http://runner;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
expires -1;
|
||||||
|
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
|
||||||
|
|
||||||
|
proxy_pass http://runner;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /ws/ {
|
||||||
|
proxy_pass http://websocket-worker;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /app/ {
|
||||||
|
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
|
||||||
|
expires 1M;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
|
||||||
|
proxy_pass http://main;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
expires -1;
|
||||||
|
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
|
||||||
|
|
||||||
|
proxy_pass http://main;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static assets for website (including /media/ subdirectory)
|
||||||
|
location ~* ^/.+\.(?:css|js|woff|woff2|ttf|eot|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
|
||||||
|
expires 1M;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
|
||||||
|
proxy_pass http://website;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Website SSR routes (rate limited)
|
||||||
|
location ~ ^/(library(/[^/]+)?|login(/(reset|change))?|signup)?$ {
|
||||||
|
limit_req zone=website burst=10 nodelay;
|
||||||
|
|
||||||
|
expires -1;
|
||||||
|
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
|
||||||
|
|
||||||
|
proxy_pass http://website;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Cookie $http_cookie;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Catch-all for junk requests
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /error-404.html =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
gitops/charts/onelab/files/rabbit-definitions.json
Normal file
20
gitops/charts/onelab/files/rabbit-definitions.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"rabbit_version": "3.6.5",
|
||||||
|
"users": [
|
||||||
|
],
|
||||||
|
"vhosts": [
|
||||||
|
{
|
||||||
|
"name": "devices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "internal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
],
|
||||||
|
"parameters": [],
|
||||||
|
"policies": [],
|
||||||
|
"queues": [],
|
||||||
|
"exchanges": [],
|
||||||
|
"bindings": []
|
||||||
|
}
|
||||||
54
gitops/charts/onelab/files/rabbit.conf
Normal file
54
gitops/charts/onelab/files/rabbit.conf
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Auth server config
|
||||||
|
|
||||||
|
auth_backends.1 = cache
|
||||||
|
|
||||||
|
auth_cache.cached_backend = http
|
||||||
|
auth_cache.cache_ttl = 5000
|
||||||
|
|
||||||
|
auth_http.user_path = http://revproxy/api/v1/rmq/user
|
||||||
|
auth_http.vhost_path = http://revproxy/api/v1/rmq/vhost
|
||||||
|
auth_http.resource_path = http://revproxy/api/v1/rmq/resource
|
||||||
|
auth_http.topic_path = http://revproxy/api/v1/rmq/topic
|
||||||
|
|
||||||
|
listeners.ssl.default = 5671
|
||||||
|
|
||||||
|
# generated with "cat server.crt server.key > server.pem"
|
||||||
|
# fullchain
|
||||||
|
ssl_options.cacertfile = /etc/rabbitmq/ssl/rabbit.fullchain.pem
|
||||||
|
|
||||||
|
ssl_options.certfile = /etc/rabbitmq/ssl/rabbit.crt
|
||||||
|
ssl_options.keyfile = /etc/rabbitmq/ssl/rabbit.key
|
||||||
|
|
||||||
|
# not very secure
|
||||||
|
ssl_options.verify = verify_peer
|
||||||
|
ssl_options.fail_if_no_peer_cert = false
|
||||||
|
|
||||||
|
# for TLS version and cipher
|
||||||
|
ssl_options.versions.1 = tlsv1.2
|
||||||
|
|
||||||
|
# these MUST be disabled if TLSv1.3 is used
|
||||||
|
ssl_options.honor_cipher_order = true
|
||||||
|
ssl_options.honor_ecc_order = true
|
||||||
|
|
||||||
|
# These are highly recommended for TLSv1.2 but cannot be used
|
||||||
|
# with TLSv1.3. If TLSv1.3 is enabled, these lines MUST be removed.
|
||||||
|
ssl_options.client_renegotiation = false
|
||||||
|
ssl_options.secure_renegotiate = true
|
||||||
|
|
||||||
|
ssl_options.ciphers.1 = ECDHE-ECDSA-AES256-GCM-SHA384
|
||||||
|
ssl_options.ciphers.2 = ECDHE-RSA-AES256-GCM-SHA384
|
||||||
|
ssl_options.ciphers.3 = ECDH-ECDSA-AES256-GCM-SHA384
|
||||||
|
ssl_options.ciphers.4 = ECDH-RSA-AES256-GCM-SHA384
|
||||||
|
ssl_options.ciphers.5 = DHE-RSA-AES256-GCM-SHA384
|
||||||
|
ssl_options.ciphers.6 = DHE-DSS-AES256-GCM-SHA384
|
||||||
|
ssl_options.ciphers.7 = ECDHE-ECDSA-AES128-GCM-SHA256
|
||||||
|
ssl_options.ciphers.8 = ECDHE-RSA-AES128-GCM-SHA256
|
||||||
|
ssl_options.ciphers.9 = ECDH-ECDSA-AES128-GCM-SHA256
|
||||||
|
ssl_options.ciphers.10 = ECDH-RSA-AES128-GCM-SHA256
|
||||||
|
ssl_options.ciphers.11 = DHE-RSA-AES128-GCM-SHA256
|
||||||
|
ssl_options.ciphers.12 = DHE-DSS-AES128-GCM-SHA256
|
||||||
|
|
||||||
|
management.load_definitions = /opt/definitions.json
|
||||||
|
|
||||||
|
# For connection events
|
||||||
|
event_exchange.vhost = devices
|
||||||
37
gitops/charts/onelab/templates/_helpers.tpl
Normal file
37
gitops/charts/onelab/templates/_helpers.tpl
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{{- define "onelab.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "onelab.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride }}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||||
|
{{- if contains $name .Release.Name }}
|
||||||
|
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "onelab.labels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | quote }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "onelab.dockerconfigjson" -}}
|
||||||
|
{{- $server := .Values.registry.server -}}
|
||||||
|
{{- $user := .Values.registry.username -}}
|
||||||
|
{{- $pass := .Values.registry.password -}}
|
||||||
|
{{- $auth := printf "%s:%s" $user $pass | b64enc -}}
|
||||||
|
{{- $entry := dict "username" $user "password" $pass "auth" $auth -}}
|
||||||
|
{{- dict "auths" (dict $server $entry) | toJson -}}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "onelab.configurationSecretName" -}}
|
||||||
|
{{- .Values.configuration.existingSecretName | default "onelab-configurations" }}
|
||||||
|
{{- end }}
|
||||||
18
gitops/charts/onelab/templates/configmap-rabbit.yaml
Normal file
18
gitops/charts/onelab/templates/configmap-rabbit.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{{- $cfg := fromYaml (.Files.AsConfig) }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: onelab-rabbit-config
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.statefulDeps | quote }}
|
||||||
|
data:
|
||||||
|
rabbit.conf: |
|
||||||
|
{{ index $cfg "rabbit.conf" | nindent 4 }}
|
||||||
|
advanced.conf: |
|
||||||
|
{{ index $cfg "advanced.conf" | nindent 4 }}
|
||||||
|
enable_plugins: |
|
||||||
|
{{ index $cfg "enable_plugins" | nindent 4 }}
|
||||||
|
definitions.json: |
|
||||||
|
{{ index $cfg "rabbit-definitions.json" | nindent 4 }}
|
||||||
14
gitops/charts/onelab/templates/configmap-revproxy.yaml
Normal file
14
gitops/charts/onelab/templates/configmap-revproxy.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{{- $cfg := fromYaml (.Files.AsConfig) }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: onelab-revproxy
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.apps | quote }}
|
||||||
|
data:
|
||||||
|
nginx.conf: |
|
||||||
|
{{ tpl (index $cfg "nginx.conf.tpl") . | nindent 4 }}
|
||||||
|
error-404.html: |
|
||||||
|
{{ index $cfg "error-404.html" | nindent 4 }}
|
||||||
111
gitops/charts/onelab/templates/deployment-optional-workers.yaml
Normal file
111
gitops/charts/onelab/templates/deployment-optional-workers.yaml
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
{{- $root := . }}
|
||||||
|
{{- if or .Values.onelab.ldap.enabled .Values.features.ldapWorker }}
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: ldap-worker
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: ldap-worker
|
||||||
|
{{- include "onelab.labels" $root | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ $root.Values.syncWaves.apps | quote }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ $root.Values.replicas.ldap | default 1 }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/component: ldap-worker
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" $root }}
|
||||||
|
app.kubernetes.io/instance: {{ $root.Release.Name }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: ldap-worker
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" $root }}
|
||||||
|
app.kubernetes.io/instance: {{ $root.Release.Name }}
|
||||||
|
spec:
|
||||||
|
{{- with $root.Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: ldap-worker
|
||||||
|
image: {{ printf "%s/%s:%s" $root.Values.images.registry "onelab-ldap-worker" $root.Values.images.tag | quote }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: configurations
|
||||||
|
mountPath: /conf/configurations.yml
|
||||||
|
subPath: configurations.yml
|
||||||
|
readOnly: true
|
||||||
|
{{- if eq $root.Values.persistence.mode "hostPath" }}
|
||||||
|
- name: logs
|
||||||
|
mountPath: /logs
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: configurations
|
||||||
|
secret:
|
||||||
|
secretName: {{ include "onelab.configurationSecretName" $root }}
|
||||||
|
{{- if eq $root.Values.persistence.mode "hostPath" }}
|
||||||
|
- name: logs
|
||||||
|
hostPath:
|
||||||
|
path: {{ $root.Values.persistence.hostPath.logs }}
|
||||||
|
type: DirectoryOrCreate
|
||||||
|
{{- else }}
|
||||||
|
- name: logs
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.features.mailerWorker }}
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: mailer-worker
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: mailer-worker
|
||||||
|
{{- include "onelab.labels" $root | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ $root.Values.syncWaves.apps | quote }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ $root.Values.replicas.mailer | default 1 }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/component: mailer-worker
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" $root }}
|
||||||
|
app.kubernetes.io/instance: {{ $root.Release.Name }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: mailer-worker
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" $root }}
|
||||||
|
app.kubernetes.io/instance: {{ $root.Release.Name }}
|
||||||
|
spec:
|
||||||
|
{{- with $root.Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: mailer-worker
|
||||||
|
image: {{ printf "%s/%s:%s" $root.Values.images.registry "onelab-mailer-worker" $root.Values.images.tag | quote }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: configurations
|
||||||
|
mountPath: /conf/configurations.yml
|
||||||
|
subPath: configurations.yml
|
||||||
|
readOnly: true
|
||||||
|
{{- if eq $root.Values.persistence.mode "hostPath" }}
|
||||||
|
- name: logs
|
||||||
|
mountPath: /logs
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: configurations
|
||||||
|
secret:
|
||||||
|
secretName: {{ include "onelab.configurationSecretName" $root }}
|
||||||
|
{{- if eq $root.Values.persistence.mode "hostPath" }}
|
||||||
|
- name: logs
|
||||||
|
hostPath:
|
||||||
|
path: {{ $root.Values.persistence.hostPath.logs }}
|
||||||
|
type: DirectoryOrCreate
|
||||||
|
{{- else }}
|
||||||
|
- name: logs
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
53
gitops/charts/onelab/templates/deployment-redis.yaml
Normal file
53
gitops/charts/onelab/templates/deployment-redis.yaml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: redis
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.statefulDeps | quote }}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/component: redis
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: redis
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: redis
|
||||||
|
image: {{ printf "%s/%s:%s" .Values.images.registry .Values.images.redis .Values.images.redisTag | quote }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 6379
|
||||||
|
name: redis
|
||||||
|
{{- with .Values.redis.resources }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: redis
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 6379
|
||||||
|
targetPort: redis
|
||||||
|
name: redis
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/component: redis
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
73
gitops/charts/onelab/templates/deployment-revproxy.yaml
Normal file
73
gitops/charts/onelab/templates/deployment-revproxy.yaml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: revproxy
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.apps | quote }}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/component: revproxy
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: revproxy
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: {{ printf "%s/%s:%s" .Values.images.registry .Values.images.nginx .Values.images.nginxTag | quote }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
name: http
|
||||||
|
volumeMounts:
|
||||||
|
- name: nginx
|
||||||
|
mountPath: /etc/nginx/nginx.conf
|
||||||
|
subPath: nginx.conf
|
||||||
|
- name: nginx
|
||||||
|
mountPath: /data/error-404.html
|
||||||
|
subPath: error-404.html
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
volumes:
|
||||||
|
- name: nginx
|
||||||
|
configMap:
|
||||||
|
name: onelab-revproxy
|
||||||
|
- name: data
|
||||||
|
{{- if eq .Values.persistence.mode "hostPath" }}
|
||||||
|
hostPath:
|
||||||
|
path: {{ .Values.persistence.hostPath.data }}
|
||||||
|
type: DirectoryOrCreate
|
||||||
|
{{- else }}
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: revproxy
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.revproxy.serviceType }}
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: http
|
||||||
|
name: http
|
||||||
|
{{- if and (eq .Values.revproxy.serviceType "NodePort") .Values.revproxy.nodePort }}
|
||||||
|
nodePort: {{ .Values.revproxy.nodePort }}
|
||||||
|
{{- end }}
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/component: revproxy
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
37
gitops/charts/onelab/templates/ingress.yaml
Normal file
37
gitops/charts/onelab/templates/ingress.yaml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{{- if .Values.ingress.enabled }}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: onelab-revproxy
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.apps | quote }}
|
||||||
|
{{- if .Values.ingress.certManager.clusterIssuer }}
|
||||||
|
cert-manager.io/cluster-issuer: {{ .Values.ingress.certManager.clusterIssuer | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .Values.ingress.host | quote }}
|
||||||
|
secretName: {{ if .Values.ingress.tlsSecretName }}{{ .Values.ingress.tlsSecretName | quote }}{{ else }}{{ printf "%s-tls" .Release.Name | quote }}{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
- host: {{ .Values.ingress.host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: {{ .Values.ingress.path | quote }}
|
||||||
|
pathType: {{ .Values.ingress.pathType | quote }}
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: revproxy
|
||||||
|
port:
|
||||||
|
name: http
|
||||||
|
{{- end }}
|
||||||
15
gitops/charts/onelab/templates/secret-configurations.yaml
Normal file
15
gitops/charts/onelab/templates/secret-configurations.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{{- if not .Values.configuration.existingSecretName }}
|
||||||
|
{{- $cfg := fromYaml (.Files.AsConfig) }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: onelab-configurations
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.statefulDeps | quote }}
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
configurations.yml: |
|
||||||
|
{{- tpl (index $cfg "configurations.gotmpl") . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
11
gitops/charts/onelab/templates/secret-postgres.yaml
Normal file
11
gitops/charts/onelab/templates/secret-postgres.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: onelab-postgres
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.postgres | quote }}
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
postgres-password: {{ .Values.postgresql.auth.password | quote }}
|
||||||
18
gitops/charts/onelab/templates/secret-rabbit-tls.yaml
Normal file
18
gitops/charts/onelab/templates/secret-rabbit-tls.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{{- if .Values.rabbitmq.tls.embed }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.rabbitmq.tls.secretName }}
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.statefulDeps | quote }}
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
rabbit.crt: |
|
||||||
|
{{ .Values.rabbitmq.tls.crt | nindent 4 }}
|
||||||
|
rabbit.key: |
|
||||||
|
{{ .Values.rabbitmq.tls.key | nindent 4 }}
|
||||||
|
rabbit.fullchain.pem: |
|
||||||
|
{{ .Values.rabbitmq.tls.fullchain | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
13
gitops/charts/onelab/templates/secret-registry.yaml
Normal file
13
gitops/charts/onelab/templates/secret-registry.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{{- if .Values.registry.createPullSecret }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.registry.pullSecretName }}
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.registry | quote }}
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
|
data:
|
||||||
|
.dockerconfigjson: {{ include "onelab.dockerconfigjson" . | b64enc }}
|
||||||
|
{{- end }}
|
||||||
18
gitops/charts/onelab/templates/service-db.yaml
Normal file
18
gitops/charts/onelab/templates/service-db.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: db
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.postgres | quote }}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 5432
|
||||||
|
targetPort: postgres
|
||||||
|
name: postgres
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/component: postgres
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
16
gitops/charts/onelab/templates/service-rabbitmq.yaml
Normal file
16
gitops/charts/onelab/templates/service-rabbitmq.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: rabbitmq
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 5671
|
||||||
|
targetPort: amqps
|
||||||
|
name: amqps
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/component: rabbitmq
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
67
gitops/charts/onelab/templates/statefulset-postgres.yaml
Normal file
67
gitops/charts/onelab/templates/statefulset-postgres.yaml
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: db
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.postgres | quote }}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
serviceName: db
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/component: postgres
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: postgres
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
annotations:
|
||||||
|
{{- if .Values.registry.createPullSecret }}
|
||||||
|
checksum/docker-registry: {{ include "onelab.dockerconfigjson" . | sha256sum | quote }}
|
||||||
|
{{- else if not (empty .Values.imagePullSecrets) }}
|
||||||
|
checksum/image-pull-secrets: {{ .Values.imagePullSecrets | toJson | sha256sum | quote }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: {{ printf "%s/%s:%s" .Values.images.registry .Values.images.postgres .Values.images.postgresTag | quote }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
name: postgres
|
||||||
|
env:
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
value: postgres
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
value: postgres
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: onelab-postgres
|
||||||
|
key: postgres-password
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /var/lib/postgresql/data
|
||||||
|
{{- with .Values.postgresql.resources }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: data
|
||||||
|
spec:
|
||||||
|
accessModes: ["ReadWriteOnce"]
|
||||||
|
{{- if .Values.persistence.storageClass }}
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.postgres.size | quote }}
|
||||||
86
gitops/charts/onelab/templates/statefulset-rabbitmq.yaml
Normal file
86
gitops/charts/onelab/templates/statefulset-rabbitmq.yaml
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: rabbitmq
|
||||||
|
labels:
|
||||||
|
{{- include "onelab.labels" . | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ .Values.syncWaves.statefulDeps | quote }}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
serviceName: rabbitmq
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/component: rabbitmq
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: rabbitmq
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
annotations:
|
||||||
|
{{- if .Values.registry.createPullSecret }}
|
||||||
|
checksum/docker-registry: {{ include "onelab.dockerconfigjson" . | sha256sum | quote }}
|
||||||
|
{{- else if not (empty .Values.imagePullSecrets) }}
|
||||||
|
checksum/image-pull-secrets: {{ .Values.imagePullSecrets | toJson | sha256sum | quote }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
hostname: onelab
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: rabbitmq
|
||||||
|
image: {{ printf "%s/%s:%s" .Values.images.registry .Values.images.rabbitmq .Values.images.rabbitmqTag | quote }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 5671
|
||||||
|
name: amqps
|
||||||
|
volumeMounts:
|
||||||
|
- name: rabbit-data
|
||||||
|
mountPath: /var/lib/rabbitmq/mnesia
|
||||||
|
- name: rabbit-config
|
||||||
|
mountPath: /etc/rabbitmq/rabbitmq.conf
|
||||||
|
subPath: rabbit.conf
|
||||||
|
- name: rabbit-config
|
||||||
|
mountPath: /etc/rabbitmq/advanced.conf
|
||||||
|
subPath: advanced.conf
|
||||||
|
- name: rabbit-config
|
||||||
|
mountPath: /etc/rabbitmq/enabled_plugins
|
||||||
|
subPath: enable_plugins
|
||||||
|
- name: rabbit-config
|
||||||
|
mountPath: /opt/definitions.json
|
||||||
|
subPath: definitions.json
|
||||||
|
- name: rabbit-tls
|
||||||
|
mountPath: /etc/rabbitmq/ssl/rabbit.crt
|
||||||
|
subPath: rabbit.crt
|
||||||
|
- name: rabbit-tls
|
||||||
|
mountPath: /etc/rabbitmq/ssl/rabbit.key
|
||||||
|
subPath: rabbit.key
|
||||||
|
- name: rabbit-tls
|
||||||
|
mountPath: /etc/rabbitmq/ssl/rabbit.fullchain.pem
|
||||||
|
subPath: rabbit.fullchain.pem
|
||||||
|
{{- with .Values.rabbitmq.resources }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: rabbit-config
|
||||||
|
configMap:
|
||||||
|
name: onelab-rabbit-config
|
||||||
|
- name: rabbit-tls
|
||||||
|
secret:
|
||||||
|
secretName: {{ .Values.rabbitmq.tls.secretName }}
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: rabbit-data
|
||||||
|
spec:
|
||||||
|
accessModes: ["ReadWriteOnce"]
|
||||||
|
{{- if .Values.persistence.storageClass }}
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.rabbitmq.size | quote }}
|
||||||
116
gitops/charts/onelab/templates/workloads.yaml
Normal file
116
gitops/charts/onelab/templates/workloads.yaml
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
{{- $root := . }}
|
||||||
|
{{- range .Values.workloads }}
|
||||||
|
{{- $n := .replicas | default 1 | int }}
|
||||||
|
{{- if and .replicaKey (hasKey $root.Values.replicas .replicaKey) }}
|
||||||
|
{{- $n = index $root.Values.replicas .replicaKey | int }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $vols := or .config (not (empty .mounts)) }}
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ .name }}
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: {{ .name }}
|
||||||
|
{{- include "onelab.labels" $root | nindent 4 }}
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: {{ $root.Values.syncWaves.apps | quote }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ $n }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/component: {{ .name }}
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" $root }}
|
||||||
|
app.kubernetes.io/instance: {{ $root.Release.Name }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: {{ .name }}
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" $root }}
|
||||||
|
app.kubernetes.io/instance: {{ $root.Release.Name }}
|
||||||
|
spec:
|
||||||
|
{{- with $root.Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: {{ .name }}
|
||||||
|
image: {{ printf "%s/%s:%s" $root.Values.images.registry .image $root.Values.images.tag | quote }}
|
||||||
|
{{- if .port }}
|
||||||
|
ports:
|
||||||
|
- containerPort: {{ .port }}
|
||||||
|
name: http
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .website (not $root.Values.website.ssr) }}
|
||||||
|
env:
|
||||||
|
- name: RENDERING_MODE
|
||||||
|
value: "no-ssr"
|
||||||
|
{{- end }}
|
||||||
|
{{- if $vols }}
|
||||||
|
volumeMounts:
|
||||||
|
{{- if .config }}
|
||||||
|
- name: configurations
|
||||||
|
mountPath: /conf/configurations.yml
|
||||||
|
subPath: configurations.yml
|
||||||
|
readOnly: true
|
||||||
|
{{- end }}
|
||||||
|
{{- if has "logs" .mounts }}
|
||||||
|
- name: logs
|
||||||
|
mountPath: /logs
|
||||||
|
{{- end }}
|
||||||
|
{{- if has "data" .mounts }}
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
{{- end }}
|
||||||
|
{{- if has "shared" .mounts }}
|
||||||
|
- name: data
|
||||||
|
mountPath: /shared-inputs
|
||||||
|
subPath: shared/inputs
|
||||||
|
- name: data
|
||||||
|
mountPath: /shared-archived
|
||||||
|
subPath: shared/archived
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $vols }}
|
||||||
|
volumes:
|
||||||
|
{{- if .config }}
|
||||||
|
- name: configurations
|
||||||
|
secret:
|
||||||
|
secretName: {{ include "onelab.configurationSecretName" $root }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $root.Values.persistence.mode "hostPath" }}
|
||||||
|
{{- if has "logs" .mounts }}
|
||||||
|
- name: logs
|
||||||
|
hostPath:
|
||||||
|
path: {{ $root.Values.persistence.hostPath.logs }}
|
||||||
|
type: DirectoryOrCreate
|
||||||
|
{{- end }}
|
||||||
|
{{- if or (has "data" .mounts) (has "shared" .mounts) }}
|
||||||
|
- name: data
|
||||||
|
hostPath:
|
||||||
|
path: {{ $root.Values.persistence.hostPath.data }}
|
||||||
|
type: DirectoryOrCreate
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .port (gt (int .port) 0) }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ .name }}
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: {{ .name }}
|
||||||
|
{{- include "onelab.labels" $root | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: {{ .port }}
|
||||||
|
targetPort: http
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/component: {{ .name }}
|
||||||
|
app.kubernetes.io/name: {{ include "onelab.name" $root }}
|
||||||
|
app.kubernetes.io/instance: {{ $root.Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
236
gitops/charts/onelab/values.yaml
Normal file
236
gitops/charts/onelab/values.yaml
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
# Default values for onelab — override per environment (see gitops/values/).
|
||||||
|
|
||||||
|
nameOverride: ""
|
||||||
|
fullnameOverride: ""
|
||||||
|
|
||||||
|
# If non-empty, workloads mount this Secret instead of chart-generated onelab-configurations.
|
||||||
|
# Secret must contain key `configurations.yml`. Chart will NOT create onelab-configurations.
|
||||||
|
configuration:
|
||||||
|
existingSecretName: ""
|
||||||
|
|
||||||
|
images:
|
||||||
|
registry: hub.andrewalliance.com/releases
|
||||||
|
tag: "1.27.0"
|
||||||
|
nginx: nginx
|
||||||
|
nginxTag: "1.29.5-alpine"
|
||||||
|
postgres: postgres
|
||||||
|
postgresTag: "17.8"
|
||||||
|
redis: redis
|
||||||
|
redisTag: "7.4.7-alpine"
|
||||||
|
rabbitmq: rabbitmq
|
||||||
|
rabbitmqTag: "3.13.7"
|
||||||
|
|
||||||
|
imagePullSecrets: []
|
||||||
|
# - name: hub-andrewalliance
|
||||||
|
|
||||||
|
# Override registry credentials in gitops/values/ (see gitops/values/secrets.example.yaml).
|
||||||
|
registry:
|
||||||
|
createPullSecret: false
|
||||||
|
pullSecretName: hub-andrewalliance
|
||||||
|
server: hub.andrewalliance.com
|
||||||
|
username: public
|
||||||
|
password: "REPLACE_REGISTRY_PASSWORD"
|
||||||
|
|
||||||
|
# hostPath: matches typical single-node Swarm-style install (shared /data and /logs).
|
||||||
|
# Use persistence.mode: pvc + a ReadWriteMany class for multi-node shared storage.
|
||||||
|
persistence:
|
||||||
|
mode: hostPath
|
||||||
|
storageClass: ""
|
||||||
|
hostPath:
|
||||||
|
data: /opt/onelab/data
|
||||||
|
logs: /opt/onelab/logs
|
||||||
|
postgres:
|
||||||
|
size: 20Gi
|
||||||
|
rabbitmq:
|
||||||
|
size: 5Gi
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
auth:
|
||||||
|
password: "DBPasswordPlaceholder"
|
||||||
|
resources: {}
|
||||||
|
|
||||||
|
redis:
|
||||||
|
resources: {}
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
resources: {}
|
||||||
|
# TLS: create Secret `onelab-rabbit-tls` in the release namespace (see README), or set embed: true.
|
||||||
|
tls:
|
||||||
|
secretName: onelab-rabbit-tls
|
||||||
|
embed: false
|
||||||
|
crt: ""
|
||||||
|
key: ""
|
||||||
|
fullchain: ""
|
||||||
|
|
||||||
|
syncWaves:
|
||||||
|
registry: "-5"
|
||||||
|
postgres: "-3"
|
||||||
|
statefulDeps: "-2"
|
||||||
|
apps: "0"
|
||||||
|
|
||||||
|
onelab:
|
||||||
|
domain: "https://localhost"
|
||||||
|
mailer:
|
||||||
|
noreply: "no-reply@example.com"
|
||||||
|
secrets:
|
||||||
|
authTokenKey: "TokenAuthPlaceholder"
|
||||||
|
monitoringToken: "TokenMonitoringPlaceholder"
|
||||||
|
rabbitToken: "TokenRabbitPlaceholder"
|
||||||
|
# Mirrors legacy OneLab configurations.yml params.compliance (templated from charts/onelab/files/configurations.gotmpl).
|
||||||
|
compliance:
|
||||||
|
enabled: false
|
||||||
|
requireElectronicSignature: true
|
||||||
|
executionOperatorRestrictionPolicy: "reviewed"
|
||||||
|
executionAdminExpertRestrictionPolicy: "reviewed"
|
||||||
|
preventCsvImport: true
|
||||||
|
preventManualMetadataEdit: true
|
||||||
|
deviceRestart: true
|
||||||
|
# Set enabled: true to turn on LDAP in configurations.yml and deploy ldap-worker (or use features.ldapWorker).
|
||||||
|
ldap:
|
||||||
|
enabled: false
|
||||||
|
timeout: ""
|
||||||
|
encryption: ""
|
||||||
|
policy: ""
|
||||||
|
tlsCaPath: ""
|
||||||
|
tlsCertPath: ""
|
||||||
|
tlsKeyPath: ""
|
||||||
|
tlsCiphers: ""
|
||||||
|
tlsSslVersion: ""
|
||||||
|
intercom:
|
||||||
|
appid: "REPLACE_INTERCOM_APP_ID"
|
||||||
|
secret: "REPLACE_INTERCOM_SECRET"
|
||||||
|
|
||||||
|
features:
|
||||||
|
# Deprecated for LDAP: prefer onelab.ldap.enabled (either enables ldap-worker + ldap.enabled in config).
|
||||||
|
ldapWorker: false
|
||||||
|
mailerWorker: false
|
||||||
|
|
||||||
|
website:
|
||||||
|
ssr: true
|
||||||
|
|
||||||
|
revproxy:
|
||||||
|
serviceType: NodePort
|
||||||
|
nodePort: 30080
|
||||||
|
ipv6Listen: true
|
||||||
|
|
||||||
|
# HTTP routing to internal nginx (revproxy). On k3s, set className: traefik (default controller).
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
className: ""
|
||||||
|
host: onelab.local
|
||||||
|
path: /
|
||||||
|
pathType: Prefix
|
||||||
|
annotations: {}
|
||||||
|
tls: false
|
||||||
|
tlsSecretName: ""
|
||||||
|
certManager:
|
||||||
|
# When set, adds cert-manager.io/cluster-issuer annotation (TLS secret is created automatically).
|
||||||
|
clusterIssuer: ""
|
||||||
|
|
||||||
|
# Replica counts (api.apidevice etc. override defaults in templates/workloads.yaml via this map)
|
||||||
|
replicas:
|
||||||
|
api: 2
|
||||||
|
apidevice: 1
|
||||||
|
apirabbit: 1
|
||||||
|
devices: 1
|
||||||
|
experiments: 1
|
||||||
|
images: 1
|
||||||
|
manual: 1
|
||||||
|
ws: 1
|
||||||
|
ldap: 1
|
||||||
|
mailer: 1
|
||||||
|
|
||||||
|
resources: {}
|
||||||
|
|
||||||
|
workloads:
|
||||||
|
- name: supervisor
|
||||||
|
image: onelab-supervisor-worker
|
||||||
|
replicas: 1
|
||||||
|
port: 0
|
||||||
|
config: true
|
||||||
|
mounts: [logs, data]
|
||||||
|
- name: file-worker
|
||||||
|
image: onelab-file-worker
|
||||||
|
replicas: 1
|
||||||
|
port: 0
|
||||||
|
config: true
|
||||||
|
mounts: [logs, data, shared]
|
||||||
|
- name: api
|
||||||
|
image: onelab-api
|
||||||
|
replicaKey: api
|
||||||
|
port: 3000
|
||||||
|
config: true
|
||||||
|
mounts: [logs, data]
|
||||||
|
- name: api-device
|
||||||
|
image: onelab-api-device
|
||||||
|
replicaKey: apidevice
|
||||||
|
port: 3000
|
||||||
|
config: true
|
||||||
|
mounts: [logs, data]
|
||||||
|
- name: api-rabbit
|
||||||
|
image: onelab-api-rabbit
|
||||||
|
replicaKey: apirabbit
|
||||||
|
port: 3000
|
||||||
|
config: true
|
||||||
|
mounts: [logs, data]
|
||||||
|
- name: devices-worker
|
||||||
|
image: onelab-devices-worker
|
||||||
|
replicaKey: devices
|
||||||
|
port: 0
|
||||||
|
config: true
|
||||||
|
mounts: [logs, data]
|
||||||
|
- name: experiments-worker
|
||||||
|
image: onelab-experiments-worker
|
||||||
|
replicaKey: experiments
|
||||||
|
port: 0
|
||||||
|
config: true
|
||||||
|
mounts: [logs]
|
||||||
|
- name: images-worker
|
||||||
|
image: onelab-images-worker
|
||||||
|
replicaKey: images
|
||||||
|
port: 0
|
||||||
|
config: true
|
||||||
|
mounts: [logs, data]
|
||||||
|
- name: manual-worker
|
||||||
|
image: onelab-manual-worker
|
||||||
|
replicaKey: manual
|
||||||
|
port: 0
|
||||||
|
config: true
|
||||||
|
mounts: [logs]
|
||||||
|
- name: websocket-worker
|
||||||
|
image: onelab-websocket-worker
|
||||||
|
replicaKey: ws
|
||||||
|
port: 3030
|
||||||
|
config: true
|
||||||
|
mounts: [logs]
|
||||||
|
- name: static
|
||||||
|
image: onelab-static
|
||||||
|
replicas: 1
|
||||||
|
port: 80
|
||||||
|
config: false
|
||||||
|
mounts: []
|
||||||
|
- name: main
|
||||||
|
image: onelab-main
|
||||||
|
replicas: 1
|
||||||
|
port: 80
|
||||||
|
config: false
|
||||||
|
mounts: []
|
||||||
|
- name: designer
|
||||||
|
image: onelab-designer
|
||||||
|
replicas: 1
|
||||||
|
port: 80
|
||||||
|
config: false
|
||||||
|
mounts: []
|
||||||
|
- name: runner
|
||||||
|
image: onelab-runner
|
||||||
|
replicas: 1
|
||||||
|
port: 80
|
||||||
|
config: false
|
||||||
|
mounts: []
|
||||||
|
- name: website
|
||||||
|
image: onelab-website
|
||||||
|
replicas: 1
|
||||||
|
port: 4000
|
||||||
|
config: false
|
||||||
|
mounts: []
|
||||||
|
website: true
|
||||||
12
gitops/observability/Chart.lock
Normal file
12
gitops/observability/Chart.lock
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
dependencies:
|
||||||
|
- name: loki
|
||||||
|
repository: https://grafana.github.io/helm-charts
|
||||||
|
version: 6.55.0
|
||||||
|
- name: promtail
|
||||||
|
repository: https://grafana.github.io/helm-charts
|
||||||
|
version: 6.17.1
|
||||||
|
- name: grafana
|
||||||
|
repository: https://grafana.github.io/helm-charts
|
||||||
|
version: 10.5.15
|
||||||
|
digest: sha256:5b34192a8db9d940587777fbc62a13503c21217da814308654ce73fca2ed5d56
|
||||||
|
generated: "2026-03-20T11:06:47.9376325+01:00"
|
||||||
16
gitops/observability/Chart.yaml
Normal file
16
gitops/observability/Chart.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: onelab-observability
|
||||||
|
description: Loki + Promtail + Grafana for OneLab (same Argo Application as app chart via multi-source).
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: "1.0"
|
||||||
|
dependencies:
|
||||||
|
- name: loki
|
||||||
|
version: 6.55.0
|
||||||
|
repository: https://grafana.github.io/helm-charts
|
||||||
|
- name: promtail
|
||||||
|
version: 6.17.1
|
||||||
|
repository: https://grafana.github.io/helm-charts
|
||||||
|
- name: grafana
|
||||||
|
version: 10.5.15
|
||||||
|
repository: https://grafana.github.io/helm-charts
|
||||||
BIN
gitops/observability/charts/grafana-10.5.15.tgz
Normal file
BIN
gitops/observability/charts/grafana-10.5.15.tgz
Normal file
Binary file not shown.
BIN
gitops/observability/charts/loki-6.55.0.tgz
Normal file
BIN
gitops/observability/charts/loki-6.55.0.tgz
Normal file
Binary file not shown.
BIN
gitops/observability/charts/promtail-6.17.1.tgz
Normal file
BIN
gitops/observability/charts/promtail-6.17.1.tgz
Normal file
Binary file not shown.
205
gitops/observability/dashboards/onelab-logs.json
Normal file
205
gitops/observability/dashboards/onelab-logs.json
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"builtIn": 1,
|
||||||
|
"datasource": {"type": "grafana", "uid": "-- Grafana --"},
|
||||||
|
"enable": true,
|
||||||
|
"hide": true,
|
||||||
|
"iconColor": "rgba(0, 211, 255, 1)",
|
||||||
|
"name": "Annotations & Alerts",
|
||||||
|
"type": "dashboard"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": null,
|
||||||
|
"links": [],
|
||||||
|
"liveNow": false,
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"datasource": {"type": "loki", "uid": "loki"},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {"mode": "thresholds"},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [{"color": "blue", "value": null}]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 5, "w": 8, "x": 0, "y": 0},
|
||||||
|
"id": 1,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {"calcs": ["lastNotNull"], "fields": "", "values": false},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {"type": "loki", "uid": "loki"},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(count_over_time({namespace=\"onelab\", component=~\"$component\"} |~ \"$filter\" [$__range]))",
|
||||||
|
"queryType": "instant",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Total lines (namespace onelab, matches line filter)",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {"type": "loki", "uid": "loki"},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {"mode": "thresholds"},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": null},
|
||||||
|
{"color": "orange", "value": 1}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 5, "w": 8, "x": 8, "y": 0},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {"calcs": ["lastNotNull"], "fields": "", "values": false},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {"type": "loki", "uid": "loki"},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(count_over_time({namespace=\"onelab\", component=~\"$component\"} |~ \"$filter\" |~ \"(?i)(\\\\[ERROR\\\\]|\\\\berror\\\\b|\\\\sERROR\\\\s)\" [$__range]))",
|
||||||
|
"queryType": "instant",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "~ Error-like lines (heuristic)",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {"type": "loki", "uid": "loki"},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {"mode": "thresholds"},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": null},
|
||||||
|
{"color": "yellow", "value": 1}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {"h": 5, "w": 8, "x": 16, "y": 0},
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {"calcs": ["lastNotNull"], "fields": "", "values": false},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {"type": "loki", "uid": "loki"},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(count_over_time({namespace=\"onelab\", component=~\"$component\"} |~ \"$filter\" |~ \"(?i)(\\\\[WARN\\\\]|\\\\bwarn(ing)?\\\\b|\\\\sWARN\\\\s)\" [$__range]))",
|
||||||
|
"queryType": "instant",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "~ Warning-like lines (heuristic)",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {"type": "loki", "uid": "loki"},
|
||||||
|
"gridPos": {"h": 16, "w": 24, "x": 0, "y": 5},
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"dedupStrategy": "none",
|
||||||
|
"enableLogDetails": true,
|
||||||
|
"prettifyLogMessage": false,
|
||||||
|
"showCommonLabels": false,
|
||||||
|
"showLabels": true,
|
||||||
|
"showTime": true,
|
||||||
|
"sortOrder": "Descending",
|
||||||
|
"wrapLogMessage": true
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {"type": "loki", "uid": "loki"},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "{namespace=\"onelab\", component=~\"$component\"} |~ \"$filter\"",
|
||||||
|
"queryType": "range",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "OneLab logs — use Component + Line filter (regex)",
|
||||||
|
"type": "logs"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "30s",
|
||||||
|
"schemaVersion": 39,
|
||||||
|
"tags": ["onelab", "loki"],
|
||||||
|
"templating": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": {"selected": true, "text": "All", "value": "$__all"},
|
||||||
|
"datasource": {"type": "loki", "uid": "loki"},
|
||||||
|
"definition": "label_values({namespace=\"onelab\"}, component)",
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": true,
|
||||||
|
"label": "Component",
|
||||||
|
"multi": true,
|
||||||
|
"name": "component",
|
||||||
|
"options": [],
|
||||||
|
"query": "label_values({namespace=\"onelab\"}, component)",
|
||||||
|
"refresh": 2,
|
||||||
|
"regex": "",
|
||||||
|
"sort": 1,
|
||||||
|
"type": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"current": {"selected": true, "text": ".*", "value": ".*"},
|
||||||
|
"hide": 0,
|
||||||
|
"label": "Line filter (regex)",
|
||||||
|
"name": "filter",
|
||||||
|
"options": [
|
||||||
|
{"selected": true, "text": ".*", "value": ".*"}
|
||||||
|
],
|
||||||
|
"query": ".*",
|
||||||
|
"type": "textbox"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"time": {"from": "now-1h", "to": "now"},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "browser",
|
||||||
|
"title": "OneLab logs",
|
||||||
|
"uid": "onelab-logs",
|
||||||
|
"version": 1,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{{- if .Values.grafana.sidecar.dashboards.enabled }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ printf "%s-dashboard-onelab-logs" .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
grafana_dashboard: "1"
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "0"
|
||||||
|
data:
|
||||||
|
onelab-logs.json: |-
|
||||||
|
{{ .Files.Get "dashboards/onelab-logs.json" | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
36
gitops/observability/templates/ingress-grafana-onelab.yaml
Normal file
36
gitops/observability/templates/ingress-grafana-onelab.yaml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{{- if .Values.grafanaOnelabIngress.enabled }}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: grafana-onelab
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: grafana-onelab
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
app.kubernetes.io/component: observability
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "0"
|
||||||
|
cert-manager.io/cluster-issuer: {{ .Values.grafanaOnelabIngress.clusterIssuer | quote }}
|
||||||
|
{{- with .Values.grafanaOnelabIngress.annotations }}
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
ingressClassName: {{ .Values.grafanaOnelabIngress.className | quote }}
|
||||||
|
{{- if .Values.grafanaOnelabIngress.tls }}
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .Values.grafanaOnelabIngress.host | quote }}
|
||||||
|
secretName: {{ .Values.grafanaOnelabIngress.tlsSecretName | quote }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
- host: {{ .Values.grafanaOnelabIngress.host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ printf "%s-grafana" .Release.Name }}
|
||||||
|
port:
|
||||||
|
number: {{ .Values.grafanaOnelabIngress.servicePort }}
|
||||||
|
{{- end }}
|
||||||
3
gitops/observability/values.yaml
Normal file
3
gitops/observability/values.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Operator-facing overrides live in gitops/values/observability.yaml (see gitops/argocd/application.yaml helm.valueFiles).
|
||||||
|
# This file is kept minimal on purpose.
|
||||||
|
{}
|
||||||
31
gitops/values/README.md
Normal file
31
gitops/values/README.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# GitOps values (operator entry point)
|
||||||
|
|
||||||
|
All environment-specific Helm input for the Argo CD `Application` should live here (plus `repoURL` / `targetRevision` in [`../argocd/application.yaml`](../argocd/application.yaml)).
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| [`env-example.yaml`](env-example.yaml) | Tracked example for OneLab chart: ingress, persistence, registry pull secret wiring, **placeholder** secrets. Fork and edit hostnames/TLS names, then replace placeholders or overlay `secrets.local.yaml`. |
|
||||||
|
| [`observability.yaml`](observability.yaml) | Loki / Promtail / Grafana: retention, Promtail host paths, Grafana ingress host, **placeholder** admin password. Edit hosts/TLS together with `grafana.ini.server`. |
|
||||||
|
| [`secrets.example.yaml`](secrets.example.yaml) | Template of secret-shaped keys only — copy to `*.local.yaml` (gitignored) and reference from Argo. |
|
||||||
|
| [`instance-overrides.example.yaml`](instance-overrides.example.yaml) | Optional features (compliance, LDAP) — merge or add as another value file. |
|
||||||
|
|
||||||
|
## Argo `helm.valueFiles` (path rules)
|
||||||
|
|
||||||
|
Paths are **relative to each source’s `path`** in the Application:
|
||||||
|
|
||||||
|
- Source `gitops/charts/onelab` → e.g. `../../values/env-example.yaml`, then optionally `../../values/secrets.local.yaml`.
|
||||||
|
- Source `gitops/observability` → e.g. `../../values/observability.yaml`, then optionally `../../values/observability.local.yaml`.
|
||||||
|
|
||||||
|
Later files in the list **override** earlier ones.
|
||||||
|
|
||||||
|
## Private secrets without committing them
|
||||||
|
|
||||||
|
1. Copy `secrets.example.yaml` to `secrets.local.yaml` (ignored by `*.local.yaml` at repo root).
|
||||||
|
2. Fill in real registry password, Postgres password, app tokens, Intercom, etc.
|
||||||
|
3. Add `- ../../values/secrets.local.yaml` under the onelab source’s `helm.valueFiles` in your **local** Application manifest or a private overlay — or keep that change only on a private branch.
|
||||||
|
|
||||||
|
For Grafana, set `grafana.adminPassword` in a gitignored file merged with [`observability.yaml`](observability.yaml), or edit `observability.yaml` in a private fork.
|
||||||
|
|
||||||
|
See the full bootstrap narrative in [`../README.md`](../README.md).
|
||||||
48
gitops/values/env-example.yaml
Normal file
48
gitops/values/env-example.yaml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# Example environment overrides — copy patterns to a gitignored file (e.g. secrets.local.yaml)
|
||||||
|
# and add it to Argo helm.valueFiles after this file so secrets stay out of Git.
|
||||||
|
# See gitops/values/README.md and gitops/values/secrets.example.yaml.
|
||||||
|
|
||||||
|
registry:
|
||||||
|
createPullSecret: true
|
||||||
|
pullSecretName: hub-andrewalliance
|
||||||
|
server: hub.andrewalliance.com
|
||||||
|
username: public
|
||||||
|
password: "REPLACE_REGISTRY_PASSWORD"
|
||||||
|
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: hub-andrewalliance
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
mode: hostPath
|
||||||
|
hostPath:
|
||||||
|
data: /opt/onelab/data
|
||||||
|
logs: /opt/onelab/logs
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
auth:
|
||||||
|
password: "REPLACE_POSTGRES_PASSWORD"
|
||||||
|
|
||||||
|
onelab:
|
||||||
|
domain: "https://onelab.example.com"
|
||||||
|
secrets:
|
||||||
|
authTokenKey: "REPLACE_AUTH_TOKEN_KEY"
|
||||||
|
monitoringToken: "REPLACE_MONITORING_TOKEN"
|
||||||
|
rabbitToken: "REPLACE_RABBIT_TOKEN"
|
||||||
|
intercom:
|
||||||
|
appid: "REPLACE_INTERCOM_APP_ID"
|
||||||
|
secret: "REPLACE_INTERCOM_SECRET"
|
||||||
|
|
||||||
|
revproxy:
|
||||||
|
serviceType: ClusterIP
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: traefik
|
||||||
|
host: onelab.example.com
|
||||||
|
path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls: true
|
||||||
|
tlsSecretName: onelab-tls
|
||||||
|
certManager:
|
||||||
|
clusterIssuer: letsencrypt-prod
|
||||||
|
annotations: {}
|
||||||
38
gitops/values/instance-overrides.example.yaml
Normal file
38
gitops/values/instance-overrides.example.yaml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Copy to a private file (e.g. gitops/values/overrides.local.yaml, gitignored) or merge into gitops/values/env-example.yaml.
|
||||||
|
#
|
||||||
|
# Argo CD: under spec.sources, for the source with path gitops/charts/onelab, add another path to helm.valueFiles
|
||||||
|
# (paths are relative to that chart directory), e.g.:
|
||||||
|
# - ../../values/env-example.yaml
|
||||||
|
# - ../../values/secrets.local.yaml
|
||||||
|
# - ../../values/overrides.local.yaml
|
||||||
|
|
||||||
|
onelab:
|
||||||
|
compliance:
|
||||||
|
enabled: true
|
||||||
|
# Optional tweaks (defaults match chart values.yaml):
|
||||||
|
# requireElectronicSignature: true
|
||||||
|
# executionOperatorRestrictionPolicy: "reviewed"
|
||||||
|
# executionAdminExpertRestrictionPolicy: "reviewed"
|
||||||
|
# preventCsvImport: true
|
||||||
|
# preventManualMetadataEdit: true
|
||||||
|
# deviceRestart: true
|
||||||
|
|
||||||
|
ldap:
|
||||||
|
enabled: true
|
||||||
|
# timeout: 30
|
||||||
|
# encryption: "start_tls"
|
||||||
|
# policy: "your-policy"
|
||||||
|
# verifyCertificates: true
|
||||||
|
# Paths inside the ldap-worker container (mount certs via extraVolumes if needed):
|
||||||
|
# tlsCaPath: "/ldap/ca.crt"
|
||||||
|
# tlsCertPath: "/ldap/client.crt"
|
||||||
|
# tlsKeyPath: "/ldap/client.key"
|
||||||
|
# tlsCiphers: ""
|
||||||
|
# tlsSslVersion: ""
|
||||||
|
|
||||||
|
# Alternative: supply the full YAML yourself (bypasses chart templates in configurations.gotmpl for those keys).
|
||||||
|
# 1. kubectl create secret generic onelab-configurations-custom -n onelab \
|
||||||
|
# --from-file=configurations.yml=./my-configurations.yml
|
||||||
|
# 2. Set in values:
|
||||||
|
# configuration:
|
||||||
|
# existingSecretName: onelab-configurations-custom
|
||||||
144
gitops/values/observability.yaml
Normal file
144
gitops/values/observability.yaml
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
# Umbrella chart: Loki (SingleBinary + filesystem) + Promtail + Grafana.
|
||||||
|
# Keep promtail hostPath below in sync with persistence.hostPath.logs in gitops/values/env-example.yaml.
|
||||||
|
|
||||||
|
loki:
|
||||||
|
deploymentMode: SingleBinary
|
||||||
|
loki:
|
||||||
|
auth_enabled: false
|
||||||
|
commonConfig:
|
||||||
|
replication_factor: 1
|
||||||
|
storage:
|
||||||
|
type: filesystem
|
||||||
|
schemaConfig:
|
||||||
|
configs:
|
||||||
|
- from: "2024-04-01"
|
||||||
|
store: tsdb
|
||||||
|
object_store: filesystem
|
||||||
|
schema: v13
|
||||||
|
index:
|
||||||
|
prefix: loki_index_
|
||||||
|
period: 24h
|
||||||
|
limits_config:
|
||||||
|
retention_period: 168h
|
||||||
|
ingestion_rate_mb: 16
|
||||||
|
ingestion_burst_size_mb: 32
|
||||||
|
singleBinary:
|
||||||
|
replicas: 1
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 10Gi
|
||||||
|
backend:
|
||||||
|
replicas: 0
|
||||||
|
read:
|
||||||
|
replicas: 0
|
||||||
|
write:
|
||||||
|
replicas: 0
|
||||||
|
ingester:
|
||||||
|
replicas: 0
|
||||||
|
querier:
|
||||||
|
replicas: 0
|
||||||
|
queryFrontend:
|
||||||
|
replicas: 0
|
||||||
|
queryScheduler:
|
||||||
|
replicas: 0
|
||||||
|
distributor:
|
||||||
|
replicas: 0
|
||||||
|
compactor:
|
||||||
|
replicas: 0
|
||||||
|
indexGateway:
|
||||||
|
replicas: 0
|
||||||
|
bloomCompactor:
|
||||||
|
replicas: 0
|
||||||
|
bloomGateway:
|
||||||
|
replicas: 0
|
||||||
|
ruler:
|
||||||
|
replicas: 0
|
||||||
|
minio:
|
||||||
|
enabled: false
|
||||||
|
lokiCanary:
|
||||||
|
enabled: false
|
||||||
|
test:
|
||||||
|
enabled: false
|
||||||
|
chunksCache:
|
||||||
|
enabled: false
|
||||||
|
resultsCache:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
promtail:
|
||||||
|
config:
|
||||||
|
clients:
|
||||||
|
- url: http://{{ .Release.Name }}-loki-gateway.{{ .Release.Namespace }}.svc.cluster.local/loki/api/v1/push
|
||||||
|
snippets:
|
||||||
|
extraRelabelConfigs:
|
||||||
|
- action: keep
|
||||||
|
source_labels:
|
||||||
|
- __meta_kubernetes_namespace
|
||||||
|
regex: onelab
|
||||||
|
extraScrapeConfigs: |
|
||||||
|
- job_name: onelab-host-log-files
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- localhost
|
||||||
|
labels:
|
||||||
|
job: onelab-files
|
||||||
|
namespace: onelab
|
||||||
|
component: host-logs
|
||||||
|
__path__: /onelab-host-logs/**/*
|
||||||
|
extraVolumes:
|
||||||
|
- name: onelab-host-logs
|
||||||
|
hostPath:
|
||||||
|
path: /opt/onelab/logs
|
||||||
|
type: DirectoryOrCreate
|
||||||
|
extraVolumeMounts:
|
||||||
|
- name: onelab-host-logs
|
||||||
|
mountPath: /onelab-host-logs
|
||||||
|
readOnly: true
|
||||||
|
|
||||||
|
grafanaOnelabIngress:
|
||||||
|
enabled: true
|
||||||
|
className: traefik
|
||||||
|
host: grafana.onelab.example.com
|
||||||
|
tls: true
|
||||||
|
tlsSecretName: grafana-onelab-tls
|
||||||
|
clusterIssuer: letsencrypt-prod
|
||||||
|
servicePort: 80
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
adminUser: admin
|
||||||
|
adminPassword: "REPLACE_GRAFANA_ADMIN_PASSWORD"
|
||||||
|
initChownData:
|
||||||
|
enabled: false
|
||||||
|
sidecar:
|
||||||
|
dashboards:
|
||||||
|
enabled: true
|
||||||
|
label: grafana_dashboard
|
||||||
|
folder: /tmp/dashboards
|
||||||
|
provider:
|
||||||
|
foldersFromFilesStructure: false
|
||||||
|
allowUiUpdates: true
|
||||||
|
datasources:
|
||||||
|
enabled: false
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 2Gi
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
grafana.ini:
|
||||||
|
server:
|
||||||
|
domain: grafana.onelab.example.com
|
||||||
|
root_url: https://grafana.onelab.example.com/
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
datasources:
|
||||||
|
datasources.yaml:
|
||||||
|
apiVersion: 1
|
||||||
|
datasources:
|
||||||
|
- name: Loki
|
||||||
|
type: loki
|
||||||
|
uid: loki
|
||||||
|
url: http://{{ .Release.Name }}-loki-gateway.{{ .Release.Namespace }}.svc.cluster.local
|
||||||
|
access: proxy
|
||||||
|
isDefault: true
|
||||||
|
jsonData:
|
||||||
|
maxLines: 1000
|
||||||
26
gitops/values/secrets.example.yaml
Normal file
26
gitops/values/secrets.example.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Copy to a gitignored file (e.g. gitops/values/secrets.local.yaml — match *.local.yaml in repo .gitignore).
|
||||||
|
# Add it as the LAST entry in spec.sources[].helm.valueFiles for the onelab chart so these values win.
|
||||||
|
#
|
||||||
|
# Do not commit real values.
|
||||||
|
|
||||||
|
registry:
|
||||||
|
username: public
|
||||||
|
password: "YOUR_REGISTRY_PASSWORD"
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
auth:
|
||||||
|
password: "YOUR_POSTGRES_PASSWORD"
|
||||||
|
|
||||||
|
onelab:
|
||||||
|
secrets:
|
||||||
|
authTokenKey: "YOUR_AUTH_TOKEN_KEY"
|
||||||
|
monitoringToken: "YOUR_MONITORING_TOKEN"
|
||||||
|
rabbitToken: "YOUR_RABBIT_TOKEN"
|
||||||
|
intercom:
|
||||||
|
appid: "YOUR_INTERCOM_APP_ID"
|
||||||
|
secret: "YOUR_INTERCOM_SECRET"
|
||||||
|
|
||||||
|
# Optional: Grafana admin password is normally set in gitops/values/observability.yaml;
|
||||||
|
# override there or add a second gitignored value file for the observability source.
|
||||||
|
# grafana:
|
||||||
|
# adminPassword: "YOUR_GRAFANA_PASSWORD"
|
||||||
Reference in New Issue
Block a user