yyuu-capistrano-chef-solo 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -107,14 +107,14 @@ set(:chef_solo_cookbooks) {{
107
107
  # use cookbooks in ./config/cookbooks.
108
108
  "local" => {
109
109
  :scm => :none,
110
- :cookbooks => "config/cookbooks",
110
+ :deploy_subdir => "config/cookbooks",
111
111
  },
112
112
  # use cookbooks in git repository.
113
113
  "repository" => {
114
114
  :scm => :git,
115
115
  :repository => "git://example.com/example.git",
116
116
  :revision => "master",
117
- :cookbooks => "/",
117
+ :deploy_subdir => "/",
118
118
  }
119
119
  }}
120
120
  ```
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.version = Capistrano::ChefSolo::VERSION
18
18
 
19
19
  gem.add_dependency("capistrano", ">= 2.10.0")
20
+ gem.add_dependency("capistrano-copy-subdir", ">= 0.1.0")
20
21
  gem.add_dependency("capistrano-rbenv", ">= 1.0.0")
21
22
  gem.add_development_dependency("net-scp", "~> 1.0.4")
22
23
  gem.add_development_dependency("net-ssh", "~> 2.2.2")
@@ -122,7 +122,7 @@ module Capistrano
122
122
 
123
123
  # FIXME:
124
124
  # Some variables (such like :default_environment set by capistrano-rbenv) may be
125
- # initialized without bootstrap settings during `on :start`.
125
+ # initialized without bootstrap settings during `on :load`.
126
126
  # Is there any way to avoid this without setting `:rbenv_setup_default_environment`
127
127
  # as false?
128
128
  set(:rbenv_setup_default_environment, false)
@@ -217,19 +217,15 @@ module Capistrano
217
217
  end
218
218
 
219
219
  def update_cookbooks(options={})
220
- tmpdir = run_locally("mktemp -d /tmp/chef-solo.XXXXXXXXXX").strip
221
- remote_tmpdir = capture("mktemp -d /tmp/chef-solo.XXXXXXXXXX").strip
222
- destination = File.join(tmpdir, "cookbooks")
223
- remote_destination = File.join(chef_solo_path, "cookbooks")
224
- filename = File.join(tmpdir, "cookbooks.tar.gz")
225
- remote_filename = File.join(remote_tmpdir, "cookbooks.tar.gz")
226
- begin
227
- bundle_cookbooks(filename, destination)
228
- run("mkdir -p #{remote_tmpdir.dump}")
229
- distribute_cookbooks(filename, remote_filename, remote_destination)
230
- ensure
231
- run("rm -rf #{remote_tmpdir.dump}") rescue nil
232
- run_locally("rm -rf #{tmpdir.dump}") rescue nil
220
+ _normalize_cookbooks(chef_solo_cookbooks).each do |name, variables|
221
+ begin
222
+ tmpdir = capture("mktemp -d /tmp/cookbooks.XXXXXXXXXX", options).strip
223
+ run("rm -rf #{tmpdir.dump} && mkdir -p #{tmpdir.dump}", options)
224
+ deploy_cookbooks(name, tmpdir, variables, options)
225
+ install_cookbooks(name, tmpdir, File.join(chef_solo_path, "cookbooks"), options)
226
+ ensure
227
+ run("rm -rf #{tmpdir.dump}", options)
228
+ end
233
229
  end
234
230
  end
235
231
 
@@ -238,84 +234,78 @@ module Capistrano
238
234
  # By default, load cookbooks from local path of "config/cookbooks".
239
235
  #
240
236
  _cset(:chef_solo_cookbooks_name) { application }
241
- _cset(:chef_solo_cookbooks_scm, :none)
237
+ _cset(:chef_solo_cookbooks_exclude, %w(.hg .git .svn))
238
+ _cset(:chef_solo_cookbooks_default_variables) {{
239
+ :scm => :none,
240
+ :deploy_via => :copy_subdir,
241
+ :deploy_subdir => nil,
242
+ :repository => ".",
243
+ :cookbooks_exclude => chef_solo_cookbooks_exclude,
244
+ :copy_cache => nil,
245
+ }}
242
246
  _cset(:chef_solo_cookbooks) {
243
- cookbooks = {}
244
- cookbooks[chef_solo_cookbooks_name] = {}
245
- cookbooks[chef_solo_cookbooks_name][:cookbooks] = fetch(:chef_solo_cookbooks_subdir, "config/cookbooks")
246
- cookbooks[chef_solo_cookbooks_name][:repository] = fetch(:chef_solo_cookbooks_repository) if exists?(:chef_solo_cookbooks_repository)
247
- cookbooks[chef_solo_cookbooks_name][:revision] = fetch(:chef_solo_cookbooks_revision) if exists?(:chef_solo_cookbooks_revision)
248
- cookbooks
247
+ variables = chef_solo_cookbooks_default_variables.dup
248
+ variables[:scm] = fetch(:chef_solo_cookbooks_scm) if exists?(:chef_solo_cookbooks_scm)
249
+ variables[:deploy_subdir] = fetch(:chef_solo_cookbooks_subdir, "config/cookbooks")
250
+ variables[:repository] = fetch(:chef_solo_cookbooks_repository) if exists?("chef_solo_cookbooks_repository")
251
+ variables[:revision] = fetch(:chef_solo_cookbooks_revision) if exists?(:chef_solo_cookbooks_revision)
252
+ { chef_solo_cookbooks_name => variables }
249
253
  }
250
254
 
251
- _cset(:chef_solo_cookbooks_exclude, %w(.hg .git .svn))
255
+ _cset(:chef_solo_repository_cache) { File.expand_path("tmp/cookbooks-cache") }
252
256
  def _normalize_cookbooks(cookbooks)
253
- xs = cookbooks.map { |name, options|
254
- options[:scm] ||= chef_solo_cookbooks_scm
255
- options[:cookbooks_exclude] ||= chef_solo_cookbooks_exclude
256
- [name, options]
257
+ xs = cookbooks.map { |name, variables|
258
+ variables = chef_solo_cookbooks_default_variables.merge(variables)
259
+ variables[:application] ||= name
260
+ # use :cookbooks as :deploy_subdir for backward compatibility with prior than 0.1.2
261
+ variables[:deploy_subdir] ||= variables[:cookbooks]
262
+ if variables[:scm] != :none
263
+ variables[:copy_cache] ||= File.expand_path(name, chef_solo_repository_cache)
264
+ end
265
+ [name, variables]
257
266
  }
258
267
  Hash[xs]
259
268
  end
260
269
 
261
- _cset(:chef_solo_repository_cache) { File.expand_path("./tmp/cookbooks-cache") }
262
- def bundle_cookbooks(filename, destination)
263
- dirs = [ File.dirname(filename), destination ].uniq
264
- run_locally("mkdir -p #{dirs.map { |x| x.dump }.join(" ")}")
265
- cookbooks = _normalize_cookbooks(chef_solo_cookbooks)
266
- cookbooks.each do |name, options|
267
- case options[:scm].to_sym
268
- when :none
269
- fetch_cookbooks_none(name, destination, options)
270
- else
271
- fetch_cookbooks_repository(name, destination, options)
270
+ def deploy_cookbooks(name, destination, variables={}, options={})
271
+ logger.debug("retrieving cookbooks `#{name}' from #{variables[:repository]} via #{variables[:deploy_via]}.")
272
+ begin
273
+ releases_path = capture("mktemp -d /tmp/releases.XXXXXXXXXX", options).strip
274
+ release_path = File.join(releases_path, release_name)
275
+ run("rm -rf #{releases_path.dump} && mkdir -p #{releases_path.dump}", options)
276
+ c = _middle_copy(top) # create new configuration with separated @variables
277
+ c.instance_eval do
278
+ set(:deploy_to, File.dirname(releases_path))
279
+ set(:releases_path, releases_path)
280
+ set(:release_path, release_path)
281
+ set(:revision) { source.head }
282
+ set(:source) { ::Capistrano::Deploy::SCM.new(scm, self) }
283
+ set(:real_revision) { source.local.query_revision(revision) { |cmd| with_env("LC_ALL", "C") { run_locally(cmd) } } }
284
+ set(:strategy) { ::Capistrano::Deploy::Strategy.new(deploy_via, self) }
285
+ variables.each do |key, val|
286
+ set(key, val)
287
+ end
288
+ strategy.deploy!
272
289
  end
273
- end
274
- run_locally("cd #{File.dirname(destination).dump} && tar chzf #{filename.dump} #{File.basename(destination).dump}")
275
- end
276
-
277
- def _fetch_cookbook(source, destination, options)
278
- exclusions = options.fetch(:cookbooks_exclude, []).map { |e| "--exclude=#{e.dump}" }.join(" ")
279
- run_locally("rsync -lrpt #{exclusions} #{source}/ #{destination}")
280
- end
281
-
282
- def _fetch_cookbooks(source, destination, options)
283
- cookbooks = [ options.fetch(:cookbooks, "/") ].flatten.compact
284
- cookbooks.each do |cookbook|
285
- _fetch_cookbook(File.join(source, cookbook), destination, options)
290
+ run("rsync -lrpt #{(release_path + "/").dump} #{destination.dump}", options)
291
+ ensure
292
+ run("rm -rf #{releases_path.dump}", options)
286
293
  end
287
294
  end
288
295
 
289
- def fetch_cookbooks_none(name, destination, options={})
290
- _fetch_cookbooks(options.fetch(:repository, "."), destination, options)
291
- end
292
-
293
- def fetch_cookbooks_repository(name, destination, options={})
294
- configuration = Capistrano::Configuration.new
295
- # refreshing just :source, :revision and :real_revision is enough?
296
- options = {
297
- :source => lambda { Capistrano::Deploy::SCM.new(configuration[:scm], configuration) },
298
- :revision => lambda { configuration[:source].head },
299
- :real_revision => lambda {
300
- configuration[:source].local.query_revision(configuration[:revision]) { |cmd| with_env("LC_ALL", "C") { run_locally(cmd) } }
301
- },
302
- }.merge(options)
303
- variables.merge(options).each do |key, val|
304
- configuration.set(key, val)
305
- end
306
- repository_cache = File.join(chef_solo_repository_cache, name)
307
- if File.exist?(repository_cache)
308
- run_locally(configuration[:source].sync(configuration[:real_revision], repository_cache))
309
- else
310
- run_locally(configuration[:source].checkout(configuration[:real_revision], repository_cache))
296
+ def _middle_copy(object)
297
+ o = object.clone
298
+ object.instance_variables.each do |k|
299
+ v = object.instance_variable_get(k)
300
+ o.instance_variable_set(k, v ? v.clone : v)
311
301
  end
312
- _fetch_cookbooks(repository_cache, destination, options)
302
+ o
313
303
  end
314
304
 
315
- def distribute_cookbooks(filename, remote_filename, remote_destination)
316
- upload(filename, remote_filename)
317
- run("rm -rf #{remote_destination.dump}")
318
- run("cd #{File.dirname(remote_destination).dump} && tar xzf #{remote_filename.dump}")
305
+ def install_cookbooks(name, source, destination, options={})
306
+ logger.debug("installing cookbooks `#{name}' to #{destination}.")
307
+ run("mkdir -p #{source.dump} #{destination.dump}", options)
308
+ run("rsync -lrpt #{(source + "/").dump} #{destination.dump}", options)
319
309
  end
320
310
 
321
311
  _cset(:chef_solo_config) {
@@ -420,12 +410,14 @@ module Capistrano
420
410
  run_list = options.delete(:run_list)
421
411
  servers = find_servers_for_task(current_task)
422
412
  servers.each do |server|
413
+ logger.debug("updating chef-solo attributes for #{server.host}.")
423
414
  attributes = _generate_attributes(:hosts => server.host, :roles => role_names_for_host(server), :run_list => run_list)
424
415
  top.put(_json_attributes(attributes), chef_solo_attributes_file, options.merge(:hosts => server.host))
425
416
  end
426
417
  end
427
418
 
428
419
  def invoke(options={})
420
+ logger.debug("invoking chef-solo.")
429
421
  args = fetch(:chef_solo_options, [])
430
422
  args << "-c #{chef_solo_config_file.dump}"
431
423
  args << "-j #{chef_solo_attributes_file.dump}"
@@ -1,5 +1,5 @@
1
1
  module Capistrano
2
2
  module ChefSolo
3
- VERSION = "0.1.1"
3
+ VERSION = "0.1.2"
4
4
  end
5
5
  end
@@ -59,13 +59,16 @@ def check_applied_recipes!(expected)
59
59
  end
60
60
  end
61
61
 
62
- def flush_attributes!()
62
+ def reset_chef_solo!()
63
63
  set(:chef_solo_attributes, {})
64
64
  set(:chef_solo_role_attributes, {})
65
65
  set(:chef_solo_host_attributes, {})
66
66
  set(:chef_solo_run_list, [])
67
67
  set(:chef_solo_role_run_list, {})
68
68
  set(:chef_solo_host_run_list, {})
69
+ variables.each_key do |key|
70
+ reset!(key) if /^chef_solo/ =~ key
71
+ end
69
72
  end
70
73
 
71
74
  namespace(:test_default) {
@@ -78,7 +81,7 @@ namespace(:test_default) {
78
81
  after "test_default", "test_default:teardown"
79
82
 
80
83
  task(:setup) {
81
- flush_attributes!
84
+ reset_chef_solo!
82
85
  set(:chef_solo_attributes, {"aaa" => "AAA"})
83
86
  set(:chef_solo_role_attributes, {:app => {"bbb" => "BBB"}})
84
87
  set(:chef_solo_host_attributes, {"192.168.33.10" => {"ccc" => "CCC"}})
@@ -116,12 +119,11 @@ namespace(:test_with_local_cookbooks) {
116
119
  after "test_with_local_cookbooks", "test_with_local_cookbooks:teardown"
117
120
 
118
121
  task(:setup) {
119
- flush_attributes!
122
+ reset_chef_solo!
120
123
  set(:chef_solo_run_list, %w(recipe[foo] recipe[bar]))
121
124
  set(:chef_solo_cookbooks_scm, :none)
122
125
  set(:chef_solo_cookbooks_repository, File.expand_path("..", File.dirname(__FILE__)))
123
126
  set(:chef_solo_cookbooks_subdir, "config/cookbooks")
124
- reset!(:chef_solo_cookbooks)
125
127
  }
126
128
 
127
129
  task(:teardown) {
@@ -152,13 +154,12 @@ namespace(:test_with_remote_cookbooks) {
152
154
  after "test_with_remote_cookbooks", "test_with_remote_cookbooks:teardown"
153
155
 
154
156
  task(:setup) {
155
- flush_attributes!
157
+ reset_chef_solo!
156
158
  set(:chef_solo_run_list, %w(recipe[one] recipe[two]))
157
159
  set(:chef_solo_cookbooks_scm, :git)
158
160
  set(:chef_solo_cookbooks_repository, "git://github.com/yyuu/capistrano-chef-solo.git")
159
161
  set(:chef_solo_cookbooks_revision, "develop")
160
162
  set(:chef_solo_cookbooks_subdir, "test/config/cookbooks-ext")
161
- reset!(:chef_solo_cookbooks)
162
163
  }
163
164
 
164
165
  task(:teardown) {
@@ -189,7 +190,7 @@ namespace(:test_with_multiple_cookbooks) {
189
190
  after "test_with_multiple_cookbooks", "test_with_multiple_cookbooks:teardown"
190
191
 
191
192
  task(:setup) {
192
- flush_attributes!
193
+ reset_chef_solo!
193
194
  set(:chef_solo_run_list, %w(recipe[bar] recipe[baz] recipe[two] recipe[three]))
194
195
  set(:chef_solo_cookbooks) {{
195
196
  "local" => {
@@ -204,7 +205,6 @@ namespace(:test_with_multiple_cookbooks) {
204
205
  :cookbooks => "test/config/cookbooks-ext",
205
206
  },
206
207
  }}
207
- # reset!(:chef_solo_cookbooks)
208
208
  }
209
209
 
210
210
  task(:teardown) {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yyuu-capistrano-chef-solo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-26 00:00:00.000000000 Z
12
+ date: 2013-04-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: capistrano
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: 2.10.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: capistrano-copy-subdir
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.1.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.1.0
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: capistrano-rbenv
32
48
  requirement: !ruby/object:Gem::Requirement