From d0ef74b21ba18af40534db8a118c810559c8c548 Mon Sep 17 00:00:00 2001 From: JamesClonk Date: Tue, 26 Mar 2024 23:50:00 +0100 Subject: [PATCH] add item-monitor --- configuration.yml | 13 +++++ deploy.sh | 3 ++ image-puller/values.yml | 1 + item-monitor/deploy.sh | 13 +++++ item-monitor/diff.sh | 12 +++++ item-monitor/image.lock.yml | 7 +++ item-monitor/lock_image.sh | 11 ++++ item-monitor/status.sh | 9 ++++ item-monitor/templates/_ytt.lib.yml | 35 ++++++++++++ item-monitor/templates/deployment.yml | 55 +++++++++++++++++++ item-monitor/templates/namespace.yml | 24 +++++++++ item-monitor/templates/secret.yml | 63 ++++++++++++++++++++++ item-monitor/templates/service_account.yml | 9 ++++ item-monitor/values.yml | 4 ++ secrets.sops | 6 +-- 15 files changed, 262 insertions(+), 3 deletions(-) create mode 100755 item-monitor/deploy.sh create mode 100755 item-monitor/diff.sh create mode 100755 item-monitor/image.lock.yml create mode 100755 item-monitor/lock_image.sh create mode 100755 item-monitor/status.sh create mode 100644 item-monitor/templates/_ytt.lib.yml create mode 100644 item-monitor/templates/deployment.yml create mode 100644 item-monitor/templates/namespace.yml create mode 100644 item-monitor/templates/secret.yml create mode 100644 item-monitor/templates/service_account.yml create mode 100644 item-monitor/values.yml diff --git a/configuration.yml b/configuration.yml index abfb958..285b888 100644 --- a/configuration.yml +++ b/configuration.yml @@ -5,3 +5,16 @@ configuration: ingress: domains: - "jamesclonk.io" + + item_monitor: + monitors: + - name: galaxus + items: + - name: Scarpa Vapor V + url: https://www.galaxus.ch/de/s3/product/scarpa-vapor-v-kletterschuhe-42-kletterschuhe-10611477 + value: 125 + regex: + - name: Scarpa Arpia V + url: https://www.galaxus.ch/de/s3/product/scarpa-arpia-v-42-kletterschuhe-41901081 + value: 110 + regex: diff --git a/deploy.sh b/deploy.sh index 6e1dbb0..6aada94 100755 --- a/deploy.sh +++ b/deploy.sh @@ -30,6 +30,9 @@ deployments=( # # building stuff with blocks.. # "minecraft" + # # monitor stuff on websites.. + "item-monitor" + # also some cronjobs for good fun.. "image-puller" "repo-mirrorer" diff --git a/image-puller/values.yml b/image-puller/values.yml index 1f98406..b3cdc17 100644 --- a/image-puller/values.yml +++ b/image-puller/values.yml @@ -23,6 +23,7 @@ image_puller: - "jamesclonk/pgbackup:aee0398bd7634f209ecd7e1ec03f55002c3c3a57" - "jamesclonk/mcbackup:f3b390668671bba69835320ab82824470f6404a4" - "jamesclonk/resume:7b30c92e6787eddaec36a9335d3d421c681e0efe" + - "jamesclonk/item-monitor:9353f75" #! other stuff - "jamesclonk/web-container:latest" diff --git a/item-monitor/deploy.sh b/item-monitor/deploy.sh new file mode 100755 index 0000000..0296788 --- /dev/null +++ b/item-monitor/deploy.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -e +set -u +set -o pipefail +source ../setup.sh + +# deploy +echo "deploying [item-monitor] ..." +sops -d ../secrets.sops | + ytt --ignore-unknown-comments -f templates -f values.yml -f ../configuration.yml -f - | + kbld -f - -f image.lock.yml | + kapp deploy -a item-monitor -c -y -f - +kapp app-change garbage-collect -a item-monitor --max 5 -y diff --git a/item-monitor/diff.sh b/item-monitor/diff.sh new file mode 100755 index 0000000..45d85ef --- /dev/null +++ b/item-monitor/diff.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e +set -u +set -o pipefail +source ../setup.sh + +# diff +kapp app-change list -a item-monitor +sops -d ../secrets.sops | + ytt --ignore-unknown-comments -f templates -f values.yml -f ../configuration.yml -f - | + kbld -f - -f image.lock.yml | + kapp deploy -a item-monitor -c --diff-run -f - diff --git a/item-monitor/image.lock.yml b/item-monitor/image.lock.yml new file mode 100755 index 0000000..6106a7a --- /dev/null +++ b/item-monitor/image.lock.yml @@ -0,0 +1,7 @@ +apiVersion: kbld.k14s.io/v1alpha1 +kind: Config +minimumRequiredVersion: 0.32.0 +overrides: +- image: jamesclonk/item-monitor:9353f75 + newImage: index.docker.io/jamesclonk/item-monitor@sha256:d42091cc41289c3f113d80a021a3b059d8b6ffdd211c40522a5b541ff083fc8e + preresolved: true diff --git a/item-monitor/lock_image.sh b/item-monitor/lock_image.sh new file mode 100755 index 0000000..8e8acf1 --- /dev/null +++ b/item-monitor/lock_image.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e +set -u +set -o pipefail +source ../setup.sh + +# lock image +echo "locking images for [item-monitor] ..." +sops -d ../secrets.sops | + ytt --ignore-unknown-comments -f templates -f values.yml -f ../configuration.yml -f - | + kbld -f - --lock-output "image.lock.yml" diff --git a/item-monitor/status.sh b/item-monitor/status.sh new file mode 100755 index 0000000..dfceb0d --- /dev/null +++ b/item-monitor/status.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +set -u +set -o pipefail +source ../setup.sh + +# status +kapp app-change list -a item-monitor +kapp inspect -a item-monitor --tree diff --git a/item-monitor/templates/_ytt.lib.yml b/item-monitor/templates/_ytt.lib.yml new file mode 100644 index 0000000..2ac08ee --- /dev/null +++ b/item-monitor/templates/_ytt.lib.yml @@ -0,0 +1,35 @@ +#@ def labels(component): + app: item-monitor + app.kubernetes.io/name: item-monitor + app.kubernetes.io/instance: item-monitor + app.kubernetes.io/component: #@ component +#@ end + +#@ def labelSelector(component): + matchExpressions: + - key: app + operator: In + values: + - item-monitor + - key: app.kubernetes.io/name + operator: In + values: + - item-monitor + - key: app.kubernetes.io/instance + operator: In + values: + - item-monitor + - key: app.kubernetes.io/component + operator: In + values: + - #@ component +#@ end + +#@ def podAntiAffinity(component): + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: #@ labelSelector(component) +#@ end diff --git a/item-monitor/templates/deployment.yml b/item-monitor/templates/deployment.yml new file mode 100644 index 0000000..296c863 --- /dev/null +++ b/item-monitor/templates/deployment.yml @@ -0,0 +1,55 @@ +#@ load("@ytt:data", "data") +#@ load("_ytt.lib.yml", "labels", "podAntiAffinity") + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: item-monitor + namespace: item-monitor + labels: #@ labels("monitor") +spec: + selector: + matchLabels: #@ labels("monitor") + replicas: 1 + revisionHistoryLimit: 5 + template: + metadata: + labels: #@ labels("monitor") + annotations: + prometheus.io/path: "/metrics" + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + spec: + serviceAccountName: item-monitor + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + affinity: #@ podAntiAffinity("monitor") + containers: + - name: item-monitor + image: #@ data.values.item_monitor.image + securityContext: + privileged: false + allowPrivilegeEscalation: false + env: + - name: PORT + value: "8080" + - name: TZ + value: "Europe/Zurich" + resources: + requests: + memory: "32Mi" + cpu: "50m" + limits: + memory: "64Mi" + cpu: "100m" + volumeMounts: + - mountPath: /item-monitor/app/config.yaml + name: config + subPath: config.yaml + volumes: + - name: config + secret: + secretName: item-monitor diff --git a/item-monitor/templates/namespace.yml b/item-monitor/templates/namespace.yml new file mode 100644 index 0000000..0d74626 --- /dev/null +++ b/item-monitor/templates/namespace.yml @@ -0,0 +1,24 @@ +#@ load("@ytt:overlay", "overlay") +#@ load("_ytt.lib.yml", "labels") + +--- +apiVersion: v1 +kind: Namespace +metadata: + name: item-monitor + labels: #@ labels("namespace") + +#@overlay/match by=overlay.all, expects="1+" +--- +#@overlay/match missing_ok=True +metadata: + #@overlay/match missing_ok=True + namespace: item-monitor + +#@overlay/match by=overlay.subset({"kind":"Namespace", "metadata":{"name":"item-monitor"}}), expects=1 +--- +metadata: + #@overlay/match missing_ok=True + labels: + #@overlay/match missing_ok=True + namespace.kubernetes.io/name: item-monitor diff --git a/item-monitor/templates/secret.yml b/item-monitor/templates/secret.yml new file mode 100644 index 0000000..4413c2e --- /dev/null +++ b/item-monitor/templates/secret.yml @@ -0,0 +1,63 @@ +#@ load("@ytt:data", "data") +#@ load("@ytt:assert", "assert") +#@ load("_ytt.lib.yml", "labels") + +#@ if len(data.values.secrets.item_monitor.teams.webhook_url) == 0 or data.values.secrets.item_monitor.teams.webhook_url == "http://example/deadbeef": +#@ assert.fail("secrets.item_monitor.teams.webhook_url is missing or invalid") +#@ end +--- +apiVersion: v1 +kind: Secret +metadata: + name: item-monitor + namespace: item-monitor + labels: #@ labels("secret") + annotations: + kapp.k14s.io/versioned: "" +type: Opaque +#@yaml/text-templated-strings +stringData: + config.yaml: | + log_level: debug + log_timestamp: true + interval: 4h + monitors: + (@ for midx in range(len(data.values.configuration.item_monitor.monitors)): -@) + (@ monitor = data.values.configuration.item_monitor.monitors[midx] @) + - name: (@= monitor.name @) + items: + (@ for idx in range(len(monitor.items)): @) + (@ item = monitor.items[idx] @) + - name: (@= item.name @) + url: (@= item.url @) + value: (@= str(item.value) @) + regex: (@= item.regex @) + (@ end @) + (@ end @) + webhooks: + - url: (@= data.values.secrets.item_monitor.teams.webhook_url @) + template: | + { + "@type": "MessageCard", + "@context": "https://schema.org/extensions", + "summary": "{{ .Name }} has current price of {{ .CurrentValue }}", + "themeColor": "1188dd", + "title": "{{ .Name }}", + "sections": [ + { + "text": "{{ .Name }} has current price of {{ .CurrentValue }}" + } + ], + "potentialAction": [ + { + "@type": "OpenUri", + "name": "{{ .URL }}", + "targets": [ + { + "os": "default", + "uri": "{{ .URL }}" + } + ] + } + ] + } diff --git a/item-monitor/templates/service_account.yml b/item-monitor/templates/service_account.yml new file mode 100644 index 0000000..708008f --- /dev/null +++ b/item-monitor/templates/service_account.yml @@ -0,0 +1,9 @@ +#@ load("_ytt.lib.yml", "labels") + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: item-monitor + namespace: item-monitor + labels: #@ labels("sa") diff --git a/item-monitor/values.yml b/item-monitor/values.yml new file mode 100644 index 0000000..94cc243 --- /dev/null +++ b/item-monitor/values.yml @@ -0,0 +1,4 @@ +#@data/values +--- +item_monitor: + image: "jamesclonk/item-monitor:9353f75" diff --git a/secrets.sops b/secrets.sops index 80c20ce..b649b22 100644 --- a/secrets.sops +++ b/secrets.sops @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data:X54Q95G15cmXPAUQUleEHewPcjdjjqLUKHFSJHgEFQEIAST1L3VFV6sRfCSK4SsiAo0iaYxH+RwJ472FLODCj2OCUrzjyL6XBBYIZyRoFYpxOjUXmAyn6iqA7VK0AiEgJqQFKpZT5e/6Ihjj1ZbhIQ1QdMWqOmrFNaLX7ZdGIduWn26foEv+saLYz7jdS4De+suDcwK/JpHT4sZ9SBEhORCycB1wXjqsYQ9NCV6kHnEQSJDPZpoH65Ojx1PwGS3qpgtGAccDkJEi8DUo5iQ8PJwhfgb/LDK5qpX7RTTDV/IJ2Cq86wXHY/svT36cP+/uYbl3VIjVFow2q1JKKkaWbWN15lYndQrchQF15ao5gLOb0gXrUmIDgdsjlXgJRCpCJ53hzDEQdVq76hf7+s62+OEE78xrrPb+3v65IxFmZZ6pYjWAZ4uWApyqrH31ZUONZsJX8ycTZL+LMhohGIBgVhp8fLEdcrpKeRXPVOb3YFJpz5q4WDimOIpevNFTLjlbwGO8rGdiT2+5HunI0B+F515tb0m8EMSqDmxFfmvM2TafcwYJ9+AsIw1xCeHqWprJvQ5BCKmBuQVDHmLW8SeRSV65hItm4K+heykuJ9t0O85dnK3G9Rg5kYHppHhadXG4WjprHrL2+Uj+UF60qivjs9hwq4Vc8kwLV7CETiAnRY5QgfNrzyqw9+cmWoppelej/UJSb84y5PzuQ2qBrodVsbIa16qqMVjC3mSP7r4qPuM5JPZpXgQd+uzokaJSPu+X17yezWh8XFuHpwiLLPbdQCAGWsye7GVgak2JnAmd55MPWu1vOnrb4nSCLIuKawqJRjtublLgz+MkvbRt6lh6QxJyEwS9GnkaInPWOLKPttshWHVntwNeffVi3ReNGqgLyhzPCJno7lMgjhbh3dRGf5APCpW762nBdIsETI8GIve9NvUud+SpSshp/9txUcYGRZBt7zPTRHgXxagNHTwhaw4FMzkhchZDOrPaGfKSy2zEhmQsmhvInKvSD/+WJkoXLdpR6N+tsragDUEy+jH6+hij2FreUoPerdGUWm2x48+eQbnFPw03BexeIg5vFdA0m3/0xicHFiyJwGF1LeFzEMiE/2g+fBpRpbThBQgpxd51v4THxGhZ9CqP3YFhA417cjCk344RHXvcuOu6ruIHPrynUlO44/osKu3uHEjsGGkqSbs+JOiL6fldNu4199Q2NlvLbc1LaUaxpV9Fix2a+Recz++UD0/9/acEj+kSDrOVaz/TwnqF/r1+mYaQsqHr2qI/BnA5DgkQckbvb86t/rkG15vg8wnr5SdWlNT1V+WAK+BDJihMXAtmpBGVeYZ4solUbT8XsvGK/FTVhyI+CaDVmckjecTjogue0CSCLu1giQ+6EBA3enXZ8fsVOAh6r49PzL0IICENfe7lpcDH1Jzl5GF4egsBTS8+YltSXunhl39nQgOQOG/UhpET2XYfdp9V2o183R1JMFF2o5SM71Pf/iOUUPt3KU6SAeic5cbvVHRobE1r9YVwFPStnU9GrZD34+aYlXLUafQLTwchraTE+mr3pX1Odk3abkIaaG8KQZGtQOEqGHgyEqrgKeOnzzfvaj4lVBFvEFWh6MLNxCyN0hOkCN2BuzogG4msroBf48Kf02Ri+gOXDHrgDxxJvKH62aToZ59yVvhW4St38V5gjfqBqitzofwTIqPRjYD1FtZgau2RrjlVwhBZ/K3IKueBQ4lQfufmwoMjLhWgGyJoOQx82+OVcpSXcfDzO9LamE5C84jt3HrSDVI+Pq/JfpZYbyw1j2JZ1gu1FdM4fYBUW4g2S1rqE5F2mxCuCa79xxHhwGT/8Lyc/RzE4Cw2BwhunDQ9naRm+BsPJlWexV8zIo9i8sjFWVPZJHkylIYnz/Xj2UmuYlLo5JPapYdUecG3U29EN+6jlgrGygn2Y8N646S6D1tyVouoUa+rSl9B/0pkRQfgcM1a4ByzZDzD+g4DlE1QrHI8P3aVBCLYopEv7AQwtZBfcvkuScLXgNBsqXH/+A52p52efA3QTOjGzpQS2d1RKjR9J91B4JHRASrAQwzykFFUbwLv7vZ3VWcSXMatx7cUzOSmOyYNsJSsCInfoTT+yeamRaLkTbADg/KON6mzck6XDQWUtkZEaa4DpbcddZjxDfYshEndNykO8O/o5LCkJR9P8aObw175iNqCaYMpqJCiIXdcFbUrqaQAygugPs+EPe4wcSDpOYOO6ILU4zg7OPAk1YM1vCw7chgeq7C88k8ccsdUTCre8F6APVCzRM9qGQ5kPhjUd4BpXSA42GMD4Ry4xhijBChrPIh1z0FjtFTA9hRA59SFjzBGIBqiqonA3z2A6PfFsFfMozG+2dwXt4Yr0qRhqwqj2oa0frLVfp2N5gOGOMU7WcWKokI8PulIUpNVPl79ZYPw+XTxRdc/wt1px4KMlO30+dgD3jeJoWFmzoBSAF/FguCXaT7tuuofUvp/l4kzEat1LtVdTeGhL0tYWUeMRWH/R/j82JwxBQLUSVUabveElWD36zLuZgwmIHcnNuUBistvBH/stHYb2kKV6mjuUv7iB0gPDvCGtfliuImw/HSMGysZHtuL3PPh5P0DFwPqpG6V0yi72quqHNOyzD3CrRmxcd+Zgi7nNDDZweqtVUrdUqZkQ/9w0wT/nYxkVA24Vp+tcixt4zcK3hyHm0emPoUs8ZPgFtS3WV4TfwUaGGWh+y+svlS264bvPsnMW0ziuWlb+C0cF0/m3brlVGCTTj5/Pc+BTIKNINy3HN5WS3FXSqnFuUU0CJ8sdzXYxn+3CaUuBVI8ErHlS/wB/CYl9YluyzhEHEDYIw8+8FQRg/e6KSKT95mtpRz7Vp5WaGRW51Akr2IHt/VV0Mki2ExTgqaYTGNcE2SZOjHzVqFC3nO3DJO+jD3AQEXte0CclG1fUbDQ4qwZ+jsYYKrNDh7hQmMJQea+kCY4nIeSICUlZgeDcL5iXUlSURCnO+T5vBTEDgMPIXY1zGOP68EQcOH6WUupuoUtEYVgMC7OUv4/8FIenbGwhWbgzevoXUse367LRiVGa+LBTZ+oCjAOYfhQUQMUSPdTzVOwz7ANGOe9CqZ5Ws/ltZMpAAbWjXP8kcXPYKCjk6Iv7IdnwEhO2CBTd632/z+cBJMpyMzqz1TK2khWjdOK4qf8kOZRrBm8bEMkRyRDCFg4bwvM+mYvYVHcIppon6jGDcQZcXXVxjiCjZ9qUnQaMWb52DRBlU3N38Lxdy6n8MuN93xcalAnp1+lcHSZS/peKFy6F45uiysdjz7FVnlNz2uyJ4wDnBhzxzZRzpnZZ485U+0JU1NN3GdkztH0mmjkOHz/dnQhPM+XJyEWg2PLz63mE6oASzF43gkQKfLBPQSacc+lBro0GReAlSgwXEaA6Au76dw9dPA95Lg9Wv8ybPLY4sSEbf+2E3g1WxX22ssZi1FUNIhwi6Z98tBik0WnGY6BQ3Kt3Eb+4aQK9/4lVGPFTL9bVtM9IICs2jJZR110ed2m976NsMn6Y/iDsdGXwBqse+6nqwY1VD6LXnkWLzZfBX3qy9HnJhSiSYy7kXWbdsAE1C9s2tUB9DG3ZQkDrFFZ1QnvST9H2EO7PcZsTttewmKxnU+vTWAYmjdLgJX9W4xr7DcNiYpJqPjs2icIZq6IImivqB5ZyOXwK+KsdzET6HfpOL7QF+VFLfDcJR5l7R5BCTy9i4hjcFpmiX5G5PIWdkrLgGjAP4e7z4QZFYN18MIUnVVExp5Y7ORsDVFHEZVMfQYcb5jFdIfq9M7lf4rWkGy/hbLspm99YOsbF1Uwsm0SLDX9kJZUyhGu2pbI791DvEiPHOtR1TtXHfBOCUJ2sYi0fLNRHuwoh+C/Dolbko31mqxYO4FU6pTJ8h/I+w+DXedV3eKBlbmEiWrXJDWFL2DLMwskiPkKLqtLxW+889+2g2Q7XWCk6Rxwe5noaZ2raQe1uLqQJz0XEBTe15zNW18tyKEybJIt+flc3WRjslIhNgL5xf0AxZNAgoHQoIU94V6f8Xanq4MuXe1U8ke/7Mt5PGntQBuasT51EgEpL9OVsWVPdJF5GCHgQnr9ZN52x7j22qBt9TQhIqgPoe/XO7bBuIrjQ4N2L7m7l8E1VYPYM+76G7ycXFRTT4YtNET0eLxl1sNMlV3TKRGLS/w4oQmxW1framxw0QmNeuiWgvg7G8hKjFUiw1c1Rt5yrH/2Tafhro6ICAb1qssW/X4YEfUXqaUJiBk13fEhDR7vo0y74AYfX7S/n5g+T/4dtUgJ+iUR4CGB9MAY7EUv1tm5Pz5r1biyaSBjieAesGGyUmgHzO9YCDua4VaEVnSqXeTrvaweP4ZGwjx/k3yOhhsZBkUi3/5kuDoIwBxrHZACzuUtpzEWmCDhuaWTE/riip5ye7ivGJ/pKQ+U2ujf95SEU4YbwR9zbdnbx144kHJaO9z9l6GB8v0F5enQot4qUGoAwZzbn0KgUCiCdPJzEDZL+ove0Vfo/exTIbhm79DR4VpVD6dfA/V0HRAfbXocQC82HLT0wIBHzVfpWnXVlSQyM9LIcpbhxAEydf58nybKEN6MudCFl+A39OfJ0Rsj2QwKap2djqqPzwnsHuafkQ3bBFyDL1NnWjYYyYskqIomghbkwUz9UIiHxhJQ9Xm/At/MojeLNKIsgfsjTJUrCkx/aJQmvmn8DQAnCjgurirAI6yM9RBVIzfMF7cwzKiHhPgro/0a1ynECqVuxdsDPwtIG0R6fd+41TppQafq9z+lW278/A0t9k9fjDAaVIfWYaXCoQMbYxK9CxFME5KXoznZ/shF2kevLTyVSkhuIWm3VRJv9a8Yu9f/LshTCUHUmp8v,iv:A4kVIPUPiU3zJup+3uScsAqJV68hkOj8O64/xcMbnno=,tag:Zp5fuf5FQAU8ASOHlIA5JQ==,type:str]", + "data": "ENC[AES256_GCM,data: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,iv:4EQedR+PsaqWdqLJxqvGwOg18v1lj801ZK4RNBr+VcU=,tag:Odf7ToKgssTUs/zH5s70OA==,type:str]", "sops": { "kms": null, "gcp_kms": null, @@ -11,8 +11,8 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoaGJabkhuMUFIY0RQcTJj\nbmZXOHBORWFvMkZKcmpXalJQeTU2L3IvYVVBClkrKy9DTE52aXlWNU5YQ3NTTXlp\nVUZ6c3NhQTliekVJbkpIbVpXZDlVUzAKLS0tIGU2bXBiWnZzdjYvZ2VnNmhEcjdP\na3MvRTcxVFdIQ0VmN2Ntb3hibE1OUlUKwXL/E+a49sXR5FMxxVyicCCVSfJo35jH\nG+PV8dG1Gb0IxwU2QLAJuBdrjtw3nVuytVWTVyrWXfE73LXHEX5/ZQ==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2023-04-22T13:56:02Z", - "mac": "ENC[AES256_GCM,data:QfultwLe7z5bkz7alga4mG6xgkk7EpDma4K6iYSEvuZX0XJ0wOSKFh39mSYohWSPkeueSSyeEJyEtPrD3V+Wwyf26dZ3bA+ixJiyYo8h701Cpe4yjkbSWcsvPY3eq0S8Ip3ia1YukvOt3zISeD5CHoc2bDhc+RNpjCstejzpuD8=,iv:10lef1+gEogy1viffeMUO+7sOsjQCU/QpKisi1GS7E8=,tag:J8b1/gVVtHZEE+PTudH70A==,type:str]", + "lastmodified": "2024-03-26T22:12:04Z", + "mac": "ENC[AES256_GCM,data:0XneYEAqw9VWnlHFYzMHWtI4GfNIoegsnH+nSM0pVpGk/g66mCMzYNCjzmrwe0fxwbWA5Ic/2unL2Egl70Kh7QkoFquVKUsobOA9GunkkUjDB/qDTONvjr3HmZGjqviknVPzuDpNyJVWGzY7GQQrRcI12s4kuewiDfVbxkqHqBs=,iv:dBwUv4FTuXVRsVu8wQbd/MQV1tWpH1BHTCfqqig/HGs=,tag:Qpu+uwmvr1PTnPc6AtJe7Q==,type:str]", "pgp": null, "unencrypted_suffix": "_unencrypted", "version": "3.7.3"