Your infrastructure as an application. - Automation, the killer app. A true app. - Version environments, speed up cycles. - Turn the focus back to the business. What is infrastructure as code?
not mean tested - Business value of your ‘app’ - Tests are outcome focused* - Investment in quality - CI/CD, continuous testing or monitoring - CD is the new economy; customer service Why should you test infrastructure?
- Continuous all the things - Everyone loves DSLs - Focus on ruby tools, but extensible - API driven; how long is the build broken? Types of testing; tonight’s talk
OO, Func, Dynamic) - Conceived 1994, released 1995, English in 1998/99, more popular than Python in Japan by 2000 - Bundler, Gemfile - rbenv, rvm, chruby - DSL friendly Ruby, toolchain overview
admin privileges' do before :each do @admin = Admin.get(1) end it 'should exist' do expect(@admin).not_to be_nil end it 'should have a name' do expect(@admin.name).not_to be_false end end #... end Unit testing with rspec
'installs foo' do expect(chef_run).to install_package('foo') end end Unit testing with chefspec - Completely compatible with most chef tools - Stub other node data and environment data - Mock objects, return results
it 'creates dangerfile' do expect(chef_run).to create_cookbook_file('/tmp/dangerfile').with_owner('root'). with_mode('00644') end end Chefspec demo (line cookbook)
OS with no package name specified" do let :facts do { :osfamily => 'Debian' } end it { should contain_package('httpd').with( { 'name' => 'apache2' } ) should contain_service('httpd').with( { 'name' => 'apache2' } ) } end end Unit testing with puppet (labs_spec_helper)
'foo'} } it do expect { should contain_file('/etc/logrotate.d/nginx') }.to raise_error(Puppet::Error, /compress must be true or false/) end end it do should contain_service('apache').with( 'ensure' => 'running', 'enable' => 'true', 'hasrestart' => 'true', ) end Unit testing with puppet (rspec-puppet)
should be_installed } end describe package('apache2'), :if => os[:family] == 'ubuntu' do it { should be_installed } end describe service('httpd'), :if => os[:family] == 'redhat' do it { should be_enabled } it { should be_running } end describe service('apache2'), :if => os[:family] == 'ubuntu' do it { should be_enabled } it { should be_running } end describe port(80) do it { should be_listening } end Integration testing tools: serverspec
monit | grep Installed | grep -v none') end describe "services" do # You can assert that a service must be running following the converge: it "runs as a daemon" do assert system('/etc/init.d/monit status') end # And that it will start when the server boots: it "boots on startup" do assert File.exists?(Dir.glob("/etc/rc5.d/S*monit").first) end end end Integration testing tools: minitest
etc - Configuration is YAML files - Multiple test suites with different input options / test-scenarios - Still stub your cfg mgmt environment Drivers, configs, options, suites