├── .gitignore
├── CHANGELOG
├── LICENSE
├── README.textile
├── Rakefile
├── bin
└── spatula
├── lib
├── spatula.rb
└── spatula
│ ├── cook.rb
│ ├── prepare.rb
│ ├── search.rb
│ └── ssh_command.rb
├── scripts
├── forward_ports.rb
├── ssh_port
└── ssh_to_virtualbox
├── spatula.gemspec
└── test
├── integration
└── spatula_test.rb
├── keys
├── spatula-integration
└── spatula-integration.pub
└── test-chef-repo
├── .gitignore
├── README
├── Rakefile
├── certificates
└── README
├── config
├── client.rb.example
├── knife.rb.example
├── local.json
├── rake.rb
├── server.rb.example
└── solo.rb
├── cookbooks
├── README
└── test_cookbook
│ ├── README.rdoc
│ ├── metadata.rb
│ └── recipes
│ └── default.rb
├── roles
├── README
└── base_example.rb
└── site-cookbooks
└── README
/.gitignore:
--------------------------------------------------------------------------------
1 | pkg/*
2 | vms/*
3 |
--------------------------------------------------------------------------------
/CHANGELOG:
--------------------------------------------------------------------------------
1 | Version: 0.0.12
2 | ---------------
3 |
4 | - Add support for arbitrary versions of ruby using
5 | the --ruby_version= flag (Thanks matschaffer)
6 |
7 | Version: 0.0.11
8 | ---------------
9 |
10 | - Properly secure ssh files (Thanks hectcastro)
11 | - Better ubuntu packages (Thanks erikh)
12 |
13 | Version: 0.0.10
14 | ---------------
15 |
16 | - Updated to latest rubygems and ruby (Thanks erikh).
17 | - Added support for alternate keyfiles using --keyfile (Thanks erikh).
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2009 Trotter Cashion
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.textile:
--------------------------------------------------------------------------------
1 | h1. Spatula
2 |
3 | Spatula is a command line helper app for use with "Chef":http://www.opscode.com/chef. It currently lets you search and install cookbooks from http://cookbooks.opscode.com. It does not yet implement the full API, but that will be coming in future versions (as I need it). If you need it to support the full API *right now*, please make it do so and send me a pull request :-)
4 |
5 | Spatula is really, really alpha. It does not handle errors at all, but it works pretty well given that you hand it the correct input. Please give it a try and pretty please fork it and make it better.
6 |
7 | h1. Installation
8 |
9 | You can get spatula from gemcutter.
10 |
11 |
12 | # Gemcutter:
13 | # Follow the instructions on http://gemcutter.org/ then...
14 | gem install spatula
15 |
16 |
17 | h1. Usage
18 |
19 | Spatula currently supports 6 commands: search, show, install, prepare, and cook.
20 |
21 |
22 | $ spatula search apache2
23 | apache2 Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions
24 | ... more output ...
25 |
26 | $ spatula show apache2
27 | name: apache2
28 | average_rating:
29 | category: Web Servers
30 | created_at: 2009-10-25T23:47:55Z
31 | updated_at: 2009-10-25T23:47:55Z
32 | maintainer: jtimberman
33 | latest_version: http://cookbooks.opscode.com/api/v1/cookbooks/apache2/versions/0_9_1
34 | external_url:
35 | versions: http://cookbooks.opscode.com/api/v1/cookbooks/apache2/versions/0_9_1
36 | description: Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions
37 |
38 | $ spatula install apache2
39 | ... downloads the apache2 cookbook and installs it into $(pwd)/cookbooks ...
40 | ... also creates a $(pwd)/cookbook_tarballs dir to store the download ...
41 |
42 | $ spatula prepare user@192.168.1.101
43 | ... installs ruby, chef and dependencies on 192.168.1.101
44 | ... starts by adding your ssh public key to authorized_keys
45 |
46 | $ spatula cook user@192.168.1.101
47 | ... uploads all of the files in the current directory to /tmp/chef-solo/
48 | ... expects solo.rb and .json to live in ./config
49 |
50 |
51 |
52 | h1. About
53 |
54 | h2. Official Repo
55 |
56 | http://github.com/trotter/spatula
57 |
58 | h2. Author
59 |
60 | Trotter Cashion
61 |
62 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'rake'
3 | require 'rake/gempackagetask'
4 | load 'spatula.gemspec'
5 |
6 | Rake::GemPackageTask.new($spec) do |t|
7 | t.need_tar = true
8 | end
9 |
--------------------------------------------------------------------------------
/bin/spatula:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | begin
4 | require 'spatula'
5 | rescue LoadError
6 | require 'rubygems'
7 | require 'spatula'
8 | end
9 |
10 | Spatula::Spatula.start
11 |
12 |
--------------------------------------------------------------------------------
/lib/spatula.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'net/http'
3 | require 'uri'
4 | require 'json'
5 | require 'thor'
6 |
7 | module Spatula
8 | BASE_URL = "http://cookbooks.opscode.com/api/v1"
9 |
10 | class Spatula < Thor
11 | desc "show COOKBOOK", "Show information about a cookbook"
12 | def show(name)
13 | print_response(get_cookbook_info(name))
14 | end
15 |
16 | desc "show_latest_version COOKBOOK", "Show the latest version for a cookbook"
17 | def show_latest_version(name)
18 | print_response(get_version_info(name))
19 | end
20 |
21 | desc "install COOKBOOK", "Install the latest version of COOKBOOK into ./cookbooks"
22 | def install(name)
23 | file = JSON.parse(get_version_info(name))["file"]
24 | filename = File.basename(file)
25 | # Use ENV['HOME'] as the base here
26 | tarball_dir = "#{ENV['HOME']}/.spatula/cookbook_tarballs"
27 | FileUtils.mkdir_p(tarball_dir)
28 | system "curl #{file} -o #{tarball_dir}/#{filename}"
29 | system "tar xzvf #{tarball_dir}/#{filename} -C cookbooks"
30 | end
31 |
32 | desc "search QUERY", "Search cookbooks.opscode.com for cookbooks matching QUERY"
33 | method_options :start => 0, :count => 10
34 | def search(query)
35 | Search.run(query, options[:start], options[:count])
36 | end
37 |
38 | desc "cook SERVER NODE", "Cook SERVER with the specification in config/NODE.js. Use local as the server to cook this box."
39 | method_options :port => nil
40 | method_options :login => nil
41 | method_options :identity => nil
42 | method_options :log_level => nil
43 | def cook(server, node)
44 | Cook.run(server, node, options[:port], options[:login], options[:identity], options[:log_level])
45 | end
46 |
47 | desc "prepare SERVER", "Install software/libs required by chef on SERVER"
48 | method_options :port => nil
49 | method_options :login => nil
50 | method_options :identity => nil
51 | method_options :upload_key => nil
52 | method_options :keyfile => :string
53 | method_options :ruby_version => :string
54 | def prepare(server)
55 | Prepare.run(server, options[:port], options[:login], options[:identity], options[:upload_key], options[:keyfile], options[:ruby_version])
56 | end
57 |
58 | private
59 | def get_cookbook_info(name)
60 | url = URI.parse("%s/cookbooks/%s" % [BASE_URL, name])
61 | Net::HTTP.get(url)
62 | end
63 |
64 | def get_version_info(name)
65 | latest = JSON.parse(get_cookbook_info(name))["latest_version"]
66 | response = Net::HTTP.get(URI.parse(latest))
67 | end
68 |
69 | def print_response(response)
70 | item = JSON.parse(response)
71 | item.each_pair do |k, v|
72 | puts "#{k}:\t#{v}"
73 | end
74 | end
75 | end
76 | end
77 |
78 | if __FILE__ == $0
79 | $: << File.dirname(__FILE__)
80 | end
81 |
82 | require 'spatula/ssh_command'
83 | require 'spatula/search'
84 | require 'spatula/prepare'
85 | require 'spatula/cook'
86 |
87 | if __FILE__ == $0
88 | Spatula::Spatula.start
89 | end
90 |
--------------------------------------------------------------------------------
/lib/spatula/cook.rb:
--------------------------------------------------------------------------------
1 | module Spatula
2 | # TODO: Set REMOTE_CHEF_PATH using value for file_cache_path
3 | REMOTE_CHEF_PATH = "/tmp/chef-solo" # Where to find upstream cookbooks
4 |
5 | class Cook < SshCommand
6 | def initialize(server, node, port=nil, login=nil, identity=nil, log_level=nil)
7 | super(server, port, login, identity)
8 | @node = node
9 | @log_level = log_level
10 | end
11 |
12 | def run
13 | Dir["**/*.rb"].each do |recipe|
14 | ok = sh "ruby -c #{recipe} >/dev/null 2>&1"
15 | raise "Syntax error in #{recipe}" if not ok
16 | end
17 |
18 | Dir["**/*.json"].each do |json|
19 | begin
20 | require 'json'
21 | # parse without instantiating Chef classes
22 | JSON.parse File.read(json), :create_additions => false
23 | rescue => error
24 | raise "Syntax error in #{json}: #{error.message}"
25 | end
26 | end
27 |
28 | if @server =~ /^local$/i
29 | sh chef_cmd
30 | else
31 | sh "rsync -rlP --rsh=\"ssh #{ssh_opts}\" --delete --exclude '.*' ./ #@server:#{REMOTE_CHEF_PATH}"
32 | ssh "cd #{REMOTE_CHEF_PATH}; #{chef_cmd}"
33 | end
34 | end
35 |
36 | private
37 | def chef_cmd
38 | "sudo -H -E chef-solo -c config/solo.rb -j config/#@node.json -l #{ @log_level || 'info'}"
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/lib/spatula/prepare.rb:
--------------------------------------------------------------------------------
1 | # Prepare :server: for chef solo to run on it
2 | module Spatula
3 | class Prepare < SshCommand
4 |
5 | RUBYGEMS_VERSION = "1.6.2"
6 | DEFAULT_RUBY_VERSION = "1.9.2-p180"
7 |
8 | def run
9 |
10 | if @key_file and !@upload_key
11 | @upload_key = true
12 | end
13 |
14 | upload_ssh_key if @upload_key
15 | send "run_for_#{os}"
16 | end
17 |
18 | def os
19 | etc_issue = `#{ssh_command("cat /etc/issue")}`
20 | case etc_issue
21 | when /ubuntu/i
22 | "ubuntu"
23 | when /debian/i
24 | "debian"
25 | when /fedora/i
26 | "fedora"
27 | when /CentOS/i
28 | "centos"
29 | when ""
30 | raise "Couldn't get system info from /etc/issue. Please check your SSH credentials."
31 | else
32 | raise "Sorry, we currently only support prepare on ubuntu, debian & fedora. Please fork http://github.com/trotter/spatula and add support for your OS. I'm happy to incorporate pull requests."
33 | end
34 | end
35 |
36 | def run_for_ubuntu
37 | ssh "#{sudo} apt-get update"
38 | ssh "#{sudo} apt-get install -y ruby irb ri libopenssl-ruby1.8 libshadow-ruby1.8 ruby1.8-dev build-essential rsync curl"
39 | install_rubygems
40 | install_chef
41 | end
42 |
43 | def run_for_debian
44 | ssh "#{sudo} apt-get update"
45 | ssh "#{sudo} apt-get install -y build-essential zlib1g-dev libssl-dev libreadline5-dev curl rsync"
46 | install_rubygems
47 | install_chef
48 | end
49 |
50 | def run_for_fedora
51 | sudo = ssh('which sudo > /dev/null 2>&1') ? 'sudo' : ''
52 | ssh "#{sudo} yum install -y make gcc gcc-c++ rsync sudo openssl-devel rubygems ruby-devel ruby-shadow curl"
53 | end
54 |
55 | def run_for_centos
56 | ssh "#{sudo} yum install -y make gcc gcc-c++ rsync sudo openssl-devel curl"
57 | install_ruby
58 | install_chef
59 | end
60 |
61 | def ruby_version
62 | @ruby_version || DEFAULT_RUBY_VERSION
63 | end
64 |
65 | def ruby_path
66 | rev = ruby_version.match(/^(\d+\.\d+)/)[1]
67 | "#{rev}/ruby-#{ruby_version}.tar.gz"
68 | end
69 |
70 | def install_ruby
71 | ssh "curl -L 'ftp://ftp.ruby-lang.org/pub/ruby/#{ruby_path}' | tar xvzf -"
72 | ssh "cd ruby-#{ruby_version} && ./configure && make && #{sudo} make install"
73 | end
74 |
75 | def install_rubygems
76 | ssh "curl -L 'http://production.cf.rubygems.org/rubygems/rubygems-#{RUBYGEMS_VERSION}.tgz' | tar xvzf -"
77 | ssh "cd rubygems* && #{sudo} ruby setup.rb --no-ri --no-rdoc"
78 | ssh "#{sudo} ln -sfv /usr/bin/gem1.8 /usr/bin/gem"
79 | end
80 |
81 | def install_chef
82 | ssh "#{sudo} gem install rdoc chef ohai --no-ri --no-rdoc --source http://gems.opscode.com --source http://gems.rubyforge.org"
83 | end
84 |
85 | def sudo
86 | ssh('which sudo > /dev/null 2>&1') ? 'sudo' : ''
87 | end
88 |
89 | def upload_ssh_key
90 | authorized_file = "~/.ssh/authorized_keys"
91 |
92 | unless @key_file
93 | %w{rsa dsa}.each do |key_type|
94 | filename = "#{ENV['HOME']}/.ssh/id_#{key_type}.pub"
95 | if File.exists?(filename)
96 | @key_file = filename
97 | break
98 | end
99 | end
100 | end
101 |
102 | raise "Key file '#{@key_file}' not found: aborting." unless File.exists?(@key_file)
103 |
104 | key = File.open(@key_file).read.split(' ')[0..1].join(' ')
105 |
106 | ssh "mkdir -p .ssh && echo #{key} >> #{authorized_file}"
107 | ssh "cat #{authorized_file} | sort | uniq > #{authorized_file}.tmp && mv #{authorized_file}.tmp #{authorized_file}"
108 | ssh "chmod 0700 .ssh && chmod 0600 #{authorized_file}"
109 | end
110 | end
111 | end
112 |
--------------------------------------------------------------------------------
/lib/spatula/search.rb:
--------------------------------------------------------------------------------
1 | # Search for cookbooks matching :query:
2 | module Spatula
3 | class Search
4 | def self.run(*args)
5 | new(*args).run
6 | end
7 |
8 | def initialize(query, start=0, count=10)
9 | @query = query
10 | @start = start
11 | @count = count
12 | end
13 |
14 | def run
15 | url = URI.parse("%s/search?q=%s&start=%s&items=%s" % [BASE_URL, @query, @start, @count])
16 | response = Net::HTTP.get(url)
17 | items = JSON.parse(response)["items"]
18 | items.each do |item|
19 | puts [item["cookbook_name"], item["cookbook_description"], item["cookbook_maintainer"]].join("\t")
20 | end
21 | end
22 | end
23 | end
24 |
25 |
--------------------------------------------------------------------------------
/lib/spatula/ssh_command.rb:
--------------------------------------------------------------------------------
1 | module Spatula
2 | class SshCommand
3 | def self.run(*args)
4 | new(*args).run
5 | end
6 |
7 | def initialize(server, port=nil, login=nil, identity=nil, upload_key=nil, key_file=nil, ruby_version=nil)
8 | @server = server
9 | @port = port
10 | @port_switch = port ? " -p #{port}" : ''
11 | @login_switch = login ? "-l #{login}" : ''
12 | @identity_switch = identity ? %Q|-i "#{identity}"| : ''
13 | @upload_key = upload_key
14 | @key_file = key_file
15 | @ruby_version = ruby_version
16 | end
17 |
18 | def ssh(command)
19 | sh ssh_command(command)
20 | end
21 |
22 | def ssh_command(command)
23 | %Q|ssh -t#{ssh_opts} #@server "#{command.gsub('"', '\\"')}"|
24 | end
25 |
26 | def ssh_opts
27 | "#@port_switch #@login_switch #@identity_switch"
28 | end
29 |
30 | private
31 | def sh(command)
32 | system command
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/scripts/forward_ports.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require 'rubygems'
4 | require 'virtualbox'
5 |
6 | module VirtualBox
7 | class VM
8 | def main_interface_name
9 | interface = nics.first.nictype
10 | case interface
11 | when /82540EM/
12 | return 'e1000'
13 | else
14 | abort "Cannot reliably determine the network interface. Email trotter (cashion@gmail.com)"
15 | end
16 | end
17 |
18 | def set_interface_data service, key, value
19 | extra_data["VBoxInternal/Devices/#{main_interface_name}/0/LUN#0/Config/#{service}/#{key}"] = value
20 | end
21 |
22 | def forward_port service, from, to, protocol="TCP"
23 | set_interface_data service, "HostPort", from
24 | set_interface_data service, "GuestPort", to
25 | set_interface_data service, "Protocol", protocol
26 | end
27 | end
28 | end
29 |
30 | if __FILE__ == $0
31 | port = File.read(File.dirname(__FILE__) + "/ssh_port").chomp.to_i
32 | image = ARGV[0] || abort("Usage: #$0 ")
33 |
34 | vm = VirtualBox::VM.find(image)
35 |
36 | puts "Forwarding ports for ssh"
37 | vm.forward_port 'SSH', port, 22
38 | vm.save
39 | end
40 |
--------------------------------------------------------------------------------
/scripts/ssh_port:
--------------------------------------------------------------------------------
1 | 3322
2 |
--------------------------------------------------------------------------------
/scripts/ssh_to_virtualbox:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ssh -p $(cat $(dirname $0)/ssh_port) -l spatula $@ localhost
4 |
--------------------------------------------------------------------------------
/spatula.gemspec:
--------------------------------------------------------------------------------
1 | PKG_VERSION = "0.0.12"
2 | PKG_FILES = Dir['README.textile',
3 | 'bin/*',
4 | 'lib/**/*.rb']
5 |
6 | $spec = Gem::Specification.new do |s|
7 | s.name = 'spatula'
8 | s.version = PKG_VERSION
9 | s.summary = "Command line helper app for use with Chef"
10 | s.description = <= 0.13.4")
16 | s.add_dependency("json", ">= 1.2.4")
17 | s.files = PKG_FILES.to_a
18 | s.bindir = 'bin'
19 | s.executables = 'spatula'
20 | s.has_rdoc = false
21 | s.author = "Trotter Cashion"
22 | s.email = "cashion@gmail.com"
23 | s.homepage = "http://trottercashion.com"
24 | end
25 |
--------------------------------------------------------------------------------
/test/integration/spatula_test.rb:
--------------------------------------------------------------------------------
1 | ## THIS TEST WON'T WORK ON YOUR MACHINE
2 | ## YOU NEED A VM THAT ONLY I HAVE RIGHT NOW
3 | ## Sorry
4 |
5 | require 'test/unit'
6 |
7 | SPATULA_ROOT = File.dirname(__FILE__) + '/../..'
8 | VM_PORT = 3322
9 | IDENTITY = SPATULA_ROOT + '/test/keys/spatula-integration'
10 |
11 | class SpatulaTest < Test::Unit::TestCase
12 | def setup
13 | start_vm("spatula-ubuntu-9.10-64bit")
14 | end
15 |
16 | def teardown
17 | stop_vm
18 | end
19 |
20 | def test_prepares_server
21 | sh "ruby #{SPATULA_ROOT}/lib/spatula.rb prepare localhost --port=#{VM_PORT} --login=spatula --identity=#{IDENTITY}"
22 | assert ssh("gem list | grep chef")
23 | end
24 |
25 | def start_vm(vm)
26 | sh "VBoxManage startvm #{vm}"
27 | sleep 2 until ssh "ls"
28 | end
29 |
30 | def stop_vm
31 | unless ssh "sudo shutdown -h now"
32 | raise "Cannot connect to VM, are you sure it is running?"
33 | end
34 | end
35 |
36 | def ssh(command)
37 | sh %Q|ssh -l spatula -p #{VM_PORT} -i #{IDENTITY} localhost "#{command.gsub('"', '\\"')}"|
38 | end
39 |
40 | def sh(command)
41 | puts "running: #{command}"
42 | system command
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/test/keys/spatula-integration:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEA2r8jdg1R3YYxpGnxWPGgDsd81kqmWR7dYArz7J57iASdscT8
3 | +waOKCLnPnvIZAWm4ZYI9XBsHpt4FGuXGiIYQ6eTWn2P6m+zY9CKPcWNrPrqOJul
4 | tXkv1VbH7c+DMmq9TFSQNGF0lsOpB5bX96C0igqr8mL5TyUATJv0ZuPbfPFHEwHD
5 | p7ugaCTdtktsvY/MI+LjPZH/Mpk5LPBbkUF44R1fTSoGHxveUNVY6qHCkf4TbeeF
6 | WRZa70NcbnCnx7SdocWQjpkWNi97DaX6+/490CMQAwRWr4BvJBG6Ms1CNKm0rjRT
7 | tPE83tfmpcnOyyDHn1qt60migE4nqWJDZyFYUQIBIwKCAQEAx/82XU4BtJfy33bO
8 | CC1fI3SPZNaJdg2XMz02ybV4QdhVqdisyECB+M90VmKLVCJssP40E5n8c8FX2Cfa
9 | m4zi/AbtH4i+GCucswfO2WQpwrmFsBlHDFGK0a5tpjoRjS5j7gQsEqI+tbo0JDIk
10 | iqGPHx+zJsDj8Jbbs8HJgqRw50FNfDedKGe4iIIgEbBwKb+OxrUC93N6mL0CTEfg
11 | pe44OT+dElO6Lvtcs7b1k7yhoMGK4Oc3H+CjgAngFJy3R1wuy4L4TMTpWpDMJTDW
12 | ka8Zuk0H4C5+lLkDktiTCzHg0e9dP510dNiwiyG4ZNGUPNV0BhSxqiKv3wpQyoOz
13 | CbKJiwKBgQD838xEEP2xCgYqYMVy+MjjRVoK4H5GI1lG0QeLf8ixanvjelyLgJit
14 | UrvQFi4ixx1WliioIvhgtS9g+JyobWvKSCeHlH4Ou8WYVFlpQi/a4GNR8+XhjpHz
15 | nm+/fTxoFk5lB0+Vo7DyxNThG3Sp0PpsBr2BtWlUmHHLqQKFddrjJQKBgQDdc1ir
16 | sox9iNBgQiz/Fx1ktTLdHm1q+DE32HoyW/w5+APoBsHm+yBDmYlsOt1PAw0M8cH4
17 | 60BHZgkuX0iW5DwAKwbJZiOoP1uDcJ8nCnbey/t9ceuarkQfnQUZ4VJMOL2BqVCG
18 | sXNJAdYj3A/q15zksfaJ48pdi+kTot+yHqsuvQKBgQCJRkpQ1gYPplseUcpFukEq
19 | 6yJAaz08BI+M19+GPg3cp4UVFooClkRA1SQggRG7G6I2UYPI/Qp9pC+pq4g+LMV8
20 | cE/5JLl1tmPzm4D+oEXdN/tnAL6fBECaMW/c+temN/6r32W3ogD40UBc8aW7RY9B
21 | 9QfKEgX6uSfU9Vkj4OSJ7wKBgAyngWjloaDF/UdUPRXkEE7lyGRoI4J0lRkiUCAi
22 | g3EG26bb0JDbJmpDSa5pw4DbmliC1+JWlfVzi37+IWe1RUHWkqxsPI1FcvGRaC4d
23 | 2ugo6cynbIx+/JQXmeQ4wt/Iul8uPx2jvXHi2QldCDlOJjj0OflAN3MPTyWxiSAf
24 | AnezAoGBAMlgf31IJrYllNGXiLXY1+yyLkODkuGoOim4NxGG2rRe2EBYIVzw/5bM
25 | VnLZE/vx6IBiIDFLXzdL9nqtvBzItCRR7aFIC3I66ZOMUWmHmjsO0sIfTE6BcVKp
26 | V5YDFaLd63TrKyFmy9Fti355xUEY+n9fzKwhxPU1Iy0Y9/YARSjZ
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/test/keys/spatula-integration.pub:
--------------------------------------------------------------------------------
1 | ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2r8jdg1R3YYxpGnxWPGgDsd81kqmWR7dYArz7J57iASdscT8+waOKCLnPnvIZAWm4ZYI9XBsHpt4FGuXGiIYQ6eTWn2P6m+zY9CKPcWNrPrqOJultXkv1VbH7c+DMmq9TFSQNGF0lsOpB5bX96C0igqr8mL5TyUATJv0ZuPbfPFHEwHDp7ugaCTdtktsvY/MI+LjPZH/Mpk5LPBbkUF44R1fTSoGHxveUNVY6qHCkf4TbeeFWRZa70NcbnCnx7SdocWQjpkWNi97DaX6+/490CMQAwRWr4BvJBG6Ms1CNKm0rjRTtPE83tfmpcnOyyDHn1qt60migE4nqWJDZyFYUQ== trotter@Trotter-Cashions-MacBook-Pro.local
2 |
--------------------------------------------------------------------------------
/test/test-chef-repo/.gitignore:
--------------------------------------------------------------------------------
1 | .rake_test_cache
2 |
3 |
--------------------------------------------------------------------------------
/test/test-chef-repo/README:
--------------------------------------------------------------------------------
1 | This is a blank repository you can use as a starting point for your
2 | local chef configuration. For full details on the parts aside from
3 | information contained in the README files, see the Chef wiki document
4 |
5 | http://wiki.opscode.com/display/chef/Chef+Repository
6 |
--------------------------------------------------------------------------------
/test/test-chef-repo/Rakefile:
--------------------------------------------------------------------------------
1 | #
2 | # Rakefile for Chef Server Repository
3 | #
4 | # Author:: Adam Jacob ()
5 | # Copyright:: Copyright (c) 2008 Opscode, Inc.
6 | # License:: Apache License, Version 2.0
7 | #
8 | # Licensed under the Apache License, Version 2.0 (the "License");
9 | # you may not use this file except in compliance with the License.
10 | # You may obtain a copy of the License at
11 | #
12 | # http://www.apache.org/licenses/LICENSE-2.0
13 | #
14 | # Unless required by applicable law or agreed to in writing, software
15 | # distributed under the License is distributed on an "AS IS" BASIS,
16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | # See the License for the specific language governing permissions and
18 | # limitations under the License.
19 | #
20 |
21 | require 'rubygems'
22 | require 'chef'
23 | require 'json'
24 |
25 | # Load constants from rake config file.
26 | require File.join(File.dirname(__FILE__), 'config', 'rake')
27 |
28 | # Detect the version control system and assign to $vcs. Used by the update
29 | # task in chef_repo.rake (below). The install task calls update, so this
30 | # is run whenever the repo is installed.
31 | #
32 | # Comment out these lines to skip the update.
33 |
34 | if File.directory?(File.join(TOPDIR, ".svn"))
35 | $vcs = :svn
36 | elsif File.directory?(File.join(TOPDIR, ".git"))
37 | $vcs = :git
38 | end
39 |
40 | # Load common, useful tasks from Chef.
41 | # rake -T to see the tasks this loads.
42 |
43 | load 'chef/tasks/chef_repo.rake'
44 |
45 | desc "Bundle a single cookbook for distribution"
46 | task :bundle_cookbook => [ :metadata ]
47 | task :bundle_cookbook, :cookbook do |t, args|
48 | tarball_name = "#{args.cookbook}.tar.gz"
49 | temp_dir = File.join(Dir.tmpdir, "chef-upload-cookbooks")
50 | temp_cookbook_dir = File.join(temp_dir, args.cookbook)
51 | tarball_dir = File.join(TOPDIR, "pkgs")
52 | FileUtils.mkdir_p(tarball_dir)
53 | FileUtils.mkdir(temp_dir)
54 | FileUtils.mkdir(temp_cookbook_dir)
55 |
56 | child_folders = [ "cookbooks/#{args.cookbook}", "site-cookbooks/#{args.cookbook}" ]
57 | child_folders.each do |folder|
58 | file_path = File.join(TOPDIR, folder, ".")
59 | FileUtils.cp_r(file_path, temp_cookbook_dir) if File.directory?(file_path)
60 | end
61 |
62 | system("tar", "-C", temp_dir, "-cvzf", File.join(tarball_dir, tarball_name), "./#{args.cookbook}")
63 |
64 | FileUtils.rm_rf temp_dir
65 | end
66 |
67 |
--------------------------------------------------------------------------------
/test/test-chef-repo/certificates/README:
--------------------------------------------------------------------------------
1 | This directory contains certificates created by the Rakefile.
2 |
--------------------------------------------------------------------------------
/test/test-chef-repo/config/client.rb.example:
--------------------------------------------------------------------------------
1 | #
2 | # Example Chef Client Config File
3 | #
4 | # We recommend using Opscode's chef cookbook for managing chef itself,
5 | # instead of using this file. It is provided as an example.
6 |
7 | log_level :info
8 | log_location STDOUT
9 | ssl_verify_mode :verify_none
10 | chef_server_url "http://chef.example.com:4000"
11 |
12 | validation_client_name "chef-validator"
13 | validation_key "/etc/chef/validation.pem"
14 | client_key "/etc/chef/client.pem"
15 |
16 | file_store_path "/srv/chef/file_store"
17 | file_cache_path "/srv/chef/cache"
18 |
19 | pid_file "/var/run/chef/chef-client.pid"
20 |
21 | Mixlib::Log::Formatter.show_time = true
22 |
--------------------------------------------------------------------------------
/test/test-chef-repo/config/knife.rb.example:
--------------------------------------------------------------------------------
1 | log_level :info
2 | log_location STDOUT
3 | node_name 'chef_admin'
4 | client_key '/home/chef_admin/.chef/chef_admin.pem'
5 | validation_client_name 'chef-validator'
6 | validation_key '/home/chef_admin/.chef/chef-validator.pem'
7 | chef_server_url 'http://chef.example.com:4000'
8 | cache_type 'BasicFile'
9 | cache_options( :path => '/home/chef_admin/.chef/checksums' )
10 | cookbook_path [ './cookbooks', './site-cookbooks' ]
11 |
--------------------------------------------------------------------------------
/test/test-chef-repo/config/local.json:
--------------------------------------------------------------------------------
1 | {
2 | "recipes": ["test_cookbook"]
3 | }
4 |
--------------------------------------------------------------------------------
/test/test-chef-repo/config/rake.rb:
--------------------------------------------------------------------------------
1 | ###
2 | # Company and SSL Details
3 | ###
4 |
5 | # The company name - used for SSL certificates, and in srvious other places
6 | COMPANY_NAME = "Example Com"
7 |
8 | # The Country Name to use for SSL Certificates
9 | SSL_COUNTRY_NAME = "US"
10 |
11 | # The State Name to use for SSL Certificates
12 | SSL_STATE_NAME = "Several"
13 |
14 | # The Locality Name for SSL - typically, the city
15 | SSL_LOCALITY_NAME = "Locality"
16 |
17 | # What department?
18 | SSL_ORGANIZATIONAL_UNIT_NAME = "Operations"
19 |
20 | # The SSL contact email address
21 | SSL_EMAIL_ADDRESS = "ops@example.com"
22 |
23 | # License for new Cookbooks
24 | # Can be :apachev2 or :none
25 | NEW_COOKBOOK_LICENSE = :apachev2
26 |
27 | ##########################
28 | # Chef Repository Layout #
29 | ##########################
30 |
31 | # Where to install upstream cookbooks for serving
32 | COOKBOOK_PATH = "/srv/chef/cookbooks"
33 |
34 | # Where to install site-local modifications to upstream cookbooks
35 | SITE_COOKBOOK_PATH = "/srv/chef/site-cookbooks"
36 |
37 | # Where to install roles
38 | ROLE_PATH = "/srv/chef/roles"
39 |
40 | # Chef Config Path
41 | CHEF_CONFIG_PATH = "/etc/chef"
42 |
43 | # The location of the Chef Server Config file (on the server)
44 | CHEF_SERVER_CONFIG = File.join(CHEF_CONFIG_PATH, "server.rb")
45 |
46 | # The location of the Chef Client Config file (on the client)
47 | CHEF_CLIENT_CONFIG = File.join(CHEF_CONFIG_PATH, "client.rb")
48 |
49 | ###
50 | # Useful Extras (which you probably don't need to change)
51 | ###
52 |
53 | # The top of the repository checkout
54 | TOPDIR = File.expand_path(File.join(File.dirname(__FILE__), ".."))
55 |
56 | # Where to store certificates generated with ssl_cert
57 | CADIR = File.expand_path(File.join(TOPDIR, "certificates"))
58 |
59 | # Where to store the mtime cache for the recipe/template syntax check
60 | TEST_CACHE = File.expand_path(File.join(TOPDIR, ".rake_test_cache"))
--------------------------------------------------------------------------------
/test/test-chef-repo/config/server.rb.example:
--------------------------------------------------------------------------------
1 | #
2 | # Chef Server Config File
3 | #
4 | # We recommend using Opscode's chef cookbook for managing chef itself,
5 | # instead of using this file. It is provided as an example.
6 |
7 | log_level :info
8 | log_location STDOUT
9 | ssl_verify_mode :verify_none
10 | chef_server_url "http://chef.example.com:4000"
11 |
12 | signing_ca_path "/srv/chef/ca"
13 | couchdb_database 'chef'
14 |
15 | cookbook_path [ "/srv/chef/cookbooks", "/srv/chef/site-cookbooks" ]
16 |
17 | file_cache_path "/srv/chef/cache"
18 | node_path "/srv/chef/nodes"
19 | openid_store_path "/srv/chef/openid/store"
20 | openid_cstore_path "/srv/chef/openid/cstore"
21 | search_index_path "/srv/chef/search_index"
22 | role_path "/srv/chef/roles"
23 |
24 | validation_client_name "chef-validator"
25 | validation_key "/etc/chef/validation.pem"
26 | client_key "/etc/chef/client.pem"
27 | web_ui_client_name "chef-webui"
28 | web_ui_key "/etc/chef/webui.pem"
29 |
30 | # change this as required.
31 | #web_ui_admin_user_name "admin"
32 | #web_ui_admin_default_password "replace_with_something_secure"
33 |
34 | supportdir = "/srv/chef/support"
35 | solr_jetty_path File.join(supportdir, "solr", "jetty")
36 | solr_data_path File.join(supportdir, "solr", "data")
37 | solr_home_path File.join(supportdir, "solr", "home")
38 | solr_heap_size "256M"
39 |
40 | umask 0022
41 |
42 | Mixlib::Log::Formatter.show_time = false
43 |
--------------------------------------------------------------------------------
/test/test-chef-repo/config/solo.rb:
--------------------------------------------------------------------------------
1 | #
2 | # Chef Solo Config File
3 | #
4 |
5 | base_path = File.expand_path(File.dirname(__FILE__) + '/..')
6 |
7 | log_level :info
8 | log_location STDOUT
9 | file_cache_path "/var/chef/cookbooks"
10 |
11 | file_cache_path base_path
12 | cookbook_path ["#{base_path}/site-cookbooks",
13 | "#{base_path}/cookbooks"]
14 |
15 | # Optionally store your JSON data file and a tarball of cookbooks remotely.
16 | #json_attribs "http://chef.example.com/dna.json"
17 | #recipe_url "http://chef.example.com/cookbooks.tar.gz"
18 |
19 | Mixlib::Log::Formatter.show_time = true
20 |
--------------------------------------------------------------------------------
/test/test-chef-repo/cookbooks/README:
--------------------------------------------------------------------------------
1 | This directory contains upstream or shared cookbooks.
2 |
3 | To replace this with a Git repository, remove this directory and
4 | clone the upstream repository.
5 |
--------------------------------------------------------------------------------
/test/test-chef-repo/cookbooks/test_cookbook/README.rdoc:
--------------------------------------------------------------------------------
1 | = DESCRIPTION:
2 |
3 | = REQUIREMENTS:
4 |
5 | = ATTRIBUTES:
6 |
7 | = USAGE:
8 |
9 |
--------------------------------------------------------------------------------
/test/test-chef-repo/cookbooks/test_cookbook/metadata.rb:
--------------------------------------------------------------------------------
1 | maintainer "Example Com"
2 | maintainer_email "ops@example.com"
3 | license "Apache 2.0"
4 | description "Installs/Configures test_cookbook"
5 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
6 | version "0.1"
7 |
--------------------------------------------------------------------------------
/test/test-chef-repo/cookbooks/test_cookbook/recipes/default.rb:
--------------------------------------------------------------------------------
1 | #
2 | # Cookbook Name:: test_cookbook
3 | # Recipe:: default
4 | #
5 | # Copyright 2010, Example Com
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 | #
19 |
20 | directory "#{ENV['HOME']}/test_dir" do
21 | action :create
22 | end
23 |
--------------------------------------------------------------------------------
/test/test-chef-repo/roles/README:
--------------------------------------------------------------------------------
1 | Create roles here, in either .rb or .json files. To install roles on the
2 | server, use knife. We provide an example role here.
3 |
4 | knife role from file roles/base_example.rb
5 |
--------------------------------------------------------------------------------
/test/test-chef-repo/roles/base_example.rb:
--------------------------------------------------------------------------------
1 | name "base_example"
2 | description "Example base role applied to all nodes."
3 | # List of recipes and roles to apply. Requires Chef 0.8, earlier versions use 'recipes()'.
4 | #run_list()
5 |
6 | # Attributes applied if the node doesn't have it set already.
7 | #default_attributes()
8 |
9 | # Attributes applied no matter what the node has set already.
10 | #override_attributes()
11 |
--------------------------------------------------------------------------------
/test/test-chef-repo/site-cookbooks/README:
--------------------------------------------------------------------------------
1 | This directory contains cookbooks that modify upstream ones,
2 | or that are specific to your site.
3 |
--------------------------------------------------------------------------------