vhost_generator 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +6 -12
- data/features/output-nginx.feature +0 -61
- data/features/version.feature +1 -1
- data/lib/vhost_generator/application.rb +2 -7
- data/lib/vhost_generator/cmdline_builder.rb +60 -0
- data/lib/vhost_generator/version.rb +1 -1
- data/lib/vhost_generator/vhost_configuration.rb +4 -18
- data/script/cibuild +9 -0
- data/spec/cmdline_builder_spec.rb +106 -0
- data/spec/vhost_configuration_spec.rb +0 -14
- data/vhost_generator.gemspec +1 -2
- metadata +9 -20
data/README.md
CHANGED
@@ -8,10 +8,8 @@ also every time the virtualhost parameters (such as the number of instances to
|
|
8
8
|
run and the ports where the instances are listening).
|
9
9
|
|
10
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
|
12
|
-
|
13
|
-
* reading configuration from foreman's standard environment variables to allow
|
14
|
-
for generating a virtualhost that matches the last `foreman export`.
|
11
|
+
* reading configuration parameters from `ENV` (or from the `.env` file if invoked via `foreman run`)
|
12
|
+
|
15
13
|
|
16
14
|
## Installation
|
17
15
|
|
@@ -37,27 +35,23 @@ Advanced usage: all command-line switches have their equivalent environment vari
|
|
37
35
|
|
38
36
|
$ SERVER_PORTS=80 SERVER_NAMES=myapp.com INSTANCE_PORTS=5000,5001,5002 bundle exec vhost-generator
|
39
37
|
|
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
38
|
More advanced usages: see `features/` directory or run:
|
47
39
|
|
48
40
|
$ bundle exec vhost-generator --help
|
49
41
|
|
50
42
|
## Tips
|
51
43
|
|
52
|
-
|
44
|
+
Pipe with `sudo tee` to save the configuration in your nginx sites-enabled directory.
|
53
45
|
|
54
46
|
$ bundle exec vhost-generator -l 80 -s myapp.com -p 5000,5001,5002 | sudo tee /etc/nginx/sites-enabled/myapp
|
55
47
|
|
56
|
-
|
48
|
+
Run through `foreman run` to leverage your application's `.env` (DRY and handy when having a configured `RAILS_RELATIVE_URL_ROOT` for example).
|
57
49
|
|
58
50
|
$ echo RAILS_RELATIVE_URL_ROOT='/myapp' >> .env
|
59
51
|
$ bundle exec foreman run vhost-generator -l 80 -s myapp.com -p 5000,5001,5002
|
60
52
|
|
53
|
+
Check the comment at top of each virtualhost configuration file for a command-line that can regenerate the file.
|
54
|
+
|
61
55
|
## Contributing
|
62
56
|
|
63
57
|
1. Fork it
|
@@ -53,67 +53,6 @@ Feature: Output nginx configuration file
|
|
53
53
|
}
|
54
54
|
"""
|
55
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
56
|
Scenario: using environment variables
|
118
57
|
When I set env variable "GENERATOR" to "nginx"
|
119
58
|
And I set env variable "GENERATOR_OPTIONS" to "upstream=myupstream"
|
data/features/version.feature
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'vhost_generator/version'
|
2
|
+
require 'vhost_generator/cmdline_builder'
|
2
3
|
require 'vhost_generator/vhost_configuration'
|
3
4
|
require 'optparse'
|
4
|
-
require 'ostruct'
|
5
|
-
require 'dotenv'
|
6
5
|
|
7
6
|
module VhostGenerator
|
8
7
|
|
@@ -22,13 +21,9 @@ module VhostGenerator
|
|
22
21
|
# Run the VhostGenerator application.
|
23
22
|
def run
|
24
23
|
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
24
|
handle_env(ENV)
|
29
25
|
handle_options(ARGV)
|
30
|
-
config.cmdline
|
31
|
-
config.cmdline << [$0] + ARGV
|
26
|
+
config.cmdline = CmdlineBuilder.new(config, Dir.pwd, $0, ENV)
|
32
27
|
@output_stream.puts config.output
|
33
28
|
end
|
34
29
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module VhostGenerator
|
4
|
+
|
5
|
+
# Represents a Shell command line (to display in vhost comments)
|
6
|
+
class CmdlineBuilder
|
7
|
+
attr_writer :config, :cwd, :progname, :env
|
8
|
+
|
9
|
+
def initialize(config, cwd, progname, env)
|
10
|
+
self.config = config
|
11
|
+
self.cwd = cwd
|
12
|
+
self.progname = progname
|
13
|
+
self.env = env
|
14
|
+
end
|
15
|
+
|
16
|
+
def cwd
|
17
|
+
@cwd ? ['cd', @cwd] : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def progname
|
21
|
+
if @progname
|
22
|
+
if @env.keys.grep(/^BUNDLE_/).empty?
|
23
|
+
[@progname]
|
24
|
+
else
|
25
|
+
['bundle', 'exec', File.basename(@progname)]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def progargs
|
31
|
+
args = []
|
32
|
+
args << '-f' << @config.static_folder
|
33
|
+
args << '-l' << @config.server_ports.join(',')
|
34
|
+
args << '-s' << @config.server_names.join(',')
|
35
|
+
args << '-p' << @config.instance_ports.join(',')
|
36
|
+
args << '-r' << @config.relative_root
|
37
|
+
args << '-g' << 'nginx' # FIXME use @config.generator when real registry
|
38
|
+
options = @config.generator_options.collect {|k,v| "#{k}=#{v}" }
|
39
|
+
args << '-o' << options.join(',')
|
40
|
+
args
|
41
|
+
end
|
42
|
+
|
43
|
+
def commands
|
44
|
+
if prog_name = progname
|
45
|
+
[cwd, prog_name + progargs].compact
|
46
|
+
else
|
47
|
+
[]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_str
|
52
|
+
parts = commands.collect { |cmd| Shellwords.shelljoin(cmd) }
|
53
|
+
if parts.length > 1
|
54
|
+
"(#{ parts.join(' && ') })"
|
55
|
+
else
|
56
|
+
parts.first
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -3,37 +3,25 @@ require 'shellwords'
|
|
3
3
|
|
4
4
|
module VhostGenerator
|
5
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
6
|
###########################################################################
|
20
7
|
# VhostConfiguration stores all the configuration values (to read from)
|
21
8
|
# +env+ or +cmdline+ needed to render the configuration template.
|
22
9
|
#
|
23
10
|
class VhostConfiguration
|
24
11
|
attr_reader :static_folder, :server_ports, :server_names,
|
25
|
-
:instance_ports, :relative_root,
|
12
|
+
:instance_ports, :relative_root,
|
26
13
|
:generator, :generator_options
|
14
|
+
attr_accessor :cmdline
|
27
15
|
|
28
16
|
def initialize(static_folder='public', server_ports='80',
|
29
17
|
server_names='localhost', instance_ports='', relative_root='/',
|
30
|
-
|
18
|
+
generator='nginx', generator_options='', cmdline=nil)
|
31
19
|
self.static_folder = static_folder
|
32
20
|
self.server_ports = server_ports
|
33
21
|
self.server_names = server_names
|
34
22
|
self.instance_ports = instance_ports
|
35
23
|
self.relative_root = relative_root
|
36
|
-
self.cmdline =
|
24
|
+
self.cmdline = cmdline # usually set later using attr_writer
|
37
25
|
self.generator = generator
|
38
26
|
self.generator_options = generator_options
|
39
27
|
end
|
@@ -76,8 +64,6 @@ module VhostGenerator
|
|
76
64
|
|
77
65
|
protected
|
78
66
|
|
79
|
-
attr_writer :cmdline
|
80
|
-
|
81
67
|
def generator_for(name)
|
82
68
|
raise ArgumentError, "unsupported generator: %s, try any of %s." % [
|
83
69
|
name.inspect, registry.keys.inspect
|
data/script/cibuild
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'vhost_generator/cmdline_builder'
|
2
|
+
|
3
|
+
describe VhostGenerator::CmdlineBuilder do
|
4
|
+
let(:config) { double('vhost config').as_null_object }
|
5
|
+
subject do
|
6
|
+
described_class.new(config, nil, nil, [])
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#cwd" do
|
10
|
+
context "when a current directory is provided" do
|
11
|
+
it "returns 'cd' followed by the current directory" do
|
12
|
+
subject.cwd = 'CWD'
|
13
|
+
expect(subject.cwd).to eql(['cd', 'CWD'])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when no current directory is provided" do
|
18
|
+
it "is nil" do
|
19
|
+
subject.cwd = nil
|
20
|
+
expect(subject.cwd).to be_nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#progname" do
|
26
|
+
before { subject.progname = '/path/to/progname' }
|
27
|
+
|
28
|
+
context "when no progname is provided" do
|
29
|
+
it "is nil" do
|
30
|
+
subject.progname = nil
|
31
|
+
expect(subject.progname).to be_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when bundler is in environment" do
|
36
|
+
it "returns 'bundle exec' followed by the basename" do
|
37
|
+
subject.env = Hash['BUNDLE_GEMFILE' => true, 'BUNDLE_BIN' => 'true']
|
38
|
+
expect(subject.progname).to eql(['bundle', 'exec', 'progname'])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when bundler is not in environment" do
|
43
|
+
it "returns the full program name" do
|
44
|
+
subject.env = Hash[]
|
45
|
+
expect(subject.progname).to eql(['/path/to/progname'])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#progargs" do
|
51
|
+
it "describes config as commandline switches" do
|
52
|
+
subject.config = mock(:static_folder => 'SF', :server_ports => [80,81],
|
53
|
+
:server_names => %w(A B),
|
54
|
+
:instance_ports => [5000,5001],
|
55
|
+
:relative_root => 'RR', :generator => 'nginx',
|
56
|
+
:generator_options => {'k' => 'a=b', 'l' => 'c'})
|
57
|
+
expect(subject.progargs).to eql(['-f', 'SF', '-l', '80,81', '-s', 'A,B',
|
58
|
+
'-p', '5000,5001', '-r', 'RR',
|
59
|
+
'-g', 'nginx', '-o', 'k=a=b,l=c'])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#commands" do
|
64
|
+
context "when a pwd is present" do
|
65
|
+
it "is same as [#pwd, #progname + #progargs]" do
|
66
|
+
subject.should_receive(:cwd).and_return('CWD')
|
67
|
+
subject.should_receive(:progname).and_return('PROGNAME')
|
68
|
+
subject.should_receive(:progargs).and_return('ARGS')
|
69
|
+
expect(subject.commands).to eql(['CWD', 'PROGNAMEARGS'])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "when no pwd is present" do
|
74
|
+
it "is same as [#progname + #progargs]" do
|
75
|
+
subject.should_receive(:cwd).and_return(nil)
|
76
|
+
subject.should_receive(:progname).and_return('PROGNAME')
|
77
|
+
subject.should_receive(:progargs).and_return('ARGS')
|
78
|
+
expect(subject.commands).to eql(['PROGNAMEARGS'])
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when no progname is present" do
|
83
|
+
it "is empty" do
|
84
|
+
subject.should_receive(:progname).and_return(nil)
|
85
|
+
expect(subject.commands).to be_empty
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#to_str" do
|
91
|
+
let(:cmd1) { %w(cd /path/to/directory) }
|
92
|
+
let(:cmd2) { %w(bundle exec progname -x arg -y arg2) }
|
93
|
+
|
94
|
+
it "is escaped #commands" do
|
95
|
+
subject.should_receive(:commands).and_return([cmd2])
|
96
|
+
cmdline = "bundle exec progname -x arg -y arg2"
|
97
|
+
expect(subject.to_str).to eql(cmdline)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "is escaped #commands joined by && & parenthesis" do
|
101
|
+
subject.should_receive(:commands).and_return([cmd1, cmd2])
|
102
|
+
cmdline = "(cd /path/to/directory && bundle exec progname -x arg -y arg2)"
|
103
|
+
expect(subject.to_str).to eql(cmdline)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -79,20 +79,6 @@ describe VhostGenerator::VhostConfiguration do
|
|
79
79
|
end
|
80
80
|
end
|
81
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
82
|
describe "#generator" do
|
97
83
|
it "is present by default" do
|
98
84
|
expect(subject.generator).to be
|
data/vhost_generator.gemspec
CHANGED
@@ -17,10 +17,9 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.files = `git ls-files`.split($/)
|
19
19
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
20
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features|script)/})
|
21
21
|
gem.require_paths = ["lib"]
|
22
22
|
|
23
|
-
gem.add_runtime_dependency('dotenv', '~> 0.2.0')
|
24
23
|
gem.add_development_dependency('rake', '~> 0.9.2.2')
|
25
24
|
gem.add_development_dependency('cucumber', '~> 1.2.1')
|
26
25
|
gem.add_development_dependency('aruba', '~> 0.4.11')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vhost_generator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,24 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-01 00:00:00.000000000 Z
|
13
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
14
|
- !ruby/object:Gem::Dependency
|
31
15
|
name: rake
|
32
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,12 +97,15 @@ files:
|
|
113
97
|
- features/version.feature
|
114
98
|
- lib/vhost_generator.rb
|
115
99
|
- lib/vhost_generator/application.rb
|
100
|
+
- lib/vhost_generator/cmdline_builder.rb
|
116
101
|
- lib/vhost_generator/nginx_generator.rb
|
117
102
|
- lib/vhost_generator/version.rb
|
118
103
|
- lib/vhost_generator/vhost_configuration.rb
|
119
104
|
- lib/vhost_generator/vhost_generator_module.rb
|
105
|
+
- script/cibuild
|
120
106
|
- spec/application_env_spec.rb
|
121
107
|
- spec/application_options_spec.rb
|
108
|
+
- spec/cmdline_builder_spec.rb
|
122
109
|
- spec/nginx_generator_spec.rb
|
123
110
|
- spec/vhost_configuration_spec.rb
|
124
111
|
- vhost_generator.gemspec
|
@@ -136,7 +123,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
123
|
version: '0'
|
137
124
|
segments:
|
138
125
|
- 0
|
139
|
-
hash: -
|
126
|
+
hash: -418120369
|
140
127
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
128
|
none: false
|
142
129
|
requirements:
|
@@ -145,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
132
|
version: '0'
|
146
133
|
segments:
|
147
134
|
- 0
|
148
|
-
hash: -
|
135
|
+
hash: -418120369
|
149
136
|
requirements: []
|
150
137
|
rubyforge_project:
|
151
138
|
rubygems_version: 1.8.23
|
@@ -159,7 +146,9 @@ test_files:
|
|
159
146
|
- features/step_definitions/dev_steps.rb
|
160
147
|
- features/support/env.rb
|
161
148
|
- features/version.feature
|
149
|
+
- script/cibuild
|
162
150
|
- spec/application_env_spec.rb
|
163
151
|
- spec/application_options_spec.rb
|
152
|
+
- spec/cmdline_builder_spec.rb
|
164
153
|
- spec/nginx_generator_spec.rb
|
165
154
|
- spec/vhost_configuration_spec.rb
|