rails_pwnerer 0.6.64 → 0.6.65

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/CHANGELOG +2 -0
  2. data/LICENSE +0 -0
  3. data/Manifest +51 -49
  4. data/README +0 -0
  5. data/RUBYFORGE +0 -0
  6. data/Rakefile +7 -11
  7. data/ext/rpwn_setup_notice/extconf.rb +24 -16
  8. data/lib/{pwnage → rails_pwnerer}/app/cluster_config.rb +17 -17
  9. data/lib/{pwnage → rails_pwnerer}/app/config.rb +14 -14
  10. data/lib/{pwnage → rails_pwnerer}/app/db/mysql.rb +9 -9
  11. data/lib/{pwnage → rails_pwnerer}/app/files.rb +13 -13
  12. data/lib/{pwnage → rails_pwnerer}/app/gems.rb +3 -3
  13. data/lib/{pwnage → rails_pwnerer}/app/main.rb +4 -4
  14. data/lib/{pwnage → rails_pwnerer}/app/nginx_config.rb +7 -7
  15. data/lib/{pwnage → rails_pwnerer}/app/scripts.rb +4 -4
  16. data/lib/{pwnage → rails_pwnerer}/app/vcs/git.rb +9 -9
  17. data/lib/{pwnage → rails_pwnerer}/app/vcs/perforce.rb +11 -11
  18. data/lib/{pwnage → rails_pwnerer}/app/vcs/svn.rb +9 -9
  19. data/lib/{pwnage → rails_pwnerer}/base/atomics.rb +1 -1
  20. data/lib/{pwnage → rails_pwnerer}/base/cpus.rb +1 -1
  21. data/lib/{pwnage → rails_pwnerer}/base/dirs.rb +1 -1
  22. data/lib/{pwnage → rails_pwnerer}/base/gems.rb +2 -2
  23. data/lib/{pwnage → rails_pwnerer}/base/hostname.rb +1 -1
  24. data/lib/{pwnage → rails_pwnerer}/base/input.rb +1 -1
  25. data/lib/rails_pwnerer/base/packages.rb +272 -0
  26. data/lib/{pwnage → rails_pwnerer}/base/process.rb +1 -1
  27. data/lib/{pwnage → rails_pwnerer}/base/rails.rb +1 -1
  28. data/lib/{pwnage → rails_pwnerer}/base/startup.rb +1 -1
  29. data/lib/{pwnage → rails_pwnerer}/base.rb +1 -1
  30. data/lib/{pwnage → rails_pwnerer}/config/app.rb +1 -1
  31. data/lib/{pwnage → rails_pwnerer}/config/frontends.rb +1 -1
  32. data/lib/rails_pwnerer/config/main.rb +3 -0
  33. data/lib/{pwnage → rails_pwnerer}/config/paths.rb +1 -1
  34. data/lib/{pwnage → rails_pwnerer}/config/ports.rb +1 -1
  35. data/lib/{pwnage → rails_pwnerer}/config/repository.rb +7 -7
  36. data/lib/rails_pwnerer/ctl_executor.rb +19 -0
  37. data/lib/{pwnage → rails_pwnerer}/dev_executor.rb +2 -2
  38. data/lib/{pwnage → rails_pwnerer}/executor.rb +17 -17
  39. data/lib/{pwnage → rails_pwnerer}/scaffolds/config.rb +7 -7
  40. data/lib/{pwnage → rails_pwnerer}/scaffolds/dir_permissions.rb +4 -4
  41. data/lib/{pwnage → rails_pwnerer}/scaffolds/dirs.rb +3 -3
  42. data/lib/{pwnage → rails_pwnerer}/scaffolds/gems.rb +2 -2
  43. data/lib/{pwnage → rails_pwnerer}/scaffolds/hook_daemon.rb +2 -2
  44. data/lib/{pwnage → rails_pwnerer}/scaffolds/hook_dyndns.rb +3 -3
  45. data/lib/{pwnage → rails_pwnerer}/scaffolds/mysql_config.rb +2 -2
  46. data/lib/rails_pwnerer/scaffolds/packages.rb +118 -0
  47. data/lib/{pwnage → rails_pwnerer}/scaffolds/rubygems.rb +2 -2
  48. data/lib/{pwnage → rails_pwnerer}/scaffolds/sshd.rb +2 -2
  49. data/lib/{pwnage → rails_pwnerer}/util/kill_process_set.rb +1 -1
  50. data/lib/rails_pwnerer/util/main.rb +5 -0
  51. data/lib/rails_pwnerer.rb +52 -52
  52. data/rails_pwnerer.gemspec +17 -7
  53. data/test/base_package_test.rb +126 -0
  54. data/test/helper.rb +25 -0
  55. metadata +151 -107
  56. data/lib/pwnage/base/packages.rb +0 -159
  57. data/lib/pwnage/config/main.rb +0 -3
  58. data/lib/pwnage/ctl_executor.rb +0 -19
  59. data/lib/pwnage/scaffolds/packages.rb +0 -110
  60. data/lib/pwnage/util/main.rb +0 -5
@@ -1,11 +1,11 @@
1
1
  # checks out and updates the application from a Git repository
2
2
 
3
- class RailsPwnage::App::Git
4
- include RailsPwnage::Base
3
+ class RailsPwnerer::App::Git
4
+ include RailsPwnerer::Base
5
5
 
6
6
  # remove any files not in Git in the application dir
7
7
  def cleanup_app_dir(app_name, instance_name, target_dir, app_name_is_dir = false)
8
- Dir.chdir(app_name_is_dir ? app_name : RailsPwnage::Config[app_name, instance_name][:app_path]) do
8
+ Dir.chdir(app_name_is_dir ? app_name : RailsPwnerer::Config[app_name, instance_name][:app_path]) do
9
9
  Kernel.system "git clean -d -f -x -- #{target_dir}"
10
10
  Kernel.system "git checkout -- #{target_dir}"
11
11
  end
@@ -14,7 +14,7 @@ class RailsPwnage::App::Git
14
14
  # clean up the application directory by removing caches
15
15
  def cleanup_app_caches(app_name, instance_name, app_name_is_dir = false)
16
16
  # TODO: this is almost-duplicated in git.rb -- pull up somewhere
17
- app_path = app_name_is_dir ? app_name : RailsPwnage::Config[app_name, instance_name][:app_path]
17
+ app_path = app_name_is_dir ? app_name : RailsPwnerer::Config[app_name, instance_name][:app_path]
18
18
  return unless File.exists?(File.join(app_path, '.git'))
19
19
 
20
20
  # TODO: learn how Rails caches work and kill those too
@@ -26,7 +26,7 @@ class RailsPwnage::App::Git
26
26
 
27
27
  # reverts the config changes made by rpwn, so git fetch doesn't get confused
28
28
  def revert_config_changes(app_name, instance_name)
29
- Dir.chdir RailsPwnage::Config[app_name, instance_name][:app_path] do
29
+ Dir.chdir RailsPwnerer::Config[app_name, instance_name][:app_path] do
30
30
  ['config', 'Gemfile'].each do |dir|
31
31
  Kernel.system "git clean -d -f -x -- #{dir}"
32
32
  Kernel.system "git checkout -- #{dir}"
@@ -35,14 +35,14 @@ class RailsPwnage::App::Git
35
35
  end
36
36
 
37
37
  def git_update(app_name, instance_name)
38
- Dir.chdir RailsPwnage::Config[app_name, instance_name][:app_path] do
38
+ Dir.chdir RailsPwnerer::Config[app_name, instance_name][:app_path] do
39
39
  print "Doing Git pull, please enter your password if prompted...\n"
40
40
  Kernel.system 'git pull'
41
41
  end
42
42
  end
43
43
 
44
44
  def update(app_name, instance_name)
45
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
45
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
46
46
  return unless File.exists?(File.join(app_path, '.git'))
47
47
  # TODO: maybe backup old version before issuing the git update?
48
48
 
@@ -52,7 +52,7 @@ class RailsPwnage::App::Git
52
52
  end
53
53
 
54
54
  def update_prefetch(app_name, instance_name)
55
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
55
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
56
56
  return unless File.exists?(File.join(app_path, '.git'))
57
57
 
58
58
  Dir.chdir app_path do
@@ -75,7 +75,7 @@ class RailsPwnage::App::Git
75
75
  end
76
76
 
77
77
  return :next unless git_repository =~ /\.git(\/.*)?$/
78
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
78
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
79
79
 
80
80
  FileUtils.rm_rf app_path
81
81
  print "Doing Git clone, please enter your password if prompted...\n"
@@ -5,14 +5,14 @@ require 'fileutils'
5
5
  require 'pathname'
6
6
  require 'set'
7
7
 
8
- class RailsPwnage::App::Perforce
9
- include RailsPwnage::Base
8
+ class RailsPwnerer::App::Perforce
9
+ include RailsPwnerer::Base
10
10
 
11
11
  # TODO(costan): figure out how to remove unused files in perforce and do it
12
12
 
13
13
  # remove any files not in client workspace
14
14
  def cleanup_app_dir(app_name, instance_name, target_dir, app_name_is_dir = false)
15
- path_base = app_name_is_dir ? app_name : RailsPwnage::Config[app_name, instance_name][:app_path]
15
+ path_base = app_name_is_dir ? app_name : RailsPwnerer::Config[app_name, instance_name][:app_path]
16
16
  path_base = File.join path_base, target_dir
17
17
  path_base = path_base[0...-1] if path_base[-1] == '/'
18
18
  Dir.chdir path_base do
@@ -41,7 +41,7 @@ class RailsPwnage::App::Perforce
41
41
  # clean up the application directory by removing caches
42
42
  def cleanup_app_caches(app_name, instance_name, app_name_is_dir = false)
43
43
  # TODO: this is almost-duplicated in git.rb -- pull up somewhere
44
- app_path = app_name_is_dir ? app_name : RailsPwnage::Config[app_name, instance_name][:app_path]
44
+ app_path = app_name_is_dir ? app_name : RailsPwnerer::Config[app_name, instance_name][:app_path]
45
45
  return unless File.exists?(File.join(app_path, '.p4clientspec'))
46
46
 
47
47
  # TODO: learn how Rails caches work and kill those too
@@ -73,7 +73,7 @@ class RailsPwnage::App::Perforce
73
73
  end
74
74
 
75
75
  def perforce_update(app_name, instance_name)
76
- Dir.chdir RailsPwnage::Config[app_name, instance_name][:app_path] do
76
+ Dir.chdir RailsPwnerer::Config[app_name, instance_name][:app_path] do
77
77
  perforce_config_file
78
78
 
79
79
  print "Doing Perforce sync...\n"
@@ -85,7 +85,7 @@ class RailsPwnage::App::Perforce
85
85
  end
86
86
 
87
87
  def checkout(remote_path, app_name, instance_name)
88
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
88
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
89
89
 
90
90
  # paths look like p4://user@depot:port/path/to/application
91
91
  path_regexp = /^p4\:\/\/([^\@\/]*\@)?([^\:\/]*)(:[1-9]+)?\/(.*)$/
@@ -127,7 +127,7 @@ END_SETTINGS
127
127
  end
128
128
 
129
129
  print "Creating Perforce client...\n"
130
- Dir.chdir RailsPwnage::Config[app_name, instance_name][:app_path] do
130
+ Dir.chdir RailsPwnerer::Config[app_name, instance_name][:app_path] do
131
131
  success = Kernel.system "p4 client -i < .p4clientspec"
132
132
  if !success
133
133
  Kernel.system "p4 client -i < .p4clientspec" if try_prompting_for_perforce_password
@@ -142,7 +142,7 @@ END_SETTINGS
142
142
  end
143
143
 
144
144
  def update(app_name, instance_name)
145
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
145
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
146
146
  return unless File.exists?(File.join(app_path, '.p4clientspec'))
147
147
 
148
148
  # TODO: maybe backup old version before issuing the p4 sync?
@@ -152,19 +152,19 @@ END_SETTINGS
152
152
  end
153
153
 
154
154
  def update_prefetch(app_name, instance_name)
155
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
155
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
156
156
  return unless File.exists?(File.join(app_path, '.p4clientspec'))
157
157
 
158
158
  # TODO: maybe figure out a way to prefetch Perforce, if it's ever worth it
159
159
  end
160
160
 
161
161
  def remove(app_name, instance_name)
162
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
162
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
163
163
  return unless File.exists?(File.join(app_path, '.p4clientspec'))
164
164
 
165
165
 
166
166
  print "Deleting Perforce client...\n"
167
- Dir.chdir RailsPwnage::Config[app_name, instance_name][:app_path] do
167
+ Dir.chdir RailsPwnerer::Config[app_name, instance_name][:app_path] do
168
168
  p4_config = File.read perforce_config_file
169
169
  client_match = /^P4CLIENT=(.*)$/.match p4_config
170
170
  p4_client = client_match[1]
@@ -5,12 +5,12 @@ require 'fileutils'
5
5
  require 'pathname'
6
6
  require 'rexml/document'
7
7
 
8
- class RailsPwnage::App::Svn
9
- include RailsPwnage::Base
8
+ class RailsPwnerer::App::Svn
9
+ include RailsPwnerer::Base
10
10
 
11
11
  # remove any files not in SVN in the application dir
12
12
  def cleanup_app_dir(app_name, instance_name, target_dir, app_name_is_dir = false)
13
- Dir.chdir(app_name_is_dir ? app_name : RailsPwnage::Config[app_name, instance_name][:app_path]) do
13
+ Dir.chdir(app_name_is_dir ? app_name : RailsPwnerer::Config[app_name, instance_name][:app_path]) do
14
14
  # get a listing of what happened in that directory
15
15
  xml_status = `svn status --xml #{target_dir}`
16
16
  xsdoc = REXML::Document.new xml_status
@@ -27,7 +27,7 @@ class RailsPwnage::App::Svn
27
27
  # clean up the application directory by removing caches
28
28
  def cleanup_app_caches(app_name, instance_name, app_name_is_dir = false)
29
29
  # TODO: this is almost-duplicated in git.rb -- pull up somewhere
30
- app_path = app_name_is_dir ? app_name : RailsPwnage::Config[app_name, instance_name][:app_path]
30
+ app_path = app_name_is_dir ? app_name : RailsPwnerer::Config[app_name, instance_name][:app_path]
31
31
  return unless File.exists?(File.join(app_path, '.svn'))
32
32
 
33
33
  # TODO: learn how Rails caches work and kill those too
@@ -39,7 +39,7 @@ class RailsPwnage::App::Svn
39
39
 
40
40
  # reverts the config changes made by rpwn, so svn update doesn't get confused
41
41
  def revert_config_changes(app_name, instance_name)
42
- Dir.chdir RailsPwnage::Config[app_name, instance_name][:app_path] do
42
+ Dir.chdir RailsPwnerer::Config[app_name, instance_name][:app_path] do
43
43
  ['config', 'Gemfile'].each do |dir|
44
44
  Kernel.system "svn revert --recursive #{dir}"
45
45
  end
@@ -47,7 +47,7 @@ class RailsPwnage::App::Svn
47
47
  end
48
48
 
49
49
  def svn_update(app_name, instance_name)
50
- Dir.chdir RailsPwnage::Config[app_name, instance_name][:app_path] do
50
+ Dir.chdir RailsPwnerer::Config[app_name, instance_name][:app_path] do
51
51
  print "Doing SVN update, please enter your password if prompted...\n"
52
52
  success = Kernel.system 'svn update'
53
53
  unless success
@@ -60,7 +60,7 @@ class RailsPwnage::App::Svn
60
60
  end
61
61
 
62
62
  def checkout(remote_path, app_name, instance_name)
63
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
63
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
64
64
  return :next unless remote_path =~ /svn.*\:\/\// or remote_path =~ /http.*\:\/\/.*svn/
65
65
 
66
66
  print "Doing SVN checkout, please enter your password if prompted...\n"
@@ -71,7 +71,7 @@ class RailsPwnage::App::Svn
71
71
  end
72
72
 
73
73
  def update(app_name, instance_name)
74
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
74
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
75
75
  return unless File.exists?(File.join(app_path, '.svn'))
76
76
 
77
77
  # TODO: maybe backup old version before issuing the svn update?
@@ -82,7 +82,7 @@ class RailsPwnage::App::Svn
82
82
  end
83
83
 
84
84
  def update_prefetch(app_name, instance_name)
85
- app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
85
+ app_path = RailsPwnerer::Config[app_name, instance_name][:app_path]
86
86
  return unless File.exists?(File.join(app_path, '.svn'))
87
87
 
88
88
  # TODO: figure out a way to prefetch using SVN (hidden local repo mirror?)
@@ -4,7 +4,7 @@ require 'digest/md5'
4
4
  require 'fileutils'
5
5
  require 'yaml'
6
6
 
7
- module RailsPwnage::Base
7
+ module RailsPwnerer::Base
8
8
  # reads the content of one file
9
9
  # returns nil if the file is corrupted, otherwise returns [file data, timestamp]
10
10
  def atomic_read_internal(file_name)
@@ -44,7 +44,7 @@ else
44
44
 
45
45
  end
46
46
 
47
- module RailsPwnage::Base
47
+ module RailsPwnerer::Base
48
48
  # returns information for each core in the system
49
49
  def cpu_cores
50
50
  cpus = []
@@ -3,7 +3,7 @@
3
3
  require 'etc'
4
4
  require 'fileutils'
5
5
 
6
- module RailsPwnage::Base
6
+ module RailsPwnerer::Base
7
7
  # gets the UID associated with the username
8
8
  def uid_for_username(name)
9
9
  passwd_entry = Etc.getpwnam(name)
@@ -1,6 +1,6 @@
1
1
  # extends Base with gem-related functions
2
2
 
3
- module RailsPwnage::Base
3
+ module RailsPwnerer::Base
4
4
  # TODO: use the Gem API instead of the command line
5
5
 
6
6
  def install_gem(gem_name)
@@ -50,7 +50,7 @@ module RailsPwnage::Base
50
50
  end
51
51
  end
52
52
 
53
- module RailsPwnage::Base
53
+ module RailsPwnerer::Base
54
54
  def install_gems(gem_names)
55
55
  unroll_collection(gem_names) { |n| install_gem(n) }
56
56
  end
@@ -3,6 +3,6 @@
3
3
  require 'digest/md5'
4
4
  require 'yaml'
5
5
 
6
- module RailsPwnage::Base
6
+ module RailsPwnerer::Base
7
7
 
8
8
  end
@@ -7,7 +7,7 @@ rescue Exception
7
7
  # no highline... tough luck
8
8
  end
9
9
 
10
- module RailsPwnage::Base
10
+ module RailsPwnerer::Base
11
11
  def prompt_user_for_password(prompt, fail_prompt)
12
12
  unless defined?(HighLine)
13
13
  print "#{fail_prompt}\n"
@@ -0,0 +1,272 @@
1
+ # extends Base with OS package-related functions
2
+
3
+ require 'English'
4
+ require 'fileutils'
5
+ require 'shellwords'
6
+
7
+ module RailsPwnerer::Base
8
+ # TODO: this works for debian-only
9
+
10
+ # Installs a package matching a pattern or list of patterns.
11
+ #
12
+ # Args:
13
+ # patterns:: same as for best_package_matching
14
+ # options:: same as for install_package
15
+ #
16
+ # Returns true for success, false if something went wrong.
17
+ def install_package_matching(patterns, options = {})
18
+ package_name = best_package_matching patterns
19
+ install_package package_name, options
20
+ end
21
+
22
+ # Installs a package.
23
+ #
24
+ # Args:
25
+ # package_name:: the exact name of the package to be installed
26
+ # options:: accepts the following:
27
+ # :source:: if true, a source package is installed and built
28
+ # :skip_proxy:: if true, apt is instructed to bypass any proxy that might
29
+ # be
30
+ #
31
+ # Returns true for success, false if something went wrong.
32
+ def install_package(package_name, options = {})
33
+ return true if install_package_impl(package_name, options)
34
+ if options[:source]
35
+ if options[:no_proxy]
36
+ install_package package_name, options.merge(:source => false)
37
+ else
38
+ install_package package_name, options.merge(:no_proxy => true)
39
+ end
40
+ else
41
+ return false unless options[:no_proxy]
42
+ install_package package_name, options.merge(:no_proxy => true)
43
+ end
44
+ end
45
+
46
+ # Removes a package.
47
+ #
48
+ # Args:
49
+ # package_name:: the exact name of the package to be installed
50
+ #
51
+ # Returns true for success, false if something went wrong.
52
+ def remove_package(package_name, options = {})
53
+ prefix, params = apt_params_for options
54
+ del_cmd = "#{prefix } apt-get remove #{params} #{package_name}"
55
+ Kernel.system(del_cmd) ? true : false
56
+ end
57
+
58
+ # Internals for install_package.
59
+ def install_package_impl(package_name, options)
60
+ prefix, params = apt_params_for options
61
+ if options[:source]
62
+ with_temp_dir(:root => true) do
63
+ dep_cmd = "#{prefix} apt-get build-dep #{params} #{package_name}"
64
+ return false unless Kernel.system(dep_cmd)
65
+ fetch_cmd = "#{prefix} apt-get source -b #{params} #{package_name}"
66
+ return false unless Kernel.system(fetch_cmd)
67
+ deb_files = Dir.glob '*.deb', File::FNM_DOTMATCH
68
+ build_cmd = "#{prefix} dpkg -i #{deb_files.join(' ')}"
69
+ return false unless Kernel.system(build_cmd)
70
+ end
71
+ else
72
+ install_cmd = "#{prefix} apt-get install #{params} #{package_name}"
73
+ return false unless Kernel.system(install_cmd)
74
+ end
75
+ return true
76
+ end
77
+
78
+ # Executes the given block in the context of having new package sources.
79
+ #
80
+ # Args:
81
+ # source_url:: the source URL, e.g. http://security.ubuntu.com/ubuntu
82
+ # repositories:: the package repositories to use, e.g. ['main', 'universe']
83
+ # options:: supports the following keys:
84
+ # :source:: if true, will use source-form packages from the new
85
+ # sources; by default, binary packages will be used
86
+ #
87
+ # Returns the block's return value.
88
+ #
89
+ # After adding the new package source, the package metadata is refreshed, so
90
+ # the block can focus on installing new packages.
91
+ #
92
+ # If the package source already exists, the given block is yielded without
93
+ # making any changes to the package configuration.
94
+ def with_package_source(source_url, source_repos = [], options = {})
95
+ source_prefix = options[:source] ? 'deb-src' : 'deb'
96
+ source_patterns = [source_prefix, source_url] + source_repos
97
+
98
+ source_contents = File.read '/etc/apt/sources.list'
99
+ sources = source_contents.split(/(\r|\n)+/)
100
+ source_exists = sources.any? do |source_line|
101
+ source_frags = source_line.split(' ')
102
+ source_patterns.all? { |pattern| source_frags.any? { |frag| frag == pattern } }
103
+ end
104
+
105
+ unless source_exists
106
+ File.open('/etc/apt/sources.list', 'a') do |f|
107
+ f.write "#{source_prefix} #{source_url} #{source_repos.join(' ')}\n"
108
+ end
109
+ update_package_metadata
110
+ end
111
+
112
+ begin
113
+ yield
114
+ ensure
115
+ unless source_exists
116
+ File.open('/etc/apt/sources.list', 'w') { |f| f.write source_contents }
117
+ update_package_metadata
118
+ end
119
+ end
120
+ end
121
+
122
+ # Updates the metadata for all the packages.
123
+ #
124
+ # Options:
125
+ # :skip_proxy:: if true, apt is instructed to bypass the proxy
126
+ #
127
+ # Returns true for success, false if something went wrong.
128
+ def update_package_metadata(options = {})
129
+ if update_package_metadata_impl(options)
130
+ # Reset the metadata cache.
131
+ RailsPwnerer::Base.instance_variable_set :@packages, nil
132
+ return true
133
+ end
134
+
135
+ return false if options[:skip_proxy]
136
+ update_package_metadata options.merge(:skip_proxy => true)
137
+ end
138
+
139
+ # Internals for update_package_metadata.
140
+ def update_package_metadata_impl(options)
141
+ prefix, params = apt_params_for options
142
+ Kernel.system("#{prefix} apt-get update #{params}") ?
143
+ true : false
144
+ end
145
+ private :update_package_metadata_impl
146
+
147
+ # Builds apt-get parameters for an option hash.
148
+ #
149
+ # Args:
150
+ # options:: an option hash, as passed to install_package, update_package,
151
+ # or update_package_metadata
152
+ #
153
+ # Returns prefix, args, where prefix is a prefix for the apt- command, and
154
+ # args is one or more command-line arguments.
155
+ def apt_params_for(options = {})
156
+ prefix = 'env DEBIAN_FRONTEND=noninteractive '
157
+ prefix += 'DEBIAN_PRIORITY=critical '
158
+ prefix += 'DEBCONF_TERSE=yes '
159
+
160
+ params = "-qq -y"
161
+ params += " -o Acquire::http::Proxy=false" if options[:skip_proxy]
162
+ return prefix, params
163
+ end
164
+ private :apt_params_for
165
+
166
+ # Package info for the best package matching a pattern or set of patterns.
167
+ #
168
+ # Args:
169
+ # patterns:: a String or Regexp, or an array of such Strings or Regexps
170
+ #
171
+ # Returns a hash with the following keys:
172
+ # :name:: the package name
173
+ # :version:: the package version
174
+ #
175
+ # Each pattern is searched for in turn. Once there are packages matching a
176
+ # pattern, the
177
+ def best_package_matching(patterns)
178
+ patterns = [patterns] unless patterns.kind_of?(Enumerable)
179
+ patterns.each do |pattern|
180
+ packages = search_packages(pattern)
181
+ next if packages.empty?
182
+ best = packages.sort_by { |key, value|
183
+ [
184
+ pattern.kind_of?(Regexp) ? ((key.index(pattern) == 0) ? 1 : 0) :
185
+ ((key == pattern) ? 1 : 0),
186
+ value.split(/[.-]/)
187
+ ]
188
+ }.last
189
+ return { :name => best.first, :version => best.last }
190
+ end
191
+ nil
192
+ end
193
+
194
+ # Searches for packages matching a name.
195
+ #
196
+ # Args:
197
+ # pattern:: a String or Regexp containing a pattern that should be matched
198
+ # by the package names
199
+ #
200
+ # Returns a hash where the keys are matching package names, and the values
201
+ # are version numbers.
202
+ def search_packages(pattern)
203
+ Hash[*(RailsPwnerer::Base.all_packages.select { |key, value|
204
+ pattern.kind_of?(Regexp) ? (pattern =~ key) : key.index(pattern)
205
+ }.flatten)]
206
+ end
207
+
208
+ # A hash of all the packages in the system, associated with their versions.
209
+ @packages = nil
210
+ def self.all_packages
211
+ @packages ||= all_packages_without_caching
212
+ end
213
+
214
+ # A hash of all the packages in the system, associated with their versions.
215
+ #
216
+ # This method is slow as hell, so it's memoized in all_packages.
217
+ def self.all_packages_without_caching
218
+ output = Kernel.` "apt-cache search --full ."
219
+ versions = output.split("\n\n").map(&:strip).reject(&:empty?).map { |info|
220
+ info_hash = Hash[*(info.split(/\n(?=\w)/).
221
+ map { |s| s.split(': ', 2) }.flatten)]
222
+ [info_hash['Package'], info_hash['Version']]
223
+ }
224
+ Hash[*(versions.flatten)]
225
+ end
226
+
227
+ # Upgrades a package to the latest version.
228
+ def upgrade_package(package_name, options = {})
229
+ return install_package(package_name, options) if options[:source]
230
+
231
+ return true if upgrade_package_impl(package_name, options)
232
+
233
+ return false if options[:no_proxy]
234
+ upgrade_package package_name, options.merge(:no_proxy => true)
235
+ end
236
+
237
+ # Internals for upgrade_package.
238
+ def upgrade_package_impl(package_name, options)
239
+ prefix, params = apt_params_for options
240
+ update_cmd = "#{prefix} apt-get upgrade #{params} #{package_name}"
241
+ Kernel.system(update_cmd) ? true : false
242
+ end
243
+
244
+ # Upgrades all the packages on the system to the latest version.
245
+ def update_all_packages(options = {})
246
+ return true if update_all_packages_impl(options)
247
+
248
+ return false if options[:no_proxy]
249
+ update_all_packages options.merge(:no_proxy => true)
250
+ end
251
+
252
+ # Internals for upgrade_all_packages.
253
+ def update_all_packages_impl(options)
254
+ prefix, params = apt_params_for options
255
+ success = Kernel.system "#{prefix} apt-get upgrade #{params}"
256
+ success ? true : false
257
+ end
258
+ end
259
+
260
+ module RailsPwnerer::Base
261
+ def install_packages(package_names, options = {})
262
+ unroll_collection(package_names) { |n| install_package(n, options) }
263
+ end
264
+
265
+ def upgrade_packages(package_names, options = {})
266
+ unroll_collection(package_names) { |n| upgrade_package(n, options) }
267
+ end
268
+
269
+ def remove_packages(package_names)
270
+ unroll_collection(package_names) { |n| remove_package(n) }
271
+ end
272
+ end
@@ -31,7 +31,7 @@ rescue Exception
31
31
  end
32
32
  end
33
33
 
34
- module RailsPwnage::Base
34
+ module RailsPwnerer::Base
35
35
  # returns information about a process
36
36
  def process_info(pid = nil)
37
37
  info = Hash.new
@@ -1,6 +1,6 @@
1
1
  # extends Base with Rails-related functions
2
2
 
3
- module RailsPwnage::Base
3
+ module RailsPwnerer::Base
4
4
  # check if the given path is the root of a Rails application
5
5
  def check_rails_root(path = '.')
6
6
  ['app', 'config', 'db', 'public', 'script', 'vendor',
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'fileutils'
4
4
 
5
- module RailsPwnage::Base
5
+ module RailsPwnerer::Base
6
6
  # TODO: make this work w/o initd (OSX, Windows)
7
7
 
8
8
  # returns the filesystem path to a boot script
@@ -1,4 +1,4 @@
1
- module RailsPwnage::Base
1
+ module RailsPwnerer::Base
2
2
  # initializes the module in UNIX mode
3
3
  def self._setup_unix
4
4
  #SUDO_PREFIX = 'sudo '
@@ -1,6 +1,6 @@
1
1
  # application-specific configuration functions
2
2
 
3
- module RailsPwnage::Config
3
+ module RailsPwnerer::Config
4
4
  # the name of the database storing an app's configuration
5
5
  def self.app_db_name(app_name, instance_name)
6
6
  return "#{app_name}.#{instance_name}"
@@ -1,6 +1,6 @@
1
1
  # computes the number of frontends to be used in an application
2
2
 
3
- module RailsPwnage::Config
3
+ module RailsPwnerer::Config
4
4
  # the number of frontends for an application
5
5
  def self.app_frontends(app_name, instance_name)
6
6
  # TODO: this is duplicated in cluster_config.rb -- pull up somewhere
@@ -0,0 +1,3 @@
1
+ module RailsPwnerer::Config
2
+
3
+ end
@@ -1,6 +1,6 @@
1
1
  # important paths in the filesystem
2
2
 
3
- module RailsPwnage::Config
3
+ module RailsPwnerer::Config
4
4
  # the path to something important (e.g. :apps --> path to all production applications)
5
5
  def self.path_to(what = :prod, app_name = nil)
6
6
  # need to hardcode path to config to avoid endless recursion
@@ -1,6 +1,6 @@
1
1
  # keeps track of the available ports on the machine
2
2
 
3
- module RailsPwnage::Config
3
+ module RailsPwnerer::Config
4
4
  def self.init_ports(free_ports = [[8000, 16000]])
5
5
  self.create_db :free_ports
6
6
  self[:free_ports][:list] = free_ports