feat: provisionar cliente acme (silo completo via GitOps)
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# Silo "demo" — isolamento do tenant (namespace + quota + limites + rede)
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: acme-prod
|
||||
labels:
|
||||
name: acme-prod
|
||||
tenant: acme
|
||||
athleticmap.io/tier: pilot
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ResourceQuota
|
||||
metadata:
|
||||
name: tenant-quota
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
hard:
|
||||
requests.cpu: "2"
|
||||
requests.memory: 2Gi
|
||||
limits.cpu: "4"
|
||||
limits.memory: 6Gi
|
||||
pods: "20"
|
||||
persistentvolumeclaims: "4"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: LimitRange
|
||||
metadata:
|
||||
name: defaults
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
limits:
|
||||
- type: Container
|
||||
default:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
defaultRequest:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: deny-cross-tenant
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes: [Ingress, Egress]
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector: {}
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: kube-system
|
||||
egress:
|
||||
- to: # intra-namespace (pods) + ClusterIPs (VIP de service, pre-DNAT)
|
||||
- podSelector: {}
|
||||
- ipBlock: { cidr: 10.43.0.0/16 }
|
||||
- to: # DNS (CoreDNS em kube-system)
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: kube-system
|
||||
ports:
|
||||
- { protocol: UDP, port: 53 }
|
||||
- { protocol: TCP, port: 53 }
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
apiVersion: bitnami.com/v1alpha1
|
||||
kind: SealedSecret
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: db-credentials
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
encryptedData:
|
||||
password: AgBFRogG+gGWgmRSXwsb3PfXhORsSoHGN0nREc98Q4KmoP0f2l9pgN9sDsX0sXNU/x4LG6eSoC6gXArU1dRplw6MkijPtWfhXWDQE7hCmhVDhBp/F+3jqDjzX0Z/1q7e8yopZuqZH3uIIagQ/SMlBCzHsm6ZOW43LoWGvrHCX94QCL3ZzuTX7t1UtO5SbRj/ooUMLDC33LqSrDvH+aAEJMEQimOYT8gbE1W1CN1VYR2A2Rac8lOUyqIFUMwEuyMvws98UEAEecilQRlmGGQJj2ORgYjFQRZCF0jDXbLYJmUxnPVAA3un3tfgABLg/S6KU/fqvIazk+OCknwXmZyQdB35lJcXxMNPuMYQ0mIdaSCDTpuZzUIF/6cdijjB+FvNMdEjTlSLcHlkQT3ABemyCpCrA00Otg+wVle0RGvhaj/2fsEYe28hNc72QO2IL53Ggboraho0BiIaxcnwVovHXno+URO4HmQsg0iecfhS09trXOMPYTf+Ire0NLSGE06kZqvRnqtBWpQYbr0r4rRV5rdF7pRGIgl09txMQ5VCKdUgoufGgQMGOquVWIUnViHTBU63vnGsOeaAr0A8bt2jQ0k4AaG3NmoPP5ROgw5U4y8ddQ9J5p1yd0RkeZ8d3605vnPXEzNRSmLhaBpT6EHg5nwQ/1vpPt4Bnjuk5CKUY1q4aSDJAzRfPfful8/LJzAAINji0e9cdKMn4Mt0bAS9P1MMCHFsOLRLdFGIUO9lBvME6A==
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: db-credentials
|
||||
namespace: acme-prod
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
apiVersion: bitnami.com/v1alpha1
|
||||
kind: SealedSecret
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: keycloak-admin
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
encryptedData:
|
||||
password: AgCD4+27tP4eujj+4aruY5qQy7JVfahQBasYRh5uz/PdYbRathBDGl5scygR0Zf+hg5Qaoem7VRO1ilBE3Uzjm/EvS2iD/pLasQP1n6ZJYgX91+HQnbORNjrTAKuZ/Jk/rzz3mcADdNl3LwEYy71iKELlmlV8zSmDgpzT8U6AkdoUc1xPErpzBch9ChpVnyTcnXz2rb8ni1zjzrG42p6lf42U9glTy/YvztouZiGggJahTPC5ChcHpWcj+1ILFt8/Lbovrv+8vODXzBg3Jt3Oe+CB0bUSVbSrMudCeFu+raBbfGiUZnpT6pBa4j8rjHL5qFmxxtjfHgNcrhJIi6b3KFt4yLRCM8c24wg29rKSRb8hTV2tLGuao4uAT9HxVW3x29hzgR+Lvj4yRGpKf7rzGJKkSF+dHrAbcaYTIWnYeMGGFKnT1edWFAB2JimDrnmjRJF8eGca/2JVL9P+mvElJetcVMbNd36310fE0Fu36Xlr/CK3gNGWCepsBdmIy7A38UlT7MArJ83bJXrKSFA0qdwZQ/oHB2WE3so/9YfPwJ8MNqv2ROf/MYRjlvL3Yx1K3GxzmR+L7nrEf/KrhsZOibVt81rHdtoH1/VZ/AeH3V2kYp9HPZi/yq1KrlzTuQWvL7mQrXqMC7GnNSzaD2fcTp0LGjshfJdzsIXW9mo5lBarWt6QW5VrR0vf74kHUGwPnS8CK5qVz8OufFHf1faN7q0qrVVjWrU46I=
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: keycloak-admin
|
||||
namespace: acme-prod
|
||||
@@ -0,0 +1,83 @@
|
||||
# PostgreSQL dedicado do tenant demo (banco da aplicação + banco do Keycloak)
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: pg-initdb
|
||||
namespace: acme-prod
|
||||
data:
|
||||
01-keycloak.sql: |
|
||||
CREATE DATABASE keycloak;
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: postgres-data
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
accessModes: [ReadWriteOnce]
|
||||
storageClassName: local-path
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: postgres
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:16
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
env:
|
||||
- name: POSTGRES_DB
|
||||
value: athleticmap
|
||||
- name: POSTGRES_USER
|
||||
value: atm
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: db-credentials
|
||||
key: password
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
- name: initdb
|
||||
mountPath: /docker-entrypoint-initdb.d
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["pg_isready", "-U", "atm", "-d", "athleticmap"]
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: postgres-data
|
||||
- name: initdb
|
||||
configMap:
|
||||
name: pg-initdb
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: postgres
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
selector:
|
||||
app: postgres
|
||||
ports:
|
||||
- port: 5432
|
||||
targetPort: 5432
|
||||
@@ -0,0 +1,86 @@
|
||||
# Keycloak dedicado do tenant demo (IdP do silo) — modo dev, persistindo no Postgres
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: keycloak
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: keycloak
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: keycloak
|
||||
spec:
|
||||
containers:
|
||||
- name: keycloak
|
||||
image: quay.io/keycloak/keycloak:26.0
|
||||
args: ["start-dev", "--import-realm"]
|
||||
env:
|
||||
- name: KC_DB
|
||||
value: postgres
|
||||
- name: KC_DB_URL
|
||||
value: "jdbc:postgresql://postgres:5432/keycloak"
|
||||
- name: KC_DB_USERNAME
|
||||
value: atm
|
||||
- name: KC_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: db-credentials
|
||||
key: password
|
||||
- name: KC_BOOTSTRAP_ADMIN_USERNAME
|
||||
value: admin
|
||||
- name: KC_BOOTSTRAP_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: keycloak-admin
|
||||
key: password
|
||||
- name: KC_HEALTH_ENABLED
|
||||
value: "true"
|
||||
- name: KC_HTTP_ENABLED
|
||||
value: "true"
|
||||
- name: KC_PROXY_HEADERS
|
||||
value: xforwarded
|
||||
- name: KC_HOSTNAME
|
||||
value: "auth-acme.athleticmap.influxdigital.com.br"
|
||||
- name: KC_HOSTNAME_STRICT
|
||||
value: "true"
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
- containerPort: 9000
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 1Gi
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health/ready
|
||||
port: 9000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
failureThreshold: 40
|
||||
volumeMounts:
|
||||
- name: realm-import
|
||||
mountPath: /opt/keycloak/data/import
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: realm-import
|
||||
configMap:
|
||||
name: kc-realm-import
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: keycloak
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
selector:
|
||||
app: keycloak
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
@@ -0,0 +1,150 @@
|
||||
# Apps do tenant demo:
|
||||
# - backend: Spring Boot OAuth2 Resource Server (imagem athletic-map-backend:1.2, porta 8083)
|
||||
# - frontend: SPA OIDC Authorization Code + PKCE (keycloak-js) chamando /api/me
|
||||
# - bff: stub (whoami)
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata: { name: backend, namespace: acme-prod }
|
||||
spec:
|
||||
replicas: 1
|
||||
selector: { matchLabels: { app: backend } }
|
||||
template:
|
||||
metadata: { labels: { app: backend } }
|
||||
spec:
|
||||
containers:
|
||||
- name: backend
|
||||
image: docker.io/library/athletic-map-backend:1.2
|
||||
imagePullPolicy: Never
|
||||
env:
|
||||
- { name: ATM_JWK_SET_URI, value: "http://keycloak:8080/realms/athleticmap/protocol/openid-connect/certs" }
|
||||
- { name: ATM_ISSUER, value: "https://auth-acme.athleticmap.influxdigital.com.br/realms/athleticmap" }
|
||||
- { name: ATM_TENANT, value: "acme" }
|
||||
ports: [{ containerPort: 8083 }]
|
||||
readinessProbe:
|
||||
httpGet: { path: /api/public/health, port: 8083 }
|
||||
initialDelaySeconds: 20
|
||||
periodSeconds: 10
|
||||
failureThreshold: 24
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata: { name: backend, namespace: acme-prod }
|
||||
spec:
|
||||
selector: { app: backend }
|
||||
ports: [{ port: 80, targetPort: 8083 }]
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata: { name: bff, namespace: acme-prod }
|
||||
spec:
|
||||
replicas: 1
|
||||
selector: { matchLabels: { app: bff } }
|
||||
template:
|
||||
metadata: { labels: { app: bff } }
|
||||
spec:
|
||||
containers:
|
||||
- name: whoami
|
||||
image: traefik/whoami:latest
|
||||
args: ["--name", "athletic-map-bff acme (stub)"]
|
||||
ports: [{ containerPort: 80 }]
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata: { name: bff, namespace: acme-prod }
|
||||
spec:
|
||||
selector: { app: bff }
|
||||
ports: [{ port: 80, targetPort: 80 }]
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata: { name: frontend-index, namespace: acme-prod }
|
||||
data:
|
||||
index.html: |
|
||||
<!doctype html>
|
||||
<html lang="pt-br"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Athletic Map — Acme</title>
|
||||
<script src="https://auth-acme.athleticmap.influxdigital.com.br/js/keycloak.js"></script>
|
||||
<style>
|
||||
body{font-family:system-ui,sans-serif;background:#155eef;color:#eaf2ff;margin:0;padding:2rem}
|
||||
.card{max-width:760px;margin:2rem auto;background:#0e2f57;border-top:4px solid #ffd23f;border-radius:12px;padding:2rem;box-shadow:0 12px 40px rgba(0,0,0,.4)}
|
||||
h1{color:#ffd23f;margin:0 0 .3rem}.muted{color:#bcd3f5}b{color:#fff}
|
||||
pre{background:#06182e;padding:1rem;border-radius:8px;overflow:auto;color:#9fe8aa;font-size:.85rem}
|
||||
button{background:#188bf6;color:#fff;border:0;border-radius:8px;padding:.6rem 1.2rem;cursor:pointer;font-weight:700}
|
||||
.tag{display:inline-block;background:#0a2547;border-radius:20px;padding:.15rem .7rem;margin:.15rem;font-size:.8rem}
|
||||
</style></head>
|
||||
<body><div class="card" id="app"><p class="muted">Carregando…</p></div>
|
||||
<script>
|
||||
const kc = new Keycloak({ url: 'https://auth-acme.athleticmap.influxdigital.com.br', realm: 'athleticmap', clientId: 'spa' });
|
||||
kc.init({ onLoad: 'login-required', pkceMethod: 'S256', checkLoginIframe: false }).then(function (auth) {
|
||||
if (!auth) { document.getElementById('app').innerHTML = '<p>Nao autenticado.</p>'; return; }
|
||||
var t = kc.tokenParsed;
|
||||
var roles = ((t.realm_access && t.realm_access.roles) || []).map(function (r) { return '<span class="tag">' + r + '</span>'; }).join('');
|
||||
document.getElementById('app').innerHTML =
|
||||
'<h1>Athletic Map</h1>' +
|
||||
'<p class="muted">tenant <b>acme</b> · login OIDC (Authorization Code + PKCE)</p>' +
|
||||
'<p>Bem-vindo, <b>' + t.preferred_username + '</b></p>' +
|
||||
'<p>Roles no token: ' + roles + '</p>' +
|
||||
'<h3>Backend <code>/api/me</code> (JWT validado no servidor):</h3>' +
|
||||
'<pre id="me">chamando…</pre>' +
|
||||
'<button onclick="kc.logout()">Sair</button>';
|
||||
fetch('/api/me', { headers: { Authorization: 'Bearer ' + kc.token } })
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (me) { document.getElementById('me').textContent = JSON.stringify(me, null, 2); })
|
||||
.catch(function (e) { document.getElementById('me').textContent = 'erro: ' + e; });
|
||||
}).catch(function (e) { document.getElementById('app').innerHTML = '<p>Erro ao iniciar Keycloak: ' + e + '</p>'; });
|
||||
</script></body></html>
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata: { name: frontend, namespace: acme-prod }
|
||||
spec:
|
||||
replicas: 1
|
||||
selector: { matchLabels: { app: frontend } }
|
||||
template:
|
||||
metadata:
|
||||
labels: { app: frontend }
|
||||
annotations: { configVersion: "spa-2" }
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports: [{ containerPort: 80 }]
|
||||
volumeMounts:
|
||||
- { name: html, mountPath: /usr/share/nginx/html }
|
||||
volumes:
|
||||
- name: html
|
||||
configMap: { name: frontend-index }
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata: { name: frontend, namespace: acme-prod }
|
||||
spec:
|
||||
selector: { app: frontend }
|
||||
ports: [{ port: 80, targetPort: 80 }]
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: demo
|
||||
namespace: acme-prod
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
traefik.ingress.kubernetes.io/router.middlewares: acme-prod-redirect-https@kubernetescrd
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
tls:
|
||||
- hosts:
|
||||
- acme.athleticmap.influxdigital.com.br
|
||||
- auth-acme.athleticmap.influxdigital.com.br
|
||||
secretName: acme-tls
|
||||
rules:
|
||||
- host: acme.athleticmap.influxdigital.com.br
|
||||
http:
|
||||
paths:
|
||||
- { path: /api, pathType: Prefix, backend: { service: { name: backend, port: { number: 80 } } } }
|
||||
- { path: /, pathType: Prefix, backend: { service: { name: frontend, port: { number: 80 } } } }
|
||||
- host: auth-acme.athleticmap.influxdigital.com.br
|
||||
http:
|
||||
paths:
|
||||
- { path: /, pathType: Prefix, backend: { service: { name: keycloak, port: { number: 8080 } } } }
|
||||
@@ -0,0 +1,39 @@
|
||||
apiVersion: v1
|
||||
data:
|
||||
athleticmap-realm.json: |
|
||||
{
|
||||
"realm": "athleticmap",
|
||||
"enabled": true,
|
||||
"displayName": "Athletic Map",
|
||||
"loginWithEmailAllowed": true,
|
||||
"roles": {
|
||||
"realm": [
|
||||
{ "name": "admin" },
|
||||
{ "name": "atm_athlete" },
|
||||
{ "name": "atm_trainer" },
|
||||
{ "name": "atm_team_admin" },
|
||||
{ "name": "atm_fed_admin" }
|
||||
]
|
||||
},
|
||||
"clients": [
|
||||
{
|
||||
"clientId": "spa",
|
||||
"name": "Athletic Map SPA",
|
||||
"publicClient": true,
|
||||
"protocol": "openid-connect",
|
||||
"standardFlowEnabled": true,
|
||||
"implicitFlowEnabled": false,
|
||||
"directAccessGrantsEnabled": false,
|
||||
"redirectUris": ["https://acme.athleticmap.influxdigital.com.br/*"],
|
||||
"webOrigins": ["https://acme.athleticmap.influxdigital.com.br"],
|
||||
"attributes": {
|
||||
"pkce.code.challenge.method": "S256",
|
||||
"post.logout.redirect.uris": "https://acme.athleticmap.influxdigital.com.br/*"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: kc-realm-import
|
||||
namespace: acme-prod
|
||||
@@ -0,0 +1,10 @@
|
||||
# Redirect HTTP->HTTPS (Traefik). Aplicado por-ingress (nao afeta o desafio ACME do cert-manager).
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: redirect-https
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
redirectScheme:
|
||||
scheme: https
|
||||
permanent: true
|
||||
@@ -0,0 +1,57 @@
|
||||
# Backup diario do Postgres do tenant demo (pg_dump -> PVC, retencao 7 dias)
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: pg-backups
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
accessModes: [ReadWriteOnce]
|
||||
storageClassName: local-path
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: pg-backup
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
schedule: "0 2 * * *"
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 3
|
||||
concurrencyPolicy: Forbid
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: pg-backup
|
||||
image: postgres:16
|
||||
env:
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: db-credentials
|
||||
key: password
|
||||
command: ["/bin/sh", "-c"]
|
||||
args:
|
||||
- |
|
||||
set -eo pipefail
|
||||
echo "aguardando postgres ficar acessivel..."
|
||||
for i in $(seq 1 30); do pg_isready -h postgres -U atm -t 3 >/dev/null 2>&1 && break; sleep 2; done
|
||||
TS=$(date +%Y%m%d-%H%M%S)
|
||||
for DB in athleticmap keycloak; do
|
||||
echo "dump $DB ..."
|
||||
pg_dump -h postgres -U atm -d "$DB" | gzip > "/backups/${DB}-${TS}.sql.gz"
|
||||
done
|
||||
find /backups -name '*.sql.gz' -mtime +7 -delete
|
||||
echo "backups atuais:"; ls -lh /backups | tail -20
|
||||
volumeMounts:
|
||||
- name: backups
|
||||
mountPath: /backups
|
||||
volumes:
|
||||
- name: backups
|
||||
persistentVolumeClaim:
|
||||
claimName: pg-backups
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"realm": "athleticmap",
|
||||
"enabled": true,
|
||||
"displayName": "Athletic Map",
|
||||
"loginWithEmailAllowed": true,
|
||||
"roles": {
|
||||
"realm": [
|
||||
{ "name": "admin" },
|
||||
{ "name": "atm_athlete" },
|
||||
{ "name": "atm_trainer" },
|
||||
{ "name": "atm_team_admin" },
|
||||
{ "name": "atm_fed_admin" }
|
||||
]
|
||||
},
|
||||
"clients": [
|
||||
{
|
||||
"clientId": "spa",
|
||||
"name": "Athletic Map SPA",
|
||||
"publicClient": true,
|
||||
"protocol": "openid-connect",
|
||||
"standardFlowEnabled": true,
|
||||
"implicitFlowEnabled": false,
|
||||
"directAccessGrantsEnabled": false,
|
||||
"redirectUris": ["https://acme.athleticmap.influxdigital.com.br/*"],
|
||||
"webOrigins": ["https://acme.athleticmap.influxdigital.com.br"],
|
||||
"attributes": {
|
||||
"pkce.code.challenge.method": "S256",
|
||||
"post.logout.redirect.uris": "https://acme.athleticmap.influxdigital.com.br/*"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user