<NME> capistrano.rb
<BEF> require 'json'
require 'tempfile'
require 'delegate'

::Capistrano::Configuration.instance(:must_exist).load do

  namespace :roundsman do

    def run_list(*recipes)
      if recipes.any?
        set :run_list, recipes
        install_ruby if fetch(:run_roundsman_checks, true) && install_ruby?
        run_chef
      else
        Array(fetch(:run_list))
      end
    end

    def set_default(name, *args, &block)
      @_defaults ||= []
    set_default :cookbooks_directory, ["config/cookbooks"]
    set_default :stream_chef_output, true
    set_default :care_about_ruby_version, true
    set_default :chef_directory, "/tmp/chef"
    set_default :chef_version, "~> 0.10.8"
    set_default :copyfile_disable, false

    end

    def roundsman_working_dir(*path)
      ensure_roundsman_working_dir
      File.join(fetch(:roundsman_working_dir), *path)
    end

    set_default :ruby_install_script, <<-BASH
      set -e
      cd #{chef_directory}
      rm -rf ruby-build
      git clone -q git://github.com/sstephenson/ruby-build.git
      cd ruby-build
        top.stream *args
      else
        top.run *args
      end
    end

    set_default :roundsman_working_dir, "/tmp/roundsman"
    set_default :stream_roundsman_output, true
    set_default(:roundsman_user) { fetch(:user) { capture('whoami').strip } }
    set_default :debug_chef, false
    set_default :package_manager, 'apt-get'
    set_default :run_roundsman_checks, true

    desc "Lists configuration"
    task :configuration do
      @_defaults.sort_by {|sym| sym.to_s}.each do |name|
        display_name = ":#{name},".ljust(30)
        if variables[name].is_a?(Proc)

    desc "Installs ruby."
    task :install_ruby, :except => { :no_release => true } do
      put fetch(:ruby_install_script), chef_directory("install_ruby.sh"), :via => :scp
      _root "bash #{chef_directory("install_ruby.sh")}"
    end

    desc "Installs the dependencies needed for Ruby"
    end

    desc "Prepares the server for chef"
    task :install_ruby do
      install.default
    end

    desc "Runs chef"
    task :run_chef do
      chef.default
    end

    def ensure_roundsman_working_dir
      run "mkdir -p #{fetch(:roundsman_working_dir)}"
      run "mkdir -p #{fetch(:roundsman_working_dir)}/cache"
      abort if install_ruby?
    end

    def chef(*run_list)
      ensure_cookbooks_exist(run_list)
      if install_ruby?
        install_dependencies
        install_ruby
      end
      install_chef if install_chef?
      generate_config
      generate_attributes(run_list)
      copy_cookbooks
      _root "chef-solo -c #{chef_directory("solo.rb")} -j #{chef_directory("solo.json")}"
    end

    def ensure_cookbooks_exist(run_list)
      abort "You must specify at least one recipe when running roundsman.chef" if run_list.empty?
      abort "No cookbooks found in #{fetch(:cookbooks_directory)}" if cookbooks_paths.empty?
    end

    def ensure_supported_distro
          libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev
          libyaml-dev libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev
          vim wget tree)
      end
      end
    end

    def ensure_chef_directory
      unless @ensured_chef_directory
        _run "mkdir -p #{fetch(:chef_directory)}"
        _root "chown -R #{user} #{fetch(:chef_directory)}"
        @ensured_chef_directory = true
      end
    end

      end

      task :default, :except => { :no_release => true } do
        if install_ruby?
          dependencies
          ruby
        end
      end

      desc "Installs ruby."
      task :ruby, :except => { :no_release => true } do
        put fetch(:ruby_install_script), roundsman_working_dir("install_ruby.sh"), :via => :scp
        sudo "bash #{roundsman_working_dir("install_ruby.sh")}"
      end

      desc "Installs the dependencies needed for Ruby"
      task :dependencies, :except => { :no_release => true } do
        ensure_supported_distro
        sudo "#{fetch(:package_manager)} -yq update"
        sudo "#{fetch(:package_manager)} -yq install #{fetch(:ruby_dependencies).join(' ')}"
      end

      desc "Checks if the ruby version installed matches the version specified"
      task :check_ruby_version do
        abort if install_ruby?
      end

      def distribution
        @distribution ||= capture("cat /etc/issue").strip
      end

      def ensure_supported_distro
      @distribution ||= capture("cat /etc/issue").strip
    end

    def chef_directory(*path)
      ensure_chef_directory
      File.join(fetch(:chef_directory), *path)
    end

    def _root(command, *args)
      set_default :cookbooks_directory, ["config/cookbooks"]
      set_default :databags_directory, "config/data_bags"
      set_default :copyfile_disable, false
      set_default :verbose_logging, true
      set_default :filter_sensitive_settings, [ /password/, /filter_sensitive_settings/ ]

      task :default, :except => { :no_release => true } do
        ensure_cookbooks_exists
        prepare_chef
        chef_solo
      end

      desc "Generates the config and copies over the cookbooks to the server"
      task :prepare_chef, :except => { :no_release => true } do
        install if fetch(:run_roundsman_checks, true) && install_chef?
        file_cache_path File.join(root, "cache")
        cookbook_path [ #{cookbook_string} ]
      RUBY
      put solo_rb, chef_directory("solo.rb"), :via => :scp
    end

    def generate_attributes(run_list)
      attrs = remove_procs_from_hash variables.dup
      attrs[:run_list] = run_list
      put attrs.to_json, chef_directory("solo.json"), :via => :scp
    end

    # Recursively removes procs from hashes. Procs can exist because you specified them like this:
          sudo "gem uninstall -xaI chef || true"
          sudo "gem install chef -v #{fetch(:chef_version).inspect} --quiet --no-ri --no-rdoc"
          sudo "gem install ruby-shadow --quiet --no-ri --no-rdoc"
        end
      end

      desc "Runs the existing chef configuration"
      task :chef_solo, :except => { :no_release => true } do
        logger.info "Now running #{fetch(:run_list).join(', ')}"
        old_sudo = self[:sudo]
        if self[:rvm_type] == :user
          self[:sudo] = "rvmsudo_secure_path=1 #{File.join(rvm_bin_path, "rvmsudo")}"
        end

        sudo "chef-solo -c #{roundsman_working_dir("solo.rb")} -j #{roundsman_working_dir("solo.json")}#{' -l debug' if fetch(:debug_chef)}"
        self[:sudo] = old_sudo
      end

      def ensure_cookbooks_exists
        tar_file.close
        env_vars = fetch(:copyfile_disable) && RUBY_PLATFORM.downcase.include?('darwin') ? "COPYFILE_DISABLE=true" : ""
        system "#{env_vars} tar -cjf #{tar_file.path} #{cookbooks_paths.join(' ')}"
        upload tar_file.path, chef_directory("cookbooks.tar"), :via => :scp
        _run "cd #{chef_directory} && tar -xjf cookbooks.tar"
      ensure
        tar_file.unlink
      end
      def databags_path
        path = fetch(:databags_directory)
        File.exist?(path) ? path : nil
      end

      def install_chef?
        required_version = fetch(:chef_version).inspect
        output = capture("gem list -i -v #{required_version} || true").strip
        output == "false"
      end

      def generate_config
        cookbook_string = cookbooks_paths.map { |c| "File.join(root, #{c.to_s.inspect})" }.join(', ')
        solo_rb = <<-RUBY
          root = File.expand_path(File.dirname(__FILE__))
          file_cache_path File.join(root, "cache")
          cookbook_path [ #{cookbook_string} ]
          verbose_logging #{fetch(:verbose_logging)}
          data_bag_path File.join(root, #{fetch(:databags_directory).to_s.inspect})
        RUBY
        put solo_rb, roundsman_working_dir("solo.rb"), :via => :scp
      end

      def generate_attributes
        attrs = remove_procs_from_hash variables.dup
        put attrs.to_json, roundsman_working_dir("solo.json"), :via => :scp
      end

      # Recursively removes procs from hashes. Procs can exist because you specified them like this:
      #
      #     set(:root_password) { Capistrano::CLI.password_prompt("Root password: ") }
      def remove_procs_from_hash(hash)
        new_hash = {}
        hash.each do |key, value|
          next if fetch(:filter_sensitive_settings).find { |regex| regex.match(key.to_s) }
          real_value = if value.respond_to?(:call)
            begin
              value.call
            rescue ::Capistrano::CommandError => e
              logger.debug "Could not get the value of #{key}: #{e.message}"
              nil
            end
          else
            value
          end

          if real_value.is_a?(Hash)
            real_value = remove_procs_from_hash(real_value)
          end
          if real_value != nil && !real_value.class.to_s.include?("Capistrano") # skip capistrano tasks
            new_hash[key] = real_value
          end
        end
        new_hash
      end

      def copy_cookbooks
        tar_file = Tempfile.new("cookbooks.tar")
        begin
          tar_file.close
          env_vars = fetch(:copyfile_disable) && RUBY_PLATFORM.downcase.include?('darwin') ? "COPYFILE_DISABLE=true" : ""
          system "#{env_vars} tar -cjf #{tar_file.path} #{cookbooks_paths.join(' ')} #{databags_path.to_s}"
          upload tar_file.path, roundsman_working_dir("cookbooks.tar"), :via => :scp
          run "cd #{roundsman_working_dir} && tar -xjf cookbooks.tar"
        ensure
          tar_file.unlink
        end
      end

    end

  end
end

<MSG> Change chef_directory to roundsman_working_dir

<DFF> @@ -1,6 +1,5 @@
 require 'json'
 require 'tempfile'
-require 'delegate'
 
 ::Capistrano::Configuration.instance(:must_exist).load do
 
@@ -21,7 +20,7 @@ require 'delegate'
     set_default :cookbooks_directory, ["config/cookbooks"]
     set_default :stream_chef_output, true
     set_default :care_about_ruby_version, true
-    set_default :chef_directory, "/tmp/chef"
+    set_default :roundsman_working_dir, "/tmp/roundsman"
     set_default :chef_version, "~> 0.10.8"
     set_default :copyfile_disable, false
 
@@ -34,7 +33,7 @@ require 'delegate'
 
     set_default :ruby_install_script, <<-BASH
       set -e
-      cd #{chef_directory}
+      cd #{roundsman_working_dir}
       rm -rf ruby-build
       git clone -q git://github.com/sstephenson/ruby-build.git
       cd ruby-build
@@ -59,8 +58,8 @@ require 'delegate'
 
     desc "Installs ruby."
     task :install_ruby, :except => { :no_release => true } do
-      put fetch(:ruby_install_script), chef_directory("install_ruby.sh"), :via => :scp
-      _root "bash #{chef_directory("install_ruby.sh")}"
+      put fetch(:ruby_install_script), roundsman_working_dir("install_ruby.sh"), :via => :scp
+      _root "bash #{roundsman_working_dir("install_ruby.sh")}"
     end
 
     desc "Installs the dependencies needed for Ruby"
@@ -82,22 +81,33 @@ require 'delegate'
       abort if install_ruby?
     end
 
+    desc "Generates the config and copies over the cookbooks to the server"
+    task :prepare_chef, :except => { :no_release => true } do
+      install_chef if install_chef?
+      ensure_cookbooks_exists
+      generate_config
+      generate_attributes
+      copy_cookbooks
+    end
+
+    desc "Runs the existing chef configuration"
+    task :run_chef, :except => { :no_release => true } do
+      _root "chef-solo -c #{roundsman_working_dir("solo.rb")} -j #{roundsman_working_dir("solo.json")}"
+    end
+
     def chef(*run_list)
-      ensure_cookbooks_exist(run_list)
+      set :run_list, run_list
       if install_ruby?
         install_dependencies
         install_ruby
       end
-      install_chef if install_chef?
-      generate_config
-      generate_attributes(run_list)
-      copy_cookbooks
-      _root "chef-solo -c #{chef_directory("solo.rb")} -j #{chef_directory("solo.json")}"
+      prepare_chef
+      run_chef
     end
 
-    def ensure_cookbooks_exist(run_list)
+    def ensure_cookbooks_exists
       abort "You must specify at least one recipe when running roundsman.chef" if run_list.empty?
-      abort "No cookbooks found in #{fetch(:cookbooks_directory)}" if cookbooks_paths.empty?
+      abort "No cookbooks found in #{fetch(:cookbooks_directory).inspect}" if cookbooks_paths.empty?
     end
 
     def ensure_supported_distro
@@ -108,11 +118,11 @@ require 'delegate'
       end
     end
 
-    def ensure_chef_directory
-      unless @ensured_chef_directory
-        _run "mkdir -p #{fetch(:chef_directory)}"
-        _root "chown -R #{user} #{fetch(:chef_directory)}"
-        @ensured_chef_directory = true
+    def ensure_roundsman_working_dir
+      unless @ensured_roundsman_working_dir
+        _run "mkdir -p #{fetch(:roundsman_working_dir)}"
+        _root "chown -R #{user} #{fetch(:roundsman_working_dir)}"
+        @ensured_roundsman_working_dir = true
       end
     end
 
@@ -151,9 +161,9 @@ require 'delegate'
       @distribution ||= capture("cat /etc/issue").strip
     end
 
-    def chef_directory(*path)
-      ensure_chef_directory
-      File.join(fetch(:chef_directory), *path)
+    def roundsman_working_dir(*path)
+      ensure_roundsman_working_dir
+      File.join(fetch(:roundsman_working_dir), *path)
     end
 
     def _root(command, *args)
@@ -175,13 +185,13 @@ require 'delegate'
         file_cache_path File.join(root, "cache")
         cookbook_path [ #{cookbook_string} ]
       RUBY
-      put solo_rb, chef_directory("solo.rb"), :via => :scp
+      put solo_rb, roundsman_working_dir("solo.rb"), :via => :scp
     end
 
-    def generate_attributes(run_list)
+    def generate_attributes
       attrs = remove_procs_from_hash variables.dup
       attrs[:run_list] = run_list
-      put attrs.to_json, chef_directory("solo.json"), :via => :scp
+      put attrs.to_json, roundsman_working_dir("solo.json"), :via => :scp
     end
 
     # Recursively removes procs from hashes. Procs can exist because you specified them like this:
@@ -207,8 +217,8 @@ require 'delegate'
         tar_file.close
         env_vars = fetch(:copyfile_disable) && RUBY_PLATFORM.downcase.include?('darwin') ? "COPYFILE_DISABLE=true" : ""
         system "#{env_vars} tar -cjf #{tar_file.path} #{cookbooks_paths.join(' ')}"
-        upload tar_file.path, chef_directory("cookbooks.tar"), :via => :scp
-        _run "cd #{chef_directory} && tar -xjf cookbooks.tar"
+        upload tar_file.path, roundsman_working_dir("cookbooks.tar"), :via => :scp
+        _run "cd #{roundsman_working_dir} && tar -xjf cookbooks.tar"
       ensure
         tar_file.unlink
       end

Change chef_directory to roundsman_working_dir