
In diesem Tutorial erfahren Sie, wie Sie in Ansible geschriebenen Framework-Code mit einem als Molecule bekannten Test-Framework testen. In Molecule werden wir Ansible als Verifizierer verwenden, den ich sonst nirgendwo finden konnte. Machen wir das!
Inhalt
- EinfΓΌhrung
- MolekΓΌl installieren
- Molecule Ansible
- Ansible Ansible Verifier
Ansible β , , , , . , . -.
, . . , , , , .
Molecule β , Ansible. 26 Ansible Molecule Ansible-lint Red Hat Ansible. Red Hat , , .
Molecule , , , .
Molecule TDD- . , , , Molecule.
Molecule
, UNIX.
Molecule :
- Python 2.7 Python 3.5 ( Python 3.7)
- Ansible 2.5 ( Ansible 2.9.6)
- Docker ( )
Pip β Molecule. Python 2.7.9 ( ) Python 3.4 ( ), PIP Python.
Molecule pip:
$ pip3 install molecule
. Β« MoleculeΒ». , Molecule, $ molecule --version.
Ansible Playbooks , , Ansible , .. Ansible , , , , , , , Ansible, , , β , , (, ).
Molecule Ansible
Molecule Ansible:
. Molecule Ansible
Molecules Ansible Galaxy Ansible. Molecule:
$ molecule init role <the_role_name>
. Initiating Ansible
Molecule , , , , , :
$ molecule init scenario -r <the_already_existing_role_name>
, Molecule, Molecule . :
.
βββ README.md
βββ files/
βββ handlers/
βββ meta/
βββ tasks/
βββ templates/
βββ tests/
βββ vars/
βββ molecule/
βββ default
βββ molecule.yml
βββ converge.yml
βββ verify.yml
βββ INSTALL.rst
Molecule :
molecule.yml
molecule.yml Molecule, .
---
dependency:
name: galaxy
enabled: true # to disable, set to false
driver:
name: docker
platforms:
- name: instance
image: docker.io/pycontribs/centos:7
pre_build_image: true
provisioner:
name: ansible
verifier:
name: ansible
dependency:
, . Ansible Galaxy β , Molecule. β Shell Gilt. dependency true, , enabled false.
driver:
Molecule, . Molecule β Docker, , : AWS, Azure, Google Cloud, Vagrant, Hetzner Cloud . . Molecule .
platforms:
, . , , , , .
provisioner:
Provider β , converge.yml ( ). β Ansible.
verifier:
verifier β , . verify.yml, , ( ) ( ). β Ansible, , : testinfra, goss inspec. testinfra , - UX , Python, testinfra , Ansible , . git issue .
, , β lint . Molevel.yml .
lint:
Lint , Molecule , , , . β yamllint, ansible-lint, flake8 .
scenario:
Molecule. , , . , .
, β , Molecule. , :
scenario:
create_sequence:
- dependency
- create
- prepare
check_sequence:
- dependency
- cleanup
- destroy
- create
- prepare
- converge
- check
- destroy
converge_sequence:
- dependency
- create
- prepare
- converge
destroy_sequence:
- dependency
- cleanup
- destroy
test_sequence:
- dependency
- lint
- cleanup
- destroy
- syntax
- create
- prepare
- converge
- idempotence
- side_effect
- verify
- cleanup
- destroy
, , Molecule, , $ molecule create , create_sequence, $ molecule check check_sequence .
, , , , , , .
Converge.yml
converge.yml, , , . . , $ molecule converge.
verify.yml
verify.yml , . , . , $ molecule verify.
INSTALL.rst
, Molecule .
Ansible Ansible Verifier
, , , Ansible Ansible Molecule.
$ molecule test test_sequence, , , , , .
, , BDD, :
# given phase
$ molecule create
# when phase
$ molecule converge
# then phase
$ molecule verify
, () . , .
β TDD . . , alpha-services, :
- 1. Java-1.8 -.
- 2:
/var/log/tomcat,tomcat,tomcat0755 - 3. , httpd
- 4.
template/tomcat/context.xml/etc/tomcat/context.xml
, Molecule :
$ molecule init role alpha-services
, . alpha-services/molecule/default/roles/test_alpha-services:
$ cd alpha-services
$ mkdir -p molecule/default/roles/test_alpha-services
. test_alpha-services
, Ansible ( , , , ). main.yml. yml, , test_. , java test_java.yml.
$ cd molecule/default/roles/test_alpha-services
$ mkdir defaults && touch defaults/main.yml
$ mkdir tasks && touch tasks/main.yml tasks/test_java.yml tasks/test_tomcat.yml tasks/test_httpd.yml tasks/test_aws.yml
$ mkdir vars && touch vars/main.yml
:
alpha-services/
βββ README.md
βββ files/
βββ handlers/
βββ meta/
βββ tasks/
βββ templates/
βββ tests/
βββ vars/
βββ molecule/
βββ default
βββ molecule.yml
βββ converge.yml
βββ verify.yml
βββ INSTALL.rst
βββ roles/
βββ test_alpha-services/
βββ defaults/
βββ main.yml
βββ tasks/
βββ main.yml
βββ test_java.yml
βββ test_tomcat.yml
βββ test_httpd.yml
βββ test_aws.yml
βββ vars/
βββ main.yml
molecule.yml:
---
dependency:
name: galaxy
enabled: false
driver:
name: docker
platforms:
- name: instance
image: docker.io/pycontribs/centos:7
pre_build_image: true
provisioner:
name: ansible
verifier:
name: ansible
converge.yml :
---
- name: Converge
hosts: all
tasks:
- name: "Include alpha-services"
include_role:
name: "alpha-services"
verify.yaml, :
---
# This is an example playbook to execute Ansible tests.
- name: Verify
hosts: all
tasks:
- name: "Include test_alpha-services"
include_role:
name: "test_alpha-services"
GIVEN : $ molecule create .
$ molecule create
--> Test matrix
βββ default
βββ dependency
βββ create
βββ prepare
--> Scenario: 'default'
--> Action: 'dependency'
Skipping, dependency is disabled.
--> Scenario: 'default'
--> Action: 'create'
--> Sanity checks: 'docker'
PLAY [Create] ******************************************************************
TASK [Log into a Docker registry] **********************************************
skipping: [localhost] => (item=None)
TASK [Check presence of custom Dockerfiles] ************************************
ok: [localhost] => (item=None)
ok: [localhost]
TASK [Create Dockerfiles from image names] *************************************
skipping: [localhost] => (item=None)
TASK [Discover local Docker images] ********************************************
ok: [localhost] => (item=None)
ok: [localhost]
TASK [Build an Ansible compatible image (new)] *********************************
skipping: [localhost] => (item=molecule_local/docker.io/pycontribs/centos:7)
TASK [Create docker network(s)] ************************************************
TASK [Determine the CMD directives] ********************************************
ok: [localhost] => (item=None)
ok: [localhost]
TASK [Create molecule instance(s)] *********************************************
changed: [localhost] => (item=instance)
TASK [Wait for instance(s) creation to complete] *******************************
FAILED - RETRYING: Wait for instance(s) creation to complete (300 retries left).
changed: [localhost] => (item=None)
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=5 changed=2 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
--> Scenario: 'default'
--> Action: 'prepare'
Skipping, prepare playbook not configured.
WHEN : $ molecule converge , . .
$ molecule converge
--> Test matrix
βββ default
βββ dependency
βββ create
βββ prepare
βββ converge
--> Scenario: 'default'
--> Action: 'dependency'
Skipping, dependency is disabled.
--> Scenario: 'default'
--> Action: 'create'
Skipping, instances already created.
--> Scenario: 'default'
--> Action: 'prepare'
Skipping, prepare playbook not configured.
--> Scenario: 'default'
--> Action: 'converge'
--> Sanity checks: 'docker'
PLAY [Converge] ****************************************************************
TASK [Gathering Facts] *********************************************************
ok: [instance]
TASK [Include alpha-services] **************************************************
TASK [alpha-services : include java installation tasks] ************************
included: /Users/chukwudiuzoma/Documents/DevOps/ANSIBLE/MyTutorials/AnsibleTestingWithMolecule/alpha-services/tasks/java.yml for instance
TASK [alpha-services : Install java] *******************************************
changed: [instance]
PLAY RECAP *********************************************************************
instance : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
.
TDD, , , , .
1. Java-1.8.0 -
---
- name: "java - check Java package status"
package:
name: "java-1.8.0"
state: "installed"
check_mode: yes
register: pkg_status
- name: "java - test java package is installed"
assert:
that:
- not pkg_status.changed
Java java-1.8.0 pkg_status. , java-1.8.0 , not pkg_status.changed true, . .
test_java.yml alpha-services/molecule/default/roles/test_alpha-services/tasks/main.yml :
---
- name: "include tasks for testing Java"
include_tasks: "test_java.yml"
THEN : $ molecule verify. , :
$ molecule verify
--> Test matrix
βββ default
βββ verify
--> Scenario: 'default'
--> Action: 'verify'
--> Running Ansible Verifier
--> Sanity checks: 'docker'
PLAY [Verify] ******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [instance]
TASK [Include test_alpha-services] *********************************************
TASK [test_alpha-services : include tasks for testing Java] ********************
included: /Users/chukwudiuzoma/Documents/DevOps/ANSIBLE/MyTutorials/AnsibleTestingWithMolecule/alpha-services/molecule/default/roles/test_alpha-services/tasks/test_java.yml for instance
TASK [test_alpha-services : Check Java package status] *************************
changed: [instance]
TASK [test_alpha-services : Test java package is installed] ********************
fatal: [instance]: FAILED! => {
"assertion": "not pkg_status.changed",
"changed": false,
"evaluated_to": false,
"msg": "Assertion failed"
}
PLAY RECAP *********************************************************************
instance : ok=3 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
ERROR:
1. alpha-services/tasks/java.yml :
---
- name: "Install '{{ java_required_software }}'"
package:
name: "{{ java_required_software }}"
lock_timeout: 60
state: "present"
java.yml alpha-services/tasks/main.yml :
---
- name: "Include java installation tasks"
include_tasks: "java.yml"
WHEN : $ molecule converge, .
THEN : $ molecule verify, , .
$ molecule verify
--> Test matrix
βββ default
βββ verify
--> Scenario: 'default'
--> Action: 'verify'
--> Running Ansible Verifier
--> Sanity checks: 'docker'
PLAY [Verify] ******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [instance]
TASK [Include test_alpha-services] *********************************************
TASK [test_alpha-services : include tasks for testing Java] ********************
included: /Users/chukwudiuzoma/Documents/DevOps/ANSIBLE/MyTutorials/AnsibleTestingWithMolecule/alpha-services/molecule/default/roles/test_alpha-services/tasks/test_java.yml for instance
TASK [test_alpha-services : Check Java package status] *************************
ok: [instance]
TASK [test_alpha-services : Test java package is installed] ********************
ok: [instance] => {
"changed": false,
"msg": "All assertions passed"
}
PLAY RECAP *********************************************************************
instance : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Verifier completed successfully.
2. /var/log/tomcat, tomcat, tomcat 0755.
---
- name: "tomcat - '{{ test_tomcat_home_dir }}' - retrieve information from path"
stat:
path: "{{ test_tomcat_home_dir }}"
register: directory
- name: "tomcat - assert that directory '{{ test_tomcat_home_dir }}' is created correctly"
assert:
that:
- "directory.stat.exists"
- "directory.stat.isdir"
- "directory.stat.mode == {{ test_tomcat_mode }}"
- "directory.stat.pw_name == {{ test_tomcat_user }}"
- "directory.stat.gr_name == {{ test_tomcat_group}}"
yml- Molecule:
---
#TOMCAT
test_tomcat_mode: "0755"
test_tomcat_user: "tomcat"
test_tomcat_group: "tomcat"
test_tomcat_home_dir: "/var/log/tomcat"
stat Ansible , .
test_java.yml alpha-services/molecule/default/roles/test_alpha-services/tasks/main.yml :
---
- name: "include tasks for testing Tomcat"
include_tasks: "test_tomcat.yml"
$ molecule verify, , . :
---
- name: "tomcat - create required tomcat logging directory"
file:
path: "{{ tomcat_home_dir }}"
state: "directory"
mode: "0755"
owner: "{{ tomcat_user }}"
group: "{{ tomcat_group }}"
recurse: yes
yml :
---
#TOMCAT
tomcat_mode: "0755"
tomcat_user: "tomcat"
tomcat_group: "tomcat"
tomcat_home_dir: "/var/log/tomcat"
tomcat.yml alpha-services/tasks/main.yml :
---
- name: "Include java installation tasks"
include_tasks: "java.yml"
: $ molecule converge, .
: $ molecule verify, , .
3: , httpd
, Ansible . Ansible, Β« Ansible β . , , , - . Ansible β , Β».
, , , , :
TASK [alpha-services : httpd - start and enable httpd service] *****************
fatal: [instance]: FAILED! => {"changed": false, "msg": "Could not find the requested service httpd: host"}
:
---
- name: "Httpd - install httpd service"
package:
name: "httpd"
state: "latest"
- name: "Httpd - start and enable httpd service"
service:
name: "httpd"
state: "started"
enabled: "yes"
, httpd Linux systemd, . , platforms Molelele.yml:
---
platforms:
- name: instance
image: docker.io/pycontribs/centos:7
pre_build_image: false # we don't need ansible installed on the instance
command: /sbin/init
tmpfs:
- /run
- /tmp
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
systemd https://molecule.readthedocs.io/en/latest/examples.html
$ molecule create $ molecule converge. , httpd . httpd, :
$ molecule login # this logs you into the docker container shell
$ systemctl | grep httpd
httpd.service loaded active running The Apache HTTP Server
$ exit # this logs you out of the docker container to your local terminal
4. template/tomcat/context.xml /etc/tomcat/context.xml.
, , -. , , , - , . , , . , , Ansible .
:
- name: "tomcat - test tomcat file"
block:
- name: "tomcat - retrieve information from path '{{ test_tomcat_context_xml_file }}'"
stat:
path: "{{ test_tomcat_context_xml_file }}"
register: remote_file
- name: "tomcat - assert that '{{ test_tomcat_context_xml_file }}' file is created correctly"
assert:
that:
- "remote_file.stat.exists"
- "remote_file.stat.isreg" # is a regular file
- "remote_file.stat.path == '{{ test_tomcat_context_xml_file }}'"
- "remote_file.stat.mode == '0755'"
test_tomcat_conf_dir: "/etc/tomcat"
test_tomcat_context_xml_file: "{{ test_tomcat_conf_dir }}/context.xml"
$ molecule verify, , . :
- name: "tomcat - copy dynamic tomcat server config files"
template:
src: "{{ tomcat_context_xml_file }}"
dest: "{{ tomcat_conf_dir }}"
tomcat_conf_dir: "/etc/tomcat"
tomcat_context_xml_file: "tomcat/context.xml"
$ molecule converge, $ molecule verify. , .
, , $ molecule test, Molecule test_sequence. .
Zusammenfassend ist dies meiner Meinung nach der richtige Ansatz fΓΌr die Entwicklung von Molekulartests fΓΌr Ansible-Rollen. Der Infrastrukturcode sollte vor der Bereitstellung in einer Produktionsumgebung getestet werden, um unangenehme Γberraschungen zu vermeiden. Dieses Tutorial war eine einfache Demonstration, wie Sie Ansible mit Molecule mit Ansible Verifier testen kΓΆnnen. Daher mΓΌssen Sie keine andere Programmiersprache wie Python, Ruby oder Go lernen.