Infrastructures can be very big. Luckily, there are provisioner like Chef, Salt, Ansible and etc. These provisioners can be very complex and possibly the developer has done something wrong. Therefore the infrastructure has to be tested! Tools like goss, Serverspec and Testinfra helps testers to validate. This tutorial show the first steps with Testinfra.
Testinfra is written in Python very small and easy to understand. Here is the GitHub repository.
Precondition
- Vagrant (min. 1.9.3) installed
- Python (min. 2.7) installed
- pip (min. 9.0.1) and virtualenv (min. 15.1.0) installed
- make (min. 3.81) installed
Project structure
To get used to it – i prepared some files for you. You only need to change the box name/url in Vagrantfile.
$ tree . ├── Makefile ├── requirements.txt ├── Vagrantfile └── tests.py
ENV_DIR = .env CURRENT_DIR := $(shell pwd) INTERPRETER = $(CURRENT_DIR)/$(ENV_DIR)/bin/ PATH := ${PATH}:$(INTERPRETER) help: @echo "run make <target> with:" @echo " > env : create virtualenv directory $(ENV_DIR)" @echo " > deps : install dependencies from requirements.txt" @echo " > clean_env : delete virtualenv directory $(ENV_DIR)" @echo " > up : run vagrant up" @echo " > destroy : run vagrant destroy" @echo " > test : run testinfra on vagrant environment" @echo " > clean_all : delete all files and directories" env: @echo "[RUN]: create virtualenv" virtualenv $(ENV_DIR) && \ . $(ENV_DIR)/bin/activate && \ make deps deps: @echo "[RUN]: install dependencies" $(INTERPRETER)/pip install -r requirements.txt up: @echo "[RUN]: vagrant up" vagrant up destroy: @echo "[RUN]: vagrant destroy -f" vagrant destroy -f rm -fr $(CURRENT_DIR)/.vagrant test: @echo "[RUN]: run testinfr on vagrant environment" vagrant ssh-config > $(CURRENT_DIR)/ssh-config $(INTERPRETER)/pytest -v --hosts=default --ssh-config=$(CURRENT_DIR)/ssh-config tests.py clean_all: @echo "[RUN]: delete all files and directories" rm -fr $(CURRENT_DIR)/.cache $(CURRENT_DIR)/__pycache__ rm -f $(CURRENT_DIR)/ssh-config make destroy make clean_env clean_env: @echo "[RUN]: delete virtualenv" rm -fr $(ENV_DIR)
testinfra==1.5.4 paramiko==2.1.2
#!/usr/bin/env python def test_system_type(SystemInfo): '''Check OS type''' type = SystemInfo.type assert type == 'linux' def test_user_exists(User): '''Check user exists''' user = User('vagrant') assert user.exists def test_firewalld_is_installed(Package): '''Check firewalld is installed''' package = Package('firewalld') assert package.is_installed def test_firewalld_running_and_enabled(Service): '''Check firewalld service is running and enabled''' service = Service('firewalld') assert service.is_running assert service.is_enabled
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| # disable ssh key update config.ssh.insert_key = false # vagrant box name config.vm.box = "" # vagrant box url config.vm.box_url = "" # disable box update config.vm.box_check_update = false # disable synced_folder config.vm.synced_folder ".", "/vagrant", disabled: true # 2nd network interface (public) # config.vm.network "public_network" # virtualbox settings config.vm.provider "virtualbox" do |vb| vb.name = "example_vm" vb.cpus = "2" vb.memory = "2048" vb.gui = false end end
Usage
# create virtualenv and install dependencies $ make env # create vagrant environment $ make up # run tests $ make test # delete all generated files and directories $ make clean_all
Testinfra offers several connections backends for remote command execution and can be used with python standard unit test framework: unittest. So the integration with build servers is easily possible.