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

More Decks by Seth Vargo

Other Decks in Technology

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/