From 142b28be80e657e5d080b0a5455788e1165672a5 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 5 Nov 2026 17:11:13 +0500 Subject: [PATCH] =?UTF-8?q?uralkal:=20django=20=E2=80=94=20Job=20upload-ob?= =?UTF-8?q?lako-las=20=D1=81=D0=BA=D0=B0=D1=87=D0=B8=D0=B2=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=20=D0=9E=D0=B1=D0=BB=D0=B0=D0=BA=D0=BE.las=20=D0=B8=20?= =?UTF-8?q?=D0=BA=D0=BB=D0=B0=D0=B4=D1=91=D1=82=20=D0=B2=20MinIO=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=BA=D0=B5=D1=82=20django?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/django/uralkal/kustomization.yaml | 1 + apps/django/uralkal/upload-oblako-job.yaml | 113 +++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 apps/django/uralkal/upload-oblako-job.yaml diff --git a/apps/django/uralkal/kustomization.yaml b/apps/django/uralkal/kustomization.yaml index 19ccdd1..7300431 100644 --- a/apps/django/uralkal/kustomization.yaml +++ b/apps/django/uralkal/kustomization.yaml @@ -6,6 +6,7 @@ resources: - kc-sync-cronjob.yaml - zitadel-action-configmap.yaml - zitadel-action-job.yaml + - upload-oblako-job.yaml patches: - path: nginx-configmap.yaml target: diff --git a/apps/django/uralkal/upload-oblako-job.yaml b/apps/django/uralkal/upload-oblako-job.yaml new file mode 100644 index 0000000..63095ac --- /dev/null +++ b/apps/django/uralkal/upload-oblako-job.yaml @@ -0,0 +1,113 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: upload-oblako-las + namespace: django + annotations: + kustomize.toolkit.fluxcd.io/force: enabled +spec: + backoffLimit: 1 + activeDeadlineSeconds: 10800 + template: + metadata: + annotations: + sidecar.istio.io/inject: "false" + vault.hashicorp.com/agent-inject: "true" + vault.hashicorp.com/agent-pre-populate-only: "true" + vault.hashicorp.com/auth-path: auth/kubernetes + vault.hashicorp.com/role: django + vault.hashicorp.com/agent-inject-secret-minio: secrets/data/minio/apps/django + vault.hashicorp.com/agent-inject-template-minio: |- + {{- with secret "secrets/data/minio/apps/django" -}} + export MINIO_ACCESS_KEY='{{ index .Data.data "access_key" }}' + export MINIO_SECRET_KEY='{{ index .Data.data "secret_key" }}' + {{- end -}} + spec: + serviceAccountName: django-vault + automountServiceAccountToken: true + restartPolicy: Never + imagePullSecrets: + - name: regcred + containers: + - name: upload + image: cr.yandex/crp3ccidau046kdj8g9q/mc-files:dev5 + imagePullPolicy: IfNotPresent + command: ["/bin/bash", "-euo", "pipefail", "-c"] + args: + - | + log() { echo "$(date -u '+%Y-%m-%dT%H:%M:%SZ') $*"; } + . /vault/secrets/minio + F="/work/$OBJECT_NAME" + + log "step 1/5: free space in /work" + df -h /work + avail=$(df -Pk /work | awk 'NR==2 {print $4 * 1024}') + log "available ${avail} bytes, need ${EXPECTED_SIZE}" + if [ "$avail" -lt "$EXPECTED_SIZE" ]; then + log "ERROR: not enough space"; exit 1 + fi + + log "step 2/5: download from Yandex Object Storage" + curl -fsS --retry 5 --retry-delay 10 -C - -o "$F" "$SOURCE_URL" & + pid=$! + while kill -0 "$pid" 2>/dev/null; do + sleep 15 + size=$(stat -c %s "$F" 2>/dev/null || echo 0) + log "downloaded ${size} / ${EXPECTED_SIZE} bytes ($((size * 100 / EXPECTED_SIZE))%)" + done + wait "$pid" || { log "ERROR: curl failed with code $?"; exit 1; } + size=$(stat -c %s "$F") + log "download finished, ${size} bytes" + if [ "$size" -ne "$EXPECTED_SIZE" ]; then + log "ERROR: size mismatch"; exit 1 + fi + + log "step 3/5: connect to MinIO ${MINIO_ENDPOINT}" + mc alias set target "$MINIO_ENDPOINT" "$MINIO_ACCESS_KEY" "$MINIO_SECRET_KEY" >/dev/null + if ! mc ls "target/$BUCKET" >/dev/null; then + log "ERROR: bucket $BUCKET is not reachable with django credentials"; exit 1 + fi + log "bucket $BUCKET is reachable" + + log "step 4/5: upload to $BUCKET/$OBJECT_NAME" + mc cp --quiet "$F" "target/$BUCKET/$OBJECT_NAME" & + pid=$! + while kill -0 "$pid" 2>/dev/null; do + sleep 30 + log "upload in progress" + done + wait "$pid" || { log "ERROR: mc cp failed with code $?"; exit 1; } + + log "step 5/5: verify" + mc stat "target/$BUCKET/$OBJECT_NAME" + remote=$(mc stat --json "target/$BUCKET/$OBJECT_NAME" | sed -n 's/.*"size":\([0-9]*\).*/\1/p') + if [ "$remote" != "$EXPECTED_SIZE" ]; then + log "ERROR: remote size ${remote} != ${EXPECTED_SIZE}"; exit 1 + fi + rm -f "$F" + log "done: $BUCKET/$OBJECT_NAME, ${remote} bytes" + env: + - name: SOURCE_URL + value: "https://storage.yandexcloud.net/documentations-prod-270-dlia-stateisarex/7937275e-967e-452e-b79d-b1991bca1dd4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=YCAJEOB86NUJTIBSnlwY_OvTI%2F20261105%2Fru-central1%2Fs3%2Faws4_request&X-Amz-Date=20261105T120651Z&X-Amz-Expires=259200&X-Amz-Signature=423bf587fbf89ba6a3b10bda57f37100bfcd72c3a6ba84a3c91eec922364c088&X-Amz-SignedHeaders=host&response-content-disposition=attachment" + - name: EXPECTED_SIZE + value: "5488991489" + - name: MINIO_ENDPOINT + value: http://10.133.0.245:9000 + - name: BUCKET + value: django + - name: OBJECT_NAME + value: Облако.las + resources: + requests: + cpu: 100m + memory: 256Mi + ephemeral-storage: 6Gi + limits: + ephemeral-storage: 7Gi + volumeMounts: + - name: work + mountPath: /work + volumes: + - name: work + emptyDir: + sizeLimit: 7Gi