#!/usr/bin/env bash function group::exists() { local name="$1" [[ -f "$(ctx::group::path "${name}.group")" ]] } function group::require_exists() { local name="$1" if ! group::exists "$name"; then log::error "Group not found: ${name}" return 1 fi } function group::path() { local name="$1" ctx::group::path "${name}.group" } function group::peers() { local name="$1" json::get "$(group::path "$name")" "peers" } function group::add_peer() { local name="$1" peer="$2" json::append "$(group::path "$name")" "peers" "$peer" } function group::remove_peer() { local name="$1" peer="$2" json::remove "$(group::path "$name")" "peers" "$peer" } function group::all() { local dir dir="$(ctx::groups)" for f in "${dir}"/*.group; do [[ -f "$f" ]] || continue basename "$f" .group done } function group::peer_groups() { local peer_name="$1" # Returns all groups that contain this peer while IFS= read -r group_name; do if group::peers "$group_name" | grep -qF "$peer_name"; then echo "$group_name" fi done < <(group::all) } function group::remove_peer_from_all() { local peer_name="${1:?peer_name required}" while IFS= read -r group_name; do group::remove_peer "$group_name" "$peer_name" done < <(json::peer_groups "$(ctx::groups)" "$peer_name") } function group::each_peer() { local name="${1:?name required}" local callback="${2:?callback required}" shift 2 # $@ = extra args passed to callback local peers_list=() mapfile -t peers_list < <(group::peers "$name") local filtered=() for p in "${peers_list[@]:-}"; do [[ -n "$p" ]] && filtered+=("$p") done [[ ${#filtered[@]} -eq 0 ]] && return 0 for peer_name in "${filtered[@]}"; do "$callback" "$peer_name" "$@" done } function group::_peer_exists_check() { local peer_name="${1:-}" peers::require_exists "$peer_name" > /dev/null 2>&1 }