ããã¯ããªã«ãããããŠæžãããã®ïŒ
Ansibleã®Roleã«å¯ŸããŠããã¹ããæžããããªããšæããŸããŠã
調ã¹ãŠã¿ãããMoleculeãšããã®ãè¯ããããªæãã ã£ãã®ã§ãã¡ãã£ãšè©ŠããŠã¿ãããšã«ããŸããã
Molecule — Molecule 2.22 documentation
MoleculeïŒ
Ansible Roleãéçºãããããã¹ãããããã®ãã®ã¿ããã§ãã
Molecule — Molecule 2.22 documentation
Molecule is designed to aid in the development and testing of Ansible roles.
è€æ°ã®ã€ã³ã¹ã¿ã³ã¹ãOSãä»®æ³åãããã€ããŒããã¹ãã«é¢ãããµããŒããæäŸããŸãããšã
Molecule provides support for testing with multiple instances, operating systems and distributions, virtualization providers, test frameworks and testing scenarios.
Ansibleã®Organizationã«ããã®ããã€ã³ãã§ããã
GitHub - ansible/molecule: Molecule aids in the development and testing of Ansible roles.
çŸåšã®ããŒãžã§ã³ã¯ã2.22ã§ãã
ãšãããããã€ã³ã¹ããŒã«ããŠGetting Startedã«æ²¿ã£ãŠè©ŠããŠã¿ãŸãããã
ç°å¢
ã€ã³ã¹ããŒã«ã«å¿ èŠãªæ å ±ã¯ããã¡ãã
Installation — Molecule 2.22 documentation
OSã¯ãCentOS 7ãUbuntu 16.xãããã§ããâŠä»åã¯ãããªæãã§ãããŸãã
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.3 LTS Release: 18.04 Codename: bionic $ docker version Client: Docker Engine - Community Version: 19.03.5 API version: 1.40 Go version: go1.12.12 Git commit: 633a0ea838 Built: Wed Nov 13 07:29:52 2019 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.5 API version: 1.40 (minimum version 1.12) Go version: go1.12.12 Git commit: 633a0ea838 Built: Wed Nov 13 07:28:22 2019 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.2.10 GitCommit: b34a5c8af56e510852c35414db4c1f4fa6172339 runc: Version: 1.0.0-rc8+dev GitCommit: 3e425f80a8c931f88e6d94a8c831b9d5aa481657 docker-init: Version: 0.18.0 GitCommit: fec3683 $ python3 -V Python 3.6.9 $ pip3 -V pip 9.0.1 from /path/to/venv/lib/python3.6/site-packages (python 3.6)
Moleculeã®ã€ã³ã¹ããŒã«ã
$ pip3 install molecule
DriverãšããŠãããã©ã«ãã§Dockerã䜿çšãããã®ã§ããã¡ããã€ã³ã¹ããŒã«ã
$ pip3 install molecule[docker]
molecule[docker]ã®ã€ã³ã¹ããŒã«ã«ã€ããŠã¯æžããŠãªããªïŒãšæã£ãããGetting Startedã«æžããŠãããŸããâŠã
Getting Started Guide — Molecule 2.22 documentation
ããŒãžã§ã³ãAnsibleãäžç·ã«ã€ã³ã¹ããŒã«ãããŸãã
$ pip3 freeze | grep -E 'ansible|molecule|docker|testinfra' ansible==2.9.3 ansible-lint==4.2.0 docker==4.1.0 molecule==2.22 testinfra==3.4.0
ãŸãããã¹ããã¬ãŒã ã¯ãŒã¯ãšããŠã¯ãTestinfraã䜿ãããŸãã
Testinfra test your infrastructure — testinfra 3.4.1.dev0+gd7a7512.d20200105 documentation
Driverã«ã¯ãDocker以å€ã«ãEC2ãAzureãGCEãªã©ãããããããããã§ãã
ãé¡ãšç¢ºèª
ä»åã¯ãUbuntu Linuxã«Apacheãã€ã³ã¹ããŒã«ããRoleãäœã£ãŠããã¹ããåããããšããŽãŒã«ã«ããŠã¿ãŸãã
åºæ¬ã¯ãGetting Startedã«æ²¿ã£ãŠãã圢ã§ã
Getting Started Guide — Molecule 2.22 documentation
ãŸãã¯ãæ°ããRoleãäœæããŸãã
ãmolecule init roleãã§äœæããŸããRoleåã¯ããapacheãã«ããŸããã
$ molecule init role -r apache
ãªãããã§ã«ååšããRoleã«Moleculeãè¿œå ããå Žåã¯ã以äžã®ã³ãã³ãã«ãªãããã§ãã
molecule init scenario -r my-role-name
äœæããããã¡ã€ã«ã¯ããããªæãã§ãã
$ find apache -type f apache/handlers/main.yml apache/README.md apache/vars/main.yml apache/meta/main.yml apache/defaults/main.yml apache/tasks/main.yml apache/molecule/default/playbook.yml apache/molecule/default/tests/__pycache__/test_default.cpython-36.pyc apache/molecule/default/tests/test_default.py apache/molecule/default/Dockerfile.j2 apache/molecule/default/molecule.yml apache/molecule/default/INSTALL.rst apache/.yamllint
Ansible RoleãšãMoleculeã«é¢é£ãããã¡ã€ã«ãããããã§ããæãã§ãããMoleculeã«é¢é£ãããã¡ã€ã«ã¯ãRoleå ã«çŽãŸã£ãŠããŸãã
MoleculeåŽã®ãã¡ã€ã«ããã¡ãã£ãšèŠãŠã¿ãŸãããã
moleculeãã£ã¬ã¯ããªé äžã®ããdefaultããšããã®ã¯ã·ããªãªã®ååã§ãã
Dockerfileã®ãã³ãã¬ãŒãã
apache/molecule/default/Dockerfile.j2
# Molecule managed {% if item.registry is defined %} FROM {{ item.registry.url }}/{{ item.image }} {% else %} FROM {{ item.image }} {% endif %} {% if item.env is defined %} {% for var, value in item.env.items() %} {% if value %} ENV {{ var }} {{ value }} {% endif %} {% endfor %} {% endif %} RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates iproute2 && apt-get clean; \ elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash iproute && dnf clean all; \ elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash iproute && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \ elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml iproute2 && zypper clean -a; \ elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \ elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates iproute2 && xbps-remove -O; fi
Molecureã®èšå®ãã¡ã€ã«ã
apache/molecule/default/molecule.yml
--- dependency: name: galaxy driver: name: docker lint: name: yamllint platforms: - name: instance image: centos:7 provisioner: name: ansible lint: name: ansible-lint verifier: name: testinfra lint: name: flake8
Playbookã
apache/molecule/default/playbook.yml
--- - name: Converge hosts: all roles: - role: apache
ãã¹ãã³ãŒãã
apache/molecule/default/tests/test_default.py
import os import testinfra.utils.ansible_runner testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE'] ).get_hosts('all') def test_hosts_file(host): f = host.file('/etc/hosts') assert f.exists assert f.user == 'root' assert f.group == 'root'
ãã£ãšããããªæãã§ãã
ãšãããããRoleå ã«ç§»åã
$ cd apache
Driverã¯Dockerãšãªã£ãŠããŸãããOSã®ã€ã¡ãŒãžã¯ä»åã¯Ubuntu Linux 18.04ã«å€æŽããŸãã
molecule.yml
driver: name: docker lint: name: yamllint platforms: - name: instance image: ubuntu:18.04
ãmolecule createãã§ãã€ã³ã¹ã¿ã³ã¹ãäœæãä»åã¯ãDriverã«Dockerã䜿çšããŠããã®ã§ãDockerã³ã³ãããç«ã¡äžãããŸãã
$ molecule create
ã€ã³ã¹ã¿ã³ã¹ã¯ããmolecule listãã§ç¢ºèªããããšãã§ããŸãã
$ molecule list --> Validating schema /path/to/apache/molecule/default/molecule.yml. Validation completed successfully. Instance Name Driver Name Provisioner Name Scenario Name Created Converged --------------- ------------- ------------------ --------------- --------- ----------- instance docker ansible default true false
Dockerã³ã³ãããªã®ã§ãdockerã³ãã³ãã§ã確èªã§ããŸãã
$ docker container ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3bf5b879b166 molecule_local/ubuntu:18.04 "bash -c 'while trueâŠ" 14 seconds ago Up 10 seconds instance
ã€ã¡ãŒãžåã¯ããããªæãã«ã
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE molecule_local/ubuntu 18.04 304dca78c3df 3 minutes ago 132MB ...
ãã®ã€ã³ã¹ã¿ã³ã¹ã«ãã°ã€ã³ããå Žåã¯ããmolecule loginãã䜿ããŸãã
$ molecule login
ã³ã³ããã®äžã«å ¥ããŸãã
root@instance:/# uname -a Linux instance 4.15.0-74-generic #84-Ubuntu SMP Thu Dec 19 08:06:28 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
ãã®ã€ã³ã¹ã¿ã³ã¹ãç Žæ£ããã«ã¯ããmolecule destroyãã§ã
$ molecule destroy
ããã§æ¬æ¥ã®Roleã®æ¹ã«ãApacheãã€ã³ã¹ããŒã«ããã¿ã¹ã¯ãæžããŠã¿ãŸãããã
tasks/main.yml
--- - name: install apache2 apt: name: apache2 state: present
ãmolecule convergeããå®è¡ãããšããmolecule createãã«å ããŠPlaybookã®å®è¡ãŸã§è¡ã£ãŠãããŸãã
$ molecule converge
ãããªæãã§ããã
--> Scenario: 'default' --> Action: 'converge' PLAY [Converge] **************************************************************** TASK [Gathering Facts] ********************************************************* [DEPRECATION WARNING]: Distribution Ubuntu 18.04 on host instance should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/ 2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg. ok: [instance] TASK [apache : install apache2] ************************************************ [WARNING]: Updating cache and auto-installing missing dependency: python-apt changed: [instance] PLAY RECAP ********************************************************************* instance : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ããã§ã³ã³ããã«ãã°ã€ã³ãããšãApacheãã€ã³ã¹ããŒã«ãããç¶æ ã確èªããããšãã§ããŸãã
次ã«ããã¹ããããŠã¿ãŸãããã
ãmolecule initãæã«äœæããããã¹ãã³ãŒããããããªæãã«ä¿®æ£ã
molecule/default/tests/test_default.py
import os import testinfra.utils.ansible_runner testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE'] ).get_hosts('all') def test_apache_is_installed(host): apache2 = host.package('apache2') assert apache2.is_installed
Apacheãã€ã³ã¹ããŒã«ãããããšã確èªãããã¹ãã«ããŸããã
ãã¹ãã¯ããmolecule verifyãã§å®è¡ããŸãã
$ molecule verify
ãã°ã
collected 1 item tests/test_default.py . [100%] ============================== 1 passed in 3.37s =============================== Verifier completed successfully.
ã¡ãããšãã¹ããåäœããŠããã確èªããããã«ã倱æãããã¹ãã«ããŠã¿ãŸãããã
def test_apache_is_installed(host): apache2 = host.package('apache2') assert apache2.is_installed == False
確èªã
collected 1 item tests/test_default.py F [100%] =================================== FAILURES =================================== _________________ test_apache_is_installed[ansible://instance] _________________ host = <testinfra.host.Host object at 0x7fde1da8af28> def test_apache_is_installed(host): apache2 = host.package('apache2') > assert apache2.is_installed == False E assert True == False E + where True = <package apache2>.is_installed tests/test_default.py:11: AssertionError ============================== 1 failed in 3.08s ===============================
ãã¹ããå®è¡ããŠãããŠããã§ããã
䜿ãçµãã£ãã€ã³ã¹ã¿ã³ã¹ã®ç Žæ£ã¯ããã£ã±ããmolecule destroyãã§ã
$ molecule destroy
æåŸã«ãããŸã§äžæ°ã«å®è¡ããã«ã¯ããmolecule testããå®è¡ããŸãã
$ molecule test
ããã©ã«ãã§äœæããRoleã®ãŸãŸã ãšãmetaãlintã§ãšã©ãŒã«ãªã£ãŠãŸãã®ã§ããšã©ãŒã¡ãã»ãŒãžãèªãã§ä¿®æ£ããŠãããŸãããã
--> Scenario: 'default' --> Action: 'lint' --> Executing Yamllint on files found in /path/to/apache/... Lint completed successfully. --> Executing Flake8 on files found in /path/to/apache/molecule/default/tests/... Lint completed successfully. --> Executing Ansible Lint on /path/to/apache/molecule/default/playbook.yml... [701] Role info should contain platforms meta/main.yml:1 {'meta/main.yml': {'galaxy_info': {'author': 'your name', 'description': 'your description', 'company': 'your company (optional)', 'license': 'license (GPLv2, CC-BY, etc)', 'min_ansible_version': 1.2, 'galaxy_tags': [], '__line__': 2, '__file__': '/path/to/apache/meta/main.yml'}, 'dependencies': [], '__line__': 1, '__file__': '/path/to/apache/meta/main.yml', 'skipped_rules': []}} [703] Should change default metadata: author meta/main.yml:1 {'meta/main.yml': {'galaxy_info': {'author': 'your name', 'description': 'your description', 'company': 'your company (optional)', 'license': 'license (GPLv2, CC-BY, etc)', 'min_ansible_version': 1.2, 'galaxy_tags': [], '__line__': 2, '__file__': '/path/to/apache/meta/main.yml'}, 'dependencies': [], '__line__': 1, '__file__': '/path/to/apache/meta/main.yml', 'skipped_rules': []}} [703] Should change default metadata: description meta/main.yml:1 {'meta/main.yml': {'galaxy_info': {'author': 'your name', 'description': 'your description', 'company': 'your company (optional)', 'license': 'license (GPLv2, CC-BY, etc)', 'min_ansible_version': 1.2, 'galaxy_tags': [], '__line__': 2, '__file__': '/path/to/apache/meta/main.yml'}, 'dependencies': [], '__line__': 1, '__file__': '/path/to/apache/meta/main.yml', 'skipped_rules': []}} [703] Should change default metadata: company meta/main.yml:1 {'meta/main.yml': {'galaxy_info': {'author': 'your name', 'description': 'your description', 'company': 'your company (optional)', 'license': 'license (GPLv2, CC-BY, etc)', 'min_ansible_version': 1.2, 'galaxy_tags': [], '__line__': 2, '__file__': '/path/to/apache/meta/main.yml'}, 'dependencies': [], '__line__': 1, '__file__': '/path/to/apache/meta/main.yml', 'skipped_rules': []}} [703] Should change default metadata: license meta/main.yml:1 {'meta/main.yml': {'galaxy_info': {'author': 'your name', 'description': 'your description', 'company': 'your company (optional)', 'license': 'license (GPLv2, CC-BY, etc)', 'min_ansible_version': 1.2, 'galaxy_tags': [], '__line__': 2, '__file__': '/path/to/apache/meta/main.yml'}, 'dependencies': [], '__line__': 1, '__file__': '/path/to/apache/meta/main.yml', 'skipped_rules': []}}
åã³ãã³ãã§ã©ããªããšãå®è¡ãããã®ãã¯ãå®è¡æã«matrixãåºåãããã®ã§ããã¡ãã§ç¢ºèªã§ããŸãã
ãmolecule testãã ãšããããªããŸãã
--> Test matrix âââ default âââ lint âââ dependency âââ cleanup âââ destroy âââ syntax âââ create âââ prepare âââ converge âââ idempotence âââ side_effect âââ verify âââ cleanup âââ destroy
ã³ãã³ãã®ãªã¹ãã¯ããã¡ãã
Usage — Molecule 2.22 documentation
ãããã°ãã°ãåºåãããã£ãããã--debugããªãã·ã§ã³ã䜿ããŸãã
$ molecule --debug test
ãšãããããç°¡åãªäœ¿ãæ¹ã¯æŒãããããæãã§ããããïŒ