{"id":14984563,"url":"https://github.com/rhythmictech/ansible-role-molecule-demo","last_synced_at":"2025-04-10T21:20:47.285Z","repository":{"id":46814850,"uuid":"203638626","full_name":"rhythmictech/ansible-role-molecule-demo","owner":"rhythmictech","description":"A Hello-World Ansible role to demonstrate the power of Molecule","archived":false,"fork":false,"pushed_at":"2023-01-24T23:22:58.000Z","size":28,"stargazers_count":12,"open_issues_count":1,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-24T18:49:37.654Z","etag":null,"topics":["ansible","ansible-roles","asciicast","ec2","molecule","molecule-demo","rad","vagrant"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rhythmictech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-08-21T18:05:13.000Z","updated_at":"2023-07-30T12:18:47.000Z","dependencies_parsed_at":"2023-02-14T02:31:09.947Z","dependency_job_id":null,"html_url":"https://github.com/rhythmictech/ansible-role-molecule-demo","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhythmictech%2Fansible-role-molecule-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhythmictech%2Fansible-role-molecule-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhythmictech%2Fansible-role-molecule-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhythmictech%2Fansible-role-molecule-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rhythmictech","download_url":"https://codeload.github.com/rhythmictech/ansible-role-molecule-demo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248298871,"owners_count":21080419,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","ansible-roles","asciicast","ec2","molecule","molecule-demo","rad","vagrant"],"created_at":"2024-09-24T14:09:16.535Z","updated_at":"2025-04-10T21:20:47.257Z","avatar_url":"https://github.com/rhythmictech.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# molecule_demo\n[![](https://github.com/rhythmictech/ansible-role-molecule-demo/workflows/Molecule%20Test/badge.svg)](https://github.com/rhythmictech/ansible-role-molecule-demo/actions)\n\n\nA \"role\" to demonstrate the power of [Ansible Molecule](https://molecule.readthedocs.io/en/stable/)\n\n\n## About \nMolecule is pretty rad, so rad that [Jeff Geerling is adopting it](https://www.jeffgeerling.com/blog/2018/testing-your-ansible-roles-molecule). \nIt helps you develop Ansible roles by providing out of the box:\n- linting with `yamlint`\n- syntax checking with `ansible-lint`\n- test \"scenarios\" on `docker`, `vagrant`, `ec2`, and friends\n- infrastructure testing with `testinfra`\n- idempotence tests\n- side effect tests\n- a fuller head of hair \n\n## Overview \nHere, we'll \n- Install Ansible Molecule \n- Create an [Ansible Role](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html)\n- Run molecule's suite of tests\n- Create new [scenarios](https://molecule.readthedocs.io/en/stable/getting-started.html#molecule-scenarios), Including \n    - testing in docker (the default)\n    - testing in vagrant \n    - testing in ec2\n\nWatch a tutorial on [asciicast](https://asciinema.org/a/7r1fPy0wIZPh0Jsp1Xj2tdYTQ)\n\n[![asciicast](https://asciinema.org/a/7r1fPy0wIZPh0Jsp1Xj2tdYTQ.svg)](https://asciinema.org/a/7r1fPy0wIZPh0Jsp1Xj2tdYTQ)\n\n## Getting Started\n\n### Requirements\nThe main requirements are documented in `requirements.txt` but this demo assumes you have a few other things installed including\n- `docker`\n- `vagrant`\n- `aws` cli \n\nPractice safe python. Create a `virtualenv`.\n```\nvirtualenv venv --python=python3.7\n```\n\nInstall the python requirements\n```\npip install -r requirements.txt\n```\n\n### Make sure Molecule is installed \n```\n$ molecule --help\nUsage: molecule [OPTIONS] COMMAND [ARGS]...\n\n   _____     _             _\n  |     |___| |___ ___ _ _| |___\n  | | | | . | | -_|  _| | | | -_|\n  |_|_|_|___|_|___|___|___|_|___|\n\n  Molecule aids in the development and testing of Ansible roles.\n\n  Enable autocomplete issue:\n\n    eval \"$(_MOLECULE_COMPLETE=source molecule)\"\n\nOptions:\n  --debug / --no-debug    Enable or disable debug mode. Default is disabled.\n  -c, --base-config TEXT  Path to a base config.  If provided Molecule will\n                          load this config first, and deep merge each\n                          scenario's molecule.yml on top.\n                          (/Users/sblack/.config/molecule/config.yml)\n  -e, --env-file TEXT     The file to read variables from when rendering\n                          molecule.yml. (.env.yml)\n  --version               Show the version and exit.\n  --help                  Show this message and exit.\n\nCommands:\n  check        Use the provisioner to perform a Dry-Run...\n  cleanup      Use the provisioner to cleanup any changes...\n  converge     Use the provisioner to configure instances...\n  create       Use the provisioner to start the instances.\n  dependency   Manage the role's dependencies.\n  destroy      Use the provisioner to destroy the instances.\n  idempotence  Use the provisioner to configure the...\n  init         Initialize a new role or scenario.\n  lint         Lint the role.\n  list         Lists status of instances.\n  login        Log in to one instance.\n  matrix       List matrix of steps used to test instances.\n  prepare      Use the provisioner to prepare the instances...\n  side-effect  Use the provisioner to perform side-effects...\n  syntax       Use the provisioner to syntax check the role.\n  test         Test (lint, destroy, dependency, syntax,...\n  verify       Run automated tests against instances.\n  ```\n\n### Create the role \nMuch like `ansible-galaxy init` molecule provides a nice template for new roles. \n```\n$ molecule init role -r molecule_demo\n--\u003e Initializing new role molecule_demo...\nInitialized role in /Users/sblack/Git/rhythmic/molecule_demo successfully.\n```\n\n### Run ALL the tests \n```\n$ molecule test\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/molecule.yml.\nValidation completed successfully.\n--\u003e Test matrix\n    \n└── default\n    ├── lint\n    ├── cleanup\n    ├── destroy\n    ├── dependency\n    ├── syntax\n    ├── create\n    ├── prepare\n    ├── converge\n    ├── idempotence\n    ├── side_effect\n    ├── verify\n    ├── cleanup\n    └── destroy\n    \n--\u003e Scenario: 'default'\n--\u003e Action: 'lint'\n--\u003e Executing Yamllint on files found in /Users/sblack/Git/rhythmic/molecule_demo/...\nLint completed successfully.\n--\u003e Executing Flake8 on files found in /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/tests/...\nLint completed successfully.\n--\u003e Executing Ansible Lint on /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/playbook.yml...\nLint completed successfully.\n--\u003e Scenario: 'default'\n--\u003e Action: 'cleanup'\nSkipping, cleanup playbook not configured.\n--\u003e Scenario: 'default'\n--\u003e Action: 'destroy'\n    \n    PLAY [Destroy] *****************************************************************\n    \n    TASK [Destroy molecule instance(s)] ********************************************\n    changed: [localhost] =\u003e (item=None)\n    changed: [localhost]\n    \n    TASK [Wait for instance(s) deletion to complete] *******************************\n    FAILED - RETRYING: Wait for instance(s) deletion to complete (300 retries left).\n    ok: [localhost] =\u003e (item=None)\n    ok: [localhost]\n    \n    TASK [Delete docker network(s)] ************************************************\n    \n    PLAY RECAP *********************************************************************\n    localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0\n    \n    \n--\u003e Scenario: 'default'\n--\u003e Action: 'dependency'\nSkipping, missing the requirements file.\n--\u003e Scenario: 'default'\n--\u003e Action: 'syntax'\n    \n    playbook: /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/playbook.yml\n    \n--\u003e Scenario: 'default'\n--\u003e Action: 'create'\n[DEPRECATION WARNING]: docker_image_facts is kept for backwards compatibility \nbut usage is discouraged. The module documentation details page may explain \nmore about this rationale.. This feature will be removed in a future release. \nDeprecation warnings can be disabled by setting deprecation_warnings=False in \nansible.cfg.\n    \n    PLAY [Create] ******************************************************************\n    \n    TASK [Log into a Docker registry] **********************************************\n    skipping: [localhost] =\u003e (item=None) \n    \n    TASK [Create Dockerfiles from image names] *************************************\n    changed: [localhost] =\u003e (item=None)\n    changed: [localhost]\n    \n    TASK [Discover local Docker images] ********************************************\n    ok: [localhost] =\u003e (item=None)\n    ok: [localhost]\n    \n    TASK [Build an Ansible compatible image] ***************************************\n    ok: [localhost] =\u003e (item=None)\n    ok: [localhost]\n    \n    TASK [Create docker network(s)] ************************************************\n    \n    TASK [Determine the CMD directives] ********************************************\n    ok: [localhost] =\u003e (item=None)\n    ok: [localhost]\n    \n    TASK [Create molecule instance(s)] *********************************************\n    changed: [localhost] =\u003e (item=None)\n    changed: [localhost]\n    \n    TASK [Wait for instance(s) creation to complete] *******************************\n    FAILED - RETRYING: Wait for instance(s) creation to complete (300 retries left).\n    changed: [localhost] =\u003e (item=None)\n    changed: [localhost]\n    \n    PLAY RECAP *********************************************************************\n    localhost                  : ok=6    changed=3    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0\n    \n    \n--\u003e Scenario: 'default'\n--\u003e Action: 'prepare'\nSkipping, prepare playbook not configured.\n--\u003e Scenario: 'default'\n--\u003e Action: 'converge'\n    \n    PLAY [Converge] ****************************************************************\n    \n    TASK [Gathering Facts] *********************************************************\n    ok: [instance]\n    \n    TASK [molecule_demo : echo hello world] ****************************************\n    ok: [instance] =\u003e {\n        \"msg\": \"hello world\"\n    }\n    \n    PLAY RECAP *********************************************************************\n    instance                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0\n    \n    \n--\u003e Scenario: 'default'\n--\u003e Action: 'idempotence'\nIdempotence completed successfully.\n--\u003e Scenario: 'default'\n--\u003e Action: 'side_effect'\nSkipping, side effect playbook not configured.\n--\u003e Scenario: 'default'\n--\u003e Action: 'verify'\n--\u003e Executing Testinfra tests found in /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/tests/...\n    ============================= test session starts ==============================\n    platform darwin -- Python 3.7.4, pytest-5.0.1, py-1.8.0, pluggy-0.12.0\n    rootdir: /Users/sblack/Git/rhythmic/molecule_demo/molecule/default\n    plugins: testinfra-3.0.5\ncollected 1 item \n    \n    tests/test_default.py .                                                  [100%]\n    \n    =========================== 1 passed in 5.35 seconds ===========================\nVerifier completed successfully.\n--\u003e Scenario: 'default'\n--\u003e Action: 'cleanup'\nSkipping, cleanup playbook not configured.\n--\u003e Scenario: 'default'\n--\u003e Action: 'destroy'\n    \n    PLAY [Destroy] *****************************************************************\n    \n    TASK [Destroy molecule instance(s)] ********************************************\n    changed: [localhost] =\u003e (item=None)\n    changed: [localhost]\n    \n    TASK [Wait for instance(s) deletion to complete] *******************************\n    FAILED - RETRYING: Wait for instance(s) deletion to complete (300 retries left).\n    changed: [localhost] =\u003e (item=None)\n    changed: [localhost]\n    \n    TASK [Delete docker network(s)] ************************************************\n    \n    PLAY RECAP *********************************************************************\n    localhost                  : ok=2    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0\n    \n```\n\n\n### Run the role against our default test rig\n\n```\n$ molecule converge\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/molecule.yml.\nValidation completed successfully.\n--\u003e Test matrix\n    \n└── default\n    ├── dependency\n    ├── create\n    ├── prepare\n    └── converge\n    \n--\u003e Scenario: 'default'\n--\u003e Action: 'dependency'\nSkipping, missing the requirements file.\n--\u003e Scenario: 'default'\n--\u003e Action: 'create'\n[DEPRECATION WARNING]: docker_image_facts is kept for backwards compatibility \nbut usage is discouraged. The module documentation details page may explain \nmore about this rationale.. This feature will be removed in a future release. \nDeprecation warnings can be disabled by setting deprecation_warnings=False in \nansible.cfg.\n    \n    PLAY [Create] ******************************************************************\n    \n    TASK [Log into a Docker registry] **********************************************\n    skipping: [localhost] =\u003e (item=None) \n    \n    TASK [Create Dockerfiles from image names] *************************************\n    changed: [localhost] =\u003e (item=None)\n    changed: [localhost]\n    \n    TASK [Discover local Docker images] ********************************************\n    ok: [localhost] =\u003e (item=None)\n    ok: [localhost]\n    \n    TASK [Build an Ansible compatible image] ***************************************\n    ok: [localhost] =\u003e (item=None)\n    ok: [localhost]\n    \n    TASK [Create docker network(s)] ************************************************\n    \n    TASK [Determine the CMD directives] ********************************************\n    ok: [localhost] =\u003e (item=None)\n    ok: [localhost]\n    \n    TASK [Create molecule instance(s)] *********************************************\n    changed: [localhost] =\u003e (item=None)\n    changed: [localhost]\n    \n    TASK [Wait for instance(s) creation to complete] *******************************\n    FAILED - RETRYING: Wait for instance(s) creation to complete (300 retries left).\n    changed: [localhost] =\u003e (item=None)\n    changed: [localhost]\n    \n    PLAY RECAP *********************************************************************\n    localhost                  : ok=6    changed=3    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0\n    \n    \n--\u003e Scenario: 'default'\n--\u003e Action: 'prepare'\nSkipping, prepare playbook not configured.\n--\u003e Scenario: 'default'\n--\u003e Action: 'converge'\n    \n    PLAY [Converge] ****************************************************************\n    \n    TASK [Gathering Facts] *********************************************************\n    ok: [instance]\n    \n    TASK [molecule_demo : echo hello world] ****************************************\n    ok: [instance] =\u003e {\n        \"msg\": \"hello world\"\n    }\n    \n    PLAY RECAP *********************************************************************\n    instance                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0\n```\n\n\nNow we can log in!\n```\n$ molecule login\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/vagrant/molecule.yml.\nValidation completed successfully.\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/molecule.yml.\nValidation completed successfully.\n[root@instance /]# \n```\n\n### Create a Vagrant Scenario and Run it!\n\nThis [scenario](https://molecule.readthedocs.io/en/stable/getting-started.html#molecule-scenarios)\nis using the vagrant [driver]() \nand \n\n\n```\n$ molecule init scenario -d vagrant -s vagrant\n--\u003e Initializing new scenario vagrant...\nInitialized scenario in /Users/sblack/Git/rhythmic/molecule_demo/molecule/vagrant successfully.\n```\n\nRun it \n```\n$ molecule converge -s vagrant\n....\n```\n\nLog in\n```\n$ molecule login -s vagrant\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/vagrant/molecule.yml.\nValidation completed successfully.\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/molecule.yml.\nValidation completed successfully.\nWarning: Permanently added '[127.0.0.1]:2222' (ECDSA) to the list of known hosts.\nWelcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-157-generic x86_64)\n\n * Documentation:  https://help.ubuntu.com\n * Management:     https://landscape.canonical.com\n * Support:        https://ubuntu.com/advantage\n\n13 packages can be updated.\n9 updates are security updates.\n\nNew release '18.04.2 LTS' available.\nRun 'do-release-upgrade' to upgrade to it.\n\n\nLast login: Wed Aug 21 20:15:46 2019 from 10.0.2.2\nvagrant@instance:~$ \n```\n\n\n### Again with ec2 as the driver \n\nCreate the Scenario\n```\n$ molecule init scenario -d ec2 -s ec2-scenario\n- -\u003e Initializing new scenario ec2-scenario...\nInitialized scenario in /Users/sblack/Git/rhythmic/molecule_demo/molecule/ec2-scenario successfully.\n```\n\nLog in to AWS\n```\n$ aws_okta_login infraservices-admin  \n```\n\n* This is where I changed a few values in `molecule/ec2-scenario/molecule.yml` \nso that ansible would use the right image in the right subnet. The Ansible code used to spin up the ec2 instances is in `molecule/ec2-scenario/create.yml`.\n\n\nNow we can run it!\n```\n$ molecule converge -s ec2-scenario\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/ec2-scenario/molecule.yml.\nValidation completed successfully.\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/vagrant/molecule.yml.\nValidation completed successfully.\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/molecule.yml.\nValidation completed successfully.\n--\u003e Test matrix\n    \n└── ec2-scenario\n    ├── dependency\n    ├── create\n    ├── prepare\n    └── converge\n    \n--\u003e Scenario: 'ec2-scenario'\n--\u003e Action: 'dependency'\nSkipping, missing the requirements file.\n--\u003e Scenario: 'ec2-scenario'\n--\u003e Action: 'create'\nSkipping, instances already created.\n--\u003e Scenario: 'ec2-scenario'\n--\u003e Action: 'prepare'\nSkipping, instances already prepared.\n--\u003e Scenario: 'ec2-scenario'\n--\u003e Action: 'converge'\n    \n    PLAY [Converge] ****************************************************************\n    \n    TASK [Gathering Facts] *********************************************************\n    ok: [instance]\n    \n    TASK [molecule_demo : echo hello world] ****************************************\n    ok: [instance] =\u003e {\n        \"msg\": \"hello world\"\n    }\n    \n    PLAY RECAP *********************************************************************\n    instance                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0\n```\n\n\nAnd we can log in! \n```\n$ molecule login -s ec2-scenario\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/ec2-scenario/molecule.yml.\nValidation completed successfully.\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/vagrant/molecule.yml.\nValidation completed successfully.\n--\u003e Validating schema /Users/sblack/Git/rhythmic/molecule_demo/molecule/default/molecule.yml.\nValidation completed successfully.\nWarning: Permanently added '18.204.56.74' (ECDSA) to the list of known hosts.\nLast login: Thu Aug 22 18:43:17 2019 from pool-108-51-226-95.washdc.fios.verizon.net\n\n       __|  __|_  )\n       _|  (     /   Amazon Linux 2 AMI\n      ___|\\___|___|\n\nhttps://aws.amazon.com/amazon-linux-2/\n5 package(s) needed for security, out of 13 available\nRun \"sudo yum update\" to apply all updates.\n[ec2-user@ip-172-31-71-132 ~]$ \n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhythmictech%2Fansible-role-molecule-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frhythmictech%2Fansible-role-molecule-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhythmictech%2Fansible-role-molecule-demo/lists"}