daf 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +71 -0
- data/LICENSE.txt +21 -0
- data/README.md +37 -0
- data/Rakefile +23 -0
- data/bin/dad +5 -0
- data/daf.gemspec +35 -0
- data/examples/config/SendEmail.yaml +16 -0
- data/lib/daf.rb +50 -0
- data/lib/daf/action.rb +25 -0
- data/lib/daf/actions/email_action.rb +34 -0
- data/lib/daf/actions/pushbullet_action.rb +26 -0
- data/lib/daf/actions/shell_action.rb +21 -0
- data/lib/daf/actions/sms_action.rb +25 -0
- data/lib/daf/command.rb +55 -0
- data/lib/daf/configurable.rb +145 -0
- data/lib/daf/datasources/yaml_data_source.rb +53 -0
- data/lib/daf/monitor.rb +27 -0
- data/lib/daf/monitors/file_update_monitor.rb +46 -0
- data/lib/daf/version.rb +4 -0
- data/spec/action_spec.rb +38 -0
- data/spec/command_spec.rb +78 -0
- data/spec/configurable_spec.rb +62 -0
- data/spec/daf_spec.rb +93 -0
- data/spec/email_action_spec.rb +61 -0
- data/spec/file_update_monitor_spec.rb +85 -0
- data/spec/monitor_spec.rb +41 -0
- data/spec/shell_action_spec.rb +55 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/yaml_data_source_spec.rb +117 -0
- metadata +188 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DAF::Configurable do
|
4
|
+
# Test class to verify Configurable functionality
|
5
|
+
class MockClass
|
6
|
+
include DAF::Configurable
|
7
|
+
|
8
|
+
attr_option :test, String, :required
|
9
|
+
attr_option :test2, Integer, :optional do |val|
|
10
|
+
val > 2
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_output :test_out, String
|
14
|
+
attr_output :test2_out, Integer
|
15
|
+
end
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
@under_test = MockClass.new
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has required option' do
|
22
|
+
expect { MockClass.required_options }.to_not raise_error
|
23
|
+
expect(MockClass.required_options).not_to be_empty
|
24
|
+
expect(MockClass.required_options.length).to eq(1)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'has options' do
|
28
|
+
expect { MockClass.options }.to_not raise_error
|
29
|
+
expect(MockClass.options).not_to be_empty
|
30
|
+
expect(MockClass.options.length).to eq(2)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'has outputs' do
|
34
|
+
expect { MockClass.outputs }.to_not raise_error
|
35
|
+
expect(MockClass.outputs).not_to be_empty
|
36
|
+
expect(MockClass.outputs.length).to eq(2)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'has readable outputs' do
|
40
|
+
expect { @under_test.test2_out }.to_not raise_error
|
41
|
+
expect { @under_test.test_out }.to_not raise_error
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'exposes required type for inputs' do
|
45
|
+
expect(@under_test.test.type).to eq(String)
|
46
|
+
expect(@under_test.test2.type).to eq(Integer)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'has writable inputs' do
|
50
|
+
@under_test.test.value = 'Test'
|
51
|
+
@under_test.test2.value = 40
|
52
|
+
expect(@under_test.test.value).to eq('Test')
|
53
|
+
expect(@under_test.test2.value).to eq(40)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'validates inputs' do
|
57
|
+
@under_test.test.value = 40
|
58
|
+
@under_test.test2.value = 'bad value'
|
59
|
+
expect(@under_test.test.valid?).to eq(false)
|
60
|
+
expect(@under_test.test.valid?).to eq(false)
|
61
|
+
end
|
62
|
+
end
|
data/spec/daf_spec.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include DAF
|
3
|
+
|
4
|
+
describe 'DAF' do
|
5
|
+
context 'when start_dad is called' do
|
6
|
+
let!(:data_source) do
|
7
|
+
dup = class_double('DAF::YAMLDataSource').as_stubbed_const
|
8
|
+
allow(dup).to receive(:new)
|
9
|
+
dup
|
10
|
+
end
|
11
|
+
|
12
|
+
let!(:command) do
|
13
|
+
dup = class_double('DAF::Command').as_stubbed_const
|
14
|
+
allow(dup).to receive(:new).and_return('com')
|
15
|
+
dup
|
16
|
+
end
|
17
|
+
|
18
|
+
let!(:dir) do
|
19
|
+
dup = class_double('Dir').as_stubbed_const(
|
20
|
+
transfer_nested_constants: true)
|
21
|
+
allow(dup).to receive(:[]).and_return(%w(test1 test2))
|
22
|
+
dup
|
23
|
+
end
|
24
|
+
|
25
|
+
let!(:dad) do
|
26
|
+
dup = class_double('DAF::DynamicActionDaemon').as_stubbed_const
|
27
|
+
allow(dup).to receive(:new).and_return(idad)
|
28
|
+
dup
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:idad) do
|
32
|
+
dup = double('DAF::DynamicActionDaemon')
|
33
|
+
allow(dup).to receive(:start)
|
34
|
+
dup
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should print usage if argument is not directory' do
|
38
|
+
expect(self).to receive(:print_usage)
|
39
|
+
ARGV[0] = '/dev/null'
|
40
|
+
start_dad
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should get list of files using Dir' do
|
44
|
+
expect(dir).to receive(:[]).with('//*.yaml')
|
45
|
+
ARGV[0] = '/'
|
46
|
+
start_dad
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should generate a list of commands from each file' do
|
50
|
+
expect(command).to receive(:new).twice
|
51
|
+
expect(data_source).to receive(:new).with('test1')
|
52
|
+
expect(data_source).to receive(:new).with('test2')
|
53
|
+
ARGV[0] = '/'
|
54
|
+
start_dad
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should create a new daemon with commands' do
|
58
|
+
expect(dad).to receive(:new).with(%w(com com))
|
59
|
+
ARGV[0] = '/'
|
60
|
+
start_dad
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should start the daemon' do
|
64
|
+
expect(idad).to receive(:start)
|
65
|
+
ARGV[0] = '/'
|
66
|
+
start_dad
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when usage information is printed' do
|
71
|
+
it 'should write to stdout' do
|
72
|
+
expect($stdout).to receive(:write).at_least(1).times
|
73
|
+
print_usage
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe 'DAF::DynamicActionDaemon' do
|
79
|
+
context 'when started' do
|
80
|
+
it 'should execute each command' do
|
81
|
+
command1 = double('DAF::Command')
|
82
|
+
command2 = double('DAF::Command')
|
83
|
+
expect(command1).to receive(:execute)
|
84
|
+
expect(command2).to receive(:execute)
|
85
|
+
dad = DynamicActionDaemon.new([command1, command2])
|
86
|
+
thread = Thread.new do
|
87
|
+
dad.start
|
88
|
+
end
|
89
|
+
sleep(1)
|
90
|
+
thread.kill
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DAF::EmailAction do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@server = 'mail.example.com'
|
7
|
+
@options = { 'from' => 'test@example.com',
|
8
|
+
'to' => 'test_to@example.com',
|
9
|
+
'subject' => 'Test Subject',
|
10
|
+
'body' => 'Test Body',
|
11
|
+
'server' => @server }
|
12
|
+
@action = DAF::EmailAction.new
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'has five required options' do
|
16
|
+
expect { @action.class.required_options }.not_to raise_error
|
17
|
+
expect(@action.class.required_options.length).to eq(5)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'has six options' do
|
21
|
+
expect { @action.class.options }.not_to raise_error
|
22
|
+
expect(@action.class.options.length).to eq(6)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'has a port option of type Integer' do
|
26
|
+
expect(@action.class.options['port']).to eq(Integer)
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when activate is called' do
|
30
|
+
before(:each) do
|
31
|
+
@smtp_obj = double(Net::SMTP.new('mail.example.com'))
|
32
|
+
@smtp = class_double('Net::SMTP')
|
33
|
+
.as_stubbed_const(transfer_nested_constants: true)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'sends with the server and port passed in' do
|
37
|
+
@options['port'] = 333
|
38
|
+
expect(@smtp).to receive(:start).with(@server, 333)
|
39
|
+
@action.activate(@options)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should use a default port if none is specified' do
|
43
|
+
expect(@smtp).to receive(:start).with(@server, 25)
|
44
|
+
@action.activate(@options)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should send a message' do
|
48
|
+
target_message = <<END
|
49
|
+
From: test@example.com
|
50
|
+
To: test_to@example.com
|
51
|
+
Subject: Test Subject
|
52
|
+
|
53
|
+
Test Body
|
54
|
+
END
|
55
|
+
allow(@smtp).to receive(:start).and_yield(@smtp_obj)
|
56
|
+
expect(@smtp_obj).to receive(:send_message).with(
|
57
|
+
target_message, 'test@example.com', 'test_to@example.com')
|
58
|
+
@action.activate(@options)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'DAF::FileUpdateMonitor' do
|
4
|
+
context 'when new monitor is created' do
|
5
|
+
it 'should validate that the path exists' do
|
6
|
+
options = { 'frequency' => 2, 'path' => '/tmp/fake' }
|
7
|
+
expect { FileUpdateMonitor.new(options) }.to raise_error
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should validate that the frequency is > 1' do
|
11
|
+
options = { 'frequency' => 0, 'path' => '/' }
|
12
|
+
expect { FileUpdateMonitor.new(options) }.to raise_error
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should have a required option named path' do
|
16
|
+
expect(FileUpdateMonitor.required_options).to include('path')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have a required option named frequency' do
|
20
|
+
expect(FileUpdateMonitor.required_options).to include('frequency')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when block_until_triggered is called' do
|
25
|
+
let(:monitor) do
|
26
|
+
options = { 'frequency' => 2, 'path' => '/' }
|
27
|
+
FileUpdateMonitor.new(options)
|
28
|
+
end
|
29
|
+
|
30
|
+
let!(:file) do
|
31
|
+
dup = class_double('File').as_stubbed_const(
|
32
|
+
transfer_nested_constants: true)
|
33
|
+
@time = 0
|
34
|
+
allow(dup).to receive(:mtime) do
|
35
|
+
@time += 1
|
36
|
+
end
|
37
|
+
allow(dup).to receive(:exist?).and_return(true)
|
38
|
+
allow(dup).to receive(:open).and_return(ifile)
|
39
|
+
dup
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:ifile) do
|
43
|
+
dup = double('File')
|
44
|
+
allow(dup).to receive(:read).and_return('contents')
|
45
|
+
allow(dup).to receive(:close)
|
46
|
+
dup
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should sleep the set frequency' do
|
50
|
+
expect(monitor).to receive(:sleep).with(2)
|
51
|
+
monitor.block_until_triggered
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should record current time' do
|
55
|
+
expect(file).to receive(:mtime).twice
|
56
|
+
monitor.block_until_triggered
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should skip loop unless file modify time changes' do
|
60
|
+
expect(monitor).to receive(:sleep).with(2).exactly(3).times
|
61
|
+
@mtime = 0
|
62
|
+
allow(file).to receive(:mtime) do
|
63
|
+
@mtime += 1
|
64
|
+
if @mtime < 4
|
65
|
+
0
|
66
|
+
else
|
67
|
+
1
|
68
|
+
end
|
69
|
+
end
|
70
|
+
monitor.block_until_triggered
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when file is modified' do
|
74
|
+
it 'should record the time as output' do
|
75
|
+
monitor.block_until_triggered
|
76
|
+
expect(monitor.time).to eq(2)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should record the contents of the file as output' do
|
80
|
+
monitor.block_until_triggered
|
81
|
+
expect(monitor.contents).to eq('contents')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Test monitor to verify functionality
|
4
|
+
class TestMonitor < DAF::Monitor
|
5
|
+
attr_option :option, String
|
6
|
+
attr_reader :output
|
7
|
+
def block_until_triggered
|
8
|
+
@output = 123
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe DAF::Monitor do
|
13
|
+
let(:test_monitor) { TestMonitor.new('option' => 'test') }
|
14
|
+
|
15
|
+
it 'should be configurable' do
|
16
|
+
mixed_in = DAF::Monitor.ancestors.select { |o| o.class == Module }
|
17
|
+
expect(mixed_in).to include(DAF::Configurable)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should have an on_trigger method' do
|
21
|
+
expect(test_monitor).to respond_to(:on_trigger)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should require a block to execute' do
|
25
|
+
expect { test_monitor.on_trigger }.to raise_error(LocalJumpError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should call block_until_triggered' do
|
29
|
+
test_monitor.on_trigger {}
|
30
|
+
expect(test_monitor.output).to eq(123)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should yield to a given block when triggered' do
|
34
|
+
expect { |b| test_monitor.on_trigger(&b) }
|
35
|
+
.to yield_with_no_args
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should set option values' do
|
39
|
+
expect(test_monitor.option.value).to eq('test')
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DAF::ShellAction do
|
4
|
+
before(:each) do
|
5
|
+
@options = { 'path' => '/bin/ls' }
|
6
|
+
@action = DAF::ShellAction.new
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'options' do
|
10
|
+
it 'has a required path option of type String' do
|
11
|
+
expect { @action.class.required_options }.not_to raise_error
|
12
|
+
expect(@action.class.required_options.length).to eq(1)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'validates the path is executable and exists' do
|
16
|
+
@action.path.value = '/bin/ls'
|
17
|
+
expect(@action.path.valid?).to eq(true)
|
18
|
+
@action.path.value = '/tmp/nonsense'
|
19
|
+
expect(@action.path.valid?).to eq(false)
|
20
|
+
@action.path.value = '/tmp/test1'
|
21
|
+
expect(@action.path.valid?).to eq(false)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'has an optional arguments option of type String' do
|
25
|
+
expect { @action.class.options }.not_to raise_error
|
26
|
+
expect(@action.class.options.length).to eq(2)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'has an output results of type String' do
|
31
|
+
expect { @action.class.outputs }.not_to raise_error
|
32
|
+
expect(@action.class.outputs.length).to eq(1)
|
33
|
+
expect(@action.class.outputs['results']).to eq(String)
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when activate is called' do
|
37
|
+
it 'executes a shell script' do
|
38
|
+
expect(@action).to receive(:`).with('/bin/ls')
|
39
|
+
@action.activate(@options)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns the result of shell script' do
|
43
|
+
allow(@action).to receive(:`).and_return('result!')
|
44
|
+
@action.activate(@options)
|
45
|
+
expect(@action.results).to eq('result!')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'passes arguments to the shell script' do
|
49
|
+
expect(@action).to receive(:`).with('/bin/ls test')
|
50
|
+
@options['arguments'] = 'test'
|
51
|
+
@action.activate(@options)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter '/spec/'
|
4
|
+
add_group 'Actions', 'lib/daf/actions/'
|
5
|
+
add_group 'Monitors', 'lib/daf/monitors/'
|
6
|
+
add_group 'Data Sources', 'lib/daf/datasources/'
|
7
|
+
minimum_coverage 95
|
8
|
+
refuse_coverage_drop
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'daf'
|
12
|
+
require 'daf/command'
|
13
|
+
require 'daf/configurable'
|
14
|
+
require 'daf/monitor'
|
15
|
+
require 'daf/action'
|
16
|
+
require 'daf/monitors/file_update_monitor'
|
17
|
+
require 'daf/actions/email_action'
|
18
|
+
require 'daf/actions/shell_action'
|
19
|
+
require 'daf/datasources/yaml_data_source'
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestMonitor < DAF::Monitor
|
4
|
+
end
|
5
|
+
|
6
|
+
class TestAction < DAF::Action
|
7
|
+
end
|
8
|
+
|
9
|
+
describe DAF::YAMLDataSource do
|
10
|
+
let!(:yaml) do
|
11
|
+
yaml = class_double('YAML').as_stubbed_const(
|
12
|
+
transfer_nested_constants: true)
|
13
|
+
allow(yaml).to receive(:load_file).and_return(
|
14
|
+
'Monitor' => { 'Options' => {}, 'Type' => 'TestMonitor' },
|
15
|
+
'Action' => { 'Options' => {
|
16
|
+
'test' => '{{test}}',
|
17
|
+
'test2' => 'thing: {{test2}}'
|
18
|
+
}, 'Type' => 'TestAction' })
|
19
|
+
yaml
|
20
|
+
end
|
21
|
+
let(:data_source) { DAF::YAMLDataSource.new('/tmp/test') }
|
22
|
+
|
23
|
+
context 'properties' do
|
24
|
+
it 'responds to #monitor' do
|
25
|
+
expect(data_source).to respond_to(:monitor)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'responds to #action' do
|
29
|
+
expect(data_source).to respond_to(:action)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when new is called' do
|
34
|
+
it 'should load the file at the given path' do
|
35
|
+
expect(yaml).to receive(:load_file).with('/tmp/2')
|
36
|
+
DAF::YAMLDataSource.new('/tmp/2')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should initialize monitor class specified' do
|
40
|
+
expect(data_source.monitor.class).to eq(TestMonitor)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should initialize action class specified' do
|
44
|
+
expect(data_source.action.class).to eq(TestAction)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should throw an exception if class does not exist' do
|
48
|
+
allow(yaml).to receive(:load_file).and_return(
|
49
|
+
'Monitor' => { 'Options' => [], 'Type' => 'BadTestMonitor' },
|
50
|
+
'Action' => { 'Options' => [], 'Type' => 'BadTestAction' })
|
51
|
+
expect { DAF::YAMLDataSource.new('/tmp/new') }.to raise_error
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when asked for action_options' do
|
56
|
+
let(:itest_action) do
|
57
|
+
double('TestAction')
|
58
|
+
end
|
59
|
+
let!(:test_action) do
|
60
|
+
dup = class_double('TestAction').as_stubbed_const
|
61
|
+
allow(dup).to receive(:new).and_return(itest_action)
|
62
|
+
dup
|
63
|
+
end
|
64
|
+
let(:itest_monitor) do
|
65
|
+
double('TestMonitor')
|
66
|
+
end
|
67
|
+
let!(:test_monitor) do
|
68
|
+
dup = class_double('TestMonitor').as_stubbed_const
|
69
|
+
allow(dup).to receive(:new).and_return(itest_monitor)
|
70
|
+
dup
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should return raw options if no outputs defined' do
|
74
|
+
allow(test_monitor).to receive(:outputs).and_return({})
|
75
|
+
expect(data_source.action_options).to have_key('test')
|
76
|
+
expect(data_source.action_options['test']).to eq('{{test}}')
|
77
|
+
expect(data_source.action_options).to have_key('test2')
|
78
|
+
expect(data_source.action_options['test2']).to eq('thing: {{test2}}')
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should return raw options if no outputs match outputs' do
|
82
|
+
allow(test_monitor).to receive(:outputs).and_return(
|
83
|
+
'another_test' => String
|
84
|
+
)
|
85
|
+
allow(itest_monitor).to receive(:another_test).and_return('test_output')
|
86
|
+
expect(data_source.action_options).to have_key('test')
|
87
|
+
expect(data_source.action_options['test']).to eq('{{test}}')
|
88
|
+
expect(data_source.action_options).to have_key('test2')
|
89
|
+
expect(data_source.action_options['test2']).to eq('thing: {{test2}}')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should substitute outputs into options' do
|
93
|
+
allow(test_monitor).to receive(:outputs).and_return(
|
94
|
+
'test' => String
|
95
|
+
)
|
96
|
+
allow(itest_monitor).to receive(:test).and_return('test output')
|
97
|
+
expect(data_source.action_options).to have_key('test')
|
98
|
+
expect(data_source.action_options['test']).to eq('test output')
|
99
|
+
expect(data_source.action_options).to have_key('test2')
|
100
|
+
expect(data_source.action_options['test2']).to eq('thing: {{test2}}')
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should substitute multiple outputs into multiple inputs' do
|
104
|
+
allow(test_monitor).to receive(:outputs).and_return(
|
105
|
+
'test' => String,
|
106
|
+
'test2' => String
|
107
|
+
)
|
108
|
+
allow(itest_monitor).to receive(:test).and_return('test output')
|
109
|
+
allow(itest_monitor).to receive(:test2).and_return('aout')
|
110
|
+
expect(data_source.action_options).to have_key('test')
|
111
|
+
expect(data_source.action_options['test']).to eq('test output')
|
112
|
+
expect(data_source.action_options).to have_key('test2')
|
113
|
+
expect(data_source.action_options['test2']).to eq('thing: aout')
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|