molecule 需要我们额外编写对应ansible role的测试代码,通过一个例子来说明具体的使用方法
创建一个空的role
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
$ molecule init role -r ansible-apache -d docker --> Initializing new role ansible-apache... Initialized role in /Users/jeremyzhang/git/hack/molecule_example/ansible-apache successfully. $tree ansible-apache ansible-apache ├── README.md ├── defaults │ └── main.yml ├── handlers │ └── main.yml ├── meta │ └── main.yml ├── molecule │ └── default │ ├── Dockerfile.j2 │ ├── INSTALL.rst │ ├── molecule.yml │ ├── playbook.yml │ └── tests │ ├── test_default.py │ └── test_default.pyc ├── tasks │ └── main.yml └── vars └── main.yml 8 directories, 12 files |
我们来编写具体的role的逻辑处理部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
cat tasks/main.yml --- # tasks file for ansible-apache - name: "Ensure required packages are present" yum: name: "{{ pkg_list }}" state: present - name: "Ensure latest index.html is present" template: src: index.html.j2 dest: /var/www/html/index.html - name: "Ensure httpd service is started and enabled" service: name: "{{ item }}" state: started enabled: true with_items: "{{ svc_list }}" - name: "Whitelist http in firewalld" firewalld: service: http state: enabled permanent: true immediate: true |
这个playbook book主要有4个task,分别是
- 确保安装包已经安装
- 从模版文件生成默认页面(确保最新,如果已经最新,不做任何修改)
- 确保服务是开启状态
- 确保防火墙打开了指定端口
因为上边task中需要模版文件index.html.j2,我们来创建这个文件
1 2 3 4 5 |
$mkdir templates&&vi templates/index.html.j2 $cat templates/index.html.j2 <div style="text-align: center"> <h2>Managed by Ansible</h2> </div> |
然后我们在vars文件夹下将我们task中需要的变量统一定义一下
1 2 3 4 5 6 7 8 9 |
cat vars/main.yml --- # vars file for ansible-apache pkg_list: - httpd - firewalld svc_list: - httpd - firewalld |
接下来就是要编写测试脚本了,首先,默认的镜像文件可能会不包含必须的包,所以我们要稍微做一下修改,melecule 专用的镜像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$cat molecule/default/molecule.yml --- dependency: name: galaxy driver: name: docker lint: name: yamllint platforms: - name: instance image: centos:7-systemd privileged:true provisioner: name: ansible lint: name: ansible-lint verifier: name: testinfra lint: name: flake8 |
然后我们编写真正的测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
$cat molecule/default/tests/test_default.py import os import pytest import testinfra.utils.ansible_runner testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') @pytest.mark.parametrize('pkg', [ 'httpd', 'firewalld' ]) def test_pkg(host, pkg): package = host.package(pkg) assert package.is_installed @pytest.mark.parametrize('svc', [ 'httpd', 'firewalld' ]) def test_svc(host, svc): service = host.service(svc) assert service.is_running assert service.is_enabled @pytest.mark.parametrize('file, content', [ ("/etc/firewalld/zones/public.xml", "<service name=\"http\"/>"), ("/var/www/html/index.html", "Managed by Ansible") ]) def test_files(host, file, content): file = host.file(file) assert file.exists assert file.contains(content) |
如上脚本包含3个方法,共覆盖了4个task(最后一个task防火墙哪个也通过检测文件中是否存在指定字符串来判断了)
- test_pkg 确认软件是否正确安装
- test_svc 确认服务是否是正常运行并开机启动
- test_files 确认文件存在并包含指定内容
执行命令
1 |
molecule test |
Note: 测试了一下,role中增加firewalld的部分有问题,应该是docker 镜像的原因, 也就是说,使用docker 来测试还是不如有一套真正的环境来测试来的方便,而且很多东西操作云相关的,例如创建一个vpc,我们是不可能通过docker这种镜像的方式来测试的
参考资料:
https://www.digitalocean.com/community/tutorials/how-to-test-ansible-roles-with-molecule-on-ubuntu-16-04
Latest posts by Zhiming Zhang (see all)
- aws eks node 自动化扩展工具 Karpenter - 8月 10, 2022
- ReplicationController and ReplicaSet in Kubernetes - 12月 20, 2021
- public key fingerprint - 5月 27, 2021