function cmd::config::run() { local subcmd="${1:-show}" # If first arg is a flag, treat as 'show' subcommand if [[ "$subcmd" == --* ]]; then subcmd="show" else shift || true fi case "$subcmd" in show) cmd::config::_show "$@" ;; migrate) cmd::config::migrate "$@" ;; help) cmd::config::help ;; *) log::error "Unknown subcommand: '${subcmd}'" cmd::config::help return 1 ;; esac } # ============================================ # Show # ============================================ function cmd::config::_show() { local name="" type="" while [[ $# -gt 0 ]]; do case "$1" in --name) name="$2"; shift 2 ;; --type) type="$2"; shift 2 ;; --help) cmd::config::help; return ;; *) log::error "Unknown flag: $1"; return 1 ;; esac done [[ -z "$name" ]] && log::error "Missing required flag: --name" && return 1 name=$(peers::resolve_and_require "$name" "$type") || return 1 local conf conf="$(ctx::clients)/${name}.conf" log::section "Client Config: ${name}" cat "$conf" } # ============================================ # Migrate # ============================================ function cmd::config::migrate() { local force=false dry_run=false while [[ $# -gt 0 ]]; do case "$1" in --force) force=true; shift ;; --dry-run) dry_run=true; shift ;; --help) cmd::config::help; return ;; *) log::error "Unknown flag: $1"; return 1 ;; esac done local wgctl_dir wgctl_dir="$(ctx::wgctl)" local config_dir="${wgctl_dir}/config" local data_dir="${wgctl_dir}/data" local legacy_conf="${wgctl_dir}/wgctl.conf" local json_conf="${config_dir}/wgctl.json" # Check if already migrated if [[ -f "$json_conf" && ! -f "$legacy_conf" ]]; then log::wg_warning "Already migrated to new config structure" return 0 fi log::section "wgctl Config Migration" printf "\n" printf " This will:\n" printf " 1. Create %s/config/ and %s/data/\n" "$wgctl_dir" "$wgctl_dir" printf " 2. Convert wgctl.conf → wgctl.json\n" printf " 3. Move data files to data/\n\n" if ! $force && ! $dry_run; then read -r -p " Proceed? [y/N] " confirm case "$confirm" in [yY]*) ;; *) log::info "Aborted"; return 0 ;; esac fi local do="" $dry_run && do="echo [dry-run]" # 1. Create directories $dry_run || mkdir -p "$config_dir" "$data_dir" $dry_run && printf " Would create: %s/config/\n" "$wgctl_dir" $dry_run && printf " Would create: %s/data/\n" "$wgctl_dir" # 2. Convert wgctl.conf → wgctl.json if [[ -f "$legacy_conf" ]]; then if ! $dry_run; then config::_convert_to_json "$legacy_conf" "$json_conf" fi printf " %s wgctl.conf → config/wgctl.json\n" "$($dry_run && echo '[dry-run]' || echo '✓')" else log::wg_warning "No wgctl.conf found — creating default wgctl.json" $dry_run || config::_write_default_json "$json_conf" fi # 3. Move data files local -a data_files=( "hosts.json" "services.json" "subnets.json" "policies.json" ) local -a data_dirs=( "rules" "identities" "groups" "blocks" "meta" "peer-history" ) for f in "${data_files[@]}"; do if [[ -f "${wgctl_dir}/${f}" ]]; then $dry_run || mv "${wgctl_dir}/${f}" "${data_dir}/${f}" printf " %s %s → data/%s\n" \ "$($dry_run && echo '[dry-run]' || echo '✓')" "$f" "$f" fi done for d in "${data_dirs[@]}"; do if [[ -d "${wgctl_dir}/${d}" ]]; then $dry_run || mv "${wgctl_dir}/${d}" "${data_dir}/${d}" printf " %s %s/ → data/%s/\n" \ "$($dry_run && echo '[dry-run]' || echo '✓')" "$d" "$d" fi done # 4. Remove legacy conf after successful migration if ! $dry_run && [[ -f "$legacy_conf" ]]; then mv "$legacy_conf" "${legacy_conf}.bak" printf " ✓ wgctl.conf → wgctl.conf.bak (backup)\n" fi printf "\n" $dry_run && log::wg_warning "Dry run — no changes made" \ || log::wg_success "Migration complete" }