Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spice up your recipes with Chef Sugar

Spice up your recipes with Chef Sugar

Slides from my ChefConf 2014 talk :)

502828deee7e3b38ca1e527dded8a1a9?s=128

Seth Vargo

April 16, 2014
Tweet

Transcript

  1. CHEF SUGAR

  2. Chef Sugar? More like crème brûlée. Beautiful Ruby code and

    exceedingly useful! “
  3. WHY?

  4. COOK-494

  5. COOK-494 "Create a core cookbook with useful primitives for system

    wrangling"
  6. COOK-494

  7. COOK-494

  8. COOK-494

  9. COOK-494

  10. COOK-494

  11. COOK-494 ✓

  12. COOK-494 ✓

  13. COOK-494 ✓

  14. COOK-494 ✓ ✓

  15. I LIED

  16. WELL NOW THIS IS AWKWARD...

  17. BACK UP

  18. CHEF SUGAR

  19. SETH

  20. SETH VARGO

  21. SETH VARGO @SETHVARGO

  22. SETH VARGO FAUXHAI CHEFSPEC BERKSHELF STOVE TEST KITCHEN @SETHVARGO

  23. SETH VARGO FAUXHAI CHEFSPEC BERKSHELF STOVE TEST KITCHEN #LEARNCHEF @SETHVARGO

  24. SETH VARGO FAUXHAI CHEFSPEC BERKSHELF STOVE TEST KITCHEN #LEARNCHEF @SETHVARGO

    (STUFF) ...
  25. SETH VARGO FAUXHAI CHEFSPEC BERKSHELF STOVE TEST KITCHEN #LEARNCHEF @SETHVARGO

    RELEASE ENGINEER (STUFF) ...
  26. SETH VARGO FAUXHAI CHEFSPEC BERKSHELF STOVE TEST KITCHEN #LEARNCHEF @SETHVARGO

    RELEASE ENGINEER (STUFF) ...
  27. THIS FUCKING GUARD

  28. YOU HAVE ALL DONE IT

  29. execute 'something' do command './configure && make && make install'

    not_if 'test -x /usr/local/bin/something' end
  30. execute 'something' do command './configure && make && make install'

    not_if 'test -x /usr/local/bin/something' end VERSION?
  31. execute 'something' do command './configure && make && make install'

    not_if <<-EOH.gsub(/^ {4}/, '') test -x /usr/local/bin/something && /usr/local/bin/something --version | grep 1.0 EOH end VERSION!
  32. execute 'something' do command './configure && make && make install'

    not_if <<-EOH.gsub(/^ {4}/, '') test -x#{install_path} && #{install_path} --version | grep #{version} EOH end DYNAMIC
  33. execute 'something' do command './configure && make && make install'

    not_if <<-EOH.gsub(/^ {4}/, '') test -x#{node['app']['config']['install_path']} && #{node['app']['config']['install_path']} --version | .. EOH end DYNAMIC
  34. AND THIS KEPT HAPPENING OVER 'N OVER

  35. AND IT IS VERY INEFFICIENT TO SHELL OUT

  36. execute 'something' do command './configure && make && make install'

    not_if { installed_at_version?('something', '1.0') } end SPOILER
  37. execute 'something' do command './configure && make && make install'

    not_if { installed_at_version?('something', '1.0') } end NO VERSION?
  38. execute 'something' do command './configure && make && make install'

    not_if { installed?('something') } end NO PROBLEM!
  39. execute 'something' do command './configure && make && make install'

    not_if do current = version_for('something').to_f current < 5.0 && current != 4.1 end end COMPLICATED?
  40. None
  41. None
  42. None
  43. None
  44. YO DAWG,
 LOOK WHAT I MADE!

  45. I'M PRETTY SURE THERE'S AN OPEN COOK TICKET...

  46. I'M PRETTY SURE THERE'S AN OPEN COOK TICKET...

  47. I'M PRETTY SURE THERE'S AN OPEN COOK TICKET...

  48. None
  49. COOK-494

  50. None
  51. None
  52. +

  53. + =

  54. + = CHEF SUGAR

  55. LÉ EXÄMPLES

  56. "CLOUD" templates '/tmp/config' do variables(use_vpc: cloud?) end

  57. DATA BAGS bag = Chef::EncryptedDataBagItem.load('accounts', 'hipchat') bag = encrypted_data_bag_item('accounts', 'hipchat')

  58. ATTRIBUTES default['apache2']['config']['root'] = '/var/www' namespace 'apache2' do namespace 'config' do

    root '/var/www' end end
  59. CONSTRAINTS Gem::Constraint.new('~> 11.0') .satisfied_by?(Gem::Version.new(Chef::VERSION)) chef_version.satisfies?('~> 11.0')

  60. GEMS require 'nokogiri' #=> LoadError, ugly stacktrace require_chef_gem 'nokogiri' #=>

    ! Chef could not load the gem `nokogiri'! You may need to install the gem manually with `gem install nokogiri', or include a recipe before you can use this resource. Please consult the documentation for this cookbook for proper usage.
  61. DEEP FETCH node['apache2']['config']['root'] #=> '/var/www' node.deep_fetch('apache2', 'config', 'root') #=> '/var/www'

  62. DEEP FETCH node['apache2']['bad_key']['root'] #=> Undefined method :[] for nil:NilClass node.deep_fetch('apache2',

    'bad_key', 'root') #=> nil
  63. DEEP FETCH node['apache2']['bad_key']['root'] #=> Undefined method :[] for nil:NilClass node.deep_fetch!('apache2',

    'bad_key', 'root') #=> No attribute node['apache2']['bad_key']['root'] exists on the current node. Please make sure you have spelled everything correctly.
  64. PLATFORMS if node['platform'] == 'ubuntu' if ubuntu?

  65. NAME PLATFORMS if node['platform'] == 'ubuntu' && node['platform_version'].to_f < 12.04

    if ubuntu_before_precise?
  66. NAME PLATFORMS debian_after_squeeze? debian_after_or_at_squeeze? debian_squeeze? debian_before_squeeze? debian_before_or_at_squeeze? debian_after_wheezy? debian_after_or_at_wheezy? debian_wheezy?

    debian_before_wheezy? debian_before_or_at_wheezy? debian_after_jessie? debian_after_or_at_jessie? debian_jessie? debian_before_jessie? debian_before_or_at_jessie? linuxmint_after_olivia? linuxmint_after_or_at_olivia? linuxmint_olivia? linuxmint_before_olivia? linuxmint_before_or_at_olivia? linuxmint_after_nadia? linuxmint_after_or_at_nadia? linuxmint_nadia? linuxmint_before_nadia? linuxmint_before_or_at_nadia? linuxmint_after_maya? linuxmint_after_or_at_maya? linuxmint_maya? linuxmint_before_maya? linuxmint_before_or_at_maya? linuxmint_after_lisa? linuxmint_after_or_at_lisa? linuxmint_lisa? linuxmint_before_lisa? linuxmint_before_or_at_lisa? mac_os_x_after_lion? mac_os_x_after_or_at_lion? mac_os_x_lion? mac_os_x_before_lion? mac_os_x_before_or_at_lion? mac_os_x_after_mountain_lion? mac_os_x_after_or_at_mountain_lion? mac_os_x_mountain_lion? mac_os_x_before_mountain_lion? mac_os_x_before_or_at_mountain_lion? mac_os_x_after_mavericks? mac_os_x_after_or_at_mavericks? mac_os_x_mavericks? mac_os_x_before_mavericks? mac_os_x_before_or_at_mavericks? ubuntu_after_lucid? ubuntu_after_or_at_lucid? ubuntu_lucid? ubuntu_before_lucid? ubuntu_before_or_at_lucid? ubuntu_after_maverick? ubuntu_after_or_at_maverick? ubuntu_maverick? ubuntu_before_maverick? ubuntu_before_or_at_maverick? ubuntu_after_natty? ubuntu_after_or_at_natty? ubuntu_natty? ubuntu_before_natty? ubuntu_before_or_at_natty? ubuntu_after_oneiric? ubuntu_after_or_at_oneiric? ubuntu_oneiric? ubuntu_before_oneiric? ubuntu_before_or_at_oneiric? ubuntu_after_precise? ubuntu_after_or_at_precise? ubuntu_precise? ubuntu_before_precise? ubuntu_before_or_at_precise? ubuntu_after_quantal? ubuntu_after_or_at_quantal? ubuntu_quantal? ubuntu_before_quantal? ubuntu_before_or_at_quantal? ubuntu_after_raring? ubuntu_after_or_at_raring? ubuntu_raring? ubuntu_before_raring? ubuntu_before_or_at_raring? ubuntu_after_saucy? ubuntu_after_or_at_saucy? ubuntu_saucy? ubuntu_before_saucy? ubuntu_before_or_at_saucy? linux_mint? mint? ubuntu? amazon_linux? amazon? centos? oracle_linux? oracle? scientific_linux? scientific? redhat_enterprise_linux? redhat_enterprise?
  67. FAMILIES if node['platform_family'] == 'debian' if debian?

  68. FILTERS package 'apache2' do action :nothing end.run_action(:install) compile_time do package

    'apache2' end
  69. THAT'S BASICALLY ALL OF CHEF SUGAR

  70. STOP

  71. STRUCTURE !"" Gemfile !"" Rakefile !"" chef-sugar.gemspec !"" lib #

    $"" chef # !"" sugar # # !"" ... # $"" sugar.rb !"" metadata.rb !"" recipes # $"" default.rb
  72. STRUCTURE !"" Gemfile !"" Rakefile !"" chef-sugar.gemspec !"" lib #

    $"" chef # !"" sugar # # !"" ... # $"" sugar.rb !"" metadata.rb !"" recipes # $"" default.rb
  73. STRUCTURE !"" Gemfile !"" Rakefile !"" chef-sugar.gemspec !"" lib #

    $"" chef # !"" sugar # # !"" ... # $"" sugar.rb !"" metadata.rb !"" recipes # $"" default.rb
  74. STRUCTURE !"" Gemfile !"" Rakefile !"" chef-sugar.gemspec !"" lib #

    $"" chef # !"" sugar # # !"" ... # $"" sugar.rb !"" metadata.rb !"" recipes # $"" default.rb YES!
  75. STRUCTURE !"" Gemfile !"" Rakefile !"" chef-sugar.gemspec !"" lib #

    $"" chef # !"" sugar # # !"" ... # $"" sugar.rb !"" metadata.rb !"" recipes # $"" default.rb YES! ENHANCE!
  76. STRUCTURE !"" lib # $"" chef # !"" sugar #

    # !"" architecture.rb # # !"" cloud.rb # # !"" constraints.rb # # !"" core_extensions # # # !"" array.rb # # # $"" string.rb # # !"" core_extensions.rb # # !"" data_bag.rb # # !"" filters.rb # # !"" ip.rb # # !"" kernel.rb
  77. SUGAR.RB class Chef module Sugar require_relative 'sugar/architecture' # ... end

    end ! Chef::Recipe.send(:include, Chef::Sugar::DSL) Chef::Resource.send(:include, Chef::Sugar::DSL) Chef::Provider.send(:include, Chef::Sugar::DSL) ! Object.send(:include, Chef::Sugar::Kernel)
  78. SUGAR.RB class Chef module Sugar require_relative 'sugar/architecture' # ... end

    end ! Chef::Recipe.send(:include, Chef::Sugar::DSL) Chef::Resource.send(:include, Chef::Sugar::DSL) Chef::Provider.send(:include, Chef::Sugar::DSL) ! Object.send(:include, Chef::Sugar::Kernel)
  79. SUGAR.RB class Chef module Sugar require_relative 'sugar/architecture' # ... end

    end ! Chef::Recipe.send(:include, Chef::Sugar::DSL) Chef::Resource.send(:include, Chef::Sugar::DSL) Chef::Provider.send(:include, Chef::Sugar::DSL) ! Object.send(:include, Chef::Sugar::Kernel)
  80. SUGAR.RB class Chef module Sugar require_relative 'sugar/architecture' # ... end

    end ! Chef::Recipe.send(:include, Chef::Sugar::DSL) Chef::Resource.send(:include, Chef::Sugar::DSL) Chef::Provider.send(:include, Chef::Sugar::DSL) ! Object.send(:include, Chef::Sugar::Kernel)
  81. SHELL.RB class Chef module Sugar::Shell extend self ! def which(cmd)

    # ... magic codez end end ! module DSL def which(cmd); Chef::Sugar::Shell.which(cmd); end end end
  82. SHELL.RB class Chef module Sugar::Shell extend self ! def which(cmd)

    # ... magic codez end end ! module DSL def which(cmd); Chef::Sugar::Shell.which(cmd); end end end
  83. SHELL.RB class Chef module Sugar::Shell extend self ! def which(cmd)

    # ... magic codez end end ! module DSL def which(cmd); Chef::Sugar::Shell.which(cmd); end end end
  84. SHELL.RB class Chef module Sugar::Shell extend self ! def which(cmd)

    # ... magic codez end end ! module DSL def which(cmd); Chef::Sugar::Shell.which(cmd); end end end
  85. SHELL.RB class Chef module Sugar::Shell extend self ! def which(cmd)

    # ... magic codez end end ! module DSL def which(cmd); Chef::Sugar::Shell.which(cmd); end end end
  86. SHELL.RB class Chef module Sugar::Shell extend self ! def which(cmd)

    # ... magic codez end end ! module DSL def which(cmd); Chef::Sugar::Shell.which(cmd); end end end
  87. SUGAR.RB class # ... end ! Chef::Recipe.send( Chef::Resource.send( Chef::Provider.send( !

    Object.send( ! ! ! ! ! ! ! ! Chef::Resource.send(:include, Chef::Sugar::DSL)
  88. CORE EXTENSIONS ARE EVIL

  89. SO I ADDED SOME INSIDE CHEF SUGAR

  90. BUT THEY ARE NOT REQUIRED

  91. REQUIRING BY DEFAULT IS AN ANTI-PATTERN

  92. RECIPE.RB include_recipe 'chef_sugar::default' require 'chef/sugar/core_extensions'

  93. RECIPE.RB include_recipe 'chef_sugar::default' require 'chef/sugar/core_extensions'

  94. RECIPE.RB include_recipe 'chef_sugar::default' require 'chef/sugar/core_extensions'

  95. RECIPE.RB include_recipe 'chef_sugar::default' require 'chef/sugar/core_extensions' ! version('1.2.3').satisfies?('~> 1.2.0')

  96. RECIPE.RB include_recipe 'chef_sugar::default' require 'chef/sugar/core_extensions' ! version('1.2.3').satisfies?('~> 1.2.0') ! !

    ! '1.2.3'.satisfies?('~> 1.2.0')
  97. THAT'S ALL FOLKS

  98. SETH VARGO EXTRA RESOURCES @SETHVARGO Info Q: http://www.infoq.com/news/2014/01/chef-sugar Code: https://github.com/sethvargo/chef-sugar

    Blog: https://sethvargo.com/spice-up-your-recipes-with-chef-sugar/
  99. SETH VARGO QUESTIONS? @SETHVARGO Info Q: http://www.infoq.com/news/2014/01/chef-sugar Code: https://github.com/sethvargo/chef-sugar Blog:

    https://sethvargo.com/spice-up-your-recipes-with-chef-sugar/