Update my-recipes

This commit is contained in:
dvirlabs 2025-12-05 11:47:17 +02:00
parent dc8d3b3bc3
commit 6900c57033
12 changed files with 418 additions and 46 deletions

View File

@ -1,6 +1,14 @@
apiVersion: v2
name: recipes-db
description: PostgreSQL (StatefulSet) for Recipes backend
name: my-recipes
description: Complete recipe management application with PostgreSQL, FastAPI backend, and React frontend
type: application
version: 0.1.0
appVersion: "16"
version: 1.0.0
appVersion: "1.0.0"
keywords:
- recipes
- fastapi
- react
- postgresql
maintainers:
- name: Development Team

View File

@ -1,26 +1,57 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-backend
name: {{ .Release.Name }}-{{ .Values.backend.name }}
namespace: {{ .Values.global.namespace }}
labels:
app: {{ .Release.Name }}-backend
app: {{ .Release.Name }}-{{ .Values.backend.name }}
component: backend
spec:
replicas: {{ .Values.backend.replicas }}
replicas: {{ .Values.backend.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}-backend
app: {{ .Release.Name }}-{{ .Values.backend.name }}
template:
metadata:
labels:
app: {{ .Release.Name }}-backend
app: {{ .Release.Name }}-{{ .Values.backend.name }}
component: backend
spec:
containers:
- name: backend
- name: {{ .Values.backend.name }}
image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}"
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
ports:
- containerPort: 8000
- containerPort: {{ .Values.backend.service.targetPort }}
name: http
protocol: TCP
env:
- name: PYTHONUNBUFFERED
value: "1"
envFrom:
- secretRef:
name: {{ .Release.Name }}-db-credentials
livenessProbe:
httpGet:
path: /docs
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /docs
port: http
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
resources:
requests:
cpu: {{ .Values.backend.resources.requests.cpu }}
memory: {{ .Values.backend.resources.requests.memory }}
limits:
cpu: {{ .Values.backend.resources.limits.cpu }}
memory: {{ .Values.backend.resources.limits.memory }}

View File

@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-{{ .Values.backend.name }}
namespace: {{ .Values.global.namespace }}
labels:
app: {{ .Release.Name }}-{{ .Values.backend.name }}
component: backend
spec:
type: {{ .Values.backend.service.type }}
ports:
- port: {{ .Values.backend.service.port }}
targetPort: {{ .Values.backend.service.targetPort }}
protocol: TCP
name: http
selector:
app: {{ .Release.Name }}-{{ .Values.backend.name }}

View File

@ -2,6 +2,7 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-db-schema
namespace: {{ .Values.global.namespace }}
data:
schema.sql: |
-- Create recipes table
@ -10,10 +11,10 @@ data:
name TEXT NOT NULL,
meal_type TEXT NOT NULL,
time_minutes INTEGER NOT NULL,
tags JSONB NOT NULL DEFAULT '[]',
ingredients JSONB NOT NULL DEFAULT '[]',
steps JSONB NOT NULL DEFAULT '[]'
steps JSONB NOT NULL DEFAULT '[]',
image TEXT
);
CREATE INDEX IF NOT EXISTS idx_recipes_meal_type
@ -27,3 +28,4 @@ data:
CREATE INDEX IF NOT EXISTS idx_recipes_ingredients_jsonb
ON recipes USING GIN (ingredients);

View File

@ -2,10 +2,12 @@ apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-db-credentials
namespace: {{ .Values.global.namespace }}
type: Opaque
stringData:
DB_HOST: {{ printf "%s-db-headless.%s.svc.cluster.local" .Release.Name .Release.Namespace }}
DB_HOST: {{ printf "%s-%s-headless.%s.svc.cluster.local" .Release.Name .Values.postgres.name .Values.global.namespace }}
DB_PORT: "{{ .Values.postgres.port }}"
DB_NAME: {{ .Values.postgres.database | quote }}
DB_USER: {{ .Values.postgres.user | quote }}
DB_PASSWORD: {{ .Values.postgres.password | quote }}

View File

@ -1,14 +1,36 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-db-headless
name: {{ .Release.Name }}-{{ .Values.postgres.name }}-headless
namespace: {{ .Values.global.namespace }}
labels:
app: {{ .Release.Name }}-db
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
component: database
spec:
clusterIP: None
selector:
app: {{ .Release.Name }}-db
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
ports:
- name: postgres
port: {{ .Values.postgres.port }}
targetPort: 5432
targetPort: {{ .Values.postgres.port }}
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-{{ .Values.postgres.name }}
namespace: {{ .Values.global.namespace }}
labels:
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
component: database
spec:
type: {{ .Values.postgres.service.type }}
selector:
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
ports:
- name: postgres
port: {{ .Values.postgres.service.port }}
targetPort: {{ .Values.postgres.port }}
protocol: TCP

View File

@ -1,26 +1,31 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}-db
name: {{ .Release.Name }}-{{ .Values.postgres.name }}
namespace: {{ .Values.global.namespace }}
labels:
app: {{ .Release.Name }}-db
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
component: database
spec:
serviceName: {{ .Release.Name }}-db-headless
serviceName: {{ .Release.Name }}-{{ .Values.postgres.name }}-headless
replicas: 1
selector:
matchLabels:
app: {{ .Release.Name }}-db
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
template:
metadata:
labels:
app: {{ .Release.Name }}-db
app: {{ .Release.Name }}-{{ .Values.postgres.name }}
component: database
spec:
containers:
- name: postgres
image: {{ .Values.postgres.image }}
image: "{{ .Values.postgres.image.repository }}:{{ .Values.postgres.image.tag }}"
imagePullPolicy: {{ .Values.postgres.image.pullPolicy }}
ports:
- containerPort: 5432
- containerPort: {{ .Values.postgres.port }}
name: postgres
protocol: TCP
env:
- name: POSTGRES_USER
value: {{ .Values.postgres.user | quote }}
@ -28,11 +33,40 @@ spec:
value: {{ .Values.postgres.password | quote }}
- name: POSTGRES_DB
value: {{ .Values.postgres.database | quote }}
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
- name: init-sql
mountPath: /docker-entrypoint-initdb.d
livenessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -U {{ .Values.postgres.user }}
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -U {{ .Values.postgres.user }}
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
resources:
requests:
cpu: {{ .Values.postgres.resources.requests.cpu }}
memory: {{ .Values.postgres.resources.requests.memory }}
limits:
cpu: {{ .Values.postgres.resources.limits.cpu }}
memory: {{ .Values.postgres.resources.limits.memory }}
volumes:
- name: init-sql
configMap:
@ -49,3 +83,4 @@ spec:
{{- if .Values.postgres.persistence.storageClass }}
storageClassName: {{ .Values.postgres.persistence.storageClass | quote }}
{{- end }}

View File

@ -0,0 +1,50 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-{{ .Values.frontend.name }}
namespace: {{ .Values.global.namespace }}
labels:
app: {{ .Release.Name }}-{{ .Values.frontend.name }}
component: frontend
spec:
replicas: {{ .Values.frontend.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}-{{ .Values.frontend.name }}
template:
metadata:
labels:
app: {{ .Release.Name }}-{{ .Values.frontend.name }}
component: frontend
spec:
containers:
- name: {{ .Values.frontend.name }}
image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }}"
imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
ports:
- containerPort: {{ .Values.frontend.service.targetPort }}
name: http
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
resources:
requests:
cpu: {{ .Values.frontend.resources.requests.cpu }}
memory: {{ .Values.frontend.resources.requests.memory }}
limits:
cpu: {{ .Values.frontend.resources.limits.cpu }}
memory: {{ .Values.frontend.resources.limits.memory }}

View File

@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-{{ .Values.frontend.name }}
namespace: {{ .Values.global.namespace }}
labels:
app: {{ .Release.Name }}-{{ .Values.frontend.name }}
component: frontend
spec:
type: {{ .Values.frontend.service.type }}
ports:
- port: {{ .Values.frontend.service.port }}
targetPort: {{ .Values.frontend.service.targetPort }}
protocol: TCP
name: http
selector:
app: {{ .Release.Name }}-{{ .Values.frontend.name }}

View File

@ -0,0 +1,48 @@
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}
namespace: {{ .Values.global.namespace }}
labels:
app: {{ .Release.Name }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
{{- if eq .backend "frontend" }}
name: {{ .Release.Name }}-{{ $.Values.frontend.name }}
port:
number: {{ $.Values.frontend.service.port }}
{{- else if eq .backend "backend" }}
name: {{ .Release.Name }}-{{ $.Values.backend.name }}
port:
number: {{ $.Values.backend.service.port }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -1,28 +1,103 @@
# Backend image
global:
namespace: default
imagePullSecrets: []
# Backend configuration
backend:
name: backend
replicaCount: 2
image:
repository: harbor.dvirlabs.com/my-apps/my-recipes-backend
tag: v1.0.0
pullPolicy: IfNotPresent
replicas: 1
tag: "latest"
service:
type: ClusterIP
port: 8000
targetPort: 8000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
env:
PYTHONUNBUFFERED: "1"
# Frontend image
# Frontend configuration
frontend:
name: frontend
replicaCount: 2
image:
repository: harbor.dvirlabs.com/my-apps/my-recipes/frontend
tag: v1.0.0
repository: harbor.dvirlabs.com/my-apps/my-recipes-frontend
pullPolicy: IfNotPresent
replicas: 1
tag: "latest"
service:
type: ClusterIP
port: 3000
targetPort: 3000
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 256Mi
# Postgres DB
# PostgreSQL configuration
postgres:
image: postgres:16
name: db
image:
repository: postgres
tag: "16-alpine"
pullPolicy: IfNotPresent
user: recipes_user
password: recipes_password # POC only later use Secret/ExternalSecret
password: recipes_password
database: recipes_db
port: 5432
service:
type: ClusterIP
port: 5432
targetPort: 5432
persistence:
enabled: true
accessMode: ReadWriteOnce
storageClass: "nfs-client"
size: 8Gi
size: 10Gi
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
# Ingress configuration
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: recipes.local
paths:
- path: /
pathType: Prefix
backend: frontend
- path: /api
pathType: Prefix
backend: backend
tls:
- secretName: recipes-tls
hosts:
- recipes.local

View File

@ -1,28 +1,93 @@
# Backend image
global:
namespace: default
imagePullSecrets: []
# Backend configuration
backend:
name: backend
replicaCount: 1
image:
repository: harbor.dvirlabs.com/my-apps/my-recipes-backend
tag: master-35e1584
pullPolicy: IfNotPresent
replicas: 1
tag: master-3afc7d2
# Frontend image
tag: "master-35e1584"
service:
type: ClusterIP
port: 8000
targetPort: 8000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
env:
PYTHONUNBUFFERED: "1"
# Frontend configuration
frontend:
name: frontend
replicaCount: 1
image:
repository: registry.dvirlabs.com/my-apps/my-recipes-frontend
tag: v1.0.0
pullPolicy: IfNotPresent
replicas: 1
tag: master-56d00c2
# Postgres DB
tag: "v1.0.0"
service:
type: ClusterIP
port: 3000
targetPort: 3000
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 256Mi
# PostgreSQL configuration
postgres:
image: postgres:16
name: db
image:
repository: postgres
tag: "16"
pullPolicy: IfNotPresent
user: recipes_user
password: recipes_password # POC only later use Secret/ExternalSecret
database: recipes_db
port: 5432
service:
type: ClusterIP
port: 5432
targetPort: 5432
persistence:
enabled: true
accessMode: ReadWriteOnce
storageClass: "nfs-client"
size: 8Gi
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
# Ingress (keep defaults in chart if you prefer not to expose)
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: recipes.local
paths:
- path: /
pathType: Prefix
backend: frontend
- path: /api
pathType: Prefix
backend: backend
tls:
- secretName: recipes-tls
hosts:
- recipes.local