Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Continuous Integration for Infrastructure

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

Continuous Integration for Infrastructure

Lots of examples of emerging infrastructure testing patterns. Test Kitchen, Puppet, Docker, Serverspec, Packer, Bats and more. Presented at #craftconf in Budapest

Avatar for Gareth Rushgrove

Gareth Rushgrove

April 25, 2014
Tweet

More Decks by Gareth Rushgrove

Other Decks in Technology

Transcript

  1. - install-packages: packages: ruby1.9.1-dev - script: name: install bundler code:

    sudo gem install bundler - bundle-install - script: name: print ruby version code: ruby —version wercker.yaml Gareth Rushgrove
  2. - install-packages: packages: ruby1.9.1-dev - script: name: install bundler code:

    sudo gem install bundler - bundle-install - script: name: print ruby version code: ruby —version wercker.yaml Gareth Rushgrove 1 2 3 4
  3. - install-packages: packages: ruby1.9.1-dev - script: name: install bundler code:

    sudo gem install bundler - bundle-install - script: name: print ruby version code: ruby —version wercker.yaml Gareth Rushgrove
  4. Run code against short lived virtual machines and make assertions

    against the resulting state Gareth Rushgrove
  5. --- driver: name: digitalocean ! provisioner: name: shell ! platforms:

    - name: ubuntu-12.04 ! suites: - name: default provisioner: script: scripts/bootstrap.sh .kitchen.yml Gareth Rushgrove
  6. platforms: - name: ubuntu-14.04 - name: ubuntu-13.10 - name: centos-6.5

    - name: centos-6.4 - name: ubuntu-12.04 - name: centos-6.4 - name: centos-6.4 - name: archlinux-2013.05 .kitchen.yml Gareth Rushgrove
  7. describe service('ntp') do it { should be_enabled } it {

    should be_running } end serverspec/sample_spec.rb Gareth Rushgrove
  8. Package "ntp" should be installed ! Service "ntp" should be

    enabled should be running ! Finished in 0.11191 seconds 3 examples, 0 failures Finished verifying <default-ubuntu-1310> (0m7.39s). -----> Destroying <default-ubuntu-1310>... Digital Ocean instance <1493500> destroyed. Finished destroying <default-ubuntu-1310> (0m4.47s). Finished testing <default-ubuntu-1310> (3m59.40s). -----> Kitchen is finished. (3m59.95s) Gareth Rushgrove
  9. Packer is a tool for creating identical machine images for

    multiple platforms from a single source configuration Gareth Rushgrove
  10. { "variables": { "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}" },

    "builders": [{ "type": "amazon-ebs", "access_key": "{{user `aws_access_key`}}", "secret_key": "{{user `aws_secret_key`}}", "region": "eu-west-1", "source_ami": "ami-480bea3f", "instance_type": "t1.micro", "ssh_username": "ubuntu", "ami_name": "packer-serverspec-example-{{timestamp}}" }], "provisioners": [{ "type": "shell", "script": "scripts/puppet.sh" }, { "type": "file", template.json Gareth Rushgrove
  11. ! "provisioners": [{ "type": "shell", "script": "scripts/puppet.sh" }, { "type":

    "puppet-masterless", "manifest_file": "manifests/site.pp", "hiera_config_path": "hiera.yaml", "module_paths": ["modules"] } template.json Gareth Rushgrove
  12. ! "provisioners": [{ "type": "shell", "script": "scripts/puppet.sh" }, { "type":

    "puppet-masterless", "manifest_file": "manifests/site.pp", "hiera_config_path": "hiera.yaml", "module_paths": ["modules"] } template.json Gareth Rushgrove
  13. #!/bin/bash ! # Install language locale as without can #

    interfere with package installation sudo apt-get install language-pack-en -y ! # Install Ruby sudo apt-get update sudo apt-get install ruby1.9.1 -y ! # Install puppet/facter sudo gem install puppet facter --no-ri --no-rdoc scripts/puppet.sh Gareth Rushgrove
  14. ! "provisioners": [{ "type": "shell", "script": "scripts/puppet.sh" }, { "type":

    "puppet-masterless", "manifest_file": "manifests/site.pp", "hiera_config_path": "hiera.yaml", "module_paths": ["modules"] } template.json Gareth Rushgrove
  15. class ExampleSimulation extends Simulation { val httpConf = http.baseURL("http://www.example.com") !

    val sample = scenario("Simple example").exec( http("Homepage").get("/").check(status.is(200))) ! setUp(sample.inject(ramp(3 users) over (10 seconds))) .protocols(httpConf) } ExampleSimulation.scala Gareth Rushgrove
  16. --- droplets: - name: production.web.1 - name: production.web.2 - name:

    production.app.1 size: 64 - name: production.app.2 size: 64 - name: production.db.1 size: 69 vars/droplets.yml Gareth Rushgrove
  17. #!/usr/bin/env bats ! @test "addition using bc" { result="$(echo 2+2

    | bc)" [ "$result" -eq 4 ] } ! @test "addition using dc" { result="$(echo 2 2+p | dc)" [ "$result" -eq 4 ] } example.bats Gareth Rushgrove
  18. @test "no droplets exist" { run tugboat droplets [ "$status"

    -eq 0 ] [ "${lines[0]}" = "You don't appear to have any droplets." ] } ! @test "provisioner runs successfully" { run ansible-playbook -i hosts provision_digital_ocean.yml [ "$status" -eq 0 ] } acceptance.bats Gareth Rushgrove
  19. @test “we can count the correct number of machines" {

    run bash -c "ansible -i hosts all --list-hosts | wc - l | tr -d ' '" [ "$status" -eq 0 ] [ "$output" -eq 5 ] } acceptance.bats Gareth Rushgrove
  20. @test "per host serverspec tests pass" { run rake spec

    [ "$status" -eq 0 ] } acceptance.bats Gareth Rushgrove
  21. ✓ no droplets exist ✓ provisioner runs successfully ✓ we

    can count the correct number of hosts ✓ we can list the new hosts ✓ all host serverspec tests pass ✓ clean up all droplets ✓ droplets have been cleaned up ! 7 tests, 0 failures Gareth Rushgrove