feat(tenants): CronJob do resumo diario (N16) de volta aos 4 tenants — agora registrados como contratacoes de demonstracao (V025)
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# =============================================================================
|
||||
# N16 — o resumo AGREGADO do tenant, entregue a plataforma uma vez por dia, para o
|
||||
# comprador ver todas as escolinhas dele lado a lado no /minha-conta.
|
||||
#
|
||||
# AGUARDANDO GRAVACAO no molde (`moldes/consolidado/` do GitOps) e nos tenants que
|
||||
# ja existem. Nada aqui foi aplicado.
|
||||
#
|
||||
# O desenho: o TENANT calcula (runtime-operacao, GET /api/resumo-do-tenant, so
|
||||
# contadores e somas) e o TENANT envia (este CronJob). A plataforma nao entra no
|
||||
# namespace nem no banco do tenant para isto.
|
||||
#
|
||||
# 1. token do client `operacao` no realm do tenant (o mesmo das tarefas do
|
||||
# financeiro: Secret `operacao-credentials`);
|
||||
# 2. GET http://runtime-operacao/api/resumo-do-tenant (lista de 1 ou 2 meses);
|
||||
# 3. POST http://servico-captacao.plataforma-prod.svc/api/public/resumo-do-tenant/acme
|
||||
# com o cabecalho `x-atm-resumo-token` — do Secret `resumo-credentials`, que
|
||||
# so vale para ESTE tenant (HMAC do nome dele com a chave da plataforma).
|
||||
#
|
||||
# A saida para a plataforma e pela internet (443 publico), que a deny-cross-tenant
|
||||
# ja libera: nao precisa de NetworkPolicy nova.
|
||||
#
|
||||
# `optional: true` no resumo-credentials: tenant sem o Secret (chave da plataforma
|
||||
# ainda nao configurada) roda o job, que termina OK dizendo "sem token" — nao gera
|
||||
# KubeJobFailed nem gasta a cota de e-mail dos alertas.
|
||||
# =============================================================================
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: resumo-cron
|
||||
namespace: acme-prod
|
||||
data:
|
||||
enviar.sh: |
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
: "${KEYCLOAK_URL:?falta KEYCLOAK_URL}"
|
||||
: "${CLIENT_SECRET:?falta CLIENT_SECRET}"
|
||||
: "${ISSUER_HOST:?falta ISSUER_HOST}"
|
||||
: "${DESTINO:?falta DESTINO}"
|
||||
|
||||
if [ -z "${RESUMO_TOKEN:-}" ]; then
|
||||
echo "sem o Secret resumo-credentials neste tenant: nada a enviar."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
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
|
||||
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
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Os tokens vao por `-K -` (stdin), e nao na linha de comando: argumento de
|
||||
# processo aparece em `ps` para quem estiver no no.
|
||||
CODIGO="$(printf 'header = "Authorization: Bearer %s"\n' "${TOKEN}" \
|
||||
| curl -sS -K - -o /tmp/resumo.json -w '%{http_code}' http://runtime-operacao/api/resumo-do-tenant)"
|
||||
if [ "${CODIGO}" != "200" ]; then
|
||||
echo "ERRO: o runtime-operacao respondeu ${CODIGO} ao resumo." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "resumo calculado: $(wc -c < /tmp/resumo.json) bytes (so numeros)"
|
||||
|
||||
CODIGO="$(printf 'header = "x-atm-resumo-token: %s"\n' "${RESUMO_TOKEN}" \
|
||||
| curl -sS -K - -X POST "${DESTINO}" -H 'Content-Type: application/json' \
|
||||
--data-binary @/tmp/resumo.json -o /tmp/saida.json -w '%{http_code}')"
|
||||
echo "plataforma: ${CODIGO}"
|
||||
cat /tmp/saida.json; echo
|
||||
case "${CODIGO}" in
|
||||
2*) ;;
|
||||
*) echo "ERRO: a plataforma respondeu ${CODIGO}." >&2; exit 1 ;;
|
||||
esac
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: resumo-para-a-plataforma
|
||||
namespace: acme-prod
|
||||
spec:
|
||||
# Madrugada, depois da virada do dia em Sao Paulo e fora do horario das
|
||||
# mensalidades (dia 1, 06h).
|
||||
schedule: "30 4 * * *"
|
||||
timeZone: America/Sao_Paulo
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 5
|
||||
jobTemplate:
|
||||
spec:
|
||||
activeDeadlineSeconds: 600
|
||||
backoffLimit: 2
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: enviar
|
||||
image: docker.io/curlimages/curl:8.9.1
|
||||
imagePullPolicy: Never
|
||||
command: ["/bin/sh", "/script/enviar.sh"]
|
||||
env:
|
||||
- name: KEYCLOAK_URL
|
||||
value: http://keycloak.plataforma-prod.svc:8080/realms/athleticmap-3/protocol/openid-connect/token
|
||||
- name: ISSUER_HOST
|
||||
value: auth.athleticmap.com
|
||||
- name: DESTINO
|
||||
value: http://servico-captacao.plataforma-prod.svc/api/public/resumo-do-tenant/acme
|
||||
- name: CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: operacao-credentials
|
||||
key: client-secret
|
||||
- name: RESUMO_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: resumo-credentials
|
||||
key: token
|
||||
optional: true
|
||||
resources:
|
||||
requests: { cpu: 10m, memory: 32Mi }
|
||||
limits: { cpu: 200m, memory: 64Mi }
|
||||
volumeMounts:
|
||||
- name: script
|
||||
mountPath: /script
|
||||
volumes:
|
||||
- name: script
|
||||
configMap:
|
||||
name: resumo-cron
|
||||
@@ -0,0 +1,141 @@
|
||||
# =============================================================================
|
||||
# N16 — o resumo AGREGADO do tenant, entregue a plataforma uma vez por dia, para o
|
||||
# comprador ver todas as escolinhas dele lado a lado no /minha-conta.
|
||||
#
|
||||
# AGUARDANDO GRAVACAO no molde (`moldes/consolidado/` do GitOps) e nos tenants que
|
||||
# ja existem. Nada aqui foi aplicado.
|
||||
#
|
||||
# O desenho: o TENANT calcula (runtime-operacao, GET /api/resumo-do-tenant, so
|
||||
# contadores e somas) e o TENANT envia (este CronJob). A plataforma nao entra no
|
||||
# namespace nem no banco do tenant para isto.
|
||||
#
|
||||
# 1. token do client `operacao` no realm do tenant (o mesmo das tarefas do
|
||||
# financeiro: Secret `operacao-credentials`);
|
||||
# 2. GET http://runtime-operacao/api/resumo-do-tenant (lista de 1 ou 2 meses);
|
||||
# 3. POST http://servico-captacao.plataforma-prod.svc/api/public/resumo-do-tenant/demo
|
||||
# com o cabecalho `x-atm-resumo-token` — do Secret `resumo-credentials`, que
|
||||
# so vale para ESTE tenant (HMAC do nome dele com a chave da plataforma).
|
||||
#
|
||||
# A saida para a plataforma e pela internet (443 publico), que a deny-cross-tenant
|
||||
# ja libera: nao precisa de NetworkPolicy nova.
|
||||
#
|
||||
# `optional: true` no resumo-credentials: tenant sem o Secret (chave da plataforma
|
||||
# ainda nao configurada) roda o job, que termina OK dizendo "sem token" — nao gera
|
||||
# KubeJobFailed nem gasta a cota de e-mail dos alertas.
|
||||
# =============================================================================
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: resumo-cron
|
||||
namespace: demo-prod
|
||||
data:
|
||||
enviar.sh: |
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
: "${KEYCLOAK_URL:?falta KEYCLOAK_URL}"
|
||||
: "${CLIENT_SECRET:?falta CLIENT_SECRET}"
|
||||
: "${ISSUER_HOST:?falta ISSUER_HOST}"
|
||||
: "${DESTINO:?falta DESTINO}"
|
||||
|
||||
if [ -z "${RESUMO_TOKEN:-}" ]; then
|
||||
echo "sem o Secret resumo-credentials neste tenant: nada a enviar."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
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
|
||||
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
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Os tokens vao por `-K -` (stdin), e nao na linha de comando: argumento de
|
||||
# processo aparece em `ps` para quem estiver no no.
|
||||
CODIGO="$(printf 'header = "Authorization: Bearer %s"\n' "${TOKEN}" \
|
||||
| curl -sS -K - -o /tmp/resumo.json -w '%{http_code}' http://runtime-operacao/api/resumo-do-tenant)"
|
||||
if [ "${CODIGO}" != "200" ]; then
|
||||
echo "ERRO: o runtime-operacao respondeu ${CODIGO} ao resumo." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "resumo calculado: $(wc -c < /tmp/resumo.json) bytes (so numeros)"
|
||||
|
||||
CODIGO="$(printf 'header = "x-atm-resumo-token: %s"\n' "${RESUMO_TOKEN}" \
|
||||
| curl -sS -K - -X POST "${DESTINO}" -H 'Content-Type: application/json' \
|
||||
--data-binary @/tmp/resumo.json -o /tmp/saida.json -w '%{http_code}')"
|
||||
echo "plataforma: ${CODIGO}"
|
||||
cat /tmp/saida.json; echo
|
||||
case "${CODIGO}" in
|
||||
2*) ;;
|
||||
*) echo "ERRO: a plataforma respondeu ${CODIGO}." >&2; exit 1 ;;
|
||||
esac
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: resumo-para-a-plataforma
|
||||
namespace: demo-prod
|
||||
spec:
|
||||
# Madrugada, depois da virada do dia em Sao Paulo e fora do horario das
|
||||
# mensalidades (dia 1, 06h).
|
||||
schedule: "30 4 * * *"
|
||||
timeZone: America/Sao_Paulo
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 5
|
||||
jobTemplate:
|
||||
spec:
|
||||
activeDeadlineSeconds: 600
|
||||
backoffLimit: 2
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: enviar
|
||||
image: docker.io/curlimages/curl:8.9.1
|
||||
imagePullPolicy: Never
|
||||
command: ["/bin/sh", "/script/enviar.sh"]
|
||||
env:
|
||||
- name: KEYCLOAK_URL
|
||||
value: http://keycloak.plataforma-prod.svc:8080/realms/athleticmap-2/protocol/openid-connect/token
|
||||
- name: ISSUER_HOST
|
||||
value: auth.athleticmap.com
|
||||
- name: DESTINO
|
||||
value: http://servico-captacao.plataforma-prod.svc/api/public/resumo-do-tenant/demo
|
||||
- name: CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: operacao-credentials
|
||||
key: client-secret
|
||||
- name: RESUMO_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: resumo-credentials
|
||||
key: token
|
||||
optional: true
|
||||
resources:
|
||||
requests: { cpu: 10m, memory: 32Mi }
|
||||
limits: { cpu: 200m, memory: 64Mi }
|
||||
volumeMounts:
|
||||
- name: script
|
||||
mountPath: /script
|
||||
volumes:
|
||||
- name: script
|
||||
configMap:
|
||||
name: resumo-cron
|
||||
@@ -0,0 +1,141 @@
|
||||
# =============================================================================
|
||||
# N16 — o resumo AGREGADO do tenant, entregue a plataforma uma vez por dia, para o
|
||||
# comprador ver todas as escolinhas dele lado a lado no /minha-conta.
|
||||
#
|
||||
# AGUARDANDO GRAVACAO no molde (`moldes/consolidado/` do GitOps) e nos tenants que
|
||||
# ja existem. Nada aqui foi aplicado.
|
||||
#
|
||||
# O desenho: o TENANT calcula (runtime-operacao, GET /api/resumo-do-tenant, so
|
||||
# contadores e somas) e o TENANT envia (este CronJob). A plataforma nao entra no
|
||||
# namespace nem no banco do tenant para isto.
|
||||
#
|
||||
# 1. token do client `operacao` no realm do tenant (o mesmo das tarefas do
|
||||
# financeiro: Secret `operacao-credentials`);
|
||||
# 2. GET http://runtime-operacao/api/resumo-do-tenant (lista de 1 ou 2 meses);
|
||||
# 3. POST http://servico-captacao.plataforma-prod.svc/api/public/resumo-do-tenant/escolinha
|
||||
# com o cabecalho `x-atm-resumo-token` — do Secret `resumo-credentials`, que
|
||||
# so vale para ESTE tenant (HMAC do nome dele com a chave da plataforma).
|
||||
#
|
||||
# A saida para a plataforma e pela internet (443 publico), que a deny-cross-tenant
|
||||
# ja libera: nao precisa de NetworkPolicy nova.
|
||||
#
|
||||
# `optional: true` no resumo-credentials: tenant sem o Secret (chave da plataforma
|
||||
# ainda nao configurada) roda o job, que termina OK dizendo "sem token" — nao gera
|
||||
# KubeJobFailed nem gasta a cota de e-mail dos alertas.
|
||||
# =============================================================================
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: resumo-cron
|
||||
namespace: escolinha-prod
|
||||
data:
|
||||
enviar.sh: |
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
: "${KEYCLOAK_URL:?falta KEYCLOAK_URL}"
|
||||
: "${CLIENT_SECRET:?falta CLIENT_SECRET}"
|
||||
: "${ISSUER_HOST:?falta ISSUER_HOST}"
|
||||
: "${DESTINO:?falta DESTINO}"
|
||||
|
||||
if [ -z "${RESUMO_TOKEN:-}" ]; then
|
||||
echo "sem o Secret resumo-credentials neste tenant: nada a enviar."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
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
|
||||
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
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Os tokens vao por `-K -` (stdin), e nao na linha de comando: argumento de
|
||||
# processo aparece em `ps` para quem estiver no no.
|
||||
CODIGO="$(printf 'header = "Authorization: Bearer %s"\n' "${TOKEN}" \
|
||||
| curl -sS -K - -o /tmp/resumo.json -w '%{http_code}' http://runtime-operacao/api/resumo-do-tenant)"
|
||||
if [ "${CODIGO}" != "200" ]; then
|
||||
echo "ERRO: o runtime-operacao respondeu ${CODIGO} ao resumo." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "resumo calculado: $(wc -c < /tmp/resumo.json) bytes (so numeros)"
|
||||
|
||||
CODIGO="$(printf 'header = "x-atm-resumo-token: %s"\n' "${RESUMO_TOKEN}" \
|
||||
| curl -sS -K - -X POST "${DESTINO}" -H 'Content-Type: application/json' \
|
||||
--data-binary @/tmp/resumo.json -o /tmp/saida.json -w '%{http_code}')"
|
||||
echo "plataforma: ${CODIGO}"
|
||||
cat /tmp/saida.json; echo
|
||||
case "${CODIGO}" in
|
||||
2*) ;;
|
||||
*) echo "ERRO: a plataforma respondeu ${CODIGO}." >&2; exit 1 ;;
|
||||
esac
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: resumo-para-a-plataforma
|
||||
namespace: escolinha-prod
|
||||
spec:
|
||||
# Madrugada, depois da virada do dia em Sao Paulo e fora do horario das
|
||||
# mensalidades (dia 1, 06h).
|
||||
schedule: "30 4 * * *"
|
||||
timeZone: America/Sao_Paulo
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 5
|
||||
jobTemplate:
|
||||
spec:
|
||||
activeDeadlineSeconds: 600
|
||||
backoffLimit: 2
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: enviar
|
||||
image: docker.io/curlimages/curl:8.9.1
|
||||
imagePullPolicy: Never
|
||||
command: ["/bin/sh", "/script/enviar.sh"]
|
||||
env:
|
||||
- name: KEYCLOAK_URL
|
||||
value: http://keycloak.plataforma-prod.svc:8080/realms/athleticmap-4/protocol/openid-connect/token
|
||||
- name: ISSUER_HOST
|
||||
value: auth.athleticmap.com
|
||||
- name: DESTINO
|
||||
value: http://servico-captacao.plataforma-prod.svc/api/public/resumo-do-tenant/escolinha
|
||||
- name: CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: operacao-credentials
|
||||
key: client-secret
|
||||
- name: RESUMO_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: resumo-credentials
|
||||
key: token
|
||||
optional: true
|
||||
resources:
|
||||
requests: { cpu: 10m, memory: 32Mi }
|
||||
limits: { cpu: 200m, memory: 64Mi }
|
||||
volumeMounts:
|
||||
- name: script
|
||||
mountPath: /script
|
||||
volumes:
|
||||
- name: script
|
||||
configMap:
|
||||
name: resumo-cron
|
||||
@@ -0,0 +1,141 @@
|
||||
# =============================================================================
|
||||
# N16 — o resumo AGREGADO do tenant, entregue a plataforma uma vez por dia, para o
|
||||
# comprador ver todas as escolinhas dele lado a lado no /minha-conta.
|
||||
#
|
||||
# AGUARDANDO GRAVACAO no molde (`moldes/consolidado/` do GitOps) e nos tenants que
|
||||
# ja existem. Nada aqui foi aplicado.
|
||||
#
|
||||
# O desenho: o TENANT calcula (runtime-operacao, GET /api/resumo-do-tenant, so
|
||||
# contadores e somas) e o TENANT envia (este CronJob). A plataforma nao entra no
|
||||
# namespace nem no banco do tenant para isto.
|
||||
#
|
||||
# 1. token do client `operacao` no realm do tenant (o mesmo das tarefas do
|
||||
# financeiro: Secret `operacao-credentials`);
|
||||
# 2. GET http://runtime-operacao/api/resumo-do-tenant (lista de 1 ou 2 meses);
|
||||
# 3. POST http://servico-captacao.plataforma-prod.svc/api/public/resumo-do-tenant/piloto
|
||||
# com o cabecalho `x-atm-resumo-token` — do Secret `resumo-credentials`, que
|
||||
# so vale para ESTE tenant (HMAC do nome dele com a chave da plataforma).
|
||||
#
|
||||
# A saida para a plataforma e pela internet (443 publico), que a deny-cross-tenant
|
||||
# ja libera: nao precisa de NetworkPolicy nova.
|
||||
#
|
||||
# `optional: true` no resumo-credentials: tenant sem o Secret (chave da plataforma
|
||||
# ainda nao configurada) roda o job, que termina OK dizendo "sem token" — nao gera
|
||||
# KubeJobFailed nem gasta a cota de e-mail dos alertas.
|
||||
# =============================================================================
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: resumo-cron
|
||||
namespace: piloto-prod
|
||||
data:
|
||||
enviar.sh: |
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
: "${KEYCLOAK_URL:?falta KEYCLOAK_URL}"
|
||||
: "${CLIENT_SECRET:?falta CLIENT_SECRET}"
|
||||
: "${ISSUER_HOST:?falta ISSUER_HOST}"
|
||||
: "${DESTINO:?falta DESTINO}"
|
||||
|
||||
if [ -z "${RESUMO_TOKEN:-}" ]; then
|
||||
echo "sem o Secret resumo-credentials neste tenant: nada a enviar."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
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
|
||||
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
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Os tokens vao por `-K -` (stdin), e nao na linha de comando: argumento de
|
||||
# processo aparece em `ps` para quem estiver no no.
|
||||
CODIGO="$(printf 'header = "Authorization: Bearer %s"\n' "${TOKEN}" \
|
||||
| curl -sS -K - -o /tmp/resumo.json -w '%{http_code}' http://runtime-operacao/api/resumo-do-tenant)"
|
||||
if [ "${CODIGO}" != "200" ]; then
|
||||
echo "ERRO: o runtime-operacao respondeu ${CODIGO} ao resumo." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "resumo calculado: $(wc -c < /tmp/resumo.json) bytes (so numeros)"
|
||||
|
||||
CODIGO="$(printf 'header = "x-atm-resumo-token: %s"\n' "${RESUMO_TOKEN}" \
|
||||
| curl -sS -K - -X POST "${DESTINO}" -H 'Content-Type: application/json' \
|
||||
--data-binary @/tmp/resumo.json -o /tmp/saida.json -w '%{http_code}')"
|
||||
echo "plataforma: ${CODIGO}"
|
||||
cat /tmp/saida.json; echo
|
||||
case "${CODIGO}" in
|
||||
2*) ;;
|
||||
*) echo "ERRO: a plataforma respondeu ${CODIGO}." >&2; exit 1 ;;
|
||||
esac
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: resumo-para-a-plataforma
|
||||
namespace: piloto-prod
|
||||
spec:
|
||||
# Madrugada, depois da virada do dia em Sao Paulo e fora do horario das
|
||||
# mensalidades (dia 1, 06h).
|
||||
schedule: "30 4 * * *"
|
||||
timeZone: America/Sao_Paulo
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 5
|
||||
jobTemplate:
|
||||
spec:
|
||||
activeDeadlineSeconds: 600
|
||||
backoffLimit: 2
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: enviar
|
||||
image: docker.io/curlimages/curl:8.9.1
|
||||
imagePullPolicy: Never
|
||||
command: ["/bin/sh", "/script/enviar.sh"]
|
||||
env:
|
||||
- name: KEYCLOAK_URL
|
||||
value: http://keycloak.plataforma-prod.svc:8080/realms/athleticmap-1/protocol/openid-connect/token
|
||||
- name: ISSUER_HOST
|
||||
value: auth.athleticmap.com
|
||||
- name: DESTINO
|
||||
value: http://servico-captacao.plataforma-prod.svc/api/public/resumo-do-tenant/piloto
|
||||
- name: CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: operacao-credentials
|
||||
key: client-secret
|
||||
- name: RESUMO_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: resumo-credentials
|
||||
key: token
|
||||
optional: true
|
||||
resources:
|
||||
requests: { cpu: 10m, memory: 32Mi }
|
||||
limits: { cpu: 200m, memory: 64Mi }
|
||||
volumeMounts:
|
||||
- name: script
|
||||
mountPath: /script
|
||||
volumes:
|
||||
- name: script
|
||||
configMap:
|
||||
name: resumo-cron
|
||||
Reference in New Issue
Block a user