Skip to content

Commit

Permalink
Add Hetzner Cloud driver
Browse files Browse the repository at this point in the history
Closes #1791.
  • Loading branch information
decentral1se committed Apr 24, 2019
1 parent 8a55c0a commit 1a429ae
Show file tree
Hide file tree
Showing 27 changed files with 1,034 additions and 0 deletions.
8 changes: 8 additions & 0 deletions doc/source/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ GCE
.. autoclass:: molecule.driver.gce.GCE()
:undoc-members:

.. _hetzner-cloud-driver:

Hetzner Cloud
^^^^^^^^^^^^^

.. autoclass:: molecule.driver.hetznercloud.HetznerCloud()
:undoc-members:

.. _linode-driver:

Linode
Expand Down
4 changes: 4 additions & 0 deletions molecule/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from molecule.driver import linode
from molecule.driver import lxc
from molecule.driver import lxd
from molecule.driver import hetznercloud
from molecule.driver import openstack
from molecule.driver import vagrant
from molecule.lint import yamllint
Expand Down Expand Up @@ -169,6 +170,8 @@ def driver(self):
driver = ec2.EC2(self)
elif driver_name == 'gce':
driver = gce.GCE(self)
elif driver_name == 'hetznercloud':
driver = hetznercloud.HetznerCloud(self)
elif driver_name == 'linode':
driver = linode.Linode(self)
elif driver_name == 'lxc':
Expand Down Expand Up @@ -501,6 +504,7 @@ def molecule_drivers():
docker.Docker(None).name,
ec2.EC2(None).name,
gce.GCE(None).name,
hetznercloud.HetznerCloud(None).name,
linode.Linode(None).name,
lxc.LXC(None).name,
lxd.LXD(None).name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ platforms:
zone: us-west1-a
machine_type: f1-micro
image: debian-8
{%- elif cookiecutter.driver_name == 'hetznercloud' %}
- name: instance
server_type: cx11
ssh_keys:
- me@myorganisation
image: debian-9
{%- elif cookiecutter.driver_name == 'lxc' %}
- name: instance
{%- elif cookiecutter.driver_name == 'linode' %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"molecule_directory": "molecule",
"role_name": "OVERRIDEN",
"scenario_name": "OVERRIDEN"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
***************************************
Hetzner Cloud driver installation guide
***************************************

Requirements
============

* Ansible 2.8+
* ``HCLOUD_TOKEN`` exposed in your environment

Install
=======

Please refer to the `Virtual environment`_ documentation for installation best
practices. If not using a virtual environment, please consider passing the
widely recommended `'--user' flag`_ when invoking ``pip``.

.. _Virtual environment: https://virtualenv.pypa.io/en/latest/
.. _'--user' flag: https://packaging.python.org/tutorials/installing-packages/#installing-to-the-user-site

.. code-block:: bash
$ pip install 'molecule[hetznercloud]'
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
{% raw -%}
- name: Create
hosts: localhost
connection: local
gather_facts: false
no_log: "{{ not (lookup('env', 'MOLECULE_DEBUG') | bool or molecule_yml.provisioner.log|default(false) | bool) }}"
vars:
ssh_port: 22
ssh_user: root
tasks:
- name: Create molecule instance(s)
hcloud_server:
name: "{{ item.name }}"
server_type: "{{ item.server_type }}"
ssh_keys: "{{ item.ssh_keys }}"
volumes: "{{ item.volumes | default(omit) }}"
image: "{{ item.image }}"
location: "{{ item.location | default(omit) }}"
datacenter: "{{ item.datacenter | default(omit) }}"
user_data: "{{ item.user_data | default(omit) }}"
api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}"
state: present
register: server
with_items: "{{ molecule_yml.platforms }}"
async: 7200
poll: 0

- name: Wait for instance(s) creation to complete
async_status:
jid: "{{ item.ansible_job_id }}"
register: hetzner_jobs
until: hetzner_jobs.finished
retries: 300
with_items: "{{ server.results }}"

# Mandatory configuration for Molecule to function.

- name: Populate instance config dict
set_fact:
instance_conf_dict: {
'instance': "{{ item.hcloud_server.name }}",
'user': "{{ ssh_user }}",
'port': "{{ ssh_port }}",
'address': "{{ item.hcloud_server.ipv4_address }}", }
with_items: "{{ hetzner_jobs.results }}"
register: instance_config_dict
when: server.changed | bool

- name: Convert instance config dict to a list
set_fact:
instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
when: server.changed | bool

- name: Dump instance config
copy:
content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
dest: "{{ molecule_instance_config }}"
when: server.changed | bool

- name: Wait for SSH
wait_for:
port: "{{ ssh_port }}"
host: "{{ item.address }}"
search_regex: SSH
delay: 10
with_items: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}"
{%- endraw %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
{% raw -%}
- name: Destroy
hosts: localhost
connection: local
gather_facts: false
no_log: "{{ not (lookup('env', 'MOLECULE_DEBUG') | bool or molecule_yml.provisioner.log|default(false) | bool) }}"
tasks:
- block:
- name: Populate instance config
set_fact:
instance_conf: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}"
skip_instances: false
rescue:
- name: Populate instance config when file missing
set_fact:
instance_conf: {}
skip_instances: true

- name: Destroy molecule instance(s)
hcloud_server:
name: "{{ item.instance }}"
api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}"
state: absent
register: server
with_items: "{{ instance_conf }}"
when: not skip_instances
async: 7200
poll: 0

- name: Wait for instance(s) deletion to complete
async_status:
jid: "{{ item.ansible_job_id }}"
register: hetzner_jobs
until: hetzner_jobs.finished
retries: 300
with_items: "{{ server.results }}"

# Mandatory configuration for Molecule to function.

- name: Populate instance config
set_fact:
instance_conf: {}

- name: Dump instance config
copy:
content: "{{ instance_conf | molecule_to_yaml | molecule_header }}"
dest: "{{ molecule_instance_config }}"
when: server.changed | bool
{%- endraw %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
- name: Converge
hosts: all
roles:
- role: {{ cookiecutter.role_name }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
{% raw -%}
- name: Prepare
hosts: all
gather_facts: false
tasks:
- name: Install python for Ansible
raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal python-zipstream)
become: true
changed_when: false
{%- endraw %}
Loading

0 comments on commit 1a429ae

Please sign in to comment.