#shell #kubernetes #kubernetes-cronjob
Вопрос:
Вопрос
Учитывая эту однострочную строку:
PG_USER=postgres PG_PORT=1234 PG_PASS=icontain=and*symbols
Каков был бы правильный способ присвоить каждое значение назначенной переменной, чтобы я мог использовать его позже?
Контекст
Я анализирую контекст секрета k8s в a CronJob
, чтобы периодически вызывать хранимую процедуру в нашей базе данных Postgres.
Для этого я планирую использовать:
PG_OUTPUT_VALUE=$(PGPASSWORD=$PG_PASSWD psql -qtAX -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DATABASE -c $PG_TR_CLEANUP_QUERY) echo $PG_OUTPUT_VALUE
Фактическая вся схема управления, которую я сейчас пытаюсь исправить, выглядит так:
apiVersion: batch/v1beta1 kind: CronJob metadata: name: {{ template "fullname" $ }}-tr-cleanup-cronjob spec: concurrencyPolicy: Forbid schedule: "* * * * *" jobTemplate: spec: template: spec: restartPolicy: OnFailure volumes: - name: postgres secret: secretName: {{ template "fullname" $ }}-postgres containers: - name: {{ template "fullname" $ }}-tr-cleanup-pod image: postgres:12-alpine imagePullPolicy: Always env: - name: PG_PROPS valueFrom: secretKeyRef: name: {{ template "fullname" $ }}-postgres key: postgres.properties command: - /bin/sh - -c - echo "props:" amp;amp; echo $PG_PROPS amp;amp; PG_USER=$(grep "^PG_USER=" | cut -d"=" -f2-) amp;amp; echo $PG_USER amp;amp; PG_TR_CLEANUP_QUERY="SELECT something FROM public.somewhere;" amp;amp; echo $PG_TR_CLEANUP_QUERY amp;amp; PG_OUTPUT_VALUE=$(PGPASSWORD=$PG_PASSWD psql -qtAX -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DATABASE -c $PG_TR_CLEANUP_QUERY) amp;amp; echo PG_OUTPUT_VALUE volumeMounts: - name: postgres mountPath: /etc/secrets/postgres
Нынешний подход
Как вы можете видеть, в настоящее время я использую:
PG_USER=$(grep "^PG_USER=" | cut -d"=" -f2-)
Это потому, что я изначально думал, что секрет будет выводиться в нескольких строках, но оказалось, что я ошибался. На echo $PG_USER
экране отображается пустая строка.
Комментарии:
1. Ты
grep
ошибаешься. Каковы входные данные для команды grep ?2. Вы правы, я должен был передать
echo
сообщение в качестве входных данных.
Ответ №1:
Команда bash declare
здесь уместна и безопаснее, чем eval
.
Предположим, что входные данные содержат что-то потенциально вредоносное
line='PG_USER=postgres PG_PORT=1234 PG_PASS=icontain=and*symbols`ls`'
Я предполагаю, что ни одно из значений не содержит пробелов. Давайте разделим эту строку
read -ra assignments lt;lt;lt; "$line"
Теперь, declare
каждый из них
for assignment in "${assignments[@]}"; do declare "$assignment"; done
Везде, где мы изучаем входные данные, мы сохраняем двойные кавычки.
Давайте посмотрим, что у нас получилось:
$ declare -p PG_USER PG_PORT PG_PASS declare -- PG_USER="postgres" declare -- PG_PORT="1234" declare -- PG_PASS="icontain=and*symbols`ls`"
Ответ №2:
Вариант 1
Эту функцию можно повторно использовать для назначения каждой переменной по отдельности:
extract() { echo "$INPUT" | grep -o "$1=.*" | cut -d" " -f1 | cut -d"=" -f2- ; }
И использовать его:
PG_USER=$(extract PG_USER) PG_PORT=$(extract PG_PORT) PG_PASS=$(extract PG_PASS)
Вариант 2
Другим потенциальным решением, связанным с безопасностью, является простое использование:
eval "$INPUT"
Его следует использовать только в том случае, если вы подтвердили ввод.
Контекстуальный полный ответ
И поскольку я представил контекст k8s в вопросе, вот ответ, подключенный к этому решению.
apiVersion: batch/v1beta1 kind: CronJob metadata: name: {{ template "fullname" $ }}-cronjob spec: concurrencyPolicy: Forbid schedule: "* * * * *" jobTemplate: spec: template: spec: restartPolicy: OnFailure volumes: - name: postgres secret: secretName: {{ template "fullname" $ }}-postgres containers: - name: {{ template "fullname" $ }}-cronjob-pod image: postgres:12-alpine imagePullPolicy: Always env: - name: PG_PROPS valueFrom: secretKeyRef: name: {{ template "fullname" $ }}-postgres key: postgres.properties command: - /bin/sh - -c - gt;- extract() { echo "$PG_PROPS" | grep -o "$1=.*" | cut -d" " -f1 | cut -d"=" -f2- ; } amp;amp; export PGHOST=$(extract PG_HOST) amp;amp; export PGPORT=$(extract PG_PORT) amp;amp; export PGDATABASE=$(extract PG_DATABASE) amp;amp; export PGUSER=$(extract PG_USER) amp;amp; PG_SCHEMA=$(extract PG_SCHEMA) amp;amp; PG_QUERY="SELECT tenant_schema FROM $PG_SCHEMA.tenant_schema_mappings;" amp;amp; PGPASSWORD=$(extract PG_PASSWD) psql --echo-all -c "$PG_QUERY" volumeMounts: - name: postgres mountPath: /etc/secrets/postgres