Initial Tower chart

This commit is contained in:
git_admin
2026-04-26 18:01:44 +03:00
parent eeca9fe9cf
commit 13a1fcd448
7 changed files with 217 additions and 0 deletions

15
Chart.yaml Normal file
View File

@@ -0,0 +1,15 @@
apiVersion: v2
name: admin-platform-v3
description: |
OdooSky v3 Tower platform — backend API + (eventually) frontend UI.
Tower deploys itself the same way it deploys tenants: forked +
overlaid + reconciled by ArgoCD. Same mechanism, no special-casing.
type: application
version: 0.1.0
appVersion: "0.1.0"
keywords:
- odoosky
- tower
- control-plane
maintainers:
- name: OdooSky platform

6
templates/_helpers.tpl Normal file
View File

@@ -0,0 +1,6 @@
{{- define "tower.labels" -}}
app.kubernetes.io/name: tower
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/version: {{ .Values.backend.image.tag | quote }}
odoosky.io/component: control-plane
{{- end -}}

View File

@@ -0,0 +1,73 @@
{{- if .Values.backend.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: tower-backend
labels:
{{- include "tower.labels" . | nindent 4 }}
odoosky.io/role: backend
spec:
replicas: {{ .Values.backend.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: tower
odoosky.io/role: backend
template:
metadata:
labels:
{{- include "tower.labels" . | nindent 8 }}
odoosky.io/role: backend
spec:
containers:
- name: tower
image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}"
imagePullPolicy: {{ .Values.backend.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
env:
- name: TOWER_LISTEN_ADDR
value: ":8080"
- name: TOWER_GITEA_URL
value: {{ .Values.config.giteaURL | quote }}
- name: TOWER_GITEA_ORG
value: {{ .Values.config.giteaOrg | quote }}
- name: TOWER_CHART_REPO
value: {{ .Values.config.chartRepo | quote }}
- name: TOWER_ARGOCD_URL
value: {{ .Values.config.argoCDURL | quote }}
- name: TOWER_ARGOCD_USERNAME
value: {{ .Values.config.argoCDUsername | quote }}
- name: TOWER_ARGOCD_DESTINATION
value: {{ .Values.config.argoCDDestination | quote }}
- name: TOWER_ARGOCD_PROJECT
value: {{ .Values.config.argoCDProject | quote }}
- name: TOWER_ARGOCD_NAMESPACE
value: {{ .Values.config.argoCDNamespace | quote }}
- name: TOWER_TENANT_NAMESPACE
value: {{ .Values.config.tenantNamespace | quote }}
- name: TOWER_GITEA_TOKEN
valueFrom:
secretKeyRef:
name: {{ .Values.config.existingSecret }}
key: GITEA_TOKEN
- name: TOWER_ARGOCD_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.config.existingSecret }}
key: ARGOCD_PASSWORD
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 2
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 15
resources:
{{- toYaml .Values.backend.resources | nindent 12 }}
{{- end }}

View File

@@ -0,0 +1,17 @@
{{- if .Values.backend.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: tower-backend
labels:
{{- include "tower.labels" . | nindent 4 }}
spec:
selector:
app.kubernetes.io/name: tower
odoosky.io/role: backend
ports:
- name: http
port: 8080
targetPort: 8080
type: ClusterIP
{{- end }}

View File

@@ -0,0 +1,14 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: tower-tls
labels:
{{- include "tower.labels" . | nindent 4 }}
spec:
secretName: tower-tls
issuerRef:
name: {{ .Values.ingress.certIssuer }}
kind: ClusterIssuer
dnsNames:
- {{ .Values.ingress.domain | quote }}
renewBefore: 720h

View File

@@ -0,0 +1,36 @@
# Tower IngressRoute. Routes by path:
# /api/* → backend (8080)
# /* → frontend (when Step 4 builds it; currently a 503 from
# Traefik because backend.frontend.enabled=false)
#
# Once frontend lands, we add a second route block with a Path matcher
# for the `/api` prefix going to backend, and the catch-all for static
# files going to frontend.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: tower
labels:
{{- include "tower.labels" . | nindent 4 }}
spec:
entryPoints:
- {{ .Values.ingress.entryPoint }}
routes:
{{- if .Values.backend.enabled }}
- match: Host(`{{ .Values.ingress.domain }}`)
kind: Rule
services:
- name: tower-backend
port: 8080
{{- end }}
{{- if .Values.frontend.enabled }}
# Frontend slot — enabled when Step 4 builds the UI.
- match: Host(`{{ .Values.ingress.domain }}`) && !PathPrefix(`/api`) && !PathPrefix(`/healthz`) && !PathPrefix(`/instances`)
kind: Rule
priority: 100
services:
- name: tower-frontend
port: 80
{{- end }}
tls:
secretName: tower-tls

56
values.yaml Normal file
View File

@@ -0,0 +1,56 @@
# admin-platform-v3 — Tower platform default values.
backend:
enabled: true
image:
repository: docker.io/odoosky/tower
tag: "0.1.0"
pullPolicy: IfNotPresent # IfNotPresent because the image is in
# containerd's k8s.io namespace already
# (lab1 single-server). Replace with
# Always when we move to a real registry.
replicas: 1
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: "1"
memory: 256Mi
frontend:
# Off until Step 4 builds it. The chart slot is reserved here so
# turning it on later is a values-flip, not a chart edit.
enabled: false
image:
repository: docker.io/odoosky/tower-ui
tag: "0.1.0"
replicas: 1
# Tower needs to talk to:
# - Gitea (create tenant repos, commit values.yaml)
# - ArgoCD (apply Application manifests)
#
# The credentials live in a K8s Secret in the same namespace, populated
# from the ExistingSecret pattern (so they aren't checked into Git).
# In Step 5+ we replace this with External Secrets sourcing from
# OpenBao at vault.odoosky.org.
config:
giteaURL: https://git.odoosky.org
giteaOrg: odoo-tower
chartRepo: instance-template-v3
argoCDURL: https://argocd.odoosky.org
argoCDUsername: admin
argoCDDestination: https://kubernetes.default.svc
argoCDProject: default
argoCDNamespace: argocd
tenantNamespace: tenants
# The Secret name (in the same namespace as Tower) that holds
# GITEA_TOKEN and ARGOCD_PASSWORD keys. Created out-of-band before
# this chart is applied.
existingSecret: tower-credentials
ingress:
domain: tower.odoosky.org
certIssuer: letsencrypt-prod
entryPoint: websecure