nová verze
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
# Executes a command inside the Redis master pod.
|
||||
# $@ (...): command and arguments to execute.
|
||||
function redisExec() {
|
||||
k3sRun exec pod/"$redisKube"-0 -c "$redisKube" -- "$@"
|
||||
}
|
||||
|
||||
# Executes a command inside a specific Redis or Redis Sentinel pod.
|
||||
# Container is selected automatically based on the pod name prefix.
|
||||
# $1 (pod): pod name.
|
||||
# $2+ (...): command and arguments to execute.
|
||||
function redisPodExec() {
|
||||
local pod="$1"
|
||||
[[ -n "$pod" ]] || { appError "Pod not specified"; return 1; }
|
||||
shift || true
|
||||
|
||||
local container="$redisKube"
|
||||
[[ "$pod" == "$redisSentinelKube-"* ]] && container="$redisSentinelKube"
|
||||
|
||||
k3sRun exec pod/"$pod" -c "$container" -- "$@"
|
||||
}
|
||||
|
||||
# Runs redis-cli against the master pod, with authentication if configured.
|
||||
# $@ (...): redis-cli arguments.
|
||||
function redisExecCli() {
|
||||
local -a cmd=(redis-cli --no-auth-warning)
|
||||
[[ -n "$redisRootPass" ]] && cmd+=(-a "$redisRootPass")
|
||||
redisExec "${cmd[@]}" "$@"
|
||||
}
|
||||
|
||||
# Runs redis-cli on a specific pod, with authentication and port selected automatically.
|
||||
# Uses port 26379 for Sentinel pods.
|
||||
# $1 (pod): pod name.
|
||||
# $2+ (...): redis-cli arguments.
|
||||
function redisPodExecCli() {
|
||||
local pod="$1"
|
||||
shift || true
|
||||
|
||||
local -a cmd=(redis-cli --no-auth-warning)
|
||||
[[ -n "$redisRootPass" ]] && cmd+=(-a "$redisRootPass")
|
||||
[[ "$pod" == "$redisSentinelKube-"* ]] && cmd+=(-p 26379)
|
||||
|
||||
redisPodExec "$pod" "${cmd[@]}" "$@"
|
||||
}
|
||||
|
||||
# Converts a domain name into a Redis-safe identifier (max 64 chars).
|
||||
# $1 (domain): domain name.
|
||||
function redisDomain2id() {
|
||||
domainToRandom "$1" 64
|
||||
}
|
||||
|
||||
# Reads the Redis root password from the Kubernetes secret.
|
||||
function redisRootPassSecretGet() {
|
||||
k3sRun get secret "$redisKube-secret" -o jsonpath="{.data.root-password}" --ignore-not-found | base64 -d
|
||||
}
|
||||
|
||||
# Saves the Redis root password from the Kubernetes secret to a local file.
|
||||
function redisRootPassSecretSave() {
|
||||
local password
|
||||
password="$(redisRootPassSecretGet)"
|
||||
[[ -n "$password" ]] && printf '%s\n' "$password" > "$appDataPath/$hostName.$redisKube"
|
||||
}
|
||||
|
||||
# Updates the Redis root password across pods. Not yet implemented.
|
||||
function redisRootPassUpdate() {
|
||||
|
||||
printWarning "In progress..."
|
||||
|
||||
# Add update pass in RedisSentinel and HAProxy !!!...
|
||||
|
||||
# k3sRun create secret generic "$redisKube-secret" --from-literal=root-password="$redisRootPass" --dry-run=client -o yaml | k3sRun apply -f -
|
||||
# k3sRun delete pod "$redisKube-0"
|
||||
# sleep 1
|
||||
# k3sRun delete pod "$redisKube-1"
|
||||
# k3sRun rollout restart "sts/$redisSentinelKube"
|
||||
|
||||
# return 1
|
||||
}
|
||||
|
||||
# List Redis users via ACL LIST (names only).
|
||||
function redisUserListGet() {
|
||||
local output error
|
||||
run output error redisExecCli ACL LIST || { appError "$error"; return 1; }
|
||||
printf '%s' "$output" | grep -oP 'user \K\w+'
|
||||
}
|
||||
|
||||
# Flushes all keys from the current Redis database.
|
||||
function redisDatabaseFlush() {
|
||||
runFail redisExecCli FLUSHDB
|
||||
}
|
||||
|
||||
# Persists the ACL user list to disk.
|
||||
function redisUserListSave() {
|
||||
runFail redisExecCli ACL SAVE
|
||||
}
|
||||
|
||||
# Creates or updates a Redis ACL user with password and key pattern.
|
||||
# $1 (username): ACL username.
|
||||
# $2 (password): ACL password.
|
||||
# [$3] (keyPattern): key access pattern (defaults to "username:*").
|
||||
function redisUserSet() {
|
||||
local username="$1"
|
||||
[[ -n "$username" ]] || { appError "Username not specified"; return 1; }
|
||||
local password="$2"
|
||||
[[ -n "$password" ]] || { appError "Password not specified"; return 1; }
|
||||
|
||||
local keyPattern="${3:-${username}:*}"
|
||||
|
||||
local podList error
|
||||
run podList error k3sPodList "$redisKube" || { appError "Get pods list: $error"; return 1; }
|
||||
[[ -n "$podList" ]] || { appError "Pods not found"; return 1; }
|
||||
|
||||
while read -r pod; do
|
||||
runFail redisPodExecCli "$pod" ACL SETUSER "$username" reset on sanitize-payload resetchannels ">$password" "~$keyPattern" -@all +@connection +@string +@keyspace +@sortedset +@scripting +@transaction +info -keys -flushdb -flushall '-script|flush' '-client|kill' '-client|pause' || return 1
|
||||
runFail redisPodExecCli "$pod" ACL SAVE || return 1
|
||||
done <<< "$podList"
|
||||
}
|
||||
|
||||
# Removes a Redis ACL user from all pods.
|
||||
# $1 (username): ACL username.
|
||||
function redisUserRemove() {
|
||||
local username="$1"
|
||||
[[ -n "$username" ]] || { appError "Username not specified"; return 1; }
|
||||
|
||||
local podList error
|
||||
run podList error k3sPodList "$redisKube" || { appError "Get pods list: $error"; return 1; }
|
||||
[[ -n "$podList" ]] || { appError "Pods not found"; return 1; }
|
||||
|
||||
while read -r pod; do
|
||||
runFail redisPodExecCli "$pod" ACL DELUSER "$username" || return 1
|
||||
runFail redisPodExecCli "$pod" ACL SAVE || return 1
|
||||
done <<< "$podList"
|
||||
}
|
||||
|
||||
# Deletes all Redis keys matching the given prefix.
|
||||
# $1 (prefixKey): key prefix to match (e.g. "user:").
|
||||
function redisKeysRemove() {
|
||||
local prefixKey="$1"
|
||||
[[ -n "$prefixKey" ]] || { appError "PrefixKey not specified"; return 1; }
|
||||
|
||||
local output error
|
||||
run output error redisExecCli --scan --pattern "${prefixKey}*" || { appError "$error"; return 1; }
|
||||
[[ -z "$output" ]] && return 0
|
||||
|
||||
local -a keys
|
||||
mapfile -t keys <<< "$output"
|
||||
runFail redisExecCli DEL "${keys[@]}"
|
||||
}
|
||||
|
||||
# Removes all Redis keys belonging to a site's user.
|
||||
# $1 (domain): site domain name.
|
||||
function redisDomainClean() {
|
||||
local domain="$1"
|
||||
domain=$(domainPrepare "$domain")
|
||||
domainCheck "$domain" || return 1
|
||||
|
||||
local redisUser
|
||||
redisUser=$(siteConfigGet "$domain" "redisUser")
|
||||
[[ -n "$redisUser" ]] && redisKeysRemove "$redisUser:"
|
||||
}
|
||||
|
||||
# Creates or updates the Redis ACL user and key pattern for a site.
|
||||
# $1 (domain): site domain name.
|
||||
function redisConfigRebuild() {
|
||||
local domain
|
||||
domain=$(domainPrepare "$1")
|
||||
domainCheck "$domain" || return 1
|
||||
|
||||
fileBackup "$redisPath/$redisFileUsersAcl"
|
||||
|
||||
local redisUser redisPass
|
||||
redisUser=$(siteConfigGetOrSet "$domain" "redisUser" "$(redisDomain2id "$domain")")
|
||||
redisPass=$(siteConfigGetOrCreate "$domain" "redisPass")
|
||||
redisUserSet "$redisUser" "$redisPass" || return 1
|
||||
}
|
||||
|
||||
# Parses raw SENTINEL REPLICAS output into tab-separated lines (name, ip, port, master-host, runid).
|
||||
# Skips disconnected/s_down replicas and deduplicates by runid.
|
||||
# $1 (raw): raw output from `SENTINEL replicas <master>`.
|
||||
function redisSentinelParseReplicas() {
|
||||
local raw="$1"
|
||||
local key value flags
|
||||
local -A slaveData=()
|
||||
local -A seenRunIds=()
|
||||
|
||||
while read -r key && read -r value; do
|
||||
if [[ "$key" == "name" && ${#slaveData[@]} -gt 0 ]]; then
|
||||
flags="${slaveData[flags]}"
|
||||
if [[ -n "${slaveData[runid]}" && "$flags" != *disconnected* && "$flags" != *s_down* ]]; then
|
||||
if [[ -z "${seenRunIds[${slaveData[runid]}]}" ]]; then
|
||||
seenRunIds["${slaveData[runid]}"]=1
|
||||
printf '%s\t%s\t%s\t%s\t%s\n' "${slaveData[name]}" "${slaveData[ip]}" "${slaveData[port]}" "${slaveData[master-host]}" "${slaveData[runid]}"
|
||||
fi
|
||||
fi
|
||||
slaveData=()
|
||||
fi
|
||||
slaveData["$key"]="$value"
|
||||
done <<< "$raw"
|
||||
|
||||
if [[ ${#slaveData[@]} -gt 0 ]]; then
|
||||
flags="${slaveData[flags]}"
|
||||
if [[ -n "${slaveData[runid]}" && "$flags" != *disconnected* && "$flags" != *s_down* ]]; then
|
||||
if [[ -z "${seenRunIds[${slaveData[runid]}]}" ]]; then
|
||||
printf '%s\t%s\t%s\t%s\t%s\n' "${slaveData[name]}" "${slaveData[ip]}" "${slaveData[port]}" "${slaveData[master-host]}" "${slaveData[runid]}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user