ai cooking
1#!/usr/bin/env bash
2set -euo pipefail
3
4usage() {
5 cat <<'EOF'
6Usage:
7 ./getsecret.sh get [secrets-dir] [namespace]
8 ./getsecret.sh put [secrets-dir] [namespace]
9
10Commands:
11 get Fetch every Kubernetes Secret in the namespace and write each
12 one to secrets-dir/<secret-name>.env.
13 put Apply each *.env file in secrets-dir to the Kubernetes Secret with
14 the same basename.
15
16Arguments:
17 secrets-dir Directory containing split env files (default: secrets/prod)
18 namespace Kubernetes namespace (default: careme)
19
20Examples:
21 ./getsecret.sh get
22 ./getsecret.sh put secrets/prod
23 ./getsecret.sh get secrets/test careme
24EOF
25}
26
27require_command() {
28 if ! command -v "$1" >/dev/null 2>&1; then
29 echo "error: required command not found: $1" >&2
30 exit 1
31 fi
32}
33
34sync_get() {
35 local secrets_dir="$1"
36 local namespace="$2"
37 local secret_names=()
38
39 mkdir -p "${secrets_dir}"
40
41 mapfile -t secret_names < <(
42 kubectl get secrets \
43 -n "${namespace}" \
44 -o json \
45 | jq -r '.items | sort_by(.metadata.name)[] | .metadata.name'
46 )
47
48 if [[ ${#secret_names[@]} -eq 0 ]]; then
49 echo "error: no secrets found in namespace '${namespace}'" >&2
50 exit 1
51 fi
52
53 local secret_name
54 for secret_name in "${secret_names[@]}"; do
55 local file
56 local tmp_file
57 file="${secrets_dir}/${secret_name}.env"
58 tmp_file="$(mktemp)"
59
60 kubectl get secret "${secret_name}" \
61 -n "${namespace}" \
62 -o json \
63 | jq -r '
64 .data
65 | to_entries
66 | sort_by(.key)[]
67 | "\(.key)=\(.value | @base64d)"
68 ' > "${tmp_file}"
69
70 mv "${tmp_file}" "${file}"
71 echo "synced secret '${secret_name}' from namespace '${namespace}' to ${file}"
72 done
73}
74
75sync_put() {
76 local secrets_dir="$1"
77 local namespace="$2"
78 local files=()
79
80 shopt -s nullglob
81 files=("${secrets_dir}"/*.env)
82 shopt -u nullglob
83
84 if [[ ${#files[@]} -eq 0 ]]; then
85 echo "error: no .env files found in ${secrets_dir}" >&2
86 exit 1
87 fi
88
89 local file
90 for file in "${files[@]}"; do
91 local secret_name
92 secret_name="$(basename "${file}" .env)"
93
94 kubectl create secret generic "${secret_name}" \
95 --from-env-file="${file}" \
96 --dry-run=client \
97 -o yaml \
98 | kubectl apply -n "${namespace}" -f -
99
100 echo "applied ${file} to secret '${secret_name}' in namespace '${namespace}'"
101 done
102}
103
104main() {
105 if [[ $# -lt 1 || $# -gt 3 ]]; then
106 usage
107 exit 1
108 fi
109
110 require_command kubectl
111 require_command jq
112
113 local command="$1"
114 local secrets_dir="${2:-secrets/prod}"
115 local namespace="${3:-careme}"
116
117 case "${command}" in
118 get)
119 sync_get "${secrets_dir}" "${namespace}"
120 ;;
121 put)
122 sync_put "${secrets_dir}" "${namespace}"
123 ;;
124 -h|--help|help)
125 usage
126 ;;
127 *)
128 echo "error: unknown command '${command}'" >&2
129 usage
130 exit 1
131 ;;
132 esac
133}
134
135main "$@"