hostess 0.1.2 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -6
- data/Rakefile +11 -6
- data/bin/hostess +1 -139
- data/lib/hostess/options.rb +40 -0
- data/lib/hostess/virtual_host.rb +104 -0
- data/lib/hostess.rb +49 -0
- metadata +23 -6
data/README.md
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
Hostess
|
2
|
-
=======
|
1
|
+
# Hostess
|
3
2
|
|
4
3
|
A simple tool for adding local directories as virtual hosts in a local apache installation. It probably only works well on a Mac, but we're scratching our own itch here.
|
5
4
|
|
6
|
-
Usage
|
7
|
-
-----
|
5
|
+
## Usage
|
8
6
|
|
9
|
-
$
|
7
|
+
$ hostess create mysite.local /Users/myuser/Sites/mysite
|
10
8
|
|
11
9
|
This will create a new virtual host in your Apache configuration, setup your Mac's DNS to respond to that domain name, and restart Apache to make the new virtual host live.
|
12
10
|
|
@@ -16,4 +14,3 @@ This will create a new virtual host in your Apache configuration, setup your Mac
|
|
16
14
|
hostess delete domain - delete a virtual host
|
17
15
|
hostess list - list hostess virtual hosts
|
18
16
|
hostess help - this info
|
19
|
-
|
data/Rakefile
CHANGED
@@ -2,10 +2,15 @@ require "rubygems"
|
|
2
2
|
require "rake/gempackagetask"
|
3
3
|
require "rake/rdoctask"
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
require "rake/testtask"
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.libs << "test"
|
8
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
9
|
+
t.verbose = true
|
7
10
|
end
|
8
11
|
|
12
|
+
task :default => ["test"]
|
13
|
+
|
9
14
|
# This builds the actual gem. For details of what all these options
|
10
15
|
# mean, and other ones you can add, check the documentation here:
|
11
16
|
#
|
@@ -15,7 +20,7 @@ spec = Gem::Specification.new do |s|
|
|
15
20
|
|
16
21
|
# Change these as appropriate
|
17
22
|
s.name = "hostess"
|
18
|
-
s.version = "0.1.
|
23
|
+
s.version = "0.1.6"
|
19
24
|
s.summary = "Manage simple apache virtual hosts"
|
20
25
|
s.author = "Chris Roos, James Adam"
|
21
26
|
s.email = "chris@chrisroos.co.uk"
|
@@ -28,10 +33,10 @@ spec = Gem::Specification.new do |s|
|
|
28
33
|
s.extra_rdoc_files = %w(README.md)
|
29
34
|
s.rdoc_options = %w(--main README.md)
|
30
35
|
|
31
|
-
s.require_paths = ['bin']
|
36
|
+
s.require_paths = ['bin', 'lib']
|
32
37
|
|
33
38
|
# Add any extra files to include in the gem (like your README)
|
34
|
-
s.files = %w(README.md Rakefile) + Dir.glob("{bin}/**/*")
|
39
|
+
s.files = %w(README.md Rakefile) + Dir.glob("{bin}/**/*") + Dir.glob("{lib}/**/*")
|
35
40
|
s.executables = FileList["bin/**"].map { |f| File.basename(f) }
|
36
41
|
|
37
42
|
# If you want to depend on other gems, add them here, along with any
|
@@ -39,7 +44,7 @@ spec = Gem::Specification.new do |s|
|
|
39
44
|
# s.add_dependency("some_other_gem", "~> 0.1.0")
|
40
45
|
|
41
46
|
# If your tests use any gems, include them here
|
42
|
-
|
47
|
+
s.add_development_dependency("mocha")
|
43
48
|
|
44
49
|
# If you want to publish automatically to rubyforge, you'll may need
|
45
50
|
# to tweak this, and the publishing task below too.
|
data/bin/hostess
CHANGED
@@ -1,144 +1,6 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'fileutils'
|
5
|
-
require 'pathname'
|
6
|
-
|
7
|
-
module Hostess
|
8
|
-
SCRIPT = File.basename($0)
|
9
|
-
APACHE_CONFIG_DIR = Pathname.new('/') + 'etc' + 'apache2'
|
10
|
-
APACHE_CONFIG = APACHE_CONFIG_DIR + 'httpd.conf'
|
11
|
-
VHOSTS_DIR = APACHE_CONFIG_DIR + "#{SCRIPT}_vhosts"
|
12
|
-
class Options
|
13
|
-
attr_reader :action, :domain, :directory
|
14
|
-
def initialize(action=nil, domain=nil, directory=nil)
|
15
|
-
@action, @domain, @directory = action, domain, directory
|
16
|
-
end
|
17
|
-
def directory
|
18
|
-
File.expand_path(@directory) if @directory
|
19
|
-
end
|
20
|
-
def display_banner_and_return
|
21
|
-
puts banner
|
22
|
-
exit
|
23
|
-
end
|
24
|
-
def valid?
|
25
|
-
valid_create? or valid_delete? or valid_list? or valid_help?
|
26
|
-
end
|
27
|
-
private
|
28
|
-
def valid_create?
|
29
|
-
@action == 'create' and domain and directory
|
30
|
-
end
|
31
|
-
def valid_delete?
|
32
|
-
@action == 'delete' and domain
|
33
|
-
end
|
34
|
-
def valid_list?
|
35
|
-
@action == 'list'
|
36
|
-
end
|
37
|
-
def valid_help?
|
38
|
-
@action == 'help'
|
39
|
-
end
|
40
|
-
def banner
|
41
|
-
<<EndBanner
|
42
|
-
Usage:
|
43
|
-
#{SCRIPT} create domain directory - create a new virtual host
|
44
|
-
#{SCRIPT} delete domain - delete a virtual host
|
45
|
-
#{SCRIPT} list - list #{SCRIPT} virtual hosts
|
46
|
-
#{SCRIPT} help - this info
|
47
|
-
EndBanner
|
48
|
-
end
|
49
|
-
end
|
50
|
-
class VirtualHost
|
51
|
-
def initialize(options)
|
52
|
-
@options = options
|
53
|
-
end
|
54
|
-
def execute!
|
55
|
-
__send__(@options.action)
|
56
|
-
end
|
57
|
-
def create
|
58
|
-
warn_and_return unless sudoer?
|
59
|
-
setup_apache_config
|
60
|
-
create_vhost_directory
|
61
|
-
create_apache_log_directory
|
62
|
-
system "dscl localhost -create /Local/Default/Hosts/#{@options.domain} IPAddress 127.0.0.1"
|
63
|
-
File.open(config_filename, 'w') { |f| f.puts(vhost_config) }
|
64
|
-
restart_apache
|
65
|
-
end
|
66
|
-
def delete
|
67
|
-
warn_and_return unless sudoer?
|
68
|
-
system "dscl localhost -delete /Local/Default/Hosts/#{@options.domain}"
|
69
|
-
File.delete(config_filename)
|
70
|
-
restart_apache
|
71
|
-
end
|
72
|
-
def list
|
73
|
-
Dir[File.join(VHOSTS_DIR, '*.conf')].each do |config_file|
|
74
|
-
puts File.basename(config_file, '.conf')
|
75
|
-
end
|
76
|
-
end
|
77
|
-
def help
|
78
|
-
@options.display_banner_and_return
|
79
|
-
end
|
80
|
-
private
|
81
|
-
def apache_log_directory
|
82
|
-
File.expand_path(File.join('~', "." + SCRIPT, 'log', @options.domain))
|
83
|
-
end
|
84
|
-
def create_apache_log_directory
|
85
|
-
FileUtils.mkdir_p(apache_log_directory)
|
86
|
-
end
|
87
|
-
def warn_and_return
|
88
|
-
puts "Please use sudo to use this utility to create or delete virtual hosts"
|
89
|
-
exit
|
90
|
-
end
|
91
|
-
def sudoer?
|
92
|
-
# A proxy for actually knowing whether or not the user has all required privileges
|
93
|
-
File.stat(APACHE_CONFIG).writable?
|
94
|
-
end
|
95
|
-
def vhost_config
|
96
|
-
domain, directory = @options.domain, @options.directory
|
97
|
-
template = <<-EOT
|
98
|
-
<VirtualHost *:80>
|
99
|
-
ServerName <%= domain %>
|
100
|
-
DocumentRoot <%= directory %>
|
101
|
-
<Directory <%= directory %>>
|
102
|
-
Options FollowSymLinks
|
103
|
-
AllowOverride All
|
104
|
-
allow from all
|
105
|
-
</Directory>
|
106
|
-
<DirectoryMatch "^/.*/\.svn/">
|
107
|
-
ErrorDocument 403 /404.html
|
108
|
-
Order allow,deny
|
109
|
-
Deny from all
|
110
|
-
Satisfy All
|
111
|
-
</DirectoryMatch>
|
112
|
-
ErrorLog <%= File.join(apache_log_directory, 'error_log') %>
|
113
|
-
CustomLog <%= File.join(apache_log_directory, 'access_log') %> common
|
114
|
-
#RewriteLogLevel 3
|
115
|
-
RewriteLog <%= File.join(apache_log_directory, 'rewrite_log') %>
|
116
|
-
</VirtualHost>
|
117
|
-
EOT
|
118
|
-
ERB.new(template).result(binding)
|
119
|
-
end
|
120
|
-
def config_filename
|
121
|
-
File.join(VHOSTS_DIR, "#{@options.domain}.conf")
|
122
|
-
end
|
123
|
-
def setup_apache_config
|
124
|
-
unless File.read(APACHE_CONFIG).include?("Include #{File.join(VHOSTS_DIR, '*.conf')}")
|
125
|
-
File.open(APACHE_CONFIG, 'a') do |file|
|
126
|
-
file.puts ""
|
127
|
-
file.puts ""
|
128
|
-
file.puts "# Line added by #{SCRIPT}"
|
129
|
-
file.puts "NameVirtualHost *:80"
|
130
|
-
file.puts "Include #{File.join(VHOSTS_DIR, '*.conf')}"
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
def create_vhost_directory
|
135
|
-
FileUtils.mkdir_p(VHOSTS_DIR)
|
136
|
-
end
|
137
|
-
def restart_apache
|
138
|
-
`apachectl restart`
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
3
|
+
require 'hostess'
|
142
4
|
|
143
5
|
options = Hostess::Options.new(*ARGV)
|
144
6
|
options.display_banner_and_return unless options.valid?
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Hostess
|
2
|
+
class Options
|
3
|
+
attr_reader :action, :domain, :directory
|
4
|
+
def initialize(action=nil, domain=nil, directory=nil)
|
5
|
+
@action, @domain, @directory = action, domain, directory
|
6
|
+
end
|
7
|
+
def directory
|
8
|
+
File.expand_path(@directory) if @directory
|
9
|
+
end
|
10
|
+
def display_banner_and_return
|
11
|
+
puts banner
|
12
|
+
exit
|
13
|
+
end
|
14
|
+
def valid?
|
15
|
+
valid_create? or valid_delete? or valid_list? or valid_help?
|
16
|
+
end
|
17
|
+
private
|
18
|
+
def valid_create?
|
19
|
+
@action == 'create' and domain and directory
|
20
|
+
end
|
21
|
+
def valid_delete?
|
22
|
+
@action == 'delete' and domain
|
23
|
+
end
|
24
|
+
def valid_list?
|
25
|
+
@action == 'list'
|
26
|
+
end
|
27
|
+
def valid_help?
|
28
|
+
@action == 'help'
|
29
|
+
end
|
30
|
+
def banner
|
31
|
+
<<EndBanner
|
32
|
+
Usage:
|
33
|
+
#{Hostess.script_name} create domain directory - create a new virtual host
|
34
|
+
#{Hostess.script_name} delete domain - delete a virtual host
|
35
|
+
#{Hostess.script_name} list - list #{Hostess.script_name} virtual hosts
|
36
|
+
#{Hostess.script_name} help - this info
|
37
|
+
EndBanner
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Hostess
|
2
|
+
class VirtualHost
|
3
|
+
def initialize(options, debug=false)
|
4
|
+
@options, @debug = options, debug
|
5
|
+
end
|
6
|
+
def execute!
|
7
|
+
__send__(@options.action)
|
8
|
+
end
|
9
|
+
def create
|
10
|
+
setup_apache_config
|
11
|
+
create_vhost_directory
|
12
|
+
create_apache_log_directory
|
13
|
+
create_dns_entry
|
14
|
+
create_vhost
|
15
|
+
restart_apache
|
16
|
+
end
|
17
|
+
def delete
|
18
|
+
delete_dns_entry
|
19
|
+
delete_vhost
|
20
|
+
restart_apache
|
21
|
+
end
|
22
|
+
def list
|
23
|
+
Dir[File.join(Hostess.vhosts_dir, '*.conf')].each do |config_file|
|
24
|
+
puts File.basename(config_file, '.conf')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
def help
|
28
|
+
@options.display_banner_and_return
|
29
|
+
end
|
30
|
+
private
|
31
|
+
def create_dns_entry
|
32
|
+
run "dscl localhost -create /Local/Default/Hosts/#{@options.domain} IPAddress 127.0.0.1"
|
33
|
+
end
|
34
|
+
def delete_dns_entry
|
35
|
+
run "dscl localhost -delete /Local/Default/Hosts/#{@options.domain}"
|
36
|
+
end
|
37
|
+
def create_vhost
|
38
|
+
tempfile = Tempfile.new('vhost')
|
39
|
+
tempfile.puts(vhost_config)
|
40
|
+
tempfile.close
|
41
|
+
run "mv #{tempfile.path} #{config_filename}"
|
42
|
+
end
|
43
|
+
def delete_vhost
|
44
|
+
run "rm #{config_filename}"
|
45
|
+
end
|
46
|
+
def apache_log_directory
|
47
|
+
File.join(Hostess.vhosts_log_dir, @options.domain)
|
48
|
+
end
|
49
|
+
def create_apache_log_directory
|
50
|
+
run "mkdir -p #{apache_log_directory}"
|
51
|
+
end
|
52
|
+
def vhost_config
|
53
|
+
domain, directory = @options.domain, @options.directory
|
54
|
+
template = <<-EOT
|
55
|
+
<VirtualHost *:80>
|
56
|
+
ServerName <%= domain %>
|
57
|
+
DocumentRoot <%= directory %>
|
58
|
+
<Directory <%= directory %>>
|
59
|
+
Options FollowSymLinks
|
60
|
+
AllowOverride All
|
61
|
+
allow from all
|
62
|
+
</Directory>
|
63
|
+
<DirectoryMatch "^/.*/\.svn/">
|
64
|
+
ErrorDocument 403 /404.html
|
65
|
+
Order allow,deny
|
66
|
+
Deny from all
|
67
|
+
Satisfy All
|
68
|
+
</DirectoryMatch>
|
69
|
+
ErrorLog <%= File.join(apache_log_directory, 'error_log') %>
|
70
|
+
CustomLog <%= File.join(apache_log_directory, 'access_log') %> common
|
71
|
+
#RewriteLogLevel 3
|
72
|
+
RewriteLog <%= File.join(apache_log_directory, 'rewrite_log') %>
|
73
|
+
</VirtualHost>
|
74
|
+
EOT
|
75
|
+
ERB.new(template).result(binding)
|
76
|
+
end
|
77
|
+
def config_filename
|
78
|
+
File.join(Hostess.vhosts_dir, "#{@options.domain}.conf")
|
79
|
+
end
|
80
|
+
def setup_apache_config
|
81
|
+
unless File.read(Hostess.apache_config).include?("Include #{File.join(Hostess.vhosts_dir, '*.conf')}")
|
82
|
+
run "echo '' >> #{Hostess.apache_config}"
|
83
|
+
run "echo '' >> #{Hostess.apache_config}"
|
84
|
+
run "echo '# Line added by #{Hostess.script_name}' >> #{Hostess.apache_config}"
|
85
|
+
run "echo 'NameVirtualHost *:80' >> #{Hostess.apache_config}"
|
86
|
+
run "echo 'Include #{File.join(Hostess.vhosts_dir, '*.conf')}' >> #{Hostess.apache_config}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
def create_vhost_directory
|
90
|
+
run "mkdir -p #{Hostess.vhosts_dir}"
|
91
|
+
end
|
92
|
+
def restart_apache
|
93
|
+
run "apachectl restart"
|
94
|
+
end
|
95
|
+
def run(cmd)
|
96
|
+
cmd = sudo(cmd) if Hostess.use_sudo?
|
97
|
+
puts cmd if @debug
|
98
|
+
system cmd
|
99
|
+
end
|
100
|
+
def sudo(cmd)
|
101
|
+
"sudo -s \"#{cmd}\""
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/hostess.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pathname'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module Hostess
|
7
|
+
|
8
|
+
autoload :Options, 'hostess/options'
|
9
|
+
autoload :VirtualHost, 'hostess/virtual_host'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
attr_writer :apache_config_dir, :apache_log_dir
|
14
|
+
|
15
|
+
def script_name
|
16
|
+
'hostess'
|
17
|
+
end
|
18
|
+
|
19
|
+
def apache_config_dir
|
20
|
+
@apache_config_dir || File.join('/', 'etc', 'apache2')
|
21
|
+
end
|
22
|
+
|
23
|
+
def apache_config
|
24
|
+
File.join(apache_config_dir, 'httpd.conf')
|
25
|
+
end
|
26
|
+
|
27
|
+
def vhosts_dir
|
28
|
+
File.join(apache_config_dir, "#{script_name}_vhosts")
|
29
|
+
end
|
30
|
+
|
31
|
+
def apache_log_dir
|
32
|
+
@apache_log_dir || File.join('/', 'var', 'log', 'apache2')
|
33
|
+
end
|
34
|
+
|
35
|
+
def vhosts_log_dir
|
36
|
+
File.join(apache_log_dir, "#{script_name}_vhosts")
|
37
|
+
end
|
38
|
+
|
39
|
+
def disable_sudo!
|
40
|
+
@disable_sudo = true
|
41
|
+
end
|
42
|
+
|
43
|
+
def use_sudo?
|
44
|
+
@disable_sudo ? false : true
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hostess
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 6
|
10
|
+
version: 0.1.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Chris Roos, James Adam
|
@@ -15,10 +15,23 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-26 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: mocha
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
22
35
|
description:
|
23
36
|
email: chris@chrisroos.co.uk
|
24
37
|
executables:
|
@@ -31,6 +44,9 @@ files:
|
|
31
44
|
- README.md
|
32
45
|
- Rakefile
|
33
46
|
- bin/hostess
|
47
|
+
- lib/hostess/options.rb
|
48
|
+
- lib/hostess/virtual_host.rb
|
49
|
+
- lib/hostess.rb
|
34
50
|
has_rdoc: false
|
35
51
|
homepage: http://chrisroos.co.uk
|
36
52
|
licenses: []
|
@@ -41,6 +57,7 @@ rdoc_options:
|
|
41
57
|
- README.md
|
42
58
|
require_paths:
|
43
59
|
- bin
|
60
|
+
- lib
|
44
61
|
required_ruby_version: !ruby/object:Gem::Requirement
|
45
62
|
none: false
|
46
63
|
requirements:
|