![Page 1: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/1.jpg)
Cookbook Refactoring
A
![Page 2: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/2.jpg)
Cookbook Refactoring
... and extracting logic into Rubygems
A
![Page 4: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/4.jpg)
![Page 5: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/5.jpg)
We're Hiring!
![Page 6: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/6.jpg)
We're Hiring!
Colorado
![Page 7: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/7.jpg)
New Branding
We're Hiring!
![Page 8: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/8.jpg)
UDO YOU SOMETIMES
FEEL LIKE
THIS
![Page 9: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/9.jpg)
![Page 10: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/10.jpg)
![Page 11: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/11.jpg)
template '/etc/hosts' do owner 'root' group 'root' source 'etc/hosts'end
recipes/default.rb
![Page 12: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/12.jpg)
# This file is managed by Chef for "<%= node['fqdn'] %>"# Do NOT modify this file by hand.
<%= node['ipaddress'] %> <%= node['fqdn'] %>127.0.0.1!localhost <%= node['fqdn'] %>255.255.255.255!broadcasthost::1 localhost fe80::1%lo0! localhost
templates/default/etc/hosts.erb
![Page 13: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/13.jpg)
![Page 14: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/14.jpg)
default['etc']['hosts'] = [] unless node['etc']['hosts']
attributes/default.rb
![Page 15: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/15.jpg)
# This file is managed by Chef for "<%= node['fqdn'] %>"# Do NOT modify this file by hand.
<%= node['ipaddress'] %> <%= node['fqdn'] %>127.0.0.1!localhost <%= node['fqdn'] %>255.255.255.255!broadcasthost::1 localhost fe80::1%lo0! localhost
# Custom Entries<% node['etc']['hosts'].each do |h| -%><%= h['ip'] %> <%= h['host'] %><% end -%>
templates/default/etc/hosts.erb
![Page 16: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/16.jpg)
include_attribute 'hostsfile'
default['etc']['hosts'] << { 'ip' => '1.2.3.4', 'host' => 'www.example.com'}
other_cookbook/attributes/default.rb
![Page 17: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/17.jpg)
node.default['etc']['hosts'] << { 'ip' => '1.2.3.4', 'host' => 'www.example.com'}
other_cookbook/recipes/default.rb
![Page 18: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/18.jpg)
default_attributes({ 'etc' => { 'hosts' => [ {'ip' => '1.2.3.4', 'host' => 'www.example.com'}, {'ip' => '4.5.6.7', 'host' => 'foo.example.com'} ] }})
roles/my_role.rb
![Page 19: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/19.jpg)
{ "default_attributes": { "etc": { "hosts": [ {"ip": "1.2.3.4", "host": "www.example.com"}, {"ip": "4.5.6.7", "host": "foo.example.com"} ] } }}
environments/production.json
![Page 20: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/20.jpg)
![Page 21: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/21.jpg)
node.set['etc']['hosts'] = { ip: '7.8.9.0', host: 'bar.example.com'})
recipes/default.rb
![Page 22: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/22.jpg)
![Page 23: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/23.jpg)
arr = [1,2,3]
arr << 4 => [1,2,3,4]arr = 4 => 4
![Page 24: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/24.jpg)
arr = [1,2,3]
arr << 4 => [1,2,3,4]arr = 4 => 4
Not an Array
![Page 25: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/25.jpg)
TODO: Add infographics
# This file is managed by Chef for "www.myapp.com"# Do NOT modify this file by hand.
1.2.3.4 www.myapp.com127.0.0.1!localhost www.myapp.com255.255.255.255!broadcasthost::1 localhost fe80::1%lo0! localhost
# Custom Entries1.2.3.4 www.example.com4.5.6.7 foo.example.com7.8.9.0 bar.example.com
/etc/hosts
![Page 26: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/26.jpg)
TODO: Add infographics
# This file is managed by Chef for "www.myapp.com"# Do NOT modify this file by hand.
1.2.3.4 www.myapp.com127.0.0.1!localhost www.myapp.com255.255.255.255!broadcasthost::1 localhost fe80::1%lo0! localhost
# Custom Entries7.8.9.0 bar.example.com
/etc/hosts
![Page 27: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/27.jpg)
Post Mortem
![Page 28: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/28.jpg)
![Page 29: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/29.jpg)
![Page 30: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/30.jpg)
<< =
![Page 31: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/31.jpg)
<< =!=
![Page 32: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/32.jpg)
Post Mortem
Action Items
7
![Page 33: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/33.jpg)
Monkey patch Chef to raise an exception when redefining that
particular node attribute.
![Page 34: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/34.jpg)
Monkey patch Chef to raise an exception when redefining that
particular node attribute.t
![Page 35: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/35.jpg)
Create a special cookbook that uses a threshold value and raises an
exception if the size of the array doesn't "make sense".
![Page 36: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/36.jpg)
Create a special cookbook that uses a threshold value and raises an
exception if the size of the array doesn't "make sense".t
![Page 37: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/37.jpg)
Move all entries to a data bag
![Page 38: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/38.jpg)
Move all entries to a data bag
u
![Page 39: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/39.jpg)
Move all entries to a data bag66 Add tests
![Page 40: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/40.jpg)
Data Bags
![Page 41: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/41.jpg)
[ "1.2.3.4 example.com www.example.com", "4.5.6.7 foo.example.com", "7.8.9.0 bar.example.com"]
data_bags/etc_hosts.json
![Page 42: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/42.jpg)
hosts = data_bag('etc_hosts')
template '/etc/hosts' do owner 'root' group 'root' source 'etc/hosts' variables( hosts: hosts )end
recipes/default.rb
![Page 43: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/43.jpg)
# This file is managed by Chef for "<%= node['fqdn'] %>"# Do NOT modify this file by hand.
<%= node['ipaddress'] %> <%= node['fqdn'] %>127.0.0.1!localhost <%= node['fqdn'] %>255.255.255.255!broadcasthost::1 localhost fe80::1%lo0! localhost
# Custom Entries<%= @hosts.join("\n") %>
templates/default/etc/hosts.erb
![Page 44: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/44.jpg)
Move all entries to a data bag56 Add tests
![Page 45: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/45.jpg)
require 'chefspec'
spec/default_spec.rb
![Page 46: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/46.jpg)
require 'chefspec'
describe 'hostsfile::default' do
end
spec/default_spec.rb
![Page 47: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/47.jpg)
require 'chefspec'
describe 'hostsfile::default' do let(:hosts) { ['1.2.3.4 example.com', '4.5.6.7 bar.com'] }
before do Chef::Recipe.any_instance.stub(:data_bag).with('etc_hosts').and_return(hosts) end
end
spec/default_spec.rb
![Page 48: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/48.jpg)
require 'chefspec'
describe 'hostsfile::default' do let(:hosts) { ['1.2.3.4 example.com', '4.5.6.7 bar.com'] }
before do Chef::Recipe.any_instance.stub(:data_bag).with('etc_hosts').and_return(hosts) end
let(:runner) { ChefSpec::ChefRunner.new.converge('hostsfile::default') }
end
spec/default_spec.rb
![Page 49: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/49.jpg)
require 'chefspec'
describe 'hostsfile::default' do let(:hosts) { ['1.2.3.4 example.com', '4.5.6.7 bar.com'] }
before do Chef::Recipe.any_instance.stub(:data_bag).with('etc_hosts').and_return(hosts) end
let(:runner) { ChefSpec::ChefRunner.new.converge('hostsfile::default') }
it 'loads the data bag' do Chef::Recipe.any_instance.should_receive(:data_bag).with('etc_hosts') end
end
spec/default_spec.rb
![Page 50: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/50.jpg)
require 'chefspec'
describe 'hostsfile::default' do let(:hosts) { ['1.2.3.4 example.com', '4.5.6.7 bar.com'] }
before do Chef::Recipe.any_instance.stub(:data_bag).with('etc_hosts').and_return(hosts) end
let(:runner) { ChefSpec::ChefRunner.new.converge('hostsfile::default') }
it 'loads the data bag' do Chef::Recipe.any_instance.should_receive(:data_bag).with('etc_hosts') end
it 'creates the /etc/hosts template' do expect(runner).to create_template('/etc/hosts').with_content(hosts.join("\n")) endend
spec/default_spec.rb
![Page 51: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/51.jpg)
$ rspec cookbooks/hostsfile
Running all specs
![Page 52: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/52.jpg)
$ rspec cookbooks/hostsfile
Running all specs
**
Finished in 0.0003 seconds2 examples, 0 failures
![Page 53: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/53.jpg)
$ rspec cookbooks/hostsfile
Running all specs
**
Finished in 0.0003 seconds2 examples, 0 failures
Really Fucking Fast™
![Page 54: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/54.jpg)
#winning
![Page 55: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/55.jpg)
10,000 tests
![Page 56: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/56.jpg)
28 seconds
![Page 57: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/57.jpg)
#winning
![Page 58: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/58.jpg)
⏳⏳
![Page 59: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/59.jpg)
![Page 60: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/60.jpg)
![Page 61: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/61.jpg)
hosts = data_bag('etc_hosts')
hosts << search(:node, 'role:mongo_master').first.tap do |n| "#{n['ip_address']} #{n['fqdn']}"end
template '/etc/hosts' do owner 'root' group 'root' source 'etc/hosts' variables( hosts: hosts )end
recipes/default.rb
![Page 62: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/62.jpg)
hosts = data_bag('etc_hosts')
hosts << search(:node, 'role:mongo_master').first.tap do |n| "#{n['ip_address']} #{n['fqdn']}"end
hosts << search(:node, 'role:mysql_master').first.tap do |n| "#{n['ip_address']} #{n['fqdn']}"end
hosts << search(:node, 'role:redis_master').first.tap do |n| "#{n['ip_address']} #{n['fqdn']}"end
template '/etc/hosts' do owner 'root' group 'root' source 'etc/hosts' variables( hosts: hosts )end
recipes/default.rb
![Page 63: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/63.jpg)
LWRPs
![Page 64: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/64.jpg)
# List of all actions supported by the provideractions :create, :create_if_missing, :update, :remove
# Make create the default actiondefault_action :create
# Required attributesattribute :ip_address, kind_of: String, name_attribute: true, required: trueattribute :hostname, kind_of: String
# Optional attributesattribute :aliases, kind_of: Arrayattribute :comment, kind_of: String
resources/entry.rb
![Page 65: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/65.jpg)
action :create do ::Chef::Util::FileEdit.search_file_delete_line(entry) ::Chef::Util::FileEdit.insert_line_after_match(/\n/, entry)end
protected
def entry [new_resource.ip_address, new_resource.hostname, new_resource.aliases.join(' ')].compact.join(' ').squeeze(' ') end
providers/entry.rb
![Page 66: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/66.jpg)
hostsfile_entry '1.2.3.4' do hostname 'example.com'end
providers/entry.rb
![Page 67: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/67.jpg)
Chef::Util::FileEdit is slow
![Page 68: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/68.jpg)
Re-writing the file on each run
![Page 69: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/69.jpg)
Provider kept growning
![Page 70: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/70.jpg)
Untested
![Page 71: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/71.jpg)
RefactorA
![Page 72: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/72.jpg)
Move to pure Ruby classes
![Page 73: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/73.jpg)
Ditch Chef::Util::FileEdit and manage the entire file
![Page 74: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/74.jpg)
Only implement Ruby classes in the Provider (logic-less Provider)
![Page 75: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/75.jpg)
Test the Ruby code
![Page 76: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/76.jpg)
Test that the Provider implements the proper Ruby classes
![Page 77: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/77.jpg)
TODO: Add infographics
class Entry attr_accessor :ip_address, :hostname, :aliases, :comment
def initialize(options = {}) if options[:ip_address].nil? || options[:hostname].nil? raise ':ip_address and :hostname are both required options' end
@ip_address = options[:ip_address] @hostname = options[:hostname] @aliases = [options[:aliases]].flatten @comment = options[:comment] end
# ...end
libraries/entry.rb
![Page 78: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/78.jpg)
TODO: Add infographics
class Manipulator def initialize contents = ::File.readlines(hostsfile_path) @entries = contents.collect do |line| Entry.parse(line) unless line.strip.nil? || line.strip.empty? end.compact end
def add(options = {}) @entries << Entry.new( ip_address: options[:ip_address], hostname: options[:hostname], aliases: options[:aliases], comment: options[:comment] ) endend
libraries/manipulator.rb
![Page 79: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/79.jpg)
# Creates a new hosts file entry. If an entry already exists, it# will be overwritten by this one.action :create do hostsfile.add( ip_address: new_resource.ip_address, hostname: new_resource.hostname, aliases: new_resource.aliases, comment: new_resource.comment )
new_resource.updated_by_last_action(true) if hostsfile.saveend
providers/entry.rb
![Page 80: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/80.jpg)
![Page 81: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/81.jpg)
![Page 82: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/82.jpg)
RSpec
![Page 83: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/83.jpg)
TODO: Add infographics
describe Entry do describe '.initialize' do subject { Entry.new(ip_address: '2.3.4.5', hostname: 'www.example.com', aliases: ['foo', 'bar'], comment: 'This is a comment!', priority: 100) }
it 'raises an exception if :ip_address is missing' do expect { Entry.new(hostname: 'www.example.com') }.to raise_error(ArgumentError) end
it 'sets the ip_address' do expect(subject.ip_address).to eq('2.3.4.5') endend
spec/entry_spec.rb
![Page 84: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/84.jpg)
![Page 85: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/85.jpg)
Chef Spec
![Page 86: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/86.jpg)
Chef Spec
![Page 87: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/87.jpg)
TODO: Add infographics
describe 'hostsfile lwrp' do let(:manipulator) { double('manipulator') } before do Manipulator.stub(:new).and_return(manipulator) Manipulator.should_receive(:new).with(kind_of(Chef::Node)) .and_return(manipulator) manipulator.should_receive(:save!) end
let(:chef_run) { ChefSpec::ChefRunner.new( cookbook_path: $cookbook_paths, step_into: ['hostsfile_entry'] ) }
spec/default_spec.rb
![Page 88: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/88.jpg)
TODO: Add infographics
context 'actions' do describe ':create' do it 'adds the entry' do manipulator.should_receive(:add).with({ ip_address: '2.3.4.5', hostname: 'www.example.com', aliases: nil, comment: nil, priority: nil })
chef_run.converge('fake::create') end end endend
![Page 89: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/89.jpg)
Open It
![Page 90: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/90.jpg)
![Page 91: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/91.jpg)
![Page 92: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/92.jpg)
![Page 93: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/93.jpg)
![Page 94: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/94.jpg)
![Page 95: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/95.jpg)
Gem It
![Page 96: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/96.jpg)
$ bundle gem hostsfile
![Page 97: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/97.jpg)
$ bundle gem hostsfile create hostsfile/Gemfile create hostsfile/Rakefile create hostsfile/LICENSE.txt create hostsfile/README.md create hostsfile/.gitignore create hostsfile/hostsfile.gemspec create hostsfile/lib/hostsfile.rb create hostsfile/lib/hostsfile/version.rbInitializating git repo in ~Development/hostsfile
![Page 98: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/98.jpg)
entry.rb
manipulator.rb
99
![Page 99: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/99.jpg)
9
![Page 100: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/100.jpg)
9?
![Page 101: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/101.jpg)
chef_gem 'hostsfile'
recipes/default.rb
![Page 102: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/102.jpg)
require 'hostsfile'
providers/entry.rb
![Page 103: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/103.jpg)
In another cookbook...
![Page 104: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/104.jpg)
# ...
depends 'hostsfile'
other_cookbook/metadata.rb
![Page 105: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/105.jpg)
{ "run_list": [ "recipe[hostsfile]" ]}
www.myapp.com (Chef Node)
![Page 106: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/106.jpg)
![Page 107: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/107.jpg)
![Page 108: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/108.jpg)
![Page 109: Cookbook refactoring & abstracting logic to Ruby(gems)](https://reader035.vdocuments.us/reader035/viewer/2022062511/54c689294a795962378b4589/html5/thumbnails/109.jpg)
ThankYou
z