testing ansible roles with test kitchen, serverspec and rspec
TRANSCRIPT
1 #Dynatrace
with Test Kitchen, Serverspec and RSpec
Testing Ansible Roles
AnsibleMeetup
2 #Dynatrace
Insertimage here Martin Etmajer
Senior Technology Strategist at Dynatrace
@metmajer
3 #Dynatrace
4 #Dynatrace
Linz, Austria
5 #Dynatrace
We Ansible
6 #Dynatrace
We Ansible
7 #Dynatrace
We Ansible
On-Premise Public Cloud
Hybrid
8 #Dynatrace
Why test?
9 #Dynatrace
You write code!
10 #Dynatrace
“Make it work. Make it right. Make it fast.”
Kent Beck, Creator of Extreme Programming and Test-Driven Development
Get the code to
operate correctly
Make the code clear,
enforce good design Optimize
11 #Dynatrace
The Red, Green, Refactor Cycle of TDD
Write a Failing Test
Make the Test PassClean Up your Code
Small increments
Able to return to known working code
Designed and
tested code
Protects against regressions
12 #Dynatrace
Agile Infrastructure
Undone WIP Done
13 #Dynatrace
Test KitchenKey Concepts
Pluggable Architecture
14 #Dynatrace
Drivers let you run your code on various...
Cloud Providers
» Azure, Cloud Stack, EC2, Digital Ocean, GCE, Rackspace,...
Virtualization Technologies
» Vagrant, Docker, LXC
Test Kitchen: Drivers
15 #Dynatrace
Platforms are the Operating Systems you want to run on.
Platforms
» Linux- or Windows-based (since latest Test Kitchen 1.4.0)
How to manage dependencies?
» Automatically resolved when using Vagrant or Docker
» Build your own and link them in the configuration file
Test Kitchen: Platforms
16 #Dynatrace
Provisioners are the tools used to converge the environment.
Provisioners
» Ansible, Chef, CFEngine, Puppet, SaltStack
Why cool?
» Useful if you need to support multiple of these tools
Test Kitchen: Provisioners
17 #Dynatrace
Test Suites define the tests to run against each platform.
Test Frameworks
» Bash, Bats, Cucumber, RSpec, Serverspec
Test Kitchen: Test Suites
18 #Dynatrace
Test KitchenInstallation
19 #Dynatrace
Installation
Ready?
$ gem install test-kitchen
Test Kitchen: Installation
$ kitchen version
Test Kitchen version 1.4.0
20 #Dynatrace
Test KitchenConfiguration
21 #Dynatrace
Create an Ansible Role Directory
Initialize Test Kitchen
$ mkdir –p ansible/roles/foo
$ cd ansible/roles/foo
Test Kitchen: Testing an Ansible Role
$ kitchen init [--driver=vagrant] --provisioner=ansible_playbook
create .kitchen.yml
create test/integration/default
Configuration goes here!Tests go here!
22 #Dynatrace
.kitchen.yml (as provided via `kitchen init`)
---
driver:
name: vagrant
provisioner:
name: ansible_playbook
platforms:
- name: ubuntu-12.04
- name: centos-6.4
suites:
- name: default
run_list:
attributes:
Test Kitchen: Testing an Ansible Role
Naming Convention:
Opscode Vagrant Boxes
at www.vagrantbox.es
23 #Dynatrace
.kitchen.yml (slightly adjusted)
---
driver:
name: vagrant
customize:
cpus: 2
memory: 2048
cpuexecutioncap: 50
provisioner:
name: ansible_playbook
hosts: test-kitchen
ansible_verbose: false
ansible_verbosity: 2
Test Kitchen: Testing an Ansible Role
platforms:
- name: ubuntu-12.04
- name: centos-6.4
suites:
- name: default
24 #Dynatrace
$ kitchen list
Instance Driver Provisioner Transport Last Action
default-ubuntu-1204 Vagrant AnsiblePlaybook Ssh <Not Created>
default-centos-64 Vagrant AnsiblePlaybook Ssh <Not Created>
`kitchen list`: List Test Kitchen Instances
Test Kitchen: Installation
This will change...Test Suite Platform
25 #Dynatrace
Test KitchenWrite an Integration Test
26 #Dynatrace
Create an Ansible Playbook for Test Suite ‘default’
Test Kitchen: Testing an Ansible Role
$ kitchen init [--driver=vagrant] --provisioner=ansible_playbook
create .kitchen.yml
create test/integration/default
Configuration goes here!Tests go here!
27 #Dynatrace
test/integration/default/default.yml
---
- hosts: test-kitchen
pre_tasks:
...
roles:
- foo
post_tasks:
...
Test Kitchen: Testing an Ansible Role
Create yourenvironment
Ansible Playbook
Test Suite
28 #Dynatrace
Serverspec and RSpecA Short Primer
29 #Dynatrace
RSpec is a TDD tool for Ruby programmers.
RSpec
require ‘foo’
describe Foo do
before do
@foo = Foo.new
end
it ‘method #bar does something useful’ do
@foo.bar.should eq ‘something useful’
end
end
30 #Dynatrace
Serverspec are RSpec tests for your infrastructure.
Serverspec
require ‘serverspec’
describe user(‘foo’) do
it { should exist }
it { should belong_to_group ‘foo’ }
end
describe file(‘/opt/bar’) do
it { should be_directory }
it { should be_mode 777 }
it { should be_owned_by ‘foo’ }
it { should be_grouped_into ‘foo’ }
end
describe service(‘bar’) do
it { should be_enabled }
it { should be_running }
end
describe port(8080) do
it { should be_listening }
end
describe command(‘apachectl –M’) do
its(:stdout) { should contain(‘proxy_module’) }
end
Resource
Matcher
31 #Dynatrace
test/integration/default/serverspec/default_spec.rb
require ‘serverspec’
describe user(‘foo’) do
it { should exist }
it { should belong_to_group ‘foo’ }
end
Test Kitchen: Testing an Ansible Role
Test
Test Suite Do Serverspec!
32 #Dynatrace
`kitchen test`: Run Test Kitchen Test
Test Kitchen: Testing an Ansible Role
$ kitchen test default-ubuntu-1204
$ kitchen test ubuntu
$ kitchen testregex!
$ kitchen list
Instance Driver Provisioner Transport Last Action
default-ubuntu-1204 Vagrant AnsiblePlaybook Ssh <Not Created>
default-centos-64 Vagrant AnsiblePlaybook Ssh <Not Created>
33 #Dynatrace
Test Kitchen: Actions
Test = Converge Setup Verify
Instance createdand provisioned
Instance prepared(dependencies installed)
34 #Dynatrace
`kitchen test`: Run Test Kitchen Test
$ kitchen test ubuntu
...
User "foo"
should exist
should belong to group "foo"
Finished in 0.14825 seconds (files took 0.6271 seconds to load)
2 examples, 0 failures
Finished verifying <default-ubuntu-1204> (0m37.21s).
Test Kitchen: Testing an Ansible Role
35 #Dynatrace
`kitchen list`: List Test Kitchen Instances
Test Kitchen: Testing an Ansible Role
$ kitchen list
Instance Driver Provisioner Transport Last Action
default-ubuntu-1204 Vagrant AnsiblePlaybook Ssh Verified
default-centos-64 Vagrant AnsiblePlaybook Ssh <Not Created>
36 #Dynatrace
Test Kitchen with AnsibleAdvanced Tips
37 #Dynatrace
Resolving Role Requirements
38 #Dynatrace
.kitchen.yml
---
driver:
name: vagrant
customize:
cpus: 2
memory: 2048
cpuexecutioncap: 50
provisioner:
name: ansible_playbook
hosts: test-kitchen
requirements_path: requirements.yml
ansible_verbose: false
ansible_verbosity: 2
Test Kitchen: Resolve Role Requirements
platforms:
- name: ubuntu-12.04
- name: centos-6.4
suites:
- name: default
Declare required roles
on Ansible Galaxy, GitHub,
or Git, Mercurial, etc. repos
39 #Dynatrace
Testing Ansible Rolesin Amazon EC2
40 #Dynatrace
.kitchen.yml
---
driver:
name: ec2
aws_access_key_id: "<%= ENV['AWS_ACCESS_KEY_ID']%>"
aws_secret_access_key: "<%= ENV['AWS_SECRET_ACCESS_KEY']%>"
aws_ssh_key_id: "<%= ENV['AWS_SSH_KEY_ID']%>"
region: eu-west-1
availability_zone: eu-west-1b
transport:
ssh_key: "<%= ENV['AWS_SSH_KEY_PATH']%>"
username: admin
...
Test Kitchen: Testing Ansible Roles in EC2
Environment Variables
41 #Dynatrace
Testing REST APIswith RSpec
Not supported by Serverspec
42 #Dynatrace
Serverspec are RSpec tests for your infrastructure.
Serverspec
require ‘serverspec’
describe user(‘foo’) do
it { should exist }
it { should belong_to_group ‘foo’ }
end
describe file(‘/opt/bar’) do
it { should be_directory }
it { should be_mode 777 }
it { should be_owned_by ‘foo’ }
it { should be_grouped_into ‘foo’ }
end
describe service(‘bar’) do
it { should be_enabled }
it { should be_running }
end
describe port(8080) do
it { should be_listening }
end
describe command(‘apachectl –M’) do
its(:stdout) { should contain(‘proxy_module’) }
end
Resource
Matcher
43 #Dynatrace
test/integration/default/rspec/default_spec.rb
require ‘json’
require ‘net/http’
...
describe ‘Server REST API’ do
it ‘/rest/foo responds correctly’ do
uri = URI(‘http://localhost:8080/rest/foo’)
request = Net::HTTP::Get.new(uri, { ‘Accept’ => ‘application/json’ })
request.basic_auth(‘foo’, ‘foo’)
response = Net::HTTP.new(uri.host, uri.port).request(request)
expect(response.code).to eq 200
expect(JSON.parse(response.body)).to eq { ‘bar’ => ‘baz’ }
end
end
Test Kitchen: Testing REST APIs
Do RSpec!Could use serverspec!
44 #Dynatrace
Questions?
45 #Dynatrace