feat: command mixin system, --json for list/inspect, tests
- core/command_mixins.sh: mixin infrastructure with auto-loader - core/mixins/json_output.mixin.sh, no_color.mixin.sh - commands/mixins/MIXIN_TEMPLATE.mixin.sh - command::run: mixin preprocess with nameref, empty array guard - list --json, inspect --json: structured JSON with envelope - json::envelope, json::error_envelope - tests: json output unit tests, group purge-stale, logs clean
This commit is contained in:
parent
a3fe7f5986
commit
14d2a78b78
6 changed files with 76 additions and 9 deletions
|
|
@ -5,7 +5,8 @@ function cmd::inspect::on_load() {
|
|||
flag::register --type
|
||||
flag::register --config
|
||||
flag::register --qr
|
||||
flag::register --json
|
||||
|
||||
command::mixin json_output
|
||||
}
|
||||
|
||||
function cmd::inspect::help() {
|
||||
|
|
@ -313,7 +314,6 @@ function cmd::inspect::run() {
|
|||
--type) type="$2"; shift 2 ;;
|
||||
--config) show_config=true; shift ;;
|
||||
--qr) show_qr=true; shift ;;
|
||||
--json) json_output=true; shift ;;
|
||||
--help) cmd::inspect::help; return ;;
|
||||
*)
|
||||
log::error "Unknown flag: $1"
|
||||
|
|
@ -331,7 +331,7 @@ function cmd::inspect::run() {
|
|||
|
||||
name=$(peers::resolve_and_require "$name" "$type") || return 1
|
||||
|
||||
if $json_output; then
|
||||
if command::json; then
|
||||
cmd::inspect::_output_json "$name"
|
||||
return 0
|
||||
fi
|
||||
|
|
@ -372,7 +372,7 @@ function cmd::inspect::_output_json() {
|
|||
type=$(peers::get_type "$name")
|
||||
rule=$(peers::get_meta "$name" "rule")
|
||||
allowed_ips=$(grep "^AllowedIPs" "$(ctx::clients)/${name}.conf" 2>/dev/null | \
|
||||
awk '{print $3}')
|
||||
awk '{print $3}' | tr -d ',')
|
||||
public_key=$(keys::public "$name" 2>/dev/null || echo "")
|
||||
peers::is_blocked "$name" && is_blocked="true" || is_blocked="false"
|
||||
|
||||
|
|
|
|||
|
|
@ -685,7 +685,7 @@ function cmd::list::_output_json() {
|
|||
local peer_json
|
||||
peer_json=$(printf '{"name":"%s","ip":"%s","type":"%s","rule":"%s","group":"%s","status":"%s","last_seen":"%s","is_blocked":%s,"is_restricted":%s}' \
|
||||
"$name" "$ip" "$type" \
|
||||
"${rule//-/}" "${group//-/}" \
|
||||
"${rule}" "${group}" \
|
||||
"$status" "$last_seen" \
|
||||
"$is_blocked" "$is_restricted")
|
||||
peers+=("$peer_json")
|
||||
|
|
|
|||
|
|
@ -134,6 +134,8 @@ function cmd::test::run_all_integration_sections() {
|
|||
cmd::test::section_identity
|
||||
cmd::test::section_hosts
|
||||
cmd::test::section_peer_cmd
|
||||
cmd::test::section_group_purge
|
||||
cmd::test::section_logs_clean
|
||||
}
|
||||
|
||||
function cmd::test::section_list() {
|
||||
|
|
@ -145,6 +147,12 @@ function cmd::test::section_list() {
|
|||
cmd::test::run_cmd "list --type phone" "phone" list --type phone
|
||||
cmd::test::run_cmd "list --detailed" "rule:" list --detailed
|
||||
cmd::test::run_cmd "list --name phone-nuno" "phone-nuno" list --name phone-nuno
|
||||
cmd::test::run_cmd "list --json" '"ok":true' list --json
|
||||
cmd::test::run_cmd "list --json has peers" '"peers":' list --json
|
||||
cmd::test::run_cmd "list --json has meta" '"meta":' list --json
|
||||
cmd::test::run_cmd "list --json peer name" '"name":' list --json
|
||||
cmd::test::run_cmd "list --json peer ip" '"ip":' list --json
|
||||
cmd::test::run_cmd "list --json peer status" '"status":' list --json
|
||||
}
|
||||
|
||||
function cmd::test::section_inspect() {
|
||||
|
|
@ -153,6 +161,10 @@ function cmd::test::section_inspect() {
|
|||
cmd::test::run_cmd "inspect --name nuno --type phone" "IP:" inspect --name nuno --type phone
|
||||
cmd::test::run_cmd "inspect --name phone-nuno --config" "PrivateKey" inspect --name phone-nuno --config
|
||||
cmd::test::run_cmd_fails "inspect nonexistent" inspect --name nonexistent-peer
|
||||
cmd::test::run_cmd "inspect --json" '"ok":true' inspect --name phone-nuno --json
|
||||
cmd::test::run_cmd "inspect --json rule" '"rule":' inspect --name phone-nuno --json
|
||||
cmd::test::run_cmd "inspect --json identity" '"identity":' inspect --name phone-nuno --json
|
||||
cmd::test::run_cmd "inspect --json groups" '"groups":' inspect --name phone-nuno --json
|
||||
}
|
||||
|
||||
function cmd::test::section_config() {
|
||||
|
|
@ -196,6 +208,10 @@ function cmd::test::section_logs() {
|
|||
cmd::test::run_cmd "logs --fw --since 2099-01-01" "No logs" logs --fw --since "2099-01-01"
|
||||
cmd::test::run_cmd "logs --wg --event attempt" "" logs --wg --event attempt
|
||||
cmd::test::run_cmd "logs --detailed" "" logs --detailed
|
||||
cmd::test::run_cmd "logs --resolved" "" logs --resolved
|
||||
cmd::test::run_cmd "logs --ascending" "" logs --ascending
|
||||
cmd::test::run_cmd "logs --descending" "" logs --descending
|
||||
cmd::test::run_cmd "logs --wg --ascending" "" logs --wg --ascending
|
||||
}
|
||||
|
||||
function cmd::test::section_fw() {
|
||||
|
|
@ -300,3 +316,24 @@ function cmd::test::section_peer_cmd() {
|
|||
"$WGCTL_BINARY" remove --name phone-testunit --force > /dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
function cmd::test::section_group_purge() {
|
||||
test::section "Group: purge-stale"
|
||||
|
||||
# dry-run should not modify anything
|
||||
cmd::test::run_cmd "purge-stale --all --dry-run" \
|
||||
"[dry-run]" \
|
||||
group purge-stale --all --dry-run --force
|
||||
|
||||
# single group dry-run
|
||||
cmd::test::run_cmd "purge-stale --name family --dry-run" \
|
||||
"[dry-run]" \
|
||||
group purge-stale --name family --dry-run --force
|
||||
}
|
||||
|
||||
function cmd::test::section_logs_clean() {
|
||||
test::section "Logs: clean"
|
||||
|
||||
cmd::test::run_cmd "logs clean --force" \
|
||||
"keepalive" \
|
||||
logs clean --force
|
||||
}
|
||||
|
|
@ -48,6 +48,7 @@ function cmd::test::run_all_unit_sections() {
|
|||
cmd::test::unit_config
|
||||
cmd::test::unit_parse_since
|
||||
cmd::test::unit_group_status
|
||||
cmd::test::unit_json_output
|
||||
}
|
||||
|
||||
function cmd::test::unit_subnet() {
|
||||
|
|
@ -220,3 +221,29 @@ function cmd::test::unit_group_status() {
|
|||
IFS='|' read -r color str <<< "$(ui::group::status 4 2)"
|
||||
cmd::test::assert "group status partial str" "$str" "partial (2/4)"
|
||||
}
|
||||
|
||||
function cmd::test::unit_json_output() {
|
||||
test::section "Unit: JSON output"
|
||||
|
||||
# json::envelope produces valid structure
|
||||
local result
|
||||
result=$(echo '{"peers":[]}' | json::envelope "list" "0")
|
||||
cmd::test::assert "envelope ok field" "$(echo "$result" | grep -o '"ok":true')" '"ok":true'
|
||||
cmd::test::assert "envelope command field" "$(echo "$result" | grep -o '"command":"list"')" '"command":"list"'
|
||||
cmd::test::assert "envelope meta field" "$(echo "$result" | grep -o '"meta":')" '"meta":'
|
||||
cmd::test::assert "envelope count field" "$(echo "$result" | grep -o '"count":0')" '"count":0'
|
||||
|
||||
# json::error_envelope
|
||||
local err_result
|
||||
err_result=$(json::error_envelope "inspect" "Peer not found")
|
||||
cmd::test::assert "error envelope ok false" \
|
||||
"$(echo "$err_result" | grep -o '"ok":false')" '"ok":false'
|
||||
cmd::test::assert "error envelope error field" \
|
||||
"$(echo "$err_result" | grep -o '"error":')" '"error":'
|
||||
|
||||
# command::json mixin accessor
|
||||
_COMMAND_JSON=true
|
||||
cmd::test::assert_true "command::json true" "command::json"
|
||||
_COMMAND_JSON=false
|
||||
cmd::test::assert_false "command::json false" "command::json"
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ function command::run() {
|
|||
|
||||
local fn
|
||||
fn=$(command::fn "$cmd" run)
|
||||
core::call_function "$fn" "${args[@]}"
|
||||
core::call_function "$fn" ${args[@]+"${args[@]}"}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -85,9 +85,12 @@ function command::_preprocess_flags() {
|
|||
local -n _args_ref="$1"
|
||||
local -a _filtered=()
|
||||
|
||||
for _arg in "${_args_ref[@]:-}"; do
|
||||
if [[ ${#_args_ref[@]} -eq 0 ]]; then
|
||||
return 0 # nothing to process
|
||||
fi
|
||||
|
||||
for _arg in "${_args_ref[@]}"; do
|
||||
local _consumed=false
|
||||
local _mixin
|
||||
for _mixin in "${_ACTIVE_MIXINS[@]:-}"; do
|
||||
local _process_fn="command::mixin::${_mixin}::process"
|
||||
if declare -f "$_process_fn" >/dev/null 2>&1; then
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue