Commit graph

7 commits

Author SHA1 Message Date
A
79e3b887c9
refactor: extract ensure_multi_credentials to reduce duplication across 5 providers (#468)
Add a generic ensure_multi_credentials() helper to shared/common.sh that
handles the env-var/config-file/prompt/test/save flow for providers needing
multiple credentials. This eliminates ~270 lines of duplicated logic across
contabo, netcup, ramnode, ionos, and upcloud, replacing it with single
function calls.

Each provider's ensure_*_credentials() function is now 3-8 lines instead
of 30-65 lines.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 07:48:32 -08:00
A
88a5e9e844
refactor: extract shared config load/save helpers to reduce credential management complexity (#434)
Add _load_json_config_fields and _save_json_config to shared/common.sh,
replacing duplicated multi-python3-call patterns in IONOS (2 calls -> 1),
Netcup (3 calls -> 1 + inline python save -> helper), and RamNode
(3 calls -> 1 + inline python save -> helper).

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 04:25:22 -08:00
A
4452f69144
refactor: extract helpers from create_server in binarylane, ramnode, upcloud (#430)
Extract response-handling and body-building helpers from the longest
create_server functions to improve readability and reduce per-function
complexity:

- binarylane: 69 -> 31 lines (extract _binarylane_build_server_body,
  _binarylane_handle_create_response)
- ramnode: 57 -> 40 lines (extract _ramnode_handle_create_response)
- upcloud: 56 -> 39 lines (extract _upcloud_handle_create_response)

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 04:06:32 -08:00
A
fdc5d5e58b
refactor: extract shared SSH helpers to eliminate ~410 lines of duplication (#429)
Add ssh_run_server, ssh_upload_file, ssh_interactive_session, and
ssh_verify_connectivity to shared/common.sh. These four functions
were copy-pasted identically across 21 cloud provider lib files,
differing only in SSH username (root vs ubuntu).

Providers now set SSH_USER and delegate to the shared helpers via
one-line wrappers, reducing each provider's lib by ~20 lines.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 03:45:18 -08:00
A
de19996360
refactor: extract helpers from create_server() in 4 cloud providers (#423)
Extract wait-for-IP polling loops and JSON body builders from the
largest create_server() functions (ramnode 105->59, netcup 95->50,
cherry 80->57, binarylane 92->70 lines), following the pattern
already established in ionos/lib/common.sh.

Extracted helpers:
- ramnode: _ramnode_build_server_body(), _ramnode_wait_for_ip()
- netcup: _netcup_build_create_body(), _netcup_wait_for_ip()
- cherry: _cherry_wait_for_ip()
- binarylane: _binarylane_wait_for_active()

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 02:59:31 -08:00
A
246b72a22b
fix: Prevent Python/JSON injection in RamNode and Netcup providers (#420)
Use sys.argv and sys.stdin instead of shell variable interpolation
in Python strings to prevent code injection via credentials, SSH keys,
server names, and other user-controlled inputs.

RamNode fixes:
- _get_ramnode_token: credentials via sys.argv instead of string interpolation
- Config file read: use sys.argv[1] for file path (matches other providers)
- Config file save: use sys.argv for all values
- ramnode_check_ssh_key: key_name via sys.argv
- ramnode_register_ssh_key: public key via stdin, name via sys.argv
- create_server: all parameters via sys.argv

Netcup fixes:
- netcup_get_session: use python3+json.dumps instead of unquoted heredoc
- netcup_api: use python3+json.dumps for action parameter
- Config file read: use sys.argv[1] for file path
- Config file save: use python3+sys.argv instead of unquoted heredoc
- create_server: all parameters via sys.argv

Agent: security-auditor

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 02:36:03 -08:00
A
1576577ed8
feat: Add RamNode cloud provider with OpenStack API support (#408)
Add RamNode budget VPS cloud provider ($0.006/hr) with full OpenStack API integration.

Implementation:
- ramnode/lib/common.sh: OpenStack Keystone v3 auth + Compute API wrapper
- ramnode/claude.sh, ramnode/aider.sh, ramnode/goose.sh: 3 agent scripts
- manifest.json: Added ramnode cloud entry + 15 matrix entries (3 implemented)
- ramnode/README.md: Complete documentation
- test/record.sh: Live cycle testing for RamNode (_live_ramnode function)
- test/mock.sh: URL stripping for Identity/Compute/Network APIs

Technical details:
- Auth: RAMNODE_USERNAME + RAMNODE_PASSWORD + RAMNODE_PROJECT_ID
- APIs: Identity (5000/v3), Compute (8774/v2.1), Network (9696/v2.0)
- Token-based authentication (X-Auth-Token header)
- Server provisioning with cloud-init via base64-encoded userdata
- SSH key management via OpenStack keypairs API

Agent: cloud-scout-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-11 01:36:02 -08:00