/lib/passenger_pane/application.rb

http://github.com/tgunr/passengerpane · Ruby · 219 lines · 174 code · 40 blank · 5 comment · 13 complexity · 4db2564c41c8e596af18d605cff0b5e0 MD5 · raw file

  1. require 'fileutils'
  2. module PassengerPane
  3. class Application
  4. RAILS_APP_REGEXP = /::Initializer\.run|Application\.initialize!/
  5. ATTRIBUTES = [:config_filename, :host, :aliases, :path, :framework, :environment, :vhost_address, :user_defined_data]
  6. def self.glob(configuration)
  7. File.join(
  8. configuration.apache_directory,
  9. configuration.passenger_vhosts,
  10. "*.#{configuration.passenger_vhosts_ext}"
  11. )
  12. end
  13. def self.all(configuration)
  14. Dir.glob(glob(configuration)).map do |config_filename|
  15. new(configuration, :config_filename => config_filename)
  16. end
  17. end
  18. def self.find(configuration, conditions={})
  19. if conditions[:host]
  20. all(configuration).detect do |app|
  21. app.host == conditions[:host]
  22. end
  23. end
  24. end
  25. attr_accessor(*ATTRIBUTES)
  26. def initialize(configuration, options={})
  27. @configuration = configuration
  28. set(options)
  29. if options[:config_filename]
  30. @new = false
  31. _parse
  32. elsif options[:path]
  33. @new = true
  34. _derive
  35. else
  36. raise ArgumentError, "Please specify either a :config_filename or :path"
  37. end
  38. @before_changes = to_hash
  39. end
  40. def set(options)
  41. options.each do |key, value|
  42. setter = trust("#{key}=")
  43. send(setter, trust(value)) if respond_to?(setter)
  44. end
  45. end
  46. def new?
  47. @new
  48. end
  49. # -- Virtual Host reading and writing
  50. def contents
  51. @contents ||= File.read(trust(@config_filename))
  52. end
  53. attr_writer :contents
  54. def _parse
  55. data = contents.dup
  56. data.gsub!(/\n\s*ServerName\s+(.+)/, '')
  57. @host = $1
  58. data.gsub!(/\n\s*ServerAlias\s+(.+)/, '')
  59. @aliases = $1 || ''
  60. data.gsub!(/\n\s*DocumentRoot\s+"(.+)"/, '')
  61. path = $1
  62. if path.end_with?('public')
  63. @path = File.dirname(path)
  64. else
  65. @path = path
  66. end
  67. data.gsub!(/\n\s*(Rails|Rack)Env\s+(\w+)/, '')
  68. @framework = $1 ? $1.downcase : nil
  69. @environment = $2
  70. data.gsub!(/<VirtualHost\s(.+?)>/, '')
  71. @vhost_address = $1
  72. data.gsub!(/\s*<\/VirtualHost>\n*/, '').gsub!(/^\n*/, '')
  73. @user_defined_data = data.strip
  74. end
  75. def _document_root
  76. File.join(@path, 'public')
  77. end
  78. def _directory_defaults
  79. %{
  80. <Directory "#{_document_root}">
  81. Order allow,deny
  82. Allow from all
  83. </Directory>
  84. }.strip
  85. end
  86. def _config_filename
  87. File.join(
  88. @configuration.apache_directory,
  89. @configuration.passenger_vhosts,
  90. "#{@host}.#{@configuration.passenger_vhosts_ext}"
  91. )
  92. end
  93. def _framework
  94. environment_file = File.join(@path, 'config', 'environment.rb')
  95. if File.exist?(environment_file) and File.read(environment_file) =~ RAILS_APP_REGEXP
  96. 'rails'
  97. else
  98. 'rack'
  99. end
  100. end
  101. def _derive
  102. @host ||= "#{File.basename(path).downcase.gsub('_','-')}.local"
  103. @aliases ||= ''
  104. @environment ||= 'development'
  105. @vhost_address ||= '*:80'
  106. @user_defined_data ||= _directory_defaults
  107. @config_filename ||= _config_filename
  108. @framework ||= _framework
  109. end
  110. def rails?; @framework == 'rails' end
  111. def rack?; @framework == 'rack' end
  112. def vhost_snippet
  113. lines = []
  114. lines << "<VirtualHost #{vhost_address}>"
  115. lines << " ServerName #{host}"
  116. lines << " ServerAlias #{aliases}" unless aliases == ''
  117. lines << " DocumentRoot \"#{_document_root}\""
  118. if @framework
  119. lines << " #{rails? ? 'RailsEnv' : 'RackEnv'} #{environment}"
  120. end
  121. lines << " #{user_defined_data}" unless user_defined_data.strip == ''
  122. lines << "</VirtualHost>"
  123. lines.join("\n")
  124. end
  125. def write
  126. FileUtils.mkdir_p(File.dirname(@config_filename))
  127. File.open(@config_filename, 'w') do |file|
  128. file.write(vhost_snippet)
  129. end; true
  130. end
  131. # -- Dirty checking
  132. def to_hash
  133. hash = { 'hosts' => [host, *aliases.split] }
  134. ATTRIBUTES.each do |key|
  135. hash[key.to_s] = instance_variable_get("@#{key}")
  136. end; hash
  137. end
  138. def changed?
  139. @before_changes != to_hash
  140. end
  141. def added_hosts
  142. to_hash['hosts'] - @before_changes['hosts']
  143. end
  144. def removed_hosts
  145. @before_changes['hosts'] - to_hash['hosts']
  146. end
  147. # -- Directory services
  148. def register
  149. PassengerPane::DirectoryServices.register(to_hash['hosts'])
  150. end
  151. def unregister
  152. PassengerPane::DirectoryServices.unregister(to_hash['hosts'])
  153. end
  154. def sync_host_registration
  155. if new?
  156. register
  157. else
  158. PassengerPane::DirectoryServices.register(added_hosts) and
  159. PassengerPane::DirectoryServices.unregister(removed_hosts)
  160. end
  161. end
  162. # -- Persisting
  163. def save
  164. write and sync_host_registration
  165. end
  166. def delete
  167. FileUtils.rm_rf(config_filename)
  168. unregister
  169. true
  170. end
  171. # -- Operational
  172. def restart
  173. if File.exist?(@path)
  174. FileUtils.mkdir_p(File.join(File.join(@path, 'tmp')))
  175. FileUtils.touch(File.join(@path, 'tmp', 'restart.txt'))
  176. end
  177. end
  178. end
  179. end