如何借助Molecule測(cè)試Ansible角色
譯文【51CTO.com快譯】測(cè)試技術(shù)在軟件開(kāi)發(fā)中扮演著重要角色,我們談?wù)摶A(chǔ)設(shè)施即代碼(IaC)時(shí)也一樣。
開(kāi)發(fā)人員總是在測(cè)試,需要不斷的反饋來(lái)促進(jìn)開(kāi)發(fā)。如果獲得變更方面的反饋很費(fèi)時(shí)間,表明你的步驟可能太龐大,難以發(fā)現(xiàn)錯(cuò)誤。小步驟和快速反饋是TDD(測(cè)試驅(qū)動(dòng)型開(kāi)發(fā))的精髓。但是你如何將這個(gè)方法應(yīng)用于開(kāi)發(fā)特定的playbook或角色呢?
開(kāi)發(fā)自動(dòng)化時(shí),典型的工作流程會(huì)從新的虛擬機(jī)開(kāi)始。我使用Vagrant來(lái)闡述這個(gè)想法,但你可以使用libvirt、Docker、VirtualBox、VMware、私有云或公共云中的實(shí)例,或者數(shù)據(jù)中心虛擬機(jī)管理程序中配置的虛擬機(jī)(比如oVirt、Xen或VMware)。
決定使用哪個(gè)虛擬機(jī)時(shí),應(yīng)兼顧反饋速度和與你的實(shí)際目標(biāo)環(huán)境的相似性。
Vagrant的最小起點(diǎn)是:
- vagrant init centos/7 # or any other box
然后將Ansible配置添加到你的Vagrantfile:
- config.vm.provision "ansible" do |ansible|
- ansible.playbook = "playbook.yml"
- end
***,你的工作流程將是這樣:
1. vagrant up。
2. 編輯playbook。
3. vagrant provision。
4. vagrant ssh,以驗(yàn)證虛擬機(jī)狀態(tài)。
5. 重復(fù)步驟2至4。
偶爾會(huì)銷毀并再次啟動(dòng)虛擬機(jī)(vagrant destroy -f; vagrant up),以提高你playbook的可靠性(即為了測(cè)試你的自動(dòng)化是不是端到端運(yùn)行)。
雖然這是很好的工作流程,但你仍在完成連接到虛擬機(jī),并驗(yàn)證一切都按預(yù)期運(yùn)行的所有棘手工作。
如果測(cè)試未自動(dòng)化,你沒(méi)有自動(dòng)化基礎(chǔ)架構(gòu)時(shí)會(huì)面臨類似那樣的問(wèn)題。
幸好,像Testinfra和Goss這樣的工具有助于自動(dòng)化這些驗(yàn)證。
我將著重介紹Testinfra,因?yàn)樗怯肞ython編寫(xiě)的,是Molecule的默認(rèn)驗(yàn)證器。想法很簡(jiǎn)單:使用Python自動(dòng)化你的驗(yàn)證。
- def test_nginx_is_installed(host):
- nginx = host.package("nginx")
- assert nginx.is_installed
- assert nginx.version.startswith("1.2")
- def test_nginx_running_and_enabled(host):
- nginx = host.service("nginx")
- assert nginx.is_running
- assert nginx.is_enabled
在開(kāi)發(fā)環(huán)境中,該腳本將使用SSH(就像Ansible)連接到目標(biāo)主機(jī)以執(zhí)行上述驗(yàn)證(包存在/版本和服務(wù)狀態(tài)):
- py.test --connection=ssh --hosts=server
簡(jiǎn)而言之,在基礎(chǔ)架構(gòu)自動(dòng)化開(kāi)發(fā)過(guò)程中,面臨的挑戰(zhàn)是配置新的基礎(chǔ)架構(gòu),針對(duì)它們執(zhí)行playbook,驗(yàn)證你的變更體現(xiàn)了你在playbooks中聲明的狀態(tài)。
- Testinfra能驗(yàn)證什么?
- 從用戶的角度來(lái)看,基礎(chǔ)架構(gòu)已安裝并運(yùn)行起來(lái)(比如,HTTPD或Nginx在回應(yīng)請(qǐng)求,MariaDB或PostgreSQL在處理SQL查詢)。
- OS服務(wù)已運(yùn)行并啟用
- 進(jìn)程在偵聽(tīng)特定的端口
- 進(jìn)程在回應(yīng)請(qǐng)求
- 配置文件用模板正確復(fù)制或生成
- 你幾乎執(zhí)行的任何操作,確保服務(wù)器狀態(tài)正確無(wú)誤
- 這些自動(dòng)化測(cè)試提供了哪些安全措施?
- 執(zhí)行復(fù)雜的變更或引入新功能而不破壞現(xiàn)有行為(比如,添加對(duì)基于Debian的系統(tǒng)的支持后,仍可以在基于RHEL的發(fā)行版中運(yùn)行)。
- 發(fā)布Ansible的新版本并引入新的***實(shí)踐時(shí),重構(gòu)/改進(jìn)代碼庫(kù)。
到目前為止,我們對(duì)Vagrant、Ansible和Testinfra所做的工作很容易與四階段測(cè)試模式中描述的步驟對(duì)應(yīng)起來(lái)――這種測(cè)試結(jié)構(gòu)方法使測(cè)試目標(biāo)清晰。它包括下列階段:安裝、演練、驗(yàn)證和拆除:
- 安裝:為測(cè)試執(zhí)行準(zhǔn)備環(huán)境(比如啟用新的虛擬機(jī)):
- vagrant up
- 演練:針對(duì)測(cè)試的系統(tǒng)有效地執(zhí)行代碼(即Ansible playbook):
- vagrant provision
- 驗(yàn)證:驗(yàn)證上一步的輸出:
- py.test(針對(duì)Testinfra)
- 拆除:回到安裝前的狀態(tài):
- vagrant destroy
我們用于特定playbook的同一個(gè)想法可以運(yùn)用于角色開(kāi)發(fā)和測(cè)試,但每當(dāng)開(kāi)發(fā)新產(chǎn)品時(shí)是否需要執(zhí)行所有這些步驟?如果你想使用容器或OpenStack而不是Vagrant,該怎么辦?如果你寧愿使用Goss而不是Testinfra,該怎么辦?如何針對(duì)你代碼中的每次變更持續(xù)運(yùn)行此操作?有沒(méi)有一種更簡(jiǎn)單快速的方法來(lái)使用自動(dòng)化測(cè)試開(kāi)發(fā)playbook和角色?
Molecule
Molecule使用測(cè)試幫助開(kāi)發(fā)角色。該工具甚至可以用測(cè)試用例初始化新角色:molecule init role –role-name foo。
Molecule很靈活,足以讓你可以將不同的驅(qū)動(dòng)程序用于基礎(chǔ)架構(gòu)配置,包括Docker、Vagrant、OpenStack、GCE、EC2和Azure。它還允許使用不同的服務(wù)器驗(yàn)證工具,包括Testinfra和Goss。
它的命令簡(jiǎn)化了開(kāi)發(fā)工作流程中常用任務(wù)的執(zhí)行:
- lint-執(zhí)行yaml-lint、ansible-lint和flake8,如果有問(wèn)題報(bào)告故障
- syntax-驗(yàn)證角色的語(yǔ)法錯(cuò)誤
- create-創(chuàng)建驅(qū)動(dòng)程序已配置的實(shí)例
- prepare-使用準(zhǔn)備playbook來(lái)配置實(shí)例
- converge-執(zhí)行針對(duì)主機(jī)的playbook
- idempotence-執(zhí)行兩次playbook;萬(wàn)一第二次運(yùn)行出現(xiàn)變更,就失效(非冪等)
- verify-執(zhí)行服務(wù)器狀態(tài)驗(yàn)證工具(testinfra或goss)
- destroy-銷毀實(shí)例
- test-執(zhí)行前面的所有步驟
login命令可用于連接到已配置的服務(wù)器用于故障排查。
逐步操作
你如何從根本沒(méi)有測(cè)試到針對(duì)每次變更/提交執(zhí)行一個(gè)體面的代碼庫(kù)?
1. virtualenv(可選)
virtualenv工具創(chuàng)建孤立的環(huán)境,而virtualenvwrapper是便于使用virtualenv的擴(kuò)展件的集合。
這些工具可防止Molecule與計(jì)算機(jī)中其他Python包之間的依賴項(xiàng)和沖突。
- sudo pip install virtualenvwrapper
- export WORKON_HOME=~/envs
- source /usr/local/bin/virtualenvwrapper.sh
- mkvirtualenv mocule
2. Molecule
安裝帶Docker驅(qū)動(dòng)程序的Molecule:
- pip install molecule ansible docker-py
生成帶測(cè)試場(chǎng)景的新角色:
- molecule init role -r role_name
或者針對(duì)現(xiàn)有角色:
- molecule init scenario -r my-role
所有必要的配置都是使用你的角色生成,你只要使用Testinfra編寫(xiě)測(cè)試用例:
- import os
- import testinfra.utils.ansible_runner
- testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
- os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
- def test_jboss_running_and_enabled(host):
- jboss = host.service('wildfly')
- assert jboss.is_enabled
- def test_jboss_listening_http(host):
- socket = host.socket('tcp://0.0.0.0:8080')
- assert socket.is_listening
- def test_mgmt_user_authentication(host):
- command = """curl --digest -L -D - http://localhost:9990/management \
- -u ansible:ansible"""
- cmd = host.run(command)
- assert 'HTTP/1.1 200 OK' in cmd.stdout
Wildfly角色的該示例測(cè)試用例驗(yàn)證OS服務(wù)已啟用,進(jìn)程在偵聽(tīng)端口8080,身份驗(yàn)證已正確配置。
為這些測(cè)試編寫(xiě)代碼很簡(jiǎn)單,你基本上需要考慮一種自動(dòng)驗(yàn)證方法。
你登錄到playbook針對(duì)的機(jī)器或者為監(jiān)視/警報(bào)系統(tǒng)構(gòu)建驗(yàn)證時(shí),你已經(jīng)在編寫(xiě)測(cè)試。 這有助于使用Testinfra API或使用系統(tǒng)命令來(lái)構(gòu)建內(nèi)容。
CI
持續(xù)執(zhí)行Molecule測(cè)試很簡(jiǎn)單。上述示例適用于帶Docker驅(qū)動(dòng)程序的TravisCI,但它可能很容易改動(dòng),適合Molecule支持的任何CI服務(wù)器和任何基礎(chǔ)架構(gòu)驅(qū)動(dòng)程序。
- ---
- sudo: required
- language: python
- services:
- - docker
- before_install:
- - sudo apt-get -qq update
- - pip install molecule
- - pip install docker-py
- script:
- - molecule test
訪問(wèn)Travis CI以獲取示例輸出。
原文標(biāo)題:Testing Ansible roles with Molecule,作者:Jairo da Silva Junior
【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】