Son aktivite 1 month ago

nuno bu gisti düzenledi 1 month ago. Düzenlemeye git

1 file changed, 288 insertions

gistfile1.txt(dosya oluşturuldu)

@@ -0,0 +1,288 @@
1 + #!/usr/bin/env bash
2 + # subnet.command.sh — manage the subnet map (subnets.json)
3 + #
4 + # Subcommands:
5 + # wgctl subnet list
6 + # wgctl subnet show --name <name>
7 + # wgctl subnet add --name <name> --subnet <cidr> [--type <type>]
8 + # [--tunnel-mode split|full] [--desc <desc>]
9 + # [--group <parent>]
10 + # wgctl subnet rm --name <name>
11 + # wgctl subnet rename --name <old> --new-name <new>
12 +
13 + # ============================================
14 + # Lifecycle
15 + # ============================================
16 +
17 + function cmd::subnet::on_load() {
18 + flag::register --name
19 + flag::register --subnet
20 + flag::register --type
21 + flag::register --tunnel-mode
22 + flag::register --desc
23 + flag::register --group
24 + flag::register --new-name
25 + }
26 +
27 + # ============================================
28 + # Help
29 + # ============================================
30 +
31 + function cmd::subnet::help() {
32 + cat <<EOF
33 + Usage: wgctl subnet <subcommand> [options]
34 +
35 + Manage the subnet map.
36 +
37 + Subcommands:
38 + list List all configured subnets
39 + show --name <name> Show details for a subnet
40 + add --name <name> Add a new subnet entry
41 + --subnet <cidr>
42 + [--type <type>]
43 + [--tunnel-mode split|full]
44 + [--desc <desc>]
45 + [--group <parent>]
46 + rm --name <name> Remove a subnet (refused if in use)
47 + rename --name <old> Rename a subnet (refused if in use)
48 + --new-name <new>
49 +
50 + Examples:
51 + wgctl subnet list
52 + wgctl subnet show --name guests
53 + wgctl subnet add --name iot-cctv --subnet 10.1.211.0/24 --type iot
54 + wgctl subnet add --name desktop --subnet 10.1.101.0/24 --group guests
55 + wgctl subnet rm --name iot-cctv
56 + wgctl subnet rename --name iot-cctv --new-name cctv
57 + EOF
58 + }
59 +
60 + # ============================================
61 + # Run
62 + # ============================================
63 +
64 + function cmd::subnet::run() {
65 + local subcmd="${1:-list}"
66 + shift || true
67 +
68 + case "$subcmd" in
69 + list) cmd::subnet::_list "$@" ;;
70 + show) cmd::subnet::_show "$@" ;;
71 + add) cmd::subnet::_add "$@" ;;
72 + rm) cmd::subnet::_rm "$@" ;;
73 + rename) cmd::subnet::_rename "$@" ;;
74 + --help) cmd::subnet::help ;;
75 + *)
76 + log::error "Unknown subcommand '${subcmd}'. Available: list, show, add, rm, rename"
77 + return 1
78 + ;;
79 + esac
80 + }
81 +
82 + # ============================================
83 + # Subcommands
84 + # ============================================
85 +
86 + function cmd::subnet::_list() {
87 + local data
88 + data=$(subnet::list_data)
89 +
90 + if [[ -z "$data" ]]; then
91 + log::info "No subnets defined."
92 + return 0
93 + fi
94 +
95 + echo ""
96 + local prev_group=""
97 + while IFS='|' read -r display_name subnet type_key tunnel_mode desc is_group group_parent; do
98 + if [[ "$is_group" == "true" ]]; then
99 + # Print group parent header when we encounter first child
100 + if [[ "$group_parent" != "$prev_group" ]]; then
101 + [[ -n "$prev_group" ]] && ui::subnet::group_separator
102 + ui::subnet::row_group_parent "$group_parent"
103 + prev_group="$group_parent"
104 + fi
105 + ui::subnet::row_group_child "$type_key" "$subnet" "$tunnel_mode"
106 + else
107 + # Scalar entry
108 + [[ -n "$prev_group" ]] && ui::subnet::group_separator
109 + prev_group=""
110 + ui::subnet::row_scalar "$display_name" "$subnet" "$tunnel_mode"
111 + fi
112 + done <<< "$data"
113 + echo ""
114 + }
115 +
116 + function cmd::subnet::_maybe_group_separator() {
117 + local is_group="${1:-}" group_parent="${2:-}" prev_group="${3:-}"
118 + if [[ "$is_group" == "true" && "$group_parent" != "$prev_group" && -n "$prev_group" ]]; then
119 + ui::subnet::group_separator
120 + elif [[ "$is_group" == "false" && -n "$prev_group" ]]; then
121 + ui::subnet::group_separator
122 + fi
123 + }
124 +
125 + function cmd::subnet::_update_prev_group() {
126 + local is_group="${1:-}" group_parent="${2:-}" prev_group="${3:-}"
127 + if [[ "$is_group" == "true" ]]; then
128 + echo "$group_parent"
129 + else
130 + echo ""
131 + fi
132 + }
133 +
134 + function cmd::subnet::_show() {
135 + local name=""
136 + while [[ $# -gt 0 ]]; do
137 + case "$1" in
138 + --name) name="$2"; shift 2 ;;
139 + --help) cmd::subnet::help; return ;;
140 + *) log::error "Unknown flag: $1"; return 1 ;;
141 + esac
142 + done
143 +
144 + [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
145 + subnet::require_exists "$name" || return 1
146 +
147 + local data
148 + data=$(subnet::show_data "$name")
149 +
150 + local is_group="false"
151 + while IFS='|' read -r key val rest; do
152 + case "$key" in
153 + name)
154 + ui::subnet::detail "$val" "$is_group"
155 + ;;
156 + is_group)
157 + is_group="$val"
158 + # Only print type once
159 + if [[ "$val" == "true" ]]; then
160 + ui::subnet::detail_field "Type" "group"
161 + ui::subnet::child_header
162 + else
163 + ui::subnet::detail_field "Type" "scalar"
164 + fi
165 + ;;
166 + subnet) ui::subnet::detail_field "Subnet" "$val" ;;
167 + type) ui::subnet::detail_field "Device type" "$val" ;;
168 + tunnel_mode) ui::subnet::detail_field "Tunnel" "$val" ;;
169 + desc) ui::subnet::detail_field "Description" "$val" ;;
170 + child)
171 + local c_type="$val"
172 + local c_subnet c_tunnel c_desc
173 + c_subnet=$(echo "$rest" | cut -d'|' -f1)
174 + c_tunnel=$(echo "$rest" | cut -d'|' -f2)
175 + c_desc=$(echo "$rest" | cut -d'|' -f3)
176 + ui::subnet::child_row "$c_type" "$c_subnet" "$c_tunnel" "$c_desc"
177 + ;;
178 + esac
179 + done <<< "$data"
180 +
181 + local peers_using
182 + peers_using=$(subnet::peers_using "$name")
183 + ui::subnet::peers_in_use "$peers_using"
184 + }
185 +
186 + function cmd::subnet::_add() {
187 + local name="" cidr="" type_key="" tunnel_mode="split" desc="" group_parent=""
188 +
189 + while [[ $# -gt 0 ]]; do
190 + case "$1" in
191 + --name) name="$2"; shift 2 ;;
192 + --subnet) cidr="$2"; shift 2 ;;
193 + --type) type_key="$2"; shift 2 ;;
194 + --tunnel-mode) tunnel_mode="$2"; shift 2 ;;
195 + --desc) desc="$2"; shift 2 ;;
196 + --group) group_parent="$2"; shift 2 ;;
197 + --help) cmd::subnet::help; return ;;
198 + *) log::error "Unknown flag: $1"; return 1 ;;
199 + esac
200 + done
201 +
202 + [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
203 + [[ -z "$cidr" ]] && { log::error "Missing required flag: --subnet"; return 1; }
204 +
205 + cmd::subnet::_validate_tunnel_mode "$tunnel_mode" || return 1
206 + cmd::subnet::_validate_cidr "$cidr" || return 1
207 +
208 + json::subnet_add "$(ctx::subnets)" "$name" "$cidr" \
209 + "${type_key:-$name}" "$tunnel_mode" "$desc" "$group_parent"
210 +
211 + log::ok "Subnet '${name}' added (${cidr})"
212 + }
213 +
214 + function cmd::subnet::_rm() {
215 + local name=""
216 + while [[ $# -gt 0 ]]; do
217 + case "$1" in
218 + --name) name="$2"; shift 2 ;;
219 + --help) cmd::subnet::help; return ;;
220 + *) log::error "Unknown flag: $1"; return 1 ;;
221 + esac
222 + done
223 +
224 + [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
225 + subnet::require_exists "$name" || return 1
226 +
227 + local peers_using
228 + peers_using=$(subnet::peers_using "$name")
229 +
230 + if [[ -n "$peers_using" ]]; then
231 + log::error "Cannot remove subnet '${name}' — in use by: ${peers_using//,/, }"
232 + log::error "Migrate or remove those peers first."
233 + return 1
234 + fi
235 +
236 + json::subnet_remove "$(ctx::subnets)" "$name" ""
237 + log::ok "Subnet '${name}' removed"
238 + }
239 +
240 + function cmd::subnet::_rename() {
241 + local name="" new_name=""
242 + while [[ $# -gt 0 ]]; do
243 + case "$1" in
244 + --name) name="$2"; shift 2 ;;
245 + --new-name) new_name="$2"; shift 2 ;;
246 + --help) cmd::subnet::help; return ;;
247 + *) log::error "Unknown flag: $1"; return 1 ;;
248 + esac
249 + done
250 +
251 + [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; }
252 + [[ -z "$new_name" ]] && { log::error "Missing required flag: --new-name"; return 1; }
253 + subnet::require_exists "$name" || return 1
254 +
255 + local peers_using
256 + peers_using=$(subnet::peers_using "$name")
257 + if [[ -n "$peers_using" ]]; then
258 + log::error "Cannot rename subnet '${name}' — configs already distributed to: ${peers_using//,/, }"
259 + log::error "Client configs reference the subnet CIDR which cannot change after distribution."
260 + return 1
261 + fi
262 +
263 + json::subnet_rename "$(ctx::subnets)" "$name" "$new_name" ""
264 + log::ok "Subnet '${name}' renamed to '${new_name}'"
265 + }
266 +
267 + # ============================================
268 + # Validation Helpers
269 + # ============================================
270 +
271 + function cmd::subnet::_validate_tunnel_mode() {
272 + local mode="${1:-}"
273 + case "$mode" in
274 + split|full) return 0 ;;
275 + *)
276 + log::error "Invalid --tunnel-mode '${mode}'. Use: split, full"
277 + return 1
278 + ;;
279 + esac
280 + }
281 +
282 + function cmd::subnet::_validate_cidr() {
283 + local cidr="${1:-}"
284 + if ! echo "$cidr" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$'; then
285 + log::error "Invalid CIDR format: '${cidr}'"
286 + return 1
287 + fi
288 + }
Daha yeni Daha eski