homelab infrastructure services
at main 266 lines 8.6 kB view raw
1#!/bin/bash 2# UID and port calculation functions for tinsnip SMEP scheme 3 4# Source core functions 5LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 6source "$LIB_DIR/core.sh" 7source "$LIB_DIR/registry.sh" 8 9# Parse machine environment name into service and environment components 10# Handles service names with hyphens (e.g., bsky-pds-dev → service=bsky-pds, env=dev) 11# Outputs two lines: service name, then environment name 12parse_machine_name() { 13 local machine_name="$1" 14 15 # Known environments (must match calculate_machine_uid) 16 local environments="prod|test|dev|staging|demo|qa|uat|preview|canary|local" 17 18 # Match the last occurrence of -<environment> 19 if [[ "$machine_name" =~ ^(.+)-(${environments})$ ]]; then 20 echo "${BASH_REMATCH[1]}" # service name 21 echo "${BASH_REMATCH[2]}" # environment 22 return 0 23 else 24 return 1 25 fi 26} 27 28# Get sheet number from registry 29get_sheet_number() { 30 local sheet="${1:-${TIN_SHEET:-topsheet}}" 31 32 # Reserve sheet 5 for the tinsnip topsheet 33 if [[ "$sheet" == "topsheet" ]]; then 34 echo "5" 35 return 36 fi 37 38 # Look up sheet in registry 39 local registry_path=$(get_sheet_registry_path) 40 if [[ -f "$registry_path" ]]; then 41 local number=$(grep "^${sheet}=" "$registry_path" | cut -d= -f2) 42 if [[ -n "$number" ]]; then 43 echo "$number" 44 return 45 fi 46 fi 47 48 # Sheet not in registry - error 49 error_with_prefix "Sheet" "Sheet '$sheet' not registered" 50 error_with_prefix "Sheet" "Register with: tin sheet add $sheet <number>" 51 return 1 52} 53 54# Get sheet name from UID (reverse lookup) 55get_sheet_from_uid() { 56 local uid="$1" 57 58 # Extract sheet number from UID (first digit of 5-digit UID) 59 local sheet_num="${uid:0:1}" 60 61 # Special case for topsheet (sheet number 5) 62 if [[ "$sheet_num" == "5" ]]; then 63 echo "topsheet" 64 return 0 65 fi 66 67 # Look up sheet name in registry 68 local registry_path=$(get_sheet_registry_path) 69 if [[ -f "$registry_path" ]]; then 70 local sheet_name=$(grep "=${sheet_num}$" "$registry_path" | cut -d= -f1) 71 if [[ -n "$sheet_name" ]]; then 72 echo "$sheet_name" 73 return 0 74 fi 75 fi 76 77 # Sheet not found - default to topsheet as fallback 78 warn_with_prefix "UID" "Could not find sheet for UID $uid (sheet number $sheet_num)" 79 echo "topsheet" 80 return 1 81} 82 83# Get path to global sheet registry 84get_sheet_registry_path() { 85 echo "/mnt/station-prod/data/sheets" 86} 87 88# Find the next available sheet number from the registry (1-4 range, 5 reserved) 89find_next_sheet_number() { 90 local registry_path=$(get_sheet_registry_path) 91 92 if [[ ! -f "$registry_path" ]]; then 93 echo "1" # First available if no registry 94 return 95 fi 96 97 # Find highest assigned number 98 local max_num=0 99 while IFS='=' read -r sheet_name sheet_num; do 100 # Skip comments and empty lines 101 [[ "$sheet_name" =~ ^#.*$ ]] || [[ -z "$sheet_name" ]] && continue 102 103 # Skip topsheet (reserved at 5) 104 [[ "$sheet_name" == "topsheet" ]] && continue 105 106 # Convert to integer and track max (handle invalid numbers) 107 if [[ "$sheet_num" =~ ^[0-9]+$ ]]; then 108 local num_int=$((10#$sheet_num)) 109 if [[ "$num_int" -gt "$max_num" && "$num_int" -le 4 ]]; then 110 max_num="$num_int" 111 fi 112 fi 113 done < "$registry_path" 114 115 # Return next available number (max + 1), capped at 4 116 local next_num=$((max_num + 1)) 117 if [[ "$next_num" -gt 4 ]]; then 118 echo "ERROR: Sheet registry full (range 1-4, 5 reserved)" >&2 119 return 1 120 fi 121 122 echo "$next_num" 123} 124 125# Find the next available machine number from a registry file (now supports 2-digit format) 126find_next_machine_number() { 127 local registry_path="$1" 128 129 if [[ ! -f "$registry_path" ]]; then 130 echo "1" # Will be formatted as "01" by caller 131 return 132 fi 133 134 # Extract all machine numbers from registry, find the highest 135 local max_num=0 136 while IFS='=' read -r machine_name machine_num; do 137 # Skip comments and empty lines 138 [[ "$machine_name" =~ ^#.*$ ]] || [[ -z "$machine_name" ]] && continue 139 140 # Convert machine_num to integer (handles both "1" and "01" formats) 141 local num_int 142 if [[ -n "$machine_num" ]] && num_int=$((10#$machine_num)) 2>/dev/null; then 143 : # Success 144 else 145 continue 146 fi 147 if [[ "$num_int" -gt "$max_num" ]]; then 148 max_num="$num_int" 149 fi 150 done < "$registry_path" 151 152 # Return next available number (max + 1), capped at 99 153 local next_num=$((max_num + 1)) 154 155 if [[ "$next_num" -gt 99 ]]; then 156 return 1 157 fi 158 159 echo "$next_num" 160} 161 162# Calculate machine UID using SMEP convention 163# S=sheet number, M=machine (2-digit), E=environment, P=port index 164calculate_machine_uid() { 165 local machine_name="$1" 166 local machine_env="$2" 167 local port_index="${3:-0}" # Optional port index, defaults to 0 168 169 # Get sheet from environment or file 170 local sheet="${TIN_SHEET:-}" 171 if [[ -z "$sheet" ]] && [[ -f "/etc/tinsnip-sheet" ]]; then 172 sheet=$(cat /etc/tinsnip-sheet) 173 fi 174 sheet="${sheet:-${TIN_SHEET:-topsheet}}" 175 176 # Get sheet number (1-9) 177 local sheet_num=$(get_sheet_number "$sheet") 178 179 # Machine number mapping (now 2-digit) 180 local machine_num 181 182 # Special case for station (sheet infrastructure) 183 if [[ "$machine_name" == "station" ]]; then 184 machine_num=0 185 else 186 # Try to read from sheet-specific machine registry 187 local registry_path="/mnt/station-prod/data/machines/$sheet/registry" 188 if [[ -f "$registry_path" ]]; then 189 machine_num=$(grep "^${machine_name}=" "$registry_path" | head -1 | cut -d= -f2) 190 if [[ -n "$machine_num" ]]; then 191 # Convert to decimal to avoid octal interpretation issues 192 machine_num=$((10#$machine_num)) 193 else 194 # Machine not in registry - auto-assign next available number 195 local next_num=$(find_next_machine_number "$registry_path") 196 machine_num=$next_num 197 warn_with_prefix "UID Calculation" "Machine '$machine_name' not in registry, auto-assigning machine number $machine_num" 198 199 # Auto-register the machine 200 if register_machine "$machine_name" "$(printf "%02d" "$machine_num")" "$sheet" 2>/dev/null; then 201 log_with_prefix "UID Calculation" "Auto-registered $machine_name=$machine_num in sheet '$sheet'" 202 fi 203 fi 204 else 205 # Registry doesn't exist - sheet not registered 206 error_with_prefix "UID Calculation" "Machine registry not found: $registry_path" 207 error_with_prefix "UID Calculation" "Register sheet first: tin sheet create $sheet" 208 return 1 209 fi 210 fi 211 212 # Environment number mapping (expanded to 0-9) 213 local env_num 214 case "$machine_env" in 215 prod) env_num=0 ;; 216 test) env_num=1 ;; 217 dev) env_num=2 ;; 218 staging) env_num=3 ;; 219 demo) env_num=4 ;; 220 qa) env_num=5 ;; 221 uat) env_num=6 ;; 222 preview) env_num=7 ;; 223 canary) env_num=8 ;; 224 local) env_num=9 ;; 225 *) 226 echo "ERROR: Unknown environment: $machine_env (supported: prod,test,dev,staging,demo,qa,uat,preview,canary,local)" >&2 227 return 1 228 ;; 229 esac 230 231 # Validate port index (0-9) 232 if [[ ! "$port_index" =~ ^[0-9]$ ]]; then 233 echo "ERROR: Port index must be 0-9, got: $port_index" >&2 234 return 1 235 fi 236 237 # Return SMEP UID: S-M-E-P format 238 printf "%d%02d%d%d\n" "$sheet_num" "$machine_num" "$env_num" "$port_index" 239} 240 241# Calculate machine ports based on UID 242calculate_machine_ports() { 243 local machine_uid="$1" 244 local port_count="${2:-3}" 245 246 local base_port=$machine_uid 247 for ((i=0; i<port_count; i++)); do 248 echo $((base_port + i)) 249 done 250} 251 252# Backward compatibility wrappers (deprecated) 253calculate_service_uid() { 254 warn_with_prefix "Deprecated" "calculate_service_uid() is deprecated, use calculate_machine_uid()" 255 calculate_machine_uid "$@" 256} 257 258find_next_service_number() { 259 warn_with_prefix "Deprecated" "find_next_service_number() is deprecated, use find_next_machine_number()" 260 find_next_machine_number "$@" 261} 262 263calculate_service_ports() { 264 warn_with_prefix "Deprecated" "calculate_service_ports() is deprecated, use calculate_machine_ports()" 265 calculate_machine_ports "$@" 266}