capistrano-paratrooper-chef 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +5 -2
- data/capistrano-paratrooper-chef.gemspec +1 -1
- data/lib/capistrano-paratrooper-chef.rb +13 -243
- data/lib/capistrano-paratrooper-chef/chef.rb +295 -0
- data/lib/capistrano-paratrooper-chef/omnibus_install.rb +2 -2
- data/lib/capistrano-paratrooper-chef/resources/default/Capfile +2 -0
- data/lib/capistrano-paratrooper-chef/resources/default/Cheffile +3 -0
- data/lib/capistrano-paratrooper-chef/resources/default/Gemfile +8 -0
- data/lib/capistrano-paratrooper-chef/resources/default/deploy.rb +21 -0
- data/lib/capistrano-paratrooper-chef/resources/default/solo.json +4 -0
- data/lib/capistrano-paratrooper-chef/resources/multistage/deploy.rb +14 -0
- data/lib/capistrano-paratrooper-chef/resources/multistage/develop.rb +8 -0
- data/lib/capistrano-paratrooper-chef/version.rb +1 -1
- data/lib/chef/knife/paratrooper_init.rb +95 -0
- metadata +20 -15
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8be49d11e9096a30c6363fa3daa051b40d4bfa71
|
4
|
+
data.tar.gz: 5461510219f83df619f33eff2083ee187ed47d1f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 74d4152dc6aa3cecbc7b912989b50791c2a75014faf15c6af2da844a6bf39684df870a1ac3a49b84b39632c70fa8745bd043582d12873d5f30b49f1c6449066a
|
7
|
+
data.tar.gz: ec0dc64c7224733f945ba13546746ae3c6b14a9367f47769f0f357b0c6f79ef23539e01413d2febc7dbd1f5c373ff5f8914acbd29cd3512a5f72381557434aac
|
data/README.md
CHANGED
@@ -33,6 +33,7 @@ by default, paratrooper-chef uses following files and directories.
|
|
33
33
|
* config/cookbooks
|
34
34
|
* config/site-cookbooks
|
35
35
|
* config/roles
|
36
|
+
* config/environments
|
36
37
|
* config/data_bags
|
37
38
|
* config/data_bag_key
|
38
39
|
|
@@ -122,6 +123,7 @@ Following options are available.
|
|
122
123
|
* `:chef_cookbooks_path` - cookbooks directories list. use `["cookbooks", "site-cookbooks"]` by default.
|
123
124
|
* `:chef_nodes_path` - nodes directory. use `nodes` by default.
|
124
125
|
* `:chef_roles_path` - roles directory. use `roles` by default.
|
126
|
+
* `:chef_environments_path` - environments directory. use `environments` by default.
|
125
127
|
* `:chef_databags_path` - data bags directory. use `data_bags` by default.
|
126
128
|
* `:chef_databag_secret` - path of secret-key for data bags. use `data_bag_key` by default.
|
127
129
|
|
@@ -132,10 +134,11 @@ Following recipes work fine with paratrooper-chef.
|
|
132
134
|
* rvm-capistrano (https://github.com/wayneeseguin/rvm-capistrano)
|
133
135
|
* capistrano-rbenv (https://github.com/yyuu/capistrano-rbenv)
|
134
136
|
|
135
|
-
## Support
|
137
|
+
## Support cookbook managers
|
136
138
|
|
137
|
-
Following
|
139
|
+
Following cookbook managers work fine with paratrooper-chef.
|
138
140
|
|
141
|
+
* berkshelf (http://berkshelf.com/)
|
139
142
|
* librarian-chef (https://github.com/applicationsonline/librarian-chef)
|
140
143
|
|
141
144
|
paratrooper-chef try to fetch cookbooks using these managers.
|
@@ -13,254 +13,24 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
|
17
|
-
require
|
18
|
-
|
19
|
-
require "capistrano-paratrooper-chef/tar_writer"
|
20
|
-
require "capistrano-paratrooper-chef/version"
|
21
|
-
|
22
|
-
|
23
|
-
Capistrano::Configuration.instance.load do
|
24
|
-
namespace :paratrooper do
|
25
|
-
# directory structure of chef-kitchen
|
26
|
-
set :chef_kitchen_path, "config"
|
27
|
-
set :chef_default_solo_json_path, "solo.json"
|
28
|
-
set :chef_cookbooks_path, ["cookbooks", "site-cookbooks"]
|
29
|
-
set :chef_nodes_path, "nodes"
|
30
|
-
set :chef_roles_path, "roles"
|
31
|
-
set :chef_databags_path, "data_bags"
|
32
|
-
set :chef_databag_secret, "data_bag_key"
|
33
|
-
|
34
|
-
# remote chef settings
|
35
|
-
set :chef_solo_path, "chef-solo"
|
36
|
-
set(:chef_working_dir) {
|
37
|
-
capture("echo $HOME").strip + "/chef-solo"
|
38
|
-
}
|
39
|
-
set :chef_cache_dir, "/var/chef/cache"
|
40
|
-
|
41
|
-
# chef settings
|
42
|
-
set :chef_roles_auto_discovery, false
|
43
|
-
set :chef_verbose_logging, true
|
44
|
-
set :chef_debug, false
|
45
|
-
|
46
|
-
def sudocmd
|
47
|
-
envvars = fetch(:default_environment, {}).collect{|k, v| "#{k}=#{v}"}
|
48
|
-
|
49
|
-
begin
|
50
|
-
old_sudo = self[:sudo]
|
51
|
-
if fetch(:rvm_type, nil) == :user
|
52
|
-
self[:sudo] = "rvmsudo_secure_path=1 #{File.join(rvm_bin_path, "rvmsudo")}"
|
53
|
-
end
|
54
|
-
|
55
|
-
if envvars
|
56
|
-
cmd = "#{top.sudo} env #{envvars.join(" ")}"
|
57
|
-
else
|
58
|
-
cmd = top.sudo
|
59
|
-
end
|
60
|
-
ensure
|
61
|
-
self[:sudo] = old_sudo if old_sudo
|
62
|
-
end
|
63
|
-
|
64
|
-
cmd
|
65
|
-
end
|
66
|
-
|
67
|
-
def sudo(command, *args)
|
68
|
-
run "#{sudocmd} #{command}", *args
|
69
|
-
end
|
70
|
-
|
71
|
-
def remote_path(*path)
|
72
|
-
File.join(fetch(:chef_working_dir), *path)
|
73
|
-
end
|
74
|
-
|
75
|
-
def cookbooks_paths
|
76
|
-
fetch(:chef_cookbooks_path).collect{|path| File.join(fetch(:chef_kitchen_path), path)}
|
77
|
-
end
|
78
|
-
|
79
|
-
def roles_path
|
80
|
-
File.join(fetch(:chef_kitchen_path), fetch(:chef_roles_path))
|
81
|
-
end
|
82
|
-
|
83
|
-
def role_exists?(name)
|
84
|
-
File.exist?(File.join(roles_path, name.to_s + ".json")) ||
|
85
|
-
File.exist?(File.join(roles_path, name.to_s + ".rb"))
|
86
|
-
end
|
87
|
-
|
88
|
-
def databags_path
|
89
|
-
File.join(fetch(:chef_kitchen_path), fetch(:chef_databags_path))
|
90
|
-
end
|
91
|
-
|
92
|
-
def databag_secret_path
|
93
|
-
File.join(fetch(:chef_kitchen_path), fetch(:chef_databag_secret))
|
94
|
-
end
|
95
|
-
|
96
|
-
def nodes_path
|
97
|
-
File.join(fetch(:chef_kitchen_path), fetch(:chef_nodes_path))
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
namespace :run_list do
|
102
|
-
def solo_json_path_for(name)
|
103
|
-
path = File.join(nodes_path, name.to_s + ".json")
|
104
|
-
if File.exist?(path)
|
105
|
-
path
|
106
|
-
else
|
107
|
-
File.join(fetch(:chef_kitchen_path), fetch(:chef_default_solo_json_path))
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def discover
|
112
|
-
find_servers_for_task(current_task).each do |server|
|
113
|
-
begin
|
114
|
-
open(solo_json_path_for(server.host)) do |fd|
|
115
|
-
server.options[:chef_attributes] = JSON.load(fd)
|
116
|
-
|
117
|
-
if server.options[:chef_attributes]["run_list"].nil?
|
118
|
-
server.options[:chef_attributes]["run_list"] = []
|
119
|
-
end
|
120
|
-
end
|
121
|
-
rescue JSON::ParserError
|
122
|
-
logger.important("Could not parse JSON file: %s" % solo_json_path_for(server.host))
|
123
|
-
rescue
|
124
|
-
logger.important("Could not read JSON file: %s" % solo_json_path_for(server.host))
|
125
|
-
ensure
|
126
|
-
if server.options[:chef_attributes].nil?
|
127
|
-
server.options[:chef_attributes] = {"run_list" => []}
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
if fetch(:chef_roles_auto_discovery)
|
132
|
-
role_names_for_host(server).each do |role|
|
133
|
-
server.options[:chef_attributes]["run_list"] << "role[#{role}]" if role_exists?(role)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def discovered_attributes
|
140
|
-
find_servers_for_task(current_task).collect{|server| server.options[:chef_attributes]}.compact
|
141
|
-
end
|
142
|
-
|
143
|
-
def discovered_lists
|
144
|
-
discovered_attributes.collect{|attr| attr["run_list"]}
|
145
|
-
end
|
146
|
-
|
147
|
-
def unique?
|
148
|
-
if fetch(:chef_roles_auto_discovery)
|
149
|
-
discovered_lists.uniq.size == 1
|
150
|
-
else
|
151
|
-
true
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def ensure
|
156
|
-
if discovered_lists.all?{|run_list| run_list.empty?}
|
157
|
-
abort "You must specify at least one recipe or role"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
namespace :chef do
|
163
|
-
task :default, :except => { :no_release => true } do
|
164
|
-
run_list.discover
|
165
|
-
run_list.ensure
|
166
|
-
kitchen.ensure_cookbooks
|
167
|
-
kitchen.ensure_working_dir
|
168
|
-
kitchen.upload
|
169
|
-
chef.generate_solo_rb
|
170
|
-
chef.generate_solo_json
|
171
|
-
chef.execute
|
172
|
-
end
|
173
|
-
|
174
|
-
task :solo, :except => { :no_release => true } do
|
175
|
-
chef.default
|
176
|
-
end
|
177
|
-
|
178
|
-
def generate_solo_rb
|
179
|
-
config = <<-CONF
|
180
|
-
root = File.expand_path(File.dirname(__FILE__))
|
181
|
-
file_cache_path #{fetch(:chef_cache_dir).inspect}
|
182
|
-
cookbook_path #{kitchen.cookbooks_paths.inspect}.collect{|dir| File.join(root, dir)}
|
183
|
-
role_path File.join(root, #{kitchen.roles_path.inspect})
|
184
|
-
data_bag_path File.join(root, #{kitchen.databags_path.inspect})
|
185
|
-
verbose_logging #{fetch(:chef_verbose_logging)}
|
186
|
-
CONF
|
187
|
-
if File.exist?(kitchen.databag_secret_path)
|
188
|
-
config += <<-CONF
|
189
|
-
encrypted_data_bag_secret File.join(root, #{kitchen.databag_secret_path.inspect})
|
190
|
-
CONF
|
191
|
-
end
|
192
|
-
|
193
|
-
put config, remote_path("solo.rb"), :via => :scp
|
194
|
-
end
|
195
|
-
|
196
|
-
def generate_solo_json
|
197
|
-
find_servers_for_task(current_task).each do |server|
|
198
|
-
put server.options[:chef_attributes].to_json, remote_path("solo.json"), :hosts => server.host, :via => :scp
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
desc "Run chef-solo"
|
203
|
-
task :execute, :except => { :no_release => true } do
|
204
|
-
logger.info "Now running chef-solo"
|
205
|
-
command = "#{chef_solo_path} -c #{remote_path("solo.rb")} -j #{remote_path("solo.json")}#{' -l debug' if fetch(:chef_debug)}"
|
206
|
-
if run_list.unique?
|
207
|
-
sudo command
|
208
|
-
else
|
209
|
-
parallel do |session|
|
210
|
-
session.when "options[:chef_attributes]['run_list'].size > 0",
|
211
|
-
"#{sudocmd} #{command}"
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
namespace :kitchen do
|
218
|
-
namespace :librarian_chef do
|
219
|
-
def fetch
|
220
|
-
require 'librarian/action'
|
221
|
-
require 'librarian/chef'
|
222
|
-
|
223
|
-
if File.exist? 'Cheffile'
|
224
|
-
logger.debug("executing librarian-chef")
|
225
|
-
Librarian::Action::Resolve.new(librarian_env).run
|
226
|
-
Librarian::Action::Install.new(librarian_env).run
|
227
|
-
end
|
228
|
-
rescue LoadError
|
229
|
-
# pass
|
230
|
-
end
|
16
|
+
if defined?(Capistrano)
|
17
|
+
require 'capistrano-paratrooper-chef/chef'
|
18
|
+
end
|
231
19
|
|
232
|
-
|
233
|
-
|
234
|
-
@librarian_env.config_db.local["path"] = cookbooks_paths[0]
|
235
|
-
@librarian_env
|
236
|
-
end
|
237
|
-
end
|
20
|
+
require "pathname"
|
21
|
+
require "capistrano-paratrooper-chef/version"
|
238
22
|
|
239
|
-
def ensure_cookbooks
|
240
|
-
abort "No cookbooks found in #{fetch(:cookbooks_directory).inspect}" if kitchen.cookbooks_paths.empty?
|
241
|
-
end
|
242
23
|
|
243
|
-
|
244
|
-
|
245
|
-
|
24
|
+
module Paratrooper
|
25
|
+
module Chef
|
26
|
+
def self.resource(name, extra_path=nil)
|
27
|
+
subdirs = [extra_path, 'default'].compact
|
28
|
+
subdirs.each do |path|
|
29
|
+
resource = Pathname.new(__FILE__).dirname.join('capistrano-paratrooper-chef/resources', path, name)
|
30
|
+
return resource if File.exists?(resource)
|
246
31
|
end
|
247
32
|
|
248
|
-
|
249
|
-
task :upload, :except => { :no_release => true } do
|
250
|
-
librarian_chef.fetch
|
251
|
-
|
252
|
-
stream = StringIO.new
|
253
|
-
TarWriter.new(stream) do |writer|
|
254
|
-
kitchen_paths = [cookbooks_paths, roles_path, databags_path, databag_secret_path].flatten.compact.select{|d| File.exists?(d)}
|
255
|
-
Find.find(*kitchen_paths) do |path|
|
256
|
-
writer.add(path)
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
stream.seek(0)
|
261
|
-
put stream.read, remote_path("kitchen.tar"), :via => :scp
|
262
|
-
run "cd #{fetch(:chef_working_dir)} && tar -xf kitchen.tar"
|
263
|
-
end
|
33
|
+
raise Errno::ENOENT, name
|
264
34
|
end
|
265
35
|
end
|
266
36
|
end
|
@@ -0,0 +1,295 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright 2012 Takeshi KOMIYA
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require "find"
|
17
|
+
require "json"
|
18
|
+
require "tempfile"
|
19
|
+
require "capistrano-paratrooper-chef/tar_writer"
|
20
|
+
require "capistrano-paratrooper-chef/version"
|
21
|
+
|
22
|
+
|
23
|
+
Capistrano::Configuration.instance.load do
|
24
|
+
namespace :paratrooper do
|
25
|
+
# directory structure of chef-kitchen
|
26
|
+
set :chef_kitchen_path, "config"
|
27
|
+
set :chef_default_solo_json_path, "solo.json"
|
28
|
+
set :chef_nodes_path, "nodes"
|
29
|
+
set :chef_cookbooks_path, ["cookbooks", "site-cookbooks"]
|
30
|
+
set :chef_roles_path, "roles"
|
31
|
+
set :chef_environments_path, "environments"
|
32
|
+
set :chef_databags_path, "data_bags"
|
33
|
+
set :chef_databag_secret, "data_bag_key"
|
34
|
+
|
35
|
+
# remote chef settings
|
36
|
+
set :chef_solo_path, "chef-solo"
|
37
|
+
set(:chef_working_dir) {
|
38
|
+
capture("echo $HOME").strip + "/chef-solo"
|
39
|
+
}
|
40
|
+
set :chef_cache_dir, "/var/chef/cache"
|
41
|
+
set(:chef_use_sudo) {
|
42
|
+
capture("id -u").to_i != 0
|
43
|
+
}
|
44
|
+
|
45
|
+
# chef settings
|
46
|
+
set :chef_roles_auto_discovery, false
|
47
|
+
set :chef_verbose_logging, true
|
48
|
+
set :chef_debug, false
|
49
|
+
|
50
|
+
def sudocmd
|
51
|
+
envvars = fetch(:default_environment, {}).collect{|k, v| "#{k}=#{v}"}
|
52
|
+
|
53
|
+
begin
|
54
|
+
old_sudo = self[:sudo]
|
55
|
+
if fetch(:rvm_type, nil) == :user
|
56
|
+
self[:sudo] = "rvmsudo_secure_path=1 #{File.join(rvm_bin_path, "rvmsudo")}"
|
57
|
+
end
|
58
|
+
|
59
|
+
if fetch(:chef_use_sudo)
|
60
|
+
cmd = top.sudo
|
61
|
+
else
|
62
|
+
cmd = ""
|
63
|
+
end
|
64
|
+
|
65
|
+
if envvars
|
66
|
+
cmd += " env #{envvars.join(" ")}"
|
67
|
+
end
|
68
|
+
ensure
|
69
|
+
self[:sudo] = old_sudo if old_sudo
|
70
|
+
end
|
71
|
+
|
72
|
+
cmd
|
73
|
+
end
|
74
|
+
|
75
|
+
def sudo(command, *args)
|
76
|
+
run "#{sudocmd} #{command}", *args
|
77
|
+
end
|
78
|
+
|
79
|
+
def remote_path(*path)
|
80
|
+
File.join(fetch(:chef_working_dir), *path)
|
81
|
+
end
|
82
|
+
|
83
|
+
def cookbooks_paths
|
84
|
+
fetch(:chef_cookbooks_path).collect{|path| File.join(fetch(:chef_kitchen_path), path)}
|
85
|
+
end
|
86
|
+
|
87
|
+
def roles_path
|
88
|
+
File.join(fetch(:chef_kitchen_path), fetch(:chef_roles_path))
|
89
|
+
end
|
90
|
+
|
91
|
+
def role_exists?(name)
|
92
|
+
File.exist?(File.join(roles_path, name.to_s + ".json")) ||
|
93
|
+
File.exist?(File.join(roles_path, name.to_s + ".rb"))
|
94
|
+
end
|
95
|
+
|
96
|
+
def environments_path
|
97
|
+
File.join(fetch(:chef_kitchen_path), fetch(:chef_environments_path))
|
98
|
+
end
|
99
|
+
|
100
|
+
def databags_path
|
101
|
+
File.join(fetch(:chef_kitchen_path), fetch(:chef_databags_path))
|
102
|
+
end
|
103
|
+
|
104
|
+
def databag_secret_path
|
105
|
+
File.join(fetch(:chef_kitchen_path), fetch(:chef_databag_secret))
|
106
|
+
end
|
107
|
+
|
108
|
+
def nodes_path
|
109
|
+
File.join(fetch(:chef_kitchen_path), fetch(:chef_nodes_path))
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
namespace :run_list do
|
114
|
+
def solo_json_path_for(name)
|
115
|
+
path = File.join(nodes_path, name.to_s + ".json")
|
116
|
+
if File.exist?(path)
|
117
|
+
path
|
118
|
+
else
|
119
|
+
File.join(fetch(:chef_kitchen_path), fetch(:chef_default_solo_json_path))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def discover
|
124
|
+
find_servers_for_task(current_task).each do |server|
|
125
|
+
begin
|
126
|
+
open(solo_json_path_for(server.host)) do |fd|
|
127
|
+
server.options[:chef_attributes] = JSON.load(fd)
|
128
|
+
|
129
|
+
if server.options[:chef_attributes]["run_list"].nil?
|
130
|
+
server.options[:chef_attributes]["run_list"] = []
|
131
|
+
end
|
132
|
+
end
|
133
|
+
rescue JSON::ParserError
|
134
|
+
logger.important("Could not parse JSON file: %s" % solo_json_path_for(server.host))
|
135
|
+
rescue
|
136
|
+
logger.important("Could not read JSON file: %s" % solo_json_path_for(server.host))
|
137
|
+
ensure
|
138
|
+
if server.options[:chef_attributes].nil?
|
139
|
+
server.options[:chef_attributes] = {"run_list" => []}
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
if fetch(:chef_roles_auto_discovery)
|
144
|
+
role_names_for_host(server).each do |role|
|
145
|
+
server.options[:chef_attributes]["run_list"] << "role[#{role}]" if role_exists?(role)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def discovered_attributes
|
152
|
+
find_servers_for_task(current_task).collect{|server| server.options[:chef_attributes]}.compact
|
153
|
+
end
|
154
|
+
|
155
|
+
def discovered_lists
|
156
|
+
discovered_attributes.collect{|attr| attr["run_list"]}
|
157
|
+
end
|
158
|
+
|
159
|
+
def unique?
|
160
|
+
if fetch(:chef_roles_auto_discovery)
|
161
|
+
discovered_lists.uniq.size == 1
|
162
|
+
else
|
163
|
+
true
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def ensure
|
168
|
+
if discovered_lists.all?{|run_list| run_list.empty?}
|
169
|
+
abort "You must specify at least one recipe or role"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
namespace :chef do
|
175
|
+
task :default, :except => { :no_release => true } do
|
176
|
+
run_list.discover
|
177
|
+
run_list.ensure
|
178
|
+
kitchen.ensure_cookbooks
|
179
|
+
kitchen.ensure_working_dir
|
180
|
+
kitchen.upload
|
181
|
+
chef.generate_solo_rb
|
182
|
+
chef.generate_solo_json
|
183
|
+
chef.execute
|
184
|
+
end
|
185
|
+
|
186
|
+
task :solo, :except => { :no_release => true } do
|
187
|
+
chef.default
|
188
|
+
end
|
189
|
+
|
190
|
+
def generate_solo_rb
|
191
|
+
config = <<-CONF
|
192
|
+
root = File.expand_path(File.dirname(__FILE__))
|
193
|
+
file_cache_path #{fetch(:chef_cache_dir).inspect}
|
194
|
+
cookbook_path #{kitchen.cookbooks_paths.inspect}.collect{|dir| File.join(root, dir)}
|
195
|
+
role_path File.join(root, #{kitchen.roles_path.inspect})
|
196
|
+
environments_path File.join(root, #{kitchen.environments_path.inspect})
|
197
|
+
data_bag_path File.join(root, #{kitchen.databags_path.inspect})
|
198
|
+
verbose_logging #{fetch(:chef_verbose_logging)}
|
199
|
+
CONF
|
200
|
+
if File.exist?(kitchen.databag_secret_path)
|
201
|
+
config += <<-CONF
|
202
|
+
encrypted_data_bag_secret File.join(root, #{kitchen.databag_secret_path.inspect})
|
203
|
+
CONF
|
204
|
+
end
|
205
|
+
|
206
|
+
put config, remote_path("solo.rb"), :via => :scp
|
207
|
+
end
|
208
|
+
|
209
|
+
def generate_solo_json
|
210
|
+
find_servers_for_task(current_task).each do |server|
|
211
|
+
put server.options[:chef_attributes].to_json, remote_path("solo.json"), :hosts => server.host, :via => :scp
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
desc "Run chef-solo"
|
216
|
+
task :execute, :except => { :no_release => true } do
|
217
|
+
logger.info "Now running chef-solo"
|
218
|
+
command = "#{chef_solo_path} -c #{remote_path("solo.rb")} -j #{remote_path("solo.json")}#{' -l debug' if fetch(:chef_debug)}"
|
219
|
+
if run_list.unique?
|
220
|
+
sudo command
|
221
|
+
else
|
222
|
+
parallel do |session|
|
223
|
+
session.when "options[:chef_attributes]['run_list'].size > 0",
|
224
|
+
"#{sudocmd} #{command}"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
namespace :kitchen do
|
231
|
+
namespace :berkshelf do
|
232
|
+
def fetch
|
233
|
+
require 'berkshelf'
|
234
|
+
|
235
|
+
if File.exist? 'Berksfile'
|
236
|
+
logger.debug("executing berkshelf")
|
237
|
+
Berkshelf::Berksfile.from_file('Berksfile').install(:path => cookbooks_paths[0])
|
238
|
+
end
|
239
|
+
rescue LoadError
|
240
|
+
# pass
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
namespace :librarian_chef do
|
245
|
+
def fetch
|
246
|
+
require 'librarian/action'
|
247
|
+
require 'librarian/chef'
|
248
|
+
|
249
|
+
if File.exist? 'Cheffile'
|
250
|
+
logger.debug("executing librarian-chef")
|
251
|
+
Librarian::Action::Resolve.new(librarian_env).run
|
252
|
+
Librarian::Action::Install.new(librarian_env).run
|
253
|
+
end
|
254
|
+
rescue LoadError
|
255
|
+
# pass
|
256
|
+
end
|
257
|
+
|
258
|
+
def librarian_env
|
259
|
+
@librarian_env ||= Librarian::Chef::Environment.new
|
260
|
+
@librarian_env.config_db.local["path"] = cookbooks_paths[0]
|
261
|
+
@librarian_env
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def ensure_cookbooks
|
266
|
+
abort "No cookbooks found in #{fetch(:cookbooks_directory).inspect}" if kitchen.cookbooks_paths.empty?
|
267
|
+
abort "Multiple cookbook definitions found: Cheffile, Berksfile" if File.exist? 'Cheffile' and File.exsit? 'Berksfile'
|
268
|
+
end
|
269
|
+
|
270
|
+
def ensure_working_dir
|
271
|
+
run "rm -rf #{fetch(:chef_working_dir)} && mkdir -p #{fetch(:chef_working_dir)}"
|
272
|
+
sudo "mkdir -p #{fetch(:chef_cache_dir)}"
|
273
|
+
end
|
274
|
+
|
275
|
+
desc "Upload files in kitchen"
|
276
|
+
task :upload, :except => { :no_release => true } do
|
277
|
+
berkshelf.fetch
|
278
|
+
librarian_chef.fetch
|
279
|
+
|
280
|
+
stream = StringIO.new
|
281
|
+
TarWriter.new(stream) do |writer|
|
282
|
+
paths = [cookbooks_paths, roles_path, environments_path, databags_path, databag_secret_path]
|
283
|
+
kitchen_paths = paths.flatten.compact.select{|d| File.exists?(d)}
|
284
|
+
Find.find(*kitchen_paths) do |path|
|
285
|
+
writer.add(path)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
stream.seek(0)
|
290
|
+
put stream.read, remote_path("kitchen.tar"), :via => :scp
|
291
|
+
run "cd #{fetch(:chef_working_dir)} && tar -xf kitchen.tar"
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
@@ -23,9 +23,9 @@ Capistrano::Configuration.instance.load do
|
|
23
23
|
desc "Installs chef (by omnibus installer)"
|
24
24
|
task :install_omnibus_chef do
|
25
25
|
if capture("command -v curl || true").strip.empty?
|
26
|
-
run "wget -O - http://www.opscode.com/chef/install.sh | #{top.sudo} bash"
|
26
|
+
run "wget -O - http://www.opscode.com/chef/install.sh | #{top.sudo if fetch(:chef_use_sudo)} bash"
|
27
27
|
else
|
28
|
-
run "curl -L http://www.opscode.com/chef/install.sh | #{top.sudo} bash"
|
28
|
+
run "curl -L http://www.opscode.com/chef/install.sh | #{top.sudo if fetch(:chef_use_sudo)} bash"
|
29
29
|
end
|
30
30
|
end
|
31
31
|
after "deploy:setup", "paratrooper:chef:install_omnibus_chef"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'capistrano_colors' if $stdout.tty? and $stderr.tty?
|
2
|
+
|
3
|
+
set :application, "set your application name here"
|
4
|
+
set :repository, "set your repository location here"
|
5
|
+
|
6
|
+
role :chef, "localhost" # Put your servers here (you can put multiple servers: ex. "server1", "server2", "server3"...)
|
7
|
+
|
8
|
+
# authentication info (example)
|
9
|
+
set :user, 'vagrant'
|
10
|
+
set :password, 'vagrant'
|
11
|
+
ssh_options[:port] = "2222"
|
12
|
+
ssh_options[:keys] = ["#{ENV['HOME']}/.ssh/your_key_for_auth.pem"]
|
13
|
+
|
14
|
+
# for deploy:setup
|
15
|
+
set(:home_directory) { capture("echo $HOME").strip }
|
16
|
+
set(:deploy_to) { File.join(fetch(:home_directory), 'deploy') }
|
17
|
+
|
18
|
+
# for paratrooper:chef
|
19
|
+
require 'capistrano-paratrooper-chef'
|
20
|
+
require 'capistrano-paratrooper-chef/omnibus_install'
|
21
|
+
set :chef_roles_auto_discovery, true
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'capistrano_colors' if $stdout.tty? and $stderr.tty?
|
2
|
+
require 'capistrano/ext/multistage'
|
3
|
+
|
4
|
+
set :application, "set your application name here"
|
5
|
+
set :repository, "set your repository location here"
|
6
|
+
|
7
|
+
# for deploy:setup
|
8
|
+
set(:home_directory) { capture("echo $HOME").strip }
|
9
|
+
set(:deploy_to) { File.join(fetch(:home_directory), 'deploy') }
|
10
|
+
|
11
|
+
# for paratrooper:chef
|
12
|
+
require 'capistrano-paratrooper-chef'
|
13
|
+
require 'capistrano-paratrooper-chef/omnibus_install'
|
14
|
+
set :chef_roles_auto_discovery, true
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Put your servers here (you can put multiple servers: ex. "server1", "server2", "server3"...)
|
2
|
+
role :chef, "localhost"
|
3
|
+
|
4
|
+
# authentication info (example)
|
5
|
+
set :user, 'vagrant'
|
6
|
+
set :password, 'vagrant'
|
7
|
+
ssh_options[:port] = "2222"
|
8
|
+
ssh_options[:keys] = ["#{ENV['HOME']}/.ssh/your_key_for_auth.pem"]
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'capistrano-paratrooper-chef'
|
3
|
+
|
4
|
+
class Chef
|
5
|
+
class Knife
|
6
|
+
class ParatrooperInit < Knife
|
7
|
+
include FileUtils
|
8
|
+
|
9
|
+
deps do
|
10
|
+
require 'fileutils'
|
11
|
+
end
|
12
|
+
|
13
|
+
option :multistage,
|
14
|
+
:short => '-m',
|
15
|
+
:long => '--multistage',
|
16
|
+
:description => 'Enable multistage extenstion',
|
17
|
+
:default => false
|
18
|
+
|
19
|
+
banner "knife paratrooper init DIRECTORY"
|
20
|
+
|
21
|
+
def run
|
22
|
+
@base = @name_args.first
|
23
|
+
validate!
|
24
|
+
mkdir_p @base
|
25
|
+
create_kitchen
|
26
|
+
create_conffiles
|
27
|
+
create_ignorefiles
|
28
|
+
end
|
29
|
+
|
30
|
+
def validate!
|
31
|
+
if @base.nil?
|
32
|
+
show_usage
|
33
|
+
ui.fatal "You must specify a directory. Use '.' to initialize the current directory."
|
34
|
+
exit 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def mkdir_p(*args)
|
39
|
+
options = args.last.kind_of?(Hash) ? args.pop : {}
|
40
|
+
|
41
|
+
path = File.join(*args)
|
42
|
+
if not File.exist? path
|
43
|
+
ui.msg "creating %s/" % path
|
44
|
+
FileUtils.mkdir_p(path)
|
45
|
+
|
46
|
+
if options[:keep]
|
47
|
+
touch File.join(path, '.keep')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_kitchen
|
53
|
+
mkdir_p @base
|
54
|
+
mkdir_p @base, "config"
|
55
|
+
mkdir_p @base, "config", "deploy" if config[:multistage]
|
56
|
+
|
57
|
+
%w[nodes roles environments data_bags cookbooks site-cookbooks].each do |subdir|
|
58
|
+
mkdir_p @base, 'config', subdir, :keep => true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_conffiles
|
63
|
+
conffiles = %w[Gemfile Capfile config/deploy.rb Cheffile config/solo.json]
|
64
|
+
extra_path = nil
|
65
|
+
|
66
|
+
if config[:multistage]
|
67
|
+
conffiles.insert(3, 'config/deploy/develop.rb')
|
68
|
+
extra_path = 'multistage'
|
69
|
+
end
|
70
|
+
|
71
|
+
conffiles.each do |conffile|
|
72
|
+
path = File.join(@base, conffile)
|
73
|
+
unless File.exist?(path)
|
74
|
+
ui.msg "creating %s" % path
|
75
|
+
cp Paratrooper::Chef.resource(File.basename(conffile), extra_path), path
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_ignorefiles
|
81
|
+
%w[.gitignore .hgignore].each do |ignore|
|
82
|
+
path = File.join(@base, ignore)
|
83
|
+
unless File.exist?(path)
|
84
|
+
ui.msg "creating %s" % path
|
85
|
+
File.open(path, 'w') do |f|
|
86
|
+
f.puts("vendor/bundle/")
|
87
|
+
f.puts("config/cookbooks/")
|
88
|
+
f.puts("tmp/librarian/")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
metadata
CHANGED
@@ -1,32 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano-paratrooper-chef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Takeshi KOMIYA
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-10-28 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: capistrano
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
19
|
+
version: '2.14'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
26
|
+
version: '2.14'
|
30
27
|
description: A capistrano task to invoke chef-solo
|
31
28
|
email:
|
32
29
|
- i.tkomiya@gmail.com
|
@@ -41,32 +38,40 @@ files:
|
|
41
38
|
- Rakefile
|
42
39
|
- capistrano-paratrooper-chef.gemspec
|
43
40
|
- lib/capistrano-paratrooper-chef.rb
|
41
|
+
- lib/capistrano-paratrooper-chef/chef.rb
|
44
42
|
- lib/capistrano-paratrooper-chef/install.rb
|
45
43
|
- lib/capistrano-paratrooper-chef/omnibus_install.rb
|
44
|
+
- lib/capistrano-paratrooper-chef/resources/default/Capfile
|
45
|
+
- lib/capistrano-paratrooper-chef/resources/default/Cheffile
|
46
|
+
- lib/capistrano-paratrooper-chef/resources/default/Gemfile
|
47
|
+
- lib/capistrano-paratrooper-chef/resources/default/deploy.rb
|
48
|
+
- lib/capistrano-paratrooper-chef/resources/default/solo.json
|
49
|
+
- lib/capistrano-paratrooper-chef/resources/multistage/deploy.rb
|
50
|
+
- lib/capistrano-paratrooper-chef/resources/multistage/develop.rb
|
46
51
|
- lib/capistrano-paratrooper-chef/tar_writer.rb
|
47
52
|
- lib/capistrano-paratrooper-chef/version.rb
|
53
|
+
- lib/chef/knife/paratrooper_init.rb
|
48
54
|
homepage: https://github.com/tk0miya/capistrano-paratrooper-chef
|
49
55
|
licenses: []
|
56
|
+
metadata: {}
|
50
57
|
post_install_message:
|
51
58
|
rdoc_options: []
|
52
59
|
require_paths:
|
53
60
|
- lib
|
54
61
|
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
62
|
requirements:
|
57
|
-
- -
|
63
|
+
- - '>='
|
58
64
|
- !ruby/object:Gem::Version
|
59
65
|
version: '0'
|
60
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
67
|
requirements:
|
63
|
-
- -
|
68
|
+
- - '>='
|
64
69
|
- !ruby/object:Gem::Version
|
65
70
|
version: '0'
|
66
71
|
requirements: []
|
67
72
|
rubyforge_project:
|
68
|
-
rubygems_version:
|
73
|
+
rubygems_version: 2.0.3
|
69
74
|
signing_key:
|
70
|
-
specification_version:
|
75
|
+
specification_version: 4
|
71
76
|
summary: A capistrano task to invoke chef-solo
|
72
77
|
test_files: []
|