Cooking Perl with Chef David Golden @xdg
Cooking Perl with Chef
David Golden@xdg
[cliff]
A metaphoric cliff
From cozy job ... to entrepreneur
Fear...
Fear... am I crazy?
Fear... am I too old for this?
Startups are for college kids, right?
[hoodie picture]
Startup culture is a grind
All night hackathons? WTF?
[hackathon sleep pic(s)]
I will never beat 20 year-olds on hours
I don't want to for two big reasons
I don't want to for two big reasonslittle
I'm not afraid of running a business
I'm not afraid of programming
I'm afraid of operations
I'm afraid of things going horribly wrong
Fear... is motivating
Memorial Day Weekend, 2012
Got lucky!
Side projects take time, too
Work smarter, not harder
Doing things by hand (more than once) sucks
Infrastructure as code
Automate deploying the whole stack
Configuration management(Chef, Puppet, etc....)
WAIT!What's wrong with this idea?
Dependency hell
Perl applications are complex
App = perl + CPAN + your code
App = perl + CPAN + your code
CHIDateTimeDBIJSONMoosePlackPOETry::Tiny...
App = perl + CPAN + your code
CHIDateTimeDBIJSONMoosePlackPOETry::Tiny...
v1.0.0
App = Perl + CPAN + your code
CHIDateTimeDBIJSONMoosePlackPOETry::Tiny...
v1.0.0 v5.14.2
App = Perl + CPAN + your code
0.550.761.6222.532.06030.99891.3540.11...
v1.0.0 v5.14.2
App = Perl + CPAN + your code
0.550.761.6222.532.06030.99891.3540.11...
v1.0.0 v5.14.2 v1.0
App = Perl + CPAN + your code
0.550.761.6222.532.06030.99891.3540.11...
v1.0.0 v5.14.2 v1.0
App = Perl + CPAN + your code
0.550.761.6222.532.06030.99891.3540.11...
v1.0.0 v5.16.0 v1.0
App = Perl + CPAN + your code
0.550.761.6222.532.06030.99891.3540.11...
v1.0.1 v5.16.0 v1.0
Repeatable deployment
Repeatable deployment
... the same Perl
Repeatable deployment
... the same Perl
... the same modules
Repeatable deployment
... the same Perl
... the same modules
... the same code
Repeatable deployment
... the same Perl
... the same modules
... the same code
... on demand
Easy...
If we have the right tools
Distro packages (?!)
(how much do you like your system perl?!)
We need something better
Let's be inspired by Larry
[larry hat pic]
YARRR!
Great hackers steal!
Great hackers steal ideas
python has virtualenv + pipruby has rvm + Bundler
We have Miyagawa
We have Kang-min Liu
We have Matt Trout
We have a community helping them
Repeatable deployment in five parts
Repeatable deployment in five parts
application-specific Perl
application-specific @INC path
versioned application code
versioned module dependencies
automate the previous four
Repeatable deployment in five parts
perlbrew
application-specific @INC path
versioned application code
versioned module dependencies
automate the previous four
Repeatable deployment in five parts
perlbrew
local::lib
versioned application code
versioned module dependencies
automate the previous four
Repeatable deployment in five parts
perlbrew
local::lib
git
versioned module dependencies
automate the previous four
Repeatable deployment in five parts
perlbrew
local::lib
git
carton
automate the previous four
Repeatable deployment in five parts
perlbrew
local::lib
git
carton
@&$%!
@&$%!
[swedish chef FAIL pic]
So I implemented it
In Ruby
After I learned some Ruby
Time for a demonstration
Our goal: deploy a “Hello World” Plack app
$ tree.├── Changes├── Makefile.PL├── app.psgi├── carton.lock├── cookbook│ └── hello-world│ ├── README.md│ ├── attributes│ │ └── default.rb│ ├── metadata.rb│ └── recipes│ └── default.rb└── lib └── ZZZ └── Hello └── World.pm
$ tree.├── Changes├── Makefile.PL├── app.psgi├── carton.lock├── cookbook│ └── hello-world│ ├── README.md│ ├── attributes│ │ └── default.rb│ ├── metadata.rb│ └── recipes│ └── default.rb└── lib └── ZZZ └── Hello └── World.pm
$ tree.├── Changes├── Makefile.PL├── app.psgi├── carton.lock├── cookbook│ └── hello-world│ ├── README.md│ ├── attributes│ │ └── default.rb│ ├── metadata.rb│ └── recipes│ └── default.rb└── lib └── ZZZ └── Hello └── World.pm
$ tree.├── Changes├── Makefile.PL├── app.psgi├── carton.lock├── cookbook│ └── hello-world│ ├── README.md│ ├── attributes│ │ └── default.rb│ ├── metadata.rb│ └── recipes│ └── default.rb└── lib └── ZZZ └── Hello └── World.pm
$ tree.├── Changes├── Makefile.PL├── app.psgi├── carton.lock├── cookbook│ └── hello-world│ ├── README.md│ ├── attributes│ │ └── default.rb│ ├── metadata.rb│ └── recipes│ └── default.rb└── lib └── ZZZ └── Hello └── World.pm
include_recipe 'carton'
package 'git-core'
git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]"end
carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group']end
carton_app "hello-world" do action :startend
include_recipe 'carton'
package 'git-core'
git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]"end
carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group']end
carton_app "hello-world" do action :startend
include_recipe 'carton'
package 'git-core'
git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]"end
carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group']end
carton_app "hello-world" do action :startend
include_recipe 'carton'
package 'git-core'
git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]"end
carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group']end
carton_app "hello-world" do action :startend
include_recipe 'carton'
package 'git-core'
git node['hello-world']['deploy_dir'] do repository node['hello-world']['deploy_repo'] reference node['hello-world']['deploy_tag'] notifies :restart, "carton_app[hello-world]"end
carton_app "hello-world" do perlbrew node['hello-world']['perl_version'] command "starman -p #{node['hello-world']['port']} app.psgi" cwd node['hello-world']['deploy_dir'] user node['hello-world']['user'] group node['hello-world']['group']end
carton_app "hello-world" do action :startend
Enough code... let's make it work
1. Set up a Vagrant virtual machine
2. Prepare Pantry
3. Get Hello World cookbook anddependencies
4. Configure Chef for Hello World
5. Deploy
1. Set up a Vagrant virtual machine
2. Prepare Pantry
3. Get Hello World cookbook anddependencies
4. Configure Chef for Hello World
5. Deploy
Vagrant is a tool for managing virtual machines
Vagrant is a tool for managing virtual machines
“Can I have a VirtualBox now, please?”
Vagrant is a tool for managing virtual machines
$ vagrant box add base \ http://files.vagrantup.com/lucid32.box
$ vagrant init
$ vagrant up
Chef brings a machine to a target state
Chef does pull
Chef Solo does push
Pantry is a tool for driving Chef Solo
Pantry is a tool for driving Chef Solo
$ pantry create node server.example.com
$ pantry apply node server.example.com \ --role web --recipe myapp
$ pantry sync node server.example.com
You can do this, too
Don't be afraid. Try it out. Get involved.
New!