| #! /bin/bash |
| # Edits mailcow.conf in the mailcow-secrets secret with $EDITOR. |
| # |
| # Usage: edit-mailcow-conf [namespace] [secret] [key] |
| set -euo pipefail |
| |
| namespace=${1:-mulk} |
| secret=${2:-mailcow-secrets} |
| key=${3:-mailcow.conf} |
| |
| editor=${VISUAL:-${EDITOR:-vi}} |
| |
| # Keep the plaintext on tmpfs and readable only by us. |
| umask 077 |
| workdir=$(mktemp -d "${XDG_RUNTIME_DIR:-/tmp}/edit-secret.XXXXXX") |
| trap 'rm -rf "$workdir"' EXIT |
| |
| json=$(kubectl -n "$namespace" get secret "$secret" -o json) |
| resource_version=$(jq -r '.metadata.resourceVersion' <<<"$json") |
| jq -r --arg key "$key" '.data[$key] // error("key \($key) not found")' <<<"$json" \ |
| | base64 -d >"$workdir/original" |
| cp "$workdir/original" "$workdir/$key" |
| |
| while :; do |
| $editor "$workdir/$key" |
| |
| if cmp -s "$workdir/original" "$workdir/$key"; then |
| echo "No changes." |
| exit 0 |
| fi |
| |
| diff -u --label "$key (cluster)" --label "$key (edited)" \ |
| "$workdir/original" "$workdir/$key" || : |
| |
| read -r -p "Apply to secret $namespace/$secret? [y]es/[e]dit again/[n]o: " answer |
| case $answer in |
| y|Y|yes) break ;; |
| e|E|edit) continue ;; |
| *) echo "Aborted."; exit 1 ;; |
| esac |
| done |
| |
| # Including resourceVersion makes the patch fail if someone else changed |
| # the secret in the meantime. |
| jq -n \ |
| --arg key "$key" \ |
| --arg rv "$resource_version" \ |
| --arg data "$(base64 -w0 <"$workdir/$key")" \ |
| '{metadata: {resourceVersion: $rv}, data: {($key): $data}}' \ |
| >"$workdir/patch.json" |
| |
| kubectl -n "$namespace" patch secret "$secret" --type merge --patch-file "$workdir/patch.json" |