SlideShare a Scribd company logo
Cooking Perl with Chef
        David Golden
           @xdg

      http://perlchef.com/

             July 2012
Configuration
    Management
(e.g. chef, puppet, cfengine, ...)
Unknown state

     ↓
 Target state
New machine

    ↓
Deployed app
Infrastructure as code
            automated!
            repeatable!
              testable!

 (no manual steps, checklist, etc.)
One tool to deploy
 the whole stack
(DB, caching, messaging, ...)
But wait!
Isn't that hard to do for Perl apps?
Perl applications are complex
Dependency hell
App = perl + CPAN + your code
CHI
             DateTime
             DBI
             JSON
App = perl + CPAN + your code
             Moose
             Plack
             POE
             Try::Tiny
             ...
CHI
                            DateTime
                            DBI
                            JSON
App = perl + CPAN + your code
                            Moose
                            Plack
                            POE
                            Try::Tiny
                            ...




 your application is the versioned set of all its compontents
CHI
                              DateTime
                              DBI
                              JSON
App
v1.0.0   = perl + CPAN + your code
                              Moose
                              Plack
                              POE
                              Try::Tiny
                              ...




   your application is the versioned set of all its compontents
CHI
                              DateTime
                              DBI
                              JSON
App
v1.0.0   = Perl + CPAN + your code
           v5.14.2            Moose
                              Plack
                              POE
                              Try::Tiny
                              ...




   your application is the versioned set of all its compontents
0.55
                              0.76
                              1.622
                              2.53
App
v1.0.0   = Perl + CPAN + your code
           v5.14.2            2.0603
                              0.9989
                              1.354
                              0.11
                              ...




   your application is the versioned set of all its compontents
0.55
                              0.76
                              1.622
                              2.53
App
v1.0.0   = Perl + CPAN + your code
           v5.14.2       v1.0 2.0603
                              0.9989
                              1.354
                              0.11
                              ...




   your application is the versioned set of all its compontents
0.55
                     0.76
                     1.622
                     2.53
App
v1.0.0   = Perl + CPAN + your code
           v5.14.2       v1.0
                     2.0603
                     0.9989
                     1.354
                     0.11
                     ...




              change one piece...
0.55
                     0.76
                     1.622
                     2.53
App
v1.0.0   = Perl + CPAN + your code
           v5.16.0       v1.0
                     2.0603
                     0.9989
                     1.354
                     0.11
                     ...




              change one piece...
0.55
                              0.76
                              1.622
                              2.53
App
v1.0.1    = Perl + CPAN + your code
            v5.16.0       v1.02.0603
                              0.9989
                              1.354
                              0.11
                              ...




         … and you have a new version of your application
Repeatable deployment means...
Repeatable deployment means...

        ... the same Perl
Repeatable deployment means...

        ... the same Perl
        ... the same modules
Repeatable deployment means...

        ... the same Perl
        ... the same modules
        ... the same code
Repeatable deployment means...

        ... the same Perl
        ... the same modules
        ... the same code
        ... on demand
Easy...
If we have the right tools
Use one-size fits all distribution packagers like
               apt, yum, etc...?

       (How much do you like your system perl?!)
This problem is not
  unique to Perl
Let's be inspired by Larry
[larry hat pic]
Or better yet, Paul
YARRR!
Great hackers steal!
Great hackers steal ideas
Consider Chef...
Chef ❤ Ruby
(written in ruby; various ruby app stacks)
Chef ❤ Python
(virtualenv; pip; django apps)
Common patterns emerge
python → virtualenv + pip
 ruby → rvm + Bundler
We've built tools like these, too
Kang-min Liu (gugod)

 Matt S Trout (mst)

Tatsuhiko Miyagawa
(and a big community helping them)
perlbrew – multiple perl manager

       Matt S Trout (mst)

      Tatsuhiko Miyagawa
      (and a big community helping them)
perlbrew – multiple perl manager

local::lib – custom @INC manager

      Tatsuhiko Miyagawa
      (and a big community helping them)
perlbrew – multiple perl manager

  local::lib – custom @INC manager

carton – versioned dependency installer
         (and a big community helping them)
So we have the pieces
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]
No support in Chef...
So I implemented it
(In Ruby)
(After I learned some Ruby)
Now...


         Chef ❤ Perl
    (perlbrew; local::lib; carton)
Time for a quick Chef glossary...

 (see http://wiki.opscode.com/)
“Cookbook”

A collection of components to configure
a particular application

Typically includes recipes, providers,
templates, etc.

(CPAN analogy → “distribution”)
“Recipe”

Component applied that deploys an
application or service

Typically declarative, specifying desired
resources and associated configuration
“Resource”

An abstraction of something to be deployed
“Provider”

Platform-specific implementation to deliver a
resource
“Node”

A host computer managed with Chef

Often means the configuration file that
defines recipes, attributes and roles that
define the target state of a host
“Attribute”

A variable used in a recipe and/or provider
that customizes the configuration of a
resource

Attributes have defaults, but can be
customized for nodes or roles
“Role”

A collection of recipes and attributes used to
apply common configuration across multiple
nodes
Summary...


    cookbooks include recipes and providers

roles, recipes and attributes get applied to nodes

recipes specify desired resources and customize
               them with attributes

 providers do the work of deploying resources
I wrote two Perl Chef cookbooks
for the Chef community repository
     (which is like CPAN circa 1996 or so)


       http://community.opscode.com/
1. perlbrew – for managing perls

2. carton – for deploying apps


Also available here: https://github.com/dagolden/perl-chef
perlbrew cookbook resources:

  perlbrew_perl – install a perl

  perlbrew_lib – create a local::lib

  perlbrew_cpanm – install modules to perl or lib

  perlbrew_run – run shell commands under a
  particular perlbrew and/or lib
carton cookbook resource:

  carton_app – deploy an app with carton

    – start in directory with the app source
    – configure for a specific perlbrew perl
    – install versioned dependencies with carton
    – create a runit service for the app
    – start the app
Time for an example:

Deploying a “Hello World” Plack app

     https://github.com/dagolden/zzz-hello-world
Steps for creating Hello World

    1. Write the application

    2. Use carton to create a carton.lock file with
       versioned dependency info

    3. Write a simple cookbook for the application

    4. Check it all into git

    5. Deploy the application with Chef
$ 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
use strict;
use warnings;
use ZZZ::Hello::World;
my $app = sub { ZZZ::Hello::World->run_psgi(@_) };




                             (this Plack app just invokes a simple module)
$ 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
use 5.008001;
use strict;
use warnings;

package ZZZ::Hello::World;
our $VERSION = "1.0";

use Plack::Request;

sub run_psgi {
  my $self = shift;
  my $req = Plack::Request->new(shift);
  my $res = $req->new_response(200);
  $res->content_type('text/html');
  $res->body(<<"HERE");
<html>
<head><title>Hello World</title></head>
<body>
<p>Hello World. It is @{[scalar localtime]}</p>
...
</body>
</html>
HERE
  return $res->finalize;
}

1;
                                   (the module just returns some dynamic HTML)
$ 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
use inc::Module::Install;
name 'ZZZ-Hello-World';
version '1.0';

requires 'Plack';
requires 'Starman';

WriteAll;




            (the Makefile.PL also includes deployment dependencies like Starman)
During development, carton installs
dependencies locally and creates a versioned
dependency file called carton.lock

$ carton install
# installs dependencies into a local directory
# creates carton.lock if it doesn't exist
# carton.lock is a JSON file of dependency info
During deployment, carton installs dependencies
from carton.lock and runs the app with them

$ carton install
# installs dependencies into a local directory

$ carton exec ­Ilib ­­ starman ­p 8080 app.psgi
# runs the app using carton installed deps
$ 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
# carton.lock JSON
{
   "modules" : {
      "Class::Inspector" : {
          "dist" : "Class-Inspector-1.27",
          "module" : "Class::Inspector",
          "pathname" :
              "A/AD/ADAMK/Class-Inspector-1.27.tar.gz",
          ...
      }.
      "Data::Dump" : {
          ...
      },
      "Devel::StackTrace" : {
          ...
      },
      "Encode::Locale" : {
          ...
      },
      ...
}
        (carton.lock associates module names to specific versions of those module)
$ 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
# perlbrew to execute with
 default['hello-world']['perl_version'] = 'perl-5.16.0'

 # Install directory, repo and tag
 default['hello-world']['deploy_dir'] = '/opt/hello-world'
 default['hello-world']['deploy_repo'] =
       'https://github.com/dagolden/zzz-hello-world.git'
 default['hello-world']['deploy_tag'] = 'master'

 # Service user/group/port
 default['hello-world']['user'] = "nobody"
 default['hello-world']['group'] = "nogroup"
 default['hello-world']['port'] = 8080




(attributes are variables used in the recipe; can be customized per-node during deployment)
$ 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 :start
end



                                (recipe ensures carton and git are available...)
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 :start
end



                          (git resource specifies where application code goes...)
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 :start
end



                              (attributes parameterize the resource statement...)
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 :start
end



                     (carton_app resources installs deps and sets up runit service...)
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 :start
end



                               (again, attributes parameterize the resource...)
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 :start
end



                                (finally, the resource is idempotently started...)
These files – and the Perl Chef
 cookbooks – are all you need
Enough code... let's see how to deploy it
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
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
Vagrant is great for testing Chef deployment

            (and other things, besides)
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
Chef Solo is Chef without a central
      configuration server

 (good for demos and smaller deployments)
Chef        – you push config data to Chef Server
            – nodes run Chef Client to pull config
              from Chef Server and execute it



Chef Solo   – you push config data to nodes
            – you run Chef Solo remotely
One advantage of Chef Solo...

        Your config repo is canonical

(i.e. you don't have to track what you've pushed to the central server)
One dis-advantage of Chef Solo...

Manual rsync/ssh required (yuck!)
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
Pantry is a tool for automating Chef Solo
Pantry is a tool for automating Chef Solo


$ pantry create node server.example.com

$ pantry apply node server.example.com 
  --role web --recipe myapp

$ pantry sync node server.example.com
Pantry is written in Perl and available on CPAN

   (Similar to pocketknife [Ruby] and littlechef [Python])
Finally, a demonstration...



   Screencast available at
http://youtu.be/H93rt-KtwBE
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
$ vagrant init
# create config file

$ vim Vagrantfile
# edit to forward local port 8080 to
# virtual machine port 8080

$ vagrant up
# launch it

$ vagrant ssh
# check that it's up, then exit
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
$ pantry init
# create directories to hold Chef Solo config

$ pantry create node vagrant 
    ­­host localhost 
    ­­port 8080      
    ­­user vagrant
# create a node config file

$ ssh­add ~/.vagrant.d/insecure_private_key
# allow pantry to ssh to vagrant machine 




         (Important tip: remove the insecure_private_key after you no longer
         need it because Github chokes on it.)
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
Four cookbooks must be downloaded
and copied to the 'cookbooks' directory

 – hello-world
 – carton
 – perlbrew
 – runit
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
$ pantry apply node vagrant ­­recipe hello­world
# apply recipe to node configuration

$ pantry apply node vagrant ­­default 
    hello­world.perl_version=perl­5.14.2
# override a default attribute

$ pantry show node vagrant
# see the resulting JSON config file
{
   "hello­world" : {
      "perl_version" : "perl­5.14.2"
   },
   "run_list" : [
      "recipe[hello­world]"
   ],
   "name" : "vagrant",
   "pantry_user" : "vagrant",
   "pantry_port" : "2222",
   "pantry_host" : "localhost"
}
Steps for deployment of Hello World


    1. Set up a Vagrant virtual machine

    2. Prepare Pantry to manage Chef Solo

    3. Get Hello World cookbook and dependencies

    4. Configure virtual machine for Hello World

    5. Deploy
$ pantry sync node vagrant
# ... wait for everything to deploy ...
# then load browser and test it!
It works
You can do this, too
Don't be afraid. Try it out. Get involved.

   tutorial and screencast → http://perlchef.com

  mailing list → perl-devops-subscribe@perl.org

More Related Content

What's hot

From Dev to DevOps - ApacheCON NA 2011
From Dev to DevOps - ApacheCON NA 2011From Dev to DevOps - ApacheCON NA 2011
From Dev to DevOps - ApacheCON NA 2011
Carlos Sanchez
 
Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012
Carlos Sanchez
 
Puppet at GitHub / ChatOps
Puppet at GitHub / ChatOpsPuppet at GitHub / ChatOps
Puppet at GitHub / ChatOps
Puppet
 
Puppet at Pinterest
Puppet at PinterestPuppet at Pinterest
Puppet at Pinterest
Puppet
 
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopPuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
Walter Heck
 
Building kubectl plugins with Quarkus | DevNation Tech Talk
Building kubectl plugins with Quarkus | DevNation Tech TalkBuilding kubectl plugins with Quarkus | DevNation Tech Talk
Building kubectl plugins with Quarkus | DevNation Tech Talk
Red Hat Developers
 
Antons Kranga Building Agile Infrastructures
Antons Kranga   Building Agile InfrastructuresAntons Kranga   Building Agile Infrastructures
Antons Kranga Building Agile Infrastructures
Antons Kranga
 
Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014
Puppet
 
Kubernetes Java Operator
Kubernetes Java OperatorKubernetes Java Operator
Kubernetes Java Operator
Anthony Dahanne
 
Take control of your Jenkins jobs via job DSL.
Take control of your Jenkins jobs via job DSL.Take control of your Jenkins jobs via job DSL.
Take control of your Jenkins jobs via job DSL.
Łukasz Proszek
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)
Soshi Nemoto
 
Docker Starter Pack
Docker Starter PackDocker Starter Pack
Docker Starter Pack
Saeed Hajizade
 
Test Driven Development with Puppet
Test Driven Development with Puppet Test Driven Development with Puppet
Test Driven Development with Puppet
Puppet
 
Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點
William Yeh
 
The Modern Developer Toolbox
The Modern Developer ToolboxThe Modern Developer Toolbox
The Modern Developer Toolbox
Pablo Godel
 
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
Mischa Taylor
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnApp
Walter Heck
 
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWS
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWSConfiguring Highly Scalable Compile Masters, Vasco Cardoso, AWS
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWS
Puppet
 
Chef for beginners module 5
Chef for beginners   module 5Chef for beginners   module 5
Chef for beginners module 5
Chef
 
A Tale of a Server Architecture (Frozen Rails 2012)
A Tale of a Server Architecture (Frozen Rails 2012)A Tale of a Server Architecture (Frozen Rails 2012)
A Tale of a Server Architecture (Frozen Rails 2012)
Flowdock
 

What's hot (20)

From Dev to DevOps - ApacheCON NA 2011
From Dev to DevOps - ApacheCON NA 2011From Dev to DevOps - ApacheCON NA 2011
From Dev to DevOps - ApacheCON NA 2011
 
Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012
 
Puppet at GitHub / ChatOps
Puppet at GitHub / ChatOpsPuppet at GitHub / ChatOps
Puppet at GitHub / ChatOps
 
Puppet at Pinterest
Puppet at PinterestPuppet at Pinterest
Puppet at Pinterest
 
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopPuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
 
Building kubectl plugins with Quarkus | DevNation Tech Talk
Building kubectl plugins with Quarkus | DevNation Tech TalkBuilding kubectl plugins with Quarkus | DevNation Tech Talk
Building kubectl plugins with Quarkus | DevNation Tech Talk
 
Antons Kranga Building Agile Infrastructures
Antons Kranga   Building Agile InfrastructuresAntons Kranga   Building Agile Infrastructures
Antons Kranga Building Agile Infrastructures
 
Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014
 
Kubernetes Java Operator
Kubernetes Java OperatorKubernetes Java Operator
Kubernetes Java Operator
 
Take control of your Jenkins jobs via job DSL.
Take control of your Jenkins jobs via job DSL.Take control of your Jenkins jobs via job DSL.
Take control of your Jenkins jobs via job DSL.
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)
 
Docker Starter Pack
Docker Starter PackDocker Starter Pack
Docker Starter Pack
 
Test Driven Development with Puppet
Test Driven Development with Puppet Test Driven Development with Puppet
Test Driven Development with Puppet
 
Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點
 
The Modern Developer Toolbox
The Modern Developer ToolboxThe Modern Developer Toolbox
The Modern Developer Toolbox
 
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnApp
 
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWS
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWSConfiguring Highly Scalable Compile Masters, Vasco Cardoso, AWS
Configuring Highly Scalable Compile Masters, Vasco Cardoso, AWS
 
Chef for beginners module 5
Chef for beginners   module 5Chef for beginners   module 5
Chef for beginners module 5
 
A Tale of a Server Architecture (Frozen Rails 2012)
A Tale of a Server Architecture (Frozen Rails 2012)A Tale of a Server Architecture (Frozen Rails 2012)
A Tale of a Server Architecture (Frozen Rails 2012)
 

Similar to Cooking Perl with Chef

Kubernetes Introduction
Kubernetes IntroductionKubernetes Introduction
Kubernetes Introduction
Red Hat Developers
 
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
tdc-globalcode
 
Kubernetes_Webinar_Slide_Deck.pdf
Kubernetes_Webinar_Slide_Deck.pdfKubernetes_Webinar_Slide_Deck.pdf
Kubernetes_Webinar_Slide_Deck.pdf
AuliaFebrian2
 
Python+gradle
Python+gradlePython+gradle
Python+gradle
Stephen Holsapple
 
Kubernetes deep dive - - Huawei 2015-10
Kubernetes deep dive - - Huawei 2015-10Kubernetes deep dive - - Huawei 2015-10
Kubernetes deep dive - - Huawei 2015-10
Vishnu Kannan
 
Kubernetes workshop -_the_basics
Kubernetes workshop -_the_basicsKubernetes workshop -_the_basics
Kubernetes workshop -_the_basics
Sjuul Janssen
 
Packaging perl (LPW2010)
Packaging perl (LPW2010)Packaging perl (LPW2010)
Packaging perl (LPW2010)
p3castro
 
Cluster management with Kubernetes
Cluster management with KubernetesCluster management with Kubernetes
Cluster management with Kubernetes
Satnam Singh
 
Docker module 1
Docker module 1Docker module 1
Docker module 1
Liang Bo
 
Kubernetes best practices
Kubernetes best practicesKubernetes best practices
Kubernetes best practices
Bill Liu
 
Kubernetes for Java Developers
 Kubernetes for Java Developers Kubernetes for Java Developers
Kubernetes for Java Developers
Red Hat Developers
 
JavaOne 2016: Kubernetes introduction for Java Developers
JavaOne 2016: Kubernetes introduction for Java Developers JavaOne 2016: Kubernetes introduction for Java Developers
JavaOne 2016: Kubernetes introduction for Java Developers
Rafael Benevides
 
Can I Contain This?
Can I Contain This?Can I Contain This?
Can I Contain This?
Eficode
 
Kubernetes intro public - kubernetes meetup 4-21-2015
Kubernetes intro   public - kubernetes meetup 4-21-2015Kubernetes intro   public - kubernetes meetup 4-21-2015
Kubernetes intro public - kubernetes meetup 4-21-2015
Rohit Jnagal
 
Kubernetes intro public - kubernetes user group 4-21-2015
Kubernetes intro   public - kubernetes user group 4-21-2015Kubernetes intro   public - kubernetes user group 4-21-2015
Kubernetes intro public - kubernetes user group 4-21-2015
reallavalamp
 
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Fabrice Bernhard
 
Docker for Devs - John Zaccone, IBM
Docker for Devs - John Zaccone, IBMDocker for Devs - John Zaccone, IBM
Docker for Devs - John Zaccone, IBM
Docker, Inc.
 
DockerDay2015: Getting started with Google Container Engine
DockerDay2015: Getting started with Google Container EngineDockerDay2015: Getting started with Google Container Engine
DockerDay2015: Getting started with Google Container Engine
Docker-Hanoi
 
DockerCon EU 2015: Stop Being Lazy and Test Your Software!
DockerCon EU 2015: Stop Being Lazy and Test Your Software!DockerCon EU 2015: Stop Being Lazy and Test Your Software!
DockerCon EU 2015: Stop Being Lazy and Test Your Software!
Docker, Inc.
 
Kubernetes - training micro-dragons without getting burnt
Kubernetes -  training micro-dragons without getting burntKubernetes -  training micro-dragons without getting burnt
Kubernetes - training micro-dragons without getting burnt
Amir Moghimi
 

Similar to Cooking Perl with Chef (20)

Kubernetes Introduction
Kubernetes IntroductionKubernetes Introduction
Kubernetes Introduction
 
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
TDC2018FLN | Trilha Containers - Kubernetes para usuarios Docker.
 
Kubernetes_Webinar_Slide_Deck.pdf
Kubernetes_Webinar_Slide_Deck.pdfKubernetes_Webinar_Slide_Deck.pdf
Kubernetes_Webinar_Slide_Deck.pdf
 
Python+gradle
Python+gradlePython+gradle
Python+gradle
 
Kubernetes deep dive - - Huawei 2015-10
Kubernetes deep dive - - Huawei 2015-10Kubernetes deep dive - - Huawei 2015-10
Kubernetes deep dive - - Huawei 2015-10
 
Kubernetes workshop -_the_basics
Kubernetes workshop -_the_basicsKubernetes workshop -_the_basics
Kubernetes workshop -_the_basics
 
Packaging perl (LPW2010)
Packaging perl (LPW2010)Packaging perl (LPW2010)
Packaging perl (LPW2010)
 
Cluster management with Kubernetes
Cluster management with KubernetesCluster management with Kubernetes
Cluster management with Kubernetes
 
Docker module 1
Docker module 1Docker module 1
Docker module 1
 
Kubernetes best practices
Kubernetes best practicesKubernetes best practices
Kubernetes best practices
 
Kubernetes for Java Developers
 Kubernetes for Java Developers Kubernetes for Java Developers
Kubernetes for Java Developers
 
JavaOne 2016: Kubernetes introduction for Java Developers
JavaOne 2016: Kubernetes introduction for Java Developers JavaOne 2016: Kubernetes introduction for Java Developers
JavaOne 2016: Kubernetes introduction for Java Developers
 
Can I Contain This?
Can I Contain This?Can I Contain This?
Can I Contain This?
 
Kubernetes intro public - kubernetes meetup 4-21-2015
Kubernetes intro   public - kubernetes meetup 4-21-2015Kubernetes intro   public - kubernetes meetup 4-21-2015
Kubernetes intro public - kubernetes meetup 4-21-2015
 
Kubernetes intro public - kubernetes user group 4-21-2015
Kubernetes intro   public - kubernetes user group 4-21-2015Kubernetes intro   public - kubernetes user group 4-21-2015
Kubernetes intro public - kubernetes user group 4-21-2015
 
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
 
Docker for Devs - John Zaccone, IBM
Docker for Devs - John Zaccone, IBMDocker for Devs - John Zaccone, IBM
Docker for Devs - John Zaccone, IBM
 
DockerDay2015: Getting started with Google Container Engine
DockerDay2015: Getting started with Google Container EngineDockerDay2015: Getting started with Google Container Engine
DockerDay2015: Getting started with Google Container Engine
 
DockerCon EU 2015: Stop Being Lazy and Test Your Software!
DockerCon EU 2015: Stop Being Lazy and Test Your Software!DockerCon EU 2015: Stop Being Lazy and Test Your Software!
DockerCon EU 2015: Stop Being Lazy and Test Your Software!
 
Kubernetes - training micro-dragons without getting burnt
Kubernetes -  training micro-dragons without getting burntKubernetes -  training micro-dragons without getting burnt
Kubernetes - training micro-dragons without getting burnt
 

More from David Golden

Slice Recycling Performance and Pitfalls
Slice Recycling Performance and PitfallsSlice Recycling Performance and Pitfalls
Slice Recycling Performance and Pitfalls
David Golden
 
Free QA!
Free QA!Free QA!
Free QA!
David Golden
 
Eversion 101: An Introduction to Inside-Out Objects
Eversion 101: An Introduction to Inside-Out ObjectsEversion 101: An Introduction to Inside-Out Objects
Eversion 101: An Introduction to Inside-Out Objects
David Golden
 
Perl 5 Version 13
Perl 5 Version 13Perl 5 Version 13
Perl 5 Version 13
David Golden
 
IsTrue(true)?
IsTrue(true)?IsTrue(true)?
IsTrue(true)?
David Golden
 
One BSON to Rule Them
One BSON to Rule ThemOne BSON to Rule Them
One BSON to Rule Them
David Golden
 
Adventures in Optimization
Adventures in OptimizationAdventures in Optimization
Adventures in Optimization
David Golden
 
Make Comments Stand Out
Make Comments Stand OutMake Comments Stand Out
Make Comments Stand Out
David Golden
 
State of the Velociraptor Mini-Keynote: Perl Toolchain
State of the Velociraptor Mini-Keynote: Perl ToolchainState of the Velociraptor Mini-Keynote: Perl Toolchain
State of the Velociraptor Mini-Keynote: Perl Toolchain
David Golden
 
Practical Consistency
Practical ConsistencyPractical Consistency
Practical Consistency
David Golden
 
How I get to the ☞
How I get to the ☞How I get to the ☞
How I get to the ☞
David Golden
 
Real World Optimization
Real World OptimizationReal World Optimization
Real World Optimization
David Golden
 
Safer Chainsaw Juggling (Lightning Talk)
Safer Chainsaw Juggling (Lightning Talk)Safer Chainsaw Juggling (Lightning Talk)
Safer Chainsaw Juggling (Lightning Talk)
David Golden
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order Functions
David Golden
 
Juggling Chainsaws: Perl and MongoDB
Juggling Chainsaws: Perl and MongoDBJuggling Chainsaws: Perl and MongoDB
Juggling Chainsaws: Perl and MongoDB
David Golden
 
Cooking Perl with Chef: Hello World Tutorial
Cooking Perl with Chef: Hello World TutorialCooking Perl with Chef: Hello World Tutorial
Cooking Perl with Chef: Hello World Tutorial
David Golden
 

More from David Golden (16)

Slice Recycling Performance and Pitfalls
Slice Recycling Performance and PitfallsSlice Recycling Performance and Pitfalls
Slice Recycling Performance and Pitfalls
 
Free QA!
Free QA!Free QA!
Free QA!
 
Eversion 101: An Introduction to Inside-Out Objects
Eversion 101: An Introduction to Inside-Out ObjectsEversion 101: An Introduction to Inside-Out Objects
Eversion 101: An Introduction to Inside-Out Objects
 
Perl 5 Version 13
Perl 5 Version 13Perl 5 Version 13
Perl 5 Version 13
 
IsTrue(true)?
IsTrue(true)?IsTrue(true)?
IsTrue(true)?
 
One BSON to Rule Them
One BSON to Rule ThemOne BSON to Rule Them
One BSON to Rule Them
 
Adventures in Optimization
Adventures in OptimizationAdventures in Optimization
Adventures in Optimization
 
Make Comments Stand Out
Make Comments Stand OutMake Comments Stand Out
Make Comments Stand Out
 
State of the Velociraptor Mini-Keynote: Perl Toolchain
State of the Velociraptor Mini-Keynote: Perl ToolchainState of the Velociraptor Mini-Keynote: Perl Toolchain
State of the Velociraptor Mini-Keynote: Perl Toolchain
 
Practical Consistency
Practical ConsistencyPractical Consistency
Practical Consistency
 
How I get to the ☞
How I get to the ☞How I get to the ☞
How I get to the ☞
 
Real World Optimization
Real World OptimizationReal World Optimization
Real World Optimization
 
Safer Chainsaw Juggling (Lightning Talk)
Safer Chainsaw Juggling (Lightning Talk)Safer Chainsaw Juggling (Lightning Talk)
Safer Chainsaw Juggling (Lightning Talk)
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order Functions
 
Juggling Chainsaws: Perl and MongoDB
Juggling Chainsaws: Perl and MongoDBJuggling Chainsaws: Perl and MongoDB
Juggling Chainsaws: Perl and MongoDB
 
Cooking Perl with Chef: Hello World Tutorial
Cooking Perl with Chef: Hello World TutorialCooking Perl with Chef: Hello World Tutorial
Cooking Perl with Chef: Hello World Tutorial
 

Recently uploaded

Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
RTTS
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 

Recently uploaded (20)

Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 

Cooking Perl with Chef

  • 1. Cooking Perl with Chef David Golden @xdg http://perlchef.com/ July 2012
  • 2. Configuration Management (e.g. chef, puppet, cfengine, ...)
  • 3. Unknown state ↓ Target state
  • 4. New machine ↓ Deployed app
  • 5. Infrastructure as code automated! repeatable! testable! (no manual steps, checklist, etc.)
  • 6. One tool to deploy the whole stack (DB, caching, messaging, ...)
  • 7. But wait! Isn't that hard to do for Perl apps?
  • 10. App = perl + CPAN + your code
  • 11. CHI DateTime DBI JSON App = perl + CPAN + your code Moose Plack POE Try::Tiny ...
  • 12. CHI DateTime DBI JSON App = perl + CPAN + your code Moose Plack POE Try::Tiny ... your application is the versioned set of all its compontents
  • 13. CHI DateTime DBI JSON App v1.0.0 = perl + CPAN + your code Moose Plack POE Try::Tiny ... your application is the versioned set of all its compontents
  • 14. CHI DateTime DBI JSON App v1.0.0 = Perl + CPAN + your code v5.14.2 Moose Plack POE Try::Tiny ... your application is the versioned set of all its compontents
  • 15. 0.55 0.76 1.622 2.53 App v1.0.0 = Perl + CPAN + your code v5.14.2 2.0603 0.9989 1.354 0.11 ... your application is the versioned set of all its compontents
  • 16. 0.55 0.76 1.622 2.53 App v1.0.0 = Perl + CPAN + your code v5.14.2 v1.0 2.0603 0.9989 1.354 0.11 ... your application is the versioned set of all its compontents
  • 17. 0.55 0.76 1.622 2.53 App v1.0.0 = Perl + CPAN + your code v5.14.2 v1.0 2.0603 0.9989 1.354 0.11 ... change one piece...
  • 18. 0.55 0.76 1.622 2.53 App v1.0.0 = Perl + CPAN + your code v5.16.0 v1.0 2.0603 0.9989 1.354 0.11 ... change one piece...
  • 19. 0.55 0.76 1.622 2.53 App v1.0.1 = Perl + CPAN + your code v5.16.0 v1.02.0603 0.9989 1.354 0.11 ... … and you have a new version of your application
  • 21. Repeatable deployment means... ... the same Perl
  • 22. Repeatable deployment means... ... the same Perl ... the same modules
  • 23. Repeatable deployment means... ... the same Perl ... the same modules ... the same code
  • 24. Repeatable deployment means... ... the same Perl ... the same modules ... the same code ... on demand
  • 26. If we have the right tools
  • 27. Use one-size fits all distribution packagers like apt, yum, etc...? (How much do you like your system perl?!)
  • 28. This problem is not unique to Perl
  • 29. Let's be inspired by Larry
  • 32.
  • 37. Chef ❤ Ruby (written in ruby; various ruby app stacks)
  • 38. Chef ❤ Python (virtualenv; pip; django apps)
  • 40. python → virtualenv + pip ruby → rvm + Bundler
  • 41. We've built tools like these, too
  • 42. Kang-min Liu (gugod) Matt S Trout (mst) Tatsuhiko Miyagawa (and a big community helping them)
  • 43. perlbrew – multiple perl manager Matt S Trout (mst) Tatsuhiko Miyagawa (and a big community helping them)
  • 44. perlbrew – multiple perl manager local::lib – custom @INC manager Tatsuhiko Miyagawa (and a big community helping them)
  • 45. perlbrew – multiple perl manager local::lib – custom @INC manager carton – versioned dependency installer (and a big community helping them)
  • 46. So we have the pieces
  • 48. Repeatable deployment in five parts application-specific Perl application-specific @INC path versioned application code versioned module dependencies automate the previous four
  • 49. Repeatable deployment in five parts perlbrew application-specific @INC path versioned application code versioned module dependencies automate the previous four
  • 50. Repeatable deployment in five parts perlbrew local::lib versioned application code versioned module dependencies automate the previous four
  • 51. Repeatable deployment in five parts perlbrew local::lib git versioned module dependencies automate the previous four
  • 52. Repeatable deployment in five parts perlbrew local::lib git carton automate the previous four
  • 53. Repeatable deployment in five parts perlbrew local::lib git carton @&$%!
  • 55. No support in Chef...
  • 58. (After I learned some Ruby)
  • 59. Now... Chef ❤ Perl (perlbrew; local::lib; carton)
  • 60. Time for a quick Chef glossary... (see http://wiki.opscode.com/)
  • 61. “Cookbook” A collection of components to configure a particular application Typically includes recipes, providers, templates, etc. (CPAN analogy → “distribution”)
  • 62. “Recipe” Component applied that deploys an application or service Typically declarative, specifying desired resources and associated configuration
  • 63. “Resource” An abstraction of something to be deployed
  • 65. “Node” A host computer managed with Chef Often means the configuration file that defines recipes, attributes and roles that define the target state of a host
  • 66. “Attribute” A variable used in a recipe and/or provider that customizes the configuration of a resource Attributes have defaults, but can be customized for nodes or roles
  • 67. “Role” A collection of recipes and attributes used to apply common configuration across multiple nodes
  • 68. Summary... cookbooks include recipes and providers roles, recipes and attributes get applied to nodes recipes specify desired resources and customize them with attributes providers do the work of deploying resources
  • 69. I wrote two Perl Chef cookbooks for the Chef community repository (which is like CPAN circa 1996 or so) http://community.opscode.com/
  • 70. 1. perlbrew – for managing perls 2. carton – for deploying apps Also available here: https://github.com/dagolden/perl-chef
  • 71. perlbrew cookbook resources: perlbrew_perl – install a perl perlbrew_lib – create a local::lib perlbrew_cpanm – install modules to perl or lib perlbrew_run – run shell commands under a particular perlbrew and/or lib
  • 72. carton cookbook resource: carton_app – deploy an app with carton – start in directory with the app source – configure for a specific perlbrew perl – install versioned dependencies with carton – create a runit service for the app – start the app
  • 73. Time for an example: Deploying a “Hello World” Plack app https://github.com/dagolden/zzz-hello-world
  • 74. Steps for creating Hello World 1. Write the application 2. Use carton to create a carton.lock file with versioned dependency info 3. Write a simple cookbook for the application 4. Check it all into git 5. Deploy the application with Chef
  • 75. $ 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
  • 76. $ 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
  • 77. use strict; use warnings; use ZZZ::Hello::World; my $app = sub { ZZZ::Hello::World->run_psgi(@_) }; (this Plack app just invokes a simple module)
  • 78. $ 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
  • 79. use 5.008001; use strict; use warnings; package ZZZ::Hello::World; our $VERSION = "1.0"; use Plack::Request; sub run_psgi { my $self = shift; my $req = Plack::Request->new(shift); my $res = $req->new_response(200); $res->content_type('text/html'); $res->body(<<"HERE"); <html> <head><title>Hello World</title></head> <body> <p>Hello World. It is @{[scalar localtime]}</p> ... </body> </html> HERE return $res->finalize; } 1; (the module just returns some dynamic HTML)
  • 80. $ 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
  • 81. use inc::Module::Install; name 'ZZZ-Hello-World'; version '1.0'; requires 'Plack'; requires 'Starman'; WriteAll; (the Makefile.PL also includes deployment dependencies like Starman)
  • 82. During development, carton installs dependencies locally and creates a versioned dependency file called carton.lock $ carton install # installs dependencies into a local directory # creates carton.lock if it doesn't exist # carton.lock is a JSON file of dependency info
  • 83. During deployment, carton installs dependencies from carton.lock and runs the app with them $ carton install # installs dependencies into a local directory $ carton exec ­Ilib ­­ starman ­p 8080 app.psgi # runs the app using carton installed deps
  • 84. $ 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
  • 85. # carton.lock JSON { "modules" : { "Class::Inspector" : { "dist" : "Class-Inspector-1.27", "module" : "Class::Inspector", "pathname" : "A/AD/ADAMK/Class-Inspector-1.27.tar.gz", ... }. "Data::Dump" : { ... }, "Devel::StackTrace" : { ... }, "Encode::Locale" : { ... }, ... } (carton.lock associates module names to specific versions of those module)
  • 86. $ 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
  • 87. # perlbrew to execute with default['hello-world']['perl_version'] = 'perl-5.16.0' # Install directory, repo and tag default['hello-world']['deploy_dir'] = '/opt/hello-world' default['hello-world']['deploy_repo'] = 'https://github.com/dagolden/zzz-hello-world.git' default['hello-world']['deploy_tag'] = 'master' # Service user/group/port default['hello-world']['user'] = "nobody" default['hello-world']['group'] = "nogroup" default['hello-world']['port'] = 8080 (attributes are variables used in the recipe; can be customized per-node during deployment)
  • 88. $ 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
  • 89. 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 :start end (recipe ensures carton and git are available...)
  • 90. 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 :start end (git resource specifies where application code goes...)
  • 91. 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 :start end (attributes parameterize the resource statement...)
  • 92. 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 :start end (carton_app resources installs deps and sets up runit service...)
  • 93. 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 :start end (again, attributes parameterize the resource...)
  • 94. 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 :start end (finally, the resource is idempotently started...)
  • 95. These files – and the Perl Chef cookbooks – are all you need
  • 96. Enough code... let's see how to deploy it
  • 97. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 98. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 99.
  • 100. Vagrant is a tool for managing virtual machines “Can I have a VirtualBox now, please?”
  • 101. Vagrant is a tool for managing virtual machines $ vagrant box add base http://files.vagrantup.com/lucid32.box $ vagrant init $ vagrant up
  • 102. Vagrant is great for testing Chef deployment (and other things, besides)
  • 103. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 104. Chef Solo is Chef without a central configuration server (good for demos and smaller deployments)
  • 105. Chef – you push config data to Chef Server – nodes run Chef Client to pull config from Chef Server and execute it Chef Solo – you push config data to nodes – you run Chef Solo remotely
  • 106.
  • 107. One advantage of Chef Solo... Your config repo is canonical (i.e. you don't have to track what you've pushed to the central server)
  • 108. One dis-advantage of Chef Solo... Manual rsync/ssh required (yuck!)
  • 109. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 110. Pantry is a tool for automating Chef Solo
  • 111. Pantry is a tool for automating Chef Solo $ pantry create node server.example.com $ pantry apply node server.example.com --role web --recipe myapp $ pantry sync node server.example.com
  • 112. Pantry is written in Perl and available on CPAN (Similar to pocketknife [Ruby] and littlechef [Python])
  • 113. Finally, a demonstration... Screencast available at http://youtu.be/H93rt-KtwBE
  • 114. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 116. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 118. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 119. Four cookbooks must be downloaded and copied to the 'cookbooks' directory – hello-world – carton – perlbrew – runit
  • 120. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 122. Steps for deployment of Hello World 1. Set up a Vagrant virtual machine 2. Prepare Pantry to manage Chef Solo 3. Get Hello World cookbook and dependencies 4. Configure virtual machine for Hello World 5. Deploy
  • 125. You can do this, too
  • 126. Don't be afraid. Try it out. Get involved. tutorial and screencast → http://perlchef.com mailing list → perl-devops-subscribe@perl.org