capchef 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+