ServerSpec is to check servers are configured correctly through their actual state using RSpec tests. Testinfra is kind of a Serverspec equivalent in Python and based on Pytest.
Prerequisite:
RVM, Ruby and rubygems are installed.
Python and pip are installed.
We would expect to run Testinfra and ServerSpec against the server rather than our local machine, so we may need to tweak a little bit by connecting the server with ssh key.
- Generate ssh key:
ssh-keygen -t rsa
- Copy ssh public key to server:
ssh-copy-id -i ~/.ssh/id_rsa.pub username@server
Add following lines to ~/.ssh/config.
12Host serverUser username
- Generate ssh key:
Get Started for ServerSpec:
Install ServerSpec.
gem install serverspec
Initial ServerSpec folder with basic settings. Please note the server will be set in this step.
serverspec-init
Write and run the ServerSpec script according to its API document.
You can reference the script here.
Using
rake spec
under the test folder to run and check the result.To run specific test rather than the entire test suite.
Using
rake spec spec/host_server/sample_spec.rb
under the test folder to run and check the result.To generate a html file as the test result, we can add
t.rspec_opts = '--format html --out reports/rspec_results.html'
in the Rakefile when new the Rake task. e.g.12345678910111213141516171819202122232425262728require 'rake'require 'rspec/core/rake_task'task :spec => 'spec:all'task :default => :specnamespace :spec dotargets = []Dir.glob('./spec/*').each do |dir|next unless File.directory?(dir)target = File.basename(dir)target = "_#{target}" if target == "default"targets << targetendtask :all => targetstask :default => :alltargets.each do |target|original_target = target == "_default" ? target[1..-1] : targetdesc "Run serverspec tests to #{original_target}"RSpec::Core::RakeTask.new(target.to_sym) do |t|ENV['TARGET_HOST'] = original_target+ t.rspec_opts = '--format html --out reports/test_results.html'endendendAnd it will generate the test result named “test_results.html” under “reports” folder every time the test runs.
Get Started for Testinfra:
Install Testinfra and Paramiko.
pip install testinfra
pip install paramiko
Write and run the Testinfra script according to its API document.
You can reference the script here.
Using
testinfra testinfra_test.py
to run and check the result.Some useful arguments we can use to make the test result more clear.
Instead of using
testinfra testinfra_test.py
directly, we can add some arguments, such as-q
,-s
,--disable-warnings
and--junit-xml
.- The argument
-q
will run Testinfra in quiet mode, with less info exposed - The argument
-s
will let Testinfra capture No pre-test info - The argument
--disable-warnings
will disable warnings during Testinfra runs - The argument
--junit-xml
will export Testinfra test result into a xml file
After adding those arguments, the command should be look like
testinfra -q -s --disable-warnings testinfra_test.py --junit-xml=report.xml
- The argument
Now we can run Testinfra against the server using
testinfra -q -s --disable-warnings --ssh-config=/Path/to/ssh/config --hosts=server testinfra_test.py --junit-xml=report.xml
.
Comparison between ServerSpec and Testinfra:
Advantages of ServerSpec
More documents and community support (compared to Testinfra);
The scripts, test results and reports are more readable (Testinfra is based on Pytest, and can only export report to XML not JSON);
Although Testinfra support “sysctl” and it runs successfully on the server, the command in script can’t run, and prompts error “bash: sysctl: command not found”; may also occurs to other commands/resources (potential risk);
ServerSpec can support more resources and attributes for resources than Testinfra.
Advantages of Testinfra
Can support most common resources, such as Docker, File, Group, Service, Socket and etc (equivalent to ServerSpec);
Can show the actual value when validating the permission but failed, so the debug will be quicker.
Conclusion
If you can only choose Python as your programming language, you have to use Testinfra; otherwise, I recommend ServerSpec because of the benefits it can bring.