refactor: simplify staged stack configuration

This commit is contained in:
lingkai5wu committed 2026-10-10 17:37:11 +08:00
1 parent 48ddc3e728
commit ebab7d3213
2 files changed
+65 -79

No files matched your search

+56 -58
View File
@@ -10,9 +10,10 @@ LOCK_FILE="${STACKS_LOCK_FILE:-/run/lock/stacks-manage.lock}"
DEFAULT_MAX_PARALLEL=2
CONFIG_GROUP_NAMES=()
CONFIG_GROUP_LIMITS=()
CONFIG_GROUP_STACKS=()
BEFORE_GROUPS=()
BEFORE_LIMITS=()
AFTER_GROUPS=()
AFTER_LIMITS=()
CONFIGURED_STACKS=()
EXCLUDED_STACKS=()
@@ -21,7 +22,6 @@ MANAGED_STACKS=()
GROUP_NAMES=()
GROUP_LIMITS=()
GROUP_STACKS=()
UNASSIGNED_STACKS=()
RUN_SUCCESS=0
RUN_FAILED=0
@@ -52,9 +52,10 @@ Commands:
list List discovered stacks and their group/status
Bulk execution:
up/start/restart/pull/update run groups in declaration order.
stop/down run groups in reverse order.
Stacks within a group run in parallel up to that group's limit.
up/start/restart/pull/update run before, default, then after.
stop/down run the same groups in reverse order.
Each before/after declaration creates an ordered group.
Stacks within a group run in parallel up to its configured limit.
ps/images/list keep ordered output.
Configuration: $CONFIG_FILE
@@ -88,52 +89,48 @@ validate_name() {
die "invalid $kind name: $value"
}
# Set the default concurrency for groups without an override.
# Set the maximum concurrency within each stage.
max_parallel() {
[[ $# -eq 1 ]] || die "max_parallel expects exactly one value"
validate_parallel_limit "$1"
DEFAULT_MAX_PARALLEL="$1"
}
# Declare an ordered group and its stacks.
# Usage: group NAME [--parallel N] STACK...
group() {
[[ $# -ge 2 ]] || die "group expects NAME [--parallel N] STACK..."
local name="$1"
add_stage_group() {
local groups_name="$1"
local limits_name="$2"
local stage="$3"
local limit=""
local stack
shift
validate_name "group" "$name"
[[ "$name" != "unassigned" ]] ||
die "group name is reserved: $name"
contains "$name" "${CONFIG_GROUP_NAMES[@]}" &&
die "group is declared more than once: $name"
local -n groups="$groups_name"
local -n limits="$limits_name"
shift 3
if [[ "${1:-}" == "--parallel" ]]; then
[[ $# -ge 3 ]] || die "group $name: --parallel expects a value and at least one stack"
[[ $# -ge 3 ]] || die "$stage --parallel expects a value and at least one stack"
limit="$2"
validate_parallel_limit "$limit"
shift 2
fi
[[ $# -ge 1 ]] || die "group has no stacks: $name"
[[ $# -ge 1 ]] || die "$stage expects at least one stack"
for stack in "$@"; do
validate_name "stack" "$stack"
contains "$stack" "${CONFIGURED_STACKS[@]}" &&
die "stack is assigned to more than one group: $stack"
die "stack is assigned more than once: $stack"
contains "$stack" "${EXCLUDED_STACKS[@]}" &&
die "stack is both grouped and excluded: $stack"
die "stack is both assigned and excluded: $stack"
CONFIGURED_STACKS+=("$stack")
done
CONFIG_GROUP_NAMES+=("$name")
CONFIG_GROUP_LIMITS+=("$limit")
CONFIG_GROUP_STACKS+=("$*")
groups+=("$*")
limits+=("$limit")
}
before() { add_stage_group BEFORE_GROUPS BEFORE_LIMITS before "$@"; }
after() { add_stage_group AFTER_GROUPS AFTER_LIMITS after "$@"; }
# Exclude stacks from all bulk operations.
exclude() {
[[ $# -ge 1 ]] || die "exclude expects at least one stack"
@@ -144,7 +141,7 @@ exclude() {
contains "$stack" "${EXCLUDED_STACKS[@]}" &&
die "stack is excluded more than once: $stack"
contains "$stack" "${CONFIGURED_STACKS[@]}" &&
die "stack is both grouped and excluded: $stack"
die "stack is both assigned and excluded: $stack"
EXCLUDED_STACKS+=("$stack")
done
}
@@ -152,7 +149,7 @@ exclude() {
load_config() {
[[ -f "$CONFIG_FILE" ]] || return 0
# The trusted config calls max_parallel, group, and exclude above.
# The trusted config calls max_parallel, before, after, and exclude above.
source "$CONFIG_FILE" || die "cannot load config file: $CONFIG_FILE"
}
@@ -187,45 +184,52 @@ validate_config_stacks() {
done
}
build_execution_groups() {
local i stack limit
append_stage_groups() {
local stage="$1"
local groups_name="$2"
local limits_name="$3"
local i name
local -a stacks=()
local -n groups="$groups_name"
local -n limits="$limits_name"
for ((i = 0; i < ${#groups[@]}; i++)); do
name="$stage"
((${#groups[@]} > 1)) && name+="-$((i + 1))"
GROUP_NAMES+=("$name")
GROUP_LIMITS+=("${limits[i]:-$DEFAULT_MAX_PARALLEL}")
GROUP_STACKS+=("${groups[i]}")
read -r -a stacks <<<"${groups[i]}"
MANAGED_STACKS+=("${stacks[@]}")
done
}
build_execution_groups() {
local stack
local -a default_stacks=()
GROUP_NAMES=()
GROUP_LIMITS=()
GROUP_STACKS=()
MANAGED_STACKS=()
UNASSIGNED_STACKS=()
for ((i = 0; i < ${#CONFIG_GROUP_NAMES[@]}; i++)); do
limit="${CONFIG_GROUP_LIMITS[i]:-$DEFAULT_MAX_PARALLEL}"
GROUP_NAMES+=("${CONFIG_GROUP_NAMES[i]}")
GROUP_LIMITS+=("$limit")
GROUP_STACKS+=("${CONFIG_GROUP_STACKS[i]}")
read -r -a stacks <<<"${CONFIG_GROUP_STACKS[i]}"
MANAGED_STACKS+=("${stacks[@]}")
done
append_stage_groups before BEFORE_GROUPS BEFORE_LIMITS
for stack in "${DISCOVERED_STACKS[@]}"; do
if ! contains "$stack" "${CONFIGURED_STACKS[@]}" &&
! contains "$stack" "${EXCLUDED_STACKS[@]}"; then
UNASSIGNED_STACKS+=("$stack")
MANAGED_STACKS+=("$stack")
default_stacks+=("$stack")
fi
done
if ((${#UNASSIGNED_STACKS[@]} > 0)); then
GROUP_NAMES+=("unassigned")
if ((${#default_stacks[@]} > 0)); then
GROUP_NAMES+=("default")
GROUP_LIMITS+=("$DEFAULT_MAX_PARALLEL")
GROUP_STACKS+=("${UNASSIGNED_STACKS[*]}")
GROUP_STACKS+=("${default_stacks[*]}")
MANAGED_STACKS+=("${default_stacks[@]}")
fi
}
warn_unassigned() {
((${#UNASSIGNED_STACKS[@]} == 0)) && return 0
echo "WARNING: unassigned stacks will run in the final implicit group: ${UNASSIGNED_STACKS[*]}" >&2
append_stage_groups after AFTER_GROUPS AFTER_LIMITS
}
stack_group() {
@@ -463,8 +467,6 @@ run_all_grouped() {
RUN_FAILED=0
RUN_FAILED_STACKS=()
RUN_SKIPPED_GROUPS=()
warn_unassigned
if [[ "$action" == "stop" || "$action" == "down" ]]; then
direction="reverse"
start=$((end - 1))
@@ -487,8 +489,6 @@ run_all_sequential() {
local action="$1"
local stack
local -a failed_stacks=()
warn_unassigned
for stack in "${MANAGED_STACKS[@]}"; do
run_stack "$stack" "$action" || failed_stacks+=("$stack")
done
@@ -503,7 +503,6 @@ run_all_sequential() {
list_stacks() {
local stack group_name status
warn_unassigned
printf '%-24s %-16s %s\n' "STACK" "GROUP" "STATUS"
printf '%-24s %-16s %s\n' "------------------------" "----------------" "---------------"
@@ -546,7 +545,6 @@ list_images() {
return
fi
warn_unassigned
for stack in "${MANAGED_STACKS[@]}"; do
stack_images "$stack" || ((failed += 1))
done