invoker 1.4.1 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.rubocop.yml +0 -1
- data/.travis.yml +4 -2
- data/Dockerfile +7 -0
- data/Gemfile +3 -0
- data/Rakefile +8 -0
- data/examples/hello_sinatra.rb +26 -0
- data/examples/sample.ini +3 -0
- data/invoker.gemspec +2 -1
- data/lib/invoker.rb +20 -3
- data/lib/invoker/cli.rb +32 -6
- data/lib/invoker/dns_cache.rb +2 -2
- data/lib/invoker/ipc/add_http_command.rb +1 -1
- data/lib/invoker/ipc/dns_check_command.rb +2 -1
- data/lib/invoker/ipc/message.rb +2 -2
- data/lib/invoker/parsers/config.rb +4 -1
- data/lib/invoker/power/balancer.rb +16 -4
- data/lib/invoker/power/config.rb +3 -2
- data/lib/invoker/power/dns.rb +1 -1
- data/lib/invoker/power/pf_migrate.rb +1 -1
- data/lib/invoker/power/setup.rb +43 -4
- data/lib/invoker/power/setup/distro/arch.rb +1 -4
- data/lib/invoker/power/setup/distro/base.rb +23 -21
- data/lib/invoker/power/setup/distro/debian.rb +1 -1
- data/lib/invoker/power/setup/distro/opensuse.rb +11 -0
- data/lib/invoker/power/setup/distro/redhat.rb +1 -7
- data/lib/invoker/power/setup/files/invoker_forwarder.sh.erb +17 -0
- data/lib/invoker/power/setup/files/socat_invoker.service +12 -0
- data/lib/invoker/power/setup/linux_setup.rb +46 -29
- data/lib/invoker/power/setup/osx_setup.rb +16 -28
- data/lib/invoker/power/url_rewriter.rb +6 -3
- data/lib/invoker/process_manager.rb +13 -7
- data/lib/invoker/version.rb +1 -1
- data/readme.md +4 -4
- data/spec/invoker/commander_spec.rb +19 -8
- data/spec/invoker/config_spec.rb +22 -27
- data/spec/invoker/invoker_spec.rb +2 -1
- data/spec/invoker/ipc/client_handler_spec.rb +11 -1
- data/spec/invoker/power/config_spec.rb +2 -1
- data/spec/invoker/power/pf_migrate_spec.rb +7 -0
- data/spec/invoker/power/setup/linux_setup_spec.rb +57 -9
- data/spec/invoker/power/setup/osx_setup_spec.rb +22 -8
- data/spec/invoker/power/url_rewriter_spec.rb +33 -1
- data/spec/invoker/power/web_sockets_spec.rb +61 -0
- data/spec/invoker/process_manager_spec.rb +34 -2
- data/spec/spec_helper.rb +12 -16
- metadata +27 -35
- data/spec/support/mock_setup_file.rb +0 -64
data/spec/invoker/config_spec.rb
CHANGED
@@ -134,59 +134,53 @@ command = ls
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
-
describe "loading power config" do
|
137
|
+
describe "loading power config", fakefs: true do
|
138
138
|
before do
|
139
|
-
|
139
|
+
FileUtils.mkdir_p('/tmp')
|
140
|
+
FileUtils.mkdir_p(inv_conf_dir)
|
141
|
+
File.open("/tmp/foo.ini", "w") { |fl| fl.write("") }
|
140
142
|
end
|
141
143
|
|
142
144
|
it "does not load config if platform is darwin but there is no power config file" do
|
143
145
|
Invoker::Power::Config.expects(:load_config).never
|
144
|
-
Invoker::Parsers::Config.new(
|
146
|
+
Invoker::Parsers::Config.new("/tmp/foo.ini", 9000)
|
145
147
|
end
|
146
148
|
|
147
149
|
it "loads config if platform is darwin and power config file exists" do
|
148
150
|
File.open(Invoker::Power::Config.config_file, "w") { |fl| fl.puts "sample" }
|
149
151
|
Invoker::Power::Config.expects(:load_config).once
|
150
|
-
Invoker::Parsers::Config.new(
|
152
|
+
Invoker::Parsers::Config.new("/tmp/foo.ini", 9000)
|
151
153
|
end
|
152
154
|
end
|
153
155
|
|
154
156
|
describe "Procfile" do
|
155
157
|
it "should load Procfiles and create config object" do
|
156
|
-
|
157
|
-
|
158
|
-
fl.write <<-EOD
|
158
|
+
File.open("/tmp/Procfile", "w") {|fl|
|
159
|
+
fl.write <<-EOD
|
159
160
|
web: bundle exec rails s -p $PORT
|
160
161
|
EOD
|
161
|
-
|
162
|
-
|
163
|
-
|
162
|
+
}
|
163
|
+
config = Invoker::Parsers::Config.new("/tmp/Procfile", 9000)
|
164
|
+
command1 = config.processes.first
|
164
165
|
|
165
|
-
|
166
|
-
|
167
|
-
ensure
|
168
|
-
File.delete("/tmp/Procfile")
|
169
|
-
end
|
166
|
+
expect(command1.port).to eq(9000)
|
167
|
+
expect(command1.cmd).to match(/bundle exec rails/)
|
170
168
|
end
|
171
169
|
end
|
172
170
|
|
173
171
|
describe "Copy of DNS information" do
|
174
172
|
it "should allow copy of DNS information" do
|
175
|
-
|
176
|
-
|
177
|
-
fl.write <<-EOD
|
173
|
+
File.open("/tmp/Procfile", "w") {|fl|
|
174
|
+
fl.write <<-EOD
|
178
175
|
web: bundle exec rails s -p $PORT
|
179
176
|
EOD
|
180
|
-
|
181
|
-
|
182
|
-
|
177
|
+
}
|
178
|
+
Invoker.load_invoker_config("/tmp/Procfile", 9000)
|
179
|
+
dns_cache = Invoker::DNSCache.new(Invoker.config)
|
183
180
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
ensure
|
188
|
-
File.delete("/tmp/Procfile")
|
189
|
-
end
|
181
|
+
expect(dns_cache.dns_data).to_not be_empty
|
182
|
+
expect(dns_cache.dns_data['web']).to_not be_empty
|
183
|
+
expect(dns_cache.dns_data['web']['port']).to eql 9000
|
190
184
|
end
|
191
185
|
end
|
192
186
|
|
@@ -227,6 +221,7 @@ command = bundle exec rails s -p $PORT
|
|
227
221
|
describe "global config file" do
|
228
222
|
it "should use global config file if available" do
|
229
223
|
begin
|
224
|
+
FileUtils.mkdir_p(Invoker::Power::Config.config_dir)
|
230
225
|
filename = "#{Invoker::Power::Config.config_dir}/foo.ini"
|
231
226
|
file = File.open(filename, "w")
|
232
227
|
config_data =<<-EOD
|
@@ -13,7 +13,8 @@ describe "Invoker" do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe "#can_run_balancer?" do
|
16
|
+
describe "#can_run_balancer?", fakefs: true do
|
17
|
+
before { FileUtils.mkdir_p(Invoker::Power::Config.config_dir) }
|
17
18
|
it "should return false if setup command was not run" do
|
18
19
|
expect(Invoker.can_run_balancer?).to be_falsey
|
19
20
|
end
|
@@ -35,7 +35,17 @@ describe Invoker::IPC::ClientHandler do
|
|
35
35
|
describe "add_http command" do
|
36
36
|
let(:message_object) { MM::AddHttp.new(process_name: 'foo', port: 9000)}
|
37
37
|
it "adds the process name and port to dns cache" do
|
38
|
-
invoker_dns_cache.expects(:add).with('foo', 9000)
|
38
|
+
invoker_dns_cache.expects(:add).with('foo', 9000, nil)
|
39
|
+
client_socket.string = message_object.encoded_message
|
40
|
+
|
41
|
+
client.read_and_execute
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "add_http command with optional ip" do
|
46
|
+
let(:message_object) { MM::AddHttp.new(process_name: 'foo', port: 9000, ip: '192.168.0.1')}
|
47
|
+
it "adds the process name, port and host ip to dns cache" do
|
48
|
+
invoker_dns_cache.expects(:add).with('foo', 9000, '192.168.0.1')
|
39
49
|
client_socket.string = message_object.encoded_message
|
40
50
|
|
41
51
|
client.read_and_execute
|
@@ -1,8 +1,9 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe "Invoker Power configuration" do
|
3
|
+
describe "Invoker Power configuration", fakefs: true do
|
4
4
|
describe "#create" do
|
5
5
|
it "should create a config file given a hash" do
|
6
|
+
FileUtils.mkdir_p(inv_conf_dir)
|
6
7
|
config = Invoker::Power::Config.create(
|
7
8
|
dns_port: 1200, http_port: 1201, ipfw_rule_number: 010
|
8
9
|
)
|
@@ -2,6 +2,7 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Invoker::Power::PfMigrate do
|
4
4
|
before do
|
5
|
+
FileUtils.mkdir_p("/tmp/.invoker")
|
5
6
|
@old_firewall_file = Invoker::Power::OsxSetup::FIREWALL_PLIST_FILE
|
6
7
|
Invoker::Power::OsxSetup.const_set(:FIREWALL_PLIST_FILE, "/tmp/.invoker/firewall")
|
7
8
|
end
|
@@ -54,12 +55,18 @@ describe Invoker::Power::PfMigrate do
|
|
54
55
|
|
55
56
|
describe "#migrate" do
|
56
57
|
before do
|
58
|
+
@original_invoker_config = Invoker.config
|
57
59
|
mock_config = mock()
|
58
60
|
mock_config.stubs(:http_port).returns(80)
|
59
61
|
mock_config.stubs(:https_port).returns(443)
|
62
|
+
mock_config.stubs(:tld).returns('dev')
|
60
63
|
Invoker.config = mock_config
|
61
64
|
end
|
62
65
|
|
66
|
+
after do
|
67
|
+
Invoker.config = @original_invoker_config
|
68
|
+
end
|
69
|
+
|
63
70
|
it "should migrate firewall to new system" do
|
64
71
|
pf_migrator.expects(:firewall_config_requires_migration?).returns(true)
|
65
72
|
pf_migrator.expects(:ask_user_for_migration).returns(true)
|
@@ -1,9 +1,31 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
require "invoker/power/setup/distro/ubuntu"
|
3
|
+
require "invoker/power/setup/distro/opensuse"
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def mock_socat_scripts
|
6
|
+
FakeFS.deactivate!
|
7
|
+
socat_content = File.read(invoker_setup.forwarder_script)
|
8
|
+
socat_systemd = File.read(invoker_setup.socat_unit)
|
9
|
+
FakeFS.activate!
|
10
|
+
FileUtils.mkdir_p(File.dirname(invoker_setup.forwarder_script))
|
11
|
+
FileUtils.mkdir_p(File.dirname(invoker_setup.socat_unit))
|
12
|
+
File.open(invoker_setup.socat_unit, "w") do |fl|
|
13
|
+
fl.write(socat_systemd)
|
14
|
+
end
|
15
|
+
File.open(invoker_setup.forwarder_script, "w") do |fl|
|
16
|
+
fl.write(socat_content)
|
17
|
+
end
|
18
|
+
FileUtils.mkdir_p("/usr/bin")
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Invoker::Power::LinuxSetup, fakefs: true do
|
22
|
+
before do
|
23
|
+
FileUtils.mkdir_p(inv_conf_dir)
|
24
|
+
FileUtils.mkdir_p(Invoker::Power::Distro::Base::RESOLVER_DIR)
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:invoker_setup) { Invoker::Power::LinuxSetup.new('dev') }
|
28
|
+
let(:distro_installer) { Invoker::Power::Distro::Ubuntu.new('dev') }
|
7
29
|
|
8
30
|
describe "should only proceed after user confirmation" do
|
9
31
|
before { invoker_setup.distro_installer = distro_installer }
|
@@ -27,8 +49,20 @@ describe Invoker::Power::LinuxSetup do
|
|
27
49
|
end
|
28
50
|
end
|
29
51
|
|
30
|
-
describe "configuring dnsmasq and
|
31
|
-
before
|
52
|
+
describe "configuring dnsmasq and socat" do
|
53
|
+
before(:all) do
|
54
|
+
@original_invoker_config = Invoker.config
|
55
|
+
Invoker.config = mock
|
56
|
+
end
|
57
|
+
|
58
|
+
after(:all) do
|
59
|
+
Invoker.config = @original_invoker_config
|
60
|
+
end
|
61
|
+
|
62
|
+
before(:each) do
|
63
|
+
invoker_setup.distro_installer = distro_installer
|
64
|
+
mock_socat_scripts
|
65
|
+
end
|
32
66
|
|
33
67
|
it "should create proper config file" do
|
34
68
|
invoker_setup.expects(:initialize_distro_installer).returns(true)
|
@@ -46,10 +80,24 @@ describe Invoker::Power::LinuxSetup do
|
|
46
80
|
expect(dnsmasq_content.strip).to_not be_empty
|
47
81
|
expect(dnsmasq_content).to match(/dev/)
|
48
82
|
|
49
|
-
|
50
|
-
expect(
|
51
|
-
expect(
|
52
|
-
expect(
|
83
|
+
socat_content = File.read(Invoker::Power::Distro::Base::SOCAT_SHELLSCRIPT)
|
84
|
+
expect(socat_content.strip).to_not be_empty
|
85
|
+
expect(socat_content.strip).to match(/#{config.https_port}/)
|
86
|
+
expect(socat_content.strip).to match(/#{config.http_port}/)
|
87
|
+
|
88
|
+
service_file = File.read(Invoker::Power::Distro::Base::SOCAT_SYSTEMD)
|
89
|
+
expect(service_file.strip).to_not be_empty
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'resolver file' do
|
94
|
+
context 'user sets up a custom top level domain' do
|
95
|
+
it 'should create the correct resolver file' do
|
96
|
+
linux_setup = Invoker::Power::LinuxSetup.new('local')
|
97
|
+
suse_installer = Invoker::Power::Distro::Opensuse.new('local')
|
98
|
+
linux_setup.distro_installer = suse_installer
|
99
|
+
expect(linux_setup.resolver_file).to eq('/etc/dnsmasq.d/local-tld')
|
100
|
+
end
|
53
101
|
end
|
54
102
|
end
|
55
103
|
end
|
@@ -1,9 +1,14 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Invoker::Power::OsxSetup do
|
4
|
-
|
3
|
+
describe Invoker::Power::OsxSetup, fakefs: true do
|
4
|
+
before do
|
5
|
+
FileUtils.mkdir_p(inv_conf_dir)
|
6
|
+
FileUtils.mkdir_p(Invoker::Power::OsxSetup::RESOLVER_DIR)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "when no setup exists" do
|
5
10
|
it "should create a config file with port etc" do
|
6
|
-
setup = Invoker::Power::OsxSetup.new
|
11
|
+
setup = Invoker::Power::OsxSetup.new('dev')
|
7
12
|
setup.expects(:install_resolver).returns(true)
|
8
13
|
setup.expects(:drop_to_normal_user).returns(true)
|
9
14
|
setup.expects(:install_firewall).once
|
@@ -23,16 +28,16 @@ describe Invoker::Power::OsxSetup do
|
|
23
28
|
fl.write("foo test")
|
24
29
|
}
|
25
30
|
Invoker::Power::Setup.any_instance.expects(:setup_invoker).never
|
26
|
-
Invoker::Power::Setup.install()
|
31
|
+
Invoker::Power::Setup.install('dev')
|
27
32
|
end
|
28
33
|
end
|
29
34
|
|
30
35
|
describe "when pow like setup exists" do
|
31
36
|
before {
|
32
|
-
File.open(Invoker::Power::OsxSetup::
|
37
|
+
File.open(File.join(Invoker::Power::OsxSetup::RESOLVER_DIR, "dev"), "w") { |fl|
|
33
38
|
fl.write("hello")
|
34
39
|
}
|
35
|
-
@setup = Invoker::Power::OsxSetup.new
|
40
|
+
@setup = Invoker::Power::OsxSetup.new('dev')
|
36
41
|
}
|
37
42
|
|
38
43
|
describe "when user selects to overwrite it" do
|
@@ -60,7 +65,7 @@ describe Invoker::Power::OsxSetup do
|
|
60
65
|
|
61
66
|
describe "uninstalling firewall rules" do
|
62
67
|
it "should uninstall firewall rules and remove all files created by setup" do
|
63
|
-
setup = Invoker::Power::OsxSetup.new
|
68
|
+
setup = Invoker::Power::OsxSetup.new('dev')
|
64
69
|
|
65
70
|
Invoker::CLI::Question.expects(:agree).returns(true)
|
66
71
|
setup.expects(:remove_resolver_file).once
|
@@ -74,7 +79,7 @@ describe Invoker::Power::OsxSetup do
|
|
74
79
|
describe "setup on fresh osx install" do
|
75
80
|
context "when resolver directory does not exist" do
|
76
81
|
before do
|
77
|
-
@setup = Invoker::Power::OsxSetup.new
|
82
|
+
@setup = Invoker::Power::OsxSetup.new('dev')
|
78
83
|
FileUtils.rm_rf(Invoker::Power::OsxSetup::RESOLVER_DIR)
|
79
84
|
end
|
80
85
|
|
@@ -88,4 +93,13 @@ describe Invoker::Power::OsxSetup do
|
|
88
93
|
end
|
89
94
|
end
|
90
95
|
end
|
96
|
+
|
97
|
+
describe '.resolver_file' do
|
98
|
+
context 'user sets up a custom top level domain' do
|
99
|
+
it 'should create the correct resolver file' do
|
100
|
+
setup = Invoker::Power::OsxSetup.new('local')
|
101
|
+
expect(setup.resolver_file).to eq('/etc/resolver/local')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
91
105
|
end
|
@@ -4,7 +4,18 @@ describe Invoker::Power::UrlRewriter do
|
|
4
4
|
let(:rewriter) { Invoker::Power::UrlRewriter.new }
|
5
5
|
|
6
6
|
context "matching domain part of incoming request" do
|
7
|
-
|
7
|
+
before(:all) do
|
8
|
+
@original_invoker_config = Invoker.config
|
9
|
+
|
10
|
+
Invoker.config = mock
|
11
|
+
Invoker.config.stubs(:tld).returns("dev")
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:all) do
|
15
|
+
Invoker.config = @original_invoker_config
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should match foo.dev" do
|
8
19
|
match = rewriter.extract_host_from_domain("foo.dev")
|
9
20
|
expect(match).to_not be_empty
|
10
21
|
|
@@ -34,5 +45,26 @@ describe Invoker::Power::UrlRewriter do
|
|
34
45
|
|
35
46
|
expect(match[0]).to eq("hello-world")
|
36
47
|
end
|
48
|
+
|
49
|
+
context 'user sets up a custom top level domain' do
|
50
|
+
before(:all) do
|
51
|
+
@original_invoker_config = Invoker.config
|
52
|
+
|
53
|
+
Invoker.config = mock
|
54
|
+
Invoker.config.stubs(:tld).returns("local")
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should match domain part of incoming request correctly' do
|
58
|
+
match = rewriter.extract_host_from_domain("foo.local")
|
59
|
+
expect(match).to_not be_empty
|
60
|
+
|
61
|
+
matching_string = match[0]
|
62
|
+
expect(matching_string).to eq("foo")
|
63
|
+
end
|
64
|
+
|
65
|
+
after(:all) do
|
66
|
+
Invoker.config = @original_invoker_config
|
67
|
+
end
|
68
|
+
end
|
37
69
|
end
|
38
70
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Full integration test. Start a server, and client. Let client interact with
|
4
|
+
# server do a ping-pong. Client checks whether ping pong is successful or not.
|
5
|
+
# Also, mock rewriter so that it returns valid port for request proxying.
|
6
|
+
# - Server will run on port 28080.
|
7
|
+
# - Balancer will run on port 28081 proxying to 28080
|
8
|
+
# - Client will connect to 28081 performing ping-pong
|
9
|
+
|
10
|
+
def websocket_server
|
11
|
+
require 'websocket-eventmachine-server'
|
12
|
+
|
13
|
+
EM.run do
|
14
|
+
WebSocket::EventMachine::Server.start(host: "0.0.0.0", port: 28080) do |ws|
|
15
|
+
ws.onerror { |e| p e }
|
16
|
+
ws.onmessage { ws.send "pong" }
|
17
|
+
end
|
18
|
+
|
19
|
+
EM.add_timer(2) { EM.stop }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def websocket_client
|
24
|
+
require 'websocket-eventmachine-client'
|
25
|
+
|
26
|
+
@message = ""
|
27
|
+
|
28
|
+
EM.run do
|
29
|
+
ws = WebSocket::EventMachine::Client.connect(uri: 'ws://0.0.0.0:28081')
|
30
|
+
ws.onerror { |e| p e }
|
31
|
+
ws.onopen { ws.send("ping") }
|
32
|
+
ws.onmessage { |m, _| @message = m }
|
33
|
+
|
34
|
+
EM.add_timer(2) do
|
35
|
+
expect(@message).to eq "pong"
|
36
|
+
EM.stop
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
describe 'Web sockets support' do
|
43
|
+
it 'can ping pong via balancer' do
|
44
|
+
dns_response = Struct.new(:port, :ip).new(28080, "0.0.0.0")
|
45
|
+
Invoker::Power::UrlRewriter.any_instance
|
46
|
+
.stubs(:select_backend_config)
|
47
|
+
.returns(dns_response)
|
48
|
+
|
49
|
+
EM.run do
|
50
|
+
EM.start_server("0.0.0.0", 28081, EM::ProxyServer::Connection, {}) do |conn|
|
51
|
+
Invoker::Power::Balancer.new(conn, "http").install_callbacks
|
52
|
+
end
|
53
|
+
|
54
|
+
fork { websocket_server }
|
55
|
+
fork { websocket_client }
|
56
|
+
EM.add_timer(3) { EM.stop }
|
57
|
+
end
|
58
|
+
|
59
|
+
Process.waitall
|
60
|
+
end
|
61
|
+
end
|
@@ -2,13 +2,19 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Invoker::ProcessManager do
|
4
4
|
let(:process_manager) { Invoker::ProcessManager.new }
|
5
|
+
|
5
6
|
describe "#start_process_by_name" do
|
6
7
|
it "should find command by label and start it, if found" do
|
7
|
-
|
8
|
-
|
8
|
+
@original_invoker_config = Invoker.config
|
9
|
+
Invoker.config = mock
|
10
|
+
|
11
|
+
Invoker.config.stubs(:processes).returns([OpenStruct.new(:label => "resque", :cmd => "foo", :dir => "bar")])
|
12
|
+
Invoker.config.expects(:process).returns(OpenStruct.new(:label => "resque", :cmd => "foo", :dir => "bar"))
|
9
13
|
process_manager.expects(:start_process).returns(true)
|
10
14
|
|
11
15
|
process_manager.start_process_by_name("resque")
|
16
|
+
|
17
|
+
Invoker.config = @original_invoker_config
|
12
18
|
end
|
13
19
|
|
14
20
|
it "should not start already running process" do
|
@@ -94,5 +100,31 @@ BAR=foo
|
|
94
100
|
dir = "/tmp"
|
95
101
|
expect(process_manager.load_env(dir)).to eq({})
|
96
102
|
end
|
103
|
+
|
104
|
+
it "should load .local.env file if it exists" do
|
105
|
+
dir = "/tmp"
|
106
|
+
begin
|
107
|
+
env_file = File.new("#{dir}/.env", "w")
|
108
|
+
env_data =<<-EOD
|
109
|
+
FOO=foo
|
110
|
+
BAR=bar
|
111
|
+
EOD
|
112
|
+
env_file.write(env_data)
|
113
|
+
env_file.close
|
114
|
+
|
115
|
+
local_env_file = File.new("#{dir}/.env.local", "w")
|
116
|
+
local_env_data =<<-EOD
|
117
|
+
FOO=emacs
|
118
|
+
EOD
|
119
|
+
local_env_file.write(local_env_data)
|
120
|
+
local_env_file.close
|
121
|
+
|
122
|
+
env_options = process_manager.load_env(dir)
|
123
|
+
expect(env_options).to include("FOO" => "emacs", "BAR" => "bar")
|
124
|
+
ensure
|
125
|
+
File.delete(env_file.path)
|
126
|
+
File.delete(local_env_file.path)
|
127
|
+
end
|
128
|
+
end
|
97
129
|
end
|
98
130
|
end
|