food_court 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## RubyMine
9
+ .idea
10
+
11
+ ## EMACS
12
+ *~
13
+ \#*
14
+ .\#*
15
+
16
+ ## VIM
17
+ *.swp
18
+
19
+ ## PROJECT::GENERAL
20
+ coverage
21
+ rdoc
22
+ pkg
23
+
24
+ ## PROJECT::SPECIFIC
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.8.7-p249@food_court
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Gabe Varela
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,55 @@
1
+ = Food Court
2
+
3
+ Food Court is a streamlined way to use chef-solo and capistrano for VPS's such as slicehost.
4
+
5
+ = Instructions
6
+ * cd into your project
7
+ food-court init
8
+ * add your root user, password, and host to config/chef/bootstrap.rb for bootstrapping your slice
9
+ * setup your slice for chef
10
+ food-court bootstrap
11
+ * modify your order.rb to change any default packages
12
+ * then run update to push up your cookbooks and configure the server with chef-solo
13
+ food-court update
14
+
15
+ = Gotchas
16
+ Since Food Court uses Chef you are bound to run into some Chef specific issues
17
+ Chef help: http://wiki.opscode.com/display/chef/Home
18
+ A good intro to chef-solo: http://akitaonrails.com/2010/02/20/cooking-solo-with-chef
19
+
20
+ a common issue on slicehost is the fqdn in /etc/hosts
21
+ 67.xx.xx.xx my-slice
22
+ should be
23
+ 67.xx.xx.xx my-slice.local my-slice
24
+
25
+ = Roadmap
26
+ * create a default template that works on Ubuntu with Nginx and Passenger
27
+ * add generators for stubbing site-cookbooks in the current project repo
28
+ * enable rollingback a deployment
29
+ * enable setup to accept a remote location for template packages
30
+ * setup a site to house common template packages (similar to the chef cookbooks site)
31
+ * add ability to package up a template package and send to package site
32
+
33
+ == Note on Patches/Pull Requests
34
+
35
+ * Fork the project.
36
+ * Make your feature addition or bug fix.
37
+ * Add tests for it. This is important so I don't break it in a
38
+ future version unintentionally.
39
+ * Commit, do not mess with rakefile, version, or history.
40
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
41
+ * Send me a pull request. Bonus points for topic branches.
42
+
43
+ == Copyright
44
+
45
+ Copyright (c) 2010 Gabe Varela. See LICENSE for details.
46
+
47
+ == Inspiration
48
+ Josh Peek: http://github.com/josh/slicehost/
49
+ Thomas Balthazar: http://github.com/suitmymind/ubuntu-machine/
50
+ Mike Hale: http://github.com/mikehale/drive-thru/
51
+
52
+ == Thanks
53
+ Fabio Akita for the great article on chef-solo
54
+ http://akitaonrails.com/2010/02/20/cooking-solo-with-chef
55
+
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "food_court"
8
+ gem.summary = %Q{Bootstrap and provision your ubuntu slice with ease}
9
+ gem.description = %Q{Bootstrap and provision your ubuntu slice with ease}
10
+ gem.email = "gvarela@gmail.com"
11
+ gem.homepage = "http://github.com/gvarela/food_court"
12
+ gem.authors = ["Gabe Varela"]
13
+ gem.add_dependency('json', '~> 1.4.6')
14
+ gem.add_dependency('activesupport', '~> 2.3.9')
15
+ gem.add_dependency('highline', '~> 1.4.0')
16
+ gem.add_dependency('capistrano', '~> 2.5.5')
17
+ gem.add_dependency('sprinkle', '~> 0.3.1')
18
+ gem.add_development_dependency "rspec", ">= 1.2.9"
19
+ gem.add_development_dependency "yard", ">= 0"
20
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
25
+ end
26
+
27
+ #require 'spec/rake/spectask'
28
+ #Spec::Rake::SpecTask.new(:spec) do |spec|
29
+ # spec.libs << 'lib' << 'spec'
30
+ # spec.spec_files = FileList['spec/**/*_spec.rb']
31
+ #end
32
+ #
33
+ #Spec::Rake::SpecTask.new(:rcov) do |spec|
34
+ # spec.libs << 'lib' << 'spec'
35
+ # spec.pattern = 'spec/**/*_spec.rb'
36
+ # spec.rcov = true
37
+ #end
38
+ #
39
+ #task :spec => :check_dependencies
40
+ #
41
+ #task :default => :spec
42
+ #
43
+ #begin
44
+ # require 'yard'
45
+ # YARD::Rake::YardocTask.new
46
+ #rescue LoadError
47
+ # task :yardoc do
48
+ # abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
49
+ # end
50
+ #end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/food-court ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ require "#{File.dirname(__FILE__)}/../lib/food_court"
3
+
4
+ trap "INT" do
5
+ exit!
6
+ end
7
+
8
+ FoodCourt::Command.new(*ARGV)
@@ -0,0 +1,94 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{food_court}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Gabe Varela"]
12
+ s.date = %q{2010-09-19}
13
+ s.default_executable = %q{food-court}
14
+ s.description = %q{Bootstrap and provision your ubuntu slice with ease}
15
+ s.email = %q{gvarela@gmail.com}
16
+ s.executables = ["food-court"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ ".rvmrc",
25
+ "LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "bin/food-court",
30
+ "food_court.gemspec",
31
+ "lib/food_court.rb",
32
+ "lib/food_court/bootstrap.rb",
33
+ "lib/food_court/command.rb",
34
+ "lib/food_court/packager.rb",
35
+ "lib/food_court/packages/base.rb",
36
+ "lib/food_court/packages/build_essential.rb",
37
+ "lib/food_court/packages/chef_solo.rb",
38
+ "lib/food_court/packages/ruby.rb",
39
+ "lib/food_court/packages/rubygems.rb",
40
+ "lib/food_court/packages/update_chef.rb",
41
+ "lib/food_court/recipes.rb",
42
+ "lib/food_court/update_slice.rb",
43
+ "spec/command_spec.rb",
44
+ "spec/fixtures/order.rb",
45
+ "spec/packager_spec.rb",
46
+ "spec/spec.opts",
47
+ "spec/spec_helper.rb",
48
+ "stacks/nginx-passenger-ree/bootstrap.rb",
49
+ "stacks/nginx-passenger-ree/order.rb"
50
+ ]
51
+ s.homepage = %q{http://github.com/gvarela/food_court}
52
+ s.rdoc_options = ["--charset=UTF-8"]
53
+ s.require_paths = ["lib"]
54
+ s.rubygems_version = %q{1.3.6}
55
+ s.summary = %q{Bootstrap and provision your ubuntu slice with ease}
56
+ s.test_files = [
57
+ "spec/command_spec.rb",
58
+ "spec/fixtures/order.rb",
59
+ "spec/packager_spec.rb",
60
+ "spec/spec_helper.rb"
61
+ ]
62
+
63
+ if s.respond_to? :specification_version then
64
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
65
+ s.specification_version = 3
66
+
67
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
68
+ s.add_runtime_dependency(%q<json>, ["~> 1.4.6"])
69
+ s.add_runtime_dependency(%q<activesupport>, ["~> 2.3.9"])
70
+ s.add_runtime_dependency(%q<highline>, ["~> 1.4.0"])
71
+ s.add_runtime_dependency(%q<capistrano>, ["~> 2.5.5"])
72
+ s.add_runtime_dependency(%q<sprinkle>, ["~> 0.3.1"])
73
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
74
+ s.add_development_dependency(%q<yard>, [">= 0"])
75
+ else
76
+ s.add_dependency(%q<json>, ["~> 1.4.6"])
77
+ s.add_dependency(%q<activesupport>, ["~> 2.3.9"])
78
+ s.add_dependency(%q<highline>, ["~> 1.4.0"])
79
+ s.add_dependency(%q<capistrano>, ["~> 2.5.5"])
80
+ s.add_dependency(%q<sprinkle>, ["~> 0.3.1"])
81
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
82
+ s.add_dependency(%q<yard>, [">= 0"])
83
+ end
84
+ else
85
+ s.add_dependency(%q<json>, ["~> 1.4.6"])
86
+ s.add_dependency(%q<activesupport>, ["~> 2.3.9"])
87
+ s.add_dependency(%q<highline>, ["~> 1.4.0"])
88
+ s.add_dependency(%q<capistrano>, ["~> 2.5.5"])
89
+ s.add_dependency(%q<sprinkle>, ["~> 0.3.1"])
90
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
91
+ s.add_dependency(%q<yard>, [">= 0"])
92
+ end
93
+ end
94
+
@@ -0,0 +1,25 @@
1
+ require 'food_court/packages/base'
2
+ require 'food_court/packages/build_essential'
3
+ require 'food_court/packages/ruby'
4
+ require 'food_court/packages/rubygems'
5
+ require 'food_court/packages/chef_solo'
6
+
7
+ policy :chef_solo, :roles => :bootstrap do
8
+ requires :chef_solo
9
+ end
10
+
11
+ deployment do
12
+ delivery :capistrano do
13
+ begin
14
+ recipes 'config/chef/bootstrap'
15
+ rescue LoadError
16
+ puts 'Please provide a config/chef/bootstrap.rb file in your working directory'
17
+ end
18
+ debug = true if ENV['DEBUG'] == 'true'
19
+ end
20
+ source do
21
+ prefix '/usr/local'
22
+ archives '/usr/local/src'
23
+ builds '/usr/local/src'
24
+ end
25
+ end
@@ -0,0 +1,77 @@
1
+ require 'fileutils'
2
+ require 'sprinkle'
3
+
4
+ module FoodCourt
5
+ class Command
6
+ attr_reader :current_path
7
+ TEMPLATE_PATH = File.join( File.dirname(__FILE__), '/../../', 'stacks' )
8
+
9
+ def initialize(*args)
10
+ @current_path = Dir.pwd
11
+ command = args.shift
12
+ if self.respond_to? command.to_sym
13
+ self.send command, *args
14
+ else
15
+ self.help
16
+ end
17
+ end
18
+
19
+ def init(template='nginx-passenger-ree')
20
+ puts "Setting up current directory for #{template} stack"
21
+ FileUtils.mkdir_p File.join(current_path, 'config/chef')
22
+ FileUtils.mkdir_p File.join(current_path, 'config/chef/deployments')
23
+ FileUtils.cp File.join(TEMPLATE_PATH, template, 'order.rb'), File.join(current_path, 'config/chef', 'order.rb')
24
+ FileUtils.cp File.join(TEMPLATE_PATH, template, 'bootstrap.rb'), File.join(current_path, 'config/chef', 'bootstrap.rb')
25
+ FileUtils.cp_r File.join(TEMPLATE_PATH, template, 'site-cookbooks'), File.join(current_path, 'config/chef/site-cookbooks')
26
+ end
27
+
28
+ def bootstrap( bootstrap_file = nil )
29
+ # Provide your own sprinkle config or use the default one to bootstrap your slice.
30
+ bootstrap_file ||= File.join(File.dirname(__FILE__), 'bootstrap.rb')
31
+ # Sprinkle::OPTIONS[:force] = true
32
+ raise 'a bootstrap.rb file is required for bootstrapping, please run "food_court init"' unless File.exists?( 'config/chef/bootstrap.rb' )
33
+ Sprinkle::OPTIONS[:verbose] = true
34
+ # Sprinkle::OPTIONS[:test] = true
35
+ Sprinkle::Script.sprinkle( File.read( bootstrap_file ) )
36
+ end
37
+
38
+ def update( update_config = nil )
39
+ # Provide your own sprinkle config or use the default one to update_slice your slice.
40
+ update_config ||= File.join(File.dirname(__FILE__), 'update_slice.rb')
41
+ # Sprinkle::OPTIONS[:force] = true
42
+ raise 'a update_slice.rb file is required for updating the chef configuration on your slice, please run "food_court update"' unless File.exists?( 'config/chef/bootstrap.rb' )
43
+ Sprinkle::OPTIONS[:verbose] = true
44
+ # Sprinkle::OPTIONS[:test] = true
45
+ Sprinkle::Script.sprinkle( File.read( update_config ) )
46
+ end
47
+
48
+
49
+ def help
50
+ puts File.read('../../README.rdoc')
51
+ end
52
+
53
+ def create_cookbook(name, dir=current_path)
54
+ raise "Must provide a name" unless name
55
+ puts "** Creating cookbook #{name}"
56
+ sh "mkdir -p #{File.join(dir, name, "attributes")}"
57
+ sh "mkdir -p #{File.join(dir, name, "recipes")}"
58
+ sh "mkdir -p #{File.join(dir, name, "definitions")}"
59
+ sh "mkdir -p #{File.join(dir, name, "libraries")}"
60
+ sh "mkdir -p #{File.join(dir, name, "files", "default")}"
61
+ sh "mkdir -p #{File.join(dir, name, "stacks", "default")}"
62
+ unless File.exists?(File.join(dir, name, "recipes", "default.rb"))
63
+ open(File.join(dir, name, "recipes", "default.rb"), "w") do |file|
64
+ file.puts <<-EOH
65
+ #
66
+ # Cookbook Name:: #{name}
67
+ # Recipe:: default
68
+ #
69
+ # Copyright #{Time.now.year}, MY_COMPANY
70
+ #
71
+ EOH
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,52 @@
1
+ require 'fileutils'
2
+ require 'json'
3
+
4
+ module FoodCourt
5
+ class Packager
6
+ attr_reader :config, :current_path
7
+
8
+ def initialize(path=nil)
9
+ @current_path = path || Dir.pwd
10
+ end
11
+
12
+ def compile()
13
+ time = Time.now
14
+
15
+ deployment_dir = File.join(current_path, 'config/chef/deployments', time.strftime('%Y-%m-%d-%h-%M-%S'))
16
+ FileUtils.mkdir_p deployment_dir, :verbose => true
17
+
18
+ dna = config[:dna]
19
+ File.open(deployment_dir + "/dna.json", "w"){ |f| f.write(dna.to_json) }
20
+
21
+ File.open(deployment_dir + "/solo.rb", "w") do |file|
22
+ file.write <<-EOH
23
+ file_cache_path '#{config[:file_cache_path]}'
24
+ cookbook_path ['#{cookbook_paths.join("', '")}']
25
+ log_level :#{config[:log_level] || 'info'}
26
+ EOH
27
+ end
28
+ FileUtils.cp_r File.join(current_path, 'config/chef/site-cookbooks'), File.join(deployment_dir, 'site-cookbooks')
29
+ `cd #{deployment_dir} && tar czvf site-cookbooks.tar.gz site-cookbooks`
30
+ return deployment_dir
31
+ end
32
+
33
+ def cookbook_remote_locations
34
+ config[:cookbooks].map{ |book, path| path }
35
+ end
36
+
37
+ def cookbook_paths
38
+ cache_path = config[:file_cache_path]
39
+ books = []
40
+ config[:cookbooks].each{ |book, path| books << "#{cache_path}/#{book}"}
41
+ books << "#{cache_path}/site-cookbooks"
42
+ books
43
+ end
44
+
45
+ def configure()
46
+ order_path = File.join(current_path, 'config/chef', 'order.rb')
47
+ raise "no order.rb found in path [#{order_path}]" unless File.exists?(order_path)
48
+ config_file = File.read(order_path)
49
+ @config ||= eval "#{config_file}"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,7 @@
1
+ def create_or_replace_file(file_name, lines)
2
+ result = ["rm -rf #{file_name}"]
3
+ lines.each do |line|
4
+ result << %(echo '#{line}' >> #{file_name})
5
+ end
6
+ result.join(' && ')
7
+ end
@@ -0,0 +1,6 @@
1
+ package :build_essential do
2
+ description 'Build tools'
3
+ apt 'build-essential' do
4
+ pre :install, 'apt-get update'
5
+ end
6
+ end
@@ -0,0 +1,24 @@
1
+ package :chef_solo do
2
+ gem 'chef'
3
+ requires :rubygems
4
+ requires :ohai
5
+ requires :rsync
6
+ requires :wget
7
+ requires :ssl_cert
8
+ end
9
+
10
+ package :wget do
11
+ apt "wget"
12
+ end
13
+
14
+ package :ssl_cert do
15
+ apt "ssl-cert"
16
+ end
17
+
18
+ package :ohai do
19
+ gem :ohai
20
+ end
21
+
22
+ package :rsync do
23
+ apt 'rsync'
24
+ end
@@ -0,0 +1,9 @@
1
+ package :ruby do
2
+ apt "ruby ruby1.8-dev libopenssl-ruby1.8 rdoc ri irb"
3
+ requires :zlib_dev
4
+ requires :libssl_dev
5
+ requires :libreadline_dev
6
+ end
7
+ package(:zlib_dev) { apt "zlib1g-dev" }
8
+ package(:libssl_dev) { apt "libssl-dev" }
9
+ package(:libreadline_dev) { apt "libreadline5-dev" }
@@ -0,0 +1,14 @@
1
+ package :rubygems do
2
+ description 'Ruby Gems'
3
+ version '1.3.7'
4
+ source "http://rubyforge.org/frs/download.php/70696/rubygems-1.3.7.tgz" do
5
+ pre :install, 'echo "gem: --no-rdoc --no-ri" >> /etc/gemrc;'
6
+ custom_install 'ruby setup.rb'
7
+ post :install, "ln -nf /usr/bin/gem1.8 /usr/bin/gem"
8
+ post :install, 'gem sources -a http://gems.opscode.com'
9
+ post :install, 'gem update'
10
+ post :install, "gem update --system"
11
+ end
12
+
13
+ requires :ruby
14
+ end
@@ -0,0 +1,46 @@
1
+
2
+ packager = FoodCourt::Packager.new()
3
+ packager.configure
4
+ deploy_dir = packager.compile
5
+
6
+
7
+ package :run_chef_solo do
8
+ noop do
9
+ pre :install, 'chef-solo -c /etc/chef/solo.rb -j /etc/chef/dna.json'
10
+ end
11
+ end
12
+
13
+ package :update_dna_config do
14
+ transfer "#{deploy_dir}/dna.json", '/tmp/dna.json' do
15
+ pre :install, "mkdir -p /etc/chef"
16
+ post :install, 'mv /tmp/dna.json /etc/chef/dna.json'
17
+ end
18
+ transfer "#{deploy_dir}/solo.rb", '/tmp/solo.rb' do
19
+ pre :install, "mkdir -p /etc/chef"
20
+ post :install, 'mv /tmp/solo.rb /etc/chef/solo.rb'
21
+ end
22
+ end
23
+
24
+ package :update_cookbooks do
25
+ transfer "#{deploy_dir}/site-cookbooks.tar.gz", "/tmp/site-cookbooks.tar.gz" do
26
+ pre :install, "mkdir -p /var/chef"
27
+ # pre :install, "rm -rf #{packager.config[:file_cache_path]}/site-cookbooks"
28
+ post :install, "tar -zxvf /tmp/site-cookbooks.tar.gz -C #{packager.config[:file_cache_path]}"
29
+ end
30
+
31
+ noop do
32
+ packager.config[:cookbooks].each do |book, path|
33
+ cookbook_path = "#{packager.config[:file_cache_path]}/#{book}"
34
+ pre :install, "rm -rf #{cookbook_path}"
35
+ pre :install, "mkdir -p #{cookbook_path}"
36
+ pre :install, "wget -O #{packager.config[:file_cache_path]}/#{book}.tar.gz #{path}"
37
+ pre :install, "tar zxvf #{packager.config[:file_cache_path]}/#{book}.tar.gz --strip-components=1 -C #{cookbook_path}"
38
+ end
39
+ end
40
+ end
41
+
42
+ package :update_chef do
43
+ requires :update_dna_config
44
+ requires :update_cookbooks
45
+ requires :run_chef_solo
46
+ end
@@ -0,0 +1,35 @@
1
+ #
2
+ # You need to add
3
+ # require 'food_court/recipes'
4
+ # to your deploy.rb
5
+ #
6
+ #
7
+ make_notify_task = lambda do
8
+
9
+ namespace :food_court do
10
+
11
+ # run food_court chef-solo on the remote server
12
+ desc "setup chef-solo on the remote server"
13
+ task :bootstrap, :only => {:food_court => true } do
14
+
15
+ end
16
+
17
+ desc "deploy your food_court chef-solo cookbooks"
18
+ task :deploy, :only => {:food_court => true } do
19
+
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ require 'capistrano/version'
26
+ if Capistrano::Version::MAJOR < 2
27
+ STDERR.puts "Unable to load #{__FILE__}\nFood Court Capistrano hooks require at least version 2.0.0"
28
+ else
29
+ instance = Capistrano::Configuration.instance
30
+ if instance
31
+ instance.load &make_notify_task
32
+ else
33
+ make_notify_task.call
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ require 'food_court/packages/update_chef'
2
+
3
+ policy :update_chef, :roles => :bootstrap do
4
+ requires :update_chef
5
+ end
6
+
7
+ deployment do
8
+ delivery :capistrano do
9
+ begin
10
+ recipes 'config/chef/bootstrap'
11
+ rescue LoadError
12
+ puts 'Please provide a config/chef/bootstrap.rb file in your working directory'
13
+ end
14
+ debug = true if ENV['DEBUG'] == 'true'
15
+ end
16
+ source do
17
+ prefix '/usr/local'
18
+ archives '/usr/local/src'
19
+ builds '/usr/local/src'
20
+ end
21
+ end
data/lib/food_court.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'food_court/command'
2
+ require 'food_court/packager'
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "FoodCourt::Command" do
4
+ before do
5
+ stub_template
6
+ end
7
+
8
+ context "#setup" do
9
+ before do
10
+ @command = FoodCourt::Command.new('setup', 'slicehost')
11
+ end
12
+
13
+ it "should create a chef directory" do
14
+ File.directory?(File.join(@path, 'config/chef')).should be_true
15
+ end
16
+
17
+ it "should create a chef/site-cookbooks directory" do
18
+ File.directory?(File.join(@path, 'config/chef/site-cookbooks')).should be_true
19
+ File.directory?(File.join(@path, 'config/chef/site-cookbooks/applications')).should be_true
20
+ File.directory?(File.join(@path, 'config/chef/site-cookbooks/applications/recipes')).should be_true
21
+ end
22
+
23
+ it "should create a chef/deployments directory" do
24
+ File.directory?(File.join(@path, 'config/chef/deployments')).should be_true
25
+ end
26
+
27
+ it "should copy over order.rb to chef/order.rb" do
28
+ order_path = File.join(@path, 'config/chef/order.rb')
29
+ File.file?(order_path).should be_true
30
+ File.read(order_path).should_not be_empty
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ application = "my_application"
2
+
3
+ {
4
+ :file_cache_path => "/var/chef",
5
+ :keep_deployments => 2,
6
+ :cookbooks => [ '' ],
7
+
8
+ :dna => {
9
+ :apps_dir => "/data/#{application}",
10
+ :applications => [
11
+ {
12
+ :name => application,
13
+ :server_name => "#{application}.com",
14
+ :server_aliases => ["www.#{application}.com"],
15
+ }
16
+ ],
17
+ :recipes => [
18
+ "mysql",
19
+ "nginx",
20
+ "passenger",
21
+ "applications"
22
+ ]
23
+ }
24
+ }
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "FoodCourt::Packager" do
4
+ before do
5
+ stub_template
6
+ end
7
+
8
+ context "#configure" do
9
+ before do
10
+ FoodCourt::Command.new('setup', 'slicehost')
11
+ @command = FoodCourt::Packager.new(@path)
12
+ @command.configure
13
+ end
14
+
15
+ it "should eval file into @config as a hash" do
16
+ @command.config.should be_a Hash
17
+ end
18
+
19
+ it "should have :dna in the config hash" do
20
+ @command.config[:dna].should be_a Hash
21
+ end
22
+ end
23
+
24
+ context "#compile" do
25
+ before do
26
+ FoodCourt::Command.new('setup', 'slicehost')
27
+ @command = FoodCourt::Packager.new(@path)
28
+ @command.configure
29
+ @command.compile
30
+ end
31
+
32
+ it "should compile dna.json" do
33
+ json = ''
34
+ Dir[File.join(@path, 'config/chef/deployments', '**', 'dna.json')].each do |file|
35
+ json = File.read(file)
36
+ end
37
+ json.should include('recipes')
38
+ end
39
+
40
+ it "should compile solo.rb" do
41
+ solo = ''
42
+ Dir[File.join(@path, 'config/chef/deployments', '**', 'solo.rb')].each do |file|
43
+ solo = File.read(file)
44
+ end
45
+ solo.should include('site-cookbooks')
46
+ end
47
+ end
48
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,46 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'food_court'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+ require 'fakefs'
7
+ require 'fakefs/spec_helpers'
8
+
9
+
10
+ Spec::Runner.configure do |config|
11
+ config.include FakeFS::SpecHelpers
12
+ end
13
+
14
+ def stub_template
15
+ @path = File.expand_path(File.dirname(__FILE__) + '/fixtures')
16
+ ENV['PATH'] = @path
17
+
18
+ @order = File.open( File.join( FoodCourt::Command::TEMPLATE_PATH, '/slicehost', 'order.rb'), 'w' ) do |f|
19
+ f.write <<-EOH
20
+ {
21
+ :file_cache_path => "/var/chef",
22
+ :cookbooks => [ '' ],
23
+
24
+ :dna => {
25
+ :apps_dir => "/data/my_app",
26
+ :applications => [
27
+ {
28
+ :name => "my_app",
29
+ :server_name => "my_app.com",
30
+ :server_aliases => ["www.my_app.com"],
31
+ }
32
+ ],
33
+ :recipes => [
34
+ "git",
35
+ "mysql",
36
+ "passenger",
37
+ "nginx",
38
+ "applications"
39
+ ]
40
+ }
41
+ }
42
+ EOH
43
+
44
+ end
45
+ @default_recipe = File.open( File.join( FoodCourt::Command::TEMPLATE_PATH, '/slicehost/site-cookbooks/applications/recipes', 'default.rb'), 'w' ) { |f| f.write 'test' }
46
+ end
@@ -0,0 +1,5 @@
1
+ # Your typical capistrano setup
2
+ # usually this is your root user
3
+ set :user, 'root'
4
+ role :bootstrap, ''
5
+ set :run_method, :run
@@ -0,0 +1,80 @@
1
+ application = "my-application.com"
2
+ user = :deploy
3
+
4
+ {
5
+ :file_cache_path => "/var/chef",
6
+ :log_level => :info,
7
+ :cookbooks => { 'cookbooks' => 'http://github.com/gvarela/food_court_cookbooks/tarball/master' },
8
+
9
+ :dna => {
10
+ :users => {
11
+ user => {
12
+ # openssl passwd -l
13
+ :password => "password-hash",
14
+ :comment => "Deploy User"
15
+ }
16
+ },
17
+
18
+ :ssh_keys => {
19
+ user => "ssh-rsa ... ==email@example.com"
20
+ },
21
+
22
+ :authorization => {
23
+ :sudo => {
24
+ :users => [ user ]
25
+ }
26
+ },
27
+
28
+ :mysql => {
29
+ :server_root_password => "root-password",
30
+ :bind_address => "127.0.0.1"
31
+ },
32
+
33
+ :ruby_enterprise => {
34
+ :version => "1.8.7-2010.01",
35
+ :install_path => "/usr/local",
36
+ :ruby_bin => "/usr/local/bin/ruby",
37
+ :gems_dir => "/usr/local/lib/ruby/gems/1.8",
38
+ :url => "http://rubyforge.org/frs/download.php/71096/ruby-enterprise-1.8.7-2010.01"
39
+ },
40
+
41
+ :passenger_enterprise => {
42
+ :version => "2.2.15",
43
+ :root_path => "/usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.15"
44
+ },
45
+
46
+ :gems => [
47
+ {:name => 'bundler'}
48
+ ],
49
+
50
+ # :pkgs => [
51
+ # {:name => 'wget'}
52
+ # ],
53
+
54
+ :apps => [
55
+ {
56
+ :name => "my-application",
57
+ :username => user,
58
+ :git_branch => "master",
59
+ :server => "my-application.local",
60
+ :pre_migration => "bundle install"
61
+ }
62
+ ],
63
+
64
+ :recipes => [
65
+ "build-essential",
66
+ "git",
67
+ "iptables",
68
+ "users",
69
+ "sudo",
70
+ # "imagemagick",
71
+ "passenger_enterprise::nginx",
72
+ "pkgs",
73
+ "gems",
74
+ "mysql::server",
75
+ "simple_rails_app"
76
+
77
+ ]
78
+ }
79
+ }
80
+
metadata ADDED
@@ -0,0 +1,188 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: food_court
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Gabe Varela
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-19 00:00:00 -06:00
18
+ default_executable: food-court
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: json
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 4
30
+ - 6
31
+ version: 1.4.6
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: activesupport
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 2
43
+ - 3
44
+ - 9
45
+ version: 2.3.9
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: highline
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 1
57
+ - 4
58
+ - 0
59
+ version: 1.4.0
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: capistrano
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 2
71
+ - 5
72
+ - 5
73
+ version: 2.5.5
74
+ type: :runtime
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: sprinkle
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 0
85
+ - 3
86
+ - 1
87
+ version: 0.3.1
88
+ type: :runtime
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
91
+ name: rspec
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 1
99
+ - 2
100
+ - 9
101
+ version: 1.2.9
102
+ type: :development
103
+ version_requirements: *id006
104
+ - !ruby/object:Gem::Dependency
105
+ name: yard
106
+ prerelease: false
107
+ requirement: &id007 !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ segments:
112
+ - 0
113
+ version: "0"
114
+ type: :development
115
+ version_requirements: *id007
116
+ description: Bootstrap and provision your ubuntu slice with ease
117
+ email: gvarela@gmail.com
118
+ executables:
119
+ - food-court
120
+ extensions: []
121
+
122
+ extra_rdoc_files:
123
+ - LICENSE
124
+ - README.rdoc
125
+ files:
126
+ - .document
127
+ - .gitignore
128
+ - .rvmrc
129
+ - LICENSE
130
+ - README.rdoc
131
+ - Rakefile
132
+ - VERSION
133
+ - bin/food-court
134
+ - food_court.gemspec
135
+ - lib/food_court.rb
136
+ - lib/food_court/bootstrap.rb
137
+ - lib/food_court/command.rb
138
+ - lib/food_court/packager.rb
139
+ - lib/food_court/packages/base.rb
140
+ - lib/food_court/packages/build_essential.rb
141
+ - lib/food_court/packages/chef_solo.rb
142
+ - lib/food_court/packages/ruby.rb
143
+ - lib/food_court/packages/rubygems.rb
144
+ - lib/food_court/packages/update_chef.rb
145
+ - lib/food_court/recipes.rb
146
+ - lib/food_court/update_slice.rb
147
+ - spec/command_spec.rb
148
+ - spec/fixtures/order.rb
149
+ - spec/packager_spec.rb
150
+ - spec/spec.opts
151
+ - spec/spec_helper.rb
152
+ - stacks/nginx-passenger-ree/bootstrap.rb
153
+ - stacks/nginx-passenger-ree/order.rb
154
+ has_rdoc: true
155
+ homepage: http://github.com/gvarela/food_court
156
+ licenses: []
157
+
158
+ post_install_message:
159
+ rdoc_options:
160
+ - --charset=UTF-8
161
+ require_paths:
162
+ - lib
163
+ required_ruby_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ segments:
168
+ - 0
169
+ version: "0"
170
+ required_rubygems_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ segments:
175
+ - 0
176
+ version: "0"
177
+ requirements: []
178
+
179
+ rubyforge_project:
180
+ rubygems_version: 1.3.6
181
+ signing_key:
182
+ specification_version: 3
183
+ summary: Bootstrap and provision your ubuntu slice with ease
184
+ test_files:
185
+ - spec/command_spec.rb
186
+ - spec/fixtures/order.rb
187
+ - spec/packager_spec.rb
188
+ - spec/spec_helper.rb