more cool stuff and more docs

This commit is contained in:
John Bintz 2010-05-11 15:19:16 -04:00
parent 710831190d
commit 5f2652af73
9 changed files with 142 additions and 56 deletions

View File

@ -1,33 +0,0 @@
# Apache Config Generator
Programmatically construct your Apache configuration using a powerful DSL built in Ruby.
## Installation
`gem install apache-config-generator`
## Usage
Run `apache-configurator <directory>` to create a new directory to hold your config files.
A Rakefile and config.yml file will also be generated.
## Building a config file
Configs center around the Apache::Config.build method:
Apache::Config.build('sites-available/my-site.conf') do
server_name 'my-cool-website.cool.wow'
document_root '/var/www/my-cool-website'
directory '/' do
options :follow_sym_links, :indexes
allow_from_all
end
location_match %r{^/secret} do
deny_from_all
basic_authentication "My secret", '/etc/apache2/users/global.users', :user => :john
satisfy :any
end
end

34
README.rdoc Normal file
View File

@ -0,0 +1,34 @@
= Apache Config Generator
Programmatically construct your Apache configuration using a powerful DSL built in Ruby.
== Installation
<tt>gem install apache-config-generator</tt>
== Usage
Run <tt>apache-configurator <directory></tt> to create a new directory to hold your config files.
A Rakefile and config.yml file will also be generated.
== Building a config file
Configs center around the Apache::Config.build method:
Apache::Config.build('sites-available/my-site.conf') do
server_name 'my-cool-website.cool.wow'
document_root '/var/www/my-cool-website'
directory '/' do
options :follow_sym_links, :indexes
allow_from_all
end
location_match %r{^/secret} do
deny_from_all
basic_authentication "My secret", '/etc/apache2/users/global.users', :user => :john
satisfy :any
end
end

View File

@ -20,6 +20,7 @@ Echoe.new('apache-config-generator') do |p|
p.summary = "A Ruby DSL for programmatically generating Apache configs" p.summary = "A Ruby DSL for programmatically generating Apache configs"
p.ignore_pattern = [ 'spec/**/*', 'test/**/*', 'docs/**/*' ] p.ignore_pattern = [ 'spec/**/*', 'test/**/*', 'docs/**/*' ]
p.executable_pattern = [ 'bin/**/*' ] p.executable_pattern = [ 'bin/**/*' ]
p.runtime_dependencies = [ 'rainbow' ]
end end
namespace :spec do namespace :spec do
@ -34,6 +35,7 @@ end
Rake::RDocTask.new do |rdoc| Rake::RDocTask.new do |rdoc|
rdoc.template = 'direct' rdoc.template = 'direct'
rdoc.rdoc_files.add('lib') rdoc.rdoc_files.add('lib', 'README.rdoc')
rdoc.main = 'README.rdoc'
rdoc.rdoc_dir = 'docs' rdoc.rdoc_dir = 'docs'
end end

View File

@ -1,4 +1,5 @@
require 'fileutils' require 'fileutils'
require 'rainbow'
Dir[File.join(File.dirname(__FILE__), '*.rb')].each { |f| require f } Dir[File.join(File.dirname(__FILE__), '*.rb')].each { |f| require f }
@ -124,7 +125,9 @@ module Apache
def apachify(name) def apachify(name)
case name case name
when String, Symbol when String, Symbol
name.to_s.split("_").collect(&:capitalize).join.gsub('Ssl', 'SSL').gsub('Cgi', 'CGI').gsub('Ldap', 'LDAP').gsub('Url', 'URL') name.to_s.split("_").collect(&:capitalize).join.gsub('Ssl', 'SSL').
gsub('Cgi', 'CGI').gsub('Ldap', 'LDAP').gsub('Url', 'URL').
gsub('Etag', 'ETag')
when Array when Array
name.collect { |n| apachify(n) } name.collect { |n| apachify(n) }
end end
@ -230,17 +233,21 @@ module Apache
"|#{@rotate_logs_path} #{path} #{time}" "|#{@rotate_logs_path} #{path} #{time}"
end end
def warn_msg(from, color = :red)
"[warn::#{from}]".foreground(color)
end
private private
def writable?(path) def writable?(path)
puts "[warn] #{path} may not be writable!" if !File.directory? File.split(path).first puts " #{warn_msg('writable?')} #{path.foreground(:yellow)} may not be writable!" if !File.directory? File.split(path).first
end end
def directory?(path) def directory?(path)
puts "[warn] #{path} does not exist!" if !File.directory? path puts " #{warn_msg('directory?')} #{path.foreground(:yellow)} does not exist!" if !File.directory? path
end end
def exist?(path) def exist?(path)
puts "[warn] #{path} does not exist!" if !File.exist?(path) puts " #{warn_msg('exist?')} #{path.foreground(:yellow)} does not exist!" if !File.exist?(path)
end end
end end

View File

@ -8,6 +8,11 @@ module Apache
@config += Modules.build(*modules, &block) @config += Modules.build(*modules, &block)
end end
def listen(*opt)
opt.each { |o| self << "Listen #{quoteize(o)}" }
end
alias :listen! :listen
# Add a User/Group block # Add a User/Group block
# runner('www', 'www-data') #=> # runner('www', 'www-data') #=>
# User www # User www

View File

@ -85,7 +85,7 @@ module Apache
# Create an Apache require directive. # Create an Apache require directive.
# Used to get around Ruby reserved word. # Used to get around Ruby reserved word.
def apache_require(*opts) def apache_require(*opts)
self << "Require #{opts * " "}" self << "Require #{opts.compact * " "}"
end end
end end
end end

View File

@ -2,6 +2,7 @@ require 'fileutils'
require 'apache/config' require 'apache/config'
require 'apache/rake/create' require 'apache/rake/create'
require 'yaml' require 'yaml'
require 'rainbow'
namespace :apache do namespace :apache do
desc "Create all defined configs for the specified environment" desc "Create all defined configs for the specified environment"
@ -19,7 +20,7 @@ namespace :apache do
Dir.chdir CONFIG[:dest_path] Dir.chdir CONFIG[:dest_path]
Dir[File.join(CONFIG[:source_path], '**', '*.rb')].each do |file| Dir[File.join(CONFIG[:source_path], '**', '*.rb')].each do |file|
puts file puts file.foreground(:green)
require file require file
end end
end end

View File

@ -21,11 +21,15 @@ module Apache
end end
# Pass the block to RewriteManager.build # Pass the block to RewriteManager.build
def rewrites(&block) def rewrites(*opt, &block)
self + indent(RewriteManager.build(&block)) self + indent(RewriteManager.build(*opt, &block))
self << '' self << ''
end end
def rewrite(*opt, &block)
raise "You probably want rewrites #{quoteize(*opt) * " "} do" if block
end
# Create a permanent Redirect # Create a permanent Redirect
# #
# r301 '/here', '/there' #=> Redirect permanent "/here" "/there" # r301 '/here', '/there' #=> Redirect permanent "/here" "/there"
@ -45,12 +49,27 @@ module Apache
end end
# Build rewritable things from the provided block # Build rewritable things from the provided block
def build(&block) def build(*opt, &block)
reset! reset!
@any_tests = false
@needs_tests = false
self.instance_eval(&block) self.instance_eval(&block)
@rewrites.collect(&:to_a).flatten name = opt.first || (@rewrites.empty? ? 'unnamed block' : "#{@rewrites.first.from} => #{@rewrites.first.to}")
if !@any_tests && !@rewrites.empty?
puts " [#{"rewrite".foreground(:blue)}] no tests found for #{name}"
end
if @needs_tests
puts " [#{"rewrite".foreground(:blue)}] #{name} needs more tests"
end
output = @rewrites.collect(&:to_a).flatten
output.unshift("# #{name}") if opt.first
output
end end
# Commit the latest rewritable thing to the list of rewrites # Commit the latest rewritable thing to the list of rewrites
@ -98,21 +117,49 @@ module Apache
# Test the rewritable things defined in this block # Test the rewritable things defined in this block
def rewrite_test(from, to, opts = {}) def rewrite_test(from, to, opts = {})
@any_tests = true
orig_from = from.dup orig_from = from.dup
@rewrites.each do |r| @rewrites.each do |r|
pre_from = from.dup pre_from = from.dup
if r.match?(from, opts) if r.match?(from, opts)
from = r.test(from, opts) from = r.test(from, opts)
from = pre_from if (from == '-') from = pre_from if (r.to == '-')
from = :http_forbidden if (r.forbidden?)
break if r.stop_if_match? break if r.stop_if_match?
end end
end end
if from != to if from != to
puts "[warn] #{orig_from} >> #{to} failed!" puts " [#{"rewrite".foreground(:blue)}] #{orig_from} >> #{to} failed!"
puts "[warn] Result: #{from}" puts " [#{"rewrite".foreground(:blue)}] Result: #{from}"
end end
end end
def needs_tests
@needs_tests = true
end
def cond_not_a_file(opts = {})
cond_file_flag '!-f', opts
end
def cond_is_a_file(opts = {})
cond_file_flag '-f', opts
end
def cond_not_a_directory(opts = {})
cond_file_flag '!-d', opts
end
def cond_is_a_directory(opts = {})
cond_file_flag '-d', opts
end
private
def cond_file_flag(flag, opts)
cond opts[:filename_only] ? "%{REQUEST_FILENAME}" : "%{DOCUMENT_ROOT}%{REQUEST_FILENAME}", flag
end
end end
end end
@ -144,6 +191,8 @@ module Apache
class MatchableThing class MatchableThing
include Apache::Quoteize include Apache::Quoteize
attr_reader :from, :to
# The Apache directive tag for this thing # The Apache directive tag for this thing
def tag; raise 'Override this method'; end def tag; raise 'Override this method'; end
@ -166,6 +215,7 @@ module Apache
end end
def stop_if_match?; false; end def stop_if_match?; false; end
def forbidden?; false; end
end end
# A RewriteRule definition # A RewriteRule definition
@ -195,12 +245,18 @@ module Apache
case key case key
when :last when :last
'L' 'L'
when :forbidden
'F'
when :no_escape
'NE'
when :redirect when :redirect
'R' (value == true) ? 'R' : "R=#{value}"
when :pass_through when :pass_through
'PT' 'PT'
when :preserve_query_string when :preserve_query_string
'QSA' 'QSA'
when :env
"E=#{value}"
end end
end.compact.sort end.compact.sort
@ -220,11 +276,12 @@ module Apache
end end
def to_a def to_a
[ @conditions.collect(&:to_s), super ].flatten [ ('' if !@conditions.empty?), @conditions.collect(&:to_s), super ].flatten
end end
# Test this RewriteRule, ensuring the RewriteConds also match # Test this RewriteRule, ensuring the RewriteConds also match
def test(from, opts = {}) def test(from, opts = {})
opts[:request_uri] = from
result = from result = from
result = super(from, opts) if match?(from, opts) result = super(from, opts) if match?(from, opts)
@ -233,6 +290,7 @@ module Apache
end end
def match?(from, opts = {}) def match?(from, opts = {})
opts[:request_uri] = from
ok = true ok = true
@conditions.each do |c| @conditions.each do |c|
@ -249,6 +307,10 @@ module Apache
def stop_if_match? def stop_if_match?
@input_options[:last] @input_options[:last]
end end
def forbidden?
@input_options[:forbidden]
end
end end
# A permanent RedirectMatch # A permanent RedirectMatch
@ -313,20 +375,26 @@ module Apache
super(from, opts) super(from, opts)
source = replace_placeholders(@from, opts) source = replace_placeholders(@from, opts)
to = @to
reverse = false
if @to[0..0] == '!'
reverse = true
to = @to[1..-1]
end
result = false result = false
case @to[0..0] case to[0..0]
when '!'
result = !source[Regexp.new(@to[1..-1])]
when '-' when '-'
case @to case to
when '-f' when '-f'
result = opts[:files].include? source if opts[:files] result = opts[:files].include? source if opts[:files]
end end
else else
result = source[Regexp.new(@to)] result = source[Regexp.new(to)]
end end
result reverse ? !result : result
end end
end end
end end

View File

@ -26,7 +26,7 @@ describe Apache::Config, "rewrites" do
rule %r{^/$}, '/test' rule %r{^/$}, '/test'
end end
apache.to_a.should == [ apache.to_a.should == [
'RewriteRule "^/$" "/test"', '' '', 'RewriteRule "^/$" "/test"', ''
] ]
end end
end end
@ -46,6 +46,7 @@ describe Apache::RewriteManager, "specific rewrite rules" do
rewrite_test '/fail', '/test' rewrite_test '/fail', '/test'
rewrite_test '/%{REQUEST_FILENAME}', '/test', :request_filename => 'success' rewrite_test '/%{REQUEST_FILENAME}', '/test', :request_filename => 'success'
end.should == [ end.should == [
'',
'RewriteCond "%{REQUEST_FILENAME}" "test"', 'RewriteCond "%{REQUEST_FILENAME}" "test"',
'RewriteRule "^/$" "/test"', 'RewriteRule "^/$" "/test"',
'RedirectMatch permanent "^/success$" "/test"' 'RedirectMatch permanent "^/success$" "/test"'
@ -79,6 +80,7 @@ describe Apache::RewriteRule, "a RewriteRule" do
its(:to_s) { should == 'RewriteRule "^/test$" "/test2" [L,QSA]' } its(:to_s) { should == 'RewriteRule "^/test$" "/test2" [L,QSA]' }
its(:to_a) { should == [ its(:to_a) { should == [
'',
'RewriteCond "/%{REQUEST_FILENAME}" "^/test$"', 'RewriteCond "/%{REQUEST_FILENAME}" "^/test$"',
'RewriteRule "^/test$" "/test2" [L,QSA]' 'RewriteRule "^/test$" "/test2" [L,QSA]'
] } ] }