@@ -278,13 +278,50 @@ proxy_group_type() {
278278 proxy_groups_json | " $( yq_bin) " -p=json eval " .proxies.\" $group \" .type // \"\" " - 2> /dev/null
279279}
280280
281- proxy_group_is_selector () {
281+ proxy_group_type_key () {
282282 local type
283283
284- type=" $( proxy_group_type " $1 " ) "
284+ type=" $( proxy_group_type " $1 " 2> /dev/null || true) "
285+ printf ' %s' " ${type:- } " | tr ' [:upper:]' ' [:lower:]' | tr -d ' [:space:]_-'
286+ }
287+
288+ proxy_group_type_label () {
289+ local group=" $1 "
290+ local type_key raw_type
291+
292+ type_key=" $( proxy_group_type_key " $group " ) "
293+
294+ case " $type_key " in
295+ selector)
296+ echo " select"
297+ ;;
298+ urltest)
299+ echo " 自动选择 / url-test"
300+ ;;
301+ fallback)
302+ echo " 故障转移 / fallback"
303+ ;;
304+ loadbalance)
305+ echo " 负载均衡 / load-balance"
306+ ;;
307+ * )
308+ raw_type=" $( proxy_group_type " $group " 2> /dev/null || true) "
309+ if [ -n " ${raw_type:- } " ] && [ " $raw_type " != " null" ]; then
310+ echo " $raw_type "
311+ else
312+ echo " unknown"
313+ fi
314+ ;;
315+ esac
316+ }
317+
318+ proxy_group_can_show_candidates () {
319+ local type_key
320+
321+ type_key=" $( proxy_group_type_key " $1 " ) "
285322
286- case " $type " in
287- Selector|URLTest|Fallback|LoadBalance )
323+ case " $type_key " in
324+ selector|urltest|fallback|loadbalance )
288325 return 0
289326 ;;
290327 * )
@@ -293,22 +330,25 @@ proxy_group_is_selector() {
293330 esac
294331}
295332
333+ proxy_group_is_selector () {
334+ proxy_group_can_show_candidates " $1 "
335+ }
336+
296337proxy_group_is_manual_selector () {
297338 proxy_group_supports_manual_pick " $1 "
298339}
299340
300341proxy_group_is_auto_managed () {
301342 local group=" $1 "
302- local type normalized_type
343+ local type_key
303344
304345 [ -n " ${group:- } " ] || return 0
305346 proxy_group_exists " $group " || return 0
306347
307- type=" $( proxy_group_type " $group " 2> /dev/null || true) "
308- normalized_type=" $( printf ' %s' " ${type:- } " | tr ' [:upper:]' ' [:lower:]' ) "
348+ type_key=" $( proxy_group_type_key " $group " ) "
309349
310- case " $normalized_type " in
311- urltest|url-test| fallback|loadbalance|load-balance )
350+ case " $type_key " in
351+ urltest|fallback|loadbalance)
312352 return 0
313353 ;;
314354 esac
@@ -389,14 +429,54 @@ proxy_group_selectable_nodes() {
389429 done < <( proxy_group_nodes " $group " )
390430}
391431
392- proxy_group_supports_manual_pick () {
432+ proxy_group_has_selectable_candidates () {
393433 local group=" $1 "
394434 local node
435+
436+ [ -n " ${group:- } " ] || return 1
437+ proxy_group_exists " $group " || return 1
438+ proxy_group_can_show_candidates " $group " || return 1
439+
440+ while IFS= read -r node; do
441+ [ -n " ${node:- } " ] || continue
442+ return 0
443+ done < <( proxy_group_selectable_nodes " $group " )
444+
445+ return 1
446+ }
447+
448+ proxy_group_manual_pick_error_message () {
449+ local group=" $1 "
450+ local type_key type_label
451+
452+ [ -n " ${group:- } " ] || {
453+ echo " 该策略组不支持手动切换"
454+ return 0
455+ }
456+
457+ type_key=" $( proxy_group_type_key " $group " ) "
458+ type_label=" $( proxy_group_type_label " $group " ) "
459+
460+ case " $type_key " in
461+ urltest|fallback|loadbalance)
462+ echo " 该策略组为${type_label} 类型,不支持手动切换:$group "
463+ ;;
464+ * )
465+ echo " 该策略组不支持手动切换:$group "
466+ ;;
467+ esac
468+ }
469+
470+ proxy_group_supports_manual_pick () {
471+ local group=" $1 "
395472 local has_now=" "
473+ local type_key
396474
397475 [ -n " ${group:- } " ] || return 1
398476 proxy_group_exists " $group " || return 1
399- proxy_group_is_auto_managed " $group " && return 1
477+
478+ type_key=" $( proxy_group_type_key " $group " ) "
479+ [ " $type_key " = " selector" ] || return 1
400480
401481 has_now=" $(
402482 proxy_groups_json \
@@ -405,12 +485,17 @@ proxy_group_supports_manual_pick() {
405485 ) "
406486 [ " ${has_now:- false} " = " true" ] || return 1
407487
408- while IFS= read -r node; do
409- [ -n " ${node:- } " ] || continue
410- return 0
411- done < <( proxy_group_selectable_nodes " $group " )
488+ proxy_group_has_selectable_candidates " $group "
489+ }
412490
413- return 1
491+ proxy_group_display_list () {
492+ local group
493+
494+ while IFS= read -r group; do
495+ [ -n " ${group:- } " ] || continue
496+ proxy_group_has_selectable_candidates " $group " || continue
497+ echo " $group "
498+ done < <( proxy_group_list)
414499}
415500
416501proxy_group_manual_list () {
@@ -472,6 +557,55 @@ proxy_group_select() {
472557 rm -f " $response_file " 2> /dev/null || true
473558}
474559
560+ proxy_group_select () {
561+ local group=" $1 "
562+ local node=" $2 "
563+ local base secret
564+ local code response_file response_body
565+ local available_node found
566+
567+ [ -n " ${group:- } " ] || die " 策略组名称不能为空"
568+ [ -n " ${node:- } " ] || die " 节点名称不能为空"
569+
570+ proxy_group_exists " $group " || die " 策略组不存在:$group "
571+ proxy_group_supports_manual_pick " $group " || die " $( proxy_group_manual_pick_error_message " $group " ) "
572+
573+ found=false
574+ while IFS= read -r available_node; do
575+ [ -n " ${available_node:- } " ] || continue
576+ if [ " $available_node " = " $node " ]; then
577+ found=true
578+ break
579+ fi
580+ done < <( proxy_group_selectable_nodes " $group " )
581+
582+ if [ " $found " != " true" ]; then
583+ die " 节点不存在于策略组中:$group -> $node "
584+ fi
585+
586+ base=" $( controller_api_base) "
587+ secret=" $( controller_secret) "
588+ response_file=" $( mktemp) "
589+ code=" $(
590+ curl -sS -o " $response_file " -w " %{http_code}" -X PUT \
591+ -H " Content-Type: application/json" \
592+ ${secret: +-H " Authorization: Bearer $secret " } \
593+ --data " {\" name\" :\" $node \" }" \
594+ " $base /proxies/$group "
595+ ) "
596+
597+ if [ " ${code:- 000} " -lt 200 ] || [ " ${code:- 000} " -ge 300 ]; then
598+ response_body=" $( cat " $response_file " 2> /dev/null || true) "
599+ rm -f " $response_file " 2> /dev/null || true
600+ if [ -n " ${response_body:- } " ]; then
601+ die " 节点切换失败:$response_body "
602+ fi
603+ die " 节点切换失败:controller 返回 HTTP $code "
604+ fi
605+
606+ rm -f " $response_file " 2> /dev/null || true
607+ }
608+
475609proxy_group_count () {
476610 proxy_group_list 2> /dev/null | awk ' NF{c++} END{print c+0}'
477611}
0 commit comments