Compare commits
No commits in common. "92993e64232a9d07594d639649e833ccecdbc70c" and "e54ce9c4177458905736fd9572947bb7532940db" have entirely different histories.
92993e6423
...
e54ce9c417
4 changed files with 131 additions and 325 deletions
|
|
@ -114,31 +114,40 @@ function cmd::group::list() {
|
|||
return 0
|
||||
fi
|
||||
|
||||
local data
|
||||
data=$(json::group_list_data "$groups_dir" "$(ctx::blocks)")
|
||||
[[ -z "$data" ]] && log::wg "No groups configured" && return 0
|
||||
|
||||
# Measure column widths
|
||||
local w_name=12 w_desc=16
|
||||
while IFS="|" read -r name desc total blocked; do
|
||||
[[ -z "$name" ]] && continue
|
||||
(( ${#name} > w_name )) && w_name=${#name}
|
||||
local desc_len=${#desc}
|
||||
[[ -z "$desc" ]] && desc_len=1
|
||||
(( desc_len > w_desc )) && w_desc=$desc_len
|
||||
done <<< "$data"
|
||||
(( w_name += 2 ))
|
||||
(( w_desc += 2 ))
|
||||
|
||||
log::section "Groups"
|
||||
echo ""
|
||||
printf "\n %-20s %-35s %-8s %s\n" "NAME" "DESCRIPTION" "PEERS" "STATUS"
|
||||
printf " %s\n" "$(printf '─%.0s' {1..75})"
|
||||
|
||||
while IFS="|" read -r name desc total blocked; do
|
||||
[[ -z "$name" ]] && continue
|
||||
ui::group::list_row "$name" "$desc" "$total" "$blocked" "$w_name" "$w_desc"
|
||||
done <<< "$data"
|
||||
|
||||
echo ""
|
||||
local status_color="" status_str="active"
|
||||
if [[ "$total" -gt 0 ]]; then
|
||||
if [[ "$blocked" -eq "$total" ]]; then
|
||||
status_color="\033[1;31m"
|
||||
status_str="blocked"
|
||||
elif [[ "$blocked" -gt 0 ]]; then
|
||||
status_color="\033[1;33m"
|
||||
status_str="blocked (${blocked}/${total})"
|
||||
else
|
||||
status_color="\033[1;32m"
|
||||
status_str="active"
|
||||
fi
|
||||
fi
|
||||
|
||||
local short_desc="${desc:0:33}"
|
||||
[[ ${#desc} -gt 33 ]] && short_desc="${short_desc}..."
|
||||
|
||||
local desc_col_width=35
|
||||
[[ "$desc" == "—" || -z "$desc" ]] && desc_col_width=37
|
||||
|
||||
printf " %-20s %-${desc_col_width}s %-8s %b\n" \
|
||||
"$name" "${short_desc:-—}" "$total" \
|
||||
"${status_color}${status_str}\033[0m"
|
||||
|
||||
done < <(json::group_list_data "$groups_dir" "$(ctx::blocks)")
|
||||
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
# ============================================
|
||||
|
|
@ -163,64 +172,62 @@ function cmd::group::show() {
|
|||
group_file="$(group::path "$name")"
|
||||
|
||||
log::section "Group: ${name}"
|
||||
printf "\n"
|
||||
|
||||
local desc
|
||||
desc=$(json::get "$group_file" "desc")
|
||||
ui::row "Description" "${desc:-—}"
|
||||
printf "\n %-20s %s\n" "Description:" "${desc:-—}"
|
||||
|
||||
# Load peers
|
||||
local peers_list=()
|
||||
mapfile -t peers_list < <(json::get "$group_file" "peers") || true
|
||||
mapfile -t peers_list < <(json::get "$group_file" "peers")
|
||||
# Filter empty entries
|
||||
local filtered=()
|
||||
for p in "${peers_list[@]:-}"; do
|
||||
[[ -n "$p" ]] && filtered+=("$p")
|
||||
done
|
||||
peers_list=("${filtered[@]:-}")
|
||||
local peer_count=${#peers_list[@]}
|
||||
[[ -z "${peers_list[0]:-}" ]] && peer_count=0
|
||||
|
||||
local peer_word="peers"
|
||||
[[ "$peer_count" -eq 1 ]] && peer_word="peer"
|
||||
local valid_count=0
|
||||
for p in "${peers_list[@]}"; do
|
||||
[[ -z "$p" ]] && continue
|
||||
peers::require_exists "$p" > /dev/null 2>&1 && (( valid_count++ )) || true
|
||||
done
|
||||
local peer_word="peers"
|
||||
[[ "$valid_count" -eq 1 ]] && peer_word="peer"
|
||||
ui::row "Peers" "${valid_count} ${peer_word}"
|
||||
printf "\n"
|
||||
[[ -z "${peers_list[0]}" ]] && peer_count=0
|
||||
|
||||
printf " %-20s %s\n" "Peers:" "$peer_count"
|
||||
printf " %s\n" "$(printf '─%.0s' {1..50})"
|
||||
|
||||
if [[ "$peer_count" -gt 0 ]]; then
|
||||
# Measure name and IP widths
|
||||
local w_name=16 w_ip=13
|
||||
for peer_name in "${peers_list[@]}"; do
|
||||
[[ -z "$peer_name" ]] && continue
|
||||
(( ${#peer_name} > w_name )) && w_name=${#peer_name}
|
||||
done
|
||||
(( w_name += 2 ))
|
||||
|
||||
printf "\n %-28s %-15s %-12s %s\n" "NAME" "IP" "RULE" "STATUS"
|
||||
printf " %s\n" "$(printf '─%.0s' {1..65})"
|
||||
for peer_name in "${peers_list[@]}"; do
|
||||
[[ -z "$peer_name" ]] && continue
|
||||
|
||||
# Skip if peer no longer exists
|
||||
if ! peers::require_exists "$peer_name" > /dev/null 2>&1; then
|
||||
printf " \033[2m%-${w_name}s (no longer exists)\033[0m\n" "$peer_name"
|
||||
log::wg_warning "Peer '${peer_name}' no longer exists — skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
local ip rule is_blocked
|
||||
local ip rule status_str status_color
|
||||
ip=$(peers::get_ip "$peer_name")
|
||||
rule=$(peers::get_meta "$peer_name" "rule")
|
||||
peers::is_blocked "$peer_name" 2>/dev/null && is_blocked="true" || is_blocked="false"
|
||||
rule="${rule:-—}"
|
||||
|
||||
ui::group::show_member_row "$peer_name" "$ip" "${rule:--}" \
|
||||
"$is_blocked" "$w_name" "$w_ip"
|
||||
if peers::is_blocked "$peer_name" 2>/dev/null; then
|
||||
status_color="\033[1;31m"
|
||||
status_str="blocked"
|
||||
else
|
||||
status_color="\033[1;32m"
|
||||
status_str="active"
|
||||
fi
|
||||
|
||||
printf " %-28s %-15s %-12s %b\n" \
|
||||
"$peer_name" "0" "$rule" \
|
||||
"${status_str}\033[0m"
|
||||
done
|
||||
else
|
||||
printf " \033[2m—\033[0m\n"
|
||||
printf " —\n"
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ============================================
|
||||
|
|
|
|||
|
|
@ -95,63 +95,53 @@ function cmd::net::list() {
|
|||
return 0
|
||||
fi
|
||||
|
||||
# Collect filtered data and build ports display per service
|
||||
local filtered_data=""
|
||||
while IFS="|" read -r name ip desc tags port_count; do
|
||||
log::section "Network Services"
|
||||
printf "\n %-20s %-16s %-6s %s\n" "NAME" "IP" "PORTS" "DESCRIPTION"
|
||||
local divider
|
||||
divider=$(printf '─%.0s' {1..72})
|
||||
printf " %s\n" "$divider"
|
||||
|
||||
local found=false
|
||||
while IFS="|" read -r name ip desc tags ports; do
|
||||
[[ -z "$name" ]] && continue
|
||||
[[ -n "$filter_tag" && "$tags" != *"$filter_tag"* ]] && continue
|
||||
|
||||
# Build ports display from json::net_show
|
||||
local ports_display=""
|
||||
while IFS="|" read -r ptype pname pport pproto pdesc; do
|
||||
[[ "$ptype" != "port" ]] && continue
|
||||
local port_str=":${pport}"
|
||||
[[ -n "$pproto" && "$pproto" != "tcp" ]] && port_str="${port_str}/${pproto}"
|
||||
ports_display+="${port_str}, "
|
||||
done < <(json::net_show "$net_file" "$name")
|
||||
ports_display="${ports_display%, }"
|
||||
[[ -z "$ports_display" ]] && ports_display="-"
|
||||
# Tag filter
|
||||
if [[ -n "$filter_tag" ]]; then
|
||||
[[ "$tags" != *"$filter_tag"* ]] && continue
|
||||
fi
|
||||
|
||||
found=true
|
||||
local tag_display=""
|
||||
[[ -n "$tags" ]] && tag_display=" \033[0;37m[${tags}]\033[0m"
|
||||
|
||||
printf " %-20s %-16s %-6s %s%b\n" \
|
||||
"$name" "$ip" "${ports}p" "${desc:-—}" "$tag_display"
|
||||
|
||||
if $detailed; then
|
||||
local has_ports=false
|
||||
# Show ports inline
|
||||
while IFS="|" read -r ptype pname pport pproto pdesc; do
|
||||
[[ "$ptype" != "port" ]] && continue
|
||||
has_ports=true
|
||||
local ann
|
||||
ann=$(net::annotation "$ip" "$pport" "$pproto")
|
||||
printf " \033[0;37m%-18s %s:%s%s\033[0m\n" \
|
||||
"${pname}" "$pport" "$pproto" \
|
||||
"${pdesc:+ # $pdesc}"
|
||||
done < <(json::net_show "$net_file" "$name")
|
||||
$has_ports && printf "\n" # newline after each service with ports
|
||||
fi
|
||||
|
||||
filtered_data+="${name}|${ip}|${desc}|${tags}|${ports_display}"$'\n'
|
||||
done < <(json::net_list "$net_file")
|
||||
|
||||
[[ -z "$filtered_data" ]] && {
|
||||
if ! $found; then
|
||||
[[ -n "$filter_tag" ]] && \
|
||||
log::wg_warning "No services with tag: ${filter_tag}" || \
|
||||
log::wg_warning "No services configured"
|
||||
return 0
|
||||
}
|
||||
fi
|
||||
|
||||
# Measure column widths
|
||||
local w_name=12 w_ip=13 w_ports=16
|
||||
while IFS="|" read -r name ip desc tags ports; do
|
||||
[[ -z "$name" ]] && continue
|
||||
(( ${#name} > w_name )) && w_name=${#name}
|
||||
(( ${#ip} > w_ip )) && w_ip=${#ip}
|
||||
(( ${#ports} > w_ports )) && w_ports=${#ports}
|
||||
done <<< "$filtered_data"
|
||||
(( w_name += 2 ))
|
||||
(( w_ip += 2 ))
|
||||
(( w_ports += 2 ))
|
||||
|
||||
log::section "Network Services"
|
||||
echo ""
|
||||
|
||||
while IFS="|" read -r name ip desc tags ports; do
|
||||
[[ -z "$name" ]] && continue
|
||||
ui::net::list_row "$name" "$ip" "$desc" "$tags" "$ports" \
|
||||
"$w_name" "$w_ip" "$w_ports"
|
||||
|
||||
if $detailed; then
|
||||
while IFS="|" read -r ptype pname pport pproto pdesc; do
|
||||
[[ "$ptype" != "port" ]] && continue
|
||||
ui::net::show_port_row "$pname" "$pport" "$pproto" "$pdesc"
|
||||
done < <(json::net_show "$net_file" "$name")
|
||||
echo ""
|
||||
fi
|
||||
done <<< "$filtered_data"
|
||||
|
||||
echo ""
|
||||
printf "\n"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ============================================
|
||||
|
|
@ -175,24 +165,26 @@ function cmd::net::show() {
|
|||
log::section "Service: ${name}"
|
||||
printf "\n"
|
||||
|
||||
local has_ports=false
|
||||
while IFS="|" read -r key val1 val2 val3 val4; do
|
||||
case "$key" in
|
||||
name) ui::row "Name" "$val1" ;;
|
||||
ip) ui::row "IP" "$val1" ;;
|
||||
desc) ui::row "Description" "${val1:-—}" ;;
|
||||
tags) ui::row "Tags" "${val1:-—}" ;;
|
||||
ip) ui::row "IP" "$val1" ;;
|
||||
port)
|
||||
if ! $has_ports; then
|
||||
printf " %-20s\n" "Ports:"
|
||||
has_ports=true
|
||||
fi
|
||||
ui::net::show_port_row "$val1" "$val2" "$val3" "$val4"
|
||||
# val1=port_name val2=port val3=proto val4=desc
|
||||
local ann
|
||||
ann=$(net::annotation "$(json::net_resolve "$(ctx::net)" "$name")" \
|
||||
"$val2" "$val3" 2>/dev/null || true)
|
||||
printf " %-20s \033[0;36m%s\033[0m %s:%s%s\n" \
|
||||
"${val1}:" "" "$val2" "$val3" \
|
||||
"${val4:+ # $val4}"
|
||||
;;
|
||||
esac
|
||||
done < <(json::net_show "$(ctx::net)" "$name")
|
||||
|
||||
printf "\n"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ============================================
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# ui/group.module.sh — rendering for groups
|
||||
|
||||
# ======================================================
|
||||
# List rendering
|
||||
# ======================================================
|
||||
|
||||
# ui::group::list_row <name> <desc> <total> <blocked> <w_name> <w_desc>
|
||||
function ui::group::list_row() {
|
||||
local name="${1:-}" desc="${2:-}" total="${3:-0}" blocked="${4:-0}" \
|
||||
w_name="${5:-16}" w_desc="${6:-30}"
|
||||
|
||||
local name_pad desc_val desc_pad_n
|
||||
name_pad=$(printf "%-${w_name}s" "$name")
|
||||
desc_val="${desc:--}"
|
||||
desc_pad_n=$(( w_desc - ${#desc_val} ))
|
||||
[[ $desc_pad_n -lt 0 ]] && desc_pad_n=0
|
||||
|
||||
# Peer count — dim if zero
|
||||
local peers_word="peers"
|
||||
[[ "$total" -eq 1 ]] && peers_word="peer"
|
||||
local peers_display
|
||||
if [[ "$total" -eq 0 ]]; then
|
||||
peers_display="\033[2m0 ${peers_word}\033[0m"
|
||||
else
|
||||
peers_display="${total} ${peers_word}"
|
||||
fi
|
||||
local peers_pad
|
||||
peers_pad=$(printf "%-10s" "${total} ${peers_word}")
|
||||
|
||||
# Status
|
||||
local status_color status_str
|
||||
IFS='|' read -r status_color status_str <<< "$(ui::group::status "$total" "$blocked")"
|
||||
|
||||
local peers_str="${total} ${peers_word}"
|
||||
local peers_pad_n=$(( 10 - ${#peers_str} ))
|
||||
[[ $peers_pad_n -lt 0 ]] && peers_pad_n=0
|
||||
|
||||
if [[ "$total" -eq 0 ]]; then
|
||||
printf " \033[2m%s %s%*s %s%*s %s\033[0m\n" \
|
||||
"$name_pad" "$desc_val" "$desc_pad_n" "" \
|
||||
"$peers_str" "$peers_pad_n" "" "inactive"
|
||||
else
|
||||
printf " %s %s%*s %s%*s %b%s\033[0m\n" \
|
||||
"$name_pad" "$desc_val" "$desc_pad_n" "" \
|
||||
"$peers_str" "$peers_pad_n" "" \
|
||||
"$status_color" "$status_str"
|
||||
fi
|
||||
}
|
||||
|
||||
# Table version (kept for future display config)
|
||||
function ui::group::list_header_table() {
|
||||
printf "\n %-20s %-35s %-8s %s\n" "NAME" "DESCRIPTION" "PEERS" "STATUS"
|
||||
printf " %s\n" "$(printf '─%.0s' {1..75})"
|
||||
}
|
||||
|
||||
function ui::group::list_row_table() {
|
||||
local name="${1:-}" desc="${2:-}" total="${3:-0}" blocked="${4:-0}"
|
||||
local status_color="" status_str="active"
|
||||
if [[ "$total" -gt 0 ]]; then
|
||||
if [[ "$blocked" -eq "$total" ]]; then
|
||||
status_color="\033[1;31m"; status_str="blocked"
|
||||
elif [[ "$blocked" -gt 0 ]]; then
|
||||
status_color="\033[1;33m"; status_str="blocked (${blocked}/${total})"
|
||||
else
|
||||
status_color="\033[1;32m"; status_str="active"
|
||||
fi
|
||||
fi
|
||||
printf " %-20s %-35s %-8s %b\n" \
|
||||
"$name" "${desc:-—}" "$total" \
|
||||
"${status_color}${status_str}\033[0m"
|
||||
}
|
||||
|
||||
# ======================================================
|
||||
# Show rendering
|
||||
# ======================================================
|
||||
|
||||
# ui::group::show_member_row <name> <ip> <rule> <is_blocked> <w_name> <w_ip>
|
||||
function ui::group::show_member_row() {
|
||||
local name="${1:-}" ip="${2:-}" rule="${3:--}" is_blocked="${4:-false}" \
|
||||
w_name="${5:-22}" w_ip="${6:-14}"
|
||||
|
||||
local name_pad ip_pad rule_pad
|
||||
name_pad=$(printf "%-${w_name}s" "$name")
|
||||
ip_pad=$(printf "%-${w_ip}s" "$ip")
|
||||
rule_pad=$(printf "%-12s" "${rule:--}")
|
||||
|
||||
local status_color status_str
|
||||
if [[ "$is_blocked" == "true" ]]; then
|
||||
status_color="\033[1;31m"; status_str="blocked"
|
||||
else
|
||||
status_color="\033[1;32m"; status_str="active"
|
||||
fi
|
||||
|
||||
printf " %s %s \033[2mrule:\033[0m %s %b%s\033[0m\n" \
|
||||
"$name_pad" "$ip_pad" "$rule_pad" \
|
||||
"$status_color" "$status_str"
|
||||
}
|
||||
|
||||
# Table version
|
||||
function ui::group::show_header_table() {
|
||||
printf "\n %-28s %-15s %-12s %s\n" "NAME" "IP" "RULE" "STATUS"
|
||||
printf " %s\n" "$(printf '─%.0s' {1..65})"
|
||||
}
|
||||
|
||||
function ui::group::show_member_row_table() {
|
||||
local name="${1:-}" ip="${2:-}" rule="${3:--}" is_blocked="${4:-false}"
|
||||
local status_color status_str
|
||||
[[ "$is_blocked" == "true" ]] && { status_color="\033[1;31m"; status_str="blocked"; } \
|
||||
|| { status_color="\033[1;32m"; status_str="active"; }
|
||||
printf " %-28s %-15s %-12s %b\n" \
|
||||
"$name" "$ip" "${rule:--}" "${status_color}${status_str}\033[0m"
|
||||
}
|
||||
|
||||
|
||||
# ======================================================
|
||||
# Helpers
|
||||
# ======================================================
|
||||
|
||||
# ui::group::status_color <total> <blocked>
|
||||
# Returns color code and status string for a group
|
||||
# Usage: IFS='|' read -r color str <<< "$(ui::group::status "$total" "$blocked")"
|
||||
function ui::group::status() {
|
||||
local total="${1:-0}" blocked="${2:-0}"
|
||||
if [[ "$total" -eq 0 ]]; then
|
||||
echo "\033[2;37m|inactive"
|
||||
elif [[ "$blocked" -eq "$total" ]]; then
|
||||
echo "\033[1;31m|blocked"
|
||||
elif [[ "$blocked" -gt 0 ]]; then
|
||||
echo "\033[1;33m|partial (${blocked}/${total})"
|
||||
else
|
||||
echo "\033[1;32m|active"
|
||||
fi
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# ui/net.module.sh — rendering for network services
|
||||
|
||||
# ======================================================
|
||||
# List rendering
|
||||
# ======================================================
|
||||
|
||||
# ui::net::list_row <name> <ip> <desc> <tags> <ports_display> <w_name> <w_ip> <w_ports>
|
||||
function ui::net::list_row() {
|
||||
local name="${1:-}" ip="${2:-}" desc="${3:-}" tags="${4:-}" ports="${5:-}" \
|
||||
w_name="${6:-16}" w_ip="${7:-14}" w_ports="${8:-20}"
|
||||
|
||||
local name_pad ip_pad
|
||||
name_pad=$(printf "%-${w_name}s" "$name")
|
||||
ip_pad=$(printf "%-${w_ip}s" "$ip")
|
||||
|
||||
local ports_pad_n=$(( w_ports - ${#ports} ))
|
||||
[[ $ports_pad_n -lt 0 ]] && ports_pad_n=0
|
||||
|
||||
local tags_display=""
|
||||
[[ -n "$tags" ]] && tags_display=" \033[2m[${tags}]\033[0m"
|
||||
|
||||
printf " %s %s %s%*s %s%b\n" \
|
||||
"$name_pad" "$ip_pad" "$ports" "$ports_pad_n" "" \
|
||||
"${desc:--}" "$tags_display"
|
||||
}
|
||||
|
||||
# Table version (kept for future display config)
|
||||
function ui::net::list_header_table() {
|
||||
printf "\n %-20s %-16s %-6s %s\n" "NAME" "IP" "PORTS" "DESCRIPTION"
|
||||
printf " %s\n" "$(printf '─%.0s' {1..72})"
|
||||
}
|
||||
|
||||
function ui::net::list_row_table() {
|
||||
local name="${1:-}" ip="${2:-}" desc="${3:-}" tags="${4:-}" port_count="${5:-}"
|
||||
local tag_display=""
|
||||
[[ -n "$tags" ]] && tag_display=" \033[0;37m[${tags}]\033[0m"
|
||||
printf " %-20s %-16s %-6s %s%b\n" \
|
||||
"$name" "$ip" "${port_count}p" "${desc:-—}" "$tag_display"
|
||||
}
|
||||
|
||||
# ======================================================
|
||||
# Show rendering
|
||||
# ======================================================
|
||||
|
||||
# ui::net::show_port_row <port_name> <port> <proto> <desc>
|
||||
function ui::net::show_port_row() {
|
||||
local port_name="${1:-}" port="${2:-}" proto="${3:-}" desc="${4:-}"
|
||||
local port_display=":${port}/${proto}"
|
||||
local port_pad
|
||||
port_pad=$(printf "%-14s" "$port_display")
|
||||
if [[ -n "$desc" ]]; then
|
||||
printf " %s \033[2m→\033[0m %-16s \033[2m# %s\033[0m\n" \
|
||||
"$port_pad" "$port_name" "$desc"
|
||||
else
|
||||
printf " %s \033[2m→\033[0m %s\n" \
|
||||
"$port_pad" "$port_name"
|
||||
fi
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue