lib/capistrano-chef-solo.rb in yyuu-capistrano-chef-solo-0.1.1 vs lib/capistrano-chef-solo.rb in yyuu-capistrano-chef-solo-0.1.2
- old
+ new
@@ -120,11 +120,11 @@
end
end
# FIXME:
# Some variables (such like :default_environment set by capistrano-rbenv) may be
- # initialized without bootstrap settings during `on :start`.
+ # initialized without bootstrap settings during `on :load`.
# Is there any way to avoid this without setting `:rbenv_setup_default_environment`
# as false?
set(:rbenv_setup_default_environment, false)
desc("Setup chef-solo.")
@@ -215,111 +215,101 @@
update_config(options)
update_attributes(options)
end
def update_cookbooks(options={})
- tmpdir = run_locally("mktemp -d /tmp/chef-solo.XXXXXXXXXX").strip
- remote_tmpdir = capture("mktemp -d /tmp/chef-solo.XXXXXXXXXX").strip
- destination = File.join(tmpdir, "cookbooks")
- remote_destination = File.join(chef_solo_path, "cookbooks")
- filename = File.join(tmpdir, "cookbooks.tar.gz")
- remote_filename = File.join(remote_tmpdir, "cookbooks.tar.gz")
- begin
- bundle_cookbooks(filename, destination)
- run("mkdir -p #{remote_tmpdir.dump}")
- distribute_cookbooks(filename, remote_filename, remote_destination)
- ensure
- run("rm -rf #{remote_tmpdir.dump}") rescue nil
- run_locally("rm -rf #{tmpdir.dump}") rescue nil
+ _normalize_cookbooks(chef_solo_cookbooks).each do |name, variables|
+ begin
+ tmpdir = capture("mktemp -d /tmp/cookbooks.XXXXXXXXXX", options).strip
+ run("rm -rf #{tmpdir.dump} && mkdir -p #{tmpdir.dump}", options)
+ deploy_cookbooks(name, tmpdir, variables, options)
+ install_cookbooks(name, tmpdir, File.join(chef_solo_path, "cookbooks"), options)
+ ensure
+ run("rm -rf #{tmpdir.dump}", options)
+ end
end
end
#
# The definition of cookbooks.
# By default, load cookbooks from local path of "config/cookbooks".
#
_cset(:chef_solo_cookbooks_name) { application }
- _cset(:chef_solo_cookbooks_scm, :none)
+ _cset(:chef_solo_cookbooks_exclude, %w(.hg .git .svn))
+ _cset(:chef_solo_cookbooks_default_variables) {{
+ :scm => :none,
+ :deploy_via => :copy_subdir,
+ :deploy_subdir => nil,
+ :repository => ".",
+ :cookbooks_exclude => chef_solo_cookbooks_exclude,
+ :copy_cache => nil,
+ }}
_cset(:chef_solo_cookbooks) {
- cookbooks = {}
- cookbooks[chef_solo_cookbooks_name] = {}
- cookbooks[chef_solo_cookbooks_name][:cookbooks] = fetch(:chef_solo_cookbooks_subdir, "config/cookbooks")
- cookbooks[chef_solo_cookbooks_name][:repository] = fetch(:chef_solo_cookbooks_repository) if exists?(:chef_solo_cookbooks_repository)
- cookbooks[chef_solo_cookbooks_name][:revision] = fetch(:chef_solo_cookbooks_revision) if exists?(:chef_solo_cookbooks_revision)
- cookbooks
+ variables = chef_solo_cookbooks_default_variables.dup
+ variables[:scm] = fetch(:chef_solo_cookbooks_scm) if exists?(:chef_solo_cookbooks_scm)
+ variables[:deploy_subdir] = fetch(:chef_solo_cookbooks_subdir, "config/cookbooks")
+ variables[:repository] = fetch(:chef_solo_cookbooks_repository) if exists?("chef_solo_cookbooks_repository")
+ variables[:revision] = fetch(:chef_solo_cookbooks_revision) if exists?(:chef_solo_cookbooks_revision)
+ { chef_solo_cookbooks_name => variables }
}
- _cset(:chef_solo_cookbooks_exclude, %w(.hg .git .svn))
+ _cset(:chef_solo_repository_cache) { File.expand_path("tmp/cookbooks-cache") }
def _normalize_cookbooks(cookbooks)
- xs = cookbooks.map { |name, options|
- options[:scm] ||= chef_solo_cookbooks_scm
- options[:cookbooks_exclude] ||= chef_solo_cookbooks_exclude
- [name, options]
+ xs = cookbooks.map { |name, variables|
+ variables = chef_solo_cookbooks_default_variables.merge(variables)
+ variables[:application] ||= name
+ # use :cookbooks as :deploy_subdir for backward compatibility with prior than 0.1.2
+ variables[:deploy_subdir] ||= variables[:cookbooks]
+ if variables[:scm] != :none
+ variables[:copy_cache] ||= File.expand_path(name, chef_solo_repository_cache)
+ end
+ [name, variables]
}
Hash[xs]
end
- _cset(:chef_solo_repository_cache) { File.expand_path("./tmp/cookbooks-cache") }
- def bundle_cookbooks(filename, destination)
- dirs = [ File.dirname(filename), destination ].uniq
- run_locally("mkdir -p #{dirs.map { |x| x.dump }.join(" ")}")
- cookbooks = _normalize_cookbooks(chef_solo_cookbooks)
- cookbooks.each do |name, options|
- case options[:scm].to_sym
- when :none
- fetch_cookbooks_none(name, destination, options)
- else
- fetch_cookbooks_repository(name, destination, options)
+ def deploy_cookbooks(name, destination, variables={}, options={})
+ logger.debug("retrieving cookbooks `#{name}' from #{variables[:repository]} via #{variables[:deploy_via]}.")
+ begin
+ releases_path = capture("mktemp -d /tmp/releases.XXXXXXXXXX", options).strip
+ release_path = File.join(releases_path, release_name)
+ run("rm -rf #{releases_path.dump} && mkdir -p #{releases_path.dump}", options)
+ c = _middle_copy(top) # create new configuration with separated @variables
+ c.instance_eval do
+ set(:deploy_to, File.dirname(releases_path))
+ set(:releases_path, releases_path)
+ set(:release_path, release_path)
+ set(:revision) { source.head }
+ set(:source) { ::Capistrano::Deploy::SCM.new(scm, self) }
+ set(:real_revision) { source.local.query_revision(revision) { |cmd| with_env("LC_ALL", "C") { run_locally(cmd) } } }
+ set(:strategy) { ::Capistrano::Deploy::Strategy.new(deploy_via, self) }
+ variables.each do |key, val|
+ set(key, val)
+ end
+ strategy.deploy!
end
+ run("rsync -lrpt #{(release_path + "/").dump} #{destination.dump}", options)
+ ensure
+ run("rm -rf #{releases_path.dump}", options)
end
- run_locally("cd #{File.dirname(destination).dump} && tar chzf #{filename.dump} #{File.basename(destination).dump}")
end
- def _fetch_cookbook(source, destination, options)
- exclusions = options.fetch(:cookbooks_exclude, []).map { |e| "--exclude=#{e.dump}" }.join(" ")
- run_locally("rsync -lrpt #{exclusions} #{source}/ #{destination}")
- end
-
- def _fetch_cookbooks(source, destination, options)
- cookbooks = [ options.fetch(:cookbooks, "/") ].flatten.compact
- cookbooks.each do |cookbook|
- _fetch_cookbook(File.join(source, cookbook), destination, options)
+ def _middle_copy(object)
+ o = object.clone
+ object.instance_variables.each do |k|
+ v = object.instance_variable_get(k)
+ o.instance_variable_set(k, v ? v.clone : v)
end
+ o
end
- def fetch_cookbooks_none(name, destination, options={})
- _fetch_cookbooks(options.fetch(:repository, "."), destination, options)
+ def install_cookbooks(name, source, destination, options={})
+ logger.debug("installing cookbooks `#{name}' to #{destination}.")
+ run("mkdir -p #{source.dump} #{destination.dump}", options)
+ run("rsync -lrpt #{(source + "/").dump} #{destination.dump}", options)
end
- def fetch_cookbooks_repository(name, destination, options={})
- configuration = Capistrano::Configuration.new
- # refreshing just :source, :revision and :real_revision is enough?
- options = {
- :source => lambda { Capistrano::Deploy::SCM.new(configuration[:scm], configuration) },
- :revision => lambda { configuration[:source].head },
- :real_revision => lambda {
- configuration[:source].local.query_revision(configuration[:revision]) { |cmd| with_env("LC_ALL", "C") { run_locally(cmd) } }
- },
- }.merge(options)
- variables.merge(options).each do |key, val|
- configuration.set(key, val)
- end
- repository_cache = File.join(chef_solo_repository_cache, name)
- if File.exist?(repository_cache)
- run_locally(configuration[:source].sync(configuration[:real_revision], repository_cache))
- else
- run_locally(configuration[:source].checkout(configuration[:real_revision], repository_cache))
- end
- _fetch_cookbooks(repository_cache, destination, options)
- end
-
- def distribute_cookbooks(filename, remote_filename, remote_destination)
- upload(filename, remote_filename)
- run("rm -rf #{remote_destination.dump}")
- run("cd #{File.dirname(remote_destination).dump} && tar xzf #{remote_filename.dump}")
- end
-
_cset(:chef_solo_config) {
(<<-EOS).gsub(/^\s*/, "")
file_cache_path #{File.join(chef_solo_path, "cache").dump}
cookbook_path #{File.join(chef_solo_path, "cookbooks").dump}
EOS
@@ -418,15 +408,17 @@
def update_attributes(options={})
run_list = options.delete(:run_list)
servers = find_servers_for_task(current_task)
servers.each do |server|
+ logger.debug("updating chef-solo attributes for #{server.host}.")
attributes = _generate_attributes(:hosts => server.host, :roles => role_names_for_host(server), :run_list => run_list)
top.put(_json_attributes(attributes), chef_solo_attributes_file, options.merge(:hosts => server.host))
end
end
def invoke(options={})
+ logger.debug("invoking chef-solo.")
args = fetch(:chef_solo_options, [])
args << "-c #{chef_solo_config_file.dump}"
args << "-j #{chef_solo_attributes_file.dump}"
run("cd #{chef_solo_path.dump} && #{sudo} #{bundle_cmd} exec #{chef_solo_cmd} #{args.join(" ")}", options)
end