1 #Dynatrace
with Ansible, Test Kitchen, Serverspec and RSpec
Test-Driven Infrastructure
DevOps Days
Berlin
2 #Dynatrace
Insert
image here
Technology Strategist at Dynatrace
martin.etmajer@dynatrace.com
@metmajer
Martin Etmajer
3 #Dynatrace
Why Continuous Delivery?
4 #Dynatrace
Why Continuous Delivery?
5 #Dynatrace
Utmost Goal: Minimize Cycle Time
feature cycle time time
Customer Users
6 #Dynatrace
Utmost Goal: Minimize Cycle Time
feature cycle time time
Customer minimize Users
7 #Dynatrace
Utmost Goal: Minimize Cycle Time
feature cycle time time
Customer
This is when you
create value!
minimize
8 #Dynatrace
Utmost Goal: Minimize Cycle Time
feature cycle time time
Customer
You
This is when you
create value!
minimize
9 #Dynatrace
Utmost Goal: Minimize Cycle Time
feature cycle time time
Customer
You
minimize
It’s about getting your features into your users’ hands
as quickly and confidently as possible!
10 #Dynatrace
Align Development and IT Operations
IT OPERATIONS
DEVELOPMENT
time
11 #Dynatrace
Align Development and IT Operations
IT OPERATIONS
DEVELOPMENT
current iteration
(e.g. 2-week time-box)
time
12 #Dynatrace
Align Development and IT Operations
IT OPERATIONS
DEVELOPMENT
current iteration
(e.g. 2-week time-box)
time
Planning
13 #Dynatrace
Align Development and IT Operations
IT OPERATIONS
DEVELOPMENT
current iteration
(e.g. 2-week time-box)
time
Planning
Implementing
and testing
14 #Dynatrace
Align Development and IT Operations
IT OPERATIONS
DEVELOPMENT
current iteration
(e.g. 2-week time-box)
time
Planning
Implementing
and testing
Working and
deployable code
15 #Dynatrace
Test-Driven Infrastructure
16 #Dynatrace
You write code!
17 #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
18 #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
19 #Dynatrace
» Refactoring
» simplify
» modularize (use 3rd-party Ansible roles)
» Migrating to different Platforms
» OS
» Cloud Providers
» Migrating to different Automation Tool
» Ansible, Chef, Puppet
» Bash, Perl, etc.
Why you shouldn’t rely on a single tool?
20 #Dynatrace
» Refactoring
» simplify
» modularize (use 3rd-party Ansible roles)
» Migrating to different Platforms
» OS
» Cloud Providers
» Migrating to different Automation Tool
» Ansible, Chef, Puppet
» Bash, Perl, etc.
Why you shouldn’t rely on a single tool?
With TDD you express your intentions twice:
once in the code and once in the test.
If they don’t match, tests fail and you’ve caught a bug!
21 #Dynatrace
Test Kitchen
Key Concepts
Pluggable Architecture
22 #Dynatrace
» Drivers
» Platforms
» Provisioners
» Test Suites
Key Concepts
23 #Dynatrace
» Drivers
» Platforms
» Provisioners
» Test Suites
Key Concepts
24 #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
25 #Dynatrace
» Drivers
» Platforms
» Provisioners
» Test Suites
Key Concepts
26 #Dynatrace
Platforms are the Operating Systems you want to run on.
Platforms
» Linux- or Windows-based (since Test Kitchen 1.4.0)
How to manage dependencies?
» Automatically resolved when using Docker or Vagrant
» Build your own and link them in the configuration file
Test Kitchen: Platforms
27 #Dynatrace
» Drivers
» Platforms
» Provisioners
» Test Suites
Key Concepts
28 #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
29 #Dynatrace
» Drivers
» Platforms
» Provisioners
» Test Suites
Key Concepts
30 #Dynatrace
Test Suites define the tests to run against each platform.
Test Frameworks
» Bash, Bats, Cucumber, RSpec, Serverspec
Test Kitchen: Test Suites
31 #Dynatrace
Test Kitchen
Installation
32 #Dynatrace
Installation
Ready?
$ gem install test-kitchen kitchen-docker kitchen-ansible
Test Kitchen: Installation
$ kitchen version
Test Kitchen version 1.4.2
33 #Dynatrace
Test Kitchen
Configuration
34 #Dynatrace
Create an Ansible Role
Initialize Test Kitchen
$ mkdir –p ansible/roles/my-role
$ cd ansible/roles/my-role
Test Kitchen: Testing an Ansible Role
$ kitchen init --driver=docker --provisioner=ansible_playbook
create .kitchen.yml
create test/integration/default
Configuration goes here!
Tests go here!
35 #Dynatrace
.kitchen.yml (as provided via `kitchen init`)
---
driver:
name: docker
provisioner:
name: ansible_playbook
platforms:
- name: ubuntu-14.04
- name: centos-7.1
suites:
- name: default
run_list:
attributes:
Test Kitchen: Testing an Ansible Role
Names resolve to
Docker Images on
the Docker Hub
36 #Dynatrace
.kitchen.yml (slightly adjusted)
---
driver:
name: docker
provisioner:
name: ansible_playbook
hosts: test-kitchen
ansible_verbose: false
ansible_verbosity: 2
Test Kitchen: Testing an Ansible Role
platforms:
- name: ubuntu-14.04
- name: centos-7.1
suites:
- name: default
37 #Dynatrace
$ kitchen list
Instance Driver Provisioner Transport Last Action
default-ubuntu-1404 Docker AnsiblePlaybook Ssh <Not Created>
default-centos-71 Docker AnsiblePlaybook Ssh <Not Created>
`kitchen list`: List Test Kitchen Instances
Test Kitchen: Installation
This will change...Test Suite Platform
38 #Dynatrace
Test Kitchen
Write an Integration Test
39 #Dynatrace
Create an Ansible Playbook for Test Suite ‘default’
Test Kitchen: Testing an Ansible Role
$ kitchen init --driver=docker --provisioner=ansible_playbook
create .kitchen.yml
create test/integration/default
Configuration goes here!
Tests go here!
40 #Dynatrace
test/integration/default/default.yml
---
- hosts: test-kitchen
pre_tasks:
...
roles:
- my-role
post_tasks:
...
Test Kitchen: Testing an Ansible Role
Create your
environment
Ansible Playbook
Test Suite
41 #Dynatrace
Serverspec and RSpec
A Short Primer
42 #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
43 #Dynatrace
Serverspec is RSpec 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
44 #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!
45 #Dynatrace
`kitchen test`: Run Test Kitchen Tests
Test Kitchen: Testing an Ansible Role
$ kitchen test default-ubuntu-1404
$ kitchen test ubuntu
$ kitchen test
regex!
$ kitchen list
Instance Driver Provisioner Transport Last Action
default-ubuntu-1404 Docker AnsiblePlaybook Ssh <Not Created>
default-centos-71 Docker AnsiblePlaybook Ssh <Not Created>
46 #Dynatrace
Test Kitchen: Stages
test = converge verify destroy
Instance created and provisioned
Instance tested and verified
47 #Dynatrace
`kitchen verify`: Run Test Kitchen Tests
$ kitchen verify 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-1404> (0m37.21s).
Test Kitchen: Testing an Ansible Role
48 #Dynatrace
`kitchen list`: List Test Kitchen Instances
Test Kitchen: Testing an Ansible Role
$ kitchen list
Instance Driver Provisioner Transport Last Action
default-ubuntu-1404 Docker AnsiblePlaybook Ssh Verified
default-centos-71 Docker AnsiblePlaybook Ssh <Not Created>
49 #Dynatrace
Test Kitchen with Ansible
Advanced Tips
50 #Dynatrace
Resolving Role Requirements
51 #Dynatrace
.kitchen.yml
---
driver:
name: docker
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-14.04
- name: centos-7.1
suites:
- name: default
Declare required roles
on Ansible Galaxy, GitHub,
or Git, Mercurial, etc. repos
52 #Dynatrace
Testing Ansible Roles
in Amazon EC2
53 #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
54 #Dynatrace
Testing REST APIs
with RSpec
Not supported by Serverspec
55 #Dynatrace
test/integration/default/serverspec/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
56 #Dynatrace
Dynatrace-Ansible Project
Further Examples: https://github.com/dynaTrace/Dynatrace-Ansible
57 #Dynatrace
58 #Dynatrace
Demo Time!
59 #Dynatrace
Questions?
60 #Dynatrace

Test-Driven Infrastructure with Ansible, Test Kitchen, Serverspec and RSpec

  • 1.
    1 #Dynatrace with Ansible,Test Kitchen, Serverspec and RSpec Test-Driven Infrastructure DevOps Days Berlin
  • 2.
    2 #Dynatrace Insert image here TechnologyStrategist at Dynatrace martin.etmajer@dynatrace.com @metmajer Martin Etmajer
  • 3.
  • 4.
  • 5.
    5 #Dynatrace Utmost Goal:Minimize Cycle Time feature cycle time time Customer Users
  • 6.
    6 #Dynatrace Utmost Goal:Minimize Cycle Time feature cycle time time Customer minimize Users
  • 7.
    7 #Dynatrace Utmost Goal:Minimize Cycle Time feature cycle time time Customer This is when you create value! minimize
  • 8.
    8 #Dynatrace Utmost Goal:Minimize Cycle Time feature cycle time time Customer You This is when you create value! minimize
  • 9.
    9 #Dynatrace Utmost Goal:Minimize Cycle Time feature cycle time time Customer You minimize It’s about getting your features into your users’ hands as quickly and confidently as possible!
  • 10.
    10 #Dynatrace Align Developmentand IT Operations IT OPERATIONS DEVELOPMENT time
  • 11.
    11 #Dynatrace Align Developmentand IT Operations IT OPERATIONS DEVELOPMENT current iteration (e.g. 2-week time-box) time
  • 12.
    12 #Dynatrace Align Developmentand IT Operations IT OPERATIONS DEVELOPMENT current iteration (e.g. 2-week time-box) time Planning
  • 13.
    13 #Dynatrace Align Developmentand IT Operations IT OPERATIONS DEVELOPMENT current iteration (e.g. 2-week time-box) time Planning Implementing and testing
  • 14.
    14 #Dynatrace Align Developmentand IT Operations IT OPERATIONS DEVELOPMENT current iteration (e.g. 2-week time-box) time Planning Implementing and testing Working and deployable code
  • 15.
  • 16.
  • 17.
    17 #Dynatrace “Make itwork. 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
  • 18.
    18 #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
  • 19.
    19 #Dynatrace » Refactoring »simplify » modularize (use 3rd-party Ansible roles) » Migrating to different Platforms » OS » Cloud Providers » Migrating to different Automation Tool » Ansible, Chef, Puppet » Bash, Perl, etc. Why you shouldn’t rely on a single tool?
  • 20.
    20 #Dynatrace » Refactoring »simplify » modularize (use 3rd-party Ansible roles) » Migrating to different Platforms » OS » Cloud Providers » Migrating to different Automation Tool » Ansible, Chef, Puppet » Bash, Perl, etc. Why you shouldn’t rely on a single tool? With TDD you express your intentions twice: once in the code and once in the test. If they don’t match, tests fail and you’ve caught a bug!
  • 21.
    21 #Dynatrace Test Kitchen KeyConcepts Pluggable Architecture
  • 22.
    22 #Dynatrace » Drivers »Platforms » Provisioners » Test Suites Key Concepts
  • 23.
    23 #Dynatrace » Drivers »Platforms » Provisioners » Test Suites Key Concepts
  • 24.
    24 #Dynatrace Drivers letyou run your code on various... Cloud Providers » Azure, Cloud Stack, EC2, Digital Ocean, GCE, Rackspace,... Virtualization Technologies » Vagrant, Docker, LXC Test Kitchen: Drivers
  • 25.
    25 #Dynatrace » Drivers »Platforms » Provisioners » Test Suites Key Concepts
  • 26.
    26 #Dynatrace Platforms arethe Operating Systems you want to run on. Platforms » Linux- or Windows-based (since Test Kitchen 1.4.0) How to manage dependencies? » Automatically resolved when using Docker or Vagrant » Build your own and link them in the configuration file Test Kitchen: Platforms
  • 27.
    27 #Dynatrace » Drivers »Platforms » Provisioners » Test Suites Key Concepts
  • 28.
    28 #Dynatrace Provisioners arethe 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
  • 29.
    29 #Dynatrace » Drivers »Platforms » Provisioners » Test Suites Key Concepts
  • 30.
    30 #Dynatrace Test Suitesdefine the tests to run against each platform. Test Frameworks » Bash, Bats, Cucumber, RSpec, Serverspec Test Kitchen: Test Suites
  • 31.
  • 32.
    32 #Dynatrace Installation Ready? $ geminstall test-kitchen kitchen-docker kitchen-ansible Test Kitchen: Installation $ kitchen version Test Kitchen version 1.4.2
  • 33.
  • 34.
    34 #Dynatrace Create anAnsible Role Initialize Test Kitchen $ mkdir –p ansible/roles/my-role $ cd ansible/roles/my-role Test Kitchen: Testing an Ansible Role $ kitchen init --driver=docker --provisioner=ansible_playbook create .kitchen.yml create test/integration/default Configuration goes here! Tests go here!
  • 35.
    35 #Dynatrace .kitchen.yml (asprovided via `kitchen init`) --- driver: name: docker provisioner: name: ansible_playbook platforms: - name: ubuntu-14.04 - name: centos-7.1 suites: - name: default run_list: attributes: Test Kitchen: Testing an Ansible Role Names resolve to Docker Images on the Docker Hub
  • 36.
    36 #Dynatrace .kitchen.yml (slightlyadjusted) --- driver: name: docker provisioner: name: ansible_playbook hosts: test-kitchen ansible_verbose: false ansible_verbosity: 2 Test Kitchen: Testing an Ansible Role platforms: - name: ubuntu-14.04 - name: centos-7.1 suites: - name: default
  • 37.
    37 #Dynatrace $ kitchenlist Instance Driver Provisioner Transport Last Action default-ubuntu-1404 Docker AnsiblePlaybook Ssh <Not Created> default-centos-71 Docker AnsiblePlaybook Ssh <Not Created> `kitchen list`: List Test Kitchen Instances Test Kitchen: Installation This will change...Test Suite Platform
  • 38.
  • 39.
    39 #Dynatrace Create anAnsible Playbook for Test Suite ‘default’ Test Kitchen: Testing an Ansible Role $ kitchen init --driver=docker --provisioner=ansible_playbook create .kitchen.yml create test/integration/default Configuration goes here! Tests go here!
  • 40.
    40 #Dynatrace test/integration/default/default.yml --- - hosts:test-kitchen pre_tasks: ... roles: - my-role post_tasks: ... Test Kitchen: Testing an Ansible Role Create your environment Ansible Playbook Test Suite
  • 41.
    41 #Dynatrace Serverspec andRSpec A Short Primer
  • 42.
    42 #Dynatrace RSpec isa 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
  • 43.
    43 #Dynatrace Serverspec isRSpec 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
  • 44.
    44 #Dynatrace test/integration/default/serverspec/default_spec.rb require ‘serverspec’ describeuser(‘foo’) do it { should exist } it { should belong_to_group ‘foo’ } end Test Kitchen: Testing an Ansible Role Test Test Suite Do Serverspec!
  • 45.
    45 #Dynatrace `kitchen test`:Run Test Kitchen Tests Test Kitchen: Testing an Ansible Role $ kitchen test default-ubuntu-1404 $ kitchen test ubuntu $ kitchen test regex! $ kitchen list Instance Driver Provisioner Transport Last Action default-ubuntu-1404 Docker AnsiblePlaybook Ssh <Not Created> default-centos-71 Docker AnsiblePlaybook Ssh <Not Created>
  • 46.
    46 #Dynatrace Test Kitchen:Stages test = converge verify destroy Instance created and provisioned Instance tested and verified
  • 47.
    47 #Dynatrace `kitchen verify`:Run Test Kitchen Tests $ kitchen verify 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-1404> (0m37.21s). Test Kitchen: Testing an Ansible Role
  • 48.
    48 #Dynatrace `kitchen list`:List Test Kitchen Instances Test Kitchen: Testing an Ansible Role $ kitchen list Instance Driver Provisioner Transport Last Action default-ubuntu-1404 Docker AnsiblePlaybook Ssh Verified default-centos-71 Docker AnsiblePlaybook Ssh <Not Created>
  • 49.
    49 #Dynatrace Test Kitchenwith Ansible Advanced Tips
  • 50.
  • 51.
    51 #Dynatrace .kitchen.yml --- driver: name: docker 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-14.04 - name: centos-7.1 suites: - name: default Declare required roles on Ansible Galaxy, GitHub, or Git, Mercurial, etc. repos
  • 52.
    52 #Dynatrace Testing AnsibleRoles in Amazon EC2
  • 53.
    53 #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
  • 54.
    54 #Dynatrace Testing RESTAPIs with RSpec Not supported by Serverspec
  • 55.
    55 #Dynatrace test/integration/default/serverspec/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
  • 56.
    56 #Dynatrace Dynatrace-Ansible Project FurtherExamples: https://github.com/dynaTrace/Dynatrace-Ansible
  • 57.
  • 58.
  • 59.
  • 60.

Editor's Notes

  • #17 And as we are dealing with code - “infrastructure as code” namely – why shouldn’t we apply the same principles that help us create better software to create better infrastructure? After all, a bug in the environment may have more severe consequences than a bug in a software.
  • #18 See: - http://c2.com/cgi/wiki?MakeItWorkMakeItRightMakeItFast
  • #19 See: http://www.jamesshore.com/Agile-Book/test_driven_development.html http://blog.goyello.com/2011/09/13/red-green-refactor-cycle/