Linecook - A Chef Alternative

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 84

Linecook

(A Chef Alternative)
Simon Chiang

Tuesday, April 26, 2011


Chef

Tuesday, April 26, 2011


Ruby
Chef

Tuesday, April 26, 2011


Opscode
Ruby
Chef

Tuesday, April 26, 2011


“Systems Integration
Framework” Opscode
Ruby
Chef

Tuesday, April 26, 2011


“Systems Integration
Framework” Opscode
Ruby

Open Source Chef

Tuesday, April 26, 2011


“Systems Integration
Framework” Opscode
Ruby

Open Source Chef


Automated

Tuesday, April 26, 2011


“Systems Integration
Framework” Opscode
Ruby

Open Source Chef


Scalable
Automated

Tuesday, April 26, 2011


“Systems Integration
Framework” Opscode
Ruby
Server Provisioning
Open Source Chef
Scalable
Automated

Tuesday, April 26, 2011


“Systems Integration
Framework” Opscode
Ruby
Server Provisioning
Open Source Chef
Scalable
Automated

Community

Tuesday, April 26, 2011


“Systems Integration
Framework” Opscode
Ruby
Server Provisioning
Open Source Chef
Scalable
Automated

Community
Hotness

Tuesday, April 26, 2011


An alternative to
shell scripts

Tuesday, April 26, 2011

Not dismissing Chef when I say that. The advantages over manually writing setup/maintenance script are not to
be underestimated. But for the most part things you do with Chef are things you would otherwise do with shell
scripts, and there are problems.
Never a quick
Quickstart
“Before installing Chef, you should take a moment to
understand the various "flavors" of chef: client-server,
chef-solo, and the Opscode Platform. Deciding which
one is right for you will impact your installation
process. You may also want to take a quick look at
Chef's architecture to get an idea of what you're
installing before you proceed.”

http://wiki.opscode.com/display/chef/Installation

Tuesday, April 26, 2011


Not a script,
but sort of...
[lib/chef/provider/package/zypper.rb] @ 0.10.0.rc.0

def install_package(name, version)


if version
run_command(
:command => "zypper -n --no-gpg-checks install -l #{name}=#{version}"
)

Tuesday, April 26, 2011


Not a script,
but sort of...
[lib/chef/provider/package/zypper.rb] @ 0.10.0.rc.0

def install_package(name, version)


if version
run_command(
:command => "zypper -n --no-gpg-checks install -l #{name}=#{version}"
)

Fixed options :(

Tuesday, April 26, 2011


Not a script,
but sort of...
[lib/chef/provider/package/zypper.rb] @ 0.10.0.rc.0

def install_package(name, version)


if version
run_command(
:command => "zypper -n --no-gpg-checks install -l #{name}=#{version}"
)

Fixed options :(

Error for version=""


https://github.com/opscode/chef/pull/27

Tuesday, April 26, 2011


Many moving parts

http://wiki.opscode.com/display/chef/Architecture

Tuesday, April 26, 2011


Many moving parts

http://wiki.opscode.com/display/chef/Vagrant

http://wiki.opscode.com/display/chef/Architecture

Tuesday, April 26, 2011


Many moving parts

http://wiki.opscode.com/display/chef/Vagrant

http://community.opscode.com/cookbooks

http://wiki.opscode.com/display/chef/Architecture

Tuesday, April 26, 2011


Alternative?

Tuesday, April 26, 2011


Shell Scripts!

Tuesday, April 26, 2011


Linecook
A Shell Script Generator

Tuesday, April 26, 2011


Established Tools
(bash, ssh, gems, VirtualBox)

Tuesday, April 26, 2011

Just use the existing systems. Some ‘advanced’ techniques but all established, known systems
Prior experience applies any learning will feed back into existing workflow
Start with a Script
End with a Script

Tuesday, April 26, 2011

Able to bring an existing script to Linecook, then rework to make it more powerful or maintainable. You will work
with scripts directly. Again all prior experience applies.
Pretty quick
Quickstart

Make a server

Make a script

Run script on server

Tuesday, April 26, 2011


Pretty quick
Quickstart

Make a server 1
Make a script

Run script on server

Tuesday, April 26, 2011


Pretty quick
Quickstart

Make a server 1
Make a script

Run script on server 2

Tuesday, April 26, 2011


Pretty quick
Quickstart

Make a server 1
Make a script 3
Run script on server 2

Tuesday, April 26, 2011


An ERB Trick...

Tuesday, April 26, 2011


How to Make a Server

VirtualBox

Install OS

SSH Key Exchange localhost

Tuesday, April 26, 2011


How to Make a Server

VirtualBox VirtualBox
Install OS

SSH Key Exchange localhost

Tuesday, April 26, 2011


How to Make a Server

abox-ubuntu

VirtualBox VirtualBox
Install OS

SSH Key Exchange localhost

Tuesday, April 26, 2011


How to Make a Server

abox-ubuntu

VirtualBox VirtualBox
Install OS

SSH Key Exchange localhost

Tuesday, April 26, 2011


Port Forwarding

abox-ubuntu
VBoxManage modifyvm abox
--natpf1 'abox-ssh,tcp,,
2220,,22' VirtualBox

Access VM by ssh to
localhost
localhost

ssh -p 2220 linecook@localhost

Tuesday, April 26, 2011


Lather, rinse

abox-ubuntu
VBoxManage modifyvm bbox
--natpf1 'bbox-ssh,tcp,, bbox-ubuntu
2221,,22' ...

Repeat as needed
localhost
ssh -p 2221 linecook@localhost
ssh -p 2220 linecook@localhost

Tuesday, April 26, 2011


Advantages

No special prerequisites on servers

Fast Access (fast enough for TDD)

Cmdline control

Multiple VMs

Snapshots

Tuesday, April 26, 2011


How to Run Scripts
cat > script.sh <<"DOC"
echo "# $(whoami)@$(hostname): hello
world!"
DOC
chmod +x script.sh

scp -P 2220 script.sh linecook@localhost:/tmp/script.sh


ssh -p 2220 linecook@localhost -- /tmp/script.sh
# linecook@abox-ubuntu: hello world!

Tuesday, April 26, 2011


Redundany
cat > script.sh <<"DOC"
echo "# $(whoami)@$(hostname): hello
world!"
DOC
chmod +x script.sh

scp -P 2220 script.sh linecook@localhost:/tmp/script.sh


ssh -p 2220 linecook@localhost -- /tmp/script.sh
# linecook@abox-ubuntu: hello world!

Tuesday, April 26, 2011


Use SSH Config
mkdir config
cat > config/ssh <<"DOC"
Host abox
Port 2220
User linecook
Hostname localhost
DOC

scp -F config/ssh script.sh abox:/tmp/script.sh


ssh -F config/ssh abox -- /tmp/script.sh
# linecook@abox-ubuntu: hello world!

Tuesday, April 26, 2011


Multiple Hosts
cat > config/ssh <<"DOC"
Host abox
Port 2220

Host bbox
Port 2221

Host *
User linecook
Hostname localhost
DOC

scp -F config/ssh script.sh bbox:/tmp/script.sh


ssh -F config/ssh bbox -- /tmp/script.sh
# linecook@bbox-ubuntu: hello world!

Tuesday, April 26, 2011


Redundancy
cat > config/ssh <<"DOC"
Host abox
Port 2220

Host bbox
Port 2221

Host *
User linecook
Hostname localhost
DOC

scp -F config/ssh script.sh bbox:/tmp/script.sh


ssh -F config/ssh bbox -- /tmp/script.sh
# linecook@bbox-ubuntu: hello world!

Tuesday, April 26, 2011


Redundancy
cat > config/ssh <<"DOC"
Host abox
Port 2220

Host bbox
Port 2221

Host *
User linecook
Hostname localhost
DOC

scp -F config/ssh script.sh bbox:/tmp/script.sh


ssh -F config/ssh bbox -- /tmp/script.sh
# linecook@bbox-ubuntu: hello world!

Tuesday, April 26, 2011


Make a “Package”
Run with Linecook
[config/ssh] [packages/abox/script.sh]
Host abox echo "# $(whoami)@$(hostname): hello
Port 2220 world!"
[packages/bbox/script.sh]
Host bbox
echo "# $(whoami)@$(hostname): Hullo
Port 2221
Wurld!"
Host *
User linecook
Hostname localhost

linecook run --script script.sh --remote-dir /tmp abox bbox


# linecook@abox-ubuntu: hello world!
# linecook@bbox-ubuntu: Hullo Wurld!

Tuesday, April 26, 2011


Leverge Defaults

[config/ssh] [packages/abox/run]
Host abox echo "# $(whoami)@$(hostname): hello
Port 2220 world!"
[packages/bbox/run]
Host bbox
echo "# $(whoami)@$(hostname): Hullo
Port 2221
Wurld!"
Host *
User linecook script: run
Hostname localhost remote dir: ~/linecook
hosts: *
linecook run
# linecook@abox-ubuntu: hello world!
# linecook@bbox-ubuntu: Hullo Wurld!

Tuesday, April 26, 2011


Easy Way To Test!
[packages/abox/run]
echo "hello world" > /tmp/message.txt

[packages/abox/test]
if [ $(cat /tmp/message.txt) == "hello world" ]
then echo "# success"
else echo "# fail"
fi

linecook run --script test


# fail
linecook run
linecook run --script test
# success

Tuesday, April 26, 2011


Cmdline Dev Cycle

linecook start
linecook run
linecook run --script test
linecook ssh abox
linecook snapshot modified
linecook stop

linecook start --snapshot modified


...

Tuesday, April 26, 2011


Advantages

Standard use of SSH

One standard config file

Ordinary inputs (directories, scripts)

Multiple VMs

Flexible!

Tuesday, April 26, 2011


How to Make a Script

Tuesday, April 26, 2011


How to Make a Script
(boring alert)

Tuesday, April 26, 2011


Start with a Script

[packages/abox/run]
echo "# I will not manually configure my server"

linecook run
# I will not manually configure my server

Tuesday, April 26, 2011


Convert to Recipe
[packages/abox.yml]
linecook:
package:
recipes:
A package file
run: abox

[recipes/abox.rb]
target <<"SCRIPT"
echo "# I will not manually configure my server"
SCRIPT

Tuesday, April 26, 2011


Convert to Recipe
[packages/abox.yml]
linecook:
package: A tempfile
recipes: (packages/abox/run)
run: abox

[recipes/abox.rb]
target <<"SCRIPT"
echo "# I will not manually configure my server"
SCRIPT

Tuesday, April 26, 2011


Simplify
[packages/abox.yml] If default, no
{}
manifest needed
[recipes/abox.rb]
target <<"SCRIPT"
echo "# I will not manually configure my server"
SCRIPT

Tuesday, April 26, 2011


Build and Run
[packages/abox.yml]
{}

[recipes/abox.rb]
target <<"SCRIPT"
echo "# I will not manually configure my server"
SCRIPT

linecook build
linecook run
# I will not manually configure my server

Tuesday, April 26, 2011


Ok... that was boring.

Tuesday, April 26, 2011

Seems pointless, but here is where it gets cool.


Use Recipe as
Context for ERB

Tuesday, April 26, 2011


ERB Compiles to Ruby

require 'erb'

compiler = ERB::Compiler.new("<>")
compiler.put_cmd = "target<<"
compiler.insert_cmd = "target<<"
compiler.compile "got <%= obj %>"

# => "target<<\"got \"; target<<(( obj ).to_s)"

Tuesday, April 26, 2011


InstanceEval for Context
class Recipe
attr_accessor :target
def initialize
@target = ""
end
def obj
"milk"
end
end

code = "target<<\"got \"; target<<(( obj ).to_s)"

recipe = Recipe.new
recipe.instance_eval(code)
recipe.target

# => "got milk"

Tuesday, April 26, 2011


Make a Module
module Helper
def get(obj)
target<<"got "; target<<(( obj ).to_s)
end
end

recipe = Recipe.new
recipe.extend Helper
recipe.instance_eval %q{
get "milk"
target << ", "
get "cookies"
}
recipe.target

# => "got milk, got cookies"

Tuesday, April 26, 2011


Make a Module
module Helper
def get(obj)
target<<"got "; target<<(( obj ).to_s)
end
end

recipe = Recipe.new
recipe.extend Helper
recipe.instance_eval %q{
get "milk"
target << ", "
get "cookies"
This is a recipe!
}
recipe.target

# => "got milk, got cookies"

Tuesday, April 26, 2011


Helpers
[helpers/example/echo.erb]
Write an echo statement
(str)
--
echo "<%= str %>"

[recipes/abox.rb]
helpers "example"
echo "# I will not manually configure my server"

Tuesday, April 26, 2011


Helpers
[helpers/example/echo.erb] [lib/example.rb]
Write an echo statement module Example
(str) # Write an echo ...
-- def echo(str)
echo "<%= str %>" target<< "echo ";...
end
end
[recipes/abox.rb]
helpers "example"
echo "# I will not manually configure my server"

Tuesday, April 26, 2011


Helpers
[helpers/example/echo.erb] [lib/example.rb]
Write an echo statement module Example
(str) # Write an echo ...
-- def echo(str)
echo "<%= str %>" target<< "echo ";...
end
end
[recipes/abox.rb]
helpers "example"
echo "# I will not manually configure my server"

Tuesday, April 26, 2011


Helpers
[helpers/example/echo.erb] [lib/example.rb]
Write an echo statement module Example
(str) # Write an echo ...
-- def echo(str)
echo "<%= str %>" target<< "echo ";...
end
end
[recipes/abox.rb]
helpers "example"
echo "# I will not manually configure my server"

Tuesday, April 26, 2011


Helpers
[helpers/example/echo.erb] [lib/example.rb]
Write an echo statement module Example
(str) # Write an echo ...
-- def echo(str)
echo "<%= str %>" target<< "echo ";...
end
end
[recipes/abox.rb]
helpers "example"
echo "# I will not manually configure my server"

Tuesday, April 26, 2011


Helpers
[helpers/example/echo.erb] [lib/example.rb]
Write an echo statement module Example
(str) # Write an echo ...
-- def echo(str)
echo "<%= str %>" target<< "echo ";...
end
end
[recipes/abox.rb]
helpers "example"
echo "# I will not manually configure my server"

Tuesday, April 26, 2011


Helpers
[helpers/example/echo.erb] [lib/example.rb]
Write an echo statement module Example
(str) # Write an echo ...
-- def echo(str)
echo "<%= str %>" target<< "echo ";...
end
end
[recipes/abox.rb]
helpers "example"
echo "# I will not manually configure my server"

Tuesday, April 26, 2011


Helpers
[helpers/example/echo.erb]
Write an echo statement
(str)
-- require "example"
echo "<%= str %>" extend Example

[recipes/abox.rb]
helpers "example"
echo "# I will not manually configure my server"

Tuesday, April 26, 2011


Helpers
[helpers/example/echo.erb]
Write an echo statement
(str)
--
echo "<%= str %>"

[recipes/abox.rb]
helpers "example"
echo "# I will not manually configure my server"

linecook build
linecook run
# I will not manually configure my server

Tuesday, April 26, 2011


Capture (no write)
[helpers/example/color.erb]
Add color to a string
(color, str)
codes = Hash[*%W{red 0;31 white 1;37 blue 0;34}]
--
\033[<%= codes[color.to_s] %>m<%= str %>\033[0m

[recipes/abox.rb]
helpers "example"
msg = "# I will not manually configure my server"
echo _color("blue", msg)

Tuesday, April 26, 2011


Capture (no write)
[helpers/example/color.erb]
Add color to a string
(color, str)
codes = Hash[*%W{red 0;31 white 1;37 blue 0;34}]
--
\033[<%= codes[color.to_s] %>m<%= str %>\033[0m

[recipes/abox.rb]
helpers "example"
msg = "# I will not manually configure my server"
echo _color("blue", msg)

Prefix with underscore


String output used as input

Tuesday, April 26, 2011


Capture (no write)
[helpers/example/color.erb]
Add color to a string
(color, str)
codes = Hash[*%W{red 0;31 white 1;37 blue 0;34}]
--
\033[<%= codes[color.to_s] %>m<%= str %>\033[0m

[recipes/abox.rb]
helpers "example"
msg = "# I will not manually configure my server"
echo _color("blue", msg)

linecook build
linecook run
# I will not manually configure my server

Tuesday, April 26, 2011


Recipes are Ruby
[recipes/abox.rb]
helpers "example"

msg = "# I will not manually configure my server"


3.times do
echo _color("blue", msg)
end

linecook build
linecook run
# I will not manually configure my server
# I will not manually configure my server
# I will not manually configure my server

Tuesday, April 26, 2011


Advantages
Easily extensible DSL

Produces ordinary modules

Test as any other Ruby

Distribute as Gems (versions, bundler)

Reprocessing of output

Also, kind of cool...

Tuesday, April 26, 2011


Linebook
(Standard Library for Linecook)

Tuesday, April 26, 2011


Logic + Pipelines
[recipes/demo.rb]
helpers 'linebook/shell'

unless_ _file?('/tmp/message') do
cat.to('/tmp/message').heredoc do
writeln 'hello world!'
end
end

cat('/tmp/message')

Tuesday, April 26, 2011


Logic + Pipelines
[packages/demo/run]

if ! [ -f "/tmp/message" ]
then
cat > /tmp/message << HEREDOC_0
hello world!
HEREDOC_0
fi

cat "/tmp/message"

Tuesday, April 26, 2011


Under Construction

Exit status checks, ‘stack trace’

Helpers for login/su

User and File Management

Server-side testing (assert_script)

Installs, config, deployments, etc.

Tuesday, April 26, 2011


No need to wait!

Tuesday, April 26, 2011


Linecook

Attributes
Helpers
Recipes Packages
Files
Templates
Server

Tuesday, April 26, 2011


Learn More
GitHub:

pinnacol/linecook.git

pinnacol/linebook.git

Me:

github.com/thinkerbot

@thinkerbot

Tuesday, April 26, 2011


Thanks Pinnacol!

Tuesday, April 26, 2011


Thanks Derailed!

Tuesday, April 26, 2011


Questions?

Tuesday, April 26, 2011

You might also like