Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Cookbook Reusability
Noah Kantrowitz
Balanced, Inc
The problem
Community cookbooks only
do 90% of what you need.
New Problem

•
Complex contribution process.
•
Forking during iteration.
•
Proliferation of special cases.
Wrapper Cookbooks

•
Overriding attributes.
•
chef-rewind, here be dragons.
•

Extension by prepend/append.
Requirements

• Responsive effort:
5% change

~5% work

• Documented extension mechanism.
Integration with kitchen, berks,...
DevOps
LWRPs?

•
Still only prepend/append.
•
No substitution except rewind.
•
Better, but not by much.
Enter: Classes
class Chef
class Resource::Something < Resource
...
end
class Provider::Something < Provider
...
end
end
Chef::Resource
def initialize(*args)
super
@resource_name = :something
@action = :enable
@allowed_actions = [
:enable, :di...
Chef::Resource
def path(arg=nil)
set_or_return(:path, arg, {
kind_of: String
})
end
Chef::Provider
def load_current_resource
end
def whyrun_supported?
true
end
def action_enable
...
end
Why?

•
• No really, subclassing!
Allows detailed, responsive
•
Subclassing.

customization.
Verbosity

• A lot of boilerplate code.
Missing some LWRP DSL goodies.
•
Poise
Poise
class Resource::Something < Resource
include Poise
...
end
class Provider::Something < Provider
include Poise
...
en...
LWRP-ese
class Resource::Something < Resource
include Poise
actions(:enable, :disable)
attribute(:path, kind_of: String)
e...
Notifying Block
def action_enable
notifying_block do
...
end
end
Include Recipe
def action_enable
include_recipe 'something'
end
Lazy Defaults
class Resource::Something < Resource
include Poise
attribute(:path,
default: lazy { node['path'] }
)
end
Option Collector
class Resource::Something < Resource
include Poise
attribute(:database,
option_collector: True)
end
Option Collector
something 'one' do
database host: 'a', port: 8000
end
Option Collector
something 'one' do
database do
host 'a'
port 8000
end
end
Sub-resources
class Resource::Something < Resource
include Poise(container: true)
end
Sub-resources
class Resource::Foo < Resource
include Poise(parent: Something)
end
Sub-resources
something 'one' do
...
foo 'asdf' do
...
end
end
Sub-resources
something 'one' do
...
end
foo 'asdf' do
parent 'one'
end
Sub-resources
something 'one'
foo 'asdf'
Distribution
• Cookbooks?
• Gems?
Reusable Cookbook Patterns
Upcoming SlideShare
Loading in …5
×

Reusable Cookbook Patterns

1,702 views

Published on

From Chef Summit 2013

  • Be the first to comment

Reusable Cookbook Patterns

  1. 1. Cookbook Reusability Noah Kantrowitz Balanced, Inc
  2. 2. The problem Community cookbooks only do 90% of what you need.
  3. 3. New Problem • Complex contribution process. • Forking during iteration. • Proliferation of special cases.
  4. 4. Wrapper Cookbooks • Overriding attributes. • chef-rewind, here be dragons. • Extension by prepend/append.
  5. 5. Requirements • Responsive effort: 5% change ~5% work • Documented extension mechanism. Integration with kitchen, berks, etc. •
  6. 6. DevOps
  7. 7. LWRPs? • Still only prepend/append. • No substitution except rewind. • Better, but not by much.
  8. 8. Enter: Classes class Chef class Resource::Something < Resource ... end class Provider::Something < Provider ... end end
  9. 9. Chef::Resource def initialize(*args) super @resource_name = :something @action = :enable @allowed_actions = [ :enable, :disable ] end
  10. 10. Chef::Resource def path(arg=nil) set_or_return(:path, arg, { kind_of: String }) end
  11. 11. Chef::Provider def load_current_resource end def whyrun_supported? true end def action_enable ... end
  12. 12. Why? • • No really, subclassing! Allows detailed, responsive • Subclassing. customization.
  13. 13. Verbosity • A lot of boilerplate code. Missing some LWRP DSL goodies. •
  14. 14. Poise
  15. 15. Poise class Resource::Something < Resource include Poise ... end class Provider::Something < Provider include Poise ... end
  16. 16. LWRP-ese class Resource::Something < Resource include Poise actions(:enable, :disable) attribute(:path, kind_of: String) end
  17. 17. Notifying Block def action_enable notifying_block do ... end end
  18. 18. Include Recipe def action_enable include_recipe 'something' end
  19. 19. Lazy Defaults class Resource::Something < Resource include Poise attribute(:path, default: lazy { node['path'] } ) end
  20. 20. Option Collector class Resource::Something < Resource include Poise attribute(:database, option_collector: True) end
  21. 21. Option Collector something 'one' do database host: 'a', port: 8000 end
  22. 22. Option Collector something 'one' do database do host 'a' port 8000 end end
  23. 23. Sub-resources class Resource::Something < Resource include Poise(container: true) end
  24. 24. Sub-resources class Resource::Foo < Resource include Poise(parent: Something) end
  25. 25. Sub-resources something 'one' do ... foo 'asdf' do ... end end
  26. 26. Sub-resources something 'one' do ... end foo 'asdf' do parent 'one' end
  27. 27. Sub-resources something 'one' foo 'asdf'
  28. 28. Distribution • Cookbooks? • Gems?

×