16 Commits
0.2.1 ... 1.0.0

Author SHA1 Message Date
1423840fba Fixup volume creation functionality
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing
2021-01-06 15:21:42 +01:00
5fd3f5ca94 Actually, this is a breaking release, mark it so 2021-01-06 13:29:19 +01:00
f226bb757a Install Ansible for integration testing 2021-01-06 13:23:11 +01:00
8226a462de Mark release and remove dev facing issue 2021-01-06 13:16:26 +01:00
2fffc4882b Fix typo 2021-01-06 13:13:51 +01:00
781e7ec7bb Support dropping sh dependency
Some checks failed
continuous-integration/drone/push Build is failing
2021-01-06 13:09:05 +01:00
8e06794f3c Document volume handling
Some checks failed
continuous-integration/drone/push Build is failing
2021-01-06 12:17:20 +01:00
92f645e43d Merge pull request 'Native ansible filters and volumes handling' (#10) from volumes-handling into main
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #10
2021-01-06 12:06:51 +01:00
d57f80a496 Support volumes handling
Some checks reported errors
continuous-integration/drone/push Build was killed
continuous-integration/drone/pr Build was killed
2021-01-06 12:01:37 +01:00
5efff53088 Use native ansible handlers 2021-01-06 12:01:37 +01:00
488469e927 Fix path in docs
Some checks failed
continuous-integration/drone/push Build is failing
2021-01-06 12:00:34 +01:00
9bf4196816 Py39, Molecule 3.2.1 and dep tree upgrade 2021-01-06 11:49:48 +01:00
447585b8c5 Merge pull request 'Support CI for PRs' (#9) from support-drone-prs into main
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #9
2021-01-06 10:58:53 +01:00
f084833ed2 Remove branch trigger focus
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-01-06 10:55:47 +01:00
0464272787 Mark branch change in change log 2021-01-06 10:53:13 +01:00
88ffc62389 Point to an open issue tracker
All checks were successful
continuous-integration/drone/push Build is passing
Closes https://github.com/ansible-community/molecule-hetznercloud/issues/15.
2020-06-15 15:53:27 +02:00
18 changed files with 309 additions and 153 deletions

View File

@ -3,28 +3,22 @@ kind: pipeline
name: linters
steps:
- name: tox -e linters
image: python:3.8-buster
image: python:3.9-buster
commands:
- pip install tox==3.14.6
- pip install tox
- tox -e linters
trigger:
ref:
- "refs/heads/master"
---
kind: pipeline
name: packaging
steps:
- name: tox -e packaging
image: python:3.8-buster
image: python:3.9-buster
commands:
- pip install tox==3.14.6
- pip install tox
- tox -e packaging
depends_on:
- linters
trigger:
ref:
- "refs/heads/master"
---
kind: pipeline
@ -33,13 +27,10 @@ steps:
- name: tox -e py36
image: python:3.6-buster
commands:
- pip install tox==3.14.6
- pip install tox
- tox -e py36
depends_on:
- linters
trigger:
ref:
- "refs/heads/master"
---
kind: pipeline
@ -48,13 +39,10 @@ steps:
- name: tox -e py37
image: python:3.7-buster
commands:
- pip install tox==3.14.6
- pip install tox
- tox -e py37
depends_on:
- linters
trigger:
ref:
- "refs/heads/master"
---
kind: pipeline
@ -63,42 +51,37 @@ steps:
- name: tox -e py38
image: python:3.8-buster
commands:
- pip install tox==3.14.6
- pip install tox
- tox -e py38
depends_on:
- linters
trigger:
ref:
- "refs/heads/master"
---
kind: pipeline
name: devel
steps:
- name: tox -e devel
image: python:3.8-buster
image: python:3.9-buster
failure: ignore
commands:
- pip install tox==3.14.6
- pip install tox
- tox -e devel
depends_on:
- linters
trigger:
ref:
- "refs/heads/master"
---
kind: pipeline
name: integration
steps:
- name: molecule test
image: python:3.8-buster
image: python:3.9-buster
environment:
MOLECULE_NO_LOG: false
HCLOUD_TOKEN:
from_secret: HCLOUD_TOKEN
commands:
- pip install -e .
- pip install "ansible>=2.10, <2.11"
- export INSTANCE_UUID=$(openssl rand -hex 5)
- cd integration && molecule test
depends_on:
@ -107,6 +90,3 @@ depends_on:
- py36
- py37
- py38
trigger:
ref:
- "refs/heads/master"

View File

@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [1.0.0] - 2021-01-06
This is a major release with breaking changes for your schema and support for a
new major version of Molecule. If you use the `volumes:` key in your
`molecule.yml` then this change will break your configuration. Please see the
section on "Volume Handling" in the README.md on how to upgrade successfully.
You will now need to install Ansible yourself as Molecule does not do it for
you. If there are any other breaking changes, please report them on the issue
tracker so that we can mention them here.
- Support Python 3.9.
- Support Molecule 3.2.1
- Add volume creation and clean up handling
## [0.2.2] - 2020-06-15
## Fixed
- Point to an open issue tracker
## [0.2.1] - 2020-04-29
### Fixed

View File

@ -72,6 +72,26 @@ $ export MOLECULE_NO_LOG=False # not so verbose, helpful
$ export MOLECULE_DEBUG=True # very verbose, last ditch effort
```
## Volume Handling
It is possible to have the driver manage volumes during the test run.
You can add the following stanza to your Molecule configuration to have
Molecule create this volume for the managed VPS. This volume will be cleaned up
after use.
```yaml
volumes:
- name: "molecule-hetznercloud-volume-1-${INSTANCE_UUID}"
- name: "molecule-hetznercloud-volume-2-${INSTANCE_UUID}"
```
Supported keys are:
- **name** (required): name of volume
- **size** (optional, default: `10GB`): size of volume
- **location** (optional, default: `omitted`): path for volume
## Only use `molecule.yml` for configuration
It is being worked on that it is possible to remove all the files except the
@ -126,5 +146,5 @@ $ sudo apt install -y direnv
$ cp .envrc.sample .envrc
$ direnv allow
$ pip install -e .
$ cd integration-test-role && molecule test
$ cd integration && molecule test
```

View File

@ -7,6 +7,9 @@ platforms:
- name: "molecule-hetznercloud-${INSTANCE_UUID}"
server_type: cx11
image: debian-10
volumes:
- name: "molecule-hetznercloud-volume-1-${INSTANCE_UUID}"
# - name: "molecule-hetznercloud-volume-2-${INSTANCE_UUID}"
provisioner:
name: ansible
verifier:

View File

@ -5,7 +5,7 @@ Hetzner Cloud plugin installation guide
Requirements
============
* Ansible >= 2.9
* Ansible >= 2.10
* ``HCLOUD_TOKEN`` exposed in your environment
Install

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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,6 +51,30 @@
retries: 300
with_items: "{{ server.results }}"
- name: Create volume(s)
hcloud_volume:
name: "{{ item.1.name | default(item.0.name) }}"
server: "{{ item.0.name }}"
location: "{{ item.1.location | default(omit) }}"
size: "{{ item.1.size | default(10) }}"
api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}"
state: "present"
loop: "{{ molecule_yml.platforms|subelements('volumes', skip_missing=True)}}"
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 is defined
- volumes.changed
with_items: "{{ volumes.results }}"
- name: Populate instance config dict
set_fact:
instance_conf_dict:
@ -62,6 +85,7 @@
"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
@ -74,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
@ -84,4 +111,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 }}"

View File

@ -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,26 @@
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 }}"
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 }}"
@ -43,7 +63,7 @@
state: absent
when:
- not skip_instances
- instance_conf | length # must contain at least one instance
- instance_conf | length # must contain at least one instance
- name: Populate instance config
set_fact:
@ -51,6 +71,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

View File

@ -12,13 +12,14 @@ LOG = logger.get_logger(__name__)
@pytest.helpers.register
def run_command(cmd, env=os.environ, log=True):
if log:
cmd = _rebake_command(cmd, env)
cmd = cmd.bake(_truncate_exc=False)
return util.run_command(cmd)
if cmd.__class__.__name__ == "Command":
if log:
cmd = _rebake_command(cmd, env)
cmd = cmd.bake(_truncate_exc=False)
return util.run_command(cmd, env=env)
def _rebake_command(cmd, env, out=LOG.out, err=LOG.error):
def _rebake_command(cmd, env, out=LOG.info, err=LOG.error):
return cmd.bake(_env=env, _out=out, _err=err)

View File

@ -1,13 +1,10 @@
import os
import pkg_resources
import shutil
import pexpect
import pkg_resources
import pytest
import sh
from molecule import logger
from molecule import util
from molecule import logger, util
from ..conftest import change_dir_to
@ -37,9 +34,8 @@ def with_scenario(request, scenario_to_test, driver_name, scenario_name, skip_te
yield
if scenario_name:
msg = "CLEANUP: Destroying instances for all scenario(s)"
LOG.out(msg)
options = {"driver_name": driver_name, "all": True}
cmd = sh.molecule.bake("destroy", **options)
LOG.info(msg)
cmd = ["molecule", "destroy", "--driver-name", driver_name, "--all"]
pytest.helpers.run_command(cmd)
@ -63,56 +59,56 @@ def skip_test(request, driver_name):
@pytest.helpers.register
def idempotence(scenario_name):
options = {"scenario_name": scenario_name}
cmd = sh.molecule.bake("create", **options)
cmd = ["molecule", "create", "--scenario-name", scenario_name]
pytest.helpers.run_command(cmd)
options = {"scenario_name": scenario_name}
cmd = sh.molecule.bake("converge", **options)
cmd = ["molecule", "converge", "--scenario_name", scenario_name]
pytest.helpers.run_command(cmd)
options = {"scenario_name": scenario_name}
cmd = sh.molecule.bake("idempotence", **options)
cmd = ["molecule", "--scenario_name", scenario_name]
pytest.helpers.run_command(cmd)
@pytest.helpers.register
def init_role(temp_dir, driver_name):
role_directory = os.path.join(temp_dir.strpath, "test-init")
cmd = sh.molecule.bake(
"init", "role", {"driver-name": driver_name, "role-name": "test-init"}
)
cmd = ["molecule", "init", "role", "test-init", "--driver-name", driver_name]
pytest.helpers.run_command(cmd)
role_directory = os.path.join(temp_dir.strpath, "test-init")
pytest.helpers.metadata_lint_update(role_directory)
with change_dir_to(role_directory):
options = {"all": True}
cmd = sh.molecule.bake("test", **options)
cmd = ["molecule", "test", "--all"]
pytest.helpers.run_command(cmd)
@pytest.helpers.register
def init_scenario(temp_dir, driver_name):
role_directory = os.path.join(temp_dir.strpath, "test-init")
cmd = sh.molecule.bake(
"init", "role", {"driver-name": driver_name, "role-name": "test-init"}
)
cmd = ["molecule", "init", "role", "test-init", "--driver-name", driver_name]
pytest.helpers.run_command(cmd)
role_directory = os.path.join(temp_dir.strpath, "test-init")
pytest.helpers.metadata_lint_update(role_directory)
with change_dir_to(role_directory):
molecule_directory = pytest.helpers.molecule_directory()
scenario_directory = os.path.join(molecule_directory, "test-scenario")
options = {"scenario_name": "test-scenario", "role_name": "test-init"}
cmd = sh.molecule.bake("init", "scenario", **options)
cmd = [
"molecule",
"init",
"scenario",
"test-scenario",
"--role-name",
"test-init",
"--driver-name",
driver_name,
]
pytest.helpers.run_command(cmd)
assert os.path.isdir(scenario_directory)
options = {"scenario_name": "test-scenario", "all": True}
cmd = sh.molecule.bake("test", **options)
cmd = ["molecule", "test", "--scenario-name", "test-scenario", "--all"]
pytest.helpers.run_command(cmd)
@ -125,13 +121,13 @@ def metadata_lint_update(role_directory):
shutil.copy(ansible_lint_src, role_directory)
with change_dir_to(role_directory):
cmd = sh.ansible_lint.bake(".")
cmd = ["ansible-lint", "."]
pytest.helpers.run_command(cmd)
@pytest.helpers.register
def list(x):
cmd = sh.molecule.bake("list")
cmd = ["molecule", "list"]
out = pytest.helpers.run_command(cmd, log=False)
out = out.stdout.decode("utf-8")
out = util.strip_ansi_color(out)
@ -142,10 +138,9 @@ def list(x):
@pytest.helpers.register
def list_with_format_plain(x):
cmd = sh.molecule.bake("list", {"format": "plain"})
out = pytest.helpers.run_command(cmd, log=False)
out = out.stdout.decode("utf-8")
out = util.strip_ansi_color(out)
cmd = ["molecule", "list", "--format", "plain"]
result = util.run_command(cmd)
out = util.strip_ansi_color(result.stdout)
for l in x.splitlines():
assert l in out
@ -153,12 +148,10 @@ def list_with_format_plain(x):
@pytest.helpers.register
def login(login_args, scenario_name="default"):
options = {"scenario_name": scenario_name}
cmd = sh.molecule.bake("destroy", **options)
cmd = ["molecule", "destroy", "--scenario-name", scenario_name]
pytest.helpers.run_command(cmd)
options = {"scenario_name": scenario_name}
cmd = sh.molecule.bake("create", **options)
cmd = ["molecule", "create", "--scenario-name", scenario_name]
pytest.helpers.run_command(cmd)
for instance, regexp in login_args:
@ -175,31 +168,26 @@ def login(login_args, scenario_name="default"):
@pytest.helpers.register
def test(driver_name, scenario_name="default", parallel=False):
options = {
"scenario_name": scenario_name,
"all": scenario_name is None,
"parallel": parallel,
}
cmd = ["molecule", "test", "--scenario-name", scenario_name]
if driver_name == "delegated":
options = {"scenario_name": scenario_name}
if driver_name != "delegated":
if scenario_name is None:
cmd.append("--all")
if parallel:
cmd.append("--parallel")
cmd = sh.molecule.bake("test", **options)
pytest.helpers.run_command(cmd)
@pytest.helpers.register
def verify(scenario_name="default"):
options = {"scenario_name": scenario_name}
cmd = sh.molecule.bake("create", **options)
cmd = ["molecule", "create", "--scenario-name", scenario_name]
pytest.helpers.run_command(cmd)
options = {"scenario_name": scenario_name}
cmd = sh.molecule.bake("converge", **options)
cmd = ["molecule", "converge", "--scenario-name", scenario_name]
pytest.helpers.run_command(cmd)
options = {"scenario_name": scenario_name}
cmd = sh.molecule.bake("verify", **options)
cmd = ["molecule", "verify", "--scenario-name", scenario_name]
pytest.helpers.run_command(cmd)

View File

@ -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 }}"

View File

@ -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

View File

@ -1,8 +1,6 @@
import os
import pytest
import sh
from molecule import util
from molecule.command.init import base
from molecule.model import schema_v3
@ -57,5 +55,5 @@ def test_drivers(
assert {} == schema_v3.validate(data)
cmd = sh.yamllint.bake("-s", _molecule_file)
cmd = ["yamllint", "-s", _molecule_file]
pytest.helpers.run_command(cmd)

View File

@ -1,7 +1,6 @@
import os
import pytest
from molecule import config
from molecule_hetznercloud import driver
@ -15,13 +14,6 @@ def test_hetznercloud_config_gives_config_object(hetznercloud_instance):
assert isinstance(hetznercloud_instance._config, config.Config)
def test_hetznercloud_testinfra_options_property(hetznercloud_instance):
assert {
"connection": "ansible",
"ansible-inventory": hetznercloud_instance._config.provisioner.inventory_file,
} == hetznercloud_instance.testinfra_options
def test_hetznercloud_name_property(hetznercloud_instance):
assert "hetznercloud" == hetznercloud_instance.name

View File

@ -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,

View File

@ -8,7 +8,7 @@ universal = 1
name = molecule-hetznercloud
url = https://git.autonomic.zone/autonomic-cooperative/molecule-hetznercloud
project_urls =
Bug Tracker = https://git.autonomic.zone/autonomic-cooperative/molecule-hetznercloud/issues
Bug Tracker = https://github.com/ansible-community/molecule-hetznercloud/issues
CI: Drone = https://drone.autonomic.zone/autonomic-cooperative/molecule-hetznercloud/
Source Code = https://git.autonomic.zone/autonomic-cooperative/molecule-hetznercloud
description = Molecule Hetzner Cloud Plugin :: run molecule tests with hetzner cloud
@ -30,7 +30,10 @@ classifiers =
Natural Language :: English
Operating System :: OS Independent
Programming Language :: Python :: 3
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Topic :: System :: Systems Administration
Topic :: Utilities
keywords =
@ -49,23 +52,23 @@ packages = find:
include_package_data = True
zip_safe = False
setup_requires =
setuptools_scm >= 3.5.0
setuptools_scm_git_archive >= 1.1
setuptools_scm
setuptools_scm_git_archive
install_requires =
hcloud >= 1.6.3, < 2
molecule >= 3.0.4, <= 3.1
hcloud >= 1.10.0, < 2
molecule >= 3.2.1, <= 3.3
pyyaml >= 5.3.1, < 6
[options.extras_require]
test =
hcloud >= 1.6.3, < 2
hcloud >= 1.10.0, < 2
mock >= 4.0.2, < 5
pytest-cov >= 2.8.1, < 3
pytest-cov >= 2.10.1, < 3
pytest-helpers-namespace >= 2019.1.8, < 2020
pytest-mock >= 3.1.0, < 4
pytest-mock >= 3.5.0, < 4
pytest-verbose-parametrize>=1.7.0, < 2
pytest-xdist>=1.31.0, < 2
pytest>=5.4.1, < 6
pytest-xdist>=2.2.0, < 3
pytest>=6.2.1, < 7
[options.packages.find]
where = .

15
tox.ini
View File

@ -1,12 +1,10 @@
# For more information about tox, see https://tox.readthedocs.io/en/latest/
[tox]
minversion = 3.14.0
envlist =
linters
packaging
py{36,37,38}
py{36,37,38,39}
devel
skipsdist = True
skip_missing_interpreters = False
isolated_build = True
@ -19,12 +17,11 @@ setenv =
PYTHONDONTWRITEBYTECODE=1
PYTEST_ADDOPTS=molecule_hetznercloud/test/unit/ --cov={toxinidir}/molecule_hetznercloud/ --no-cov-on-fail {env:PYTEST_ADDOPTS:-n auto}
deps =
ansible>=2.9,<2.10
ansible>=2.10,<2.11
extras =
test
commands =
python -m pytest {posargs}
whitelist_externals =
bash
twine
@ -34,7 +31,7 @@ whitelist_externals =
[testenv:linters]
commands =
python -m pre_commit run {posargs:--all}
deps = pre-commit>=1.18.1
deps = pre-commit
skip_install = true
usedevelop = false
@ -42,9 +39,9 @@ usedevelop = false
usedevelop = false
skip_install = true
deps =
collective.checkdocs >= 0.2
pep517 >= 0.5.0
twine >= 2.0.0
collective.checkdocs
pep517
twine
commands =
bash -c "rm -rf {toxinidir}/dist/ && mkdir -p {toxinidir}/dist/"
python -m pep517.build \