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 :)

Seth Vargo

April 16, 2014
Tweet

More Decks by Seth Vargo

Other Decks in Technology

Transcript

  1. CHEF
    SUGAR

    View Slide

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

    View Slide

  3. WHY?

    View Slide

  4. COOK-494

    View Slide

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

    View Slide

  6. COOK-494

    View Slide

  7. COOK-494

    View Slide

  8. COOK-494

    View Slide

  9. COOK-494

    View Slide

  10. COOK-494

    View Slide

  11. COOK-494

    View Slide

  12. COOK-494

    View Slide

  13. COOK-494

    View Slide

  14. COOK-494


    View Slide

  15. I LIED

    View Slide

  16. WELL NOW THIS
    IS AWKWARD...

    View Slide

  17. BACK UP

    View Slide

  18. CHEF
    SUGAR

    View Slide

  19. SETH

    View Slide

  20. SETH
    VARGO

    View Slide

  21. SETH
    VARGO
    @SETHVARGO

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  27. THIS FUCKING
    GUARD

    View Slide

  28. YOU HAVE ALL
    DONE IT

    View Slide

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

    View Slide

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

    View Slide

  31. execute 'something' do
    command './configure && make && make install'
    not_if <test -x /usr/local/bin/something &&
    /usr/local/bin/something --version | grep 1.0
    EOH
    end
    VERSION!

    View Slide

  32. execute 'something' do
    command './configure && make && make install'
    not_if <test -x#{install_path} &&
    #{install_path} --version | grep #{version}
    EOH
    end
    DYNAMIC

    View Slide

  33. execute 'something' do
    command './configure && make && make install'
    not_if <test -x#{node['app']['config']['install_path']} &&
    #{node['app']['config']['install_path']} --version | ..
    EOH
    end
    DYNAMIC

    View Slide

  34. AND THIS KEPT HAPPENING
    OVER 'N OVER

    View Slide

  35. AND IT IS VERY INEFFICIENT
    TO SHELL OUT

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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?

    View Slide

  40. View Slide

  41. View Slide

  42. View Slide

  43. View Slide

  44. YO DAWG,

    LOOK WHAT I MADE!

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  48. View Slide

  49. COOK-494

    View Slide

  50. View Slide

  51. View Slide

  52. +

    View Slide

  53. + =

    View Slide

  54. + =
    CHEF SUGAR

    View Slide

  55. LÉ EXÄMPLES

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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.

    View Slide

  61. DEEP FETCH
    node['apache2']['config']['root'] #=> '/var/www'
    node.deep_fetch('apache2', 'config', 'root') #=> '/var/www'

    View Slide

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

    View Slide

  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.

    View Slide

  64. PLATFORMS
    if node['platform'] == 'ubuntu'
    if ubuntu?

    View Slide

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

    View Slide

  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?

    View Slide

  67. FAMILIES
    if node['platform_family'] == 'debian'
    if debian?

    View Slide

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

    View Slide

  69. THAT'S BASICALLY ALL OF
    CHEF SUGAR

    View Slide

  70. STOP

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  87. SUGAR.RB
    class
    # ...
    end
    !
    Chef::Recipe.send(
    Chef::Resource.send(
    Chef::Provider.send(
    !
    Object.send(
    !
    !
    !
    !
    !
    !
    !
    !
    Chef::Resource.send(:include, Chef::Sugar::DSL)

    View Slide

  88. CORE EXTENSIONS
    ARE EVIL

    View Slide

  89. SO I ADDED SOME INSIDE
    CHEF SUGAR

    View Slide

  90. BUT THEY ARE
    NOT REQUIRED

    View Slide

  91. REQUIRING BY DEFAULT IS AN
    ANTI-PATTERN

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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')

    View Slide

  97. THAT'S ALL
    FOLKS

    View Slide

  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/

    View Slide

  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/

    View Slide