From 045aa8637801e57d502a610bcbbaeb8d0bc9a5d5 Mon Sep 17 00:00:00 2001 From: Mulder Date: Fri, 26 Apr 2024 10:40:27 -0700 Subject: [PATCH] DBC22-2085: Backup Media and improve log handling --- .github/workflows/dev.yml | 14 +-- .github/workflows/prod.yml | 6 +- .github/workflows/test.yml | 14 +-- .github/workflows/test_manual.yml | 14 +-- .github/workflows/uat.yml | 6 +- compose/logprocessing/DockerFile | 16 --- compose/logprocessing/entrypoint.sh | 86 -------------- compose/openshiftjobs/DockerFile | 23 ++++ compose/openshiftjobs/entrypoint.sh | 28 +++++ .../scripts/analyzeexportlogs.sh | 107 ++++++++++++++++++ .../openshiftjobs/scripts/backupmediapvc.sh | 36 ++++++ compose/openshiftjobs/scripts/ziplogs.sh | 21 ++++ infrastructure/_logprocessing/README.md | 27 ----- infrastructure/_logprocessing/values.yaml | 21 ---- .../.helmignore | 0 .../Chart.yaml | 2 +- infrastructure/_openshiftjobs/README.md | 32 ++++++ .../templates/_helpers.tpl | 0 .../templates/analyzeuploadlogs-cronjob.yaml | 57 ++++++++++ .../templates/backupmediapvc-cronjob.yaml | 58 ++++++++++ .../templates/ziplogs-cronjob.yaml} | 23 ++-- infrastructure/_openshiftjobs/values.yaml | 55 +++++++++ infrastructure/main/Chart.lock | 8 +- infrastructure/main/Chart.yaml | 6 +- infrastructure/main/charts/django-0.1.0.tgz | Bin 3509 -> 3510 bytes .../main/charts/logprocessing-0.1.0.tgz | Bin 2185 -> 0 bytes .../main/charts/openshiftjobs-0.1.0.tgz | Bin 0 -> 2689 bytes infrastructure/main/charts/redis-0.1.0.tgz | Bin 2214 -> 2214 bytes infrastructure/main/charts/static-0.1.0.tgz | Bin 3180 -> 3180 bytes infrastructure/main/charts/tasks-0.1.0.tgz | Bin 2595 -> 2596 bytes infrastructure/main/values-dev.yaml | 68 ++++++++--- infrastructure/main/values-prod.yaml | 69 ++++++++--- infrastructure/main/values-test.yaml | 68 ++++++++--- infrastructure/main/values-uat.yaml | 68 ++++++++--- infrastructure/main/values.yaml | 67 ++++++++--- 35 files changed, 721 insertions(+), 279 deletions(-) delete mode 100644 compose/logprocessing/DockerFile delete mode 100644 compose/logprocessing/entrypoint.sh create mode 100644 compose/openshiftjobs/DockerFile create mode 100644 compose/openshiftjobs/entrypoint.sh create mode 100644 compose/openshiftjobs/scripts/analyzeexportlogs.sh create mode 100644 compose/openshiftjobs/scripts/backupmediapvc.sh create mode 100644 compose/openshiftjobs/scripts/ziplogs.sh delete mode 100644 infrastructure/_logprocessing/README.md delete mode 100644 infrastructure/_logprocessing/values.yaml rename infrastructure/{_logprocessing => _openshiftjobs}/.helmignore (100%) rename infrastructure/{_logprocessing => _openshiftjobs}/Chart.yaml (98%) create mode 100644 infrastructure/_openshiftjobs/README.md rename infrastructure/{_logprocessing => _openshiftjobs}/templates/_helpers.tpl (100%) create mode 100644 infrastructure/_openshiftjobs/templates/analyzeuploadlogs-cronjob.yaml create mode 100644 infrastructure/_openshiftjobs/templates/backupmediapvc-cronjob.yaml rename infrastructure/{_logprocessing/templates/logprocessing-deployment.yaml => _openshiftjobs/templates/ziplogs-cronjob.yaml} (64%) create mode 100644 infrastructure/_openshiftjobs/values.yaml delete mode 100644 infrastructure/main/charts/logprocessing-0.1.0.tgz create mode 100644 infrastructure/main/charts/openshiftjobs-0.1.0.tgz diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 117a039a7..b4d5b9a2f 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -106,9 +106,9 @@ jobs: username: ${{ env.REGISTRY_USER }} password: ${{ env.REGISTRY_PASSWORD }} - build-logprocessing: + build-openshiftjobs: runs-on: ubuntu-latest - name: Build & Push Docker Log Processing Image + name: Build & Push Docker OpenShift Jobs Image environment: name: dev @@ -116,17 +116,17 @@ jobs: - name: Checkout Code uses: actions/checkout@v4 - - name: Build Log Processing + - name: Build OpenShift Jobs id: build_image uses: redhat-actions/buildah-build@v2 with: context: . layers: true - image: drivebc-logprocessing + image: drivebc-openshiftjobs tags: latest latest-dev ${{ github.sha }} labels: | app=drivebc - containerfiles: ./compose/logprocessing/DockerFile + containerfiles: ./compose/openshiftjobs/DockerFile - name: Push to Github Packages uses: redhat-actions/push-to-registry@v2 @@ -138,7 +138,7 @@ jobs: password: ${{ env.REGISTRY_PASSWORD }} versionUpdate: - needs: [build-static, build-backend, build-redis, build-logprocessing] + needs: [build-static, build-backend, build-redis, build-openshiftjobs] runs-on: ubuntu-latest name: Deploy Latest Images environment: @@ -159,4 +159,4 @@ jobs: - name: Helm upgrade on OpenShift Environment run: | helm dependency update ./infrastructure/main - helm upgrade dev-drivebc -f ./infrastructure/main/values-dev.yaml ./infrastructure/main --set django.image.tag="${{ github.sha }}" --set redis.image.tag="${{ github.sha }}" --set static.image.tag="${{ github.sha }}" --set tasks.image.tag="${{ github.sha }}" --set logprocessing.image.tag="${{ github.sha }}" + helm upgrade dev-drivebc -f ./infrastructure/main/values-dev.yaml ./infrastructure/main --set django.image.tag="${{ github.sha }}" --set redis.image.tag="${{ github.sha }}" --set static.image.tag="${{ github.sha }}" --set tasks.image.tag="${{ github.sha }}" --set openshiftjobs.image.tag="${{ github.sha }}" diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml index fe58976c7..951df32a0 100644 --- a/.github/workflows/prod.yml +++ b/.github/workflows/prod.yml @@ -59,11 +59,11 @@ jobs: tags: | latest-prod - - name: Add latest-uat tag to logprocessing image + - name: Add latest-uat tag to openshiftjobs image uses: shrink/actions-docker-registry-tag@v4 with: registry: ghcr.io - repository: bcgov/drivebc-logprocessing + repository: bcgov/drivebc-openshiftjobs target: ${{ needs.deploy-pre.outputs.tag }} tags: | latest-prod @@ -90,4 +90,4 @@ jobs: - name: Helm upgrade on OpenShift Environment run: | helm dependency update ./infrastructure/main - helm upgrade prod-drivebc -f ./infrastructure/main/values-prod.yaml ./infrastructure/main --set django.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set redis.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set static.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set tasks.image.tag="${{ needs.deploy-pre.outputs.tag }}" \ No newline at end of file + helm upgrade prod-drivebc -f ./infrastructure/main/values-prod.yaml ./infrastructure/main --set django.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set redis.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set static.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set tasks.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set openshiftjobs.image.tag="${{ needs.deploy-pre.outputs.tag }}" \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 272a052d1..6aea34366 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -152,25 +152,25 @@ jobs: username: ${{ env.REGISTRY_USER }} password: ${{ env.REGISTRY_PASSWORD }} - build-logprocessing: + build-openshiftjobs: needs: [build-pre] runs-on: ubuntu-latest - name: Build & Push Docker Log-Processing Image + name: Build & Push Docker OpenShift Jobs Image environment: test steps: - name: Checkout Code uses: actions/checkout@v4 - - name: Build Log-Processing + - name: Build OpenShift Jobs id: build_image uses: redhat-actions/buildah-build@v2 with: - image: drivebc-logprocessing + image: drivebc-openshiftjobs tags: latest latest-test ${{ github.sha }} ${{ needs.build-pre.outputs.tag }} labels: | app=drivebc - containerfiles: ./compose/logprocessing/DockerFile + containerfiles: ./compose/openshiftjobs/DockerFile - name: Push to Github Packages uses: redhat-actions/push-to-registry@v2 @@ -182,7 +182,7 @@ jobs: password: ${{ env.REGISTRY_PASSWORD }} versionUpdate: - needs: [build-pre, build-static, build-backend, build-redis, build-logprocessing] + needs: [build-pre, build-static, build-backend, build-redis, build-openshiftjobs] runs-on: ubuntu-latest name: Deploy Latest Images environment: @@ -205,4 +205,4 @@ jobs: - name: Helm upgrade on OpenShift Environment run: | helm dependency update ./infrastructure/main - helm upgrade test-drivebc -f ./infrastructure/main/values-test.yaml ./infrastructure/main --set django.image.tag="${{ needs.build-pre.outputs.tag }}" --set redis.image.tag="${{ needs.build-pre.outputs.tag }}" --set static.image.tag="${{ needs.build-pre.outputs.tag }}" --set tasks.image.tag="${{ needs.build-pre.outputs.tag }}" --set logprocessing.image.tag="${{ needs.build-pre.outputs.tag }}" + helm upgrade test-drivebc -f ./infrastructure/main/values-test.yaml ./infrastructure/main --set django.image.tag="${{ needs.build-pre.outputs.tag }}" --set redis.image.tag="${{ needs.build-pre.outputs.tag }}" --set static.image.tag="${{ needs.build-pre.outputs.tag }}" --set tasks.image.tag="${{ needs.build-pre.outputs.tag }}" --set openshiftjobs.image.tag="${{ needs.build-pre.outputs.tag }}" diff --git a/.github/workflows/test_manual.yml b/.github/workflows/test_manual.yml index 1d5f0bcf1..acbaa07b0 100644 --- a/.github/workflows/test_manual.yml +++ b/.github/workflows/test_manual.yml @@ -131,25 +131,25 @@ jobs: username: ${{ env.REGISTRY_USER }} password: ${{ env.REGISTRY_PASSWORD }} - build-logprocessing: + build-openshiftjobs: needs: [build-pre] runs-on: ubuntu-latest - name: Build & Push Docker Log-Processing Image + name: Build & Push Docker OpenShift Jobs Image environment: test steps: - name: Checkout Code uses: actions/checkout@v4 - - name: Build Log-Processing + - name: Build OpenShift Jobs id: build_image uses: redhat-actions/buildah-build@v2 with: - image: drivebc-logprocessing + image: drivebc-openshiftjobs tags: latest latest-test ${{ github.sha }} ${{ needs.build-pre.outputs.tag }} labels: | app=drivebc - containerfiles: ./compose/logprocessing/DockerFile + containerfiles: ./compose/openshiftjobs/DockerFile - name: Push to Github Packages uses: redhat-actions/push-to-registry@v2 @@ -161,7 +161,7 @@ jobs: password: ${{ env.REGISTRY_PASSWORD }} versionUpdate: - needs: [build-pre, build-static, build-backend, build-redis, build-logprocessing] + needs: [build-pre, build-static, build-backend, build-redis, build-openshiftjobs] runs-on: ubuntu-latest name: Deploy Latest Images environment: @@ -184,4 +184,4 @@ jobs: - name: Helm upgrade on OpenShift Environment run: | helm dependency update ./infrastructure/main - helm upgrade test-drivebc -f ./infrastructure/main/values-test.yaml ./infrastructure/main --set django.image.tag="${{ needs.build-pre.outputs.tag }}" --set redis.image.tag="${{ needs.build-pre.outputs.tag }}" --set static.image.tag="${{ needs.build-pre.outputs.tag }}" --set tasks.image.tag="${{ needs.build-pre.outputs.tag }}" --set logprocessing.image.tag="${{ needs.build-pre.outputs.tag }}" \ No newline at end of file + helm upgrade test-drivebc -f ./infrastructure/main/values-test.yaml ./infrastructure/main --set django.image.tag="${{ needs.build-pre.outputs.tag }}" --set redis.image.tag="${{ needs.build-pre.outputs.tag }}" --set static.image.tag="${{ needs.build-pre.outputs.tag }}" --set tasks.image.tag="${{ needs.build-pre.outputs.tag }}" --set openshiftjobs.image.tag="${{ needs.build-pre.outputs.tag }}" \ No newline at end of file diff --git a/.github/workflows/uat.yml b/.github/workflows/uat.yml index 6b048885e..057781293 100644 --- a/.github/workflows/uat.yml +++ b/.github/workflows/uat.yml @@ -61,11 +61,11 @@ jobs: tags: | latest-uat - - name: Add latest-uat tag to logprocessing image + - name: Add latest-uat tag to openshiftjobs image uses: shrink/actions-docker-registry-tag@v4 with: registry: ghcr.io - repository: bcgov/drivebc-logprocessing + repository: bcgov/drivebc-openshiftjobs target: ${{ needs.deploy-pre.outputs.tag }} tags: | latest-uat @@ -92,4 +92,4 @@ jobs: - name: Helm upgrade on OpenShift Environment run: | helm dependency update ./infrastructure/main - helm upgrade uat-drivebc -f ./infrastructure/main/values-uat.yaml ./infrastructure/main --set django.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set redis.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set static.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set tasks.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set logprocessing.image.tag="${{ needs.deploy-pre.outputs.tag }}" \ No newline at end of file + helm upgrade uat-drivebc -f ./infrastructure/main/values-uat.yaml ./infrastructure/main --set django.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set redis.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set static.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set tasks.image.tag="${{ needs.deploy-pre.outputs.tag }}" --set openshiftjobs.image.tag="${{ needs.deploy-pre.outputs.tag }}" \ No newline at end of file diff --git a/compose/logprocessing/DockerFile b/compose/logprocessing/DockerFile deleted file mode 100644 index ed54841e2..000000000 --- a/compose/logprocessing/DockerFile +++ /dev/null @@ -1,16 +0,0 @@ -FROM alpine:3 -RUN apk update && apk upgrade -#Need goaccess 1.92 for a timezone fix. Once that version is in the regular branch, we can pull it from there. -RUN apk add goaccess --repository=https://dl-cdn.alpinelinux.org/alpine/edge/main - -RUN apk add --no-cache \ - aws-cli \ - bash \ - coreutils \ - tzdata - -COPY ./compose/logprocessing/entrypoint.sh / - -RUN sed -i 's/\r$//g' /entrypoint.sh && chmod +x /entrypoint.sh - -ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/compose/logprocessing/entrypoint.sh b/compose/logprocessing/entrypoint.sh deleted file mode 100644 index 02fa1fbcc..000000000 --- a/compose/logprocessing/entrypoint.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash - -cd logs - -# Initialize an empty array -zipped_files=() - -# Get yesterday's start and end time in the America/Vancouver timezone -yesterday_start=$(TZ=America/Vancouver date -d "yesterday 00:00") -yesterday_end=$(TZ=America/Vancouver date -d "yesterday 23:59") - -# Convert yesterday's start and end time to UTC -yesterday_start_utc=$(date -u -d "$yesterday_start" +%Y%m%d%H) -yesterday_end_utc=$(date -u -d "$yesterday_end" +%Y%m%d%H) - -# Loop through all files in the current directory ending with ".log" -for file in *.log; do - # Check if the file exists and is a regular file - if [[ -f $file ]]; then - # Extract the date and time part from the filename (assuming UTC timezone) - file_datetime_utc=$(echo "$file" | grep -oE '[0-9]{10}') - # Check if the file date and time in UTC falls within yesterday's start and end time in UTC - if [[ $file_datetime_utc -ge $yesterday_start_utc && $file_datetime_utc -le $yesterday_end_utc ]]; then - # Echo the filename - echo "Zipping $file..." - # Gzip the file - gzip "$file" - # Add the zipped filename to the array - zipped_files+=("$file.gz") - fi - fi -done - -# Print the elements of the array -echo "Log files that will be processed:" -printf '%s\n' "${zipped_files[@]}" - -# Get yesterday's start formatted date in the America/Vancouver timezone -yesterday_start_formatted=$(TZ=America/Vancouver date -d "yesterday 00:00" +%Y%m%d) - -# Run the following command only if zipped_files array is not empty -if [ ${#zipped_files[@]} -gt 0 ]; then - #Run goaccess on all the log files from yesterday - goaccess_report_name=$yesterday_start_formatted-goaccess_report.html - zcat "${zipped_files[@]}" | goaccess - -o "$goaccess_report_name" --log-format='%h %e %^[%x] "%r" %s %b "%R" "%u" %C "%M" %T' --datetime-format='%d/%b/%Y:%H:%M:%S %z' --ignore-panel=REMOTE_USER --tz=America/Vancouver --jobs=2 - echo "GoAccess report generated successfully at $goaccess_report_name" - - # Get current date in YYYYMMDD format - year=$(TZ=America/Vancouver date -d "yesterday" +"%Y") - month=$(TZ=America/Vancouver date -d "yesterday" +"%m") - day=$(TZ=America/Vancouver date -d "yesterday" +"%d") - - # Create folder structure in S3 bucket - s3_path="s3://$AWS_BUCKET/$year/$month/$day/" - - # Upload zipped files to S3 - for file in "${zipped_files[@]}"; do - aws --endpoint-url "$AWS_ENDPOINT" s3 cp "$file" "$s3_path" - if [ $? -eq 0 ]; then - echo "File $file copied to S3 bucket under $s3_path" - else - echo "Failed to upload $file to S3. Exiting..." - exit 1 - fi - done - - echo "All files copied to S3 bucket under $s3_path" - - - # Upload HTML report to S3 - aws --endpoint-url $AWS_ENDPOINT s3 cp "$goaccess_report_name" "$s3_path" - if [ $? -eq 0 ]; then - echo "HTML report copied to S3 bucket under $s3_path" - else - echo "Failed to upload HTML report to S3. Exiting..." - exit 1 - fi - - # Delete the zipped files and HTML report - rm "${zipped_files[@]}" "$goaccess_report_name" - - echo "Zipped Files and HTML report deleted from PVC successfully" - -else - echo "No files to process for $yesterday_start_formatted" -fi \ No newline at end of file diff --git a/compose/openshiftjobs/DockerFile b/compose/openshiftjobs/DockerFile new file mode 100644 index 000000000..b9cfc31d5 --- /dev/null +++ b/compose/openshiftjobs/DockerFile @@ -0,0 +1,23 @@ +FROM alpine:3 +RUN apk update && apk upgrade +#Need goaccess 1.92 for a timezone fix. Once that version is in the regular branch, we can pull it from there. +RUN apk add goaccess --repository=https://dl-cdn.alpinelinux.org/alpine/edge/main + +RUN apk add --no-cache \ + aws-cli \ + bash \ + coreutils \ + tzdata + +COPY ./compose/openshiftjobs/entrypoint.sh / +COPY ./compose/openshiftjobs/scripts/analyzeexportlogs.sh /scripts/ +COPY ./compose/openshiftjobs/scripts/backupmediapvc.sh /scripts/ +COPY ./compose/openshiftjobs/scripts/ziplogs.sh /scripts/ + +RUN sed -i 's/\r$//g' /entrypoint.sh && chmod +x /entrypoint.sh +RUN sed -i 's/\r$//g' /scripts/analyzeexportlogs.sh && chmod +x /scripts/analyzeexportlogs.sh +RUN sed -i 's/\r$//g' /scripts/backupmediapvc.sh && chmod +x /scripts/backupmediapvc.sh +RUN sed -i 's/\r$//g' /scripts/ziplogs.sh && chmod +x /scripts/ziplogs.sh + + +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/compose/openshiftjobs/entrypoint.sh b/compose/openshiftjobs/entrypoint.sh new file mode 100644 index 000000000..70d313f92 --- /dev/null +++ b/compose/openshiftjobs/entrypoint.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Check the number of arguments +if [ "$#" -lt 1 ]; then + echo "Usage: $0 [args...]" + exit 1 +fi + +# Determine which script to run based on the first argument +case "$1" in + backupmediapvc) + # Run backupmediapvc.sh which will backup the data from the django-media pvc to s3 storage + /scripts/backupmediapvc.sh + ;; + ziplogs) + # Run ziplogs.sh which will zip all files that were created in the previous hour or older in the nginx log storage pvc + /scripts/ziplogs.sh + ;; + analyzeexportlogs) + # Run analyzeexportlogs with additional arguments which will send the specified days logs through goaccess and then upload to s3. + shift # Remove the first argument (script number) + /scripts/analyzeexportlogs.sh "$@" + ;; + *) + echo "Invalid script" + exit 1 + ;; +esac diff --git a/compose/openshiftjobs/scripts/analyzeexportlogs.sh b/compose/openshiftjobs/scripts/analyzeexportlogs.sh new file mode 100644 index 000000000..4288636e6 --- /dev/null +++ b/compose/openshiftjobs/scripts/analyzeexportlogs.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +# Directory where the logs are stored +log_dir="/logs" +cd $log_dir || { echo "Failed to change directory to $log_dir. Exiting..."; exit 1; } + +# Initialize an empty array +zipped_files=() + +# Get the number of days ago as a positional parameter +days_ago="$1" + +# If no argument is provided, default to 1 day ago +if [ -z "$days_ago" ]; then + days_ago=1 +fi + +# Get the start and end time for $days_ago days ago in the America/Vancouver timezone +start_time=$(TZ=America/Vancouver date -d "$days_ago days ago 00:00") +end_time=$(TZ=America/Vancouver date -d "$days_ago days ago 23:59") + +# Convert the start and end time to UTC +start_time_utc=$(date -u -d "$start_time" +%Y%m%d%H) +end_time_utc=$(date -u -d "$end_time" +%Y%m%d%H) + +echo "Will analyze and archive logs between $start_time_utc and $end_time_utc" + +# Loop through all files in the current directory ending with ".gz" +for file in *.gz; do + # Check if the file exists and is a regular file + if [[ -f $file ]]; then + # Extract the date and time part from the filename (assuming UTC timezone) + file_datetime_utc=$(echo "$file" | grep -oE '[0-9]{10}') + # Check if the file date and time in UTC falls within days_ago's start and end time in UTC + if [[ $file_datetime_utc -ge $start_time_utc && $file_datetime_utc -le $end_time_utc ]]; then + zipped_files+=("$file") + fi + fi +done + +# Print the elements of the array +echo "Log files that will be processed:" +printf '%s\n' "${zipped_files[@]}" + +# Get the start dates formatted for the goaccess report name +start_time_formatted=$(date -d "$start_time" +%Y%m%d) + +# Run the following command only if zipped_files array is not empty +if [ ${#zipped_files[@]} -gt 0 ]; then + # Define file URL and destination directory to pull down the latest geoip data + FILE_URL="https://download.db-ip.com/free/dbip-city-lite-$(date -u +'%Y-%m').mmdb.gz" + OLD_FILE="dbip-city-lite-$(date -d 'last month' +'%Y-%m').mmdb" + + # Check if the file exists + if [ ! -f "dbip-city-lite-$(date -u +'%Y-%m').mmdb" ]; then + # If the file doesn't exist, download it + echo "Downloading file..." + if wget -q --spider "$FILE_URL"; then + wget "$FILE_URL" -P "$log_dir" + echo "Download complete." + gzip -d "dbip-city-lite-$(date -u +'%Y-%m').mmdb.gz" + # Delete the old file if it exists + if [ -f "$OLD_FILE" ]; then + echo "Deleting old file ($OLD_FILE)..." + rm "$OLD_FILE" + echo "Old file deleted." + fi + else + echo "Failed to download file. URL is unreachable." + fi + else + echo "MMDB file already exists." + fi + mmdb_file=$(find . -maxdepth 1 -type f -name "*.mmdb") + + #Run goaccess on all the log files from the date entered + goaccess_report_name=$start_time_formatted-goaccess_report.html + zcat "${zipped_files[@]}" | goaccess - -o "$goaccess_report_name" --log-format='%h %e %^[%x] "%r" %s %b "%R" "%u" %C "%M" %T' --datetime-format='%d/%b/%Y:%H:%M:%S %z' --ignore-panel=REMOTE_USER --ignore-panel=ASN --tz=America/Vancouver --jobs=2 --geoip-database=$mmdb_file + echo "GoAccess report generated successfully at $goaccess_report_name" + + # Get the start date formated in YYYY/MM/DD format + start_time_formatted_s3=$(date -d "$start_time" +"%Y/%m/%d") + + # Create folder structure in S3 bucket + s3_path="s3://$AWS_BUCKET/logs/$start_time_formatted_s3/" + + # Upload zipped files to S3 + for file in "${zipped_files[@]}"; do + aws --endpoint-url "$AWS_ENDPOINT" s3 cp "$file" "$s3_path" || { echo "Failed to upload $file to S3. Exiting..."; exit 1; } + echo "File $file copied to S3 bucket under $s3_path" + done + + echo "All files copied to S3 bucket under $s3_path" + + + # Upload HTML report to S3 + aws --endpoint-url $AWS_ENDPOINT s3 cp "$goaccess_report_name" "$s3_path" || { echo "Failed to upload HTML report to S3. Exiting..."; exit 1; } + echo "HTML report copied to S3 bucket under $s3_path" + + # Delete the zipped files and HTML report + rm "${zipped_files[@]}" "$goaccess_report_name" + + echo "Zipped Files and HTML report deleted from PVC successfully" + +else + echo "No files to process for $start_time_formatted" +fi \ No newline at end of file diff --git a/compose/openshiftjobs/scripts/backupmediapvc.sh b/compose/openshiftjobs/scripts/backupmediapvc.sh new file mode 100644 index 000000000..ed31a6e4a --- /dev/null +++ b/compose/openshiftjobs/scripts/backupmediapvc.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Specify the folder path +folder_path="/app/media" + +# Check if the folder exists +if [ ! -d "$folder_path" ]; then + echo "Folder does not exist." + exit 1 +fi + +# Get the current date in YYYY/MM/DD format in America/Vancouver timezone +current_date=$(TZ="America/Vancouver" date +"%Y/%m/%d") + +# Get the folder name +folder_name=$(basename "$folder_path") + +# Navigate to the folder +cd "$(dirname "$folder_path")" || exit + +# Compress the entire folder using tar +tar -czvf "/tmp/${folder_name}.tar.gz" "$folder_name" + +# Upload compressed file to S3 +s3_path="s3://${AWS_BUCKET}/media/${current_date}/${folder_name}.tar.gz" + +# Upload the file to S3 +if aws --endpoint-url "$AWS_ENDPOINT" s3 cp "/tmp/${folder_name}.tar.gz" "$s3_path"; then + echo "Compression and upload completed. Now deleting backup file" + rm "/tmp/${folder_name}.tar.gz" + echo "Deleted backup file. Process Complete." +else + echo "Upload failed. Deleting backup file." + rm "/tmp/${folder_name}.tar.gz" + exit 1 +fi diff --git a/compose/openshiftjobs/scripts/ziplogs.sh b/compose/openshiftjobs/scripts/ziplogs.sh new file mode 100644 index 000000000..eb599d3ce --- /dev/null +++ b/compose/openshiftjobs/scripts/ziplogs.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Calculate the hour one hour ago in UTC +previous_hour=$(TZ=UTC date -d '1 hour ago' +"%Y%m%d%H") +echo "Previous Hour in UTC: $previous_hour" + +# Directory where the logs are stored +log_dir="./logs" + +# Iterate over log files +find "$log_dir" -type f -name '*.log' | while read -r file; do + # Extract timestamp from filename + timestamp=$(echo "$file" | grep -oE '[0-9]{10}') + + # Check if timestamp is less than or equal to previous hour + if [[ $timestamp -le $previous_hour ]]; then + # gzip the file + gzip "$file" + echo "File $file with timestamp $timestamp gzipped." + fi +done diff --git a/infrastructure/_logprocessing/README.md b/infrastructure/_logprocessing/README.md deleted file mode 100644 index e30839d2b..000000000 --- a/infrastructure/_logprocessing/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Log Processing Chart - -This chart to provision a OpenShift CronJob to process log files from nginx. - -## Configuration - -### Log Processing Options - -| Parameter | Description | Default | -| ------------------ | ----------------------------------- | -------------------------------------- | -| `fullnameOverride` | Instance Name if other than default | `logprocessing` | -| `nameOverride` | Instance Name if other than default | `logprocessing` | -| `repository` | Image Source | `ghcr.io/bcgov/drivebc-logprocessing` | -| `tag` | Image Tag | `latest` | -| `CPU Request` | CPU Request Amount | `50` | -| `CPU Limit` | CPU Limit Amount | `2000` | -| `Memory Request` | Memory Requests Amount | `1Gi` | -| `Memory Limit` | Memory Limit Amount | `2Gi` | -| `s3Secret` | Secret for static | `drivebc-logprocessing` | - - -## Components -### OpenShift -- Cronjob - -### Other -- Ensure you have a Secret with the S3 Values diff --git a/infrastructure/_logprocessing/values.yaml b/infrastructure/_logprocessing/values.yaml deleted file mode 100644 index cd091a658..000000000 --- a/infrastructure/_logprocessing/values.yaml +++ /dev/null @@ -1,21 +0,0 @@ - - -fullnameOverride: logprocessing -nameOverride: logprocessing - -image: - repository: ghcr.io/bcgov/drivebc-logprocessing - tag: latest - -deployment: - resources: - requests: - cpu: 50m - memory: 1Gi - limits: - cpu: 2000m - memory: 2Gi - env: - s3Secret: drivebc-logprocessing - volumes: - logs: static-log-storage \ No newline at end of file diff --git a/infrastructure/_logprocessing/.helmignore b/infrastructure/_openshiftjobs/.helmignore similarity index 100% rename from infrastructure/_logprocessing/.helmignore rename to infrastructure/_openshiftjobs/.helmignore diff --git a/infrastructure/_logprocessing/Chart.yaml b/infrastructure/_openshiftjobs/Chart.yaml similarity index 98% rename from infrastructure/_logprocessing/Chart.yaml rename to infrastructure/_openshiftjobs/Chart.yaml index 10d87740d..6b8208fbe 100644 --- a/infrastructure/_logprocessing/Chart.yaml +++ b/infrastructure/_openshiftjobs/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -name: logprocessing +name: openshiftjobs description: A Helm chart for Kubernetes # A chart can be either an 'application' or a 'library' chart. diff --git a/infrastructure/_openshiftjobs/README.md b/infrastructure/_openshiftjobs/README.md new file mode 100644 index 000000000..f874f77e9 --- /dev/null +++ b/infrastructure/_openshiftjobs/README.md @@ -0,0 +1,32 @@ +# OpenShift Jobs Chart + +This chart to provision a OpenShift CronJob to process logs from NGINX and backup files from the django media PVC + +## Configuration + +### Log Processing Options + +| Parameter | Description | Default | +| ------------------ | ------------------------------------------- | ------------------------------------- | +| `fullnameOverride` | Instance Name if other than default | `openshiftjobs` | +| `nameOverride` | Instance Name if other than default | `openshiftjobs` | +| `repository` | Image Source | `ghcr.io/bcgov/drivebc-openshiftjobs` | +| `tag` | Image Tag | `latest` | +| `cronjobs` | | | +| `name` | Specific name for the cronjob | | +| `CPU Request` | CPU Request Amount | | +| `CPU Limit` | CPU Limit Amount | | +| `Memory Request` | Memory Requests Amount | | +| `Memory Limit` | Memory Limit Amount | | +| `s3Secret` | Secret used to store S3 details for the job | | +| `volumes` | Used to store the name of the shared volume | | + + +## Components +### OpenShift +- Analyze and Upload Logs Cronjob +- Backup Media PVC Cronjob +- Zip Logs Cronjobs + +### Other +- Ensure you have the secret with the S3 Values diff --git a/infrastructure/_logprocessing/templates/_helpers.tpl b/infrastructure/_openshiftjobs/templates/_helpers.tpl similarity index 100% rename from infrastructure/_logprocessing/templates/_helpers.tpl rename to infrastructure/_openshiftjobs/templates/_helpers.tpl diff --git a/infrastructure/_openshiftjobs/templates/analyzeuploadlogs-cronjob.yaml b/infrastructure/_openshiftjobs/templates/analyzeuploadlogs-cronjob.yaml new file mode 100644 index 000000000..7e6c15a0b --- /dev/null +++ b/infrastructure/_openshiftjobs/templates/analyzeuploadlogs-cronjob.yaml @@ -0,0 +1,57 @@ +{{- $deploymentTag := .Values.image.tag | default .Chart.AppVersion -}} +{{- $deploymentTime := now | date "2006-01-02 15:04:05.000000" -}} + +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ template "app.fullname" . }}-{{ .Values.cronjobs.analyzeuploadlogs.name }} + labels: {{ include "app.labels" . | nindent 4 }} + +spec: + schedule: {{ .Values.cronjobs.analyzeuploadlogs.schedule }} + concurrencyPolicy: Replace + suspend: false + jobTemplate: + spec: + template: + spec: + volumes: + - name: log-storage + persistentVolumeClaim: + claimName: {{ .Values.cronjobs.analyzeuploadlogs.deployment.volumes.logs }} + containers: + - resources: + limits: + cpu: {{ .Values.cronjobs.analyzeuploadlogs.deployment.resources.limits.cpu }} + memory: {{ .Values.cronjobs.analyzeuploadlogs.deployment.resources.limits.memory }} + requests: + cpu: {{ .Values.cronjobs.analyzeuploadlogs.deployment.resources.requests.cpu }} + memory: {{ .Values.cronjobs.analyzeuploadlogs.deployment.resources.requests.memory }} + name: {{ include "app.fullname" . }}-{{ .Values.cronjobs.analyzeuploadlogs.name }} + args: + - "analyzeexportlogs" + - "1" + volumeMounts: + - name: log-storage + mountPath: /logs + env: + - name: DEPLOYMENT_TAG + value: {{ $deploymentTag | quote }} + - name: DEPLOYMENT_TIME + value: {{ $deploymentTime | quote }} + envFrom: + - secretRef: + name: {{ .Values.cronjobs.analyzeuploadlogs.deployment.env.s3Secret }} + imagePullPolicy: IfNotPresent + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + securityContext: + seccompProfile: + type: 'RuntimeDefault' + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: + - all + add: + - NET_BIND_SERVICE + restartPolicy: Never \ No newline at end of file diff --git a/infrastructure/_openshiftjobs/templates/backupmediapvc-cronjob.yaml b/infrastructure/_openshiftjobs/templates/backupmediapvc-cronjob.yaml new file mode 100644 index 000000000..634ce836a --- /dev/null +++ b/infrastructure/_openshiftjobs/templates/backupmediapvc-cronjob.yaml @@ -0,0 +1,58 @@ +{{- $deploymentTag := .Values.image.tag | default .Chart.AppVersion -}} +{{- $deploymentTime := now | date "2006-01-02 15:04:05.000000" -}} + +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ template "app.fullname" . }}-{{ .Values.cronjobs.backupmediapvc.name }} + labels: {{ include "app.labels" . | nindent 4 }} + +spec: + schedule: {{ .Values.cronjobs.backupmediapvc.schedule }} + concurrencyPolicy: Replace + suspend: false + jobTemplate: + spec: + template: + metadata: + creationTimestamp: null + spec: + volumes: + - name: django-media + persistentVolumeClaim: + claimName: {{ .Values.cronjobs.backupmediapvc.deployment.volumes.media }} + containers: + - resources: + limits: + cpu: {{ .Values.cronjobs.backupmediapvc.deployment.resources.limits.cpu }} + memory: {{ .Values.cronjobs.backupmediapvc.deployment.resources.limits.memory }} + requests: + cpu: {{ .Values.cronjobs.backupmediapvc.deployment.resources.requests.cpu }} + memory: {{ .Values.cronjobs.backupmediapvc.deployment.resources.requests.memory }} + name: {{ include "app.fullname" . }}-{{ .Values.cronjobs.backupmediapvc.name }} + args: + - "backupmediapvc" + volumeMounts: + - name: django-media + mountPath: /app/media + env: + - name: DEPLOYMENT_TAG + value: {{ $deploymentTag | quote }} + - name: DEPLOYMENT_TIME + value: {{ $deploymentTime | quote }} + envFrom: + - secretRef: + name: {{ .Values.cronjobs.backupmediapvc.deployment.env.s3Secret }} + imagePullPolicy: IfNotPresent + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + securityContext: + seccompProfile: + type: 'RuntimeDefault' + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: + - all + add: + - NET_BIND_SERVICE + restartPolicy: Never \ No newline at end of file diff --git a/infrastructure/_logprocessing/templates/logprocessing-deployment.yaml b/infrastructure/_openshiftjobs/templates/ziplogs-cronjob.yaml similarity index 64% rename from infrastructure/_logprocessing/templates/logprocessing-deployment.yaml rename to infrastructure/_openshiftjobs/templates/ziplogs-cronjob.yaml index 831f96829..6dc98f5cd 100644 --- a/infrastructure/_logprocessing/templates/logprocessing-deployment.yaml +++ b/infrastructure/_openshiftjobs/templates/ziplogs-cronjob.yaml @@ -4,32 +4,32 @@ apiVersion: batch/v1 kind: CronJob metadata: - name: {{ template "app.fullname" . }} + name: {{ template "app.fullname" . }}-{{ .Values.cronjobs.ziplogs.name }} labels: {{ include "app.labels" . | nindent 4 }} spec: - schedule: '0 9 * * *' + schedule: {{ .Values.cronjobs.ziplogs.schedule }} concurrencyPolicy: Replace suspend: false jobTemplate: spec: template: - metadata: - creationTimestamp: null spec: volumes: - name: log-storage persistentVolumeClaim: - claimName: {{ .Values.deployment.volumes.logPVC }} + claimName: {{ .Values.cronjobs.ziplogs.deployment.volumes.logs }} containers: - resources: limits: - cpu: {{ .Values.deployment.resources.limits.cpu }} - memory: {{ .Values.deployment.resources.limits.memory }} + cpu: {{ .Values.cronjobs.ziplogs.deployment.resources.limits.cpu }} + memory: {{ .Values.cronjobs.ziplogs.deployment.resources.limits.memory }} requests: - cpu: {{ .Values.deployment.resources.requests.cpu }} - memory: {{ .Values.deployment.resources.requests.memory }} - name: {{ include "app.fullname" . }} + cpu: {{ .Values.cronjobs.ziplogs.deployment.resources.requests.cpu }} + memory: {{ .Values.cronjobs.ziplogs.deployment.resources.requests.memory }} + name: {{ include "app.fullname" . }}-{{ .Values.cronjobs.ziplogs.name }} + args: + - "ziplogs" volumeMounts: - name: log-storage mountPath: /logs @@ -38,9 +38,6 @@ spec: value: {{ $deploymentTag | quote }} - name: DEPLOYMENT_TIME value: {{ $deploymentTime | quote }} - envFrom: - - secretRef: - name: {{ .Values.deployment.env.s3Secret }} imagePullPolicy: IfNotPresent image: {{ .Values.image.repository }}:{{ .Values.image.tag }} securityContext: diff --git a/infrastructure/_openshiftjobs/values.yaml b/infrastructure/_openshiftjobs/values.yaml new file mode 100644 index 000000000..e5956c6df --- /dev/null +++ b/infrastructure/_openshiftjobs/values.yaml @@ -0,0 +1,55 @@ + + +fullnameOverride: openshiftjobs +nameOverride: openshiftjobs + +image: + repository: ghcr.io/bcgov/drivebc-openshiftjobs + tag: latest + +cronjobs: + analyzeuploadlogs: + name: analyzeuploadlogs + schedule: '0 9 * * *' #NOTE: This is in UTC + deployment: + resources: + requests: + cpu: 50m + memory: 1Gi + limits: + cpu: 2000m + memory: 2Gi + env: + s3Secret: drivebc-cronjob-s3bucket + volumes: + logs: static-log-storage + + ziplogs: + name: ziplogs + schedule: '30 * * * *' + deployment: + resources: + requests: + cpu: 50m + memory: 100Mi + limits: + cpu: 150m + memory: 200Mi + volumes: + logs: static-log-storage + + backupmediapvc: + name: backupmediapvc + schedule: '0 8 * * *' + deployment: + resources: + requests: + cpu: 50m + memory: 100Mi + limits: + cpu: 100m + memory: 250Mi + env: + s3Secret: drivebc-cronjob-s3bucket + volumes: + media: django diff --git a/infrastructure/main/Chart.lock b/infrastructure/main/Chart.lock index f3c684710..f6acaaabf 100644 --- a/infrastructure/main/Chart.lock +++ b/infrastructure/main/Chart.lock @@ -11,8 +11,8 @@ dependencies: - name: static repository: file://../_static version: 0.1.0 -- name: logprocessing - repository: file://../_logprocessing +- name: openshiftjobs + repository: file://../_openshiftjobs version: 0.1.0 -digest: sha256:6e52f8f5347093915401e544f039ae4e052a9459389d5c8b5930b1a59d8673f1 -generated: "2024-04-24T13:42:00.94538-07:00" +digest: sha256:c30da475ca6c16b2b174c7fe49023067ca89b52afefefe2c1cab809e66762ac8 +generated: "2024-04-26T10:10:49.6997356-07:00" diff --git a/infrastructure/main/Chart.yaml b/infrastructure/main/Chart.yaml index a16ffe838..c23486c49 100644 --- a/infrastructure/main/Chart.yaml +++ b/infrastructure/main/Chart.yaml @@ -21,7 +21,7 @@ dependencies: version: '0.1.0' repository: 'file://../_static' condition: static.enabled - - name: logprocessing + - name: openshiftjobs version: '0.1.0' - repository: 'file://../_logprocessing' - condition: static.enabled + repository: 'file://../_openshiftjobs' + condition: openshiftjobs.enabled diff --git a/infrastructure/main/charts/django-0.1.0.tgz b/infrastructure/main/charts/django-0.1.0.tgz index 16d2c817c805df0967a7af60a8ec51a5364d1b78..2d2d4aff0bfc26711f1f69bea61107aea70f275b 100644 GIT binary patch delta 3376 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 LBX2wl04e|gw`w+) diff --git a/infrastructure/main/charts/openshiftjobs-0.1.0.tgz b/infrastructure/main/charts/openshiftjobs-0.1.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..8dd1efb956ff514da4722b3f168679e109629a94 GIT binary patch literal 2689 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 literal 0 HcmV?d00001 diff --git a/infrastructure/main/charts/redis-0.1.0.tgz b/infrastructure/main/charts/redis-0.1.0.tgz index 8ca86edd34f306d9bd50d8e71a3b12e1b7b314b4..ff9da1411b4c9834c83c4934fd469d20a6677104 100644 GIT binary patch delta 2070 zcmV+x22nI*T!RQ49-vUgVa;1rU5&Z78+MD|yA(GLzC>0fa z49g>rWLfnZ_ya%iB2=NInYK-5@ONY>gyy=yLP+=}pQGfcQF)xCI0k#4JiW?r3?$1K z4T+iREt_1w_qGpIkkkJqVL7UAWdI)2|KT8L>;K8|@j?HegMSt|V@7k|EKy1tl^Wdf zb~biAiB_l2Mb7mY2BwLoB*t;a1CW>rMYWKtF~mtIeJc9%Fc!;xBpIctn^nu}YEaf{_xr3{lxP^ZqeMrOQ`5251Uf-5dJke@e_KEAcf42qUw`d*4-Y+va6vgjmt>i5Ms}fB>moVR;JaY*#_;jq zI>%BsCa?xAa~{Iz*#4yHG+!*}C+PONP%=Xv+27{P0DnA}NHhYeRxx&K1s`+5=z?No zVhs!3?|A=2w}73X%`#>m3g#G+Tp=itVl8lSJ6=#^kpd#oSq_Xq3(yHw@Z)@CrEzgH zHDf7{L1h^JP&4o{l7&&{_E2ZwuZA3gyZ7hIw`ry71l=U7X!>B<$3|#A5`xL z)opQe>wd{q+xNS51#2g3RHle)&8gbcE$)gN#mF4l-V?TCYRB8&PhH&ZcM+Py+IU(< zLWJ(0y3l>s{cSoW(o}E!@~nm98S}Osx0E+VaJ>`e9VQ$tqpJUNeL%0M!osUu_~|56y=hJ z+Z;-fO^Z!DBDD5id%ID%jHxXsr}X|F^HnEcYb+tA+EB!+d{4b=3mvS4*a)Hx3>?#*0d zIlD(eFzN+^UT_41lW{N{2PeLhR-q#1!f(nEB+FEPIp}yFD38W)QSt70DQXfCO>B5y zsZn{0+YZ#}5)?|it#Pa}No(MgN60k{?SCBO=gZ8-q&;qODV>^@l>JaFRa$@||44}r z6K4&ojO1|xxj{23*=k8N#;byfE3@2UXkC*{s|pd6>(=FDv!W&jgQE9z7=JEc091l8 zv=l5)vCg#zwQ5jrP$gk5DnQvB+s^h%YNc=`*;H=dF%+D9H`fod94gQoDwDq_a({8d zw;64vrC$WGoc()2R(y8D-0fwywWFj=$gLgqHb*xR#`TYmPyf=!n@OQXDA*Y8&L{Ow zYegnGV-vw>xEjON;zsC+L}itEGtgb6YmxIE2zK76N>*mhgy>`peRJWrmT!pBnYB%| z!ia3V)o;vROE$=tdvIM`PF}zH*MIfp&E31Zv%j_B+4`D=(6Y7lkmWJ9SJ#(M<4bMi zyNj{HFqc%X&IQ-_Nw@Z*FbqYSO{7>*hFh1qur@i@G{p<&4O;q;^D}iL_^l9nY$8%@ z_7ld${Y26wWf?H+UQaDh@{bbpac%HwI6 zV3ae;I0hPhp=KDP(=NaIA?I#3g=S+ZE}4rRJ64v`5a;?*y>8atiZ9jSHO z6Ri!NHXTHrb~%fN6!!;`O%J%y@BRLNcl@VZ9Q>6E!jIK|PmbF4-%)U=|2z*hzW-FQ zR*?sNhd`_DeR}q->1;HSF@Nf9C$!V~IKXCDPluUlrCg)rgxyJFWWv%RowHnNlsh7~ zFNxBIPfxr4Fy!>#H<>-P=JFe?@u>cfhFjl%2E&8?KL@>p3DHI;6lekN3c!7W9OgM? z5#=#tB>X^PRDQ>M33mxqpz_S>DX0V)gP4iA^IDY0KZ8W$)t3kv(SJ#;o$$zT;22w{ z4?h~mO+R4-_f#kFe?R%~hO-q2Zl@Yhkf8)dIr<&XznH$8Y9Y}uDQZ`5&!-SksXCq? zQ{8tDw~3DD&;Kp^?ol-*ao_%5HK--;*BH)8_#w~0#6POzz4Fz4W*&3$!8~+o--M)b z$9wf3Gw&^tROAY-E`Kf!icE_480wDa(+Ekwm?Xvfj^{5`C?f3tvA#7q{lC3DySTpe z)99P5@!0pDVA%fqkHP5p^q~LGK`-If+yGaw?sy&Vtf*aUVSMV6y6Sc@s*GvPz?Vj8 z_=3i{wEFDYN`7zbUyRsK#%q`mNmA4(YfNl-9O4P znr(d_nZX*aitT}|r_u!oouCAr5MGtP)-ba=Gb`mEgjZBNv(P#7v9YDldS&TRg^ zlhH{qYchIGQ-7*wwINmGUN%lff#u{FUAt0A9n>0{jcO;mHlkuq9aP2Wv!EJ?%70d; z(oAsVS~+!klOdlbbfG(5ZxfgI8s$(o@jWXmaRu+i96sh~viR?9rVezV10CovB6|A&L1t^X&-!-M`m2Y)Sc#*F5^S)!CQDmA#{ z?QHCL60J_3i=68*3``SENsQx;2Ou#MifSQOV~CSb`c(AiVJw#YNYW+F!(PD$K$Cb3 zjA&Ha@Q5&DVwED-1tTSL8KSap=KW)iN|&zyVU~~KBuLBm6jQtENpMYF8>1<0PZ$K- zGX{a3^1aXDdw-GBe~oEo52ODsL6)IZzRtdyDR@Nxk4}#VE&U&!27`nCKLl{nnn7|se%y|f-WBZe)(|oa@pP<|8LdgtyWPh7C1Ap*bBGCw>TE*C{6@1JIqYH|W zi8U;AzvKNA-2!%kHp`fOD41hNa)qEoinYMS?RY_vMGA;SXE`teEkGw!!H@HmmBz)* z)QqJ(29;s>li%^K79f!!QH9(>!8M^=6%mqcqZ;lhV=za^l|ib2SokI0-O?=$b4|i@ zQ3!jo+S6CaZUkosllO%Kj_qXYkNK?TbNVN~7>n%_w$WmV=eSeF53=a=LdC2mpxgoz;vDvARVW@?C zT`=_P*QMCsS(Sa*PBZO8rKcvCsIrKMhaGd)@G%z}w>G@ZCncQ381?2W$Ev(KQB!4o5BjKRP)c9sK`ukhS!is1BWx?u*j)Jow>vZ>s@V<yo4a>+XMbzMv-LF#p=E39A?e$g`-!AW$}q-D6%s~VVR=EAss@wAf^w=?H3XT6&bX#$+dbyq;R2<^=zk)Yl*iLB z!6;{x$5$~IRrBR140F3!eQpo#k;aL(b)Y6#vt+T{9m;fD93m4;#H(L$HFi3+J5uYm zCt4dkZ90fL?Q#|kDeey>n;vkZ-~0Xl?)Xo+IQT0SgdeN_o*cF7zoXz#|9Kv2eE+Fp zts)Ql4uMwP`}FKv)7fYuV}I1!PH3m|ae&RRo(?n9O1VbK3A>ZV$b_XsI%m1kD0f6| zUlOGapPqL8VaVyfZ!&vo&E+>(<5B$|4Y$7k3{DRE{~YuZCPW*ZP@o04D**Qia+v3o zMU=;ok?;eFQTZM3CEO)cfyy(hr=SvK3}Pnc&TCN~{|pk1S6?DzM1Lo>cETgWfn#i) zKKy7LH~oYW+*6&v|NZ2{8_rfBxSeW1L530-<>+@j|6=-Xs)a5Y;fFi}6aT1=_sUoInR(2~2lLRWeG`(# z9q-kD%)GZmQjsgTx_`JdC^9MDW2ifxPa`D#Vv-c^JD$H(p@^{m$NJXf^#Atq?Be>; zPor=aM1tfpqFrKZh$LTcf5{wR@APwFg|rjU3I${RmQYt;7g-4 zd_m(}T77nHCBHZJFGlPq<26i(Bq?f?wJ3HC7n{E<*$#4Rqkml4X>Azwwh4B&?jPkC z&9=Ue%wP>y#rD9~Q|SVPPEdkQ2(QXtYnWM`nH7v$OdROn!l?dbeOB)NwyG=br!~w5 z#lj_{BCnlohFqDH7N)jj@EJx8M4H62ts#z)$z4B-=(LXLeDV*tbybR4HKf)EXEuM| z$>=1QH5t98DSy?o+K{SoFB>PLz;beou3f354r&d}Mzxb&8&NT*4yt1GSx^l`(;pwKGw;AbETQsdsMu8?qW z-$bcWIV$Ifb%K!OxPtd$4j*$gS^W1lQwKWGfev(_uMbTB4FCZD|B)d=XaFt%03i1o AcK`qY diff --git a/infrastructure/main/charts/static-0.1.0.tgz b/infrastructure/main/charts/static-0.1.0.tgz index 9cde6f8bb2f78af80e5ae847e22b1c78c2174bdd..65d6b6670bf9b5e09fc97320ee9f0d07c38529ea 100644 GIT binary patch delta 1389 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 TjLQE400960gfiEw05kvqXpSG+ delta 2036 zcmV4G?~aBWn2Y;gB<&p{R+vRo#<>NbN63%3ghf5(GhT zxW8|IgCJ=B2ED_hSH1niUcY~M)Zgp93VQv${^2VKJ_VU($rhC+@>TG`eKiO7ObW^9 zTa=0lK7e`Okz9zA8`K5ce;ij)i3=hq1 zpk{ZK2de{7w|Q`JXWAOi+3p9yVJGNyf9mk^m;jph_dxZ|%DilkW`b5-T}SP3<-3R8a6M zL8z!g8H1o)rPxd@%hG>H7b^}XZQR^@h2*=oewgKT0%a)^%_pKb@pYiJ9QeH`maRXO zWQDVt=H@+Z-4-kEB25X88e{4}*SKYUW49w;CCgWJ!DYg}Z0HCKPe(sr{`>s&;`-+L z_=o0L?Qxf7*>HXJ2x1rP+4;`9wbVR}VQhtqD_ZaWQ}_o{F4@C_9Nzdg~BImsihV2$_)Ehw#hz^y*6;LatD5 zCO*0xU;l7*I)0|~&C)p@kAJF*WkI#Q%E~@I&cNpfjvwGVO+#!t<_bIDR)pS^Nc8zk~b!d?ZCgR0U#eas^s|TLN&GActvASwwjZ83}KVqx64U-fOr{r~;K|*3pAXkTHmvn7VaK zdHfHMXsmjUkP)5K>Ishw0>{`IJ$!8pm%hUY?x;@SFW>lZ$=Lz~w@nQx$WQ{K9Q~H( z563rSEhHL{;_UkE$rvIkRm<~Zs=MyT4Wi}w)Bnh>`>CpuxNHAb6>84AHNYteZ}SX{ z|5JZ0?~SkSGV?Pfx8_Hu_DM(@x4bw1HSOLKNky*UYBCTjgWMUMpFFN z^8C39MTFgt`0@556lecer^mzdQ$LM9Ngq4xe{U~ne*f(q9=zQD_$=i$3~lrT_Efj! zwY=lvR z2r9QbW3;?d^4eIRiB)rH9fPZ@h+W#dXIAn7MnsYnHOktK_yEJ@9kulhvnJ&Zu(t^q z{LXrTjkWJB&2=r@pTLNpBnUDt-~vPL?gtOgsx?djh$AekYGzIhqvsn#4^OCH}RE zm$%b{iMy@zxPDGXzrd9{BArw%Yn7$0HsK!~Jf@%}{?9a}H5v}zR&GVN`2B<6kq#XG zxjWUZ58(k;E7itc%=|tbzdnQt|IvRT82-U-{MCHC;D4PUxT{-5;_JTOH}N;$@|vvR zH*)Jqgi@psg@|%hK)^iW;Y*6I?(@_}@shJ?+mq zwO4a&(1#>U3U3tVQX