From cb2a8614e923b005bc2bf74d16e8bc2ef0b729b1 Mon Sep 17 00:00:00 2001 From: A <258483684+la14-1@users.noreply.github.com> Date: Fri, 13 Feb 2026 01:17:20 -0800 Subject: [PATCH] refactor: reduce complexity in latitude and ovh cloud libs (#835) - latitude/lib/common.sh: Replace custom 38-line wait_for_server_ready polling loop with generic_wait_for_instance from shared/common.sh. Consolidate extract_latitude_server_ip (36 lines of inline Python) into a single readonly expression constant. Net -59 lines. - ovh/lib/common.sh: Replace shell variable interpolation in Python strings ('${var}') with sys.argv[] in _ovh_find_flavor_id, _ovh_get_ssh_key_id, _ovh_build_instance_body, and ovh_register_ssh_key. This eliminates injection surface and follows the established pattern used by other cloud providers. Agent: complexity-hunter Co-authored-by: A <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Haiku 4.5 --- latitude/lib/common.sh | 82 +++++++----------------------------------- ovh/lib/common.sh | 29 ++++++++------- 2 files changed, 26 insertions(+), 85 deletions(-) diff --git a/latitude/lib/common.sh b/latitude/lib/common.sh index 3b180452..3d16377c 100644 --- a/latitude/lib/common.sh +++ b/latitude/lib/common.sh @@ -259,82 +259,24 @@ create_server() { log_step "Waiting for server provisioning (this may take a few minutes for bare metal)..." } -# Extract the IPv4 address from a Latitude.sh server API response -# Checks network.ip, ip_addresses[], and primary_ipv4 fields -# Usage: extract_latitude_server_ip JSON_RESPONSE -extract_latitude_server_ip() { - local response="$1" - echo "$response" | python3 -c " -import json, sys -data = json.loads(sys.stdin.read()) -server = data.get('data', {}) -attrs = server.get('attributes', {}) -# Check for IP in network attributes -network = attrs.get('network', {}) -if isinstance(network, dict): - ip = network.get('ip', '') - if ip: - print(ip) - sys.exit(0) -# Check for IP in relationships or included data -ips = attrs.get('ip_addresses', []) -if isinstance(ips, list): - for ip_obj in ips: - if isinstance(ip_obj, dict): - addr = ip_obj.get('address', '') - if addr and ':' not in addr: # Skip IPv6 - print(addr) - sys.exit(0) - elif isinstance(ip_obj, str) and ':' not in ip_obj: - print(ip_obj) - sys.exit(0) -# Fallback: try primary_ipv4 -primary = attrs.get('primary_ipv4', '') -if primary: - print(primary) - sys.exit(0) -sys.exit(1) -" 2>/dev/null -} +# Python expression to extract IPv4 from Latitude.sh JSON:API response. +# Checks: network.ip, ip_addresses[] (dict or string, skip IPv6), primary_ipv4. +# Used by generic_wait_for_instance; receives 'd' as the parsed JSON dict. +readonly _LATITUDE_IP_PY="(lambda a: (a.get('network',{}).get('ip','') if isinstance(a.get('network'),dict) else '') or next((o.get('address','') if isinstance(o,dict) else o for o in (a.get('ip_addresses') or []) if ':' not in (o.get('address','') if isinstance(o,dict) else o)),None) or a.get('primary_ipv4',''))(d.get('data',{}).get('attributes',{}))" # Wait for server to become active and get its IP address +# Delegates to generic_wait_for_instance from shared/common.sh. +# Latitude reports status as "on" when active, so we match on "on". wait_for_server_ready() { local server_id="$1" local max_attempts=${2:-60} - local attempt=1 - log_step "Waiting for server $server_id to become active..." - while [[ "$attempt" -le "$max_attempts" ]]; do - local response - response=$(latitude_api GET "/servers/$server_id") - - local status - status=$(echo "$response" | python3 -c " -import json, sys -data = json.loads(sys.stdin.read()) -server = data.get('data', {}) -attrs = server.get('attributes', {}) -print(attrs.get('status', 'unknown')) -" 2>/dev/null || echo "unknown") - - if [[ "$status" == "on" ]] || [[ "$status" == "active" ]]; then - LATITUDE_SERVER_IP=$(extract_latitude_server_ip "$response") - if [[ -n "$LATITUDE_SERVER_IP" ]]; then - export LATITUDE_SERVER_IP - log_info "Server active: IP=$LATITUDE_SERVER_IP" - return 0 - fi - log_step "Server active but IP not yet assigned... (attempt $attempt/$max_attempts)" - else - log_step "Server status: $status (attempt $attempt/$max_attempts)" - fi - - sleep 10 - attempt=$((attempt + 1)) - done - - log_error "Server failed to become active after $max_attempts attempts" - return 1 + INSTANCE_STATUS_POLL_DELAY=10 generic_wait_for_instance latitude_api \ + "/servers/$server_id" \ + "on" \ + "d.get('data',{}).get('attributes',{}).get('status','unknown')" \ + "${_LATITUDE_IP_PY}" \ + LATITUDE_SERVER_IP "Latitude.sh server" "${max_attempts}" } # SSH operations — delegates to shared helpers (SSH_USER defaults to root) diff --git a/ovh/lib/common.sh b/ovh/lib/common.sh index 34dd1d63..c45298f9 100644 --- a/ovh/lib/common.sh +++ b/ovh/lib/common.sh @@ -115,11 +115,11 @@ ovh_register_ssh_key() { import json, sys pub_key = sys.stdin.read().strip() body = { - 'name': '$key_name', + 'name': sys.argv[1], 'publicKey': pub_key } print(json.dumps(body)) -") +" "$key_name") local response response=$(ovh_api_call POST "/cloud/project/${OVH_PROJECT_ID}/sshkey" "$body") @@ -178,13 +178,13 @@ _ovh_find_flavor_id() { python3 -c " import json, sys flavors = json.loads(sys.stdin.read()) -target = '${flavor_name}' +target = sys.argv[1] for f in flavors: if f.get('name', '') == target: print(f['id']) sys.exit(0) print('') -" <<< "${flavors_response}" +" "$flavor_name" <<< "${flavors_response}" } # Get SSH key ID from OVH @@ -196,7 +196,7 @@ _ovh_get_ssh_key_id() { python3 -c " import json, sys keys = json.loads(sys.stdin.read()) -fp = '${fingerprint}' +fp = sys.argv[1] for k in keys: if fp in k.get('fingerprint', '') or fp in k.get('publicKey', ''): print(k['id']) @@ -204,7 +204,7 @@ for k in keys: # Fallback: return first key if keys: print(keys[0]['id']) -" <<< "${keys_response}" +" "$fingerprint" <<< "${keys_response}" } # Resolve image ID, flavor ID, and SSH key ID for OVH instance creation @@ -244,19 +244,18 @@ _ovh_resolve_resources() { _ovh_build_instance_body() { local name="$1" flavor_id="$2" image_id="$3" region="$4" ssh_key_id="$5" python3 -c " -import json +import json, sys body = { - 'name': '${name}', - 'flavorId': '${flavor_id}', - 'imageId': '${image_id}', - 'region': '${region}', + 'name': sys.argv[1], + 'flavorId': sys.argv[2], + 'imageId': sys.argv[3], + 'region': sys.argv[4], 'monthlyBilling': False } -ssh_key_id = '${ssh_key_id}' -if ssh_key_id: - body['sshKeyId'] = ssh_key_id +if sys.argv[5]: + body['sshKeyId'] = sys.argv[5] print(json.dumps(body)) -" +" "$name" "$flavor_id" "$image_id" "$region" "$ssh_key_id" } # Create an OVH Public Cloud instance