foreman 0.46.0-mingw32 → 0.50.0-mingw32
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 -0
- data/bin/foreman-runner +3 -7
- data/bin/taskman +8 -0
- data/data/example/Procfile +4 -3
- data/data/example/spawnee +14 -0
- data/data/example/spawner +7 -0
- data/data/export/bluepill/master.pill.erb +11 -10
- data/data/export/launchd/launchd.plist.erb +22 -0
- data/data/export/runit/log/run.erb +7 -0
- data/data/export/runit/run.erb +2 -2
- data/data/export/supervisord/app.conf.erb +12 -12
- data/data/export/upstart/master.conf.erb +2 -2
- data/data/export/upstart/process.conf.erb +3 -3
- data/lib/foreman.rb +4 -0
- data/lib/foreman/cli.rb +59 -23
- data/lib/foreman/engine.rb +233 -147
- data/lib/foreman/engine/cli.rb +105 -0
- data/lib/foreman/env.rb +27 -0
- data/lib/foreman/export.rb +2 -2
- data/lib/foreman/export/base.rb +107 -12
- data/lib/foreman/export/bluepill.rb +3 -17
- data/lib/foreman/export/inittab.rb +8 -11
- data/lib/foreman/export/launchd.rb +15 -0
- data/lib/foreman/export/runit.rb +14 -39
- data/lib/foreman/export/supervisord.rb +3 -13
- data/lib/foreman/export/upstart.rb +9 -27
- data/lib/foreman/process.rb +73 -67
- data/lib/foreman/procfile.rb +59 -25
- data/lib/foreman/version.rb +1 -1
- data/man/foreman.1 +5 -1
- data/spec/foreman/cli_spec.rb +46 -150
- data/spec/foreman/engine_spec.rb +47 -74
- data/spec/foreman/export/base_spec.rb +4 -7
- data/spec/foreman/export/bluepill_spec.rb +7 -6
- data/spec/foreman/export/inittab_spec.rb +7 -7
- data/spec/foreman/export/launchd_spec.rb +21 -0
- data/spec/foreman/export/runit_spec.rb +12 -17
- data/spec/foreman/export/supervisord_spec.rb +7 -56
- data/spec/foreman/export/upstart_spec.rb +22 -21
- data/spec/foreman/process_spec.rb +27 -110
- data/spec/foreman/procfile_spec.rb +26 -16
- data/spec/resources/Procfile +4 -0
- data/spec/resources/bin/echo +2 -0
- data/spec/resources/bin/env +2 -0
- data/spec/resources/bin/test +2 -0
- data/spec/resources/export/bluepill/app-concurrency.pill +6 -4
- data/spec/resources/export/bluepill/app.pill +6 -4
- data/spec/resources/export/launchd/launchd-a.default +22 -0
- data/spec/resources/export/launchd/launchd-b.default +22 -0
- data/spec/resources/export/runit/{app-alpha-1-log-run → app-alpha-1/log/run} +0 -0
- data/spec/resources/export/runit/{app-alpha-1-run → app-alpha-1/run} +0 -0
- data/spec/resources/export/runit/{app-alpha-2-log-run → app-alpha-2/log/run} +0 -0
- data/spec/resources/export/runit/{app-alpha-2-run → app-alpha-2/run} +0 -0
- data/spec/resources/export/runit/{app-bravo-1-log-run → app-bravo-1/log/run} +0 -0
- data/spec/resources/export/runit/{app-bravo-1-run → app-bravo-1/run} +0 -0
- data/spec/resources/export/supervisord/app-alpha-1.conf +24 -0
- data/spec/resources/export/supervisord/app-alpha-2.conf +4 -4
- data/spec/spec_helper.rb +57 -6
- metadata +29 -21
- data/data/export/runit/log_run.erb +0 -7
- data/lib/foreman/color.rb +0 -40
- data/lib/foreman/procfile_entry.rb +0 -26
- data/lib/foreman/utils.rb +0 -18
- data/spec/foreman/color_spec.rb +0 -31
- data/spec/foreman/procfile_entry_spec.rb +0 -13
- data/spec/resources/export/supervisord/app-env-with-comma.conf +0 -24
- data/spec/resources/export/supervisord/app-env.conf +0 -21
- data/spec/resources/export/supervisord/app.conf +0 -24
@@ -5,127 +5,44 @@ require 'timeout'
|
|
5
5
|
require 'tmpdir'
|
6
6
|
|
7
7
|
describe Foreman::Process do
|
8
|
-
subject { described_class.new entry, number, port }
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
its(:entry) { entry }
|
17
|
-
its(:num) { number }
|
18
|
-
its(:port) { port }
|
19
|
-
its(:name) { "#{name}.#{port}" }
|
20
|
-
its(:pid) { nil }
|
21
|
-
|
22
|
-
describe '#run' do
|
23
|
-
let(:pipe) { :pipe }
|
24
|
-
let(:basedir) { Dir.mktmpdir }
|
25
|
-
let(:env) {{ 'foo' => 'bar' }}
|
26
|
-
let(:init_delta) { 0.1 }
|
9
|
+
def run(process, options={})
|
10
|
+
rd, wr = IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY")
|
11
|
+
process.run(options.merge(:output => wr))
|
12
|
+
rd.gets
|
13
|
+
end
|
27
14
|
|
28
|
-
|
15
|
+
describe "#run" do
|
29
16
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
subject.detach && sleep(init_delta)
|
17
|
+
it "runs the process" do
|
18
|
+
process = Foreman::Process.new(resource_path("bin/test"))
|
19
|
+
run(process).should == "testing\n"
|
34
20
|
end
|
35
21
|
|
36
|
-
|
37
|
-
|
38
|
-
run
|
39
|
-
sleep 1
|
22
|
+
it "can set environment" do
|
23
|
+
process = Foreman::Process.new(resource_path("bin/env FOO"), :env => { "FOO" => "bar" })
|
24
|
+
run(process).should == "bar\n"
|
40
25
|
end
|
41
26
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
ENV['PORT'].should == port.to_s
|
46
|
-
end
|
47
|
-
run
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'should set custom variables for environment' do
|
51
|
-
mock(subject).run_process(basedir, command, pipe) do
|
52
|
-
ENV['foo'].should == 'bar'
|
53
|
-
end
|
54
|
-
run
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'should restore environment afterwards' do
|
58
|
-
mock(subject).run_process(basedir, command, pipe)
|
59
|
-
run
|
60
|
-
ENV.should_not include('PORT', 'foo')
|
61
|
-
end
|
27
|
+
it "can set per-run environment" do
|
28
|
+
process = Foreman::Process.new(resource_path("bin/env FOO"))
|
29
|
+
run(process, :env => { "FOO" => "bar "}).should == "bar\n"
|
62
30
|
end
|
63
31
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
spec.run
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
let(:pipe) { @writer }
|
73
|
-
let(:output) { @reader.read_nonblock 1024 }
|
74
|
-
|
75
|
-
it 'should not block' do
|
76
|
-
expect {
|
77
|
-
Timeout.timeout(2*init_delta) { run 'sleep 2' }
|
78
|
-
}.should_not raise_exception
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'should be alive' do
|
82
|
-
run 'sleep 1'
|
83
|
-
subject.should be_alive
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'should be dead' do
|
87
|
-
run 'exit'
|
88
|
-
subject.should be_dead
|
89
|
-
end
|
90
|
-
|
91
|
-
it 'should be killable' do
|
92
|
-
run 'sleep 1'
|
93
|
-
subject.kill 'TERM'
|
94
|
-
subject.should be_dead
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'should send different signals' do
|
98
|
-
run_file 'ruby', <<-CODE
|
99
|
-
trap "TERM", "IGNORE"
|
100
|
-
loop { sleep 1 }
|
101
|
-
CODE
|
102
|
-
subject.should be_alive
|
103
|
-
subject.kill 'TERM'
|
104
|
-
subject.should be_alive
|
105
|
-
subject.kill 'KILL'
|
106
|
-
subject.should be_dead
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'should redirect stdout' do
|
110
|
-
run 'echo hey'
|
111
|
-
output.should include('hey')
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'should redirect stderr' do
|
115
|
-
run 'echo hey >2'
|
116
|
-
output.should include('hey')
|
117
|
-
end
|
32
|
+
it "can handle env vars in the command" do
|
33
|
+
process = Foreman::Process.new(resource_path("bin/echo $FOO"), :env => { "FOO" => "bar" })
|
34
|
+
run(process).should == "bar\n"
|
35
|
+
end
|
118
36
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
37
|
+
it "can handle per-run env vars in the command" do
|
38
|
+
process = Foreman::Process.new(resource_path("bin/echo $FOO"))
|
39
|
+
run(process, :env => { "FOO" => "bar" }).should == "bar\n"
|
40
|
+
end
|
123
41
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
subject.should be_alive
|
128
|
-
end
|
42
|
+
it "should output utf8 properly" do
|
43
|
+
process = Foreman::Process.new(resource_path("bin/utf8"))
|
44
|
+
run(process).should == "\xFF\x03\n"
|
129
45
|
end
|
130
46
|
end
|
47
|
+
|
131
48
|
end
|
@@ -3,29 +3,39 @@ require 'foreman/procfile'
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'tmpdir'
|
5
5
|
|
6
|
-
describe Foreman::Procfile do
|
7
|
-
subject {
|
6
|
+
describe Foreman::Procfile, :fakefs do
|
7
|
+
subject { Foreman::Procfile.new }
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
it "can load from a file" do
|
10
|
+
write_procfile
|
11
|
+
subject.load "Procfile"
|
12
|
+
subject["alpha"].should == "./alpha"
|
13
|
+
subject["bravo"].should == "./bravo"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "loads a passed-in Procfile" do
|
17
|
+
write_procfile
|
18
|
+
procfile = Foreman::Procfile.new("Procfile")
|
19
|
+
procfile["alpha"].should == "./alpha"
|
20
|
+
procfile["bravo"].should == "./bravo"
|
21
|
+
end
|
11
22
|
|
12
23
|
it "can have a process appended to it" do
|
13
|
-
subject
|
14
|
-
subject[
|
24
|
+
subject["charlie"] = "./charlie"
|
25
|
+
subject["charlie"].should == "./charlie"
|
15
26
|
end
|
16
27
|
|
17
|
-
it "can write
|
18
|
-
subject
|
19
|
-
subject
|
20
|
-
|
28
|
+
it "can write to a string" do
|
29
|
+
subject["foo"] = "./foo"
|
30
|
+
subject["bar"] = "./bar"
|
31
|
+
subject.to_s.should == "foo: ./foo\nbar: ./bar"
|
21
32
|
end
|
22
33
|
|
23
|
-
it "can
|
24
|
-
|
25
|
-
subject
|
26
|
-
subject.
|
27
|
-
|
28
|
-
subject.process_names.should include('gamma', 'theta')
|
34
|
+
it "can write to a file" do
|
35
|
+
subject["foo"] = "./foo"
|
36
|
+
subject["bar"] = "./bar"
|
37
|
+
subject.save "/tmp/proc"
|
38
|
+
File.read("/tmp/proc").should == "foo: ./foo\nbar: ./bar\n"
|
29
39
|
end
|
30
40
|
|
31
41
|
end
|
@@ -11,13 +11,14 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
|
|
11
11
|
|
12
12
|
process.working_dir = "/tmp/app"
|
13
13
|
process.daemonize = true
|
14
|
-
process.environment = {"PORT"
|
14
|
+
process.environment = {"PORT"=>"5000"}
|
15
15
|
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
|
16
|
+
process.stop_grace_time = 45.seconds
|
16
17
|
|
17
18
|
process.stdout = process.stderr = "/var/log/app/app-alpha-1.log"
|
18
19
|
|
19
20
|
process.monitor_children do |children|
|
20
|
-
children.stop_command "kill
|
21
|
+
children.stop_command "kill {{PID}}"
|
21
22
|
end
|
22
23
|
|
23
24
|
process.group = "app-alpha"
|
@@ -29,13 +30,14 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
|
|
29
30
|
|
30
31
|
process.working_dir = "/tmp/app"
|
31
32
|
process.daemonize = true
|
32
|
-
process.environment = {"PORT"
|
33
|
+
process.environment = {"PORT"=>"5001"}
|
33
34
|
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
|
35
|
+
process.stop_grace_time = 45.seconds
|
34
36
|
|
35
37
|
process.stdout = process.stderr = "/var/log/app/app-alpha-2.log"
|
36
38
|
|
37
39
|
process.monitor_children do |children|
|
38
|
-
children.stop_command "kill
|
40
|
+
children.stop_command "kill {{PID}}"
|
39
41
|
end
|
40
42
|
|
41
43
|
process.group = "app-alpha"
|
@@ -11,13 +11,14 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
|
|
11
11
|
|
12
12
|
process.working_dir = "/tmp/app"
|
13
13
|
process.daemonize = true
|
14
|
-
process.environment = {"PORT"
|
14
|
+
process.environment = {"PORT"=>"5000"}
|
15
15
|
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
|
16
|
+
process.stop_grace_time = 45.seconds
|
16
17
|
|
17
18
|
process.stdout = process.stderr = "/var/log/app/app-alpha-1.log"
|
18
19
|
|
19
20
|
process.monitor_children do |children|
|
20
|
-
children.stop_command "kill
|
21
|
+
children.stop_command "kill {{PID}}"
|
21
22
|
end
|
22
23
|
|
23
24
|
process.group = "app-alpha"
|
@@ -28,13 +29,14 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
|
|
28
29
|
|
29
30
|
process.working_dir = "/tmp/app"
|
30
31
|
process.daemonize = true
|
31
|
-
process.environment = {"PORT"
|
32
|
+
process.environment = {"PORT"=>"5100"}
|
32
33
|
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
|
34
|
+
process.stop_grace_time = 45.seconds
|
33
35
|
|
34
36
|
process.stdout = process.stderr = "/var/log/app/app-bravo-1.log"
|
35
37
|
|
36
38
|
process.monitor_children do |children|
|
37
|
-
children.stop_command "kill
|
39
|
+
children.stop_command "kill {{PID}}"
|
38
40
|
end
|
39
41
|
|
40
42
|
process.group = "app-bravo"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>Label</key>
|
6
|
+
<string>app-alpha-1</string>
|
7
|
+
<key>ProgramArguments</key>
|
8
|
+
<array>
|
9
|
+
<string>./alpha</string>
|
10
|
+
</array>
|
11
|
+
<key>KeepAlive</key>
|
12
|
+
<true/>
|
13
|
+
<key>RunAtLoad</key>
|
14
|
+
<true/>
|
15
|
+
<key>StandardErrorPath</key>
|
16
|
+
<string>/var/log/app/app-alpha-1.log</string>
|
17
|
+
<key>UserName</key>
|
18
|
+
<string>app</string>
|
19
|
+
<key>WorkingDirectory</key>
|
20
|
+
<string>/tmp/app</string>
|
21
|
+
</dict>
|
22
|
+
</plist>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>Label</key>
|
6
|
+
<string>app-bravo-1</string>
|
7
|
+
<key>ProgramArguments</key>
|
8
|
+
<array>
|
9
|
+
<string>./bravo</string>
|
10
|
+
</array>
|
11
|
+
<key>KeepAlive</key>
|
12
|
+
<true/>
|
13
|
+
<key>RunAtLoad</key>
|
14
|
+
<true/>
|
15
|
+
<key>StandardErrorPath</key>
|
16
|
+
<string>/var/log/app/app-bravo-1.log</string>
|
17
|
+
<key>UserName</key>
|
18
|
+
<string>app</string>
|
19
|
+
<key>WorkingDirectory</key>
|
20
|
+
<string>/tmp/app</string>
|
21
|
+
</dict>
|
22
|
+
</plist>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
[program:app-alpha-1]
|
3
|
+
command=./alpha
|
4
|
+
autostart=true
|
5
|
+
autorestart=true
|
6
|
+
stopsignal=QUIT
|
7
|
+
stdout_logfile=/var/log/app/alpha-1.log
|
8
|
+
stderr_logfile=/var/log/app/alpha-1.error.log
|
9
|
+
user=app
|
10
|
+
directory=/tmp/app
|
11
|
+
environment=PORT="5000"
|
12
|
+
[program:app-bravo-1]
|
13
|
+
command=./bravo
|
14
|
+
autostart=true
|
15
|
+
autorestart=true
|
16
|
+
stopsignal=QUIT
|
17
|
+
stdout_logfile=/var/log/app/bravo-1.log
|
18
|
+
stderr_logfile=/var/log/app/bravo-1.error.log
|
19
|
+
user=app
|
20
|
+
directory=/tmp/app
|
21
|
+
environment=PORT="5100"
|
22
|
+
|
23
|
+
[group:app]
|
24
|
+
programs=app-alpha-1,app-bravo-1
|
@@ -4,8 +4,8 @@ command=./alpha
|
|
4
4
|
autostart=true
|
5
5
|
autorestart=true
|
6
6
|
stopsignal=QUIT
|
7
|
-
stdout_logfile=/var/log/app/alpha-1
|
8
|
-
stderr_logfile=/var/log/app/alpha-1
|
7
|
+
stdout_logfile=/var/log/app/alpha-1.log
|
8
|
+
stderr_logfile=/var/log/app/alpha-1.error.log
|
9
9
|
user=app
|
10
10
|
directory=/tmp/app
|
11
11
|
environment=PORT="5000"
|
@@ -14,8 +14,8 @@ command=./alpha
|
|
14
14
|
autostart=true
|
15
15
|
autorestart=true
|
16
16
|
stopsignal=QUIT
|
17
|
-
stdout_logfile=/var/log/app/alpha-2
|
18
|
-
stderr_logfile=/var/log/app/alpha-2
|
17
|
+
stdout_logfile=/var/log/app/alpha-2.log
|
18
|
+
stderr_logfile=/var/log/app/alpha-2.error.log
|
19
19
|
user=app
|
20
20
|
directory=/tmp/app
|
21
21
|
environment=PORT="5001"
|
data/spec/spec_helper.rb
CHANGED
@@ -6,6 +6,7 @@ SimpleCov.start do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
require "rspec"
|
9
|
+
require "timecop"
|
9
10
|
require "fakefs/safe"
|
10
11
|
require "fakefs/spec_helpers"
|
11
12
|
|
@@ -23,7 +24,38 @@ def mock_error(subject, message)
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def foreman(args)
|
26
|
-
|
27
|
+
capture_stdout do
|
28
|
+
begin
|
29
|
+
Foreman::CLI.start(args.split(" "))
|
30
|
+
rescue SystemExit
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def forked_foreman(args)
|
36
|
+
rd, wr = IO.pipe("BINARY")
|
37
|
+
Process.spawn("bundle exec bin/foreman #{args}", :out => wr, :err => wr)
|
38
|
+
wr.close
|
39
|
+
rd.read
|
40
|
+
end
|
41
|
+
|
42
|
+
def fork_and_capture(&blk)
|
43
|
+
rd, wr = IO.pipe("BINARY")
|
44
|
+
pid = fork do
|
45
|
+
rd.close
|
46
|
+
wr.sync = true
|
47
|
+
$stdout.reopen wr
|
48
|
+
$stderr.reopen wr
|
49
|
+
blk.call
|
50
|
+
$stdout.flush
|
51
|
+
$stdout.close
|
52
|
+
end
|
53
|
+
wr.close
|
54
|
+
Process.wait pid
|
55
|
+
buffer = ""
|
56
|
+
until rd.eof?
|
57
|
+
buffer += rd.gets
|
58
|
+
end
|
27
59
|
end
|
28
60
|
|
29
61
|
def mock_exit(&block)
|
@@ -55,13 +87,21 @@ def write_env(env=".env", options={"FOO"=>"bar"})
|
|
55
87
|
end
|
56
88
|
end
|
57
89
|
|
58
|
-
def
|
90
|
+
def without_fakefs
|
59
91
|
FakeFS.deactivate!
|
60
|
-
|
61
|
-
hash.update(file => File.read(file))
|
62
|
-
end
|
92
|
+
ret = yield
|
63
93
|
FakeFS.activate!
|
64
|
-
|
94
|
+
ret
|
95
|
+
end
|
96
|
+
|
97
|
+
def load_export_templates_into_fakefs(type)
|
98
|
+
without_fakefs do
|
99
|
+
Dir[File.expand_path("../../data/export/#{type}/**/*", __FILE__)].inject({}) do |hash, file|
|
100
|
+
next(hash) if File.directory?(file)
|
101
|
+
hash.update(file => File.read(file))
|
102
|
+
end
|
103
|
+
end.each do |filename, contents|
|
104
|
+
FileUtils.mkdir_p File.dirname(filename)
|
65
105
|
File.open(filename, "w") do |f|
|
66
106
|
f.puts contents
|
67
107
|
end
|
@@ -93,6 +133,17 @@ def normalize_space(s)
|
|
93
133
|
s.gsub(/\n[\n\s]*/, "\n")
|
94
134
|
end
|
95
135
|
|
136
|
+
def capture_stdout
|
137
|
+
old_stdout = $stdout.dup
|
138
|
+
rd, wr = IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY")
|
139
|
+
$stdout = wr
|
140
|
+
yield
|
141
|
+
wr.close
|
142
|
+
rd.read
|
143
|
+
ensure
|
144
|
+
$stdout = old_stdout
|
145
|
+
end
|
146
|
+
|
96
147
|
RSpec.configure do |config|
|
97
148
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
98
149
|
config.color_enabled = true
|