capchef 0.0.1

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.
data/lib/capchef.rb ADDED
@@ -0,0 +1,57 @@
1
+ module Capchef
2
+ extend self
3
+
4
+ # Default to /tmp but allow change in case it is noexec
5
+ def tmpdir
6
+ @tmpdir ||= '/tmp'
7
+ end
8
+
9
+ def tmpdir=(tmpdir)
10
+ @tmpdir = tmpdir
11
+ end
12
+
13
+ def path
14
+ @path ||= '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin'
15
+ end
16
+
17
+ def path=(path)
18
+ @path = path
19
+ end
20
+
21
+ def prepend_path(dir)
22
+ @path = "#{dir}:#{path}"
23
+ end
24
+
25
+ # Runs +command+ as root invoking the command with su -c
26
+ # and handling the root password prompt.
27
+ #
28
+ # surun "/etc/init.d/apache reload"
29
+ # # Executes
30
+ # # su - -c '/etc/init.d/apache reload'
31
+ #
32
+ def surun(cap, command, options={})
33
+ @root_password ||= cap.fetch(:root_password, Capistrano::CLI.password_prompt("root password: "))
34
+ cap.run("su -c 'cd; PATH=#{path}; #{command}'", options) do |channel, stream, output|
35
+ puts "[#{channel[:host]}] #{output}" if output
36
+ channel.send_data("#{@root_password}\n") if output && output =~ /^Password:/
37
+ yield channel, stream, output if block_given?
38
+ end
39
+ end
40
+
41
+ def surun_script(cap, script, options={})
42
+ # TBD - We can change this to use /tmp as its no longer noexec
43
+ raise "No such file: #{script}" unless File.exist?(script)
44
+ basename = File.basename(script)
45
+ tmpdir = "/tmp/#{basename}.#$$"
46
+ remote_script = "#{tmpdir}/#{basename}"
47
+ cap.run "mkdir #{tmpdir}", options
48
+ cap.upload script, remote_script, options
49
+ cap.run "chmod 0755 #{remote_script}", options
50
+ if block_given?
51
+ yield remote_script
52
+ else
53
+ surun cap, remote_script, options
54
+ end
55
+ cap.run "rm -rf #{tmpdir}", options
56
+ end
57
+ end
@@ -0,0 +1,83 @@
1
+ require 'erb'
2
+ require 'yaml'
3
+ require 'json'
4
+ require 'tempfile'
5
+ require 'zlib'
6
+ require 'archive/tar/minitar'
7
+ require 'capchef'
8
+ include Archive::Tar
9
+
10
+ Capistrano::Configuration.instance.load do
11
+ # User settings
12
+ #set :user, 'deploy' unless exists?(:user)
13
+ #set :group,'www-data' unless exists?(:group)
14
+
15
+ # Git settings for capistrano
16
+ default_run_options[:pty] = true
17
+ ssh_options[:forward_agent] = true
18
+
19
+ namespace :chef do
20
+ desc 'Install chef recipes on remote machines.'
21
+ task :default do
22
+ Capchef.prepend_path(chef_solo_path) if exists?(:chef_solo_path)
23
+
24
+ raise 'No nodes.yml' unless File.exist?('nodes.yml')
25
+ config = YAML.load(ERB.new(File.read('nodes.yml')).result(binding))
26
+
27
+ remote_tmpdir = "/tmp/chef_solo.#$$"
28
+ run "mkdir #{remote_tmpdir}"
29
+ remote_node_file = "#{remote_tmpdir}/node.json"
30
+ remote_solo_file = "#{remote_tmpdir}/solo.rb"
31
+ remote_cookbooks_tgz = "#{remote_tmpdir}/cookbooks.tgz"
32
+ remote_roles_tgz = "#{remote_tmpdir}/roles.tgz"
33
+
34
+ valid_hosts = []
35
+ find_servers_for_task(current_task).each do |s|
36
+ host_config = config[s.host]
37
+ if host_config
38
+ valid_hosts << s.host
39
+ put host_config.to_json, remote_node_file, :hosts => s.host
40
+ else
41
+ $stderr.puts "WARNING: #{s.host} not configured in nodes.yml, skipping"
42
+ end
43
+ end
44
+ if valid_hosts.empty?
45
+ $stderr.puts 'No configured hosts'
46
+ exit 1
47
+ end
48
+
49
+ solo_rb = "file_cache_path '/etc/chef'\ncookbook_path '/etc/chef/cookbooks'\nrole_path '/etc/chef/roles'\n"
50
+ put solo_rb, remote_solo_file, :hosts => valid_hosts
51
+ begin
52
+ tmp_cookbooks_tgz = Tempfile.new('cookbooks')
53
+ Dir.chdir('chef-repo') do
54
+ Minitar.pack('cookbooks', Zlib::GzipWriter.new(tmp_cookbooks_tgz))
55
+ tmp_cookbooks_tgz.close
56
+ upload tmp_cookbooks_tgz.path, remote_cookbooks_tgz, :hosts => valid_hosts
57
+
58
+ sio_roles_tgz = StringIO.new
59
+ gzip = Zlib::GzipWriter.new(sio_roles_tgz)
60
+ Minitar::Writer.open(gzip) do |tar|
61
+ #Minitar::Writer.open(sio_roles_tgz) do |tar|
62
+ Find.find('roles') do |role_file|
63
+ # TODO: This does not work (how do I specify a role in JSON?
64
+ if role_file.match(/\.yml$/)
65
+ data = YAML.load(ERB.new(File.read(role_file)).result(binding)).to_json
66
+ new_role_file = role_file.sub(/\.yml$/, '.json')
67
+ tar.add_file_simple(new_role_file, :size=>data.size, :mode=>0644, :mtime=>File.mtime(role_file)) { |f| f.write(data) }
68
+ else
69
+ Minitar.pack_file(role_file, tar)
70
+ end
71
+ end
72
+ end
73
+ gzip.close
74
+ put sio_roles_tgz.string, remote_roles_tgz, :hosts => valid_hosts
75
+ end
76
+ Capchef.surun(self, "mkdir -p /etc/chef; cd /etc/chef; rm -rf cookbooks roles; tar zxf #{remote_cookbooks_tgz}; tar zxf #{remote_roles_tgz}; chef-solo -c #{remote_solo_file} -j #{remote_node_file}", :hosts => valid_hosts)
77
+ ensure
78
+ tmp_cookbooks_tgz.unlink
79
+ run "rm -rf #{remote_tmpdir}"
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,15 @@
1
+ require 'capchef'
2
+
3
+ Capistrano::Configuration.instance.load do
4
+ default_run_options[:pty] = true
5
+ ssh_options[:forward_agent] = true
6
+
7
+ namespace :utility do
8
+ desc "execute basic command line functions. ie. cap exec cmd='ps -eaf | grep redis' optional arg: HOSTS=ip1,ip2 (replace cmd with sudo for sudo commands)"
9
+ task :default do
10
+ run(ENV['cmd']) if ENV['cmd']
11
+ Capchef.surun(self, ENV['sudo']) if ENV['sudo']
12
+ end
13
+ end
14
+ end
15
+
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capchef
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Brad Pardee
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-09-03 00:00:00 -04:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: capistrano
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: minitar
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id003
49
+ description: Chef capistrano recipes so you can configure your machines without a server
50
+ email:
51
+ - bradpardee@gmail.com
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - lib/capchef.rb
60
+ - lib/capchef_recipes.rb
61
+ - lib/capchef_utility_recipes.rb
62
+ has_rdoc: true
63
+ homepage: http://github.com/ClarityServices/capchef
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.5.1
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Chef capistrano recipes
90
+ test_files: []
91
+