feat: Add PostgreSQL support for Gitea installer

- Add PostgreSQL configuration options
- Generate PostgreSQL YAML when selected
- Verify PostgreSQL pod readiness
- Update documentation for PostgreSQL usage
- Add PostgreSQL service and pod definitions
This commit is contained in:
Mahmoud-Emad
2025-11-03 17:04:40 +02:00
parent 472e4bfaaa
commit bafc519cd7
6 changed files with 203 additions and 7 deletions

View File

@@ -19,9 +19,19 @@ mut installer := gitea.get(
// // Gitea server configuration
// installer.http_port = 3000 // Default: 3000
// installer.disable_registration = false // Default: false (allow new user registration)
// installer.db_type = 'sqlite3' // Default: 'sqlite3' (can be 'postgres', 'mysql')
// // Database configuration - Option 1: SQLite (default)
// installer.db_type = 'sqlite3' // Default: 'sqlite3'
// installer.db_path = '/data/gitea/gitea.db' // Default: '/data/gitea/gitea.db'
// installer.storage_size = '5Gi' // Default: '5Gi' (PVC storage size)
// // Database configuration - Option 2: PostgreSQL
// // When using postgres, a PostgreSQL pod will be automatically deployed
installer.db_type = 'postgres' // Use PostgreSQL instead of SQLite
installer.db_host = 'postgres' // Default: 'postgres' (PostgreSQL service name)
installer.db_name = 'gitea' // Default: 'gitea' (database name)
installer.db_user = 'gitea' // Default: 'gitea' (database user)
installer.db_password = 'gitea' // Default: 'gitea' (database password)
installer.storage_size = '5Gi' // Default: '5Gi' (PVC storage size)
// 3. Install Gitea.
// This will generate the necessary Kubernetes YAML files and apply them to your cluster.

View File

@@ -43,8 +43,14 @@ installer.namespace = 'forge' // Default: '${installer.name}-gitea-namespa
installer.http_port = 3000 // Default: 3000
// Database configuration
installer.db_type = 'sqlite3' // Default: 'sqlite3' (options: 'sqlite3', 'postgres', 'mysql')
installer.db_path = '/data/gitea/gitea.db' // Default: '/data/gitea/gitea.db'
installer.db_type = 'sqlite3' // Default: 'sqlite3' (options: 'sqlite3', 'postgres')
installer.db_path = '/data/gitea/gitea.db' // Default: '/data/gitea/gitea.db' (for sqlite3)
// PostgreSQL configuration (only used when db_type = 'postgres')
installer.db_host = 'postgres' // Default: 'postgres' (PostgreSQL service name)
installer.db_name = 'gitea' // Default: 'gitea' (PostgreSQL database name)
installer.db_user = 'gitea' // Default: 'gitea' (PostgreSQL user)
installer.db_password = 'gitea' // Default: 'gitea' (PostgreSQL password)
// Registration
installer.disable_registration = false // Default: false (allow new user registration)
@@ -53,6 +59,8 @@ installer.disable_registration = false // Default: false (allow new user regist
installer.storage_size = '5Gi' // Default: '5Gi' (PVC storage size)
```
**Note**: When using `db_type = 'postgres'`, a PostgreSQL pod will be automatically deployed in the same namespace. The installer only supports `sqlite3` and `postgres` database types.
## Full Example
```v
@@ -79,6 +87,34 @@ installer.install()!
println('Gitea: https://${installer.hostname}.gent01.grid.tf')
```
## PostgreSQL Example
To use PostgreSQL instead of SQLite:
```v
import incubaid.herolib.installers.k8s.gitea
mut installer := gitea.get(
name: 'mygitea'
create: true
)!
// Configure to use PostgreSQL
installer.db_type = 'postgres' // Use PostgreSQL
installer.storage_size = '10Gi' // Storage for both Gitea and PostgreSQL
// Optional: customize PostgreSQL settings
installer.db_host = 'postgres' // PostgreSQL service name
installer.db_name = 'gitea' // Database name
installer.db_user = 'gitea' // Database user
installer.db_password = 'securepassword' // Database password
// Install (PostgreSQL pod will be deployed automatically)
installer.install()!
println('Gitea with PostgreSQL: https://${installer.hostname}.gent01.grid.tf')
```
## Management
### Check Installation Status

View File

@@ -69,7 +69,20 @@ fn install() ! {
// 3. Verify TFGW deployment
verify_tfgw_deployment(tfgw_name: 'gitea', namespace: installer.namespace)!
// 4. Apply Gitea App YAML
// 4. Apply PostgreSQL YAML if postgres is selected
if installer.db_type == 'postgres' {
console.print_info('Applying PostgreSQL YAML file to the cluster...')
res_postgres := k8s.apply_yaml('/tmp/gitea/postgres.yaml')!
if !res_postgres.success {
return error('Failed to apply postgres.yaml: ${res_postgres.stderr}')
}
console.print_info('PostgreSQL YAML file applied successfully.')
// Verify PostgreSQL pod is ready
verify_postgres_pod(namespace: installer.namespace)!
}
// 5. Apply Gitea App YAML
console.print_info('Applying Gitea App YAML file to the cluster...')
res2 := k8s.apply_yaml('/tmp/gitea/gitea.yaml')!
if !res2.success {
@@ -77,7 +90,7 @@ fn install() ! {
}
console.print_info('Gitea App YAML file applied successfully.')
// 5. Verify deployment status
// 6. Verify deployment status
console.print_info('Verifying deployment status...')
mut is_running := false
for i in 0 .. max_deployment_retries {
@@ -105,6 +118,45 @@ pub mut:
namespace string // namespace name for gitea deployments/services
}
// params for verifying postgres pod is ready
@[params]
struct VerifyPostgresPod {
pub mut:
namespace string // namespace name for postgres pod
}
// Function for verifying postgres pod is ready
fn verify_postgres_pod(args VerifyPostgresPod) ! {
console.print_info('Verifying PostgreSQL pod is ready...')
installer := get()!
mut k8s := installer.kube_client
mut is_ready := false
for i in 0 .. max_deployment_retries {
// Check if postgres pod exists and is running
result := k8s.kubectl_exec(
command: 'get pod ${installer.db_host} -n ${args.namespace} -o jsonpath="{.status.phase}"'
) or {
console.print_info('Waiting for PostgreSQL pod to be created... (${i + 1}/${max_deployment_retries})')
time.sleep(deployment_check_interval_seconds * time.second)
continue
}
if result.success && result.stdout == 'Running' {
is_ready = true
break
}
console.print_info('Waiting for PostgreSQL pod to be ready... (${i + 1}/${max_deployment_retries})')
time.sleep(deployment_check_interval_seconds * time.second)
}
if !is_ready {
console.print_stderr('PostgreSQL pod failed to become ready.')
return error('PostgreSQL pod failed to become ready.')
}
console.print_info('PostgreSQL pod is ready.')
}
// Function for verifying the generating of of the FQDN using tfgw crd
fn verify_tfgw_deployment(args VerifyTfgwDeployment) ! {
console.print_info('Verifying TFGW deployment for ${args.tfgw_name}...')

View File

@@ -22,6 +22,11 @@ pub mut:
db_type string // Database type (sqlite3, postgres, mysql)
db_path string // Database path for SQLite
storage_size string // PVC storage size
// Postgres-specific settings
db_host string // Database host (for postgres)
db_name string // Database name (for postgres)
db_user string // Database user (for postgres)
db_password string // Database password (for postgres)
}
@[heap]
@@ -38,9 +43,15 @@ pub mut:
db_type string = 'sqlite3'
db_path string = '/data/gitea/gitea.db'
storage_size string = '5Gi'
// PostgreSQL configuration (only used when db_type = 'postgres')
db_host string = 'postgres' // PostgreSQL host (service name)
db_name string = 'gitea' // PostgreSQL database name
db_user string = 'gitea' // PostgreSQL user
db_password string = 'gitea' // PostgreSQL password
// Internal paths
gitea_app_path string = '/tmp/gitea/gitea.yaml'
tfgw_path string = '/tmp/gitea/tfgw-gitea.yaml'
postgres_path string = '/tmp/gitea/postgres.yaml'
kube_client kubernetes.KubeClient @[skip]
}
@@ -58,7 +69,7 @@ fn obj_init(mycfg_ GiteaK8SInstaller) !GiteaK8SInstaller {
mycfg.name = mycfg.name.replace('.', '')
if mycfg.namespace == '' {
mycfg.namespace = '${mycfg.name}gitea-namespace'
mycfg.namespace = '${mycfg.name}-gitea-namespace'
}
if mycfg.namespace.contains('_') || mycfg.namespace.contains('.') {
@@ -70,6 +81,12 @@ fn obj_init(mycfg_ GiteaK8SInstaller) !GiteaK8SInstaller {
mycfg.hostname = '${mycfg.name}giteaapp'
}
// Validate database type
if mycfg.db_type !in ['sqlite3', 'postgres'] {
console.print_stderr('Only sqlite3 and postgres databases are supported. Got: ${mycfg.db_type}')
return error('Unsupported database type: ${mycfg.db_type}. Only sqlite3 and postgres are supported.')
}
mycfg.kube_client = kubernetes.get(create: true)!
mycfg.kube_client.config.namespace = mycfg.namespace
return mycfg
@@ -104,6 +121,11 @@ fn configure() ! {
db_type: installer.db_type
db_path: installer.db_path
storage_size: installer.storage_size
// Postgres connection details (use full DNS name for service)
db_host: '${installer.db_host}.${installer.namespace}.svc.cluster.local'
db_name: installer.db_name
db_user: installer.db_user
db_password: installer.db_password
}
// Ensure the output directory exists
@@ -123,6 +145,14 @@ fn configure() ! {
mut gitea_app_path := pathlib.get_file(path: installer.gitea_app_path, create: true)!
gitea_app_path.write(gitea_app_yaml)!
// Generate postgres YAML if postgres is selected
if installer.db_type == 'postgres' {
postgres_yaml := $tmpl('./templates/postgres.yaml')
mut postgres_path := pathlib.get_file(path: installer.postgres_path, create: true)!
postgres_path.write(postgres_yaml)!
console.print_info('PostgreSQL configuration file generated.')
}
console.print_info('Configuration files generated successfully.')
}

View File

@@ -47,8 +47,20 @@ spec:
value: "false"
- name: GITEA__database__DB_TYPE
value: "@{config_values.db_type}"
@if config_values.db_type == 'sqlite3'
- name: GITEA__database__PATH
value: "@{config_values.db_path}"
@end
@if config_values.db_type == 'postgres'
- name: GITEA__database__HOST
value: "@{config_values.db_host}"
- name: GITEA__database__NAME
value: "@{config_values.db_name}"
- name: GITEA__database__USER
value: "@{config_values.db_user}"
- name: GITEA__database__PASSWD
value: "@{config_values.db_password}"
@end
- name: GITEA__service__DISABLE_REGISTRATION
value: "@{config_values.disable_registration}"
volumeMounts:

View File

@@ -0,0 +1,56 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
namespace: @{config_values.namespace}
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: @{config_values.storage_size}
---
apiVersion: v1
kind: Pod
metadata:
name: @{config_values.db_host}
namespace: @{config_values.namespace}
labels:
app: @{config_values.db_host}
spec:
containers:
- name: postgres
image: postgres:16-alpine
env:
- name: POSTGRES_DB
value: @{config_values.db_name}
- name: POSTGRES_USER
value: @{config_values.db_user}
- name: POSTGRES_PASSWORD
value: @{config_values.db_password}
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
ports:
- containerPort: 5432
name: postgres
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-data
---
apiVersion: v1
kind: Service
metadata:
name: @{config_values.db_host}
namespace: @{config_values.namespace}
spec:
selector:
app: @{config_values.db_host}
ports:
- port: 5432
targetPort: 5432
name: postgres
type: ClusterIP