如何藉助Molecule測試Ansible角色
【51CTO.com快譯】測試技術在軟體開發中扮演著重要角色,我們談論基礎設施即程式碼(IaC)時也一樣。
開發人員總是在測試,需要不斷的反饋來促進開發。如果獲得變更方面的反饋很費時間,表明你的步驟可能太龐大,難以發現錯誤。小步驟和快速反饋是TDD(測試驅動型開發)的精髓。但是你如何將這個方法應用於開發特定的playbook或角色呢?
開發自動化時,典型的工作流程會從新的虛擬機器開始。我使用Vagrant來闡述這個想法,但你可以使用libvirt、Docker、VirtualBox、VMware、私有云或公共雲中的例項,或者資料中心虛擬機器管理程式中配置的虛擬機器(比如oVirt、Xen或VMware)。
決定使用哪個虛擬機器時,應兼顧反饋速度和與你的實際目標環境的相似性。
Vagrant的最小起點是:
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,以驗證虛擬機器狀態。
5. 重複步驟2至4。
偶爾會銷燬並再次啟動虛擬機器(vagrant destroy -f; vagrant up),以提高你playbook的可靠性(即為了測試你的自動化是不是端到端執行)。
雖然這是很好的工作流程,但你仍在完成連線到虛擬機器,並驗證一切都按預期執行的所有棘手工作。
如果測試未自動化,你沒有自動化基礎架構時會面臨類似那樣的問題。
幸好,像Testinfra和Goss這樣的工具有助於自動化這些驗證。
我將著重介紹Testinfra,因為它是用Python編寫的,是Molecule的預設驗證器。想法很簡單:使用Python自動化你的驗證。
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
在開發環境中,該指令碼將使用SSH(就像Ansible)連線到目標主機以執行上述驗證(包存在/版本和服務狀態):
py.test --connection=ssh --hosts=server
簡而言之,在基礎架構自動化開發過程中,面臨的挑戰是配置新的基礎架構,針對它們執行playbook,驗證你的變更體現了你在playbooks中宣告的狀態。
- Testinfra能驗證什麼?
- 這些自動化測試提供了哪些安全措施?
- 執行復雜的變更或引入新功能而不破壞現有行為(比如,新增對基於Debian的系統的支援後,仍可以在基於RHEL的發行版中執行)。
- 釋出Ansible的新版本並引入新的最佳實踐時,重構/改進程式碼庫。
到目前為止,我們對Vagrant、Ansible和Testinfra所做的工作很容易與四階段測試模式中描述的步驟對應起來――這種測試結構方法使測試目標清晰。它包括下列階段:安裝、演練、驗證和拆除:
- 安裝:為測試執行準備環境(比如啟用新的虛擬機器):
vagrant up
- 演練:針對測試的系統有效地執行程式碼(即Ansible playbook):
vagrant provision
- 驗證:驗證上一步的輸出:
py.test(針對Testinfra)
- 拆除:回到安裝前的狀態:
vagrant destroy
我們用於特定playbook的同一個想法可以運用於角色開發和測試,但每當開發新產品時是否需要執行所有這些步驟?如果你想使用容器或OpenStack而不是Vagrant,該怎麼辦?如果你寧願使用Goss而不是Testinfra,該怎麼辦?如何針對你程式碼中的每次變更持續執行此操作?有沒有一種更簡單快速的方法來使用自動化測試開發playbook和角色?
Molecule
Molecule使用測試幫助開發角色。該工具甚至可以用測試用例初始化新角色:molecule init role –role-name foo。
Molecule很靈活,足以讓你可以將不同的驅動程式用於基礎架構配置,包括Docker、Vagrant、OpenStack、GCE、EC2和Azure。它還允許使用不同的伺服器驗證工具,包括Testinfra和Goss。
它的命令簡化了開發工作流程中常用任務的執行:
- lint-執行yaml-lint、ansible-lint和flake8,如果有問題報告故障
- syntax-驗證角色的語法錯誤
- create-建立驅動程式已配置的例項
- prepare-使用準備playbook來配置例項
- converge-執行鍼對主機的playbook
- idempotence-執行兩次playbook;萬一第二次執行出現變更,就失效(非冪等)
- verify-執行伺服器狀態驗證工具(testinfra或goss)
- destroy-銷燬例項
- test-執行前面的所有步驟
login命令可用於連線到已配置的伺服器用於故障排查。
逐步操作
你如何從根本沒有測試到針對每次變更/提交執行一個體面的程式碼庫?
1. virtualenv(可選)
virtualenv工具建立孤立的環境,而virtualenvwrapper是便於使用virtualenv的擴充套件件的集合。
這些工具可防止Molecule與計算機中其他Python包之間的依賴項和衝突。
sudo pip install virtualenvwrapper export WORKON_HOME=~/envs source /usr/local/bin/virtualenvwrapper.sh mkvirtualenv mocule
2. Molecule
安裝帶Docker驅動程式的Molecule:
pip install molecule ansible docker-py
生成帶測試場景的新角色:
molecule init role -r role_name
或者針對現有角色:
molecule init scenario -r my-role
所有必要的配置都是使用你的角色生成,你只要使用Testinfra編寫測試用例:
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角色的該示例測試用例驗證OS服務已啟用,程序在偵聽埠8080,身份驗證已正確配置。
為這些測試編寫程式碼很簡單,你基本上需要考慮一種自動驗證方法。
你登入到playbook針對的機器或者為監視/警報系統構建驗證時,你已經在編寫測試。 這有助於使用Testinfra API或使用系統命令來構建內容。
CI
持續執行Molecule測試很簡單。上述示例適用於帶Docker驅動程式的TravisCI,但它可能很容易改動,適合Molecule支援的任何CI伺服器和任何基礎架構驅動程式。
--- sudo: required language: python services: - docker before_install: - sudo apt-get -qq update - pip install molecule - pip install docker-py script: - molecule test
訪問 ofollow,noindex" target="_blank">Travis CI 以獲取示例輸出。
原文標題:Testing Ansible roles with Molecule,作者:Jairo da Silva Junior
【51CTO譯稿,合作站點轉載請註明原文譯者和出處為51CTO.com】
【責任編輯:龐桂玉 TEL:(010)68476606】