vhost_generator 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +69 -0
- data/Rakefile +11 -0
- data/bin/vhost-generator +6 -0
- data/features/help.feature +12 -0
- data/features/output-nginx.feature +171 -0
- data/features/step_definitions/dev_steps.rb +3 -0
- data/features/support/env.rb +1 -0
- data/features/version.feature +12 -0
- data/lib/vhost_generator/application.rb +150 -0
- data/lib/vhost_generator/nginx_generator.rb +66 -0
- data/lib/vhost_generator/version.rb +3 -0
- data/lib/vhost_generator/vhost_configuration.rb +108 -0
- data/lib/vhost_generator/vhost_generator_module.rb +18 -0
- data/lib/vhost_generator.rb +6 -0
- data/spec/application_env_spec.rb +29 -0
- data/spec/application_options_spec.rb +31 -0
- data/spec/nginx_generator_spec.rb +61 -0
- data/spec/vhost_configuration_spec.rb +127 -0
- data/vhost_generator.gemspec +28 -0
- metadata +165 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Julien Pervillé
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# VhostGenerator
|
2
|
+
|
3
|
+
This gem outputs a general-purpose VirtualHost configuration file
|
4
|
+
to run your web application behind an nginx or apache frontend.
|
5
|
+
|
6
|
+
The motivation of this gem is to automate that tedious task the first time, but
|
7
|
+
also every time the virtualhost parameters (such as the number of instances to
|
8
|
+
run and the ports where the instances are listening).
|
9
|
+
|
10
|
+
The gem features tries to integrate with the [foreman][1] gem by:
|
11
|
+
* reading configuration parameters from `ENV` (or from the `.env` file if present)
|
12
|
+
* detecting whether to proxy to tcp or unix socket from `Procfile` if present
|
13
|
+
* reading configuration from foreman's standard environment variables to allow
|
14
|
+
for generating a virtualhost that matches the last `foreman export`.
|
15
|
+
|
16
|
+
## Installation
|
17
|
+
|
18
|
+
Add this line to your application's Gemfile:
|
19
|
+
|
20
|
+
gem 'vhost_generator'
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install vhost_generator
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
Basic usage:
|
33
|
+
|
34
|
+
$ bundle exec vhost-generator -l 80 -s myapp.com -p 5000,5001,5002
|
35
|
+
|
36
|
+
Advanced usage: all command-line switches have their equivalent environment variables. See note in `bundle exec vhost-generator --help`.
|
37
|
+
|
38
|
+
$ SERVER_PORTS=80 SERVER_NAMES=myapp.com INSTANCE_PORTS=5000,5001,5002 bundle exec vhost-generator
|
39
|
+
|
40
|
+
Advanced usage for lazy people: environment variables may be saved into the `.env` file or into another file whose name is given in `ENV['DOTENV']`.
|
41
|
+
This last option is nice, as it allows to store the environment in a file and reuse it later to generate the same virtualhost configurations.
|
42
|
+
|
43
|
+
$ echo "SERVER_PORTS=80\nSERVER_NAMES=myapp.com\nINSTANCE_PORTS=5000,5001,5002" >> my.env
|
44
|
+
$ DOTENV=my.env bundle exec vhost-generator
|
45
|
+
|
46
|
+
More advanced usages: see `features/` directory or run:
|
47
|
+
|
48
|
+
$ bundle exec vhost-generator --help
|
49
|
+
|
50
|
+
## Tips
|
51
|
+
|
52
|
+
Protip: pipe with `sudo tee` to save the configuration in your nginx sites-enabled directory.
|
53
|
+
|
54
|
+
$ bundle exec vhost-generator -l 80 -s myapp.com -p 5000,5001,5002 | sudo tee /etc/nginx/sites-enabled/myapp
|
55
|
+
|
56
|
+
Protip: run through `foreman run` to leverage your application's `.env` (DRY and handy when having a configured `RAILS_RELATIVE_URL_ROOT` for example)
|
57
|
+
|
58
|
+
$ echo RAILS_RELATIVE_URL_ROOT='/myapp' >> .env
|
59
|
+
$ bundle exec foreman run vhost-generator -l 80 -s myapp.com -p 5000,5001,5002
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
1. Fork it
|
64
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
66
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
67
|
+
5. Create new Pull Request
|
68
|
+
|
69
|
+
[1]: https://github.com/ddollar/foreman "Foreman"
|
data/Rakefile
ADDED
data/bin/vhost-generator
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Feature: Output help summary
|
2
|
+
|
3
|
+
In order to know how to invoke the program
|
4
|
+
As a user of the library
|
5
|
+
I want to display the program's help summary.
|
6
|
+
|
7
|
+
Scenario: output program help summary
|
8
|
+
When I run `bundle exec vhost-generator --help`
|
9
|
+
Then it should pass with:
|
10
|
+
"""
|
11
|
+
Display this help message.
|
12
|
+
"""
|
@@ -0,0 +1,171 @@
|
|
1
|
+
Feature: Output nginx configuration file
|
2
|
+
|
3
|
+
In order to run my application as an nginx virtualhost
|
4
|
+
As a user of the library
|
5
|
+
I want to output a nginx virtualhost configuration.
|
6
|
+
|
7
|
+
Scenario: using command-line options
|
8
|
+
When I run `bundle exec vhost-generator -g nginx -o upstream=myupstream -f html -l 80,81 -s localhost,my.server -p 5000,5001,5002 -r /myapp`
|
9
|
+
Then the output should match /FILE GENERATED BY.*EDIT AT YOUR OWN RISK/
|
10
|
+
And the output should contain:
|
11
|
+
"""
|
12
|
+
upstream myupstream {
|
13
|
+
server localhost:5000 fail_timeout=0;
|
14
|
+
server localhost:5001 fail_timeout=0;
|
15
|
+
server localhost:5002 fail_timeout=0;
|
16
|
+
}
|
17
|
+
"""
|
18
|
+
And the output should contain:
|
19
|
+
"""
|
20
|
+
server {
|
21
|
+
listen 80;
|
22
|
+
listen 81;
|
23
|
+
"""
|
24
|
+
And the output should contain:
|
25
|
+
"""
|
26
|
+
server_name localhost, my.server;
|
27
|
+
"""
|
28
|
+
And the output should match /root.*html;/
|
29
|
+
And the output should contain:
|
30
|
+
"""
|
31
|
+
try_files $uri/index.html $uri @upstream;
|
32
|
+
location @upstream {
|
33
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
34
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
35
|
+
proxy_set_header Host $http_host;
|
36
|
+
proxy_redirect off;
|
37
|
+
proxy_pass http://myupstream;
|
38
|
+
}
|
39
|
+
"""
|
40
|
+
And the output should contain:
|
41
|
+
"""
|
42
|
+
location /myapp/assets {
|
43
|
+
gzip_static on; # to serve pre-gzipped version
|
44
|
+
expires 60d;
|
45
|
+
add_header Cache-Control public;
|
46
|
+
}
|
47
|
+
"""
|
48
|
+
And the output should contain:
|
49
|
+
"""
|
50
|
+
error_page 500 502 503 504 /500.html;
|
51
|
+
client_max_body_size 4G;
|
52
|
+
keepalive_timeout 10;
|
53
|
+
}
|
54
|
+
"""
|
55
|
+
|
56
|
+
Scenario: using dotenv
|
57
|
+
Given a file named "tmpdir/my.env" with:
|
58
|
+
"""
|
59
|
+
GENERATOR=nginx
|
60
|
+
GENERATOR_OPTIONS=upstream=myupstream
|
61
|
+
STATIC_FOLDER=html
|
62
|
+
SERVER_PORTS=80,81
|
63
|
+
SERVER_NAMES=localhost,my.server
|
64
|
+
INSTANCE_PORTS=5000,5001,5002
|
65
|
+
RAILS_RELATIVE_URL_ROOT=/myapp
|
66
|
+
"""
|
67
|
+
When I cd to "tmpdir"
|
68
|
+
And I set env variable "DOTENV" to "my.env"
|
69
|
+
And I run `bundle exec vhost-generator`
|
70
|
+
Then the output should match /FILE GENERATED BY.*EDIT AT YOUR OWN RISK/
|
71
|
+
And the output should contain:
|
72
|
+
"""
|
73
|
+
upstream myupstream {
|
74
|
+
server localhost:5000 fail_timeout=0;
|
75
|
+
server localhost:5001 fail_timeout=0;
|
76
|
+
server localhost:5002 fail_timeout=0;
|
77
|
+
}
|
78
|
+
"""
|
79
|
+
And the output should contain:
|
80
|
+
"""
|
81
|
+
server {
|
82
|
+
listen 80;
|
83
|
+
listen 81;
|
84
|
+
"""
|
85
|
+
And the output should contain:
|
86
|
+
"""
|
87
|
+
server_name localhost, my.server;
|
88
|
+
"""
|
89
|
+
And the output should match /root.*html;/
|
90
|
+
And the output should contain:
|
91
|
+
"""
|
92
|
+
try_files $uri/index.html $uri @upstream;
|
93
|
+
location @upstream {
|
94
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
95
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
96
|
+
proxy_set_header Host $http_host;
|
97
|
+
proxy_redirect off;
|
98
|
+
proxy_pass http://myupstream;
|
99
|
+
}
|
100
|
+
"""
|
101
|
+
And the output should contain:
|
102
|
+
"""
|
103
|
+
location /myapp/assets {
|
104
|
+
gzip_static on; # to serve pre-gzipped version
|
105
|
+
expires 60d;
|
106
|
+
add_header Cache-Control public;
|
107
|
+
}
|
108
|
+
"""
|
109
|
+
And the output should contain:
|
110
|
+
"""
|
111
|
+
error_page 500 502 503 504 /500.html;
|
112
|
+
client_max_body_size 4G;
|
113
|
+
keepalive_timeout 10;
|
114
|
+
}
|
115
|
+
"""
|
116
|
+
|
117
|
+
Scenario: using environment variables
|
118
|
+
When I set env variable "GENERATOR" to "nginx"
|
119
|
+
And I set env variable "GENERATOR_OPTIONS" to "upstream=myupstream"
|
120
|
+
And I set env variable "STATIC_FOLDER" to "html"
|
121
|
+
And I set env variable "SERVER_PORTS" to "80,81"
|
122
|
+
And I set env variable "SERVER_NAMES" to "localhost,my.server"
|
123
|
+
And I set env variable "INSTANCE_PORTS" to "5000,5001,5002"
|
124
|
+
And I set env variable "RAILS_RELATIVE_URL_ROOT" to "/myapp"
|
125
|
+
And I run `bundle exec vhost-generator`
|
126
|
+
Then the output should match /FILE GENERATED BY.*EDIT AT YOUR OWN RISK/
|
127
|
+
And the output should contain:
|
128
|
+
"""
|
129
|
+
upstream myupstream {
|
130
|
+
server localhost:5000 fail_timeout=0;
|
131
|
+
server localhost:5001 fail_timeout=0;
|
132
|
+
server localhost:5002 fail_timeout=0;
|
133
|
+
}
|
134
|
+
"""
|
135
|
+
And the output should contain:
|
136
|
+
"""
|
137
|
+
server {
|
138
|
+
listen 80;
|
139
|
+
listen 81;
|
140
|
+
"""
|
141
|
+
And the output should contain:
|
142
|
+
"""
|
143
|
+
server_name localhost, my.server;
|
144
|
+
"""
|
145
|
+
And the output should match /root.*html;/
|
146
|
+
And the output should contain:
|
147
|
+
"""
|
148
|
+
try_files $uri/index.html $uri @upstream;
|
149
|
+
location @upstream {
|
150
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
151
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
152
|
+
proxy_set_header Host $http_host;
|
153
|
+
proxy_redirect off;
|
154
|
+
proxy_pass http://myupstream;
|
155
|
+
}
|
156
|
+
"""
|
157
|
+
And the output should contain:
|
158
|
+
"""
|
159
|
+
location /myapp/assets {
|
160
|
+
gzip_static on; # to serve pre-gzipped version
|
161
|
+
expires 60d;
|
162
|
+
add_header Cache-Control public;
|
163
|
+
}
|
164
|
+
"""
|
165
|
+
And the output should contain:
|
166
|
+
"""
|
167
|
+
error_page 500 502 503 504 /500.html;
|
168
|
+
client_max_body_size 4G;
|
169
|
+
keepalive_timeout 10;
|
170
|
+
}
|
171
|
+
"""
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'aruba/cucumber'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Feature: Output program version
|
2
|
+
|
3
|
+
In order to know if I am up to date
|
4
|
+
As a user of the library
|
5
|
+
I want to know the current version of vhost-generator.
|
6
|
+
|
7
|
+
Scenario: output program version
|
8
|
+
When I run `bundle exec vhost-generator --version`
|
9
|
+
Then it should pass with:
|
10
|
+
"""
|
11
|
+
vhost-generator, version 0.1.0
|
12
|
+
"""
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'vhost_generator/version'
|
2
|
+
require 'vhost_generator/vhost_configuration'
|
3
|
+
require 'optparse'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'dotenv'
|
6
|
+
|
7
|
+
module VhostGenerator
|
8
|
+
|
9
|
+
###########################################################################
|
10
|
+
# VhostGenerator main application object. When invoking +vhost-generator+
|
11
|
+
# from the command line, a VhostGenerator::Application object is created
|
12
|
+
# and run.
|
13
|
+
#
|
14
|
+
class Application
|
15
|
+
attr_writer :config
|
16
|
+
|
17
|
+
def initialize(output_stream=$stdout)
|
18
|
+
@name = File.basename($0 || 'vhost-generator')
|
19
|
+
@output_stream = output_stream
|
20
|
+
end
|
21
|
+
|
22
|
+
# Run the VhostGenerator application.
|
23
|
+
def run
|
24
|
+
standard_exception_handling do
|
25
|
+
# load serialized environment variables from DOTENV files if present.
|
26
|
+
dotenvs = ['.env', ENV['DOTENV']]
|
27
|
+
dotenvs.compact.each { |f| Dotenv.load(f) }
|
28
|
+
handle_env(ENV)
|
29
|
+
handle_options(ARGV)
|
30
|
+
config.cmdline << ['cd', Dir.pwd]
|
31
|
+
config.cmdline << [$0] + ARGV
|
32
|
+
@output_stream.puts config.output
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def config(configurator=VhostGenerator::VhostConfiguration)
|
37
|
+
@config ||= configurator.new # XXX
|
38
|
+
end
|
39
|
+
|
40
|
+
def handle_env(env)
|
41
|
+
if path = env['STATIC_FOLDER']
|
42
|
+
config.static_folder = path
|
43
|
+
end
|
44
|
+
if ports = env['SERVER_PORTS']
|
45
|
+
config.server_ports = ports
|
46
|
+
end
|
47
|
+
if names = env['SERVER_NAMES']
|
48
|
+
config.server_names = names
|
49
|
+
end
|
50
|
+
if ports = env['INSTANCE_PORTS']
|
51
|
+
config.instance_ports = ports
|
52
|
+
end
|
53
|
+
if root = env['RAILS_RELATIVE_URL_ROOT']
|
54
|
+
config.relative_root = root
|
55
|
+
end
|
56
|
+
if generator = env['GENERATOR']
|
57
|
+
config.generator = generator
|
58
|
+
end
|
59
|
+
if options = env['GENERATOR_OPTIONS']
|
60
|
+
config.generator_options = options
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def handle_options(argv)
|
65
|
+
OptionParser.new do |opts|
|
66
|
+
opts.banner = "Usage: #{@name} [options]"
|
67
|
+
|
68
|
+
opts.separator ""
|
69
|
+
opts.separator ['Note: all command-line options below also exist as ' \
|
70
|
+
'environment variables.', 'You may try to setenv all ' \
|
71
|
+
'uppercase names in the rest of this summary, eg.',
|
72
|
+
'`export RAILS_RELATIVE_URL_ROOT=/myapp`.'].join($/)
|
73
|
+
|
74
|
+
opts.separator ""
|
75
|
+
opts.separator "Application options:"
|
76
|
+
application_options.each { |args| opts.on(*args) }
|
77
|
+
|
78
|
+
opts.separator ""
|
79
|
+
opts.separator "Generator options:"
|
80
|
+
generator_options.each { |args| opts.on(*args) }
|
81
|
+
|
82
|
+
opts.separator ""
|
83
|
+
|
84
|
+
opts.on_tail("-v", "--version", "Display the program version.") do
|
85
|
+
@output_stream.puts "#{@name}, version #{VhostGenerator::VERSION}"
|
86
|
+
exit(true)
|
87
|
+
end
|
88
|
+
|
89
|
+
opts.on_tail("-h", "--help", "-H", "Display this help message.") do
|
90
|
+
@output_stream.puts opts
|
91
|
+
exit(true)
|
92
|
+
end
|
93
|
+
end.parse(argv)
|
94
|
+
end
|
95
|
+
|
96
|
+
def application_options
|
97
|
+
[
|
98
|
+
['-f', '--static-folder STATIC_FOLDER',
|
99
|
+
%q{Path of your application's static folder (e.g. public/)},
|
100
|
+
lambda { |value| config.static_folder = value }],
|
101
|
+
['-l', '--listen SERVER_PORTS',
|
102
|
+
%q{Public ports to listen on (e.g. 80,81)},
|
103
|
+
lambda { |value| config.server_ports = value }],
|
104
|
+
['-s', '--server-name SERVER_NAMES',
|
105
|
+
%q{Server names to listen on (e.g. localhost,example.com)},
|
106
|
+
lambda { |value| config.server_names = value }],
|
107
|
+
['-p', '--instance-port INSTANCE_PORTS',
|
108
|
+
%q{Internal ports where instances listen on (e.g. 5000,5001)},
|
109
|
+
lambda { |value| config.instance_ports = value }],
|
110
|
+
['-r', '--relative-root RAILS_RELATIVE_URL_ROOT',
|
111
|
+
lambda { |value| config.relative_root = value }],
|
112
|
+
]
|
113
|
+
end
|
114
|
+
|
115
|
+
def generator_options
|
116
|
+
[
|
117
|
+
['-g', '--generator GENERATOR',
|
118
|
+
%q{Generator to use to output virtualhost configuration file},
|
119
|
+
lambda { |value| config.generator = value }],
|
120
|
+
['-o', '--generator-options GENERATOR_OPTIONS',
|
121
|
+
%q{Generator options as comma-separated list of key=value},
|
122
|
+
lambda { |value| config.generator_options = value }],
|
123
|
+
].freeze
|
124
|
+
end
|
125
|
+
|
126
|
+
# Provide standard exception handling for the given block.
|
127
|
+
def standard_exception_handling
|
128
|
+
begin
|
129
|
+
yield
|
130
|
+
rescue SystemExit => ex
|
131
|
+
# Exit silently with current status
|
132
|
+
raise
|
133
|
+
rescue OptionParser::InvalidOption => ex
|
134
|
+
$stderr.puts ex.message
|
135
|
+
exit(false)
|
136
|
+
rescue Exception => ex
|
137
|
+
# Exit with error message
|
138
|
+
display_error_message(ex)
|
139
|
+
exit(false)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Display the error message that caused the exception.
|
144
|
+
def display_error_message(ex)
|
145
|
+
$stderr.puts "#{@name} aborted!"
|
146
|
+
$stderr.puts ex.message
|
147
|
+
$stderr.puts ex.backtrace.join("\n")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module VhostGenerator
|
5
|
+
|
6
|
+
# Nginx VhostGenerator
|
7
|
+
#
|
8
|
+
class NginxGenerator
|
9
|
+
attr_reader :cfg, :options
|
10
|
+
def initialize(cfg, options={})
|
11
|
+
@cfg = cfg
|
12
|
+
@options = OpenStruct.new(default_options.merge(options)).freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
def render
|
16
|
+
template.result(binding)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def default_options
|
22
|
+
Hash[ 'client_max_body_size' => '4G', 'keepalive_timeout' => '10',
|
23
|
+
'assets_expire_in' => '60d', 'upstream' => 'appservers' ].freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def template
|
29
|
+
@template ||= ERB.new <<EOF
|
30
|
+
#### FILE GENERATED BY `<%= String(cfg.cmdline) %>`, EDIT AT YOUR OWN RISK ####
|
31
|
+
|
32
|
+
upstream <%= options.upstream %> {
|
33
|
+
<% cfg.instance_ports.each do |p| %> server localhost:<%= p %> fail_timeout=0;
|
34
|
+
<% end %>}
|
35
|
+
|
36
|
+
server {
|
37
|
+
<% cfg.server_ports.each do |p| %>listen <%= p %>;
|
38
|
+
<% end %>
|
39
|
+
<% unless cfg.server_names.empty? %>server_name <%=
|
40
|
+
cfg.server_names.join(', ') %>;<% end %>
|
41
|
+
|
42
|
+
root <%= cfg.static_folder %>;
|
43
|
+
|
44
|
+
try_files $uri/index.html $uri @upstream;
|
45
|
+
location @upstream {
|
46
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
47
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
48
|
+
proxy_set_header Host $http_host;
|
49
|
+
proxy_redirect off;
|
50
|
+
proxy_pass http://<%= options.upstream %>;
|
51
|
+
}
|
52
|
+
|
53
|
+
location <%= cfg.relative_root %>assets {
|
54
|
+
gzip_static on; # to serve pre-gzipped version
|
55
|
+
expires <%= options.assets_expire_in %>;
|
56
|
+
add_header Cache-Control public;
|
57
|
+
}
|
58
|
+
|
59
|
+
error_page 500 502 503 504 /500.html;
|
60
|
+
client_max_body_size <%= options.client_max_body_size %>;
|
61
|
+
keepalive_timeout <%= options.keepalive_timeout %>;
|
62
|
+
}
|
63
|
+
EOF
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'vhost_generator/nginx_generator'
|
2
|
+
require 'shellwords'
|
3
|
+
|
4
|
+
module VhostGenerator
|
5
|
+
|
6
|
+
# Represents a Shell command line (to display in vhost comments)
|
7
|
+
# TODO: make it a real class with a more narrow interface than Array
|
8
|
+
class ShellCmdLine < Array
|
9
|
+
def to_str
|
10
|
+
parts = self.collect { |cmd| Shellwords.join(cmd) }
|
11
|
+
if parts.length > 1
|
12
|
+
"(" + parts.join(' && ') + ")"
|
13
|
+
else
|
14
|
+
parts.join
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
###########################################################################
|
20
|
+
# VhostConfiguration stores all the configuration values (to read from)
|
21
|
+
# +env+ or +cmdline+ needed to render the configuration template.
|
22
|
+
#
|
23
|
+
class VhostConfiguration
|
24
|
+
attr_reader :static_folder, :server_ports, :server_names,
|
25
|
+
:instance_ports, :relative_root, :cmdline,
|
26
|
+
:generator, :generator_options
|
27
|
+
|
28
|
+
def initialize(static_folder='public', server_ports='80',
|
29
|
+
server_names='localhost', instance_ports='', relative_root='/',
|
30
|
+
cmdlinebuilder=ShellCmdLine, generator='nginx', generator_options='')
|
31
|
+
self.static_folder = static_folder
|
32
|
+
self.server_ports = server_ports
|
33
|
+
self.server_names = server_names
|
34
|
+
self.instance_ports = instance_ports
|
35
|
+
self.relative_root = relative_root
|
36
|
+
self.cmdline = cmdlinebuilder.new
|
37
|
+
self.generator = generator
|
38
|
+
self.generator_options = generator_options
|
39
|
+
end
|
40
|
+
|
41
|
+
def static_folder=(folder)
|
42
|
+
@static_folder = File.expand_path(folder)
|
43
|
+
end
|
44
|
+
|
45
|
+
def server_ports=(ports)
|
46
|
+
@server_ports = parse_integer_list(ports)
|
47
|
+
end
|
48
|
+
|
49
|
+
def server_names=(names)
|
50
|
+
@server_names = parse_word_list(names)
|
51
|
+
end
|
52
|
+
|
53
|
+
def instance_ports=(ports)
|
54
|
+
@instance_ports = parse_integer_list(ports)
|
55
|
+
end
|
56
|
+
|
57
|
+
def relative_root=(root)
|
58
|
+
@relative_root = (String(root) + '/').gsub(%r{/+}, '/')
|
59
|
+
end
|
60
|
+
|
61
|
+
def generator=(name)
|
62
|
+
@generator = generator_for(name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def generator_options=(options)
|
66
|
+
@generator_options = parse_option_list(options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def configure!(parser)
|
70
|
+
parser.parse(self)
|
71
|
+
end
|
72
|
+
|
73
|
+
def output
|
74
|
+
self.generator.new(self, self.generator_options).render
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
attr_writer :cmdline
|
80
|
+
|
81
|
+
def generator_for(name)
|
82
|
+
raise ArgumentError, "unsupported generator: %s, try any of %s." % [
|
83
|
+
name.inspect, registry.keys.inspect
|
84
|
+
] unless registry.has_key?(name)
|
85
|
+
registry[name]
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
attr_writer :registry
|
91
|
+
def registry
|
92
|
+
# XXX use a real registry to reduce coupling
|
93
|
+
@registry ||= {'nginx' => VhostGenerator::NginxGenerator}
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_word_list(s)
|
97
|
+
String(s).split(/[,\s]+/)
|
98
|
+
end
|
99
|
+
|
100
|
+
def parse_option_list(s)
|
101
|
+
Hash[ parse_word_list(s).map { |i| i.split('=', 2) } ]
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse_integer_list(s)
|
105
|
+
parse_word_list(s).map { |i| Integer(i) }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'vhost_generator/application'
|
2
|
+
|
3
|
+
module VhostGenerator
|
4
|
+
|
5
|
+
# VhostGenerator module singleton methods.
|
6
|
+
#
|
7
|
+
class << self
|
8
|
+
# Current VhostGenerator Application
|
9
|
+
def application
|
10
|
+
@application ||= VhostGenerator::Application.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# Set the current VhostGenerator application object.
|
14
|
+
def application=(app)
|
15
|
+
@application = app
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'vhost_generator/application'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
describe VhostGenerator::Application do
|
5
|
+
describe "Env" do
|
6
|
+
let(:config) { OpenStruct.new }
|
7
|
+
before { subject.config = config }
|
8
|
+
|
9
|
+
options = Hash[
|
10
|
+
'static_folder' => 'STATIC_FOLDER',
|
11
|
+
'server_ports' => 'SERVER_PORTS',
|
12
|
+
'server_names' => 'SERVER_NAMES',
|
13
|
+
'instance_ports' => 'INSTANCE_PORTS',
|
14
|
+
'relative_root' => 'RAILS_RELATIVE_URL_ROOT',
|
15
|
+
'generator' => 'GENERATOR',
|
16
|
+
'generator_options' => 'GENERATOR_OPTIONS',
|
17
|
+
]
|
18
|
+
|
19
|
+
options.each_pair do |name, var|
|
20
|
+
describe "#{name} option" do
|
21
|
+
it "is set by the #{var} variable" do
|
22
|
+
expect {
|
23
|
+
subject.handle_env(var => 'value')
|
24
|
+
}.to change(config, name).to('value')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'vhost_generator/application'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
describe VhostGenerator::Application do
|
5
|
+
describe "Options" do
|
6
|
+
let(:config) { OpenStruct.new }
|
7
|
+
before { subject.config = config }
|
8
|
+
|
9
|
+
options = Hash[
|
10
|
+
'static_folder' => %w(-f --static-folder),
|
11
|
+
'server_ports' => %w(-l --listen),
|
12
|
+
'server_names' => %w(-s --server-name),
|
13
|
+
'instance_ports' => %w(-p --instance-port),
|
14
|
+
'relative_root' => %w(-r --relative-root),
|
15
|
+
'generator' => %w(-g --generator),
|
16
|
+
'generator_options' => %w(-o --generator-options)
|
17
|
+
]
|
18
|
+
|
19
|
+
options.each_pair do |name, flags|
|
20
|
+
describe "#{name} option" do
|
21
|
+
flags.each do |flag|
|
22
|
+
it "is set by the #{flag} flag" do
|
23
|
+
expect {
|
24
|
+
subject.handle_options([flag, 'value'])
|
25
|
+
}.to change(config, name).to('value')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'vhost_generator/nginx_generator'
|
2
|
+
|
3
|
+
describe VhostGenerator::NginxGenerator do
|
4
|
+
let(:config) { double('vhost config').as_null_object }
|
5
|
+
subject do
|
6
|
+
described_class.new(config, 'upstream' => 'myupstream')
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#render" do
|
10
|
+
let(:output) { subject.render }
|
11
|
+
|
12
|
+
it "includes the cmdline in a comment" do
|
13
|
+
config.stub(:cmdline).and_return('CMDLINE')
|
14
|
+
expect(output).to match(/^#### FILE GENERATED BY .*CMDLINE/)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "declares the named upstream" do
|
18
|
+
expect(output).to include('upstream myupstream {')
|
19
|
+
end
|
20
|
+
|
21
|
+
it "references the named upstream" do
|
22
|
+
expect(output).to include('http://myupstream;')
|
23
|
+
end
|
24
|
+
|
25
|
+
it "declares all the requested upstream servers" do
|
26
|
+
config.stub(:instance_ports).and_return([1337, 1338])
|
27
|
+
expect(output).to include('server localhost:1337 fail_timeout=0;')
|
28
|
+
expect(output).to include('server localhost:1338 fail_timeout=0;')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "listens to the requested server ports" do
|
32
|
+
config.stub(:server_ports).and_return([12345, 12346])
|
33
|
+
expect(output).to include('listen 12345;')
|
34
|
+
expect(output).to include('listen 12346;')
|
35
|
+
end
|
36
|
+
|
37
|
+
it "declares the server names it responds to" do
|
38
|
+
config.stub(:server_names).and_return(%w(host1 host2))
|
39
|
+
expect(output).to include('server_name host1, host2;')
|
40
|
+
end
|
41
|
+
|
42
|
+
it "declares the requested document root" do
|
43
|
+
config.stub(:static_folder).and_return('STATIC-FOLDER')
|
44
|
+
expect(output).to include('root STATIC-FOLDER;')
|
45
|
+
end
|
46
|
+
|
47
|
+
it "forwards X-Forwarded-For header" do
|
48
|
+
expect(output).to \
|
49
|
+
include('proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;')
|
50
|
+
end
|
51
|
+
|
52
|
+
it "forwards X-Forwarded-Proto header" do
|
53
|
+
expect(output).to include('proxy_set_header X-Forwarded-Proto $scheme;')
|
54
|
+
end
|
55
|
+
|
56
|
+
it "respects custom relative_roots" do
|
57
|
+
config.stub(:relative_root).and_return('RELATIVE_ROOT')
|
58
|
+
expect(output).to include('location RELATIVE_ROOTassets {')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'vhost_generator/vhost_configuration'
|
2
|
+
|
3
|
+
describe VhostGenerator::VhostConfiguration do
|
4
|
+
describe "#static_folder" do
|
5
|
+
it "is 'public/' by default" do
|
6
|
+
expect(subject.static_folder).to eql(File.expand_path('public'))
|
7
|
+
end
|
8
|
+
|
9
|
+
it "expanded" do
|
10
|
+
expect {
|
11
|
+
subject.static_folder = 'html'
|
12
|
+
}.to change(subject, :static_folder).to File.expand_path('html')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#server_ports" do
|
17
|
+
it "is 80 by default" do
|
18
|
+
expect(subject.server_ports).to eql([80])
|
19
|
+
end
|
20
|
+
|
21
|
+
it "parses to Array of Integer" do
|
22
|
+
expect {
|
23
|
+
subject.server_ports = '80,81'
|
24
|
+
}.to change(subject, :server_ports).to [80, 81]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "complains when trying to set invalid values" do
|
28
|
+
expect {
|
29
|
+
subject.server_ports = '80a'
|
30
|
+
}.to raise_error(ArgumentError, /invalid value for Integer/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#server_names" do
|
35
|
+
it "is 'localhost' by default" do
|
36
|
+
expect(subject.server_names).to eql(%w(localhost))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "parses to Array of String" do
|
40
|
+
expect {
|
41
|
+
subject.server_names = 'localhost , test.host'
|
42
|
+
}.to change(subject, :server_names).to %w(localhost test.host)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#instance_ports" do
|
47
|
+
it "is empty by default" do
|
48
|
+
expect(subject.instance_ports).to be_empty
|
49
|
+
end
|
50
|
+
|
51
|
+
it "parses to Array of Integer" do
|
52
|
+
expect {
|
53
|
+
subject.instance_ports = '5000,5001'
|
54
|
+
}.to change(subject, :instance_ports).to [5000, 5001]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "complains when trying to set invalid values" do
|
58
|
+
expect {
|
59
|
+
subject.instance_ports = '5000a'
|
60
|
+
}.to raise_error(ArgumentError, /invalid value for Integer/)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#relative_root" do
|
65
|
+
it "is '/' by default" do
|
66
|
+
expect(subject.relative_root).to eql('/')
|
67
|
+
end
|
68
|
+
|
69
|
+
it "appends '/' at end" do
|
70
|
+
expect {
|
71
|
+
subject.relative_root = '/myapp'
|
72
|
+
}.to change(subject, :relative_root).to '/myapp/'
|
73
|
+
end
|
74
|
+
|
75
|
+
it "strips redundant slashes" do
|
76
|
+
expect {
|
77
|
+
subject.relative_root = '/path//to///myapp////'
|
78
|
+
}.to change(subject, :relative_root).to '/path/to/myapp/'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#cmdline" do
|
83
|
+
it "is empty by default" do
|
84
|
+
subject.cmdline.should be_empty
|
85
|
+
end
|
86
|
+
|
87
|
+
it "can be append to using the shovel operator" do
|
88
|
+
subject.cmdline.should respond_to(:<<)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "can be coerced into string" do
|
92
|
+
subject.cmdline.should respond_to(:to_str)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#generator" do
|
97
|
+
it "is present by default" do
|
98
|
+
expect(subject.generator).to be
|
99
|
+
end
|
100
|
+
|
101
|
+
it "is resolved into a generator plugin" do
|
102
|
+
generator = double('generator')
|
103
|
+
subject.send(:registry).merge!('test' => generator)
|
104
|
+
expect {
|
105
|
+
subject.generator = 'test'
|
106
|
+
}.to change(subject, :generator).to generator
|
107
|
+
end
|
108
|
+
|
109
|
+
it "complains when trying to set invalid values" do
|
110
|
+
expect {
|
111
|
+
subject.generator = 'xyzzy'
|
112
|
+
}.to raise_error(ArgumentError, /unsupported generator/)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#generator_options" do
|
117
|
+
it "is empty by default" do
|
118
|
+
expect(subject.generator_options).to be_empty
|
119
|
+
end
|
120
|
+
|
121
|
+
it "parses to Hash[key=value]" do
|
122
|
+
expect {
|
123
|
+
subject.generator_options = 'k=a=b , l=j'
|
124
|
+
}.to change(subject, :generator_options).to Hash['k' => 'a=b', 'l' => 'j']
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'vhost_generator/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "vhost_generator"
|
8
|
+
gem.version = VhostGenerator::VERSION
|
9
|
+
gem.authors = ["Julien Pervillé"]
|
10
|
+
gem.email = ["julien.perville@mingalar.fr"]
|
11
|
+
gem.description = ['vhost_generator outputs a general-purpose VirtualHost',
|
12
|
+
'configuration file to run your web application behind',
|
13
|
+
'an nginx or apache frontend'].join(' ')
|
14
|
+
gem.summary = ['vhost_generator outputs nginx or apache VirtualHost',
|
15
|
+
'configurations to run your web application'].join(' ')
|
16
|
+
gem.homepage = "https://github.com/mingalar/vhost_generator"
|
17
|
+
|
18
|
+
gem.files = `git ls-files`.split($/)
|
19
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
20
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
21
|
+
gem.require_paths = ["lib"]
|
22
|
+
|
23
|
+
gem.add_runtime_dependency('dotenv', '~> 0.2.0')
|
24
|
+
gem.add_development_dependency('rake', '~> 0.9.2.2')
|
25
|
+
gem.add_development_dependency('cucumber', '~> 1.2.1')
|
26
|
+
gem.add_development_dependency('aruba', '~> 0.4.11')
|
27
|
+
gem.add_development_dependency('rspec', '~> 2.11.0')
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vhost_generator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Julien Pervillé
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: dotenv
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.2.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.2.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.9.2.2
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.9.2.2
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: cucumber
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.2.1
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.2.1
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: aruba
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.4.11
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.4.11
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.11.0
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 2.11.0
|
94
|
+
description: vhost_generator outputs a general-purpose VirtualHost configuration file
|
95
|
+
to run your web application behind an nginx or apache frontend
|
96
|
+
email:
|
97
|
+
- julien.perville@mingalar.fr
|
98
|
+
executables:
|
99
|
+
- vhost-generator
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- .gitignore
|
104
|
+
- Gemfile
|
105
|
+
- LICENSE.txt
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- bin/vhost-generator
|
109
|
+
- features/help.feature
|
110
|
+
- features/output-nginx.feature
|
111
|
+
- features/step_definitions/dev_steps.rb
|
112
|
+
- features/support/env.rb
|
113
|
+
- features/version.feature
|
114
|
+
- lib/vhost_generator.rb
|
115
|
+
- lib/vhost_generator/application.rb
|
116
|
+
- lib/vhost_generator/nginx_generator.rb
|
117
|
+
- lib/vhost_generator/version.rb
|
118
|
+
- lib/vhost_generator/vhost_configuration.rb
|
119
|
+
- lib/vhost_generator/vhost_generator_module.rb
|
120
|
+
- spec/application_env_spec.rb
|
121
|
+
- spec/application_options_spec.rb
|
122
|
+
- spec/nginx_generator_spec.rb
|
123
|
+
- spec/vhost_configuration_spec.rb
|
124
|
+
- vhost_generator.gemspec
|
125
|
+
homepage: https://github.com/mingalar/vhost_generator
|
126
|
+
licenses: []
|
127
|
+
post_install_message:
|
128
|
+
rdoc_options: []
|
129
|
+
require_paths:
|
130
|
+
- lib
|
131
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ! '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
segments:
|
138
|
+
- 0
|
139
|
+
hash: -198369393
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
none: false
|
142
|
+
requirements:
|
143
|
+
- - ! '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
segments:
|
147
|
+
- 0
|
148
|
+
hash: -198369393
|
149
|
+
requirements: []
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 1.8.23
|
152
|
+
signing_key:
|
153
|
+
specification_version: 3
|
154
|
+
summary: vhost_generator outputs nginx or apache VirtualHost configurations to run
|
155
|
+
your web application
|
156
|
+
test_files:
|
157
|
+
- features/help.feature
|
158
|
+
- features/output-nginx.feature
|
159
|
+
- features/step_definitions/dev_steps.rb
|
160
|
+
- features/support/env.rb
|
161
|
+
- features/version.feature
|
162
|
+
- spec/application_env_spec.rb
|
163
|
+
- spec/application_options_spec.rb
|
164
|
+
- spec/nginx_generator_spec.rb
|
165
|
+
- spec/vhost_configuration_spec.rb
|