#!/usr/bin/env bash # commands/config/helpers.sh function cmd::config::_migrate_impl() { local force="$1" dry_run="$2" 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" 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" != "true" && "$dry_run" != "true" ]]; then read -r -p " Proceed? [y/N] " confirm case "$confirm" in [yY]*) ;; *) log::info "Aborted"; return 0 ;; esac fi $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" if [[ -f "$legacy_conf" ]]; then $dry_run || config::_convert_to_json "$legacy_conf" "$json_conf" 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 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 if [[ "$dry_run" != "true" && -f "$legacy_conf" ]]; then mv "$legacy_conf" "${legacy_conf}.bak" printf " ✓ wgctl.conf → wgctl.conf.bak (backup)\n" fi printf "\n" [[ "$dry_run" == "true" ]] \ && log::wg_warning "Dry run — no changes made" \ || log::wg_success "Migration complete" } # ── Helpers ─────────────────────────────────────────────────────────────────── function config::_convert_to_json() { local legacy_file="$1" output_file="$2" # Read legacy conf into variables local wg_interface="wg0" wg_endpoint="" wg_dns="10.0.0.103" local wg_dns_fallback="" wg_port="51820" wg_subnet="10.1.0.0/16" local wg_lan="10.0.0.0/24" wg_hs_check="300" date_format="eu" while IFS='=' read -r key value || [[ -n "$key" ]]; do [[ "$key" =~ ^[[:space:]]*# ]] && continue [[ -z "${key// }" ]] && continue key="${key// /}" value="${value// /}" case "$key" in WG_INTERFACE) wg_interface="$value" ;; WG_ENDPOINT) wg_endpoint="$value" ;; WG_DNS) wg_dns="$value" ;; WG_DNS_FALLBACK) wg_dns_fallback="$value" ;; WG_PORT) wg_port="$value" ;; WG_SUBNET) wg_subnet="$value" ;; WG_LAN) wg_lan="$value" ;; WG_HANDSHAKE_CHECK_TIME_SEC) wg_hs_check="$value" ;; DATE_FORMAT) date_format="$value" ;; esac done < "$legacy_file" # Build fallback DNS array local dns_fallback_json="[]" if [[ -n "$wg_dns_fallback" ]]; then local fallback_array fallback_array=$(echo "$wg_dns_fallback" | tr ',' '\n' | \ while IFS= read -r s; do s="${s// /}" [[ -n "$s" ]] && printf '"%s",' "$s" done | sed 's/,$//') dns_fallback_json="[${fallback_array}]" fi mkdir -p "$(dirname "$output_file")" cat > "$output_file" << JSON { "wireguard": { "interface": "${wg_interface}", "endpoint": "${wg_endpoint}", "port": ${wg_port}, "subnet": "${wg_subnet}", "lan": "${wg_lan}" }, "dns": { "primary": "${wg_dns}", "fallback": ${dns_fallback_json} }, "handshake": { "check_interval_sec": ${wg_hs_check} }, "activity": { "total": {"low": 1000000, "medium": 10000000, "high": 100000000}, "current": {"low": 1000000, "medium": 10000000, "high": 100000000} }, "display": { "date_format": "${date_format}" } } JSON } function config::_write_default_json() { local output_file="$1" mkdir -p "$(dirname "$output_file")" cat > "$output_file" << 'JSON' { "wireguard": { "interface": "wg0", "endpoint": "", "port": 51820, "subnet": "10.1.0.0/16", "lan": "10.0.0.0/24" }, "dns": { "primary": "10.0.0.103", "fallback": [] }, "handshake": { "check_interval_sec": 300 }, "activity": { "total": {"low": 1000000, "medium": 10000000, "high": 100000000}, "current": {"low": 1000000, "medium": 10000000, "high": 100000000} }, "display": { "date_format": "eu" } } JSON }