Test driven infrastructure

  • 795 views
Uploaded on

In this talk for CukeUp Jon Topper investigates if we can apply a software testing approach to validate our infrastructure configuration.

In this talk for CukeUp Jon Topper investigates if we can apply a software testing approach to validate our infrastructure configuration.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
795
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
9
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Test-drivenInfrastructure Jon Topper
  • 2. What is Infrastructure?★ Physical Servers★ Virtual / Cloud Servers★ Switches★ Firewalls★ Routers★ Load Balancers
  • 3. 3 Year Infrastructure Lifecycle Change BuildRisk! 14% Operate 86%
  • 4. The Rise of DevOps★ Increased collaboration between developers and operations staff★ Improved tooling for automation★ “Dev” solutions to “Ops” problems
  • 5. Infrastructure as Code
  • 6. Puppetnode webserver { package { httpd: ensure => latest } file { /etc/httpd/httpd.conf: require => Package[httpd], owner => root, mode => 644, content => template(httpd.conf) } service { httpd: ensure => running, enable => true, require => File[/etc/httpd/httpd.conf] }}
  • 7. “Dev” Tooling★ IDEs, text editors, refactoring tools★ Version Control Systems★ Automated documentation generation★ ... Testing?
  • 8. Automated Infrastructure Testing★ cucumber-puppet / rspec-puppet★ cucumber-nagios★ puppet-lint★ cucumber-chef★ vagrant-guard-demo
  • 9. Cucumber ExampleScenario: Basic install of Apache Given there is a running VM called "server" When I apply a puppet manifest containing: """ include cucumber_defaults class { sf_apache: Port => 80, Children => 10 } """ Then a second manifest application should do nothing And there should be 11 processes called “httpd” running And the Apache module "core_module" should be loaded And a process called “httpd” should be listening on TCP port 80 And a GET request to http://localhost/server-status/ should return an http status of 200
  • 10. Given there is a running VM called "server"
  • 11. Vagrant★ Template (“Box”) based virtual environment★ Shared filesystem between host and guest★ Snapshot support via “Sahara” plugin★ API for scripted interaction http://vagrantup.com/
  • 12. Given there is a running VM called "server" Given /^there is a running VM called "([^"]*)"$/ do |vm_name| vm_platform.vm( vm_name ).start vm_platform.vm( vm_name ).snapshot end
  • 13. attr_reader :last_vmdef initialize @name_map = {}enddef vm(name) if @name_map.has_key?(name) @last_vm = @name_map[name] return @name_map[name] end vm = create_vm_object_by_name( name ) @name_map[name] = vm @last_vm = vm return vmenddef clean_tainted @name_map.each { |name,vm| vm.rollback @name_map.delete(name) }end
  • 14. When I apply a puppet manifest containing: """ include cucumber_defaults class { sf_apache: Port => 80, Children => 10 } """ Then a second manifest application should do nothing★ Fragment uploaded with SCP★ Puppet tasks run over Vagrant SSH link★ Included manifests read from Vagrant shared folder
  • 15. When /^I apply a puppet manifest(#{VMRE}) containing:$/ do |vmre, manifest_content| vm = identified_vm( vmre ) file = Tempfile.new(cucumber-puppet) begin file.write(manifest_content) file.fsync vm.upload(file.path,/tmp/cucumber-puppet.pp) @puppet_command ="puppet apply --verbose --modulepath=#{$puppet_modulepath} " + "--manifestdir=#{$puppet_manifestdir} --detailed-exitcodes --color=false " + "/tmp/cucumber-puppet.pp" exit_status = vm.sudo( @puppet_command ) do |type,data| data.chomp! puts data if data != “” end Test::Unit::assert( exit_status == 0 || exit_status == 2, Exit code of puppet run not 0 or 2 - errors ) ensure file.close file.unlink endend
  • 16. VMREVMRE ||= /(?: on the last VM| on the VM(?: called|) "(?:[^"]+)"|)/def identified_vm( str ) case str when /^( on the last VM|)$/ return vm_platform.last_vm when /^ on the VM(?: called|) "([^"]+)"$/ return @vm_platform.vm( $1 ) endend
  • 17. And a GET request to http://localhost/server-status/ should return an http status of 200Then /^a GET request to (.+)(#{VMRE}) should return an http status of (d+)$/do |url,vmre,status| vm = identified_vm( vmre ) response = vm.freeman.call(http.GET,url) assert( response[code].to_i == status.to_i, "Response code 200 expected from #{url}, " + "received #{response[code]}" )end★ ‘freeman’ is an XML-RPC service★ First call starts a new XML-RPC server in the guest★ Code shared over Vagrant’s folder system
  • 18. Full Stack Host Filesystem Features Step Definitions Cumberbatch Freeman Client Vagrant Library Freeman Sharedsshd Server Folder Vagrant VM
  • 19. Benefits★ Cleaner interfaces★ Improved separation of concerns★ Increased reusability★ Rapid troubleshooting★ Empowering for junior engineers
  • 20. Challenges★ Scenarios slow to run★ Difficult to debug when snapshot rolled back★ Multi-VM VirtualBox unstable on OS X★ Good use of Cucumber not always obvious to the sysadmin-minded
  • 21. Jon Topper jon@scalefactory.comhttp://www.scalefactory.com/ Twitter: @jtopper