capistrano-paratrooper-chef 0.2.0 → 0.3.0
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.
- 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: []
|