module RailsPwnerer::Config
application-specific configuration functions
computes the number of frontends to be used in an application
important paths in the filesystem
keeps track of the available ports on the machine
implements the configuration repository
Public Class Methods
override [] to make the global DB look like a Hash
# File lib/rails_pwnerer/config/repository.rb 99 def self.[](db_or_app_name, instance_name = nil) 100 if instance_name.nil? 101 db_name = db_or_app_name 102 else 103 db_name = app_db_name(db_or_app_name, instance_name) 104 end 105 get_db(db_name) 106 end
all instances of all applications installed on this box
# File lib/rails_pwnerer/config/app.rb 15 def self.all_applications() 16 self.databases().select { |db| db.include? ?. }.map do |db| 17 lastdot = db.rindex ?. 18 [db[0...lastdot], db[(lastdot + 1)..-1]] 19 end 20 end
allocates a contiguous range of ports returns the starting port or nil
# File lib/rails_pwnerer/config/ports.rb 12 def self.alloc_ports(nports = 1) 13 free_ports = self[:free_ports][:list] 14 free_ports.each_index do |i| 15 next if free_ports[i][1] - free_ports[i][0] < nports 16 first_port = free_ports[i][0] 17 free_ports[i][0] += nports 18 free_ports.delete_at i if free_ports[i][0] == free_ports[i][1] 19 self[:free_ports][:list] = free_ports 20 self.flush_db :free_ports 21 return first_port 22 end 23 end
the name of the database storing an app’s configuration
# File lib/rails_pwnerer/config/app.rb 5 def self.app_db_name(app_name, instance_name) 6 return "#{app_name}.#{instance_name}" 7 end
the number of frontends for an application
# File lib/rails_pwnerer/config/frontends.rb 5 def self.app_frontends(app_name, instance_name) 6 # TODO: this is duplicated in cluster_config.rb -- pull up somewhere 7 app_config = self[app_name, instance_name] 8 return nil unless app_config and fixed_frontends = app_config[:frontends] 9 10 frontends_per_core = app_config[:frontends_per_core] || 0 11 detected_cores = app_config[:detected_cores] || 0 12 cores_frontends = frontends_per_core * detected_cores 13 return (cores_frontends != 0) ? cores_frontends : fixed_frontends 14 end
the instances of an application installed on this box
# File lib/rails_pwnerer/config/app.rb 10 def self.app_instances(app_name) 11 self.databases().select { |db| db.include? ?. }.map { |db| db[0...(db.rindex ?.)] } 12 end
creates a new database
# File lib/rails_pwnerer/config/repository.rb 40 def self.create_db(db_name) 41 db_name = db_name.to_s 42 43 db_contents = install_db_hooks({}, db_name) 44 @@db_cache[db_name] = db_contents 45 @@db_dirty[db_name] = true 46 flush_db db_name 47 return db_contents 48 end
# File lib/rails_pwnerer/config/repository.rb 108 def self.databases() 109 entries = Dir.entries RailsPwnerer::Config.path_to(:config) 110 databases = [] 111 entries.each do |entry| 112 next unless entry =~ /\.yml(2)?$/ 113 databases << entry.gsub(/\.yml(2)?$/, '') 114 end 115 return databases 116 end
drops a database
# File lib/rails_pwnerer/config/repository.rb 51 def self.drop_db(db_name) 52 @@db_cache[db_name] = nil 53 @@db_dirty[db_name] = true 54 flush_db db_name 55 end
flushes the contents of the given db from cache
# File lib/rails_pwnerer/config/repository.rb 76 def self.flush_db(db_name) 77 db_name = db_name.to_s 78 return unless @@db_dirty[db_name] 79 db_path = RailsPwnerer::Config.path_to :config 80 if @@db_cache[db_name].nil? 81 atomic_erase db_path, db_name 82 else 83 host_config = get_db :host 84 atomic_write @@db_cache[db_name], db_path, db_name, 85 :owner => (host_config && host_config[:pwnerer_user]) 86 end 87 @@db_dirty[db_name] = false 88 end
flushes the entire database cache (used when exiting)
# File lib/rails_pwnerer/config/repository.rb 91 def self.flush_db_cache 92 @@db_dirty.each do |db_name, is_dirty| 93 next unless is_dirty 94 flush_db db_name 95 end 96 end
returns a continuous range of ports to the free list
# File lib/rails_pwnerer/config/ports.rb 26 def self.free_ports(start, count = 1) 27 free_ports = self[:free_ports][:list] 28 free_ports << [start, start + count] 29 30 # concatenate duplicates 31 free_ports.sort! { |a, b| a[0] <=> b[0]} 32 new_ports = [free_ports.first] 33 free_ports.each_index do |i| 34 if new_ports.last[1] >= free_ports[i][0] 35 new_ports.last[1] = [new_ports.last[1], free_ports[i][1]].max 36 else 37 new_ports << free_ports[i] 38 end 39 end 40 41 # write the new database 42 self[:free_ports][:list] = new_ports 43 self.flush_db :free_ports 44 end
retrieves the contents of a db (from cache if necessary)
# File lib/rails_pwnerer/config/repository.rb 58 def self.get_db(db_name) 59 db_name = db_name.to_s 60 unless @@db_cache.has_key? db_name 61 db_path = RailsPwnerer::Config.path_to :config 62 db_contents = atomic_read(db_path, db_name) 63 64 if db_contents.nil? 65 @@db_cache[db_name] = nil 66 else 67 @@db_cache[db_name] = install_db_hooks db_contents, db_name 68 end 69 @@db_dirty[db_name] = false 70 end 71 72 return @@db_cache[db_name] 73 end
# File lib/rails_pwnerer/config/ports.rb 4 def self.init_ports(free_ports = [[8000, 16000]]) 5 self.create_db :free_ports 6 self[:free_ports][:list] = free_ports 7 self.flush_db :free_ports 8 end
installs the database hooks into a Hash
# File lib/rails_pwnerer/config/repository.rb 19 def self.install_db_hooks(db_contents, db_name) 20 # hooks: 21 # (1) automatically convert keys to strings 22 # (2) flip the dirty flag on writes 23 class << db_contents 24 def [](key) 25 super(key.to_s) 26 end 27 def []=(key, value) 28 super(key.to_s, value) 29 RailsPwnerer::Config.mark_db_dirty @db_name 30 end 31 def has_key?(key) 32 super(key.to_s) 33 end 34 end 35 db_contents.instance_variable_set :@db_name, db_name 36 return db_contents 37 end
called when a database is dirty
# File lib/rails_pwnerer/config/repository.rb 14 def self.mark_db_dirty(db_name) 15 @@db_dirty[db_name] = true 16 end
the path to something important (e.g. :apps –> path to all production applications)
# File lib/rails_pwnerer/config/paths.rb 5 def self.path_to(what = :prod, app_name = nil) 6 # need to hardcode path to config to avoid endless recursion 7 if what == :config 8 return '/prod/config/' 9 end 10 11 # first try the paths in the database 12 return self[:paths][what] if self[:paths] and self[:paths].has_key? what 13 14 # then try the global paths 15 static_path = static_path_to what 16 return static_path unless static_path.nil? 17 end
hardcoded paths
# File lib/rails_pwnerer/config/paths.rb 20 def self.static_path_to(what) 21 case what 22 when :config 23 # the directory containing the config files 24 '/prod/config' 25 when :prod 26 # the directory containing all the production data 27 '/prod' 28 when :apps 29 # the directory containing the production apps 30 '/prod/apps' 31 when :backups 32 '/prod/backups' 33 else 34 return 35 end 36 end