Files
2026-10-27 14:29:43 +03:00

88 lines
5.7 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Первый шаг переноса инстанса на другой куб (DST, по умолчанию loop-3): секреты + перепривязка в визоре.
# loopctl k8s rebind loop12a40f770b5a
# Источник = куб из SOURCES, где есть CR; провайдер БД в визоре ищется по host:port из секрета.
# Не делает: sync, гашение на исходном кубе, DNS (это loopctl k8s move).
set -euo pipefail
ID=${1:?loop id, например loop12a40f770b5a}
. "$(dirname "$0")/../lib/common.sh"
copy_secret() { # $1 имя; копирует с $SRC на $DST без вывода данных
kubectl --context "$SRC" -n loop get secret "$1" -o json \
| jq '{apiVersion,kind,type,data,metadata:{name:.metadata.name,namespace:"loop"}}' \
| kubectl --context "$DST" apply -f - >/dev/null
echo " $1 скопирован"
}
hash_secrets() { # $1 context
kubectl --context "$1" -n loop get secret "$ID-db-credentials" "$ID-s3-credentials" "$ID-license" -o json \
| jq -S '[.items[]|{n:.metadata.name,t:.type,d:.data}]' | shasum | cut -c1-12
}
echo "== $ID"
# источник = куб, где есть CR (registry неактуален); домен из ingress CR
for SRC in $SOURCES ""; do
[ -n "$SRC" ] || { echo "CR $ID не найден ни на одном исходном кубе"; exit 1; }
DOMAIN=$(kubectl --context "$SRC" -n loop get mattermost "$ID" -o jsonpath='{.spec.ingress.host}' 2>/dev/null) && [ -n "$DOMAIN" ] && break
done
SRC_CLUSTER=$(echo "select id from cluster_instance where name='$SRC';" | vsql)
DST_CLUSTER=$(echo "select id from cluster_instance where name='$DST';" | vsql)
[ -n "$DST_CLUSTER" ] || { echo "в визоре нет кластера $DST"; exit 1; }
echo " $DOMAIN $SRC"
# база в секрете на исходном кубе уже должна смотреть в Selectel
DBHOST=$(kubectl --context "$SRC" -n loop get secret "$ID-db-credentials" -o json | jq -r '.data.DB_CONNECTION_STRING|@base64d' | sed -E 's#.*@([^/]+)/.*#\1#')
echo " БД в секрете: $DBHOST"
case $DBHOST in *.mdb.yandexcloud.net*) echo "секрет ещё смотрит в Yandex, стоп"; exit 1;; esac
# CR с таким именем на $DST быть не должно
if kubectl --context "$DST" -n loop get mattermost "$ID" >/dev/null 2>&1; then echo "CR уже есть на $DST, стоп"; exit 1; fi
# провайдер БД = ON_PREM-провайдер визора с тем же host:port, что в секрете
PROVIDER=$(echo "select id||'|'||name from database_provider where vendor='ON_PREM' and host_name='${DBHOST%:*}' and host_port::text='${DBHOST##*:}';" | vsql)
[ "$(grep -c . <<<"$PROVIDER")" = 1 ] || { echo "в визоре не один ON_PREM-провайдер для $DBHOST: '$PROVIDER'"; exit 1; }
TARGET=${PROVIDER#*|}; PROVIDER=${PROVIDER%%|*}; echo " провайдер: $TARGET"
confirm "Скопирую секреты $ID на $DST и перепривяжу инстанс в визоре на $DST." || exit 1
echo "-- секреты на $DST"
for s in wildcard-loop.ru-tls private.docker.wilix.dev; do # общие, копируем один раз
kubectl --context "$DST" -n loop get secret "$s" >/dev/null 2>&1 || copy_secret "$s"
done
for s in db-credentials s3-credentials license; do copy_secret "$ID-$s"; done
H1=$(hash_secrets "$SRC"); H3=$(hash_secrets "$DST")
[ "$H1" = "$H3" ] || { echo "секреты не совпали: $H1 / $H3"; exit 1; }
echo " совпадают ($H1)"
# свой сертификат (не wildcard): cluster-issuer оставляем, иначе на новом кубе он перестанет продлеваться
OWN_TLS=$(kubectl --context "$SRC" -n loop get mattermost "$ID" -o jsonpath='{.spec.ingress.tlsSecret}')
[ "$OWN_TLS" = wildcard-loop.ru-tls ] && OWN_TLS=""
echo "-- визор"
TAIL=${ID#loop}
FOUND=$(printf "select i.id, i.domain, c.name, d.id from loop_instance i join cluster_instance c on c.id=i.cluster_instance_id join database_instance d on d.id=i.database_instance_id where i.id like '%%%s' and i.deleted_at is null;\n" "$TAIL" | vsql)
[ "$(printf '%s\n' "$FOUND" | grep -c .)" = 1 ] || { echo "в визоре не один инстанс: $FOUND"; exit 1; }
IFS='|' read -r VID VDOMAIN VCLUSTER DBID <<<"$FOUND"
echo " $VID $VDOMAIN куб=$VCLUSTER"
[ "$VDOMAIN" = "$DOMAIN" ] || { echo "домен в визоре другой: $VDOMAIN"; exit 1; }
vsql <<SQL
begin;
update loop_instance set cluster_instance_id='$DST_CLUSTER', synchronization_status='NOT_SYNCHRONIZED' where id='$VID';
update database_instance set vendor='ON_PREM',
database_provider_id='$PROVIDER'
where id='$DBID';
-- на целевом кубе traefik; без класса оператор ставит nginx. cluster-issuer убрать: с wildcard он перезапишет wildcard-loop.ru-tls
delete from loop_instance_annotation where loop_instance_id='$VID'
and (annotation='kubernetes.io/ingress.class' or (annotation='cert-manager.io/cluster-issuer' and '$OWN_TLS'=''));
insert into loop_instance_annotation(id, loop_instance_id, annotation, annotation_value)
values (gen_random_uuid()::text, '$VID', 'kubernetes.io/ingress.class', '${DST_INGRESS_CLASS:-traefik}');
select i.domain, c.name, p.name, d.vendor from loop_instance i
join cluster_instance c on c.id=i.cluster_instance_id
join database_instance d on d.id=i.database_instance_id
join database_provider p on p.id=d.database_provider_id where i.id='$VID';
commit;
SQL
echo "Готово. Дальше: loopctl k8s move $ID (env, sync, проверки, прокси, DNS)."
echo "Откат визора: update loop_instance set cluster_instance_id='$SRC_CLUSTER' where id='$VID';"