Linecook - A Chef Alternative

Post on 25-Nov-2014

109 views 0 download

Tags:

description

Slides from my talk at DeRailed in Denver on April 26, 2011

Transcript of Linecook - A Chef Alternative

Linecook(A Chef Alternative)

Simon Chiang

Tuesday, April 26, 2011

Chef

Tuesday, April 26, 2011

ChefRuby

Tuesday, April 26, 2011

ChefRuby

Opscode

Tuesday, April 26, 2011

ChefRuby

Opscode“Systems Integration

Framework”

Tuesday, April 26, 2011

ChefRuby

Opscode“Systems Integration

Framework”

Open Source

Tuesday, April 26, 2011

ChefRuby

Opscode“Systems Integration

Framework”

Automated

Open Source

Tuesday, April 26, 2011

ChefRuby

Opscode“Systems Integration

Framework”

AutomatedScalable

Open Source

Tuesday, April 26, 2011

ChefRuby

Opscode“Systems Integration

Framework”

AutomatedScalable

Open SourceServer Provisioning

Tuesday, April 26, 2011

ChefRuby

Opscode“Systems Integration

Framework”

AutomatedScalable

Open Source

Community

Server Provisioning

Tuesday, April 26, 2011

ChefRuby

Opscode“Systems Integration

Framework”

AutomatedScalable

Hotness

Open Source

Community

Server Provisioning

Tuesday, April 26, 2011

An alternative toshell 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 quickQuickstart

“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}" )

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

Error for version=""

Fixed options :(

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://wiki.opscode.com/display/chef/Architecture

http://community.opscode.com/cookbooks

Tuesday, April 26, 2011

Alternative?

Tuesday, April 26, 2011

Shell Scripts!

Tuesday, April 26, 2011

LinecookA 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 systemsPrior experience applies any learning will feed back into existing workflow

Start with a ScriptEnd 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 quickQuickstart

Make a server

Make a script

Run script on server

Tuesday, April 26, 2011

Pretty quickQuickstart

Make a server

Make a script

Run script on server

1

Tuesday, April 26, 2011

Pretty quickQuickstart

Make a server

Make a script

Run script on server

1

2

Tuesday, April 26, 2011

Pretty quickQuickstart

Make a server

Make a script

Run script on server

1

2

3

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

Install OS

SSH Key Exchange

VirtualBox

localhost

Tuesday, April 26, 2011

How to Make a Server

VirtualBox

Install OS

SSH Key Exchange

VirtualBox

abox-ubuntu

localhost

Tuesday, April 26, 2011

How to Make a Server

VirtualBox

Install OS

SSH Key Exchange

VirtualBox

abox-ubuntu

localhost

Tuesday, April 26, 2011

abox-ubuntu

localhost

VirtualBox

Port Forwarding

Access VM by ssh to localhost

ssh -p 2220 linecook@localhost

VBoxManage modifyvm abox --natpf1 'abox-ssh,tcp,,

2220,,22'

Tuesday, April 26, 2011

abox-ubuntu

localhost

bbox-ubuntu

Lather, rinse

Repeat as needed

ssh -p 2220 linecook@localhost

ssh -p 2221 linecook@localhost

...VBoxManage modifyvm bbox

--natpf1 'bbox-ssh,tcp,,2221,,22'

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!"DOCchmod +x script.sh

scp -P 2220 script.sh linecook@localhost:/tmp/script.shssh -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!"DOCchmod +x script.sh

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

Tuesday, April 26, 2011

Use SSH Configmkdir configcat > config/ssh <<"DOC" Host aboxPort 2220User linecookHostname localhostDOC

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

Tuesday, April 26, 2011

Multiple Hostscat > config/ssh <<"DOC"Host aboxPort 2220

Host bboxPort 2221

Host *User linecookHostname localhostDOC

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

Tuesday, April 26, 2011

Redundancycat > config/ssh <<"DOC"Host aboxPort 2220

Host bboxPort 2221

Host *User linecookHostname localhostDOC

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

Tuesday, April 26, 2011

Redundancycat > config/ssh <<"DOC"Host aboxPort 2220

Host bboxPort 2221

Host *User linecookHostname localhostDOC

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

Tuesday, April 26, 2011

Make a “Package”Run with Linecook

[config/ssh] Host aboxPort 2220 Host bboxPort 2221

Host *User linecookHostname localhost

[packages/abox/script.sh]echo "# $(whoami)@$(hostname): hello world!"

[packages/bbox/script.sh]echo "# $(whoami)@$(hostname): Hullo Wurld!"

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] Host aboxPort 2220 Host bboxPort 2221

Host *User linecookHostname localhost

[packages/abox/run]echo "# $(whoami)@$(hostname): hello world!"

[packages/bbox/run]echo "# $(whoami)@$(hostname): Hullo Wurld!"

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

script: runremote dir: ~/linecookhosts: *

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# faillinecook run linecook run --script test# success

Tuesday, April 26, 2011

Cmdline Dev Cycle

linecook startlinecook runlinecook run --script testlinecook ssh aboxlinecook snapshot modifiedlinecook 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: run: abox

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

A package file

Tuesday, April 26, 2011

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

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

A tempfile(packages/abox/run)

Tuesday, April 26, 2011

Simplify

[packages/abox.yml]{}

If default, nomanifest 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 buildlinecook 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 asContext 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 Contextclass Recipe attr_accessor :target def initialize @target = "" end def obj "milk" endend

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

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

# => "got milk"

Tuesday, April 26, 2011

Make a Modulemodule Helper def get(obj) target<<"got "; target<<(( obj ).to_s) endend

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

# => "got milk, got cookies"

Tuesday, April 26, 2011

Make a Modulemodule Helper def get(obj) target<<"got "; target<<(( obj ).to_s) endend

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

# => "got milk, got cookies"

This is a recipe!

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]Write an echo statement(str)--echo "<%= str %>"

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

[lib/example.rb]module Example # Write an echo ... def echo(str) target<< "echo ";... endend

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"

[lib/example.rb]module Example # Write an echo ... def echo(str) target<< "echo ";... endend

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"

[lib/example.rb]module Example # Write an echo ... def echo(str) target<< "echo ";... endend

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"

[lib/example.rb]module Example # Write an echo ... def echo(str) target<< "echo ";... endend

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"

[lib/example.rb]module Example # Write an echo ... def echo(str) target<< "echo ";... endend

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"

[lib/example.rb]module Example # Write an echo ... def echo(str) target<< "echo ";... endend

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"

require "example"extend Example

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 buildlinecook 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 underscoreString 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 buildlinecook 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 buildlinecook 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!' endend

cat('/tmp/message')

Tuesday, April 26, 2011

Logic + Pipelines[packages/demo/run]

if ! [ -f "/tmp/message" ]then cat > /tmp/message << HEREDOC_0hello world!HEREDOC_0fi

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

Recipes Packages

Server

AttributesHelpers

FilesTemplates

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