Version: 0.7.0-rc.109
An Ansible collection for my opinionated development workstation configuration and prototyping Ansible (and non-Ansible) features for other Python packages and Ansible collections.
This collection houses roles, playbooks, and other Ansible content suitable for setting up standardized tooling and settings on development workstations. It also facilitates automated configuration of other systems, like Raspberry Pi servers and cloud instances for training labs or "capture the flag" contests.
The original design was influenced by the blog posts listed below in the See also section by Jonas Hecht and Jeff Geerling.
Development of this collection is supported by a test-driven design that uses
molecule
to test any or all
roles, both locally and driven by GitHub Actions workflows on push
actions.
The operating system distributions supported at this time by the full set of
roles in this collection for molecule
testing are:
- Debian 11 (default distribution)
- Ubuntu 22.04 LTS
The development environment and test infrastructure that invokes molecule
for testing has been tested on the following (in order of most-frequently
to least-frequently used):
- Mac OS X (Darwin) 10.15.7
- Ubuntu 20.04 LTS on Windows Subsystem for Linux v2 (WSL2)
- Kali Linux (Debian 11 experimental, 2022-07-07 release)
- HypriotOS v1.12.3 (Debian 10, w/o
kali_like
role))
To help reduce the amount of time taken by all this testing, some optimization techniques are employed:
-
Local testing during development is done against only Debian 11. Once all tests are passing, the remaining OS distributions can then be selected for further compatibility testing.
-
Testing of all roles except
kali_like
(which requires Debian 11) are done using Raspberry Pi 3 and 4 systems using Hypriot's custom Debian 10 images flashed with a modified version of Hypriot'sflash
program (found in thehypriot
directory. -
GitHub Action testing for release candidates on the
develop
branch and releases on themain
branch are the only ones that test all roles against multiple distributions. When youpush
to a feature branch with a name related to the role you are developing (e.g.,feature/branding
for thedavedittrich.utils.branding
role), only that role is tested against the distribution matrix. This reduces test time by only testing role-specific changes.
All of this comes at a cost, however. There is a lot of
non-DRY repetition of logic,
code, and molecule
configuration settings. Some of the non-DRY aspects of GitHub
Actions workflows could be reduced by refactoring so as to
share workflows.
Some repetition in molecule
configuration and tests has been reduced by
modularity and cross-inclusion of testing code.
https://github.com/davedittrich/utils
Before using this collection, you need to install it with the Ansible Galaxy command-line tool:
ansible-galaxy collection install davedittrich.utils
You can also include it in a requirements.yml
file and install it with
ansible-galaxy collection install -r requirements.yml
, using the format:
---
collections:
- name: davedittrich.utils
Note that if you install the collection from Ansible Galaxy, it will not be upgraded automatically
when you upgrade the ansible
package. To upgrade the collection to the latest available version,
run the following command:
ansible-galaxy collection install davedittrich.utils --upgrade
You can also install a specific version of the collection, for example if you need to downgrade
when something is broken in the latest version (please report an issue in this repository). Use
the following syntax to install version 0.1.0
:
ansible-galaxy collection install davedittrich.utils:==0.1.0
See Using Ansible collections for more details.
Following is a high-level breakdown of tasks performed by role. This is not an exhaustive list of all tasks, but rather a summary of the general topics:
- Install base OS packages necessary for Kali tooling.
- Set up for installing packages from Kali repo.
- Install a specific subset of Kali packages.
- Hush the Kali developer login message.
- Install templated helper scripts for user convenience.
- Set up
~/.local/bin
directories in accounts for local add-on programs. - Pre-configure Kali menus and desktop.
- Set host name based on system serial number.
- Install and configure system for Apache Guacamole (RDP in browser).
- Set custom timezone.
- Make LXDE/
lightdm
default X11 session manager. - Customize LXDE and
lightdm
settings and menus. - Customize display wallpaper, login greeter background, and boot splash images.
- Disable boot logo (e.g., on Raspberry Pi devices.)
- Disable
clipit
history.
- Ensure SSH host key fingerprints are visible on console login screen.
- Ensure Ethernet device and IP addressing information is visible on console login screen.
davedittrich.utils.kdmt
role.
- Swaps Left keyboard CapsLock key with CTRL.
- Disables bell sound for keyboard,
bash
,csh
,ex
family editors,vim
editor and instead sets visible bell. - Enables "natural scrolling" on mouse and trackpad.
- Configures
hid_apple
keyboard devices to use function keys without needingFn
key.
- Ensures
update-dotdee
is installed viapipx
. - Create initial dropin directories with original files appearing at top.
- By default, enabled use of
update-dotdee
to control users'~/.bash_aliases
,~/.bashrc
,~/.gitconfig
, and~/.ssh/config
files.
To reduce redundancy in code across multiple scenarios representing individual
roles in a larger collection, tests, variables, and functions are located in
the molecule/shared
directory.
$ tree molecule/shared
molecule/shared
├── cleanup.yml
├── Dockerfile-debian_bullseye.j2
├── files
│  ├── cmdline.txt
│  ├── config.txt
│  └── Hello_World.jpg
├── __init__.py
├── prepare.yml
├── pytest.ini
├── tasks
│  └── fix_systemctl.yml
└── tests
├── conftest.py
├── helpers
│  └── __init__.py
├── __init__.py
├── test_branding.py
├── test_dropins.py
├── test_ip_in_issue.py
├── test_kali_like.py
├── test_kdmt.py
└── test_shared.py
4 directories, 18 files
The directory molecule/shared/tests/helpers/
contains shared variables and
functions used by the tests (as opposed to using conftest.py
) as seen here:
from helpers import (
ansible_vars,
get_homedir,
skip_unless_role,
)
The verifier
section in files like molecule/default/molecule.yml
are
configured as follows to allow the import to work:
verifier:
name: testinfra
directory: ../shared/tests
env:
PYTHONPATH: "${PWD}/molecule/shared/tests"
#PYTEST_ADDOPTS: "--debug -v -ra --trace-config"
PYTEST_ADDOPTS: "-v -ra"
When debugging exceptions during the verify
stage, you may want to swap the
PYTEST_ADDOPTS
settings.
To further reduce redundancy and hard-coding values in tests, all Ansible
variables that were defined during the converge
phase are dumped to a YAML
file in the molecule
scenario's ephemeral directory so they are available to
tests in the verify
stage. The path to the file for the default
scenario
would be ${HOME}/.config/molecule/utils/default/ansible-vars.yml
.
It is possible to conditionally call pytest.xfail()
based on these variables.
Tests can also be skipped by use of the @skip_unless_role()
decorator, which
checks to see if the role for which they apply is in the ansible_roles_names
variable (meaning that role was applied and thus needs testing).
. . .
ansible_role_names: [davedittrich.utils.ip_in_issue]
. . .
Here is an example with a simple test.
@skip_unless_role('davedittrich.utils.branding')
def test_boot_config(host):
f = host.file('/boot/config.txt')
assert f.exists
assert f.user == 'root'
assert f.group == 'root'
assert r'disable_splash=1' in f.content_string
If the ip_in_issue
scenario was being tested, which only includes the
davedittrich.utils.ip_in_issue
role (as seen in the ansible_role_names
variable above), this particular test would be skipped.
$ make SCENARIO=ip_in_issue test
[+] using 'conda' environment 'utils' and 'psec' environment 'utils'
molecule test --destroy=never -s ip_in_issue
INFO ip_in_issue scenario test matrix: dependency, lint, create, prepare, converge, idempotence, verify
INFO Performing prerun with role_name_check=0...
INFO Set ANSIBLE_LIBRARY=/home/dittrich/.cache/ansible-compat/6fd897/modules:/home/dittrich/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO Set ANSIBLE_COLLECTIONS_PATH=/home/dittrich/.cache/ansible-compat/6fd897/collections:/home/dittrich/.ansible/collections:/usr/share/ansible/collections
INFO Set ANSIBLE_ROLES_PATH=/home/dittrich/.cache/ansible-compat/6fd897/roles:roles:/home/dittrich/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO Running ansible-galaxy collection install -v --force -p /home/dittrich/.cache/ansible-compat/6fd897/collections .
INFO Running ip_in_issue > dependency
. . .
INFO Idempotence completed successfully.
INFO Running ip_in_issue > verify
INFO Executing Testinfra tests found in /home/dittrich/code/davedittrich/utils/molecule/ip_in_issue/../shared/tests/...
/home/dittrich/miniconda3/envs/utils/lib/python3.9/site-packages/molecule/config.py:51: DeprecationWarning: molecule.config.ansible_version is deprecated, will be removed in the future.
warnings.warn(
============================= test session starts ==============================
platform linux -- Python 3.9.13, pytest-7.1.3, pluggy-1.0.0 -- /home/dittrich/miniconda3/envs/utils/bin/python
metadata: {'Python': '3.9.13', 'Platform': 'Linux-5.18.0-kali7-amd64-x86_64-with-glibc2.34', 'Packages': {'pytest': '7.1.3', 'py': '1.11.0', 'pluggy': '1.0.0', 'molecule': '4.0.2.dev19'}, 'Plugins': {'ansible': '2.3.0', 'metadata':
'2.0.2', 'testinfra': '6.8.1.dev4+gd423e29', 'html': '3.1.1', 'molecule': '2.0.1.dev8+g236ac70'}, 'Tools': {'ansible': '2.13.3'}, 'env': 'ANSIBLE_COLLECTIONS_PATH=/home/dittrich/.cache/ansible-compat/6fd897/collections:/home/dittr
ich/.cache/molecule/utils/ip_in_issue/collections:/home/dittrich/.ansible/collections:/usr/share/ansible/collections:/etc/ansible/collections ANSIBLE_CONFIG=/home/dittrich/.cache/molecule/utils/ip_in_issue/ansible.cfg ANSIBLE_FILTE
R_PLUGINS=/home/dittrich/miniconda3/envs/utils/lib/python3.9/site-packages/molecule/provisioner/ansible/plugins/filter:/home/dittrich/.cache/molecule/utils/ip_in_issue/plugins/filter:/home/dittrich/code/davedittrich/utils/plugins/f
ilter:/home/dittrich/.ansible/plugins/filter:/usr/share/ansible/plugins/filter ANSIBLE_FORCE_COLOR=True ANSIBLE_LIBRARY=/home/dittrich/miniconda3/envs/utils/lib/python3.9/site-packages/molecule/provisioner/ansible/plugins/modules:/
home/dittrich/.cache/molecule/utils/ip_in_issue/library:/home/dittrich/code/davedittrich/utils/library:/home/dittrich/.ansible/plugins/modules:/usr/share/ansible/plugins/modules ANSIBLE_ROLES_PATH=/home/dittrich/.cache/ansible-comp
at/6fd897/roles:/home/dittrich/.cache/molecule/utils/ip_in_issue/roles:/home/dittrich/code/davedittrich:/home/dittrich/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles ANSIBLE_VERBOSITY=1 MOLECULE_DEBUG=False MOLECULE_DEP
ENDENCY_NAME=galaxy MOLECULE_DISTRO=debian11 MOLECULE_DRIVER_NAME=docker MOLECULE_ENV_FILE=/home/dittrich/code/davedittrich/utils/.env.yml MOLECULE_EPHEMERAL_DIRECTORY=/home/dittrich/.cache/molecule/utils/ip_in_issue MOLECULE_FILE=
/home/dittrich/.cache/molecule/utils/ip_in_issue/molecule.yml MOLECULE_INSTANCE_CONFIG=/home/dittrich/.cache/molecule/utils/ip_in_issue/instance_config.yml MOLECULE_INVENTORY_FILE=/home/dittrich/.cache/molecule/utils/ip_in_issue/in
ventory/ansible_inventory.yml MOLECULE_PROJECT_DIRECTORY=/home/dittrich/code/davedittrich/utils MOLECULE_PROVISIONER_NAME=ansible MOLECULE_SCENARIO_DIRECTORY=/home/dittrich/code/davedittrich/utils/molecule/ip_in_issue MOLECULE_SCEN
ARIO_NAME=ip_in_issue MOLECULE_STATE_FILE=/home/dittrich/.cache/molecule/utils/ip_in_issue/state.yml MOLECULE_VERIFIER_NAME=testinfra MOLECULE_VERIFIER_TEST_DIRECTORY=/home/dittrich/code/davedittrich/utils/molecule/ip_in_issue/../s
hared/tests '}
ansible: 2.13.3
rootdir: /home/dittrich/code/davedittrich/utils/molecule/shared, configfile: pytest.ini
plugins: ansible-2.3.0, metadata-2.0.2, testinfra-6.8.1.dev4+gd423e29, html-3.1.1, molecule-2.0.1.dev8+g236ac70
collecting ... collected 43 items
molecule/shared/tests/test_branding.py::test_boot_config[ansible:/debian_bullseye] SKIPPED [ 2%]
molecule/shared/tests/test_branding.py::test_boot_cmdline[ansible:/debian_bullseye] SKIPPED [ 4%]
molecule/shared/tests/test_branding.py::test_fbi_package[ansible:/debian_bullseye] SKIPPED [ 6%]
molecule/shared/tests/test_branding.py::test_splashscreen_service[ansible:/debian_bullseye] SKIPPED [ 9%]
molecule/shared/tests/test_branding.py::test_wallpaper_image[ansible:/debian_bullseye] SKIPPED [ 11%]
molecule/shared/tests/test_branding.py::test_x11_session_manager_is_lxde[ansible:/debian_bullseye] SKIPPED [ 13%]
molecule/shared/tests/test_branding.py::test_lightdm_login_background[ansible:/debian_bullseye] SKIPPED [ 16%]
molecule/shared/tests/test_branding.py::test_user_homedir[ansible:/debian_bullseye-user0] SKIPPED [ 18%]
molecule/shared/tests/test_branding.py::test_user_wallpaper_setting[ansible:/debian_bullseye-user0] SKIPPED [ 20%]
molecule/shared/tests/test_branding.py::test_user_LXDE_autostart_xset[ansible:/debian_bullseye-user0] SKIPPED [ 23%]
molecule/shared/tests/test_branding.py::test_config_files[fixture_users0-fixture_config_files0-ansible:/debian_bullseye] SKIPPED [ 25%]
molecule/shared/tests/test_dropins.py::test_etc_profile_d_dotlocal[ansible:/debian_bullseye] SKIPPED [ 27%]
molecule/shared/tests/test_dropins.py::test_bashrc_sources_aliases[fixture_users0-ansible:/debian_bullseye] SKIPPED [ 30%]
molecule/shared/tests/test_dropins.py::test_dropin_files[fixture_users0-fixture_dropin_files0-ansible:/debian_bullseye] SKIPPED [ 32%]
molecule/shared/tests/test_dropins.py::test_dropin_directories[fixture_users0-fixture_dropin_files0-ansible:/debian_bullseye] SKIPPED [ 34%]
molecule/shared/tests/test_dropins.py::test_pipx[fixture_users0-pipx-ansible:/debian_bullseye] SKIPPED [ 37%]
molecule/shared/tests/test_dropins.py::test_pipx[fixture_users0-update-dotdee-ansible:/debian_bullseye] SKIPPED [ 39%]
molecule/shared/tests/test_dropins.py::test_update_dotdee_write_bash_profile[fixture_users0-ansible:/debian_bullseye] SKIPPED [ 41%]
molecule/shared/tests/test_ip_in_issue.py::test_issue_file[ansible:/debian_bullseye] PASSED [ 44%]
molecule/shared/tests/test_ip_in_issue.py::test_issue_d[ansible:/debian_bullseye] PASSED [ 46%]
molecule/shared/tests/test_ip_in_issue.py::test_issue_d_interfaces[ansible:/debian_bullseye] PASSED [ 48%]
molecule/shared/tests/test_ip_in_issue.py::test_issue_d_fingerprints[ansible:/debian_bullseye] PASSED [ 51%]
molecule/shared/tests/test_kali_like.py::test_kali_apt_list[ansible:/debian_bullseye] SKIPPED [ 53%]
molecule/shared/tests/test_kali_like.py::test_script_files[fixture_users0-fixture_helper_script_files0-ansible:/debian_bullseye] SKIPPED [ 55%]
molecule/shared/tests/test_kali_like.py::test_kali_like_packages[fixture_kali_like_packages0-ansible:/debian_bullseye] SKIPPED [ 58%]
molecule/shared/tests/test_kali_like.py::test_gawk[ansible:/debian_bullseye] SKIPPED [ 60%]
molecule/shared/tests/test_kali_like.py::test_kali_application_menu[ansible:/debian_bullseye] SKIPPED [ 62%]
molecule/shared/tests/test_kali_like.py::test_guacamole_guacd[ansible:/debian_bullseye] SKIPPED [ 65%]
molecule/shared/tests/test_kali_like.py::test_guacamole_services[fixture_guac_services0-ansible:/debian_bullseye] SKIPPED [ 67%]
molecule/shared/tests/test_kdmt.py::test_keyboard_config_packages[ansible:/debian_bullseye] SKIPPED [ 69%]
molecule/shared/tests/test_kdmt.py::test_custom_load_xmodmap[ansible:/debian_bullseye] SKIPPED [ 72%]
molecule/shared/tests/test_kdmt.py::test_udev_hwdb_file[ansible:/debian_bullseye] SKIPPED [ 74%]
molecule/shared/tests/test_kdmt.py::test_xkboptions[ansible:/debian_bullseye] SKIPPED [ 76%]
molecule/shared/tests/test_kdmt.py::test_keyboard_configuration[ansible:/debian_bullseye] SKIPPED [ 79%]
molecule/shared/tests/test_kdmt.py::test_hid_apple_conf[ansible:/debian_bullseye] SKIPPED [ 81%]
molecule/shared/tests/test_kdmt.py::test_hid_apple_fnmode[ansible:/debian_bullseye] SKIPPED [ 83%]
molecule/shared/tests/test_kdmt.py::test_hid_apple_iso_layout[ansible:/debian_bullseye] SKIPPED [ 86%]
molecule/shared/tests/test_kdmt.py::test_user_inputrc[ansible:/debian_bullseye-user0] SKIPPED [ 88%]
molecule/shared/tests/test_kdmt.py::test_user_cshrc[ansible:/debian_bullseye-user0] SKIPPED [ 90%]
molecule/shared/tests/test_kdmt.py::test_user_exrc[ansible:/debian_bullseye-user0] SKIPPED [ 93%]
molecule/shared/tests/test_kdmt.py::test_user_vimrc[ansible:/debian_bullseye-user0] SKIPPED [ 95%]
molecule/shared/tests/test_kdmt.py::test_user_xmodmap[ansible:/debian_bullseye-user0] SKIPPED [ 97%]
molecule/shared/tests/test_shared.py::test_shared_skip SKIPPED (forc...) [100%]
=========================== short test summary info ============================
SKIPPED [1] molecule/shared/tests/test_branding.py:16: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:24: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:32: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:37: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:43: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:52: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:60: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:74: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:83: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:106: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_branding.py:148: role davedittrich.utils.branding only
SKIPPED [1] molecule/shared/tests/test_dropins.py:33: role davedittrich.utils.dropins only
SKIPPED [1] molecule/shared/tests/test_dropins.py:41: role davedittrich.utils.dropins only
SKIPPED [1] molecule/shared/tests/test_dropins.py:52: role davedittrich.utils.dropins only
SKIPPED [1] molecule/shared/tests/test_dropins.py:63: role davedittrich.utils.dropins only
SKIPPED [2] molecule/shared/tests/test_dropins.py:75: role davedittrich.utils.dropins only
SKIPPED [1] molecule/shared/tests/test_dropins.py:87: role davedittrich.utils.dropins only
SKIPPED [1] molecule/shared/tests/test_kali_like.py:52: role davedittrich.utils.kali_like only
SKIPPED [1] molecule/shared/tests/test_kali_like.py:61: role davedittrich.utils.kali_like only
SKIPPED [1] molecule/shared/tests/test_kali_like.py:72: role davedittrich.utils.kali_like only
SKIPPED [1] molecule/shared/tests/test_kali_like.py:78: role davedittrich.utils.kali_like only
SKIPPED [1] molecule/shared/tests/test_kali_like.py:85: role davedittrich.utils.kali_like only
SKIPPED [1] molecule/shared/tests/test_kali_like.py:94: role davedittrich.utils.kali_like only
SKIPPED [1] molecule/shared/tests/test_kali_like.py:103: role davedittrich.utils.kali_like only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:16: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:22: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:30: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:39: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:47: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:54: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:64: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:76: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:91: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:118: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:132: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:146: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_kdmt.py:160: role davedittrich.utils.kdmt only
SKIPPED [1] molecule/shared/tests/test_shared.py:6: force skip
======================== 4 passed, 39 skipped in 1.70s =========================
INFO Verifier completed successfully.
[+] all tests succeeded
[+] instance(s) were not destroyed: use 'molecule destroy' or 'molecule reset' manually
. . .
Using the pytest
option -rP
instead, the output from the verify
stage is much
shorter:
$ PYTEST_ADDOPTS="-rP" molecule verify -s ip_in_issue
INFO ip_in_issue scenario test matrix: verify
INFO Performing prerun with role_name_check=0...
INFO Set ANSIBLE_LIBRARY=/home/dittrich/.cache/ansible-compat/6fd897/modules:/home/dittrich/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO Set ANSIBLE_COLLECTIONS_PATH=/home/dittrich/.cache/ansible-compat/6fd897/collections:/home/dittrich/.ansible/collections:/usr/share/ansible/collections
INFO Set ANSIBLE_ROLES_PATH=/home/dittrich/.cache/ansible-compat/6fd897/roles:roles:/home/dittrich/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO Running ansible-galaxy collection install -v --force -p /home/dittrich/.cache/ansible-compat/6fd897/collections .
INFO Running ip_in_issue > verify
INFO Executing Testinfra tests found in /home/dittrich/code/davedittrich/utils/molecule/ip_in_issue/../shared/tests/...
/home/dittrich/miniconda3/envs/utils/lib/python3.9/site-packages/molecule/config.py:51: DeprecationWarning: molecule.config.ansible_version is deprecated, will be removed in the future.
warnings.warn(
============================= test session starts ==============================
platform linux -- Python 3.9.13, pytest-7.1.3, pluggy-1.0.0
ansible: 2.13.3
rootdir: /home/dittrich/code/davedittrich/utils/molecule/shared, configfile: pytest.ini
plugins: ansible-2.3.0, metadata-2.0.2, testinfra-6.8.1.dev4+gd423e29, html-3.1.1, molecule-2.0.1.dev8+g236ac70
collected 43 items
molecule/shared/tests/test_branding.py sssssssssss [ 25%]
molecule/shared/tests/test_dropins.py sssssss [ 41%]
molecule/shared/tests/test_ip_in_issue.py .... [ 51%]
molecule/shared/tests/test_kali_like.py sssssss [ 67%]
molecule/shared/tests/test_kdmt.py sssssssssssss [ 97%]
molecule/shared/tests/test_shared.py s [100%]
==================================== PASSES ====================================
======================== 4 passed, 39 skipped in 1.76s =========================
INFO Verifier completed successfully.
The file containing the Ansible variables from the converge
phase also help
in debugging playbooks. They provide "ground truth" of the Ansible runtime state
and help you identify variables to use in playbooks and tests, or to watch
while running tests in a debugger. (There is a pytest
launch rule for
VSCode defined in the .vscode/launch.json
file.)
To continue on to testing in molecule
, you can manually run molecule verify
. The variables are loaded from the cached file and are available to
tests. This allows you to redefine some variables during development, re-run
molecule converge
to have them take effect, and your tests can then
automatically adjust.
Only when molecule destroy
is run will the file be deleted.
$ molecule destroy -s ip_in_issue
INFO ip_in_issue scenario test matrix: dependency, destroy
INFO Performing prerun with role_name_check=0...
INFO Set ANSIBLE_LIBRARY=/home/dittrich/.cache/ansible-compat/6fd897/modules:/home/dittrich/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO Set ANSIBLE_COLLECTIONS_PATH=/home/dittrich/.cache/ansible-compat/6fd897/collections:/home/dittrich/.ansible/collections:/usr/share/ansible/collections
INFO Set ANSIBLE_ROLES_PATH=/home/dittrich/.cache/ansible-compat/6fd897/roles:roles:/home/dittrich/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO Running ansible-galaxy collection install -v --force -p /home/dittrich/.cache/ansible-compat/6fd897/collections .
INFO Running ip_in_issue > dependency
WARNING Skipping, missing the requirements file.
WARNING Skipping, missing the requirements file.
INFO Running ip_in_issue > destroy
INFO Sanity checks: 'docker'
Using /home/dittrich/.cache/molecule/utils/ip_in_issue/ansible.cfg as config file
PLAY [Destroy] *****************************************************************
TASK [Destroy molecule instance(s)] ********************************************
changed: [localhost] => (item=debian_bullseye) => {"ansible_job_id": "151811718162.2756561", "ansible_loop_var": "item", "changed": true, "finished": 0, "item": {"capabilities": ["SYS_ADMIN"], "dockerfile": "../shared/Dockerfile-debian_bullseye.j2", "image": "debian:bullseye", "name": "debian_bullseye", "override_command": false, "privileged": true, "security_opts": ["seccomp=unconfined"], "tmpfs": ["/run", "/run/lock", "/tmp"]}, "results_file": "/home/dittrich/.ansible_async/151811718162.2756561", "started": 1}
TASK [Wait for instance(s) deletion to complete] *******************************
FAILED - RETRYING: [localhost]: Wait for instance(s) deletion to complete (300 retries left).
changed: [localhost] => (item=debian_bullseye) => {"ansible_job_id": "151811718162.2756561", "ansible_loop_var": "item", "attempts": 2, "changed": true, "finished": 1, "item": {"ansible_job_id": "151811718162.2756561", "ansible_loop_var": "item", "changed": true, "failed": 0, "finished": 0, "item": {"capabilities": ["SYS_ADMIN"], "dockerfile": "../shared/Dockerfile-debian_bullseye.j2", "image": "debian:bullseye", "name": "debian_bullseye", "override_command": false, "privileged": true, "security_opts": ["seccomp=unconfined"], "tmpfs": ["/run", "/run/lock", "/tmp"]}, "results_file": "/home/dittrich/.ansible_async/151811718162.2756561", "started": 1}, "results_file": "/home/dittrich/.ansible_async/151811718162.2756561", "started": 1, "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
TASK [Delete docker networks(s)] ***********************************************
PLAY RECAP *********************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
INFO Pruning extra files from scenario ephemeral directory
You can see the defined scenarios and state information about related instances
with molecule list
:
$ molecule list
INFO Running branding > list
INFO Running default > list
INFO Running delegated > list
INFO Running dropins > list
INFO Running ip_in_issue > list
INFO Running kali_like > list
INFO Running kdmt > list
â•· â•· â•· â•· â•·
Instance Name │ Driver Name │ Provisioner Name │ Scenario Name │ Created │ Converged
╶─────────────────┼─────────────┼──────────────────┼───────────────┼─────────┼───────────╴
debian_bullseye │ docker │ ansible │ branding │ false │ false
debian_bullseye │ docker │ ansible │ default │ true │ false
delegated-host │ delegated │ ansible │ delegated │ unknown │ false
debian_bullseye │ docker │ ansible │ dropins │ false │ false
debian_bullseye │ docker │ ansible │ ip_in_issue │ false │ false
debian_bullseye │ docker │ ansible │ kali_like │ false │ false
debian_bullseye │ docker │ ansible │ kdmt │ false │ false
╵ ╵ ╵ ╵ ╵
When using the delegated
scenario--in this case against a Raspberry Pi with users
root
and pirate
--all of the roles and their associated tests for all users
will be applied:
$ make SCENARIO=delegated verify
molecule verify -s delegated
INFO delegated scenario test matrix: verify
INFO Performing prerun...
INFO Guessed /Users/dittrich/git/davedittrich/utils as project root directory
INFO Added ANSIBLE_LIBRARY=plugins/modules
INFO Added ANSIBLE_COLLECTIONS_PATH=/Users/dittrich/.cache/ansible-lint/6dd05e/collections
INFO Added ANSIBLE_ROLES_PATH=~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:roles
INFO Running delegated > verify
INFO Executing Testinfra tests found in /Users/dittrich/git/davedittrich/utils/molecule/delegated/../shared/tests/...
============================= test session starts ==============================
platform darwin -- Python 3.9.5, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /usr/local/Caskroom/miniconda/base/envs/ansible/bin/python
metadata: {'Python': '3.9.5', 'Platform': 'macOS-10.14.6-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.4', 'py': '1.10.0', 'pluggy':
'0.13.1'}, 'Plugins': {'cov': '2.12.1', 'metadata': '1.11.0', 'helpers-namespace': '0.0.0', 'xdist': '2.3.0', 'html': '3.1.1', 'mock':
'3.6.1', 'plus': '0.2', 'verbose-parametrize': '1.7.0', 'forked': '1.3.0', 'testinfra': '6.4.0'}}
rootdir: /Users/dittrich
plugins: cov-2.12.1, metadata-1.11.0, helpers-namespace-0.0.0, xdist-2.3.0, html-3.1.1, mock-3.6.1, plus-0.2, verbose-parametrize-1.7.0,
forked-1.3.0, testinfra-6.4.0
collecting ... collected 106 items
molecule/shared/tests/test_branding.py::test_boot_config[ansible:/delegated-host] PASSED [ 0%]
molecule/shared/tests/test_branding.py::test_boot_cmdline[ansible:/delegated-host] PASSED [ 1%]
molecule/shared/tests/test_branding.py::test_fbi_package[ansible:/delegated-host] PASSED [ 2%]
molecule/shared/tests/test_branding.py::test_splashscreen_service[ansible:/delegated-host] PASSED [ 3%]
molecule/shared/tests/test_branding.py::test_user_homedir[ansible:/delegated-host-root] PASSED [ 4%]
molecule/shared/tests/test_branding.py::test_user_homedir[ansible:/delegated-host-pirate] PASSED [ 5%]
molecule/shared/tests/test_branding.py::test_x11_session_manager_is_lxde[ansible:/delegated-host] PASSED [ 6%]
molecule/shared/tests/test_branding.py::test_wallpaper_image[ansible:/delegated-host] PASSED [ 7%]
molecule/shared/tests/test_branding.py::test_user_wallpaper_setting[ansible:/delegated-host-root] XFAIL [ 8%]
molecule/shared/tests/test_branding.py::test_user_wallpaper_setting[ansible:/delegated-host-pirate] XFAIL [ 9%]
molecule/shared/tests/test_branding.py::test_lightdm_login_background[ansible:/delegated-host] PASSED [ 10%]
molecule/shared/tests/test_branding.py::test_config_files[root-user-dirs.dirs.j20-ansible:/delegated-host] PASSED [ 11%]
molecule/shared/tests/test_branding.py::test_config_files[root-user-dirs.locale.j20-ansible:/delegated-host] PASSED [ 12%]
molecule/shared/tests/test_branding.py::test_config_files[root-gtk-3.0/bookmarks.j20-ansible:/delegated-host] PASSED [ 13%]
molecule/shared/tests/test_branding.py::test_config_files[root-qt5ct/qt5ct.conf.j20-ansible:/delegated-host] PASSED [ 14%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxterminal/lxterminal.conf.j20-ansible:/delegated-host] PASSED [ 15%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxsession/LXDE/desktop.conf.j20-ansible:/delegated-host] PASSED [ 16%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxsession/LXDE/autostart.j20-ansible:/delegated-host] PASSED [ 16%]
molecule/shared/tests/test_branding.py::test_config_files[root-pcmanfm/LXDE/desktop-items-0.conf.j20-ansible:/delegated-host] PASSED [ 17%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxpanel/launchtaskbar.cfg.j20-ansible:/delegated-host] PASSED [ 18%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxpanel/LXDE/panels/panel.j20-ansible:/delegated-host] PASSED [ 19%]
molecule/shared/tests/test_branding.py::test_config_files[root-openbox/lxde-rc.xml.j20-ansible:/delegated-host] PASSED [ 20%]
molecule/shared/tests/test_branding.py::test_config_files[root-clipit/disabled.j20-ansible:/delegated-host] PASSED [ 21%]
molecule/shared/tests/test_branding.py::test_config_files[root-libfm/libfm.conf.j20-ansible:/delegated-host] PASSED [ 22%]
molecule/shared/tests/test_branding.py::test_config_files[root-user-dirs.dirs.j21-ansible:/delegated-host] PASSED [ 23%]
molecule/shared/tests/test_branding.py::test_config_files[root-user-dirs.locale.j21-ansible:/delegated-host] PASSED [ 24%]
molecule/shared/tests/test_branding.py::test_config_files[root-gtk-3.0/bookmarks.j21-ansible:/delegated-host] PASSED [ 25%]
molecule/shared/tests/test_branding.py::test_config_files[root-qt5ct/qt5ct.conf.j21-ansible:/delegated-host] PASSED [ 26%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxterminal/lxterminal.conf.j21-ansible:/delegated-host] PASSED [ 27%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxsession/LXDE/desktop.conf.j21-ansible:/delegated-host] PASSED [ 28%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxsession/LXDE/autostart.j21-ansible:/delegated-host] PASSED [ 29%]
molecule/shared/tests/test_branding.py::test_config_files[root-pcmanfm/LXDE/desktop-items-0.conf.j21-ansible:/delegated-host] PASSED [ 30%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxpanel/launchtaskbar.cfg.j21-ansible:/delegated-host] PASSED [ 31%]
molecule/shared/tests/test_branding.py::test_config_files[root-lxpanel/LXDE/panels/panel.j21-ansible:/delegated-host] PASSED [ 32%]
molecule/shared/tests/test_branding.py::test_config_files[root-openbox/lxde-rc.xml.j21-ansible:/delegated-host] PASSED [ 33%]
molecule/shared/tests/test_branding.py::test_config_files[root-clipit/disabled.j21-ansible:/delegated-host] PASSED [ 33%]
molecule/shared/tests/test_branding.py::test_config_files[root-libfm/libfm.conf.j21-ansible:/delegated-host] PASSED [ 34%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-user-dirs.dirs.j20-ansible:/delegated-host] PASSED [ 35%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-user-dirs.locale.j20-ansible:/delegated-host] PASSED [ 36%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-gtk-3.0/bookmarks.j20-ansible:/delegated-host] PASSED [ 37%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-qt5ct/qt5ct.conf.j20-ansible:/delegated-host] PASSED [ 38%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxterminal/lxterminal.conf.j20-ansible:/delegated-host] PASSED [ 39%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxsession/LXDE/desktop.conf.j20-ansible:/delegated-host] PASSED [ 40%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxsession/LXDE/autostart.j20-ansible:/delegated-host] PASSED [ 41%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-pcmanfm/LXDE/desktop-items-0.conf.j20-ansible:/delegated-host] PASSED [ 42%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxpanel/launchtaskbar.cfg.j20-ansible:/delegated-host] PASSED [ 43%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxpanel/LXDE/panels/panel.j20-ansible:/delegated-host] PASSED [ 44%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-openbox/lxde-rc.xml.j20-ansible:/delegated-host] PASSED [ 45%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-clipit/disabled.j20-ansible:/delegated-host] PASSED [ 46%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-libfm/libfm.conf.j20-ansible:/delegated-host] PASSED [ 47%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-user-dirs.dirs.j21-ansible:/delegated-host] PASSED [ 48%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-user-dirs.locale.j21-ansible:/delegated-host] PASSED [ 49%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-gtk-3.0/bookmarks.j21-ansible:/delegated-host] PASSED [ 50%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-qt5ct/qt5ct.conf.j21-ansible:/delegated-host] PASSED [ 50%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxterminal/lxterminal.conf.j21-ansible:/delegated-host] PASSED [ 51%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxsession/LXDE/desktop.conf.j21-ansible:/delegated-host] PASSED [ 52%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxsession/LXDE/autostart.j21-ansible:/delegated-host] PASSED [ 53%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-pcmanfm/LXDE/desktop-items-0.conf.j21-ansible:/delegated-host] PASSED [ 54%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxpanel/launchtaskbar.cfg.j21-ansible:/delegated-host] PASSED [ 55%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-lxpanel/LXDE/panels/panel.j21-ansible:/delegated-host] PASSED [ 56%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-openbox/lxde-rc.xml.j21-ansible:/delegated-host] PASSED [ 57%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-clipit/disabled.j21-ansible:/delegated-host] PASSED [ 58%]
molecule/shared/tests/test_branding.py::test_config_files[pirate-libfm/libfm.conf.j21-ansible:/delegated-host] PASSED [ 59%]
molecule/shared/tests/test_dropins.py::test_bashrc_sources_aliases[root-ansible:/delegated-host] PASSED [ 60%]
molecule/shared/tests/test_dropins.py::test_bashrc_sources_aliases[pirate-ansible:/delegated-host] PASSED [ 61%]
molecule/shared/tests/test_dropins.py::test_dropin_files[root-.bash_profile-ansible:/delegated-host] PASSED [ 62%]
molecule/shared/tests/test_dropins.py::test_dropin_files[root-.bash_aliases-ansible:/delegated-host] PASSED [ 63%]
molecule/shared/tests/test_dropins.py::test_dropin_files[root-.gitconfig-ansible:/delegated-host] PASSED [ 64%]
molecule/shared/tests/test_dropins.py::test_dropin_files[root-.ssh/config-ansible:/delegated-host] PASSED [ 65%]
molecule/shared/tests/test_dropins.py::test_dropin_files[pirate-.bash_profile-ansible:/delegated-host] PASSED [ 66%]
molecule/shared/tests/test_dropins.py::test_dropin_files[pirate-.bash_aliases-ansible:/delegated-host] PASSED [ 66%]
molecule/shared/tests/test_dropins.py::test_dropin_files[pirate-.gitconfig-ansible:/delegated-host] PASSED [ 67%]
molecule/shared/tests/test_dropins.py::test_dropin_files[pirate-.ssh/config-ansible:/delegated-host] PASSED [ 68%]
molecule/shared/tests/test_dropins.py::test_dropin_directories[root-.bash_profile-ansible:/delegated-host] PASSED [ 69%]
molecule/shared/tests/test_dropins.py::test_dropin_directories[root-.bash_aliases-ansible:/delegated-host] PASSED [ 70%]
molecule/shared/tests/test_dropins.py::test_dropin_directories[root-.gitconfig-ansible:/delegated-host] PASSED [ 71%]
molecule/shared/tests/test_dropins.py::test_dropin_directories[root-.ssh/config-ansible:/delegated-host] PASSED [ 72%]
molecule/shared/tests/test_dropins.py::test_dropin_directories[pirate-.bash_profile-ansible:/delegated-host] PASSED [ 73%]
molecule/shared/tests/test_dropins.py::test_dropin_directories[pirate-.bash_aliases-ansible:/delegated-host] PASSED [ 74%]
molecule/shared/tests/test_dropins.py::test_dropin_directories[pirate-.gitconfig-ansible:/delegated-host] PASSED [ 75%]
molecule/shared/tests/test_dropins.py::test_dropin_directories[pirate-.ssh/config-ansible:/delegated-host] PASSED [ 76%]
molecule/shared/tests/test_dropins.py::test_pipx[root-pipx-ansible:/delegated-host] PASSED [ 77%]
molecule/shared/tests/test_dropins.py::test_pipx[root-update-dotdee-ansible:/delegated-host] PASSED [ 78%]
molecule/shared/tests/test_dropins.py::test_pipx[pirate-pipx-ansible:/delegated-host] PASSED [ 79%]
molecule/shared/tests/test_dropins.py::test_pipx[pirate-update-dotdee-ansible:/delegated-host] PASSED [ 80%]
molecule/shared/tests/test_dropins.py::test_update_dotdee_write_bash_profile[root-ansible:/delegated-host] PASSED [ 81%]
molecule/shared/tests/test_dropins.py::test_update_dotdee_write_bash_profile[pirate-ansible:/delegated-host] PASSED [ 82%]
molecule/shared/tests/test_ip_in_issue.py::test_issue_file[ansible:/delegated-host] PASSED [ 83%]
molecule/shared/tests/test_ip_in_issue.py::test_issue_d[ansible:/delegated-host] PASSED [ 83%]
molecule/shared/tests/test_ip_in_issue.py::test_issue_d_interfaces[ansible:/delegated-host] PASSED [ 84%]
molecule/shared/tests/test_ip_in_issue.py::test_issue_d_fingerprints[ansible:/delegated-host] PASSED [ 85%]
molecule/shared/tests/test_shared.py::test_shared_skip SKIPPED (forc...) [ 86%]
molecule/shared/tests/test_swapcapslockctrl.py::test_udev_package[ansible:/delegated-host] PASSED [ 87%]
molecule/shared/tests/test_swapcapslockctrl.py::test_udev_hwdb_file[ansible:/delegated-host] PASSED [ 88%]
molecule/shared/tests/test_swapcapslockctrl.py::test_xkboptions[ansible:/delegated-host] PASSED [ 89%]
molecule/shared/tests/test_swapcapslockctrl.py::test_keyboard_configuration[ansible:/delegated-host] PASSED [ 90%]
molecule/shared/tests/test_swapcapslockctrl.py::test_inputrc[ansible:/delegated-host-root] PASSED [ 91%]
molecule/shared/tests/test_swapcapslockctrl.py::test_inputrc[ansible:/delegated-host-pirate] PASSED [ 92%]
molecule/shared/tests/test_swapcapslockctrl.py::test_bashrc[ansible:/delegated-host-root] PASSED [ 93%]
molecule/shared/tests/test_swapcapslockctrl.py::test_bashrc[ansible:/delegated-host-pirate] PASSED [ 94%]
molecule/shared/tests/test_swapcapslockctrl.py::test_cshrc[ansible:/delegated-host-root] PASSED [ 95%]
molecule/shared/tests/test_swapcapslockctrl.py::test_cshrc[ansible:/delegated-host-pirate] PASSED [ 96%]
molecule/shared/tests/test_swapcapslockctrl.py::test_exrc[ansible:/delegated-host-root] PASSED [ 97%]
molecule/shared/tests/test_swapcapslockctrl.py::test_exrc[ansible:/delegated-host-pirate] PASSED [ 98%]
molecule/shared/tests/test_swapcapslockctrl.py::test_vimrc[ansible:/delegated-host-root] PASSED [ 99%]
molecule/shared/tests/test_swapcapslockctrl.py::test_vimrc[ansible:/delegated-host-pirate] PASSED [100%]
============ 103 passed, 1 skipped, 2 xfailed in 116.30s (0:01:56) =============
INFO Verifier completed successfully.
Several environment variables in the molecule.yml
files that allow you to control the amount
of output that is produced. These are:
ANSIBLE_VERBOSITY
- Controls verbosity ofansible-playbook
,ansible-lint
, andpipdeptree
output. Set to a numeric value corresponding to output level (default0
).ANSIBLE_FORCE_COLOR
- Set tofalse
to disable color output fromansible-playbook
.
If you are producing collection artifacts for testing on delegated hosts, such as a Raspberry Pi or cloud instance, you will want to bump the version number when building artifacts.
Doing a make build
will first do bumpversion build
so each new
artifact will have a unique build
version number component for the
artifact and its constituent files.
$ cat VERSION
0.6.0
$ bumpversion build
$ git diff VERSION
diff --git a/VERSION b/VERSION
index a918a2a..758efdb 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.6.0
+0.6.0.1
These artifacts will work for testing by manually loading them, but
they will not be published when you push to GitHub. The GitHub Actions
workflows will only run molecule
tests, which is necessary before
any artifacts can be published via the GitHub Actions workflows.
Of course you can always manually publish the last built artifact
using make publish
if need be.
When you are preparing to publish a release candidate, specify the current
version number and manually set a new version number with the -rc
pre-release
identifier like this:
$ bumpversion --current-version 0.6.0.1 --new-version 0.6.1-rc.1 build
$ git diff VERSION
diff --git a/VERSION b/VERSION
index a918a2a..2f12cd4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.6.0
+0.6.1-rc.1
When you push to the develop
branch with a tag containing the 0.6.1-rc.1
identifier, it will be published to the Ansible Galaxy development server.
As long as you are continuing to iterate, just keep doing make build
and
the release candidate number will increment:
$ bumpversion build
$ git diff VERSION
diff --git a/VERSION b/VERSION
index a918a2a..2f12cd4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.6.0
+0.6.1-rc.2
When you are satisfied that all tests work on your development servers and GitHub, you are ready to publish a full "production" release artifact.
To do that, you need to do two things:
-
Manually remove the
-rc.N
components from the version number by doing the opposite of what was done above, and -
Tag the commit with the new version number (in this case,
0.6.1
) on themain
branch and the GitHub Actions workflow will publish it to the main Ansible Galaxy server.
Again, do frequent make test
runs whenever making significant changes beyond
bumping version numbers and updating release history. Each push to GitHub
before pushing the tags will run tests as well, reassuring you that the
published artifacts will work.
This repo is set up assuming miniconda
is installed for two reasons:
-
It allows you to avoid conflicts with your system's
python
installation by using virtual environments for managing yourpython
executable and manage packages in itssite-packages
directory, and -
It sets environment variables automatically when activating virtual environments. This allows you to associate the
python-secrets
environment you will be using for storing configuration variables, secrets like API keys and passwords, and storing temporary files that contain secrets (e.g., a Raspberry Picloud-config
file).
Create your virtual environment. For this example, the name utils
is used.
$ conda create -n utils python=3.9
Set environment variables for python-secrets
to use for finding where your
secrets will be stored and which environment identifier to use.
$ conda env config vars set D2_SECRETS_BASEDIR=~/.secrets D2_ENVIRONMENT=utils CLIFF_FIT_WIDTH=1
To make your changes take effect please reactivate your environment
Follow the guidance the first time you do this to get these environment variables set. When the values change, you will be notified of this fact.
To see what variables are set by conda
on activation, do:
$ conda env config vars list
D2_SECRETS_BASEDIR = /home/dittrich/.secrets
D2_ENVIRONMENT = utils
CLIFF_FIT_WIDTH = 1
When developing and testing your new roles, you may find that some Ansible plays cause idempotence tests to fail. Here are some of the causes and solutions.
-
More than one role may attempt to manage the same file in the file system. This can cause problems when one play copies or templates an entire file, while another uses
ansible.builtin.blockinfile
oransible.builtin.lineinfile
. This can cause the file contents to change back and forth. Closely examine the plays that fail idempotence tests to see what file the change and how. You may need to change the order of the roles, change the way the file contents are modified, change the markers inblockinfile
plays to be more unique. -
Idempotence failures can also be caused by changes in file metadata rather than contents. The most common reason for this is different
mode
values in two or more plays that manage the same file. This can result in the mode changing back and forth between the different values, even when the content remains exactly the same. Pay attention tomode
andgroup
settings. You may get warnings fromansible-lint
that a newly created file may end up with insecure settings. Usemolecule converge
to get all the plays to run, followed bymolecule login
to log into the instance to check file contents and/or file system metadata. Runningmolecule verify
will run the tests again to debug your plays. -
"FOSS-rot". Yes, I said it. Like most popular open source projects, anything you write for or with Ansible will, after a few months, simply fail because of breaking changes in Ansible, community collections and roles, and related software like
molecule
,testinfra
, and Docker is also part of this particular problem.I hadn't touched this collection in many months and when I came back to it to continue developing I got several failures in what previously was working fine. By pinning some packages to attempt to maintain stability, deprecations and non-backward compatible changes and newly set minimum versions above those being pinned resulted in breakages. This included operating system distributions reaching "end-of-life" status.
I rat-holed for days trying to get Debian 10 to run
systemd
processes in Docker to install Kali Linux packages, which failed duringapt-get install
because of a change inperl-base
andlibc6
that resulted in a dynamic library that was refactored out of a dependent package toperl-base
(whichdpkg
uses to complete installation of packages, breaking the installation entirely in a way that requires manually re-inserting the missing dynamic library and using APT's--fix-broken
flag to recover!After giving up on that and just moving to Debian 11 (which Kali Linux now uses), I ran into a cluster of issues with incompatible versions of
ansible
,ansible-core
,ansible-lint
,ansible-compat
, andpytest
plugins fortestinfra
andansible
. They interact in very complex ways that are extremely difficult to debug.-
molecule
usesansible-compat
(behind the scenes, mind you) to runansible-playbook
,ansible-galaxy
,ansible
, linters, andpytest
. -
pytest
, in turn, also runsansible
as well astestinfra
(in my case) for testing. But wait, there's more! -
testinfra
runsdocker
, in which the Ansible collection is installed and tested.
I ended up having to get
pytest
testing working under VSCode, single-step through process execution to see data structures at runtime, and forking 5 repositories in which I fixed bugs in order to achieve enough stability to finally get everything working and the collection testable on a Raspberry Pi.Sigh. (At least everything seems to be stable again. For now...)
-
- Test-driven infrastructure development with Ansible & Molecule, by Jonas Hecht, December 4, 2018
- Continuous Infrastructure with Ansible, Molecule & TravisCI, by Jonas Hecht, December 11, 2018
- Make your Ansible Playbooks flexible, maintainable, and scalable, by Jeff Geerling, September 28, 2018
- Testing Ansible automation with molecule, by Peter Gustafsson, March 4, 2019
- Question: accessing values of variables as they are being used for provisioning an instance inside Testinfra tests #151, April 5, 2016
- Using Ansible Molecule to test roles in monorepo, by Maria Kotlyarevskaya, Mar 13, 2021
test infra
modules- Advanced
bumpversion
examples - Five Ansible Techniques I Wish I'd Known Sooner, by zwischenzugs, August 27, 2021
- Mastering Molecule, by Sorin Sbarnea, January 1, 2019
See the changelog.
We follow the Ansible Code of Conduct in all our interactions within this project.
If you encounter abusive behavior, please refer to the policy violations section of the Code for information on how to raise a complaint.
Apache 2.0 License
See LICENSE to see the full text.
Dave Dittrich < dave.dittrich@gmail.com > (https://github.com/davedittrich/utils)