From db4ae81a1b2588d8f6d176d966a81ec6eabdf732 Mon Sep 17 00:00:00 2001 From: deploy Date: Sat, 26 Sep 2026 14:18:22 +0000 Subject: [PATCH] feat(tenants): CronJobs financeiros para escolinha/acme/demo/piloto, com client operacao e roles atm_financeiro proprias --- tenants/acme/08-sealed-operacao.yaml | 15 ++ tenants/acme/55-cronjobs-financeiro.yaml | 203 ++++++++++++++++++ tenants/demo/08-sealed-operacao.yaml | 15 ++ tenants/demo/55-cronjobs-financeiro.yaml | 203 ++++++++++++++++++ tenants/escolinha/08-sealed-operacao.yaml | 15 ++ tenants/escolinha/55-cronjobs-financeiro.yaml | 203 ++++++++++++++++++ tenants/piloto/08-sealed-operacao.yaml | 15 ++ tenants/piloto/55-cronjobs-financeiro.yaml | 203 ++++++++++++++++++ 8 files changed, 872 insertions(+) create mode 100644 tenants/acme/08-sealed-operacao.yaml create mode 100644 tenants/acme/55-cronjobs-financeiro.yaml create mode 100644 tenants/demo/08-sealed-operacao.yaml create mode 100644 tenants/demo/55-cronjobs-financeiro.yaml create mode 100644 tenants/escolinha/08-sealed-operacao.yaml create mode 100644 tenants/escolinha/55-cronjobs-financeiro.yaml create mode 100644 tenants/piloto/08-sealed-operacao.yaml create mode 100644 tenants/piloto/55-cronjobs-financeiro.yaml diff --git a/tenants/acme/08-sealed-operacao.yaml b/tenants/acme/08-sealed-operacao.yaml new file mode 100644 index 0000000..9dee728 --- /dev/null +++ b/tenants/acme/08-sealed-operacao.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + creationTimestamp: null + name: operacao-credentials + namespace: acme-prod +spec: + encryptedData: + client-secret: AgB4hMs59kInlOcAxILy9KRLtN5sUEl5bCjV+fqh9wlmMCvAIx7h1v+C66FGYmiwPqwFeyAvpWqlAukPwUHpz8VtZ+EPiFrzm6sdwlUFVPWGznplTxGfFFU+VdZ3nyNBq69tULnmZBsOX1dW5B8YMgt1Sdq6jiC9MCcVqg6bRrl7YEbkEW1NXCUnQ9JOT5QeFlUo77q3iUf7ZEAkdzHkSpJf7A+GMmme6FkI/agL1YOQlVbIJxijimFEo5fELUsW6xqK5aAby7Qz9rbxI8e+kUdtJ0Dq5CTd8R8JUsJOh2bXRibCM3WhCcFpF/l/w9TSMqinWGsKQWmFk4V2qfr0H5jj+rSRsOkUYdwRImDCJuDT7tjCHux9+rhobvc2rWdj5gQ+3vAe6GOs+f8uPR4ipP5vTr3Vmz3BxNCz08xaDeRcsIhOIznVAclgoweVJy8y1u6feTA6GgtNkjHTzdB8IOxaIqxjiTmxiwipzMEqGVlfQuIsACk+yz8G5iasE//et5Hjx4RwQgW1B0RZersabABCs43qo998nSqPpWHMMVc2ivRYtYLnS+6rFMWkjDrOCv3E30rKtW+IgGRgKgnFpg6Wzb71Ti0cz+Nf4sl/KUC/FCfb6ZxMAMhBtFL2PcfpleJR2dGhBEFvRWWmD8lDdoUGcrEaSSWn67z19oLNe34w07XuuTqLYw5I891pKJjhVOghP/kLWuu4zdicKtR06Ait+sK/m1xMcpF7szsiXNEuqw== + template: + metadata: + creationTimestamp: null + name: operacao-credentials + namespace: acme-prod diff --git a/tenants/acme/55-cronjobs-financeiro.yaml b/tenants/acme/55-cronjobs-financeiro.yaml new file mode 100644 index 0000000..2d2a421 --- /dev/null +++ b/tenants/acme/55-cronjobs-financeiro.yaml @@ -0,0 +1,203 @@ +# ============================================================================= +# Os tres processos do Financeiro que ninguem disparava sozinho: sem eles nasce +# mensalidade nenhuma, nota fiscal nenhuma processa e a conciliacao nunca roda. +# Mesmo padrao de tenants/plataforma/55-cronjobs-financeiro.yaml — adaptado so +# no ISSUER_HOST (host publico deste tenant) e no cliente/segredo, que sao +# proprios de cada realm. +# +# Criado em 2026-09-26 junto com o client Keycloak `operacao` e as roles +# `atm_financeiro`/`atm_financeiro-leitura`, que este tenant nao tinha. +# ============================================================================= +apiVersion: v1 +kind: ConfigMap +metadata: + name: financeiro-cron + namespace: acme-prod +data: + disparar.sh: | + #!/bin/sh + set -eu + + : "${KEYCLOAK_URL:?falta KEYCLOAK_URL}" + : "${ALVO:?falta ALVO}" + : "${CLIENT_SECRET:?falta CLIENT_SECRET}" + : "${ISSUER_HOST:?falta ISSUER_HOST}" + + echo "[$(date -u +%FT%TZ)] alvo: ${ALVO}" + + i=0 + until curl -sS -o /dev/null -m 5 "${KEYCLOAK_URL}" 2>/dev/null; do + i=$((i+1)) + if [ "$i" -ge 24 ]; then + echo "ERRO: ${KEYCLOAK_URL} inalcancavel depois de 2 min." >&2 + echo " Se for pod novo, e a politica de rede ainda nao programada;" >&2 + echo " se persistir, confira o Service keycloak e a deny-cross-tenant." >&2 + exit 1 + fi + sleep 5 + done + + RESP="$(printf 'grant_type=client_credentials&client_id=operacao&client_secret=%s' \ + "${CLIENT_SECRET}" \ + | curl -sS --fail-with-body -X POST "${KEYCLOAK_URL}" \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + -H 'X-Forwarded-Proto: https' \ + -H 'X-Forwarded-Port: 443' \ + -H "X-Forwarded-Host: ${ISSUER_HOST}" -d @-)" + + TOKEN="$(printf '%s' "${RESP}" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')" + if [ -z "${TOKEN}" ]; then + echo "ERRO: nao consegui token pelo client 'operacao'." >&2 + echo " Confira o Secret operacao-credentials e se o client existe no realm." >&2 + exit 1 + fi + + printf 'header = "Authorization: Bearer %s"\n' "${TOKEN}" \ + | curl -sS --fail-with-body -K - -X POST "${ALVO}" -o /tmp/saida.json -w '%{http_code}\n' + + echo "resposta:" + cat /tmp/saida.json + echo +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-mensalidades + namespace: acme-prod +spec: + schedule: "0 6 1 * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 900 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "-c"] + args: + - | + export ALVO="http://servico-financeiro/api/financeiro/matriculas/gerar-mensalidades?competencia=$(date +%Y-%m)" + exec /bin/sh /script/disparar.sh + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-acme.athleticmap.com + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-notas + namespace: acme-prod +spec: + schedule: "15 * * * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 600 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "/script/disparar.sh"] + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-acme.athleticmap.com + - name: ALVO + value: http://servico-financeiro/api/financeiro/notas/processar?limite=50 + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-conciliacao + namespace: acme-prod +spec: + schedule: "30 */6 * * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 900 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "/script/disparar.sh"] + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-acme.athleticmap.com + - name: ALVO + value: http://servico-financeiro/api/financeiro/conciliacao?limiteEventos=100&limiteCobrancas=100 + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 diff --git a/tenants/demo/08-sealed-operacao.yaml b/tenants/demo/08-sealed-operacao.yaml new file mode 100644 index 0000000..7bfb366 --- /dev/null +++ b/tenants/demo/08-sealed-operacao.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + creationTimestamp: null + name: operacao-credentials + namespace: demo-prod +spec: + encryptedData: + client-secret: AgBDXw2Wvu8899B2WD+3I5p0Qb34kaYlEix6WXL536TYrFrTXW7itICDkozT+1uL6IBfOLR1yL1K3GCSeXDsA7r1vHRptM16/vW5W2mG6+lH4DkrxMPtzPRhMZk/1NAd2jh7RuVOLLn3IgOShfBO6zvFqSmFICfQuuY5m7ZQExSTWC2vh2WWpT7kWjhzAS/FNSZXwJwuM0Vw9/PShxqOpN0Nd8qAxyN6DgzNzCgtRshFls3+nh3Tqa0a5TageXcYs6QS46mCNriCbaPILz3Y6p3oDZqpl8mhrT8l80bhJl54ckIslOqEoaCP/mnmlzXznvtXymkaZkBXBTLO1/sWBG1S2HpG5a1sfgmCxIBdJEICjZerjFqnmMGletAEU7FR+xYLraq5nUDnATVowJVTDnezrA2ZdSZbQfwQfvmHHV751WZaKSh6vYww18cwsWPDS+OBtkg/kvl+JPaOARSekgwAbJmW/QybgHALMJK2gTgI94eJEq3MKwRsrN85Ii3w+kygN7lSN17fuXO/G4fTHTVJasCor+Sn+XmxuEgHS+OT62ihZnFPwZSV0ECmU/Z10uCUBeBOroOMRxTMqTioyHUzskdmBf1hzwpIsyNZUrijxwWoUOzVjS5VLSm7Tzp2hbPzsbj/eVRAl/y/sfECdBew5SmEbqqMgZU4fDvdkNCEtme5VYMv7PKh/a6aRctJjVcxu0l3lU4+gckeG/hWEZ4dBavyFDf5ULFU1T4qxUC87g== + template: + metadata: + creationTimestamp: null + name: operacao-credentials + namespace: demo-prod diff --git a/tenants/demo/55-cronjobs-financeiro.yaml b/tenants/demo/55-cronjobs-financeiro.yaml new file mode 100644 index 0000000..b861892 --- /dev/null +++ b/tenants/demo/55-cronjobs-financeiro.yaml @@ -0,0 +1,203 @@ +# ============================================================================= +# Os tres processos do Financeiro que ninguem disparava sozinho: sem eles nasce +# mensalidade nenhuma, nota fiscal nenhuma processa e a conciliacao nunca roda. +# Mesmo padrao de tenants/plataforma/55-cronjobs-financeiro.yaml — adaptado so +# no ISSUER_HOST (host publico deste tenant) e no cliente/segredo, que sao +# proprios de cada realm. +# +# Criado em 2026-09-26 junto com o client Keycloak `operacao` e as roles +# `atm_financeiro`/`atm_financeiro-leitura`, que este tenant nao tinha. +# ============================================================================= +apiVersion: v1 +kind: ConfigMap +metadata: + name: financeiro-cron + namespace: demo-prod +data: + disparar.sh: | + #!/bin/sh + set -eu + + : "${KEYCLOAK_URL:?falta KEYCLOAK_URL}" + : "${ALVO:?falta ALVO}" + : "${CLIENT_SECRET:?falta CLIENT_SECRET}" + : "${ISSUER_HOST:?falta ISSUER_HOST}" + + echo "[$(date -u +%FT%TZ)] alvo: ${ALVO}" + + i=0 + until curl -sS -o /dev/null -m 5 "${KEYCLOAK_URL}" 2>/dev/null; do + i=$((i+1)) + if [ "$i" -ge 24 ]; then + echo "ERRO: ${KEYCLOAK_URL} inalcancavel depois de 2 min." >&2 + echo " Se for pod novo, e a politica de rede ainda nao programada;" >&2 + echo " se persistir, confira o Service keycloak e a deny-cross-tenant." >&2 + exit 1 + fi + sleep 5 + done + + RESP="$(printf 'grant_type=client_credentials&client_id=operacao&client_secret=%s' \ + "${CLIENT_SECRET}" \ + | curl -sS --fail-with-body -X POST "${KEYCLOAK_URL}" \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + -H 'X-Forwarded-Proto: https' \ + -H 'X-Forwarded-Port: 443' \ + -H "X-Forwarded-Host: ${ISSUER_HOST}" -d @-)" + + TOKEN="$(printf '%s' "${RESP}" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')" + if [ -z "${TOKEN}" ]; then + echo "ERRO: nao consegui token pelo client 'operacao'." >&2 + echo " Confira o Secret operacao-credentials e se o client existe no realm." >&2 + exit 1 + fi + + printf 'header = "Authorization: Bearer %s"\n' "${TOKEN}" \ + | curl -sS --fail-with-body -K - -X POST "${ALVO}" -o /tmp/saida.json -w '%{http_code}\n' + + echo "resposta:" + cat /tmp/saida.json + echo +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-mensalidades + namespace: demo-prod +spec: + schedule: "0 6 1 * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 900 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "-c"] + args: + - | + export ALVO="http://servico-financeiro/api/financeiro/matriculas/gerar-mensalidades?competencia=$(date +%Y-%m)" + exec /bin/sh /script/disparar.sh + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-demo.athleticmap.com + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-notas + namespace: demo-prod +spec: + schedule: "15 * * * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 600 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "/script/disparar.sh"] + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-demo.athleticmap.com + - name: ALVO + value: http://servico-financeiro/api/financeiro/notas/processar?limite=50 + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-conciliacao + namespace: demo-prod +spec: + schedule: "30 */6 * * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 900 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "/script/disparar.sh"] + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-demo.athleticmap.com + - name: ALVO + value: http://servico-financeiro/api/financeiro/conciliacao?limiteEventos=100&limiteCobrancas=100 + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 diff --git a/tenants/escolinha/08-sealed-operacao.yaml b/tenants/escolinha/08-sealed-operacao.yaml new file mode 100644 index 0000000..071615d --- /dev/null +++ b/tenants/escolinha/08-sealed-operacao.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + creationTimestamp: null + name: operacao-credentials + namespace: escolinha-prod +spec: + encryptedData: + client-secret: AgAjEMYaGRizDE6cgHG9BELeXkzNvm86u1vnpLKD01VHoE1OEMaoOhO9ZS/FlDIeCih60/vi+l7G9hIT/nakB/azfOUi9PjIkD6wbz2f7uXEmWaZR3zkvYJNb5sL6cGyMadIaLVX9Cj3GvtpFckROG1c+O6GqsKWLzvCN2w+uUhxTBbMQJdT2ZBWdDtuW/t6Z6AAXp1yk1ApkhnsRdsZcZra1cv/MF/EDu0r2xRT+y+csS3QqHlXK2oia+Xty64+SZP61CXc5ejDAqM0nkvMgx9+Sei5uqQs/hD64UYhHQB8Urh/jzYaumaf8pZxsWzAv37yTp11qK5+V2wsmz5B2HMpwBUuZjY38g5ZQ/pIwJK4YPUp2vZV7n1drb0mF3Bd3ojhE+E/ZcpEcmfEfSfYRLSFAxXr53WDB65EH7BrB8ZKj6R8jxUWHnYWWQsmIkz/qwjBy/RCzXm+VDuS1pO2Vgz5LVqmVvxtXoBCexAyoZNViXgI5vdINmQsbpk6HYzgwlXfeQKfoT0+nKTsTxI4tg17INfPZsYmtQBwMc7kqotIM4on6d2ln9HKmMaB9OW+cCaw82mP582BGMpAV1yp/MX4y5HQgrUo7Oh6qNudCEvQbCeetCnqDh/0lIj5jmewPLh1e5eFm3kJ0NDIJtnOJzXY0nZkmXle4MOrnLSHBXjFyJKtuv1wBy+6MxL4USmpYGwX7BIttjBMuyxjsdX+MrUyXSuEAkwU6+k70ClDvngbUQ== + template: + metadata: + creationTimestamp: null + name: operacao-credentials + namespace: escolinha-prod diff --git a/tenants/escolinha/55-cronjobs-financeiro.yaml b/tenants/escolinha/55-cronjobs-financeiro.yaml new file mode 100644 index 0000000..2c3cd99 --- /dev/null +++ b/tenants/escolinha/55-cronjobs-financeiro.yaml @@ -0,0 +1,203 @@ +# ============================================================================= +# Os tres processos do Financeiro que ninguem disparava sozinho: sem eles nasce +# mensalidade nenhuma, nota fiscal nenhuma processa e a conciliacao nunca roda. +# Mesmo padrao de tenants/plataforma/55-cronjobs-financeiro.yaml — adaptado so +# no ISSUER_HOST (host publico deste tenant) e no cliente/segredo, que sao +# proprios de cada realm. +# +# Criado em 2026-09-26 junto com o client Keycloak `operacao` e as roles +# `atm_financeiro`/`atm_financeiro-leitura`, que este tenant nao tinha. +# ============================================================================= +apiVersion: v1 +kind: ConfigMap +metadata: + name: financeiro-cron + namespace: escolinha-prod +data: + disparar.sh: | + #!/bin/sh + set -eu + + : "${KEYCLOAK_URL:?falta KEYCLOAK_URL}" + : "${ALVO:?falta ALVO}" + : "${CLIENT_SECRET:?falta CLIENT_SECRET}" + : "${ISSUER_HOST:?falta ISSUER_HOST}" + + echo "[$(date -u +%FT%TZ)] alvo: ${ALVO}" + + i=0 + until curl -sS -o /dev/null -m 5 "${KEYCLOAK_URL}" 2>/dev/null; do + i=$((i+1)) + if [ "$i" -ge 24 ]; then + echo "ERRO: ${KEYCLOAK_URL} inalcancavel depois de 2 min." >&2 + echo " Se for pod novo, e a politica de rede ainda nao programada;" >&2 + echo " se persistir, confira o Service keycloak e a deny-cross-tenant." >&2 + exit 1 + fi + sleep 5 + done + + RESP="$(printf 'grant_type=client_credentials&client_id=operacao&client_secret=%s' \ + "${CLIENT_SECRET}" \ + | curl -sS --fail-with-body -X POST "${KEYCLOAK_URL}" \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + -H 'X-Forwarded-Proto: https' \ + -H 'X-Forwarded-Port: 443' \ + -H "X-Forwarded-Host: ${ISSUER_HOST}" -d @-)" + + TOKEN="$(printf '%s' "${RESP}" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')" + if [ -z "${TOKEN}" ]; then + echo "ERRO: nao consegui token pelo client 'operacao'." >&2 + echo " Confira o Secret operacao-credentials e se o client existe no realm." >&2 + exit 1 + fi + + printf 'header = "Authorization: Bearer %s"\n' "${TOKEN}" \ + | curl -sS --fail-with-body -K - -X POST "${ALVO}" -o /tmp/saida.json -w '%{http_code}\n' + + echo "resposta:" + cat /tmp/saida.json + echo +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-mensalidades + namespace: escolinha-prod +spec: + schedule: "0 6 1 * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 900 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "-c"] + args: + - | + export ALVO="http://servico-financeiro/api/financeiro/matriculas/gerar-mensalidades?competencia=$(date +%Y-%m)" + exec /bin/sh /script/disparar.sh + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-escolinha.athleticmap.com + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-notas + namespace: escolinha-prod +spec: + schedule: "15 * * * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 600 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "/script/disparar.sh"] + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-escolinha.athleticmap.com + - name: ALVO + value: http://servico-financeiro/api/financeiro/notas/processar?limite=50 + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-conciliacao + namespace: escolinha-prod +spec: + schedule: "30 */6 * * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 900 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "/script/disparar.sh"] + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-escolinha.athleticmap.com + - name: ALVO + value: http://servico-financeiro/api/financeiro/conciliacao?limiteEventos=100&limiteCobrancas=100 + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 diff --git a/tenants/piloto/08-sealed-operacao.yaml b/tenants/piloto/08-sealed-operacao.yaml new file mode 100644 index 0000000..53e8859 --- /dev/null +++ b/tenants/piloto/08-sealed-operacao.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + creationTimestamp: null + name: operacao-credentials + namespace: piloto-prod +spec: + encryptedData: + client-secret: AgAQEYRBIwAUZzvdsAKtF7Jq+1rTnlR9IC+y2yokZdUGyEIr/k0L+tK01+zWhxKb/jhf+TjFYjGXT3KxxZ0l+UPvJs2TuOaSfLO+u5tjrjD/KrZU08h7sEUPr3rw5X7MlHbE5PyVoHLCb3QQ0vBgg8+r78wf5BDOiDf4TSa3jWScDkrfqJe4+BVkE9/RDkfzj7pvn86+ZXKz1do60HVrQea48zq96ImRl24Pw2bWyX85nFnjIzrG7vQJln1jcLicN/P66d7ROeS7yidFi5rHW71Ws5QVu2i/WMwVmpq2YFLkkD6d3EWuFzfGPNmk3fssqUjC3B1tsJM/lc3B93Ov/eVmtwinkL3qjyYCNYEsjhMC56igpICpCocoaYusTHSn0xuzrz9mfpTWaa9WbMlWN9tQrERJpl2E9WlN1u77QJ+Fwb1oKkVxt9quHsl1jPujjZfyNnoOkIf+lX7z6rPhz5ZT1XeBdwb/FLQJM9rAU6axzPtKL8KQP+NkUZqqE7/21rp8mbS86OsT5MXXjfHAEtmBdhSdm38peRw1RXVPl8EGMBqCsrrj0OMxo4wDftNoLLoQ1GHsX1sU3DVLjdVDDG3pXQc/4jXmNoompmbcfNKoigcpEOAXeAbjsEuQhlChOmH8KzO8/hUYpgaH5xds0HN+84fZXt+ZCGLGIbGZ3n9LujjB6XPCqFf162ZG9FzAEfgSGoV83bDi/Axq7PQaUgu0up2gEu4ZvX6cvD0Q4nltbw== + template: + metadata: + creationTimestamp: null + name: operacao-credentials + namespace: piloto-prod diff --git a/tenants/piloto/55-cronjobs-financeiro.yaml b/tenants/piloto/55-cronjobs-financeiro.yaml new file mode 100644 index 0000000..3eff301 --- /dev/null +++ b/tenants/piloto/55-cronjobs-financeiro.yaml @@ -0,0 +1,203 @@ +# ============================================================================= +# Os tres processos do Financeiro que ninguem disparava sozinho: sem eles nasce +# mensalidade nenhuma, nota fiscal nenhuma processa e a conciliacao nunca roda. +# Mesmo padrao de tenants/plataforma/55-cronjobs-financeiro.yaml — adaptado so +# no ISSUER_HOST (host publico deste tenant) e no cliente/segredo, que sao +# proprios de cada realm. +# +# Criado em 2026-09-26 junto com o client Keycloak `operacao` e as roles +# `atm_financeiro`/`atm_financeiro-leitura`, que este tenant nao tinha. +# ============================================================================= +apiVersion: v1 +kind: ConfigMap +metadata: + name: financeiro-cron + namespace: piloto-prod +data: + disparar.sh: | + #!/bin/sh + set -eu + + : "${KEYCLOAK_URL:?falta KEYCLOAK_URL}" + : "${ALVO:?falta ALVO}" + : "${CLIENT_SECRET:?falta CLIENT_SECRET}" + : "${ISSUER_HOST:?falta ISSUER_HOST}" + + echo "[$(date -u +%FT%TZ)] alvo: ${ALVO}" + + i=0 + until curl -sS -o /dev/null -m 5 "${KEYCLOAK_URL}" 2>/dev/null; do + i=$((i+1)) + if [ "$i" -ge 24 ]; then + echo "ERRO: ${KEYCLOAK_URL} inalcancavel depois de 2 min." >&2 + echo " Se for pod novo, e a politica de rede ainda nao programada;" >&2 + echo " se persistir, confira o Service keycloak e a deny-cross-tenant." >&2 + exit 1 + fi + sleep 5 + done + + RESP="$(printf 'grant_type=client_credentials&client_id=operacao&client_secret=%s' \ + "${CLIENT_SECRET}" \ + | curl -sS --fail-with-body -X POST "${KEYCLOAK_URL}" \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + -H 'X-Forwarded-Proto: https' \ + -H 'X-Forwarded-Port: 443' \ + -H "X-Forwarded-Host: ${ISSUER_HOST}" -d @-)" + + TOKEN="$(printf '%s' "${RESP}" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')" + if [ -z "${TOKEN}" ]; then + echo "ERRO: nao consegui token pelo client 'operacao'." >&2 + echo " Confira o Secret operacao-credentials e se o client existe no realm." >&2 + exit 1 + fi + + printf 'header = "Authorization: Bearer %s"\n' "${TOKEN}" \ + | curl -sS --fail-with-body -K - -X POST "${ALVO}" -o /tmp/saida.json -w '%{http_code}\n' + + echo "resposta:" + cat /tmp/saida.json + echo +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-mensalidades + namespace: piloto-prod +spec: + schedule: "0 6 1 * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 900 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "-c"] + args: + - | + export ALVO="http://servico-financeiro/api/financeiro/matriculas/gerar-mensalidades?competencia=$(date +%Y-%m)" + exec /bin/sh /script/disparar.sh + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-piloto.athleticmap.com + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-notas + namespace: piloto-prod +spec: + schedule: "15 * * * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 600 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "/script/disparar.sh"] + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-piloto.athleticmap.com + - name: ALVO + value: http://servico-financeiro/api/financeiro/notas/processar?limite=50 + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555 +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: financeiro-conciliacao + namespace: piloto-prod +spec: + schedule: "30 */6 * * *" + timeZone: America/Sao_Paulo + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 5 + jobTemplate: + spec: + activeDeadlineSeconds: 900 + backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure + containers: + - name: disparar + image: docker.io/curlimages/curl:8.9.1 + imagePullPolicy: Never + command: ["/bin/sh", "/script/disparar.sh"] + env: + - name: KEYCLOAK_URL + value: http://keycloak:8080/realms/athleticmap/protocol/openid-connect/token + - name: ISSUER_HOST + value: auth-piloto.athleticmap.com + - name: ALVO + value: http://servico-financeiro/api/financeiro/conciliacao?limiteEventos=100&limiteCobrancas=100 + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: operacao-credentials + key: client-secret + resources: + requests: { cpu: 10m, memory: 32Mi } + limits: { cpu: 200m, memory: 64Mi } + volumeMounts: + - name: script + mountPath: /script + volumes: + - name: script + configMap: + name: financeiro-cron + defaultMode: 0555