lib/capistrano-chef-solo.rb in yyuu-capistrano-chef-solo-0.1.5 vs lib/capistrano-chef-solo.rb in yyuu-capistrano-chef-solo-0.1.6

- old
+ new

@@ -33,20 +33,31 @@ desc("Show chef-solo attributes. (an alias of chef_solo:attributes)") task(:attributes, :except => { :no_release => true }) { find_and_execute_task("chef_solo:attributes") } + + desc("Show chef-solo attributes for role. (an alias of chef_solo:role_attributes)") + task(:role_attributes, :except => { :no_release => true }) { + find_and_execute_task("chef_solo:role_attributes") + } + + desc("Show chef-solo attributes for host. (an alias of chef_solo:host_attributes)") + task(:host_attributes, :except => { :no_release => true }) { + find_and_execute_task("chef_solo:host_attributes") + } } namespace(:chef_solo) { _cset(:chef_solo_use_bundler, true) _cset(:chef_solo_version, "11.4.0") _cset(:chef_solo_path) { capture("echo $HOME/chef").strip } _cset(:chef_solo_cache_path) { File.join(chef_solo_path, "cache") } _cset(:chef_solo_config_path) { File.join(chef_solo_path, "config") } _cset(:chef_solo_cookbooks_path) { File.join(chef_solo_path, "cookbooks") } _cset(:chef_solo_data_bags_path) { File.join(chef_solo_path, "data_bags") } + _cset(:chef_solo_roles_path) { File.join(chef_solo_path, "roles") } _cset(:chef_solo_config_file) { File.join(chef_solo_config_path, "solo.rb") } _cset(:chef_solo_attributes_file) { File.join(chef_solo_config_path, "solo.json") } _cset(:chef_solo_bootstrap_user) { if variables.key?(:chef_solo_user) @@ -173,15 +184,17 @@ end } # Acts like `default`, but will apply specified recipes only. def run_list(*recipes) + options = { :update => true }.merge(Hash === recipes.last ? recipes.pop : {}) + update_p = options.delete(:update) connect_with_settings do setup transaction do - update - invoke(:run_list => recipes) + update(options) if update_p + invoke(options.merge(:run_list => recipes)) end end end _cset(:chef_solo_cmd, "chef-solo") @@ -193,17 +206,40 @@ end } desc("Show chef-solo attributes.") task(:attributes, :except => { :no_release => true }) { - hosts = ENV.fetch("HOST", "").split(/\s*,\s*/) - roles = ENV.fetch("ROLE", "").split(/\s*,\s*/).map { |role| role.to_sym } - roles += hosts.map { |host| role_names_for_host(ServerDefinition.new(host)) } - attributes = _generate_attributes(:hosts => hosts, :roles => roles) - STDOUT.puts(_json_attributes(attributes)) + find_and_execute_task("chef_solo:host_attributes") + find_and_execute_task("chef_solo:role_attributes") } + desc("Show chef-solo attributes for host.") + task(:host_attributes, :except => { :no_release => true }) { + if ENV.key?("HOST") + hosts = ENV.fetch("HOST", "").split(/\s*,\s*/) + else + hosts = find_servers_for_task(current_task).map { |server| server.host } + end + hosts.each do |host| + logger.debug("generating chef-solo attributes for host `#{host}'.") + STDOUT.puts(_json_attributes(_generate_host_attributes(host, :roles => role_names_for_host(ServerDefinition.new(host))))) + end + } + + desc("Show chef-solo attributes for role.") + task(:role_attributes, :except => { :no_release => true }) { + if ENV.key?("ROLE") + roles = ENV.fetch("ROLE", "").split(/\s*,\s*/).map { |role| role.to_sym } + else + roles = find_servers_for_task(current_task).map { |server| role_names_for_host(server) }.flatten.uniq + end + roles.each do |role| + logger.debug("generating chef-solo attributes for role `#{role}'.") + STDOUT.puts(_json_attributes(_generate_role_attributes(role))) + end + } + _cset(:chef_solo_gem_dependencies) {{ fetch(:chef_solo_gem, "chef") => chef_solo_version, }} _cset(:chef_solo_gemfile) { gemfile = [] @@ -224,13 +260,13 @@ version = execute("--version", :via => :capture) installed = Regexp.new(Regexp.escape(chef_solo_version)) =~ version rescue installed = false end + dirs = [ chef_solo_path, chef_solo_cache_path, chef_solo_config_path, chef_solo_roles_path ].uniq + run("mkdir -p #{dirs.map { |x| x.dump }.join(" ")}") unless installed - dirs = [ chef_solo_path, chef_solo_cache_path, chef_solo_config_path ].uniq - run("mkdir -p #{dirs.map { |x| x.dump }.join(" ")}") if chef_solo_use_bundler top.put(chef_solo_gemfile, File.join(chef_solo_path, "Gemfile")) args = fetch(:chef_solo_bundle_options, []) args << "--path=#{File.join(chef_solo_path, "bundle").dump}" args << "--quiet" @@ -421,10 +457,11 @@ _cset(:chef_solo_config) { (<<-EOS).gsub(/^\s*/, "") file_cache_path #{chef_solo_cache_path.dump} cookbook_path #{chef_solo_cookbooks_path.dump} data_bag_path #{chef_solo_data_bags_path.dump} + role_path #{chef_solo_roles_path.dump} EOS } def update_config(options={}) top.put(chef_solo_config, chef_solo_config_file, options) end @@ -467,53 +504,56 @@ :application, :deploy_to, :rails_env, :latest_release, :releases_path, :shared_path, :current_path, :release_path, ]) _cset(:chef_solo_capistrano_attributes_exclude, [:logger, /password/, :source, :strategy]) _cset(:chef_solo_attributes, {}) - _cset(:chef_solo_host_attributes, {}) - _cset(:chef_solo_role_attributes, {}) _cset(:chef_solo_run_list, []) + _cset(:chef_solo_host_attributes, {}) _cset(:chef_solo_host_run_list, {}) - _cset(:chef_solo_role_run_list, {}) - - def _generate_attributes(options={}) - hosts = [ options.delete(:hosts) ].flatten.compact.uniq + def _generate_host_attributes(host, options={}) roles = [ options.delete(:roles) ].flatten.compact.uniq # # By default, the Chef attributes will be generated by following order. # # 1. Use _non-lazy_ variables of Capistrano. # 2. Use attributes defined in `:chef_solo_attributes`. - # 3. Use attributes defined in `:chef_solo_role_attributes` for target role. - # 4. Use attributes defined in `:chef_solo_host_attributes` for target host. + # 3. Use attributes defined in `:chef_solo_host_attributes` for target host. # attributes = chef_solo_capistrano_attributes.dup _merge_attributes!(attributes, chef_solo_attributes) - roles.each do |role| - _merge_attributes!(attributes, chef_solo_role_attributes.fetch(role, {})) - end - hosts.each do |host| - _merge_attributes!(attributes, chef_solo_host_attributes.fetch(host, {})) - end + _merge_attributes!(attributes, chef_solo_host_attributes.fetch(host, {})) # - # The Chef `run_list` will be generated from `:chef_solo_role_run_list` and - # `:chef_solo_host_run_list`. + # The Chef `run_list` will be generated from `:chef_solo_run_list` and `:chef_solo_host_run_list`. # _merge_attributes!(attributes, {"run_list" => chef_solo_run_list}) - roles.each do |role| - _merge_attributes!(attributes, {"run_list" => chef_solo_role_run_list.fetch(role, [])}) - end - hosts.each do |host| - _merge_attributes!(attributes, {"run_list" => chef_solo_host_run_list.fetch(host, [])}) - end + _merge_attributes!(attributes, {"run_list" => roles.map { |role| "role[#{role}]" } }) unless roles.empty? + _merge_attributes!(attributes, {"run_list" => chef_solo_host_run_list.fetch(host, [])}) attributes end + _cset(:chef_solo_role_attributes, {}) + _cset(:chef_solo_role_run_list, {}) + def _generate_role_attributes(role, options={}) + attributes = { + "name" => role, + "chef_type" => "role", + "json_class" => "Chef::Role", + } + _merge_attributes!(attributes, {"default_attributes" => chef_solo_role_attributes.fetch(role, {})}) + _merge_attributes!(attributes, {"run_list" => chef_solo_role_run_list.fetch(role, [])}) + attributes + end + def update_attributes(options={}) + roles.each_key.each do |role| + logger.debug("updating chef-solo role attributes for #{role}.") + attributes = _generate_role_attributes(role) + top.put(_json_attributes(attributes), File.join(chef_solo_roles_path, "#{role}.json"), options) + end 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)) + logger.debug("updating chef-solo host attributes for #{server.host}.") + attributes = _generate_host_attributes(server.host, :roles => role_names_for_host(server)) top.put(_json_attributes(attributes), chef_solo_attributes_file, options.merge(:hosts => server.host)) end end def invoke(options={})