Surface runtime health in menu
This commit is contained in:
@@ -72,6 +72,8 @@ sudo ./iptables-forward.sh
|
|||||||
- 立即保存到磁盘
|
- 立即保存到磁盘
|
||||||
- 退出
|
- 退出
|
||||||
|
|
||||||
|
主菜单状态行会同时显示环境状态、规则数、持久化可用性与运行态健康;若数据库里存在半残规则,`运行态` 会降级为 `[!]`。
|
||||||
|
|
||||||
规则列表中的状态列含义:
|
规则列表中的状态列含义:
|
||||||
|
|
||||||
- `✓`:该条规则对应的 PREROUTING / POSTROUTING / 双向 FORWARD 运行态规则都存在
|
- `✓`:该条规则对应的 PREROUTING / POSTROUTING / 双向 FORWARD 运行态规则都存在
|
||||||
|
|||||||
@@ -63,9 +63,10 @@ bootstrap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render_main_menu() {
|
render_main_menu() {
|
||||||
local status persist count width line
|
local status persist runtime count width line
|
||||||
status=$(env_status_summary)
|
status=$(env_status_summary)
|
||||||
count=$(storage_count)
|
count=$(storage_count)
|
||||||
|
runtime=$(rules_runtime_mark)
|
||||||
if persist_available; then
|
if persist_available; then
|
||||||
persist='[✓]'
|
persist='[✓]'
|
||||||
else
|
else
|
||||||
@@ -77,7 +78,7 @@ render_main_menu() {
|
|||||||
box_top "${width}"
|
box_top "${width}"
|
||||||
box_line "${width}" "${IPF_APP_NAME}"
|
box_line "${width}" "${IPF_APP_NAME}"
|
||||||
box_separator "${width}"
|
box_separator "${width}"
|
||||||
box_line "${width}" "状态: ${status} 规则数: ${count} 持久化: ${persist}"
|
box_line "${width}" "状态: ${status} 规则数: ${count} 持久化: ${persist} 运行态: ${runtime}"
|
||||||
box_separator "${width}"
|
box_separator "${width}"
|
||||||
for line in "${MENU_LINES[@]}"; do
|
for line in "${MENU_LINES[@]}"; do
|
||||||
box_line "${width}" "${line}"
|
box_line "${width}" "${line}"
|
||||||
@@ -85,7 +86,7 @@ render_main_menu() {
|
|||||||
box_bottom "${width}"
|
box_bottom "${width}"
|
||||||
else
|
else
|
||||||
printf '%s\n' "${IPF_APP_NAME}"
|
printf '%s\n' "${IPF_APP_NAME}"
|
||||||
printf '状态: %s | 规则数: %s | 持久化: %s\n' "${status}" "${count}" "${persist}"
|
printf '状态: %s | 规则数: %s | 持久化: %s | 运行态: %s\n' "${status}" "${count}" "${persist}" "${runtime}"
|
||||||
printf '%s\n' "${MENU_LINES[@]}"
|
printf '%s\n' "${MENU_LINES[@]}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,6 +146,14 @@ rule_health_mark() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rules_runtime_mark() {
|
||||||
|
local line
|
||||||
|
while IFS= read -r line || [[ -n ${line} ]]; do
|
||||||
|
[[ -z ${line} || $(rule_health_mark "${line}") == '✓' ]] || { printf '[!]\n'; return 0; }
|
||||||
|
done < <(storage_list)
|
||||||
|
printf '[✓]\n'
|
||||||
|
}
|
||||||
|
|
||||||
render_rules_row() {
|
render_rules_row() {
|
||||||
printf '%s %s %s %s %s %s %s %s\n' \
|
printf '%s %s %s %s %s %s %s %s\n' \
|
||||||
"$(pad_right "${1-}" 3)" "$(pad_right "${2-}" 10)" "$(pad_right "${3-}" 10)" "$(pad_right "${4-}" 32)" \
|
"$(pad_right "${1-}" 3)" "$(pad_right "${2-}" 10)" "$(pad_right "${3-}" 10)" "$(pad_right "${4-}" 32)" \
|
||||||
|
|||||||
@@ -40,6 +40,27 @@ export NETFILTER_PERSISTENT_BIN="${ROOT_DIR}/tests/mocks/persist-mock.sh"
|
|||||||
export PERSIST_MOCK_LOG="${TMP_DIR}/persist.log"
|
export PERSIST_MOCK_LOG="${TMP_DIR}/persist.log"
|
||||||
export IPF_SKIP_ENV_CHECK=1
|
export IPF_SKIP_ENV_CHECK=1
|
||||||
export IPF_FORCE_PLAIN_UI=1
|
export IPF_FORCE_PLAIN_UI=1
|
||||||
|
|
||||||
|
# shellcheck source=lib/common.sh
|
||||||
|
source "${ROOT_DIR}/lib/common.sh"
|
||||||
|
# shellcheck source=lib/storage.sh
|
||||||
|
source "${ROOT_DIR}/lib/storage.sh"
|
||||||
|
# shellcheck source=lib/persist.sh
|
||||||
|
source "${ROOT_DIR}/lib/persist.sh"
|
||||||
|
# shellcheck source=lib/iptables_ops.sh
|
||||||
|
source "${ROOT_DIR}/lib/iptables_ops.sh"
|
||||||
|
# shellcheck source=lib/rules_mgr.sh
|
||||||
|
source "${ROOT_DIR}/lib/rules_mgr.sh"
|
||||||
|
|
||||||
|
reset_mock_state() {
|
||||||
|
rm -rf "${IPTABLES_MOCK_DIR}" "${IPF_STORAGE_DIR}"
|
||||||
|
mkdir -p "${IPTABLES_MOCK_DIR}" "${IPF_STORAGE_DIR}"
|
||||||
|
: >"${IPTABLES_MOCK_LOG}"
|
||||||
|
: >"${PERSIST_MOCK_LOG}"
|
||||||
|
storage_init
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_mock_state
|
||||||
export IPF_TEST_INPUTS=$'4\n2\n1\n8080\n1\n127.0.0.1\n80\ninteractive web\ny\n5\n1\n3\n1\ny\n0\n'
|
export IPF_TEST_INPUTS=$'4\n2\n1\n8080\n1\n127.0.0.1\n80\ninteractive web\ny\n5\n1\n3\n1\ny\n0\n'
|
||||||
|
|
||||||
output=$("${ROOT_DIR}/iptables-forward.sh" 2>&1)
|
output=$("${ROOT_DIR}/iptables-forward.sh" 2>&1)
|
||||||
@@ -59,4 +80,17 @@ assert_eq '4' "$(grep -Ec ' -A ' "${IPTABLES_MOCK_LOG}")" 'interactive add flow
|
|||||||
assert_eq '4' "$(grep -Ec ' -D ' "${IPTABLES_MOCK_LOG}")" 'interactive delete should emit four delete commands'
|
assert_eq '4' "$(grep -Ec ' -D ' "${IPTABLES_MOCK_LOG}")" 'interactive delete should emit four delete commands'
|
||||||
assert_eq '3' "$(grep -Ec 'persist-mock\.sh save' "${PERSIST_MOCK_LOG}")" 'interactive add/menu-save/delete flow should persist three times'
|
assert_eq '3' "$(grep -Ec 'persist-mock\.sh save' "${PERSIST_MOCK_LOG}")" 'interactive add/menu-save/delete flow should persist three times'
|
||||||
|
|
||||||
|
reset_mock_state
|
||||||
|
uuid=$(cmd_add_batch tcp 8081 127.0.0.1 81 4 'degraded menu' 2>/dev/null)
|
||||||
|
"${IPTABLES_BIN}" -D FORWARD \
|
||||||
|
-p tcp -s 127.0.0.1 --sport 81 \
|
||||||
|
-m conntrack --ctstate ESTABLISHED,RELATED \
|
||||||
|
-j ACCEPT \
|
||||||
|
-m comment --comment "MGMT:${uuid}"
|
||||||
|
export IPF_TEST_INPUTS=$'0\n'
|
||||||
|
|
||||||
|
degraded_output=$("${ROOT_DIR}/iptables-forward.sh" 2>&1)
|
||||||
|
assert_contains "${degraded_output}" '运行态: [!]' 'main menu should surface degraded runtime status'
|
||||||
|
assert_contains "${degraded_output}" '规则数: 1' 'main menu should still show current rule count'
|
||||||
|
|
||||||
pass 'test_interactive.sh'
|
pass 'test_interactive.sh'
|
||||||
|
|||||||
Reference in New Issue
Block a user