diff --git a/integration/molecule/default/molecule.yml b/integration/molecule/default/molecule.yml index 62700d3..4754c90 100644 --- a/integration/molecule/default/molecule.yml +++ b/integration/molecule/default/molecule.yml @@ -7,6 +7,10 @@ platforms: - name: "molecule-hetznercloud-${INSTANCE_UUID}" server_type: cx11 image: debian-10 + volumes: + name: "molecule-hetznercloud-volume-${INSTANCE_UUID}" + size: 11 + create: true provisioner: name: ansible verifier: diff --git a/molecule_hetznercloud/cookiecutter/scenario/driver/hetznercloud/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/create.yml b/molecule_hetznercloud/cookiecutter/scenario/driver/hetznercloud/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/create.yml index d964d5b..71034b8 100644 --- a/molecule_hetznercloud/cookiecutter/scenario/driver/hetznercloud/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/create.yml +++ b/molecule_hetznercloud/cookiecutter/scenario/driver/hetznercloud/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/create.yml @@ -33,7 +33,6 @@ server_type: "{{ item.server_type }}" ssh_keys: - "{{ ssh_key_name }}" - volumes: "{{ item.volumes | default(omit) }}" image: "{{ item.image }}" location: "{{ item.location | default(omit) }}" datacenter: "{{ item.datacenter | default(omit) }}" @@ -53,6 +52,31 @@ retries: 300 with_items: "{{ server.results }}" + - name: Create volume(s) + hcloud_volume: + name: "{{ item.volumes.name | default(item.name) }}" + server: "{{ item.name }}" + location: "{{ item.volumes.location | default(omit) }}" + size: "{{ item.volumes.size | default(10) }}" + api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}" + state: "present" + with_items: "{{ molecule_yml.platforms }}" + when: + - item.volumes is defined + - item.volumes.create | default(False) | bool + register: volumes + async: 7200 + poll: 0 + + - name: Wait for volume(s) creation to complete + async_status: + jid: "{{ item.ansible_job_id }}" + register: hetzner_volumes + until: hetzner_volumes.finished + retries: 300 + when: volumes.changed + with_items: "{{ volumes.results }}" + - name: Populate instance config dict set_fact: instance_conf_dict: { @@ -61,7 +85,8 @@ 'address': "{{ item.hcloud_server.ipv4_address }}", 'user': "{{ ssh_user }}", 'port': "{{ ssh_port }}", - 'identity_file': "{{ ssh_path }}", } + 'identity_file': "{{ ssh_path }}", + 'volumes': "{{ item.item.item.volumes | default({}) }}", } with_items: "{{ hetzner_jobs.results }}" register: instance_config_dict when: server.changed | bool @@ -73,7 +98,10 @@ - name: Dump instance config copy: - content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}" + content: | + # Molecule managed + + {{ instance_conf | to_json | from_json | to_yaml }} dest: "{{ molecule_instance_config }}" when: server.changed | bool @@ -83,5 +111,5 @@ host: "{{ item.address }}" search_regex: SSH delay: 10 - with_items: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}" + with_items: "{{ lookup('file', molecule_instance_config) | from_yaml }}" {%- endraw %} diff --git a/molecule_hetznercloud/cookiecutter/scenario/driver/hetznercloud/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/destroy.yml b/molecule_hetznercloud/cookiecutter/scenario/driver/hetznercloud/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/destroy.yml index afd44a2..fc93d52 100644 --- a/molecule_hetznercloud/cookiecutter/scenario/driver/hetznercloud/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/destroy.yml +++ b/molecule_hetznercloud/cookiecutter/scenario/driver/hetznercloud/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/destroy.yml @@ -10,7 +10,7 @@ block: - name: Populate instance config from file set_fact: - instance_conf: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}" + instance_conf: "{{ lookup('file', molecule_instance_config) | from_yaml }}" skip_instances: false rescue: - name: Populate instance config when file missing @@ -37,6 +37,29 @@ retries: 300 with_items: "{{ server.results }}" + - name: Destroy volume(s) + hcloud_volume: + name: "{{ item.volumes.name | default(item.instance) }}" + server: "{{ item.instance }}" + api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}" + state: "absent" + register: volumes + with_items: "{{ instance_conf }}" + when: + - item.volumes is defined + - item.volumes.create | default(False) | bool + async: 7200 + poll: 0 + + - name: Wait for volume(s) deletion to complete + async_status: + jid: "{{ item.ansible_job_id }}" + register: hetzner_volumes + until: hetzner_volumes.finished + retries: 300 + when: volumes.changed + with_items: "{{ volumes.results }}" + - name: Remove registered SSH key hcloud_ssh_key: name: "{{ instance_conf[0].ssh_key_name }}" @@ -52,7 +75,10 @@ - name: Dump instance config copy: - content: "{{ instance_conf | molecule_to_yaml | molecule_header }}" + content: | + # Molecule managed + + {{ instance_conf | to_json | from_json | to_yaml }} dest: "{{ molecule_instance_config }}" when: server.changed | bool {%- endraw %} diff --git a/molecule_hetznercloud/playbooks/create.yml b/molecule_hetznercloud/playbooks/create.yml index 7bbcfbc..23ee263 100644 --- a/molecule_hetznercloud/playbooks/create.yml +++ b/molecule_hetznercloud/playbooks/create.yml @@ -32,7 +32,6 @@ server_type: "{{ item.server_type }}" ssh_keys: - "{{ ssh_key_name }}" - volumes: "{{ item.volumes | default(omit) }}" image: "{{ item.image }}" location: "{{ item.location | default(omit) }}" datacenter: "{{ item.datacenter | default(omit) }}" @@ -52,17 +51,41 @@ retries: 300 with_items: "{{ server.results }}" + - name: Create volume(s) + hcloud_volume: + name: "{{ item.volumes.name | default(item.name) }}" + server: "{{ item.name }}" + location: "{{ item.volumes.location | default(omit) }}" + size: "{{ item.volumes.size | default(10) }}" + api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}" + state: "present" + with_items: "{{ molecule_yml.platforms }}" + when: + - item.volumes is defined + - item.volumes.create | default(False) | bool + register: volumes + async: 7200 + poll: 0 + + - name: Wait for volume(s) creation to complete + async_status: + jid: "{{ item.ansible_job_id }}" + register: hetzner_volumes + until: hetzner_volumes.finished + retries: 300 + when: volumes.changed + with_items: "{{ volumes.results }}" + - name: Populate instance config dict set_fact: - instance_conf_dict: - { - "instance": "{{ item.hcloud_server.name }}", - "ssh_key_name": "{{ ssh_key_name }}", - "address": "{{ item.hcloud_server.ipv4_address }}", - "user": "{{ ssh_user }}", - "port": "{{ ssh_port }}", - "identity_file": "{{ ssh_path }}", - } + instance_conf_dict: { + 'instance': "{{ item.hcloud_server.name }}", + 'ssh_key_name': "{{ ssh_key_name }}", + 'address': "{{ item.hcloud_server.ipv4_address }}", + 'user': "{{ ssh_user }}", + 'port': "{{ ssh_port }}", + 'identity_file': "{{ ssh_path }}", + 'volumes': "{{ item.item.item.volumes | default({}) }}", } with_items: "{{ hetzner_jobs.results }}" register: instance_config_dict when: server.changed | bool @@ -74,7 +97,10 @@ - name: Dump instance config copy: - content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}" + content: | + # Molecule managed + + {{ instance_conf | to_json | from_json | to_yaml }} dest: "{{ molecule_instance_config }}" when: server.changed | bool @@ -84,4 +110,4 @@ host: "{{ item.address }}" search_regex: SSH delay: 10 - with_items: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}" + with_items: "{{ lookup('file', molecule_instance_config) | from_yaml }}" diff --git a/molecule_hetznercloud/playbooks/destroy.yml b/molecule_hetznercloud/playbooks/destroy.yml index aae4ed6..16eb0e5 100644 --- a/molecule_hetznercloud/playbooks/destroy.yml +++ b/molecule_hetznercloud/playbooks/destroy.yml @@ -9,7 +9,7 @@ block: - name: Populate instance config from file set_fact: - instance_conf: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}" + instance_conf: "{{ lookup('file', molecule_instance_config) | from_yaml }}" skip_instances: false rescue: - name: Populate instance config when file missing @@ -36,6 +36,29 @@ retries: 300 with_items: "{{ server.results }}" + - name: Destroy volume(s) + hcloud_volume: + name: "{{ item.volumes.name | default(item.instance) }}" + server: "{{ item.instance }}" + api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}" + state: "absent" + register: volumes + with_items: "{{ instance_conf }}" + when: + - item.volumes is defined + - item.volumes.create | default(False) | bool + async: 7200 + poll: 0 + + - name: Wait for volume(s) deletion to complete + async_status: + jid: "{{ item.ansible_job_id }}" + register: hetzner_volumes + until: hetzner_volumes.finished + retries: 300 + when: volumes.changed + with_items: "{{ volumes.results }}" + - name: Remove registered SSH key hcloud_ssh_key: name: "{{ instance_conf[0].ssh_key_name }}" @@ -51,6 +74,9 @@ - name: Dump instance config copy: - content: "{{ instance_conf | molecule_to_yaml | molecule_header }}" + content: | + # Molecule managed + + {{ instance_conf | to_json | from_json | to_yaml }} dest: "{{ molecule_instance_config }}" when: server.changed | bool diff --git a/molecule_hetznercloud/test/resources/playbooks/hetznercloud/create.yml b/molecule_hetznercloud/test/resources/playbooks/hetznercloud/create.yml index bf26ee8..23ee263 100644 --- a/molecule_hetznercloud/test/resources/playbooks/hetznercloud/create.yml +++ b/molecule_hetznercloud/test/resources/playbooks/hetznercloud/create.yml @@ -23,6 +23,7 @@ hcloud_ssh_key: name: "{{ ssh_key_name }}" public_key: "{{ generated_ssh_key.public_key }}" + api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}" state: present - name: Create molecule instance(s) @@ -31,7 +32,6 @@ server_type: "{{ item.server_type }}" ssh_keys: - "{{ ssh_key_name }}" - volumes: "{{ item.volumes | default(omit) }}" image: "{{ item.image }}" location: "{{ item.location | default(omit) }}" datacenter: "{{ item.datacenter | default(omit) }}" @@ -51,19 +51,41 @@ retries: 300 with_items: "{{ server.results }}" - # Mandatory configuration for Molecule to function. + - name: Create volume(s) + hcloud_volume: + name: "{{ item.volumes.name | default(item.name) }}" + server: "{{ item.name }}" + location: "{{ item.volumes.location | default(omit) }}" + size: "{{ item.volumes.size | default(10) }}" + api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}" + state: "present" + with_items: "{{ molecule_yml.platforms }}" + when: + - item.volumes is defined + - item.volumes.create | default(False) | bool + register: volumes + async: 7200 + poll: 0 + + - name: Wait for volume(s) creation to complete + async_status: + jid: "{{ item.ansible_job_id }}" + register: hetzner_volumes + until: hetzner_volumes.finished + retries: 300 + when: volumes.changed + with_items: "{{ volumes.results }}" - name: Populate instance config dict set_fact: - instance_conf_dict: - { - "instance": "{{ item.hcloud_server.name }}", - "ssh_key_name": "{{ ssh_key_name }}", - "address": "{{ item.hcloud_server.ipv4_address }}", - "user": "{{ ssh_user }}", - "port": "{{ ssh_port }}", - "identity_file": "{{ ssh_path }}", - } + instance_conf_dict: { + 'instance': "{{ item.hcloud_server.name }}", + 'ssh_key_name': "{{ ssh_key_name }}", + 'address': "{{ item.hcloud_server.ipv4_address }}", + 'user': "{{ ssh_user }}", + 'port': "{{ ssh_port }}", + 'identity_file': "{{ ssh_path }}", + 'volumes': "{{ item.item.item.volumes | default({}) }}", } with_items: "{{ hetzner_jobs.results }}" register: instance_config_dict when: server.changed | bool @@ -75,7 +97,10 @@ - name: Dump instance config copy: - content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}" + content: | + # Molecule managed + + {{ instance_conf | to_json | from_json | to_yaml }} dest: "{{ molecule_instance_config }}" when: server.changed | bool @@ -85,4 +110,4 @@ host: "{{ item.address }}" search_regex: SSH delay: 10 - with_items: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}" + with_items: "{{ lookup('file', molecule_instance_config) | from_yaml }}" diff --git a/molecule_hetznercloud/test/resources/playbooks/hetznercloud/destroy.yml b/molecule_hetznercloud/test/resources/playbooks/hetznercloud/destroy.yml index f49f0d7..16eb0e5 100644 --- a/molecule_hetznercloud/test/resources/playbooks/hetznercloud/destroy.yml +++ b/molecule_hetznercloud/test/resources/playbooks/hetznercloud/destroy.yml @@ -9,7 +9,7 @@ block: - name: Populate instance config from file set_fact: - instance_conf: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}" + instance_conf: "{{ lookup('file', molecule_instance_config) | from_yaml }}" skip_instances: false rescue: - name: Populate instance config when file missing @@ -36,15 +36,37 @@ retries: 300 with_items: "{{ server.results }}" + - name: Destroy volume(s) + hcloud_volume: + name: "{{ item.volumes.name | default(item.instance) }}" + server: "{{ item.instance }}" + api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}" + state: "absent" + register: volumes + with_items: "{{ instance_conf }}" + when: + - item.volumes is defined + - item.volumes.create | default(False) | bool + async: 7200 + poll: 0 + + - name: Wait for volume(s) deletion to complete + async_status: + jid: "{{ item.ansible_job_id }}" + register: hetzner_volumes + until: hetzner_volumes.finished + retries: 300 + when: volumes.changed + with_items: "{{ volumes.results }}" + - name: Remove registered SSH key hcloud_ssh_key: name: "{{ instance_conf[0].ssh_key_name }}" + api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}" state: absent when: - not skip_instances - - instance_conf # must contain at least one instance - - # Mandatory configuration for Molecule to function. + - instance_conf | length # must contain at least one instance - name: Populate instance config set_fact: @@ -52,6 +74,9 @@ - name: Dump instance config copy: - content: "{{ instance_conf | molecule_to_yaml | molecule_header }}" + content: | + # Molecule managed + + {{ instance_conf | to_json | from_json | to_yaml }} dest: "{{ molecule_instance_config }}" when: server.changed | bool diff --git a/molecule_hetznercloud/test/unit/model/v2/test_platforms_section.py b/molecule_hetznercloud/test/unit/model/v2/test_platforms_section.py index 81cc274..b3f6df0 100644 --- a/molecule_hetznercloud/test/unit/model/v2/test_platforms_section.py +++ b/molecule_hetznercloud/test/unit/model/v2/test_platforms_section.py @@ -10,7 +10,7 @@ def _model_platform_hetznercloud_section_data(): { "name": "instance", "server_type": "", - "volumes": [""], + "volumes": {}, "image": "", "location": "", "datacenter": "", @@ -35,7 +35,7 @@ def _model_platforms_hetznercloud_errors_section_data(): { "name": 0, "server_type": 0, - "volumes": {}, + "volumes": [], "image": 0, "location": 0, "datacenter": 0, @@ -57,7 +57,7 @@ def test_platforms_hetznercloud_has_errors(_config): { "name": ["must be of string type"], "server_type": ["must be of string type"], - "volumes": ["must be of list type"], + "volumes": ["must be of dict type"], "image": ["must be of string type"], "location": ["must be of string type"], "datacenter": ["must be of string type"],