Thursday, October 3, 13 1files.meetup.com/8763012/Opscode_AWS CICD Meetup_101713.pdf · Speaker...

Preview:

Citation preview

1Thursday, October 3, 13

Testing Your Chef Infrastructure CodeTDD Your Infrastructure With Chefspec, Test-Kitchen, & Serverspec

2Thursday, October 3, 13

Speaker Introduction

Charles JohnsonSolutions Engineer, Opscodecharles@opscode.com@chipadeedoodah

3Thursday, October 3, 13

Your Infrastructure Code Isn’t “Just Scripts”

4Thursday, October 3, 13

Cookbooks Are Source Code• Chef Cookbook source code is just like the source

code for other programs.

• Changes are tracked and versioned with source control software such as git

• Code is inert until it has been deployed

• Code can be used to re-create the desired system configuration from scratch

5Thursday, October 3, 13

Cookbooks Are Artifacts• Chef Cookbook artifacts are just like the artifacts for other

programs.• Cookbooks are packaged for distribution• Cookbooks are deployed• Cookbooks are released with versions• Cookbooks are immutable once deployed• Cookbooks can depend on one another

6Thursday, October 3, 13

Cookbooks Are Artifacts

Close Encounters of the Third Kind, copyright 1977, Columbia Pictures

“This means something! This is important!”

7Thursday, October 3, 13

Cookbooks Are Artifacts

• Depending entirely on context,your infrastructure code can be either source code OR artifact.

Close Encounters of the Third Kind, copyright 1977, Columbia Pictures

“This means something! This is important!”

7Thursday, October 3, 13

Cookbooks Are Artifacts• This sounds obvious, but it’s easy to overlook:

Treating infrastructure code only as source code or only as artifacts will lead to long-term problems when using code to manage infrastructure.

Source'Code' Ar+fact'

• A good infrastructure code workflow treats code appropriately depending on context

8Thursday, October 3, 13

Code Can (Help)9Thursday, October 3, 13

But wait... Isn’t Chef a declarative language?

10Thursday, October 3, 13

• Chef itself is a testing engine. Either the intent expressed is executed, or the Chef run fails!

Yes! Chef is Declarative!package "apache2" do action :installend

template "/etc/apache2/apache2.conf" do source "apache2.conf.erb" owner "root" group "root" mode "0644" variables(:allow_override => "All") notifies :reload, "service[apache2]"end

service "apache2" do action [:enable,:start] supports :reload => trueend

11Thursday, October 3, 13

• Code Linting:

• Is my code properly formed?

• Signal in: Unit test

• Did I send Chef the correct command?

• Signal Processing: Convergence

• Did Chef interpret my command correctly?

• Signal out: Acceptance test

• Did my expressed intent, executed by Chef, achieve the desired result?

What and When To Test

Flickr user: Rain Rabbit

12Thursday, October 3, 13

Chef Testing Tools

13Thursday, October 3, 13

Chef Testing Tools• Linting: Foodcritic, Rubocop

http://acrmp.github.io/foodcritic/https://github.com/bbatsov/rubocop

13Thursday, October 3, 13

Chef Testing Tools• Linting: Foodcritic, Rubocop

http://acrmp.github.io/foodcritic/https://github.com/bbatsov/rubocop

• Unit Testing: Chefspechttps://github.com/acrmp/chefspec

13Thursday, October 3, 13

Chef Testing Tools• Linting: Foodcritic, Rubocop

http://acrmp.github.io/foodcritic/https://github.com/bbatsov/rubocop

• Unit Testing: Chefspechttps://github.com/acrmp/chefspec

• Convergence Testing: Test-Kitchenhttps://github.com/opscode/test-kitchen

13Thursday, October 3, 13

Chef Testing Tools• Linting: Foodcritic, Rubocop

http://acrmp.github.io/foodcritic/https://github.com/bbatsov/rubocop

• Unit Testing: Chefspechttps://github.com/acrmp/chefspec

• Convergence Testing: Test-Kitchenhttps://github.com/opscode/test-kitchen

• Acceptance Testing: ServerSpechttp://serverspec.org

13Thursday, October 3, 13

Berkshelf• Cookbook manager

• No more maintaining copies ofunmodified community cookbooksin a personal repo!

• Automatically resolves all cookbook dependencies

• Artifact installer• If you’re familiar with bundler,

berks is easy• Integrates tightly with...

14Thursday, October 3, 13

Make a Test Recipe

15Thursday, October 3, 13

$ knife cookbook create -o . myface

Create New Cookbook

** Creating cookbook myface** Creating README for cookbook: myface** Creating CHANGELOG for cookbook: myface** Creating metadata for cookbook: myface

16Thursday, October 3, 13

OPEN IN EDITOR: myface/Gemfile

source 'https://rubygems.org'

gem 'berkshelf', '~> 2.0'gem 'chefspec', '~> 2.0'gem 'foodcritic', '~> 2.2'gem 'rubocop', '~> 0.12'

group :integration do gem 'test-kitchen', '~> 1.0.0.beta' gem 'kitchen-ec2', '~> 0.7.0'end

Set Up Gemfile

17Thursday, October 3, 13

OPEN IN EDITOR: myface/Berksfile

site :opscodemetadata

group :integration do cookbook 'apt', '~> 2.0'end

Set Up Berksfile

18Thursday, October 3, 13

OPEN IN EDITOR: myface/recipes/default.rb

## Cookbook Name:: myface# Recipe:: default## Copyright 2013, Charles Johnson## All rights reserved - Do Not Redistribute#

package "apache2" do action :installend

service "apache2" do action [:enable,:start] supports :reload => trueend

Edit default recipe

19Thursday, October 3, 13

Chefspec- Signal In / Unit Test

20Thursday, October 3, 13

How ChefSpec Works

Sysadmin / Developer

21Thursday, October 3, 13

How ChefSpec Works

$rspec

Sysadmin / Developer

$ mock node$ mock chef-client converge$ verify test assertions$ report results

in-memory test

21Thursday, October 3, 13

How ChefSpec Works

$rspec

Sysadmin / Developer

..

Finished in 0.0222 seconds2 examples, 0 failures

21Thursday, October 3, 13

$ cd myface myface $ bundle install

Install Test Suite Bundle

Fetching gem metadata from https://rubygems.org/......Resolving dependencies...Installing i18n (0.6.5)Installing multi_json (1.8.0)...Using bundler (1.3.5)Your bundle is complete!Use `bundle show [gemname]` to see where a bundled gem is installed.

22Thursday, October 3, 13

myface $ mkdir -p spec/unit/recipes

Create Unit Test Directories

(no output)

23Thursday, October 3, 13

OPEN IN EDITOR: spec/spec_helper.rb

require 'chefspec'require 'berkshelf'

Berkshelf.ui.mute do Berkshelf::Berksfile.from_file('Berksfile').install(path: 'vendor/cookbooks/')end

RSpec.configure do |c| c.after(:suite) do # Berks will infinitely nest vendor/cookbooks/ntp on each rspec run # https://github.com/RiotGames/berkshelf/issues/828 FileUtils.rm_rf('vendor/') endend

Create the Chefspec spec_helper.rb

24Thursday, October 3, 13

OPEN IN EDITOR: myface/recipes/default.rb

## Cookbook Name:: myface# Recipe:: default## Copyright 2013, Charles Johnson## All rights reserved - Do Not Redistribute#

package "apache2" do action :installend

service "apache2" do action [:enable,:start] supports :reload => trueend

One more time: The Default Recipe

25Thursday, October 3, 13

OPEN IN EDITOR: spec/unit/recipes/default_spec.rb

require 'spec_helper'

describe 'myface::default' do let (:chef_run) { ChefSpec::ChefRunner.new.converge 'myface::default' }

it "installs apache2" do expect(chef_run).to install_package 'apache2' end

it "starts and enables the apache2 service" do expect(chef_run).to start_service 'apache2' expect(chef_run).to set_service_to_start_on_boot 'apache2' endend

Create default_spec.rb

26Thursday, October 3, 13

OPEN IN EDITOR: spec/unit/recipes/default_spec.rb

require 'spec_helper'

describe 'myface::default' do let (:chef_run) { ChefSpec::ChefRunner.new.converge 'myface::default' }

it "installs apache2" do expect(chef_run).to install_package 'apache2' end

it "starts and enables the apache2 service" do expect(chef_run).to start_service 'apache2' expect(chef_run).to set_service_to_start_on_boot 'apache2' endend

Create default_spec.rb

26Thursday, October 3, 13

OPEN IN EDITOR: spec/unit/recipes/default_spec.rb

require 'spec_helper'

describe 'myface::default' do let (:chef_run) { ChefSpec::ChefRunner.new.converge 'myface::default' }

it "installs apache2" do expect(chef_run).to install_package 'apache2' end

it "starts and enables the apache2 service" do expect(chef_run).to start_service 'apache2' expect(chef_run).to set_service_to_start_on_boot 'apache2' endend

Create default_spec.rb

26Thursday, October 3, 13

myface $ rspec

Run Chefspec Test Suite

..

Finished in 0.02124 seconds2 examples, 0 failures

27Thursday, October 3, 13

Test Kitchen- Signal Processing / Convergence Test

28Thursday, October 3, 13

How Test-Kitchen Works

Cloud Provisioner(Amazon EC2)

Sysadmin / Developer

29Thursday, October 3, 13

How Test-Kitchen Works

$ kitchen test

Cloud Provisioner(Amazon EC2)

https

Instances

Sysadmin / Developer

29Thursday, October 3, 13

How Test-Kitchen Works

$ kitchen test

Cloud Provisioner(Amazon EC2)

https

Instances

ssh

$ install Chef$ configure Chef$ copy cookbook$ run Chef$ report results

Sysadmin / Developer

29Thursday, October 3, 13

How Test-Kitchen Works

$ kitchen test

Cloud Provisioner(Amazon EC2)

https

Sysadmin / Developer

Chef Client finished, 4 resources updated Finished converging <default-ubuntu-1004> (1m24.99s).-----> Kitchen is finished. (1m25.45s)

29Thursday, October 3, 13

OPEN IN EDITOR: .kitchen.yml

---driver_plugin: ec2driver_config: availability_zone: us-east-1a aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> aws_ssh_key_id: <%= ENV['EC2_SSH_KEY_NAME'] %> ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> flavor_id: m1.small require_chef_omnibus: true

platforms:- name: ubuntu-10.04suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}

Create Kitchen.yml

30Thursday, October 3, 13

OPEN IN EDITOR: .kitchen.yml

---driver_plugin: ec2driver_config: availability_zone: us-east-1a aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> aws_ssh_key_id: <%= ENV['EC2_SSH_KEY_NAME'] %> ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> flavor_id: m1.small require_chef_omnibus: true...

Create Kitchen.yml

31Thursday, October 3, 13

OPEN IN EDITOR: .kitchen.yml

...platforms:- name: ubuntu-10.04

suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}

Create Kitchen.yml

32Thursday, October 3, 13

OPEN IN EDITOR: .kitchen.yml

---driver_plugin: ec2driver_config: availability_zone: us-east-1a aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> aws_ssh_key_id: <%= ENV['EC2_SSH_KEY_NAME'] %> ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> flavor_id: m1.small require_chef_omnibus: true

platforms:- name: ubuntu-10.04

suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}

Create Kitchen.yml

33Thursday, October 3, 13

myface $ kitchen test

Test Myface

-----> Starting Kitchen (v1.0.0.beta.3)-----> Cleaning up any prior instances of <default-ubuntu-1004>...-----> Testing <default-ubuntu-1004>-----> Creating <default-ubuntu-1004> EC2 instance <i-e941558c> created.-----> Converging <default-ubuntu-1004>... (Lots of Chef happens here) Resolving cookbook dependencies with BerkshelfUsing myface (0.1.0)Using apt (2.1.1)... (Lots more Chef) Finished converging <default-ubuntu-1004> (1m24.99s).-----> Kitchen is finished. (1m25.45s)

34Thursday, October 3, 13

Bussers & ServerSpec- Signal Out / Acceptance Test

35Thursday, October 3, 13

Instance

$ install Chef$ configure Chef$ copy cookbook$ run Chef

How Kitchen Bussers Work

36Thursday, October 3, 13

Instance

$ install Chef$ configure Chef$ copy cookbook$ run Chef

If acceptance tests present:$ install acceptance test framework$ copy acceptance tests$ run acceptance suite

$ report results

How Kitchen Bussers Work

36Thursday, October 3, 13

Currently Supported Bussers• Minitest

• Not to be confused with chef-minitest-handler. Straight minitest, no fancy Chef-specific matchers or assertions.https://github.com/fnichol/busser-minitest

• BATS• Bash-based acceptance testing & host inspection.

https://github.com/sstephenson/bats

• ServerSpec

• Young project, aims to provide rspec-based testing & host inspection.http://serverspec.org

37Thursday, October 3, 13

myface $ mkdir -p test/integration/default/serverspec/localhost

Create Serverspec Test Directories

(no output)

38Thursday, October 3, 13

OPEN IN EDITOR: test/integration/default/serverspec/spec_helper.rb

require 'serverspec'require 'pathname'

include Serverspec::Helper::Execinclude Serverspec::Helper::DetectOS

RSpec.configure do |c| c.before :all do c.os = backend(Serverspec::Commands::Base).check_os endend

Create the ServerSpec spec_helper.rb

39Thursday, October 3, 13

OPEN IN EDITOR: test/integration/default/serverspec/localhost/default_spec.rb

require 'spec_helper'

describe 'myface::default recipe' do

it 'Enables & starts the apache2 service' do expect(service 'apache2').to be_running expect(service 'apache2').to be_enabled end

end

Create the ServerSpec spec_helper.rb

40Thursday, October 3, 13

OPEN IN EDITOR: test/integration/default/serverspec/localhost/default_spec.rb

require 'spec_helper'

describe 'myface::default recipe' do

it 'Enables & starts the apache2 service' do expect(service 'apache2').to be_running expect(service 'apache2').to be_enabled end

end

Create the ServerSpec spec_helper.rb

40Thursday, October 3, 13

myface $ kitchen verify

Test Myface

-----> Starting Kitchen (v1.0.0.beta.3)-----> Cleaning up any prior instances of <default-ubuntu-1004>... (all the same stuff from before)-----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/opt/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /opt/busser/suites/serverspec/localhost/default_spec.rb .

Finished in 0.12308 seconds 1 example, 0 failures Finished verifying <default-ubuntu-1004> (0m8.99s).-----> Kitchen is finished. (1m34.66s)

41Thursday, October 3, 13

Put It All Together

42Thursday, October 3, 13

Chef Testing Tools

43Thursday, October 3, 13

Chef Testing Tools

• Unit Testing: Chefspechttps://github.com/acrmp/chefspec

43Thursday, October 3, 13

Chef Testing Tools

• Unit Testing: Chefspechttps://github.com/acrmp/chefspec

• Convergence Testing: Test-Kitchenhttps://github.com/opscode/test-kitchen

43Thursday, October 3, 13

Chef Testing Tools

• Unit Testing: Chefspechttps://github.com/acrmp/chefspec

• Convergence Testing: Test-Kitchenhttps://github.com/opscode/test-kitchen

• Acceptance Testing: ServerSpechttp://serverspec.org

43Thursday, October 3, 13

• New initiative: Upgrade or replace all Ubuntu 10.04 instances with Ubuntu 12.04.

New Edict: Upgrade to Ubuntu 12.04

Flickr user: iheartubuntu

44Thursday, October 3, 13

• New initiative: Upgrade or replace all Ubuntu 10.04 instances with Ubuntu 12.04.

• Because we have a comprehensive automated test suite, we can easily test our infrastructure code and deploy with confidence.

New Edict: Upgrade to Ubuntu 12.04

Flickr user: iheartubuntu

44Thursday, October 3, 13

OPEN IN EDITOR: .kitchen.yml

...platforms:- name: ubuntu-10.04- name: ubuntu-12.04

suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}

Create Kitchen.yml

45Thursday, October 3, 13

OPEN IN EDITOR: .kitchen.yml

...platforms:- name: ubuntu-10.04- name: ubuntu-12.04

suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}

Create Kitchen.yml

45Thursday, October 3, 13

OPEN IN EDITOR: .kitchen.yml

---driver_plugin: ec2driver_config: availability_zone: us-east-1a aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> aws_ssh_key_id: <%= ENV['EC2_SSH_KEY_NAME'] %> ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> flavor_id: m1.small require_chef_omnibus: true

platforms:- name: ubuntu-10.04- name: ubuntu-12.04suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}

Create Kitchen.yml

46Thursday, October 3, 13

myface $ kitchen test --parallel

Test Myface

-----> Starting Kitchen (v1.0.0.beta.3)-----> Creating <default-ubuntu-1004>-----> Creating <default-ubuntu-1204> EC2 instance <i-f1f43688> created. EC2 instance <i-2557e15d> created.... (Chef converges)... (ServerSpec tests) EC2 instance <i-f1f43688> created. EC2 instance <i-2557e15d> created. Finished testing <default-ubuntu-1004> (3m21.22s). Finished testing <default-ubuntu-1204> (3m54.97s).-----> Kitchen is finished. (3m55.45s)

47Thursday, October 3, 13

So What’s the Catch?

48Thursday, October 3, 13

• Test-Kitchen is in beta & still has bugs

It’s All Bleeding Edge

fanex.com

49Thursday, October 3, 13

• Test-Kitchen is in beta & still has bugs

• Serverspec is a young language

It’s All Bleeding Edge

fanex.com

49Thursday, October 3, 13

• Test-Kitchen is in beta & still has bugs

• Serverspec is a young language

• Chefspec is under heavy development

It’s All Bleeding Edge

fanex.com

49Thursday, October 3, 13

• Test-Kitchen is in beta & still has bugs

• Serverspec is a young language

• Chefspec is under heavy development

• Cookbook generators don’t cover all the boilerplate files & folders just yet

It’s All Bleeding Edge

fanex.com

49Thursday, October 3, 13

• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers

But Wait! There’s More!

Chris Notarile

50Thursday, October 3, 13

• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers

• Fancy tricks:

But Wait! There’s More!

Chris Notarile

50Thursday, October 3, 13

• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers

• Fancy tricks:

• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!

But Wait! There’s More!

Chris Notarile

50Thursday, October 3, 13

• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers

• Fancy tricks:

• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!

• The Future:

But Wait! There’s More!

Chris Notarile

50Thursday, October 3, 13

• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers

• Fancy tricks:

• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!

• The Future:

• Support for other CM systems

But Wait! There’s More!

Chris Notarile

50Thursday, October 3, 13

• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers

• Fancy tricks:

• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!

• The Future:

• Support for other CM systems

• Support for other bussers

But Wait! There’s More!

Chris Notarile

50Thursday, October 3, 13

• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers

• Fancy tricks:

• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!

• The Future:

• Support for other CM systems

• Support for other bussers

• Support for even more cloud provisioners

But Wait! There’s More!

Chris Notarile

50Thursday, October 3, 13

• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers

• Fancy tricks:

• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!

• The Future:

• Support for other CM systems

• Support for other bussers

• Support for even more cloud provisioners

• Cookbook generators that write all these extra boilerplate files for you

But Wait! There’s More!

Chris Notarile

50Thursday, October 3, 13

Who’s this guy, again?

Charles JohnsonSolutions Engineer, Opscodecharles@opscode.com@chipadeedoodah

51Thursday, October 3, 13

Questions

• Question & Answer

52Thursday, October 3, 13

Recommended