From b3d6638395acaa7289a6ade4cc92272577a7f40a Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Sat, 3 Oct 2020 13:11:44 +0200 Subject: [PATCH] move molecule to hcloud --- cookiecutter.json | 4 +- hooks/post_gen_project.sh | 2 +- .../.drone.jsonnet | 27 +----- .../README.md | 4 - .../molecule/requirements.yml | 4 + .../create.yml | 89 ------------------ .../prepare.yml | 9 -- .../converge.yml | 0 .../create.yml | 92 +++++++++++++++++++ .../destroy.yml | 29 +++--- .../molecule.yml | 10 +- .../prepare.yml | 15 +++ .../tests/test_default.py | 0 13 files changed, 140 insertions(+), 145 deletions(-) create mode 100644 {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/requirements.yml delete mode 100644 {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/create.yml delete mode 100644 {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/prepare.yml rename {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{{cookiecutter.molecule_scenario | replace('-', '')}} => {{cookiecutter.molecule_scenario|replace('-', '')}}}/converge.yml (100%) create mode 100644 {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/create.yml rename {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{{cookiecutter.molecule_scenario | replace('-', '')}} => {{cookiecutter.molecule_scenario|replace('-', '')}}}/destroy.yml (66%) rename {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{{cookiecutter.molecule_scenario | replace('-', '')}} => {{cookiecutter.molecule_scenario|replace('-', '')}}}/molecule.yml (62%) create mode 100644 {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/prepare.yml rename {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{{cookiecutter.molecule_scenario | replace('-', '')}} => {{cookiecutter.molecule_scenario|replace('-', '')}}}/tests/test_default.py (100%) diff --git a/cookiecutter.json b/cookiecutter.json index 7602996..273a795 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -6,8 +6,8 @@ "role_description_short": "My demo role", "role_category": "misc", "role_min_ansible_version": "2.8", - "molecule_scenario": "centos-8", - "molecule_machine_size": "s-1vcpu-1gb", + "molecule_scenario": "centos-7", + "molecule_machine_size": "cx11", "git_server": "gitea.rknet.org:ansible", "license_year": "{% now 'Europe/Berlin', '%Y' %}" } diff --git a/hooks/post_gen_project.sh b/hooks/post_gen_project.sh index 51b2df9..64656ee 100644 --- a/hooks/post_gen_project.sh +++ b/hooks/post_gen_project.sh @@ -5,4 +5,4 @@ if hash git 2>/dev/null; then git remote add origin gitea@{{ cookiecutter.git_server }}/xoxys.{{ cookiecutter.role_name }}.git fi -ln -s {{ cookiecutter.molecule_scenario }}/default +ln -s {{ cookiecutter.molecule_scenario | replace("-", "") }} molecule/default diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/.drone.jsonnet b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/.drone.jsonnet index 55376ac..413f2ee 100644 --- a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/.drone.jsonnet +++ b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/.drone.jsonnet @@ -8,7 +8,7 @@ local PipelineLinting = { steps: [ { name: 'ansible-later', - image: 'xoxys/ansible-later', + image: 'thegeeklab/ansible-later', commands: [ 'ansible-later', ], @@ -36,14 +36,12 @@ local PipelineDeployment(scenario='{{ cookiecutter.molecule_scenario | replace(" steps: [ { name: 'ansible-molecule', - image: 'xoxys/molecule:3', + image: 'thegeeklab/molecule:3', environment: { - DO_API_KEY: { from_secret: 'do_api_key' }, - MOLECULE_CUSTOM_MODULES_REPO: 'https://gitea.rknet.org/ansible/custom_modules', - MOLECULE_CUSTOM_FILTERS_REPO: 'https://gitea.rknet.org/ansible/custom_filters', + HCLOUD_TOKEN: { from_secret: 'hcloud_token' }, }, commands: [ - 'molecule test -s' + scenario, + 'molecule test -s ' + scenario, ], }, ], @@ -65,7 +63,7 @@ local PipelineDocumentation = { steps: [ { name: 'generate', - image: 'xoxys/ansible-doctor', + image: 'thegeeklab/ansible-doctor', environment: { ANSIBLE_DOCTOR_LOG_LEVEL: 'INFO', ANSIBLE_DOCTOR_FORCE_OVERWRITE: true, @@ -90,21 +88,6 @@ local PipelineDocumentation = { ref: ['refs/heads/master'], }, }, - { - name: 'trigger', - image: 'plugins/downstream', - settings: { - server: 'https://drone.rknet.org', - token: { from_secret: 'drone_token' }, - fork: true, - repositories: [ - 'ansible/ansible-galaxy', - ], - }, - when: { - ref: ['refs/heads/master'], - }, - }, ], trigger: { ref: ['refs/heads/master', 'refs/tags/**', 'refs/pull/**'], diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/README.md b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/README.md index 78c7da3..f55909b 100644 --- a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/README.md +++ b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/README.md @@ -8,7 +8,3 @@ You can find the full documentation at [https://galaxy.geekdocs.de](https://gala ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. - -## Maintainers and Contributors - -[{{ cookiecutter.author_full }}](https://gitea.rknet.org/{{ cookiecutter.author }}) diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/requirements.yml b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/requirements.yml new file mode 100644 index 0000000..280de95 --- /dev/null +++ b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/requirements.yml @@ -0,0 +1,4 @@ +--- +collections: + - name: https://gitea.rknet.org/ansible/xoxys.general/releases/download/v1.2.0/xoxys-general-1.2.0.tar.gz + - name: community.general diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/create.yml b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/create.yml deleted file mode 100644 index 9638405..0000000 --- a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/create.yml +++ /dev/null @@ -1,89 +0,0 @@ ---- -{% raw %} -- name: Create - hosts: localhost - connection: local - gather_facts: false - no_log: "{{ molecule_no_log }}" - vars: - ssh_user: root - ssh_port: 22 - - keypair_name: molecule_key - keypair_path: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/ssh_key" - tasks: - - name: Create local keypair - user: - name: "{{ lookup('env', 'USER') }}" - generate_ssh_key: true - ssh_key_file: "{{ keypair_path }}" - register: local_keypair - - - name: Create remote keypair - digital_ocean_sshkey: - name: "{{ keypair_name }}" - ssh_pub_key: "{{ local_keypair.ssh_public_key }}" - state: present - register: remote_keypair - - - name: Create molecule instance(s) - digital_ocean_droplet: - name: "{{ item.name }}" - unique_name: true - region: "{{ item.region_id }}" - image: "{{ item.image_id }}" - size: "{{ item.size_id }}" - ssh_keys: "{{ remote_keypair.data.ssh_key.id }}" - wait: true - wait_timeout: 300 - state: present - register: server - loop: "{{ molecule_yml.platforms }}" - async: 7200 - poll: 0 - - - name: Wait for instance(s) creation to complete - async_status: - jid: "{{ item.ansible_job_id }}" - register: digitalocean_jobs - until: digitalocean_jobs.finished - retries: 300 - loop: "{{ server.results }}" - - # Mandatory configuration for Molecule to function. - - - name: Populate instance config dict - set_fact: - instance_conf_dict: { - 'instance': "{{ item.data.droplet.name }}", - 'address': "{{ item.data.ip_address }}", - 'user': "{{ ssh_user }}", - 'port': "{{ ssh_port }}", - 'identity_file': "{{ keypair_path }}", - 'droplet_id': "{{ item.data.droplet.id }}", - 'ssh_key_id': "{{ remote_keypair.data.ssh_key.id }}", - } - loop: "{{ digitalocean_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 - timeout: 320 - loop: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}" -{% endraw %} diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/prepare.yml b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/prepare.yml deleted file mode 100644 index 559de83..0000000 --- a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/prepare.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: Prepare - hosts: all - gather_facts: false - tasks: - - name: Install python for Ansible - raw: test -e /usr/bin/python || (dnf -y install python3 && alternatives --set python /usr/bin/python3) - become: true - changed_when: false diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/converge.yml b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/converge.yml similarity index 100% rename from {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/converge.yml rename to {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/converge.yml diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/create.yml b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/create.yml new file mode 100644 index 0000000..6c1d373 --- /dev/null +++ b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/create.yml @@ -0,0 +1,92 @@ +--- +- name: Create + hosts: localhost + connection: local + gather_facts: false + no_log: "{{ molecule_no_log }}" + vars: + ssh_port: 22 + ssh_user: root + ssh_path: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/ssh_key" + tasks: + - name: Create SSH key + user: + name: "{{ lookup('env', 'USER') }}" + generate_ssh_key: true + ssh_key_file: "{{ ssh_path }}" + force: true + register: generated_ssh_key + + - name: Register the SSH key name + set_fact: + ssh_key_name: "molecule-generated-{{ 12345 | random | to_uuid }}" + + - name: Register SSH key for test instance(s) + hcloud_ssh_key: + name: "{{ ssh_key_name }}" + public_key: "{{ generated_ssh_key.ssh_public_key }}" + state: present + + - name: Create molecule instance(s) + hcloud_server: + name: "{{ item.name }}" + 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) }}" + 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 }}", + 'ssh_key_name': "{{ ssh_key_name }}", + 'address': "{{ item.hcloud_server.ipv4_address }}", + 'user': "{{ ssh_user }}", + 'port': "{{ ssh_port }}", + 'identity_file': "{{ ssh_path }}", } + 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 }}" + + - name: Wait for VM to settle down + pause: + seconds: 30 diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/destroy.yml b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/destroy.yml similarity index 66% rename from {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/destroy.yml rename to {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/destroy.yml index 56eded8..ecf2ed3 100644 --- a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/destroy.yml +++ b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/destroy.yml @@ -1,13 +1,13 @@ --- -{% raw %} - name: Destroy hosts: localhost connection: local gather_facts: false no_log: "{{ molecule_no_log }}" tasks: - - block: - - name: Populate instance config + - name: Populate the instance config + block: + - name: Populate instance config from file set_fact: instance_conf: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}" skip_instances: false @@ -18,12 +18,12 @@ skip_instances: true - name: Destroy molecule instance(s) - digital_ocean_droplet: + hcloud_server: name: "{{ item.instance }}" - id: "{{ item.droplet_id }}" + api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}" state: absent register: server - loop: "{{ instance_conf | flatten(levels=1) }}" + with_items: "{{ instance_conf }}" when: not skip_instances async: 7200 poll: 0 @@ -31,16 +31,18 @@ - name: Wait for instance(s) deletion to complete async_status: jid: "{{ item.ansible_job_id }}" - register: digitalocean_jobs - until: digitalocean_jobs.finished + register: hetzner_jobs + until: hetzner_jobs.finished retries: 300 - loop: "{{ server.results }}" + with_items: "{{ server.results }}" - - name: Delete remote keypair - digital_ocean_sshkey: - fingerprint: "{{ item.ssh_key_id }}" + - name: Remove registered SSH key + hcloud_ssh_key: + name: "{{ instance_conf[0].ssh_key_name }}" state: absent - loop: "{{ instance_conf | flatten(levels=1) }}" + when: + - not skip_instances + - (instance_conf | default([])) | length > 0 # must contain at least one instance # Mandatory configuration for Molecule to function. @@ -53,4 +55,3 @@ content: "{{ instance_conf | molecule_to_yaml | molecule_header }}" dest: "{{ molecule_instance_config }}" when: server.changed | bool -{% endraw %} diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/molecule.yml b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/molecule.yml similarity index 62% rename from {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/molecule.yml rename to {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/molecule.yml index 7fe964c..d89680f 100644 --- a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/molecule.yml +++ b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/molecule.yml @@ -1,15 +1,17 @@ --- dependency: name: galaxy + options: + role-file: molecule/requirements.yml + requirements-file: molecule/requirements.yml driver: name: delegated platforms: - name: {{ cookiecutter.molecule_scenario | replace("-", "") }}-{{ cookiecutter.role_name | replace("_", "-") }} - region_id: fra1 - image_id: {{ cookiecutter.molecule_scenario }}-x64 - size_id: {{ cookiecutter.molecule_machine_size }} + image: {{ cookiecutter.molecule_scenario }} + server_type: {{ cookiecutter.molecule_machine_size }} lint: | - flake8 + /usr/local/bin/flake8 provisioner: name: ansible env: diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/prepare.yml b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/prepare.yml new file mode 100644 index 0000000..183f4d3 --- /dev/null +++ b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/prepare.yml @@ -0,0 +1,15 @@ +--- +- name: Prepare + hosts: all + gather_facts: false + tasks: + - name: Bootstrap python for Ansible + raw: | + command -v python3 python || ( + (test -e /usr/bin/dnf && sudo dnf install -y python3) || + (test -e /usr/bin/apt && (apt -y update && apt install -y python-minimal)) || + (test -e /usr/bin/yum && sudo yum -y -qq install python3) || + echo "Warning: Python not boostrapped due to unknown platform." + ) + become: true + changed_when: false diff --git a/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/tests/test_default.py b/{{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/tests/test_default.py similarity index 100% rename from {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario | replace('-', '')}}/tests/test_default.py rename to {{cookiecutter.author}}.{{cookiecutter.role_name}}/molecule/{{cookiecutter.molecule_scenario|replace('-', '')}}/tests/test_default.py