Project: Chef InSpec (Provisioning / Security & Compliance)
File: migration.md

+++ title = "Serverspec Migration Guide" draft = false gh_repo = "inspec" [menu] [menu.inspec] title = "Migration from Serverspec" identifier = "inspec/friends/migration.md Migration from Serverspec" parent = "inspec/friends" weight = 20 +++ We've written a complete blog post about that topic: Chef InSpec is a framework that allows you to run infrastructure testing as well as compliance testing. The compliance features are always optional and provide customers a way to use Chef InSpec for both use-cases. To ensure we build the best infrastructure testing, we migrate our cookbooks to InSpec. The following resources are available in Chef InSpec: | Serverspec | Chef InSpec | |::|::| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Some Serverspec resources are not available yet. We will implement those resources based on user feedback. If you need a resource that is not available in InSpec, please open an . The list of resources that are not available in InSpec: In addition Chef InSpec provides additional that are not available in Serverspec: For most cases, the migration to Chef InSpec is pretty straight forward. First, replace the current verifier in `kitchen.yml` configuration with: ```yaml verifier: name: inspec ``` Second, rename the directory `test/integration/default/serverspec` to `test/integration/default/inspec` Third, remove the Serverspec-specific code from the test files. ``` require 'serverspec' set :backend, :exec ``` Chef InSpec is now configured with Test-Kitchen: ```bash kitchen verify package-install-centos-72 --> Starting Kitchen (v1.14.2) --> Verifying <package-install-centos-72>... Detected alternative framework tests for `inspec` Loaded Target: ssh://vagrant@127.0.0.1:2200 PHP has php the pear.php.net channel the pecl.php.net channel Test Summary: 3 successful, 0 failures, 0 skipped Finished verifying <package-install-centos-72> (0m0.40s). --> Kitchen is finished. (0m3.31s) ``` Some real-world migrations are available: Some general recommendations: use test-kitchen 1.14+ in case of errors, increase the log level `kitchen verify package-install-centos-72 -l debug` Chef InSpec does not attach backend information to test files. All tests are defined independently of any backend. Therefore a Serverspec test file: ```ruby require 'serverspec' set :backend, :exec describe 'PHP' do it 'has php' do expect(command('php -v').exit_status).to eq(0) end it 'has the pear.php.net channel' do expect(command('pear list-channels').stdout).to include('pear.php.net') end it 'has the pecl.php.net channel' do expect(command('pear

include('pecl.php.net') end end ``` will become the following Chef InSpec test file: ```ruby describe 'PHP' do it 'has php' do expect(command('php -v').exit_status).to eq(0) end it 'has the pear.php.net channel' do expect(command('pear list-channels').stdout).to include('pear.php.net') end it 'has the pecl.php.net channel' do expect(command('pear list-channels').stdout).to include('pecl.php.net') end end ``` As you can see, the Chef InSpec test files just focuses on tests and tries to avoid all clutter. Serverspec and RSpec allow you to define nested describe blocks. We did a survey and found out that most users use nested describe blocks only to improve their output report. We believe the code structure should not change to improve the output of a report. Nevertheless we understand that nested describe blocks help you to structure test code. A sample code block looks like: ```ruby describe 'chef-server-directories' do describe file('/etc/opscode') do it { should be_directory } it { should beownedby 'root' } end describe file('/etc/opscode-analytics') do it { should be_directory } it { should beownedby 'opscode' } it { should begroupedinto 'opscode' } end describe file('/var/log/opscode') do it { should be_directory } it { should beownedby 'opscode' } it { should begroupedinto 'opscode' } end describe file('/var/opt/opscode') do it { should be_directory } it { should beownedby 'root' } end end ``` In Chef InSpec you would split up groups into files. ``` tests server-directories.rb other-tests.rb further-tests.rb ``` Each file can have a top-level description of its content: ```ruby title "Chef Server Directories" describe file('/etc/opscode') do it { should be_directory } it { should beownedby 'root' } end describe file('/etc/opscode-analytics') do it { should be_directory } it { should beownedby 'opscode' } it { should begroupedinto 'opscode' } end describe file('/var/log/opscode') do it { should be_directory } it { should beownedby 'opscode' } it { should begroupedinto 'opscode' } end describe file('/var/opt/opscode') do it { should be_directory } it { should beownedby 'root' } end ``` Of course. We still prefer the `should` syntax for UX reasons. We did surveys with various types of customers like devops engineers, auditors, managers. All participants who preferred the `expect` syntax have been Ruby experts. All non-Ruby developers found it easier to understand the `should` syntax. ```ruby describe command('php -v') do its('exit_status') { should eq 0 } end describe command('pear list-channels') do its('stdout') { should include('pear.php.net')} end describe command('pear list-channels') do its('stdout') { should include('pecl.php.net')} end ``` ```ruby describe 'PHP' do it 'has php' do expect(command('php -v').exit_status).to eq(0) end it 'has the pear.php.net channel' do expect(command('pear list-channels').stdout).to include('pear.php.net') end it 'has the pecl.php.net channel' do expect(command('pear list-channels').stdout).to include('pecl.php.net') end end ```