mirror of
https://github.com/trailofbits/algo.git
synced 2026-08-17 21:25:50 +02:00
* feat: add destroy subcommand to tear down deployed servers Add `./algo destroy <server-ip>` to programmatically remove cloud resources and clean up local configs. Reads provider and server name from configs/<ip>/.config.yml, gathers credentials via existing prompts.yml, confirms with user, then dispatches to provider-specific destroy tasks. Supports all 11 cloud providers: - DigitalOcean, EC2, Lightsail (CloudFormation), Azure (resource group), GCE (instance + subsidiary resources), Hetzner, Vultr, Scaleway, OpenStack, CloudStack, Linode - Local provider: config cleanup only Also stores algo_region in .config.yml during deployment so destroy can auto-detect region. Fixes Scaleway module to allow state=absent without image/commercial_type/organization params. Adds Vultr to region-required providers and stores algo_region in Vultr prompts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add list-servers script and tests Add scripts/list_servers.py to scan configs/ for deployed server metadata and output JSON. Referenced by `./algo list-servers`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
145 lines
4.8 KiB
YAML
145 lines
4.8 KiB
YAML
---
|
|
- name: Destroy an Algo VPN server
|
|
hosts: localhost
|
|
gather_facts: false
|
|
become: false
|
|
vars_files:
|
|
- config.cfg
|
|
|
|
tasks:
|
|
- block:
|
|
- name: Validate server_ip is provided
|
|
assert:
|
|
that: server_ip is defined and server_ip | length > 0
|
|
fail_msg: |
|
|
server_ip is required. Usage:
|
|
./algo destroy <server-ip>
|
|
ansible-playbook destroy.yml -e "server_ip=YOUR_SERVER_IP"
|
|
|
|
- name: Check that server config exists
|
|
stat:
|
|
path: "configs/{{ server_ip }}/.config.yml"
|
|
register: _server_config
|
|
|
|
- name: Fail if server config not found
|
|
fail:
|
|
msg: |
|
|
No config found at configs/{{ server_ip }}/.config.yml
|
|
|
|
This server may not have been deployed by Algo, or
|
|
its configs were already removed.
|
|
|
|
Known servers:
|
|
ls configs/*/
|
|
when: not _server_config.stat.exists
|
|
|
|
- name: Load server configuration
|
|
include_vars:
|
|
file: "configs/{{ server_ip }}/.config.yml"
|
|
name: _server_cfg
|
|
|
|
- name: Set provider and server name from config
|
|
set_fact:
|
|
algo_provider: "{{ _server_cfg.algo_provider }}"
|
|
algo_server_name: "{{ _server_cfg.algo_server_name }}"
|
|
|
|
- name: Validate required config values
|
|
assert:
|
|
that:
|
|
- algo_provider is defined and algo_provider | length > 0
|
|
- algo_server_name is defined and algo_server_name | length > 0
|
|
fail_msg: |
|
|
Server config is missing algo_provider or algo_server_name.
|
|
Check configs/{{ server_ip }}/.config.yml
|
|
|
|
- name: Install cloud provider dependencies
|
|
shell: "uv pip install '.[{{ _provider_extras[algo_provider] | default(algo_provider) }}]'"
|
|
vars:
|
|
_provider_extras:
|
|
ec2: aws
|
|
lightsail: aws
|
|
azure: azure
|
|
gce: gcp
|
|
hetzner: hetzner
|
|
linode: linode
|
|
openstack: openstack
|
|
cloudstack: cloudstack
|
|
when: algo_provider != "local"
|
|
changed_when: false
|
|
|
|
- name: Set region from stored config
|
|
set_fact:
|
|
region: "{{ _server_cfg.algo_region }}"
|
|
when:
|
|
- region is not defined
|
|
- _server_cfg.algo_region is defined
|
|
- _server_cfg.algo_region | length > 0
|
|
|
|
- name: Validate region for providers that require it
|
|
fail:
|
|
msg: |
|
|
Region is required to destroy {{ algo_provider }} servers.
|
|
Pass it with: -e "region=YOUR_REGION"
|
|
|
|
Example:
|
|
./algo destroy {{ server_ip }} -e "region=us-east-1"
|
|
when:
|
|
- algo_provider in ['ec2', 'lightsail', 'gce', 'scaleway', 'vultr']
|
|
- region is not defined
|
|
|
|
- name: Set dummy region for providers that do not need it
|
|
set_fact:
|
|
region: "unused"
|
|
when:
|
|
- region is not defined
|
|
- algo_provider not in ['ec2', 'lightsail', 'gce', 'scaleway', 'vultr']
|
|
|
|
- name: Gather provider credentials
|
|
include_tasks: "roles/cloud-{{ algo_provider }}/tasks/prompts.yml"
|
|
when: algo_provider != "local"
|
|
|
|
- name: Display destroy plan
|
|
debug:
|
|
msg:
|
|
- "Server IP: {{ server_ip }}"
|
|
- "Server name: {{ algo_server_name }}"
|
|
- "Provider: {{ algo_provider }}"
|
|
|
|
- name: Confirm destruction
|
|
pause:
|
|
prompt: |
|
|
This will permanently destroy the server and remove local configs.
|
|
Type 'yes' to confirm
|
|
register: _confirm_destroy
|
|
when: confirm_destroy is not defined or not confirm_destroy | bool
|
|
|
|
- name: Abort if not confirmed
|
|
fail:
|
|
msg: "Destroy aborted by user."
|
|
when:
|
|
- confirm_destroy is not defined or not confirm_destroy | bool
|
|
- _confirm_destroy.user_input | default('') | lower != 'yes'
|
|
|
|
- name: Destroy cloud resources
|
|
include_tasks: "roles/cloud-{{ algo_provider }}/tasks/destroy.yml"
|
|
when: algo_provider != "local"
|
|
|
|
- name: Remove local config directory
|
|
file:
|
|
path: "configs/{{ server_ip }}"
|
|
state: absent
|
|
|
|
- name: Remove localhost symlink
|
|
file:
|
|
path: configs/localhost
|
|
state: absent
|
|
when: server_ip == "localhost"
|
|
|
|
- name: Destroy complete
|
|
debug:
|
|
msg:
|
|
- "Server {{ algo_server_name }} ({{ server_ip }}) destroyed."
|
|
- "Local configs removed from configs/{{ server_ip }}/"
|
|
rescue:
|
|
- include_tasks: playbooks/rescue.yml
|