Professional Documents
Culture Documents
Velocity Accessible
Velocity Accessible
sethvargo@opscode.com
yz E b
BB
WORKSTATION SETUP
BB
#LEARNCHEF
BB
BB
!!
GITHUB
fd
i myface
gist.github.com/5737141
f myface d Gemfile
Gemfile
source 'https://rubygems.org' group :test do gem 'chefspec', '~> gem 'foodcritic', '~> gem 'strainer', '~> gem 'test-kitchen', '~> gem 'kitchen-lxc', '~> gem 'knife-spork', '~> gem 'hipchat', '~> 1.3' 2.1' 3.0' 1.0.0.alpha' 0.0.1.beta1' 1.0.17' 0.10.0'
gem 'guard', '~> 1.8' gem 'guard-foodcritic', '~> 1.0' gem 'guard-rspec', '~> 3.0' end
$ (sudo) bundle
spec/default_spec.rb
require 'spec_helper' describe 'sethvargo-myface::default' do let(:chef_run) do run = ChefSpec::ChefRunner.new(platfrom: 'ubuntu', version: '12.04') run.converge('sethvargo-myface::default') end it 'installs apache2' do expect(chef_run).to install_package('apache2') end # ... end
spec/spec_helper.rb
require 'chefspec'
Guardfile
guard :rspec, all_on_start: false do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^(recipes)/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } watch('spec/spec_helper.rb') { 'spec' } end ! guard :foodcritic, cookbook_paths: '.', all_on_start: false do watch(%r{attributes/.+\.rb$}) watch(%r{providers/.+\.rb$}) watch(%r{recipes/.+\.rb$}) watch(%r{resources/.+\.rb$}) end
!+ S
0.0134s
Strainerfile
knife: foodcritic: rspec: bundle exec knife cookbook test $COOKBOOK bundle exec foodcritic $SANDBOX/$COOKBOOK -f any (cd $COOKBOOK && bundle exec rspec --color)
recipes/default.rb
package 'apache2' service 'apache2' do action [:enable, :start] end
!+ S
POLICY CHANGE
RUN
UNIT TESTS
BEFORE MERGING TO
MASTER
RUN
UNIT TESTS
BEFORE MERGING TO
MASTER
u HUMAN (PROS) D h a J K
HUMAN (CONS) t
7 c L r M
CREATE REPO
GITHUB INTERFACE
?
T myface
T (anything)
Create repository
SETUP JOB
ci.trychef.com
J New
Job
T {username}-myface
J Build
a free-style...
J OK
T (github
URL)
J Git
T git://github.com/...
J Build
when a change...
J Color
ANSI Console...
J Add
Build Step
J Execute
Shell
J Email
Notification
T (your
email)
J Save
J Build
Now
J (the
build)
SETUP HOOK
J Settings
J Service
Hooks
J Jenkins
(GitHub Plugin)
http://ci.trychef.com/github-webhook/
http://ci.trychef.com/github-webhook/
IMPORTANT
J Active
J Update
settings
spec/default_spec.rb
describe 'sethvargo-myface::default' do # pre-existing tests # ... it 'creates the default template' do expect(chef_run).to create_file('/var/www/index.html') end it 'creates the site with the correct content' do template = chef_run.template('/var/www/index.html') expect(template.owner).to eq('root') expect(template.group).to eq('root') end end
recipes/default.rb
package 'apache2' service 'apache2' do action [:enable, :start] end template '/var/www/index.html' do owner 'root' group 'root' mode '0755' source 'index.html.erb' end
templates/default/index.html.erb
<html> <head> <title>Welcome to <%= node['fqdn'] %></title> </head> <body> <p>Here's everything you need to know about <%= node['fqdn'] %>:</p> <pre><%= JSON.pretty_generate(node.to_hash) %></pre> </body> </html>
J Pull
Request
J Send
pull request
J Merge
pull request
J (the
build)
J Console
Output
metadata.rb
name maintainer maintainer_email license description long_description version 'myface' 'YOUR_COMPANY_NAME' 'YOUR_EMAIL' 'All rights reserved' 'Installs/Configures myface' IO.read(File.join(File.dirname(__FILE__), 'README.md')) '0.1.0'
metadata.rb
name maintainer maintainer_email license description long_description version 'myface' 'Seth Vargo' 'sethvargo@opscode.com' 'All rights reserved' 'Installs/Configures myface' IO.read(File.join(File.dirname(__FILE__), 'README.md')) '0.1.0'
AWESOME
WHY?
1 WE HAVE TESTS
J Configure
J Add
post-build action
J Post
build task
T Strainer
marked build OK
J
T
J Save
J Build
Now
J (the
build)
J Console
Output
AWESOME
BUT DO WE KNOW
ARE UPLOADED TO OUR CHEF SERVER?
BUT DO WE KNOW
ARE UPLOADED TO OUR CHEF SERVER?
jonlives/knife-spork
jonlives/knife-spork
jonlives/knife-spork
J Configure
J Escalate
script execution...
J Save
hipchat.com/sign_in
J Launch
J Try
Chef
J Build
Now
THERE'S MORE!
THERE'S MORE!
TEST KITCHEN!
f myface d .kitchen.yml
.kitchen.yml
driver_plugin: lxc driver_config: use_sudo: true platforms: - name: ubuntu-12.04 driver_config: base_container: ubuntu_12.04 username: ubuntu password: ubuntu suites: - name: default run_list: ["recipe[myface]"] attributes: {}
Strainerfile
knife: foodcritic: rspec: kitchen: bundle exec knife cookbook test $COOKBOOK bundle exec foodcritic $SANDBOX/$COOKBOOK -f any (cd $COOKBOOK && bundle exec rspec --color) (cd $COOKBOOK && bundle exec kitchen test)
metadata.rb
name maintainer maintainer_email license description long_description version 'myface' 'Seth Vargo' 'sethvargo@opscode.com' 'All rights reserved' 'Installs/Configures myface' IO.read(File.join(File.dirname(__FILE__), 'README.md')) '0.1.0'
metadata.rb
name maintainer maintainer_email license description long_description version 'myface' 'Seth Vargo' 'sethvargo@opscode.com' 'All rights reserved' 'Installs/Configures myface' IO.read(File.join(File.dirname(__FILE__), 'README.md')) '0.1.1'
UH OH!
some_recipe.rb
template owner group source end '/etc/foo/bar' do 'root' 'root' 'bar.erb'
some_recipe.rb
template owner group source end '/etc/foo/bar' do 'root' 'root' 'bar.erb'
IF WE REMOVE THIS
WILL THE FILE BE DELETED?
some_recipe.rb
template owner group source end '/etc/foo/bar' do 'root' 'root' 'bar.erb'
NO
some_recipe.rb
template owner group source end '/etc/foo/bar' do 'root' 'root' 'bar.erb'
some_recipe.rb
template owner group source action end '/etc/foo/bar' do 'root' 'root' 'bar.erb' :delete
$ git add . $ git commit -m "Revert abc123" $ git push origin master
environments/production.json
{ "name" : "production", "description" : "Production cluster in EC2", "override_attributes" : { ... }, "default_attributes" : { ... } }
environments/production.json
{ "name" : "production", "description" : "Production cluster in EC2", "override_attributes" : { ... }, "default_attributes" : { ... }, "cookbook_versions" : { "myface": "0.1.0" }, }
CD
CD
PUSH
CD
PUSH
sethvargo@opscode.com
yz E b