Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
453 lines
20 KiB
YAML
453 lines
20 KiB
YAML
{{- if and (not .Values.devEnv.enabled) (or .Values.setup.runMigrations .Values.setup.runSeeds) }}
|
|
apiVersion: batch/v1
|
|
kind: Job
|
|
metadata:
|
|
name: {{ include "sebastian.fullname" . }}-bootstrap
|
|
namespace: {{ include "sebastian.namespace" . }}
|
|
{{- if not .Values.setup.applianceBootstrap.enabled }}
|
|
# SaaS: run as a post-install/upgrade hook. NOT for the appliance — the alga
|
|
# core Deployment's wait-for-bootstrap init blocks readiness until this job
|
|
# creates the `users` table, but a post-install hook only fires AFTER the
|
|
# install succeeds, which can't happen while readiness is blocked. That
|
|
# deadlocks the appliance install, so there it runs as a regular concurrent Job.
|
|
annotations:
|
|
"helm.sh/hook": post-install,post-upgrade
|
|
"helm.sh/hook-weight": "0"
|
|
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
|
{{- end }}
|
|
spec:
|
|
ttlSecondsAfterFinished: 300
|
|
template:
|
|
metadata:
|
|
name: {{ include "sebastian.fullname" . }}-bootstrap
|
|
spec:
|
|
{{- if .Values.setup.image.is_private }}
|
|
imagePullSecrets:
|
|
- name: "{{ .Values.setup.image.credentials }}"
|
|
{{- end }}
|
|
containers:
|
|
- name: bootstrap
|
|
image: "{{ .Values.setup.image.name }}:{{ .Values.setup.image.tag }}"
|
|
imagePullPolicy: {{ .Values.setup.pullPolicy }}
|
|
{{- if .Values.setup.applianceBootstrap.enabled }}
|
|
command: ["/bin/sh", "/bootstrap/appliance-bootstrap.sh"]
|
|
{{- else }}
|
|
command: ["/bin/sh", "-ec"]
|
|
args:
|
|
- |
|
|
log() {
|
|
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1"
|
|
}
|
|
|
|
is_enabled() {
|
|
case "${1:-true}" in
|
|
[Ff][Aa][Ll][Ss][Ee]|0|[Nn][Oo]|[Oo][Ff][Ff])
|
|
return 1
|
|
;;
|
|
*)
|
|
return 0
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_admin_password() {
|
|
local password=""
|
|
|
|
if [ -f /run/secrets/postgres_password ]; then
|
|
password="$(cat /run/secrets/postgres_password 2>/dev/null)"
|
|
fi
|
|
|
|
if [ -z "$password" ] && [ -n "${DB_PASSWORD_ADMIN:-}" ]; then
|
|
password="${DB_PASSWORD_ADMIN}"
|
|
fi
|
|
|
|
if [ -z "$password" ] && [ -n "${DB_PASSWORD_SUPERUSER:-}" ]; then
|
|
password="${DB_PASSWORD_SUPERUSER}"
|
|
fi
|
|
|
|
echo "$password" | tr -d '[:space:]'
|
|
}
|
|
|
|
psql_quiet() {
|
|
local database="$1"
|
|
shift
|
|
local pg_admin_host="${DB_HOST_ADMIN:-${DB_HOST:-postgres}}"
|
|
local pg_admin_port="${DB_PORT_ADMIN:-${DB_PORT:-5432}}"
|
|
local pg_admin_user="${DB_USER_ADMIN:-${DB_USER:-postgres}}"
|
|
local pg_password
|
|
|
|
pg_password="$(get_admin_password)"
|
|
PGPASSWORD="${pg_password}" psql -h "${pg_admin_host}" -p "${pg_admin_port}" -U "${pg_admin_user}" -d "${database}" "$@" 2>&1
|
|
}
|
|
|
|
wait_for_postgres() {
|
|
local pg_admin_host="${DB_HOST_ADMIN:-${DB_HOST:-postgres}}"
|
|
local pg_admin_port="${DB_PORT_ADMIN:-${DB_PORT:-5432}}"
|
|
local pg_admin_user="${DB_USER_ADMIN:-${DB_USER:-postgres}}"
|
|
local pg_password
|
|
local output
|
|
|
|
pg_password="$(get_admin_password)"
|
|
if [ -z "$pg_password" ]; then
|
|
log "ERROR: No admin database password available"
|
|
exit 1
|
|
fi
|
|
|
|
while true; do
|
|
output="$(PGPASSWORD="${pg_password}" psql -h "${pg_admin_host}" -p "${pg_admin_port}" -U "${pg_admin_user}" -d postgres -c '\q' 2>&1)" && break
|
|
|
|
case "$output" in
|
|
*"password authentication failed"*|*"no password supplied"*|*"SASL authentication failed"*|*"role \""* )
|
|
log "ERROR: PostgreSQL authentication failed for ${pg_admin_user} at ${pg_admin_host}:${pg_admin_port}"
|
|
log "ERROR: Existing appliance data may not match the current db-credentials secret. Reuse the original credentials in recover mode or wipe appliance data before a fresh install."
|
|
exit 1
|
|
;;
|
|
*"could not translate host name"*|*"Name or service not known"*|*"Temporary failure in name resolution"* )
|
|
log "ERROR: PostgreSQL DNS resolution failed for ${pg_admin_host}"
|
|
log "ERROR: ${output}"
|
|
exit 1
|
|
;;
|
|
*)
|
|
log "PostgreSQL is unavailable at ${pg_admin_host}:${pg_admin_port} - sleeping"
|
|
;;
|
|
esac
|
|
sleep 1
|
|
done
|
|
|
|
log "PostgreSQL is up and running"
|
|
}
|
|
|
|
database_exists() {
|
|
local database_name="$1"
|
|
psql_quiet postgres -Atqc "SELECT EXISTS (SELECT 1 FROM pg_database WHERE datname='${database_name}');" | grep -q '^t$'
|
|
}
|
|
|
|
users_table_exists() {
|
|
psql_quiet "${DB_NAME_SERVER:-server}" -Atqc "SELECT to_regclass('public.users') IS NOT NULL;" | grep -q '^t$'
|
|
}
|
|
|
|
seed_row_count() {
|
|
psql_quiet "${DB_NAME_SERVER:-server}" -Atqc "SELECT COUNT(*) FROM users;" | tr -d '[:space:]'
|
|
}
|
|
|
|
preflight_database_state() {
|
|
local server_db=false
|
|
local hocuspocus_db=false
|
|
local users_table=false
|
|
local user_count=0
|
|
|
|
if database_exists "${DB_NAME_SERVER:-server}"; then
|
|
server_db=true
|
|
if users_table_exists; then
|
|
users_table=true
|
|
user_count="$(seed_row_count)"
|
|
fi
|
|
fi
|
|
|
|
if database_exists "${DB_NAME_HOCUSPOCUS:-hocuspocus}"; then
|
|
hocuspocus_db=true
|
|
fi
|
|
|
|
log "Database preflight: bootstrap_mode=${BOOTSTRAP_MODE:-recover} server_db=${server_db} hocuspocus_db=${hocuspocus_db} users_table=${users_table} user_count=${user_count}"
|
|
|
|
if [ "${BOOTSTRAP_MODE:-recover}" = "fresh" ] && { [ "$server_db" = "true" ] || [ "$hocuspocus_db" = "true" ] || [ "$user_count" -gt 0 ]; }; then
|
|
log "ERROR: Existing application database state detected while bootstrap.mode=fresh."
|
|
log "ERROR: Wipe persisted appliance data before a fresh install or rerun in recover mode."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_seeds_status() {
|
|
local pg_admin_host="${DB_HOST_ADMIN:-${DB_HOST:-postgres}}"
|
|
local pg_admin_port="${DB_PORT_ADMIN:-${DB_PORT:-5432}}"
|
|
local pg_admin_user="${DB_USER_ADMIN:-${DB_USER:-postgres}}"
|
|
local pg_password
|
|
|
|
pg_password="$(get_admin_password)"
|
|
PGPASSWORD="${pg_password}" psql -h "${pg_admin_host}" -p "${pg_admin_port}" -U "${pg_admin_user}" -d "${DB_NAME_SERVER:-server}" -tAc "SELECT EXISTS (SELECT 1 FROM users LIMIT 1);" 2>/dev/null | grep -q '^t$'
|
|
}
|
|
|
|
wait_for_postgres
|
|
preflight_database_state
|
|
|
|
log "Creating databases and roles"
|
|
timeout 120 node /app/server/setup/create_database.js
|
|
|
|
if is_enabled "${SETUP_RUN_MIGRATIONS:-true}"; then
|
|
pg_admin_host="${DB_HOST_ADMIN:-${DB_HOST:-postgres}}"
|
|
pg_admin_port="${DB_PORT_ADMIN:-${DB_PORT:-5432}}"
|
|
pg_admin_user="${DB_USER_ADMIN:-${DB_USER:-postgres}}"
|
|
|
|
pg_password="$(get_admin_password)"
|
|
|
|
log "Creating pgboss schema"
|
|
PGPASSWORD="${pg_password}" psql -h "${pg_admin_host}" -p "${pg_admin_port}" -U "${pg_admin_user}" -d "${DB_NAME_SERVER:-server}" -c 'CREATE SCHEMA IF NOT EXISTS pgboss;'
|
|
|
|
log "Granting necessary permissions"
|
|
PGPASSWORD="${pg_password}" psql -h "${pg_admin_host}" -p "${pg_admin_port}" -U "${pg_admin_user}" -d "${DB_NAME_SERVER:-server}" -c 'GRANT ALL ON SCHEMA public TO postgres;'
|
|
|
|
log "Running migrations"
|
|
NODE_ENV=migration timeout 300 npx knex migrate:latest --knexfile /app/server/knexfile.cjs --verbose
|
|
else
|
|
log "SETUP_RUN_MIGRATIONS is disabled; skipping migrations"
|
|
fi
|
|
|
|
if is_enabled "${SETUP_RUN_SEEDS:-true}"; then
|
|
if check_seeds_status; then
|
|
log "Seeds already exist; skipping"
|
|
else
|
|
log "Running seeds"
|
|
NODE_ENV=migration timeout 300 npx knex seed:run --knexfile /app/server/knexfile.cjs --verbose
|
|
fi
|
|
else
|
|
log "SETUP_RUN_SEEDS is disabled; skipping seeds"
|
|
fi
|
|
|
|
log "Setup completed"
|
|
{{- end }}
|
|
env:
|
|
- name: APP_NAME
|
|
value: "{{ .Values.nameOverride }}"
|
|
- name: APP_ENV
|
|
value: "{{ .Values.env | default "production" }}"
|
|
- name: NODE_ENV
|
|
value: "{{ .Values.env | default "production" }}"
|
|
- name: EDITION
|
|
value: "{{ .Values.edition | default "community" }}"
|
|
- name: SETUP_RUN_MIGRATIONS
|
|
value: {{ ternary "true" "false" .Values.setup.runMigrations | quote }}
|
|
- name: SETUP_RUN_SEEDS
|
|
value: {{ ternary "true" "false" .Values.setup.runSeeds | quote }}
|
|
- name: BOOTSTRAP_MODE
|
|
value: {{ .Values.bootstrap.mode | default "recover" | quote }}
|
|
- name: BOOTSTRAP_WAIT_TIMEOUT_SECONDS
|
|
value: {{ .Values.setup.applianceBootstrap.waitTimeoutSeconds | default 300 | quote }}
|
|
- name: BOOTSTRAP_WAIT_RETRY_SECONDS
|
|
value: {{ .Values.setup.applianceBootstrap.retryIntervalSeconds | default 2 | quote }}
|
|
- name: BOOTSTRAP_LOCK_TIMEOUT_SECONDS
|
|
value: {{ .Values.setup.applianceBootstrap.lockTimeoutSeconds | default 1800 | quote }}
|
|
- name: BOOTSTRAP_LOCK_STALE_SECONDS
|
|
value: {{ .Values.setup.applianceBootstrap.lockStaleSeconds | default 120 | quote }}
|
|
- name: BOOTSTRAP_LOCK_HEARTBEAT_SECONDS
|
|
value: {{ .Values.setup.applianceBootstrap.lockHeartbeatSeconds | default 10 | quote }}
|
|
{{- if .Values.setup.applianceBootstrap.enabled }}
|
|
- name: SEEDS_DIR
|
|
value: "/app/ee/server/seeds/onboarding"
|
|
{{- end }}
|
|
|
|
# Secret provider configuration for setup jobs
|
|
- name: SECRET_READ_CHAIN
|
|
value: "{{ .Values.secrets_provider.readChain | default "env,filesystem" }}"
|
|
- name: SECRET_WRITE_PROVIDER
|
|
value: "{{ .Values.secrets_provider.writeProvider | default "filesystem" }}"
|
|
{{- if .Values.secrets_provider.envPrefix }}
|
|
- name: SECRET_ENV_PREFIX
|
|
value: "{{ .Values.secrets_provider.envPrefix }}"
|
|
{{- end }}
|
|
|
|
{{- if .Values.setup.applianceBootstrap.enabled }}
|
|
# Appliance bootstrap hashes the initial admin password with PBKDF2
|
|
# peppered by getSecret('nextauth_secret','NEXTAUTH_SECRET'); getSecret
|
|
# consults the env provider FIRST, which looks up the *lowercase*
|
|
# secret name. Bind both names to the shared cluster secret so the
|
|
# bootstrap and the server resolve the identical pepper.
|
|
- name: nextauth_secret
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: "{{ include "sebastian.fullname" . }}-secrets"
|
|
key: NEXTAUTH_SECRET
|
|
- name: NEXTAUTH_SECRET
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: "{{ include "sebastian.fullname" . }}-secrets"
|
|
key: NEXTAUTH_SECRET
|
|
# PBKDF2 params MUST match the server deployment (.Values.crypto),
|
|
# else the bootstrap hashes with the hardcoded defaults (10000/64/
|
|
# 12/sha512) while the server verifies with the configured values --
|
|
# a permanent "Invalid email or password" at first login.
|
|
- name: SALT_BYTES
|
|
value: "{{ .Values.crypto.salt_bytes }}"
|
|
- name: ITERATIONS
|
|
value: "{{ .Values.crypto.iteration }}"
|
|
- name: KEY_LENGTH
|
|
value: "{{ .Values.crypto.key_length }}"
|
|
- name: ALGORITHM
|
|
value: "{{ .Values.crypto.algorithm }}"
|
|
{{- end }}
|
|
|
|
# Vault configuration for setup jobs (only if vault is used)
|
|
{{- if or (contains "vault" .Values.secrets_provider.readChain) (eq .Values.secrets_provider.writeProvider "vault") }}
|
|
{{- if .Values.secrets_provider.vault.addr }}
|
|
- name: VAULT_ADDR
|
|
value: "{{ .Values.secrets_provider.vault.addr }}"
|
|
{{- end }}
|
|
{{- if .Values.secrets_provider.vault.token }}
|
|
- name: VAULT_TOKEN
|
|
value: "{{ .Values.secrets_provider.vault.token }}"
|
|
{{- end }}
|
|
{{- if .Values.secrets_provider.vault.appSecretPath }}
|
|
- name: VAULT_APP_SECRET_PATH
|
|
value: "{{ .Values.secrets_provider.vault.appSecretPath }}"
|
|
{{- end }}
|
|
{{- if .Values.secrets_provider.vault.tenantSecretPathTemplate }}
|
|
- name: VAULT_TENANT_SECRET_PATH_TEMPLATE
|
|
value: "{{ .Values.secrets_provider.vault.tenantSecretPathTemplate }}"
|
|
{{- end }}
|
|
{{- end }}
|
|
|
|
{{- if .Values.db.enabled }}
|
|
- name: DB_TYPE
|
|
value: postgres
|
|
- name: DB_NAME
|
|
value: "postgres"
|
|
- name: DB_HOST
|
|
value: "db.{{ include "sebastian.namespace" . }}.svc.cluster.local"
|
|
- name: DB_HOST_ADMIN
|
|
value: "db.{{ include "sebastian.namespace" . }}.svc.cluster.local"
|
|
- name: DB_PORT
|
|
value: "5432"
|
|
- name: DB_PORT_ADMIN
|
|
value: "5432"
|
|
- name: DB_USER
|
|
value: "postgres"
|
|
- name: DB_PASSWORD_ADMIN
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: db-credentials
|
|
key: DB_PASSWORD_SUPERUSER
|
|
- name: DB_USER_ADMIN
|
|
value: "postgres"
|
|
- name: DB_PASSWORD_SUPERUSER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: db-credentials
|
|
key: DB_PASSWORD_SUPERUSER
|
|
- name: DB_USER_HOCUSPOCUS
|
|
value: "hocuspocus_user"
|
|
- name: DB_NAME_HOCUSPOCUS
|
|
value: "hocuspocus"
|
|
- name: DB_PASSWORD_HOCUSPOCUS
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: db-credentials
|
|
key: DB_PASSWORD_HOCUSPOCUS
|
|
- name: DB_USER_SERVER
|
|
value: "app_user"
|
|
- name: DB_USER_PGBOUNCER
|
|
value: "app_user_pgbouncer"
|
|
- name: DB_NAME_SERVER
|
|
value: "server"
|
|
- name: DB_PASSWORD_SERVER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: db-credentials
|
|
key: DB_PASSWORD_SERVER
|
|
- name: DB_PASSWORD_PGBOUNCER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: db-credentials
|
|
key: DB_PASSWORD_PGBOUNCER
|
|
{{- else }}
|
|
- name: DB_TYPE
|
|
value: "{{ .Values.config.db.type }}"
|
|
- name: DB_HOST
|
|
value: "{{ .Values.config.db.host }}"
|
|
- name: DB_HOST_ADMIN
|
|
value: "{{ .Values.config.db.adminHost | default .Values.config.db.host }}"
|
|
- name: DB_PORT
|
|
value: "{{ .Values.config.db.port }}"
|
|
- name: DB_PORT_ADMIN
|
|
value: "{{ .Values.config.db.adminPort | default .Values.config.db.port }}"
|
|
- name: DB_USER
|
|
value: "{{ .Values.config.db.user }}"
|
|
- name: DB_PASSWORD_ADMIN
|
|
{{- if and .Values.config.db.server_password_admin_secret.name .Values.config.db.server_password_admin_secret.key }}
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Values.config.db.server_password_admin_secret.name | quote }}
|
|
key: {{ .Values.config.db.server_password_admin_secret.key | quote }}
|
|
{{- else }}
|
|
value: {{ .Values.config.db.server_admin_password | quote }}
|
|
{{- end }}
|
|
- name: DB_USER_ADMIN
|
|
value: "{{ .Values.config.db.adminUser | default .Values.config.db.user }}"
|
|
- name: DB_PASSWORD_SUPERUSER
|
|
{{- if and .Values.config.db.server_password_admin_secret.name .Values.config.db.server_password_admin_secret.key }}
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Values.config.db.server_password_admin_secret.name | quote }}
|
|
key: {{ .Values.config.db.server_password_admin_secret.key | quote }}
|
|
{{- else }}
|
|
value: {{ .Values.config.db.server_admin_password | quote }}
|
|
{{- end }}
|
|
- name: DB_USER_HOCUSPOCUS
|
|
value: "{{ .Values.config.db.hocuspocus_user | default "hocuspocus_user" }}"
|
|
- name: DB_NAME_HOCUSPOCUS
|
|
value: "{{ .Values.config.db.hocuspocus_database }}"
|
|
- name: DB_PASSWORD_HOCUSPOCUS
|
|
{{- if .Values.config.db.hocuspocus_password_secret }}
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Values.config.db.hocuspocus_password_secret.name | quote }}
|
|
key: {{ .Values.config.db.hocuspocus_password_secret.key | quote }}
|
|
{{- else }}
|
|
value: {{ .Values.config.db.password | quote }}
|
|
{{- end }}
|
|
- name: DB_USER_SERVER
|
|
value: "{{ .Values.config.db.user }}"
|
|
{{- if .Values.config.db.pgbouncer_user }}
|
|
- name: DB_USER_PGBOUNCER
|
|
value: "{{ .Values.config.db.pgbouncer_user }}"
|
|
{{- end }}
|
|
- name: DB_NAME_SERVER
|
|
value: "{{ .Values.config.db.server_database }}"
|
|
- name: DB_PASSWORD_SERVER
|
|
{{- if and .Values.config.db.server_password_secret.name .Values.config.db.server_password_secret.key }}
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Values.config.db.server_password_secret.name | quote }}
|
|
key: {{ .Values.config.db.server_password_secret.key | quote }}
|
|
{{- else }}
|
|
value: {{ .Values.config.db.server_password | quote }}
|
|
{{- end }}
|
|
{{- if .Values.config.db.pgbouncer_password_secret }}
|
|
- name: DB_PASSWORD_PGBOUNCER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Values.config.db.pgbouncer_password_secret.name | quote }}
|
|
key: {{ .Values.config.db.pgbouncer_password_secret.key | quote }}
|
|
{{- else if .Values.config.db.pgbouncer_password }}
|
|
- name: DB_PASSWORD_PGBOUNCER
|
|
value: {{ .Values.config.db.pgbouncer_password | quote }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{- if .Values.setup.applianceBootstrap.enabled }}
|
|
envFrom:
|
|
- secretRef:
|
|
name: appliance-initial-tenant
|
|
optional: true
|
|
- secretRef:
|
|
name: appliance-license-seed
|
|
optional: true
|
|
volumeMounts:
|
|
- name: appliance-bootstrap
|
|
mountPath: /bootstrap
|
|
readOnly: true
|
|
{{- end }}
|
|
restartPolicy: Never
|
|
{{- if .Values.setup.applianceBootstrap.enabled }}
|
|
volumes:
|
|
- name: appliance-bootstrap
|
|
configMap:
|
|
name: {{ include "sebastian.fullname" . }}-appliance-bootstrap
|
|
defaultMode: 0755
|
|
{{- end }}
|
|
{{- if .Values.setup.applianceBootstrap.enabled }}
|
|
# Appliance: this runs concurrently with db-0 coming up (not a post-install
|
|
# hook), so allow retries while Postgres becomes reachable.
|
|
backoffLimit: 6
|
|
{{- else }}
|
|
backoffLimit: 0
|
|
{{- end }}
|
|
{{- end }}
|