Initial release of the oVirt/RHV Engine API simulator.

Stateful FastAPI lab with contract packs, Compose/Helm, Docker Hub release
targets, and Pulumi coverage across all Engine series (GET/POST/PUT/DELETE/HEAD).
This commit is contained in:
Sergey Antropoff
2026-07-18 04:49:28 +03:00
commit 194d7015e5
218 changed files with 246804 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
apiVersion: v2
name: ovirt-api-simulator
description: Stateful oVirt Engine API simulator
type: application
version: 0.1.0
appVersion: "0.1.0"
+22
View File
@@ -0,0 +1,22 @@
**Language / Язык:** [English](README.md) | [Русский](README.ru.md)
# Helm chart: ovirt-api-simulator
Installs the simulator Deployment (port `8080`), optional bundled PostgreSQL,
migrate initContainer, and optional seed Job.
```bash
helm upgrade --install ovirt-sim . \
-n ovirt-sim --create-namespace \
--set image.repository=inecs/ovirt-api-simulator \
--set image.tag=0.1.0 \
--set config.ovirtSeries=4.5 \
--set seed.profile=minimal \
--set secrets.ticketSigningKey="$(openssl rand -hex 32)"
```
Access via port-forward to Service `:8080` (Engine API, SSO, Web UI, `/docs`).
The Compose nginx gateway is **not** part of this chart yet.
Full guide: [docs/kubernetes.md](../../docs/kubernetes.md).
Values: [`values.yaml`](values.yaml).
+22
View File
@@ -0,0 +1,22 @@
**Language / Язык:** [English](README.md) | [Русский](README.ru.md)
# Helm-чарт: ovirt-api-simulator
Ставит Deployment симулятора (порт `8080`), опциональный PostgreSQL,
initContainer migrate и опциональный seed Job.
```bash
helm upgrade --install ovirt-sim . \
-n ovirt-sim --create-namespace \
--set image.repository=inecs/ovirt-api-simulator \
--set image.tag=0.1.0 \
--set config.ovirtSeries=4.5 \
--set seed.profile=minimal \
--set secrets.ticketSigningKey="$(openssl rand -hex 32)"
```
Доступ через port-forward к Service `:8080` (Engine API, SSO, Web UI, `/docs`).
Nginx gateway из Compose в этот чарт **пока не** входит.
Полное руководство: [docs/ru/kubernetes.md](../../docs/ru/kubernetes.md).
Values: [`values.yaml`](values.yaml).
@@ -0,0 +1,13 @@
oVirt Engine API Simulator installed.
Simulator Service: port {{ .Values.service.port }} ({{ .Values.service.type }})
Engine API: http://<svc>:{{ .Values.service.port }}/ovirt-engine/api
SSO token: POST /ovirt-engine/sso/oauth/token
Web UI: http://<svc>:{{ .Values.service.port }}/
OpenAPI: http://<svc>:{{ .Values.service.port }}/docs
Credentials: admin@internal / secret
Series: {{ .Values.config.ovirtSeries }}
Note: Compose publishes Engine HTTPS (:443) + UI (:5000) via nginx gateway.
This chart exposes the FastAPI app directly on :{{ .Values.service.port }}.
@@ -0,0 +1,16 @@
{{- define "ovirt-api-simulator.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "ovirt-api-simulator.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 -}}
@@ -0,0 +1,51 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "ovirt-api-simulator.fullname" . }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ include "ovirt-api-simulator.name" . }}
template:
metadata:
labels:
app: {{ include "ovirt-api-simulator.name" . }}
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
initContainers:
{{- if .Values.migrate.enabled }}
- name: migrate
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ["python", "-m", "app.db.migrate_cli"]
envFrom:
- secretRef:
name: {{ include "ovirt-api-simulator.fullname" . }}-secret
{{- end }}
containers:
- name: simulator
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 8080
env:
- name: OVIRT_SERIES
value: {{ .Values.config.ovirtSeries | quote }}
- name: LOG_LEVEL
value: {{ .Values.config.logLevel | quote }}
envFrom:
- secretRef:
name: {{ include "ovirt-api-simulator.fullname" . }}-secret
livenessProbe:
httpGet:
path: /health/live
port: 8080
readinessProbe:
httpGet:
path: /health/ready
port: 8080
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
@@ -0,0 +1,50 @@
{{- if .Values.postgresql.enabled }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "ovirt-api-simulator.fullname" . }}-postgresql
spec:
serviceName: {{ include "ovirt-api-simulator.fullname" . }}-postgresql
replicas: 1
selector:
matchLabels:
app: {{ include "ovirt-api-simulator.name" . }}-postgresql
template:
metadata:
labels:
app: {{ include "ovirt-api-simulator.name" . }}-postgresql
spec:
containers:
- name: postgres
image: postgres:17.5-bookworm
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: {{ .Values.postgresql.auth.database | quote }}
- name: POSTGRES_USER
value: {{ .Values.postgresql.auth.username | quote }}
- name: POSTGRES_PASSWORD
value: {{ .Values.postgresql.auth.password | quote }}
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: {{ .Values.postgresql.persistence.size }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "ovirt-api-simulator.fullname" . }}-postgresql
spec:
selector:
app: {{ include "ovirt-api-simulator.name" . }}-postgresql
ports:
- port: 5432
{{- end }}
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ include "ovirt-api-simulator.fullname" . }}-secret
type: Opaque
stringData:
{{- if .Values.postgresql.enabled }}
DATABASE_URL: "postgresql://{{ .Values.postgresql.auth.username }}:{{ .Values.postgresql.auth.password }}@{{ include "ovirt-api-simulator.fullname" . }}-postgresql:5432/{{ .Values.postgresql.auth.database }}"
{{- else }}
DATABASE_URL: {{ required "databaseUrl is required when postgresql.enabled=false" .Values.databaseUrl | quote }}
{{- end }}
TICKET_SIGNING_KEY: {{ .Values.secrets.ticketSigningKey | quote }}
@@ -0,0 +1,20 @@
{{- if .Values.seed.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "ovirt-api-simulator.fullname" . }}-seed
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: seed
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ["python", "-m", "app.ovirt.seed_cli", "--profile", "{{ .Values.seed.profile }}"]
envFrom:
- secretRef:
name: {{ include "ovirt-api-simulator.fullname" . }}-secret
{{- end }}
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "ovirt-api-simulator.fullname" . }}
spec:
type: {{ .Values.service.type }}
selector:
app: {{ include "ovirt-api-simulator.name" . }}
ports:
- name: http
port: {{ .Values.service.port }}
targetPort: 8080
+53
View File
@@ -0,0 +1,53 @@
image:
repository: inecs/ovirt-api-simulator
tag: "0.1.0"
pullPolicy: IfNotPresent
replicaCount: 1
service:
type: ClusterIP
port: 8080
gateway:
enabled: true
ports:
http: 80
https: 443
httpsAlt: 8443
console: 5000
ingress:
enabled: false
className: nginx
hosts:
- host: ovirt-engine.local
paths:
- path: /
pathType: Prefix
config:
ovirtSeries: "4.5"
logLevel: INFO
# Required when postgresql.enabled=false (external Postgres DSN).
databaseUrl: ""
postgresql:
enabled: true
auth:
username: ovirt
password: ovirt
database: ovirt_simulator
persistence:
size: 10Gi
migrate:
enabled: true
seed:
enabled: true
profile: minimal
secrets:
ticketSigningKey: development-only-signing-key-change-me