Add self-contained API simulators lab with Compose and Helm.
Ship Proxmox, oVirt, VMware, and OpenStack behind one Postgres stack, Makefile helpers (up/clean/helm up|down/push), and a Helm chart with namespace, Let's Encrypt ingresses, migrate inits, and skip-if-seeded jobs.
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
.DS_Store
|
||||
*.tgz
|
||||
charts/
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v2
|
||||
name: api-simulators-lab
|
||||
description: Laboratory stack — Proxmox, oVirt, VMware and OpenStack API simulators
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "latest"
|
||||
keywords:
|
||||
- simulators
|
||||
- proxmox
|
||||
- ovirt
|
||||
- vmware
|
||||
- openstack
|
||||
maintainers:
|
||||
- name: inecs
|
||||
@@ -0,0 +1,28 @@
|
||||
1. Namespace: {{ include "lab.namespace" . }}
|
||||
|
||||
2. Point DNS (or /etc/hosts for local-only) at the Ingress controller:
|
||||
{{- range $name, $ing := .Values.ingresses }}
|
||||
{{- if $ing.enabled }}
|
||||
{{ $ing.host }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
3. Open simulators (TLS via cert-manager / Let's Encrypt when enabled):
|
||||
{{- range $name, $ing := .Values.ingresses }}
|
||||
{{- if $ing.enabled }}
|
||||
{{- $https := or $ing.tls $.Values.certManager.enabled }}
|
||||
http{{ if $https }}s{{ end }}://{{ $ing.host }}{{ $ing.path | default "/" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.certManager.enabled }}
|
||||
|
||||
cert-manager ClusterIssuer: {{ include "lab.clusterIssuer" . }}
|
||||
{{- if .Values.certManager.createClusterIssuer }}
|
||||
(created by this chart; email={{ .Values.certManager.email }})
|
||||
{{- else }}
|
||||
(expected to already exist in the cluster)
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
Configure namespace / hosts / TLS under `.Values.namespace`, `.Values.ingresses`, `.Values.certManager`.
|
||||
@@ -0,0 +1,69 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "lab.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
*/}}
|
||||
{{- define "lab.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 "lab.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "lab.labels" -}}
|
||||
helm.sh/chart: {{ include "lab.chart" . }}
|
||||
{{ include "lab.selectorLabels" . }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "lab.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "lab.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "lab.postgresHost" -}}
|
||||
{{- printf "%s-postgres" (include "lab.fullname" .) }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "lab.namespace" -}}
|
||||
{{- .Values.namespace | default .Release.Namespace }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "lab.databaseUrl" -}}
|
||||
{{- $sim := .sim -}}
|
||||
{{- printf "postgresql://%s:%s@%s:5432/%s" $sim.db.user $sim.db.password (include "lab.postgresHost" .root) $sim.db.name }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "lab.commonEnv" -}}
|
||||
- name: TICKET_SIGNING_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "lab.fullname" . }}
|
||||
key: ticketSigningKey
|
||||
- name: LOG_LEVEL
|
||||
value: {{ .Values.logLevel | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "lab.clusterIssuer" -}}
|
||||
{{- if .Values.certManager.useStaging }}
|
||||
{{- .Values.certManager.stagingIssuerName }}
|
||||
{{- else }}
|
||||
{{- .Values.certManager.issuerName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,42 @@
|
||||
{{- if and .Values.certManager.enabled .Values.certManager.createClusterIssuer }}
|
||||
{{- $solverClass := .Values.certManager.solverIngressClassName | default "nginx" }}
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: {{ .Values.certManager.issuerName }}
|
||||
labels:
|
||||
{{- include "lab.labels" . | nindent 4 }}
|
||||
spec:
|
||||
acme:
|
||||
email: {{ required "certManager.email is required when createClusterIssuer=true" .Values.certManager.email | quote }}
|
||||
server: {{ .Values.certManager.server | quote }}
|
||||
privateKeySecretRef:
|
||||
name: {{ printf "%s-account-key" .Values.certManager.issuerName }}
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
{{- if $solverClass }}
|
||||
ingressClassName: {{ $solverClass }}
|
||||
{{- end }}
|
||||
---
|
||||
{{- if .Values.certManager.createStagingIssuer }}
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: {{ .Values.certManager.stagingIssuerName }}
|
||||
labels:
|
||||
{{- include "lab.labels" . | nindent 4 }}
|
||||
spec:
|
||||
acme:
|
||||
email: {{ .Values.certManager.email | quote }}
|
||||
server: {{ .Values.certManager.stagingServer | quote }}
|
||||
privateKeySecretRef:
|
||||
name: {{ printf "%s-account-key" .Values.certManager.stagingIssuerName }}
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
{{- if $solverClass }}
|
||||
ingressClassName: {{ $solverClass }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,52 @@
|
||||
{{- range $name, $ing := .Values.ingresses }}
|
||||
{{- if $ing.enabled }}
|
||||
{{- $svcName := printf "%s-%s" (include "lab.fullname" $) $ing.service }}
|
||||
{{- $className := $ing.className | default $.Values.ingressClassName }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ include "lab.fullname" $ }}-{{ $name }}
|
||||
namespace: {{ include "lab.namespace" $ }}
|
||||
labels:
|
||||
{{- include "lab.labels" $ | nindent 4 }}
|
||||
app.kubernetes.io/component: ingress-{{ $name }}
|
||||
annotations:
|
||||
{{- if $.Values.certManager.enabled }}
|
||||
cert-manager.io/cluster-issuer: {{ include "lab.clusterIssuer" $ | quote }}
|
||||
{{- end }}
|
||||
{{- with $ing.annotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if $className }}
|
||||
ingressClassName: {{ $className | quote }}
|
||||
{{- end }}
|
||||
{{- if $ing.tls }}
|
||||
tls:
|
||||
{{- range $ing.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- else if $.Values.certManager.enabled }}
|
||||
tls:
|
||||
- hosts:
|
||||
- {{ $ing.host | quote }}
|
||||
secretName: {{ printf "%s-%s-tls" (include "lab.fullname" $) $name }}
|
||||
{{- end }}
|
||||
rules:
|
||||
- host: {{ $ing.host | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ $ing.path | default "/" | quote }}
|
||||
pathType: {{ $ing.pathType | default "Prefix" }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ $svcName }}
|
||||
port:
|
||||
number: {{ $ing.port }}
|
||||
---
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,8 @@
|
||||
{{- if .Values.namespaceCreate }}
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ include "lab.namespace" . }}
|
||||
labels:
|
||||
{{- include "lab.labels" . | nindent 4 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if .Values.postgres.enabled }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "lab.fullname" . }}-postgres-init
|
||||
namespace: {{ include "lab.namespace" . }}
|
||||
labels:
|
||||
{{- include "lab.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
data:
|
||||
01-simulators.sql: |
|
||||
{{- range .Values.postgres.initDatabases }}
|
||||
CREATE USER {{ .user }} WITH PASSWORD '{{ .password }}';
|
||||
CREATE DATABASE {{ .database }} OWNER {{ .user }};
|
||||
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,110 @@
|
||||
{{- if .Values.postgres.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "lab.postgresHost" . }}
|
||||
namespace: {{ include "lab.namespace" . }}
|
||||
labels:
|
||||
{{- include "lab.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: postgres
|
||||
port: 5432
|
||||
targetPort: postgres
|
||||
protocol: TCP
|
||||
selector:
|
||||
{{- include "lab.selectorLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "lab.postgresHost" . }}
|
||||
namespace: {{ include "lab.namespace" . }}
|
||||
labels:
|
||||
{{- include "lab.labels" . | nindent 4 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
spec:
|
||||
serviceName: {{ include "lab.postgresHost" . }}
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "lab.selectorLabels" . | nindent 6 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "lab.selectorLabels" . | nindent 8 }}
|
||||
app.kubernetes.io/component: postgres
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: postgres
|
||||
image: "{{ .Values.postgres.image.repository }}:{{ .Values.postgres.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.postgres.image.pullPolicy }}
|
||||
ports:
|
||||
- name: postgres
|
||||
containerPort: 5432
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: {{ .Values.postgres.auth.username | quote }}
|
||||
- name: POSTGRES_DB
|
||||
value: {{ .Values.postgres.auth.database | quote }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "lab.fullname" . }}
|
||||
key: postgres-password
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
- name: init
|
||||
mountPath: /docker-entrypoint-initdb.d
|
||||
readOnly: true
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["pg_isready", "-U", {{ .Values.postgres.auth.username | quote }}, "-d", {{ .Values.postgres.auth.database | quote }}]
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 12
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: ["pg_isready", "-U", {{ .Values.postgres.auth.username | quote }}, "-d", {{ .Values.postgres.auth.database | quote }}]
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
{{- with .Values.postgres.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: init
|
||||
configMap:
|
||||
name: {{ include "lab.fullname" . }}-postgres-init
|
||||
{{- if not .Values.postgres.persistence.enabled }}
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- if .Values.postgres.persistence.enabled }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
{{- if .Values.postgres.persistence.storageClass }}
|
||||
storageClassName: {{ .Values.postgres.persistence.storageClass | quote }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.postgres.persistence.size }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "lab.fullname" . }}
|
||||
namespace: {{ include "lab.namespace" . }}
|
||||
labels:
|
||||
{{- include "lab.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
ticketSigningKey: {{ .Values.ticketSigningKey | quote }}
|
||||
postgres-password: {{ .Values.postgres.auth.password | quote }}
|
||||
{{- range $name, $sim := .Values.simulators }}
|
||||
{{- if and $sim.enabled $sim.db }}
|
||||
{{ $name }}-db-password: {{ $sim.db.password | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,92 @@
|
||||
{{- if .Values.seedJobs.enabled }}
|
||||
{{- range $name, $sim := .Values.simulators }}
|
||||
{{- if and $sim.enabled $sim.seed $sim.seed.enabled }}
|
||||
{{- $fullname := printf "%s-%s" (include "lab.fullname" $) $name }}
|
||||
{{- $tag := $sim.image.tag | default $.Values.imageTag }}
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ $fullname }}-seed
|
||||
namespace: {{ include "lab.namespace" $ }}
|
||||
labels:
|
||||
{{- include "lab.labels" $ | nindent 4 }}
|
||||
app.kubernetes.io/component: {{ $name }}-seed
|
||||
annotations:
|
||||
helm.sh/hook: post-install,post-upgrade
|
||||
helm.sh/hook-weight: "10"
|
||||
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
|
||||
spec:
|
||||
backoffLimit: {{ $.Values.seedJobs.backoffLimit }}
|
||||
ttlSecondsAfterFinished: {{ $.Values.seedJobs.ttlSecondsAfterFinished }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "lab.selectorLabels" $ | nindent 8 }}
|
||||
app.kubernetes.io/component: {{ $name }}-seed
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
{{- with $.Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: wait-ready
|
||||
image: curlimages/curl:8.12.1
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
url="http://{{ $fullname }}:{{ $sim.port }}{{ $sim.healthPath }}"
|
||||
echo "waiting for $url"
|
||||
until curl -fsS "$url" >/dev/null; do sleep 3; done
|
||||
containers:
|
||||
- name: seed
|
||||
image: "{{ $sim.image.repository }}:{{ $tag }}"
|
||||
imagePullPolicy: {{ $sim.image.pullPolicy }}
|
||||
# Skip when skipIfSql returns a row (DB already seeded / has lab data).
|
||||
command:
|
||||
- python
|
||||
- -c
|
||||
- |
|
||||
import asyncio, os, subprocess, sys
|
||||
import asyncpg
|
||||
|
||||
skip_sql = os.environ.get("SEED_SKIP_IF_SQL", "").strip()
|
||||
seed_cmd = {{ $sim.seed.command | toJson }}
|
||||
|
||||
async def already_seeded() -> bool:
|
||||
if not skip_sql:
|
||||
return False
|
||||
conn = await asyncpg.connect(os.environ["DATABASE_URL"])
|
||||
try:
|
||||
return await conn.fetchval(skip_sql) is not None
|
||||
except Exception as exc: # noqa: BLE001 — empty/unmigrated DB
|
||||
print(f"seed: skip-check deferred ({exc})")
|
||||
return False
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
if asyncio.run(already_seeded()):
|
||||
print("seed: database already has data — skipping")
|
||||
raise SystemExit(0)
|
||||
print("seed: applying", seed_cmd)
|
||||
raise SystemExit(subprocess.call(seed_cmd))
|
||||
env:
|
||||
{{- include "lab.commonEnv" $ | nindent 12 }}
|
||||
- name: DATABASE_URL
|
||||
value: {{ include "lab.databaseUrl" (dict "root" $ "sim" $sim) | quote }}
|
||||
- name: SEED_SKIP_IF_SQL
|
||||
value: {{ ($sim.seed.skipIfSql | default "") | quote }}
|
||||
{{- range $k, $v := $sim.env }}
|
||||
- name: {{ $k }}
|
||||
value: {{ $v | quote }}
|
||||
{{- end }}
|
||||
{{- range $k, $v := ($sim.seed.env | default dict) }}
|
||||
- name: {{ $k }}
|
||||
value: {{ $v | quote }}
|
||||
{{- end }}
|
||||
---
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,111 @@
|
||||
{{- range $name, $sim := .Values.simulators }}
|
||||
{{- if $sim.enabled }}
|
||||
{{- $fullname := printf "%s-%s" (include "lab.fullname" $) $name }}
|
||||
{{- $tag := $sim.image.tag | default $.Values.imageTag }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ $fullname }}
|
||||
namespace: {{ include "lab.namespace" $ }}
|
||||
labels:
|
||||
{{- include "lab.labels" $ | nindent 4 }}
|
||||
app.kubernetes.io/component: {{ $name }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: http
|
||||
port: {{ $sim.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
selector:
|
||||
{{- include "lab.selectorLabels" $ | nindent 4 }}
|
||||
app.kubernetes.io/component: {{ $name }}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ $fullname }}
|
||||
namespace: {{ include "lab.namespace" $ }}
|
||||
labels:
|
||||
{{- include "lab.labels" $ | nindent 4 }}
|
||||
app.kubernetes.io/component: {{ $name }}
|
||||
spec:
|
||||
replicas: {{ $sim.replicas | default 1 }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "lab.selectorLabels" $ | nindent 6 }}
|
||||
app.kubernetes.io/component: {{ $name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "lab.selectorLabels" $ | nindent 8 }}
|
||||
app.kubernetes.io/component: {{ $name }}
|
||||
spec:
|
||||
{{- with $.Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: wait-postgres
|
||||
image: "{{ $.Values.postgres.image.repository }}:{{ $.Values.postgres.image.tag }}"
|
||||
imagePullPolicy: {{ $.Values.postgres.image.pullPolicy }}
|
||||
command:
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
until pg_isready -h {{ include "lab.postgresHost" $ }} -p 5432 -U {{ $.Values.postgres.auth.username }}; do
|
||||
echo "waiting for postgres..."; sleep 2;
|
||||
done
|
||||
{{- if and $sim.migrate $sim.migrate.enabled }}
|
||||
- name: migrate
|
||||
image: "{{ $sim.image.repository }}:{{ $tag }}"
|
||||
imagePullPolicy: {{ $sim.image.pullPolicy }}
|
||||
# Idempotent: migrate_cli applies 0 migrations when schema is already current.
|
||||
command: {{- toYaml $sim.migrate.command | nindent 12 }}
|
||||
env:
|
||||
{{- include "lab.commonEnv" $ | nindent 12 }}
|
||||
- name: DATABASE_URL
|
||||
value: {{ include "lab.databaseUrl" (dict "root" $ "sim" $sim) | quote }}
|
||||
{{- range $k, $v := $sim.env }}
|
||||
- name: {{ $k }}
|
||||
value: {{ $v | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: simulator
|
||||
image: "{{ $sim.image.repository }}:{{ $tag }}"
|
||||
imagePullPolicy: {{ $sim.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ $sim.port }}
|
||||
protocol: TCP
|
||||
env:
|
||||
{{- include "lab.commonEnv" $ | nindent 12 }}
|
||||
- name: DATABASE_URL
|
||||
value: {{ include "lab.databaseUrl" (dict "root" $ "sim" $sim) | quote }}
|
||||
{{- range $k, $v := $sim.env }}
|
||||
- name: {{ $k }}
|
||||
value: {{ $v | quote }}
|
||||
{{- end }}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: {{ $sim.healthPath }}
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: {{ $sim.healthPath }}
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 20
|
||||
timeoutSeconds: 3
|
||||
{{- with $sim.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
---
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,258 @@
|
||||
# Laboratory defaults — rotate secrets before any non-lab use.
|
||||
|
||||
nameOverride: ""
|
||||
fullnameOverride: "simulators"
|
||||
|
||||
# Target Kubernetes namespace (also used by make helm up/down).
|
||||
namespace: simulators
|
||||
# Create the Namespace resource from this chart.
|
||||
namespaceCreate: true
|
||||
|
||||
imagePullSecrets: []
|
||||
ticketSigningKey: development-only-signing-key-change-me
|
||||
logLevel: INFO
|
||||
imageTag: latest
|
||||
|
||||
postgres:
|
||||
enabled: true
|
||||
image:
|
||||
repository: postgres
|
||||
tag: 17.5-bookworm
|
||||
pullPolicy: IfNotPresent
|
||||
auth:
|
||||
username: lab
|
||||
password: lab
|
||||
database: postgres
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 5Gi
|
||||
storageClass: ""
|
||||
resources: {}
|
||||
# users/databases created on first start (empty volume only)
|
||||
initDatabases:
|
||||
- user: proxmox
|
||||
password: proxmox
|
||||
database: proxmox_simulator
|
||||
- user: ovirt
|
||||
password: ovirt
|
||||
database: ovirt_simulator
|
||||
- user: vmware
|
||||
password: vmware
|
||||
database: vmware_simulator
|
||||
- user: openstack
|
||||
password: openstack
|
||||
database: openstack_simulator
|
||||
|
||||
simulators:
|
||||
proxmox:
|
||||
enabled: true
|
||||
image:
|
||||
repository: inecs/proxmox-api-simulator
|
||||
pullPolicy: IfNotPresent
|
||||
port: 8006
|
||||
healthPath: /health/ready
|
||||
replicas: 1
|
||||
db:
|
||||
user: proxmox
|
||||
password: proxmox
|
||||
name: proxmox_simulator
|
||||
env:
|
||||
CONTRACT_SNAPSHOT: /app/contracts/pve-9.2.3.json
|
||||
COMPATIBILITY_EVIDENCE: /app/evidence/pve-9.2.3.json
|
||||
TASK_WORKER_CONCURRENCY: "2"
|
||||
SIMULATION_TIME_SCALE: "10"
|
||||
migrate:
|
||||
enabled: true
|
||||
command: ["python", "-m", "app.db.migrate_cli"]
|
||||
seed:
|
||||
enabled: true
|
||||
# Skip seed Job when this query returns a row (already seeded).
|
||||
skipIfSql: "SELECT 1 FROM nodes LIMIT 1"
|
||||
command: ["python", "-m", "app.simulation.seed_cli"]
|
||||
env:
|
||||
SEED_PROFILE: small
|
||||
resources: {}
|
||||
|
||||
ovirt:
|
||||
enabled: true
|
||||
image:
|
||||
repository: inecs/ovirt-api-simulator
|
||||
pullPolicy: IfNotPresent
|
||||
port: 8080
|
||||
healthPath: /health/ready
|
||||
replicas: 1
|
||||
db:
|
||||
user: ovirt
|
||||
password: ovirt
|
||||
name: ovirt_simulator
|
||||
env:
|
||||
OVIRT_SERIES: "4.5"
|
||||
APP_PORT: "8080"
|
||||
migrate:
|
||||
enabled: true
|
||||
command: ["python", "-m", "app.db.migrate_cli"]
|
||||
seed:
|
||||
enabled: true
|
||||
skipIfSql: "SELECT 1 FROM ov_datacenters LIMIT 1"
|
||||
command: ["python", "-m", "app.ovirt.seed_cli", "--profile", "minimal"]
|
||||
resources: {}
|
||||
|
||||
vmware:
|
||||
enabled: true
|
||||
image:
|
||||
repository: inecs/vmware-api-simulator
|
||||
pullPolicy: IfNotPresent
|
||||
port: 8080
|
||||
healthPath: /health/ready
|
||||
replicas: 1
|
||||
db:
|
||||
user: vmware
|
||||
password: vmware
|
||||
name: vmware_simulator
|
||||
env:
|
||||
ENABLE_PVE_STUB: "false"
|
||||
SEED_VSPHERE_PROFILE: small
|
||||
APP_PORT: "8080"
|
||||
TASK_WORKER_CONCURRENCY: "2"
|
||||
SIMULATION_TIME_SCALE: "10"
|
||||
migrate:
|
||||
enabled: true
|
||||
command: ["python", "-m", "app.db.migrate_cli"]
|
||||
seed:
|
||||
enabled: true
|
||||
skipIfSql: "SELECT 1 FROM vsphere_objects LIMIT 1"
|
||||
command: ["python", "-m", "app.simulation.seed_cli"]
|
||||
env:
|
||||
SEED_PROFILE: small
|
||||
SEED_VSPHERE_PROFILE: small
|
||||
resources: {}
|
||||
|
||||
openstack:
|
||||
enabled: true
|
||||
image:
|
||||
repository: inecs/openstack-api-simulator
|
||||
pullPolicy: IfNotPresent
|
||||
port: 8080
|
||||
healthPath: /health/ready
|
||||
replicas: 1
|
||||
db:
|
||||
user: openstack
|
||||
password: openstack
|
||||
name: openstack_simulator
|
||||
env:
|
||||
APP_PORT: "8080"
|
||||
TASK_WORKER_CONCURRENCY: "2"
|
||||
SIMULATION_TIME_SCALE: "10"
|
||||
migrate:
|
||||
enabled: true
|
||||
command: ["python", "-m", "app.db.migrate_cli"]
|
||||
seed:
|
||||
enabled: true
|
||||
skipIfSql: "SELECT 1 FROM os_projects LIMIT 1"
|
||||
command: ["python", "-m", "app.openstack.seed_cli", "--profile", "minimal"]
|
||||
resources: {}
|
||||
|
||||
# Ingress hosts — edit here. Each enabled entry creates one Ingress.
|
||||
# Default hosts: <name>.lab.local — for Let's Encrypt use a public DNS name.
|
||||
ingressClassName: nginx
|
||||
|
||||
ingresses:
|
||||
proxmox:
|
||||
enabled: true
|
||||
className: "" # falls back to ingressClassName
|
||||
host: proxmox.lab.local
|
||||
path: /
|
||||
pathType: Prefix
|
||||
service: proxmox
|
||||
port: 8006
|
||||
tls:
|
||||
- secretName: simulators-proxmox-tls
|
||||
hosts: [proxmox.lab.local]
|
||||
annotations: {}
|
||||
|
||||
ovirt:
|
||||
enabled: true
|
||||
className: ""
|
||||
host: ovirt.lab.local
|
||||
path: /
|
||||
pathType: Prefix
|
||||
service: ovirt
|
||||
port: 8080
|
||||
tls:
|
||||
- secretName: simulators-ovirt-tls
|
||||
hosts: [ovirt.lab.local]
|
||||
annotations: {}
|
||||
|
||||
vmware:
|
||||
enabled: true
|
||||
className: ""
|
||||
host: vmware.lab.local
|
||||
path: /
|
||||
pathType: Prefix
|
||||
service: vmware
|
||||
port: 8080
|
||||
tls:
|
||||
- secretName: simulators-vmware-tls
|
||||
hosts: [vmware.lab.local]
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||
proxy_set_header X-VMware-Service "vcenter";
|
||||
proxy_set_header X-Forwarded-Port "443";
|
||||
|
||||
openstack:
|
||||
enabled: true
|
||||
className: ""
|
||||
host: openstack.lab.local
|
||||
path: /
|
||||
pathType: Prefix
|
||||
service: openstack
|
||||
port: 8080
|
||||
tls:
|
||||
- secretName: simulators-openstack-tls
|
||||
hosts: [openstack.lab.local]
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||
proxy_set_header X-OpenStack-Service "https";
|
||||
proxy_set_header X-Forwarded-Port "443";
|
||||
|
||||
# Optional extras — same shape as above, e.g.:
|
||||
# ovirt-ui:
|
||||
# enabled: true
|
||||
# host: ovirt-ui.lab.local
|
||||
# service: ovirt
|
||||
# port: 8080
|
||||
# tls:
|
||||
# - secretName: simulators-ovirt-ui-tls
|
||||
# hosts: [ovirt-ui.lab.local]
|
||||
# openstack-keystone:
|
||||
# enabled: true
|
||||
# host: keystone.lab.local
|
||||
# service: openstack
|
||||
# port: 8080
|
||||
# tls:
|
||||
# - secretName: simulators-keystone-tls
|
||||
# hosts: [keystone.lab.local]
|
||||
# annotations:
|
||||
# nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||
# proxy_set_header X-OpenStack-Service "keystone";
|
||||
|
||||
# TLS via cert-manager + Let's Encrypt (HTTP-01).
|
||||
# Requires cert-manager in the cluster. Hosts must resolve publicly for ACME.
|
||||
certManager:
|
||||
enabled: true
|
||||
# Create ClusterIssuer resources from this chart (false = use existing letsencrypt-prod).
|
||||
createClusterIssuer: false
|
||||
createStagingIssuer: true
|
||||
email: "" # required when createClusterIssuer=true
|
||||
issuerName: letsencrypt-prod
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
stagingIssuerName: letsencrypt-staging
|
||||
stagingServer: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
useStaging: false
|
||||
solverIngressClassName: nginx
|
||||
|
||||
seedJobs:
|
||||
# post-install / post-upgrade Jobs; skipIfSql avoids re-seeding when data exists
|
||||
enabled: true
|
||||
backoffLimit: 3
|
||||
ttlSecondsAfterFinished: 600
|
||||
Reference in New Issue
Block a user