You've already forked cookiecutter-ansible-role
Initial Import
This commit is contained in:
55
README.md
Normal file
55
README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Ansible Role Cookiecutter #
|
||||
|
||||
This is a [cookiecutter project] for creating [Ansible roles]. It includes tests using [Molecule] and [YAML Lint] to work with [Azure Pipelines].
|
||||
|
||||
To use this, first install `cookiecutter`, then run `cookiecutter git+https://hub.cybercinch.nz/guisea/cookiecutter-ansible-role` and answer the prompts.
|
||||
|
||||
## Development Workflow ##
|
||||
|
||||
Molecule uses Docker by default to spin up local containers for testing. I have created [several containers] work well for testing Ansible roles. Feel free to use them or change to your own in `molecule/default/molecule.yml`.
|
||||
|
||||
To test your role, you first need to install Molecule by running `pip install molecule`, or using your package manager of choice. You may also `pip install molecule[docker]` to also install the `docker` Python library, or `pip install molecule[lint]` to install `ansible-lint`, `yamllint`, and `flake8`.
|
||||
|
||||
Next, run `molecule test`. This will run the entire default test scenario, which creates a test container, runs the linters, runs the role twice, then destroys the container.
|
||||
|
||||
I frequently find I want to interact with the test instance rather than destroying it. To create a test instance, run your role, then leave the container running, run `molecule converge`. You can then interact with the container using `molecule login`. To rerun your role against the existing container, just run `molecule converge` again.
|
||||
|
||||
Once you are done with the container, run `molecule destroy` to remove it.
|
||||
|
||||
### Customizing the Test ###
|
||||
|
||||
The default scenario runs `molecule/default/converge.yml`. You can customize this playbook to suit your needs.
|
||||
|
||||
The `molecule.yml` file is setup to accept three environment variables:
|
||||
|
||||
`MOLECULE_DISTRIBUTION`: controls the distribution to test against
|
||||
`MOLECULE_COMMAND`: the command to run inside the container
|
||||
`MOLECULE_PLAYBOOK`: the name of the playbook to run
|
||||
|
||||
Valid values for `MOLECULE_DISTRIBUTION` based on how I name my test containers are:
|
||||
- centos7
|
||||
- centos8 (the default)
|
||||
- ubuntu16
|
||||
- ubuntu18
|
||||
- ubuntu20
|
||||
- debian9
|
||||
- debian10
|
||||
- fedora30
|
||||
- fedora31
|
||||
|
||||
For example, to test your role on Debian 10, run `env MOLECULE_DISTRIBUTION=debian10 molecule test`.
|
||||
|
||||
|
||||
## Thanks ##
|
||||
|
||||
A special thank you to [Jeff Geerling] for being a trailblazer with Molecule (and Ansible role testing in general). I would be lost without his amazing work.
|
||||
|
||||
[cookiecutter project]: https://github.com/audreyr/cookiecutter
|
||||
[Ansible roles]:https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html
|
||||
[molecule]: https://molecule.readthedocs.io
|
||||
[Ansible Lint]: https://docs.ansible.com/ansible-lint/
|
||||
[YAML Lint]:https://yamllint.readthedocs.io/en/stable/
|
||||
[Azure Pipelines]: https://dev.azure.com
|
||||
[several containers]: https://quay.io/user/samdoran
|
||||
[Jeff Geerling]: https://www.jeffgeerling.com/blog/2018/testing-your-ansible-roles-molecule
|
||||
[linting behavior changed]: https://molecule.readthedocs.io/en/latest/configuration.html#lint
|
||||
14
cookiecutter.json
Normal file
14
cookiecutter.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"role_title": "{{ cookiecutter.role_title }}",
|
||||
"role_name": "{{ cookiecutter.role_title | lower | replace(' ','_') }}",
|
||||
"repo_name": "ansible-role-{{ cookiecutter.role_name }}",
|
||||
"branch_name": "main",
|
||||
"author": "Aaron Guise",
|
||||
"short_description": "This role does amazing things",
|
||||
"company": "Acme, Inc.",
|
||||
"galaxy_username": "{{ cookiecutter.author | lower | replace(' ', '') }}",
|
||||
"azp_username": "{{ cookiecutter.author | lower | replace(' ', '') }}",
|
||||
"azp_branch": "main",
|
||||
"license": "Apache 2.0",
|
||||
"min_ansible_version": "2.9"
|
||||
}
|
||||
9
hooks/post_gen_project.py
Normal file
9
hooks/post_gen_project.py
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
|
||||
for dirpath, dirs, files in os.walk(os.getcwd()):
|
||||
if 'keep' in files:
|
||||
for file in files:
|
||||
path = os.path.join(dirpath, file)
|
||||
os.unlink(path)
|
||||
28
{{ cookiecutter.role_name }}/.woodpecker/cron.yml
Normal file
28
{{ cookiecutter.role_name }}/.woodpecker/cron.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
matrix:
|
||||
include:
|
||||
- MOLECULE_DISTRO: centos7
|
||||
- MOLECULE_DISTRO: almalinux8
|
||||
|
||||
clone:
|
||||
git:
|
||||
image: woodpeckerci/plugin-git
|
||||
settings:
|
||||
recursive: true
|
||||
submodule_update_remote: true
|
||||
when:
|
||||
event: [ cron ]
|
||||
|
||||
steps:
|
||||
test:
|
||||
name: Test on ${MOLECULE_DISTRO}
|
||||
image: guisea/ansible-molecule
|
||||
pull: true
|
||||
environment:
|
||||
PY_COLORS: '1'
|
||||
ANSIBLE_FORCE_COLOR: '1'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- molecule test --scenario-name ${MOLECULE_SCENARIO:-default}
|
||||
when:
|
||||
event: [ cron ]
|
||||
43
{{ cookiecutter.role_name }}/.woodpecker/lint.yml
Normal file
43
{{ cookiecutter.role_name }}/.woodpecker/lint.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
clone:
|
||||
git:
|
||||
image: woodpeckerci/plugin-git
|
||||
settings:
|
||||
recursive: true
|
||||
submodule_update_remote: true
|
||||
when:
|
||||
event: [ push, manual ]
|
||||
|
||||
steps:
|
||||
ansible-lint:
|
||||
group: test
|
||||
name: "Lint: Ansible-lint"
|
||||
image: guisea/ansible-molecule
|
||||
environment:
|
||||
PY_COLORS: '1'
|
||||
ANSIBLE_FORCE_COLOR: '1'
|
||||
commands:
|
||||
- ansible-lint -c ".ansible-lint"
|
||||
when:
|
||||
event: [ push, manual ]
|
||||
yamllint:
|
||||
group: test
|
||||
name: "Lint: Yamllint"
|
||||
image: guisea/ansible-molecule
|
||||
commands:
|
||||
- yamllint -f colored .
|
||||
when:
|
||||
event: [ push, manual ]
|
||||
ntfy:
|
||||
image: codeberg.org/l-x/woodpecker-ntfy
|
||||
settings:
|
||||
url: https://ntfy.cybercinch.nz/ci-status
|
||||
title: "Lint failed for ${CI_REPO_NAME}"
|
||||
priority: urgent
|
||||
icon: https://woodpecker-ci.org/img/logo.svg
|
||||
tags: robot,warning,rotating_light,${CI_BUILD_EVENT},${CI_REPO_NAME}
|
||||
message: >
|
||||
📝 Commit by ${CI_COMMIT_AUTHOR} on ${CI_COMMIT_BRANCH}:
|
||||
${CI_COMMIT_MESSAGE}
|
||||
when:
|
||||
event: [ push, manual ]
|
||||
status: [ failure ]
|
||||
46
{{ cookiecutter.role_name }}/.woodpecker/test.yml
Normal file
46
{{ cookiecutter.role_name }}/.woodpecker/test.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
matrix:
|
||||
include:
|
||||
# - MOLECULE_DISTRO: almalinux8
|
||||
- MOLECULE_DISTRO: almalinux9
|
||||
|
||||
clone:
|
||||
git:
|
||||
image: woodpeckerci/plugin-git
|
||||
settings:
|
||||
recursive: true
|
||||
submodule_update_remote: true
|
||||
when:
|
||||
event: [ push, manual ]
|
||||
|
||||
steps:
|
||||
test:
|
||||
name: Test on ${MOLECULE_DISTRO}
|
||||
image: guisea/ansible-molecule
|
||||
pull: true
|
||||
environment:
|
||||
PY_COLORS: '1'
|
||||
ANSIBLE_FORCE_COLOR: '1'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- molecule test --scenario-name ${MOLECULE_SCENARIO:-default}
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- manual
|
||||
ntfy:
|
||||
image: codeberg.org/l-x/woodpecker-ntfy
|
||||
settings:
|
||||
url: https://ntfy.cybercinch.nz/ci-status
|
||||
title: "Test failed for ${CI_REPO_NAME} - Distro: ${MOLECULE_DISTRO} Scenario: ${MOLECULE_SCENARIO:-default}"
|
||||
priority: urgent
|
||||
icon: https://woodpecker-ci.org/img/logo.svg
|
||||
tags: robot,warning,rotating_light,${CI_BUILD_EVENT},${CI_REPO_NAME}
|
||||
message: >
|
||||
📝 Commit by ${CI_COMMIT_AUTHOR} on ${CI_COMMIT_BRANCH}:
|
||||
${CI_COMMIT_MESSAGE}
|
||||
when:
|
||||
event: [ push, manual ]
|
||||
status: [ failure ]
|
||||
depends_on:
|
||||
- lint
|
||||
16
{{ cookiecutter.role_name }}/.woodpecker/z.ntfy-cron.yml
Normal file
16
{{ cookiecutter.role_name }}/.woodpecker/z.ntfy-cron.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
skip_clone: true
|
||||
|
||||
steps:
|
||||
ntfy-success:
|
||||
image: codeberg.org/l-x/woodpecker-ntfy
|
||||
settings:
|
||||
url: https://ntfy.cybercinch.nz/ci-status
|
||||
title: Build succeeded on ${CI_REPO_NAME}
|
||||
priority: urgent
|
||||
icon: https://woodpecker-ci.org/img/logo.svg
|
||||
tags: robot,white_check_mark,${CI_BUILD_EVENT},${CI_REPO_NAME}
|
||||
message: >
|
||||
Test success when run by cron for ${CI_REPO_NAME}.
|
||||
depends_on:
|
||||
- "cron"
|
||||
runs_on: [ success ]
|
||||
20
{{ cookiecutter.role_name }}/.woodpecker/z.ntfy.yml
Normal file
20
{{ cookiecutter.role_name }}/.woodpecker/z.ntfy.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
skip_clone: true
|
||||
|
||||
steps:
|
||||
ntfy:
|
||||
image: codeberg.org/l-x/woodpecker-ntfy
|
||||
settings:
|
||||
url: https://ntfy.cybercinch.nz/ci-status
|
||||
title: "Build completed for ${CI_REPO_NAME}"
|
||||
priority: urgent
|
||||
icon: https://woodpecker-ci.org/img/logo.svg
|
||||
tags: robot,tada,white_check_mark,${CI_BUILD_EVENT},${CI_REPO_NAME}
|
||||
message: >
|
||||
📝 Commit by ${CI_COMMIT_AUTHOR} on ${CI_COMMIT_BRANCH}:
|
||||
${CI_COMMIT_MESSAGE}
|
||||
when:
|
||||
event: [ push, manual ]
|
||||
status: [ success ]
|
||||
depends_on:
|
||||
- lint
|
||||
- test
|
||||
@@ -0,0 +1,16 @@
|
||||
skip_clone: true
|
||||
|
||||
steps:
|
||||
ntfy-failed:
|
||||
image: codeberg.org/l-x/woodpecker-ntfy
|
||||
settings:
|
||||
url: https://ntfy.cybercinch.nz/ci-status
|
||||
title: Build failed on ${CI_REPO_NAME}
|
||||
priority: urgent
|
||||
icon: https://woodpecker-ci.org/img/logo.svg
|
||||
tags: robot,rotating_light,no_entry,${CI_BUILD_EVENT},${CI_REPO_NAME}
|
||||
message: >
|
||||
Test failed when run by cron for ${CI_REPO_NAME}.
|
||||
depends_on:
|
||||
- "cron"
|
||||
runs_on: [ failure ]
|
||||
36
{{ cookiecutter.role_name }}/Makefile
Normal file
36
{{ cookiecutter.role_name }}/Makefile
Normal file
@@ -0,0 +1,36 @@
|
||||
.PHONY: clean virtualenv lint test docker dist dist-upload
|
||||
|
||||
clean:
|
||||
find . -name '*.py[co]' -delete
|
||||
|
||||
virtualenv:
|
||||
virtualenv --prompt '|> ansible-role-common <| ' .venv
|
||||
.venv/bin/pip install --upgrade pip
|
||||
.venv/bin/pip install -r requirements.txt
|
||||
.venv/bin/ansible-galaxy collection install -r requirements.yml
|
||||
@echo
|
||||
@echo "VirtualENV Setup Complete. Now run: source .venv/bin/activate"
|
||||
@echo
|
||||
|
||||
test:
|
||||
for distro in almalinux9 ; do \
|
||||
MOLECULE_DISTRO=$$distro molecule test --all ; \
|
||||
done
|
||||
|
||||
lint:
|
||||
@echo "Linting with Ansible-lint"
|
||||
@echo
|
||||
ansible-lint -c ".ansible-lint" --exclude ".venv"
|
||||
@echo
|
||||
@echo "Linting with Yamllint"
|
||||
@echo
|
||||
yamllint .
|
||||
@echo
|
||||
|
||||
dist: clean
|
||||
rm -rf dist/*
|
||||
python setup.py sdist
|
||||
python setup.py bdist_wheel
|
||||
|
||||
dist-upload:
|
||||
twine upload dist/*
|
||||
35
{{ cookiecutter.role_name }}/README.md
Normal file
35
{{ cookiecutter.role_name }}/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
{{ cookiecutter.role_title | title }}
|
||||
=========
|
||||
[](https://galaxy.ansible.com/{{ cookiecutter.galaxy_username }}/{{ cookiecutter.role_name }})
|
||||
[](https://dev.azure.com/{{ cookiecutter.azp_username }}/{{ cookiecutter.repo_name }}/_build/latest?definitionId=3&branchName={{ cookiecutter.azp_branch }})
|
||||
A brief description of the role goes here.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
|
||||
|
||||
Role Variables
|
||||
--------------
|
||||
|
||||
| Name | Default Value | Description |
|
||||
|-------------------|---------------------|----------------------|
|
||||
| `` | `` | |
|
||||
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
|
||||
|
||||
Example Playbook
|
||||
----------------
|
||||
|
||||
- hosts: all
|
||||
roles:
|
||||
- {{ cookiecutter.galaxy_username }}.{{ cookiecutter.role_name }}
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
{{ cookiecutter.license }}
|
||||
1
{{ cookiecutter.role_name }}/defaults/main.yml
Normal file
1
{{ cookiecutter.role_name }}/defaults/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
0
{{ cookiecutter.role_name }}/files/keep
Normal file
0
{{ cookiecutter.role_name }}/files/keep
Normal file
0
{{ cookiecutter.role_name }}/handlers/main.yml
Normal file
0
{{ cookiecutter.role_name }}/handlers/main.yml
Normal file
17
{{ cookiecutter.role_name }}/meta/main.yml
Normal file
17
{{ cookiecutter.role_name }}/meta/main.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
galaxy_info:
|
||||
role_name: {{ cookiecutter.role_name | lower | replace(' ', '_') }}
|
||||
author: {{ cookiecutter.author }}
|
||||
description: {{ cookiecutter.short_description }}
|
||||
company: {{ cookiecutter.company }}
|
||||
license: {{ cookiecutter.license }}
|
||||
min_ansible_version: {{ cookiecutter.min_ansible_version }}
|
||||
|
||||
platforms:
|
||||
- name: EL
|
||||
versions:
|
||||
- 8
|
||||
|
||||
galaxy_tags:
|
||||
- system
|
||||
|
||||
dependencies: []
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: "Include common"
|
||||
include_role:
|
||||
name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
|
||||
18
{{ cookiecutter.role_name }}/molecule/default/molecule.yml
Normal file
18
{{ cookiecutter.role_name }}/molecule/default/molecule.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
driver:
|
||||
name: docker
|
||||
platforms:
|
||||
- name: {{ cookiecutter.role_name }}-test-${MOLECULE_DISTRO:-almalinux8}
|
||||
image: "cybercinch/docker-${MOLECULE_DISTRO:-almalinux8}-ansible:latest"
|
||||
command: ${MOLECULE_DOCKER_COMMAND:-""}
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||
cgroupns_mode: host
|
||||
privileged: true
|
||||
pre_build_image: true
|
||||
provisioner:
|
||||
name: ansible
|
||||
env:
|
||||
MOLECULE_NO_LOG: true
|
||||
6
{{ cookiecutter.role_name }}/molecule/default/verify.yml
Normal file
6
{{ cookiecutter.role_name }}/molecule/default/verify.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
- name: Verify role
|
||||
hosts: all
|
||||
become: yes
|
||||
gather_facts: no
|
||||
|
||||
tasks: []
|
||||
6
{{ cookiecutter.role_name }}/molecule/requirements.yml
Normal file
6
{{ cookiecutter.role_name }}/molecule/requirements.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
collections:
|
||||
- name: ansible.posix
|
||||
- name: community.general
|
||||
- name: community.docker
|
||||
|
||||
roles: []
|
||||
25
{{ cookiecutter.role_name }}/molecule/yamllint.yml
Normal file
25
{{ cookiecutter.role_name }}/molecule/yamllint.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
extends: default
|
||||
|
||||
ignore: .cache
|
||||
|
||||
rules:
|
||||
braces:
|
||||
max-spaces-inside: 1
|
||||
level: error
|
||||
brackets:
|
||||
max-spaces-inside: 1
|
||||
level: error
|
||||
comments-indentation: disable
|
||||
document-start: disable
|
||||
line-length: disable
|
||||
truthy:
|
||||
allowed-values:
|
||||
- 'yes'
|
||||
- 'on'
|
||||
- 'true'
|
||||
- 'True'
|
||||
- 'no'
|
||||
- 'off'
|
||||
- 'false'
|
||||
- 'False'
|
||||
check-keys: no
|
||||
0
{{ cookiecutter.role_name }}/tasks/main.yml
Normal file
0
{{ cookiecutter.role_name }}/tasks/main.yml
Normal file
0
{{ cookiecutter.role_name }}/templates/keep
Normal file
0
{{ cookiecutter.role_name }}/templates/keep
Normal file
1
{{ cookiecutter.role_name }}/vars/main.yml
Normal file
1
{{ cookiecutter.role_name }}/vars/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user