chef_cap 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=nested
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2-p0@chef_cap
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source :rubygems
2
+
3
+ group :development do
4
+ gem "rspec-rails", "2.1"
5
+ gem 'wirble'
6
+ gem 'capistrano'
7
+ end
8
+
9
+ group :test do
10
+ gem "rspec-rails", "2.1"
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,37 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ capistrano (2.5.19)
5
+ highline
6
+ net-scp (>= 1.0.0)
7
+ net-sftp (>= 2.0.0)
8
+ net-ssh (>= 2.0.14)
9
+ net-ssh-gateway (>= 1.0.0)
10
+ diff-lcs (1.1.2)
11
+ highline (1.6.1)
12
+ net-scp (1.0.4)
13
+ net-ssh (>= 1.99.1)
14
+ net-sftp (2.0.5)
15
+ net-ssh (>= 2.0.9)
16
+ net-ssh (2.0.23)
17
+ net-ssh-gateway (1.0.1)
18
+ net-ssh (>= 1.99.1)
19
+ rspec (2.1.0)
20
+ rspec-core (~> 2.1.0)
21
+ rspec-expectations (~> 2.1.0)
22
+ rspec-mocks (~> 2.1.0)
23
+ rspec-core (2.1.0)
24
+ rspec-expectations (2.1.0)
25
+ diff-lcs (~> 1.1.2)
26
+ rspec-mocks (2.1.0)
27
+ rspec-rails (2.1.0)
28
+ rspec (~> 2.1.0)
29
+ wirble (0.1.3)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ capistrano
36
+ rspec-rails (= 2.1)
37
+ wirble
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010-11 Case Commons, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,49 @@
1
+ = Chef Cap
2
+
3
+ * http://github.com/casecommons/chef_cap/
4
+
5
+ == DESCRIPTION
6
+
7
+ capistrano + chef-solo == deployment + server automation
8
+
9
+ Using chef's JSON configuration format to drive capistrano and chef-solo so you can use both to not only deploy your application but also completely automate the configuration of your servers.
10
+
11
+ == INSTALL
12
+
13
+ Add chef_cap to your Gemfile
14
+
15
+ group :development do
16
+ gem 'chef_cap'
17
+ end
18
+
19
+ Then run:
20
+
21
+ $ bundle install
22
+
23
+ === Rails 3
24
+
25
+ $ rails generate chef_cap:install
26
+
27
+ === Rails 2
28
+
29
+ Edit your Rakefile and add:
30
+
31
+ require 'chef_cap/tasks'
32
+
33
+ Then run:
34
+
35
+ $ bundle exec rake chef_cap:install
36
+
37
+ Which will overwrite your Capfile and create a chef directory with sample files unless one already exists.
38
+
39
+ == REQUIREMENTS
40
+
41
+ * Capistrano 2.x
42
+
43
+ == LICENSE
44
+
45
+ MIT
46
+
47
+ == NOTICE
48
+
49
+ Chef and chef-solo are © 2010 Opscode (http://www.opscode.com/)
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+ require 'rake'
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ task :default => :spec
8
+
9
+ desc "Run all specs in spec directory (excluding plugin specs)"
10
+ RSpec::Core::RakeTask.new(:spec)
data/chef_cap.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "chef_cap/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "chef_cap"
7
+ s.version = ChefCap::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Case Commons, LLC"]
10
+ s.email = ["casecommons-dev@googlegroups.com"]
11
+ s.homepage = "https://github.com/Casecommons/chef_cap"
12
+ s.license = "MIT"
13
+ s.add_dependency('capistrano', '>= 2.5.5')
14
+ s.summary = %q{capistrano + chef-solo == chef_cap"}
15
+ s.description = %q{chef_cap uses chef"s JSON config format to drive both capistrano and chef-solo"}
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "from_file_key": "from_file_value"
3
+ }
@@ -0,0 +1 @@
1
+ dsa imaprivatekey
@@ -0,0 +1 @@
1
+ imapublickey
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require "chef_cap"
@@ -0,0 +1,18 @@
1
+ require 'rake'
2
+
3
+ namespace :chef_cap do
4
+ desc "Install chefcap JSON and cookbooks for the first time"
5
+ task :install => :environment do
6
+ require "fileutils"
7
+ templates_path = File.join(File.dirname(__FILE__), "..", "generators", "chef_cap", "templates", "chef")
8
+
9
+ FileUtils.cp_r File.join(templates_path, "..", "Capfile"), File.join(Rails.root, "Capfile")
10
+
11
+ if File.exist?(Rails.root + "chef/node.json") || File.directory?(Rails.root + "chef/cookbooks")
12
+ puts "Already initialized chef_cap?"
13
+ else
14
+ FileUtils.mkdir_p(Rails.root + "chef")
15
+ FileUtils.cp_r Dir.glob(templates_path, "/*"), (Rails.root + "chef")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module ChefCap
2
+ VERSION = "0.0.5"
3
+ end
data/lib/chef_cap.rb ADDED
@@ -0,0 +1,14 @@
1
+ require "chef_cap/version"
2
+
3
+ module ChefCap
4
+
5
+ class Capistrano
6
+ RECIPES_PATH = File.expand_path(File.join(File.dirname(__FILE__), "..", "recipes"))
7
+
8
+ def self.load_recipes(capistrano)
9
+ Dir[File.join(RECIPES_PATH, "*.rb")].each { |recipe| capistrano.send(:load, recipe) }
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,14 @@
1
+ module ChefCap
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def install
7
+ copy_file "Capfile", "Capfile"
8
+ directory "chef/cookbooks/gems/recipes"
9
+ copy_file "chef/node.json", "chef/node.json"
10
+ copy_file "chef/cookbooks/gems/recipes/default.rb", "chef/cookbooks/gems/recipes/default.rb"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+
3
+ # Set up gems listed in the Gemfile.
4
+ gemfile = File.expand_path('Gemfile', __FILE__)
5
+ begin
6
+ ENV['BUNDLE_GEMFILE'] = gemfile
7
+ require 'bundler'
8
+ Bundler.setup
9
+ rescue Bundler::GemNotFound => e
10
+ STDERR.puts e.message
11
+ STDERR.puts "Try running `bundle install`."
12
+ exit!
13
+ end if File.exist?(gemfile)
14
+ require "chef_cap"
15
+ load 'deploy' if respond_to?(:namespace) # cap2 differentiator
16
+ ::ChefCap::Capistrano.load_recipes(self)
17
+ Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }
18
+ load 'config/deploy'
@@ -0,0 +1,11 @@
1
+ node[:gems].each do |gem|
2
+ gem_package gem[:name] do
3
+ if gem[:version] && !gem[:version].empty?
4
+ version gem[:version]
5
+ end
6
+ if gem[:source]
7
+ source gem[:source]
8
+ end
9
+ action :install
10
+ end
11
+ end
@@ -0,0 +1,50 @@
1
+ {
2
+ "application": {
3
+ "name": "your-app-name",
4
+ "repository": "your-repo"
5
+ },
6
+ "upload": [
7
+ ],
8
+ "environments": {
9
+ "defaults": {
10
+ "user": "deploy",
11
+ "branch": "master",
12
+ "use_sudo": false,
13
+ "ssh": {
14
+ "deploy_key_file": "<%= ENV['HOME'] %>/.ssh/servers_deploy_key",
15
+ "authorized_pub_file": "<%= ENV['HOME'] %>/.ssh/your_workstations_public_key.pub",
16
+ "known_hosts": "github.com,207.97.227.239 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==",
17
+ "options": {
18
+ "keys": "<%= ENV['HOME'] %>/.ssh/your_workstations_private_key"
19
+ }
20
+ }
21
+ },
22
+ "production": {
23
+ "rails_env": "production",
24
+ "database": {
25
+ "user": "production-db-user",
26
+ "host": "production-db-host"
27
+ },
28
+ "servers": [
29
+ {
30
+ "hostname": "some.fq.dn",
31
+ "roles": ["web", "app", "db"],
32
+ "primary": ["web", "app", "db"]
33
+ }
34
+ ]
35
+ }
36
+ },
37
+ "shared": {
38
+ "gems": [
39
+ { "name": "bundler" },
40
+ { "name": "chef", "version": ">=0.9.12" }
41
+ ],
42
+ "run_list": ["gems"]
43
+ },
44
+ "roles": {
45
+ "web": {},
46
+ "app": {},
47
+ "db": {}
48
+ }
49
+ // "deploy_recipe": "yourcustomdeployrecipe",
50
+ }
@@ -0,0 +1,196 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "lib", "chef_dna_parser"))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "lib", "chef_cap_helper"))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "lib", "chef_cap_configuration"))
4
+ require File.expand_path(File.join(File.dirname(__FILE__), "lib", "chef_cap_initializer"))
5
+
6
+ class DnaConfigurationError < Exception; end
7
+
8
+ ChefCapConfiguration.configuration = self
9
+ ChefDnaParser.load_dna
10
+
11
+ before "deploy", "chef:setup"
12
+
13
+ set :application, ChefDnaParser.parsed["application"]["name"] rescue nil
14
+ set :repository, ChefDnaParser.parsed["application"]["repository"] rescue nil
15
+
16
+ ChefCapConfiguration.set_repository_settings
17
+
18
+ if ChefDnaParser.parsed["environments"]
19
+ if environment_defaults = ChefDnaParser.parsed["environments"]["defaults"]
20
+ ChefCapHelper.parse_hash(environment_defaults)
21
+ end
22
+
23
+ ChefDnaParser.parsed["environments"].each_key do |environment|
24
+ next if environment == "default"
25
+ environment_hash = ChefDnaParser.parsed["environments"][environment]
26
+
27
+ desc "Set server roles for the #{environment} environment"
28
+ task environment.to_sym do
29
+ set :environment_settings, environment_hash
30
+ set :rails_env, environment_hash["rails_env"] || environment
31
+ default_environment["RAILS_ENV"] = rails_env
32
+
33
+ ChefCapHelper.parse_hash(environment_hash)
34
+
35
+ (environment_hash["servers"] || []).each do |server|
36
+ if server["roles"] && server["hostname"]
37
+ server["roles"].each do |role|
38
+ options = {}
39
+ options[:primary] = true if server["primary"] && server["primary"].include?(role)
40
+ role role.to_sym, server["hostname"], options
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ private_key = ssh_deploy_key_file rescue false
49
+ public_key = ssh_authorized_pub_file rescue false
50
+ known_hosts = ssh_known_hosts rescue false
51
+ if private_key || public_key || known_hosts
52
+ private_key_remote_file = ".ssh/id_rsa"
53
+ if private_key
54
+ key_contents = File.read(private_key)
55
+ private_key_remote_file = ".ssh/id_dsa" if key_contents =~ /DSA/i
56
+ end
57
+
58
+
59
+ namespace :ssh do
60
+ desc "Transfer SSH keys to the remote server"
61
+ task :transfer_keys do
62
+ run "mkdir -p ~/.ssh"
63
+ if private_key
64
+ put(File.read(private_key), private_key_remote_file, :mode => "0600")
65
+ end
66
+ put(File.read(public_key), ".ssh/authorized_keys", :mode => "0600") if public_key
67
+ put(known_hosts, ".ssh/known_hosts", :mode => "0600") if known_hosts
68
+ end
69
+ end
70
+ before "chef:setup", "ssh:transfer_keys"
71
+
72
+ depend(:remote, :file, private_key_remote_file) if private_key
73
+ depend(:remote, :file, ".ssh/authorized_keys") if public_key
74
+ depend(:remote, :file, ".ssh/known_hosts") if known_hosts
75
+ end
76
+
77
+ ssh_options[:paranoid] = ssh_options_paranoid rescue nil
78
+ ssh_options[:keys] = ssh_options_keys rescue nil
79
+ ssh_options[:forward_agent] = ssh_options_forward_agent rescue nil
80
+ ssh_options[:username] = ssh_options_username rescue user rescue nil
81
+
82
+ if ChefDnaParser.parsed["upload"]
83
+ uploads_for_roles = {}
84
+ ChefDnaParser.parsed["upload"].each do |upload|
85
+ unless upload.has_key?("source") && upload.has_key?("destination") && upload.has_key?("roles")
86
+ raise DnaConfigurationError, "Invalid upload entry, should be {'source':value, 'destination':value, 'roles':[list], 'mode':value}"
87
+ end
88
+ upload["roles"].each do |role|
89
+ uploads_for_roles[role] ||= []
90
+ uploads_for_roles[role] << [upload["source"], upload["destination"], {:mode => upload["mode"] || "0644"}]
91
+ end
92
+ end
93
+
94
+ uploads_for_roles.each_pair do |role, file_uploads|
95
+ task "chef_upload_for_#{role}".to_sym, :roles => role do
96
+ file_uploads.each do |file_to_upload|
97
+ # TODO: better then mac local -> linux remote compatibility here
98
+ run "md5sum #{file_to_upload[1]} | cut -f1 -d ' '" do |channel, stream, data|
99
+ remote_md5 = data.to_s.strip
100
+ local_md5 = `md5 #{file_to_upload[0]} | cut -f 2 -d '='`.to_s.strip
101
+ if remote_md5 == local_md5
102
+ puts "#{File.basename(file_to_upload[1])} matches checksum, skipping"
103
+ else
104
+ upload file_to_upload[0], file_to_upload[1], :host => channel[:host]
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ namespace :chef do
112
+ desc "Uploads specified files to remote server"
113
+ task :upload_all do
114
+ uploads_for_roles.keys.each do |role|
115
+ send "chef_upload_for_#{role}".to_sym
116
+ end
117
+ end
118
+ end
119
+
120
+ before "chef:deploy", "chef:upload_all"
121
+ end
122
+
123
+ if ChefDnaParser.parsed["chef"] && ChefDnaParser.parsed["chef"]["root"]
124
+ set :chef_root_path, ChefDnaParser.parsed["chef"]["root"]
125
+ elsif ChefDnaParser.file_path
126
+ default_chef_path = File.expand_path(File.join(File.dirname(ChefDnaParser.file_path)))
127
+ if File.directory?(File.join(default_chef_path, "cookbooks"))
128
+ set :chef_root_path, default_chef_path
129
+ end
130
+ else
131
+ raise DnaConfigurationError, "Could not find cookbooks in JSON or as a subdirectory of where your JSON is!"
132
+ end
133
+
134
+ namespace :chef do
135
+ desc "Setup chef solo on the server(s)"
136
+ task :setup do
137
+ sudo "rvm default exec gem specification --version '>=0.9.12' chef 2>&1 | awk 'BEGIN { s = 0 } /^name:/ { s = 1; exit }; END { if(s == 0) exit 1 }' || sudo rvm default exec gem install chef --no-ri --no-rdoc && echo 'Chef Solo already on this server.'"
138
+ sudo "rvm default exec which chef-solo"
139
+ end
140
+
141
+ desc "Run chef-solo on the server(s)"
142
+ task :deploy do
143
+ put "cookbook_path '/tmp/chef-cap-#{rails_env}/cookbooks'", "/tmp/chef-cap-solo-#{rails_env}.rb", :mode => "0600"
144
+ sudo "rm -rf /tmp/chef-cap-#{rails_env}"
145
+ upload chef_root_path, "/tmp/chef-cap-#{rails_env}", :mode => "0700"
146
+
147
+
148
+ begin
149
+ env_settings = environment_settings
150
+ rescue
151
+ raise "Could not load environment_settings, usually this means you tried to run the deploy task without calling an <env> first"
152
+ end
153
+ parallel do |session|
154
+ session.else "echo 'Deploying Chef to this machine'" do |channel, stream, data|
155
+ roles_for_host = ChefCapHelper.roles_for_host(roles, channel[:host])
156
+
157
+ json_to_modify = ChefDnaParser.parsed.dup
158
+ hash_for_host = ChefCapHelper.merge_roles_for_host(json_to_modify["roles"], roles_for_host)
159
+
160
+ shared_hash = json_to_modify["shared"] || {}
161
+ shared_hash.each { |k, v| ChefCapHelper.recursive_merge(json_to_modify, k, v) }
162
+ hash_for_host.each {|k, v| ChefCapHelper.recursive_merge(json_to_modify, k, v) }
163
+
164
+ json_to_modify["environment"] ||= json_to_modify["environments"]["defaults"] || {} rescue {}
165
+ env_settings.each { |k, v| ChefCapHelper.recursive_merge(json_to_modify["environment"] || {}, k, v) }
166
+
167
+ json_to_modify["environment"]["revision"] = ChefCapHelper.set_revision if ChefCapHelper.has_revision?
168
+ json_to_modify["environment"]["servers"] = ChefCapHelper.intialize_primary_values(json_to_modify["environment"]["servers"])
169
+
170
+ should_not_deploy = no_deploy rescue false
171
+ json_to_modify["run_list"] = ChefCapHelper.rewrite_run_list_for_deploy(json_to_modify, should_not_deploy)
172
+
173
+ set "node_hash_for_#{channel[:host].gsub(/\./, "_")}", json_to_modify
174
+ put json_to_modify.to_json, "/tmp/chef-cap-#{rails_env}-#{channel[:host]}.json", :mode => "0600"
175
+ end
176
+ end
177
+
178
+ chef.run_chef_solo
179
+ end
180
+
181
+ task :run_chef_solo do
182
+ db = find_servers(:roles => [:db]).map(&:host)
183
+ app_and_web_only = find_servers(:roles => [:app, :web]).map(&:host) - db
184
+
185
+ run_chef_solo = "env PATH=$PATH:/usr/sbin rvm default exec chef-solo -c /tmp/chef-cap-solo-#{rails_env}.rb -j /tmp/chef-cap-#{rails_env}-`hostname`.json #{ENV['DEBUG'] ? '-l debug' : ''}"
186
+ sudo(run_chef_solo, :hosts => db) if db.any?
187
+ sudo(run_chef_solo, :hosts => app_and_web_only) if app_and_web_only.any?
188
+ end
189
+
190
+ desc "Remove all chef-cap files from /tmp"
191
+ task :cleanup do
192
+ sudo "rm -rf /tmp/chef-cap*"
193
+ end
194
+ end
195
+
196
+ before "chef:deploy", "chef:setup"
data/recipes/cook.rb ADDED
@@ -0,0 +1,7 @@
1
+ desc "Run chef without deploy"
2
+ task :cook do
3
+ set :no_deploy, true
4
+ chef.deploy
5
+ end
6
+
7
+ before "cook", "chef:setup"
@@ -0,0 +1,19 @@
1
+ class ChefCapConfiguration
2
+ class << self
3
+ attr_accessor :configuration
4
+
5
+ def set_repository_settings
6
+ repository_value = @configuration.send(:repository) rescue false
7
+ case repository_value
8
+ when /git/
9
+ @configuration.send(:set, :scm, :git)
10
+ @configuration.send(:set, :git_enable_submodules, 1)
11
+ @configuration.send(:default_run_options)[:pty] = true
12
+ @configuration.send(:depend, :remote, :command, "git")
13
+ when /svn/
14
+ @configuration.send(:set, :scm, :svn)
15
+ @configuration.send(:depend, :remote, :command, "svn")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,77 @@
1
+ class ChefCapHelper
2
+ class << self
3
+ def debug(message)
4
+ puts "** #{message}" if ENV["DEBUG"]
5
+ end
6
+
7
+ def parse_hash(hash, prefix = nil)
8
+ hash.each do |key, value|
9
+ if value.is_a? Hash
10
+ parse_hash(value, [prefix, key].compact.join("_"))
11
+ else
12
+ key = [prefix, key].compact.join("_").to_sym
13
+ debug("Setting #{key.inspect} => #{value.inspect}")
14
+ ChefCapConfiguration.configuration.set key, value
15
+ end
16
+ end
17
+ end
18
+
19
+ def recursive_merge(hash, key, value)
20
+ case "#{hash[key].class}_#{value.class}"
21
+ when "Array_Array"
22
+ hash[key] = hash[key] | value
23
+ when "Hash_Hash"
24
+ hash[key] = hash[key].merge(value)
25
+ else
26
+ hash[key] = value
27
+ end
28
+ hash
29
+ end
30
+
31
+ def roles_for_host(roles, current_host)
32
+ roles.select do |role_name, role|
33
+ role.servers.map(&:host).include?(current_host)
34
+ end.map(&:first).map(&:to_s)
35
+ end
36
+
37
+ def merge_roles_for_host(roles_hash, roles_for_host)
38
+ return {} if roles_hash.nil?
39
+
40
+ merged_hash_for_host = {}
41
+ roles_hash.each do |role_name, role_hash|
42
+ if roles_for_host.include?(role_name.to_s)
43
+ role_hash.each do |role_hash_key, role_hash_key_value|
44
+ merged_hash_for_host.merge(recursive_merge(merged_hash_for_host, role_hash_key, role_hash_key_value))
45
+ end
46
+ end
47
+ end
48
+ merged_hash_for_host
49
+ end
50
+
51
+ def set_revision
52
+ ENV["rev"] || ENV["tag"] || ENV["REV"] || ENV["TAG"] || ENV["revision"] || ENV["REVISION"]
53
+ end
54
+
55
+ def has_revision?
56
+ !set_revision.nil?
57
+ end
58
+
59
+ def rewrite_run_list_for_deploy(json_hash, should_not_deploy = false)
60
+ return nil if json_hash["run_list"].nil?
61
+ new_run_list = json_hash["run_list"].dup
62
+ if json_hash.has_key? "deploy_recipe"
63
+ deploy_recipe = new_run_list.delete(json_hash["deploy_recipe"])
64
+ new_run_list << deploy_recipe if deploy_recipe && !should_not_deploy
65
+ end
66
+ new_run_list
67
+ end
68
+
69
+ def intialize_primary_values(array_of_server_hashes)
70
+ array_of_server_hashes.each do |server_hash|
71
+ server_hash["primary"] ||= []
72
+ end
73
+ array_of_server_hashes
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,6 @@
1
+ class ChefCapInitializer
2
+
3
+ def self.load(configuration)
4
+
5
+ end
6
+ end
@@ -0,0 +1,36 @@
1
+ require "json"
2
+ require "erb"
3
+ require "fileutils"
4
+
5
+ class ChefDnaParser
6
+
7
+ class << self
8
+ attr_accessor :dna, :parsed, :file_path, :test_dna
9
+
10
+ def test_dna=(json)
11
+ @test_dna = json
12
+ end
13
+
14
+ def load_dna
15
+ @parsed ||= {}
16
+ @dna ||= ""
17
+ if @test_dna
18
+ @dna = ERB.new(@test_dna).result(binding)
19
+ else
20
+ @file_path = ENV["DNA"] || ENV["dna"] || default_dna_path
21
+
22
+ @dna = ERB.new(File.read(file_path)).result(binding)
23
+ end
24
+ @parsed = JSON.parse(@dna)
25
+ end
26
+
27
+ def default_dna_path
28
+ File.join(rails_root, "chef", "node.json")
29
+ end
30
+
31
+ def rails_root
32
+ FileUtils.pwd
33
+ end
34
+ end
35
+
36
+ end