diff --git a/config.cfg b/config.cfg index 6b5358b..8331d81 100644 --- a/config.cfg +++ b/config.cfg @@ -154,9 +154,12 @@ cloud_providers: size: nano_1_0 image: ubuntu_18_04 scaleway: - size: START1-S + size: DEV1-S image: Ubuntu Bionic Beaver arch: x86_64 + hetzner: + server_type: cx11 + image: ubuntu-18.04 openstack: flavor_ram: ">=512" image: Ubuntu-18.04 diff --git a/docs/cloud-hetzner.md b/docs/cloud-hetzner.md new file mode 100644 index 0000000..f0cb28b --- /dev/null +++ b/docs/cloud-hetzner.md @@ -0,0 +1,3 @@ +## API Token + +Sign in into the [Hetzner Cloud Console](https://console.hetzner.cloud/) choose a project, go to `Access` → `Tokens`, and create a new token. Make sure to copy the token because it won’t be shown to you again. A token is bound to a project, to interact with the API of another project you have to create a new token inside the project. diff --git a/input.yml b/input.yml index cf0e9eb..0a56680 100644 --- a/input.yml +++ b/input.yml @@ -14,9 +14,10 @@ - { name: DigitalOcean, alias: digitalocean } - { name: Amazon Lightsail, alias: lightsail } - { name: Amazon EC2, alias: ec2 } - - { name: Vultr, alias: vultr } - { name: Microsoft Azure, alias: azure } - { name: Google Compute Engine, alias: gce } + - { name: Hetzner Cloud, alias: hetzner } + - { name: Vultr, alias: vultr } - { name: Scaleway, alias: scaleway} - { name: OpenStack (DreamCompute optimised), alias: openstack } - { name: CloudStack (Exoscale optimised), alias: cloudstack } diff --git a/roles/cloud-hetzner/defaults/main.yml b/roles/cloud-hetzner/defaults/main.yml new file mode 100644 index 0000000..12ad96d --- /dev/null +++ b/roles/cloud-hetzner/defaults/main.yml @@ -0,0 +1,2 @@ +--- +hetzner_venv: "{{ playbook_dir }}/configs/.venvs/hetzner" diff --git a/roles/cloud-hetzner/tasks/main.yml b/roles/cloud-hetzner/tasks/main.yml new file mode 100644 index 0000000..0aa02c3 --- /dev/null +++ b/roles/cloud-hetzner/tasks/main.yml @@ -0,0 +1,32 @@ +--- +- name: Build python virtual environment + import_tasks: venv.yml + +- block: + - name: Include prompts + import_tasks: prompts.yml + + - name: Create an ssh key + hcloud_ssh_key: + name: "algo-{{ 999999 | random(seed=lookup('file', SSH_keys.public)) }}" + public_key: "{{ lookup('file', SSH_keys.public) }}" + state: present + register: hcloud_ssh_key + + - name: Create a server... + hcloud_server: + name: "{{ algo_server_name }}" + location: "{{ algo_hcloud_region }}" + server_type: "{{ cloud_providers.hetzner.server_type }}" + image: "{{ cloud_providers.hetzner.image }}" + state: present + ssh_keys: "{{ hcloud_ssh_key.hcloud_ssh_key.name }}" + labels: + Environment: algo + register: hcloud_server + + - set_fact: + cloud_instance_ip: "{{ hcloud_server.hcloud_server.ipv4_address }}" + ansible_ssh_user: root + environment: + PYTHONPATH: "{{ hetzner_venv }}/lib/python2.7/site-packages/" diff --git a/roles/cloud-hetzner/tasks/prompts.yml b/roles/cloud-hetzner/tasks/prompts.yml new file mode 100644 index 0000000..be42abd --- /dev/null +++ b/roles/cloud-hetzner/tasks/prompts.yml @@ -0,0 +1,48 @@ +--- +- pause: + prompt: | + Enter your API token (https://trailofbits.github.io/algo/cloud-hetzner.html#api-token): + echo: false + register: _hcloud_token + when: + - hcloud_token is undefined + - lookup('env','HCLOUD_TOKEN')|length <= 0 + +- name: Set the token as a fact + set_fact: + algo_hcloud_token: "{{ hcloud_token | default(_hcloud_token.user_input|default(None)) | default(lookup('env','HCLOUD_TOKEN'), true) }}" + +- name: Get regions + hcloud_datacenter_facts: + api_token: "{{ algo_hcloud_token }}" + register: _hcloud_regions + +- name: Set facts about thre regions + set_fact: + hcloud_regions: "{{ hcloud_datacenter_facts | sort(attribute='location') }}" + +- name: Set default region + set_fact: + default_region: >- + {% for r in hcloud_regions %} + {%- if r['location'] == "nbg1" %}{{ loop.index }}{% endif %} + {%- endfor %} + +- pause: + prompt: | + What region should the server be located in? + {% for r in hcloud_regions %} + {{ loop.index }}. {{ r['location'] }} {{ r['description'] }} + {% endfor %} + + Enter the number of your desired region + [{{ default_region }}] + register: _algo_region + when: region is undefined + +- name: Set additional facts + set_fact: + algo_hcloud_region: >- + {% if region is defined %}{{ region }} + {%- elif _algo_region.user_input %}{{ hcloud_regions[_algo_region.user_input | int -1 ]['location'] }} + {%- else %}{{ hcloud_regions[default_region | int - 1]['location'] }}{% endif %} diff --git a/roles/cloud-hetzner/tasks/venv.yml b/roles/cloud-hetzner/tasks/venv.yml new file mode 100644 index 0000000..80bb69b --- /dev/null +++ b/roles/cloud-hetzner/tasks/venv.yml @@ -0,0 +1,14 @@ +--- +- name: Clean up the environment + file: + dest: "{{ hetzner_venv }}" + state: absent + when: clean_environment + +- name: Install requirements + pip: + name: + - hcloud + state: latest + virtualenv: "{{ hetzner_venv }}" + virtualenv_python: python2.7