producer-core 0.2.5 → 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/features/{actions/echo.feature → action_echo.feature} +1 -1
- data/features/{actions/file_append.feature → action_file_append.feature} +1 -1
- data/features/{actions/file_replace_content.feature → action_file_replace_content.feature} +11 -14
- data/features/{actions/file_write.feature → action_file_write.feature} +7 -12
- data/features/{actions/mkdir.feature → action_mkdir.feature} +8 -13
- data/features/{actions/sh.feature → action_sh.feature} +14 -14
- data/features/{cli/dry_run.feature → cli_dry_run.feature} +0 -0
- data/features/{cli/usage.feature → cli_usage.feature} +1 -0
- data/features/{cli/verbose.feature → cli_verbose.feature} +12 -23
- data/features/{recipes/ask.feature → recipe_ask.feature} +1 -0
- data/features/{recipes/macro.feature → recipe_macro.feature} +4 -4
- data/features/{recipes/source.feature → recipe_source.feature} +3 -1
- data/features/{recipes/target.feature → recipe_target.feature} +3 -1
- data/features/recipe_test_macro.feature +52 -0
- data/features/{recipes/registry.feature → registry.feature} +9 -4
- data/features/{ssh/config.feature → ssh_config.feature} +3 -1
- data/features/support/env.rb +32 -0
- data/features/support/env_aruba_timeout.rb +3 -0
- data/features/{tasks/condition.feature → task_condition.feature} +1 -1
- data/features/{tests/dir.feature → test_dir.feature} +1 -1
- data/features/{tests/env.feature → test_env.feature} +24 -34
- data/features/{tests/executable.feature → test_executable.feature} +12 -14
- data/features/{tests/file.feature → test_file.feature} +1 -1
- data/features/{tests/file_contains.feature → test_file_contains.feature} +1 -1
- data/features/{tests/negated_test.feature → test_negated_test.feature} +0 -0
- data/features/test_shell_command_status.feature +48 -0
- data/lib/producer/core/cli.rb +19 -15
- data/lib/producer/core/condition/dsl.rb +17 -8
- data/lib/producer/core/condition.rb +2 -2
- data/lib/producer/core/env.rb +6 -10
- data/lib/producer/core/errors.rb +2 -1
- data/lib/producer/core/recipe/dsl.rb +4 -0
- data/lib/producer/core/remote.rb +1 -1
- data/lib/producer/core/tests/condition_test.rb +23 -0
- data/lib/producer/core/version.rb +1 -1
- data/lib/producer/core.rb +1 -0
- data/spec/producer/core/cli_spec.rb +73 -44
- data/spec/producer/core/condition/dsl_spec.rb +33 -5
- data/spec/producer/core/env_spec.rb +41 -36
- data/spec/producer/core/recipe/dsl_spec.rb +10 -0
- data/spec/producer/core/remote_spec.rb +16 -7
- data/spec/producer/core/tests/condition_test_spec.rb +55 -0
- metadata +56 -55
- data/features/recipes/evaluation.feature +0 -9
- data/features/tasks/evaluation.feature +0 -11
- data/features/tasks/registry.feature +0 -13
- data/features/tests/shell_command_status.feature +0 -58
data/lib/producer/core.rb
CHANGED
@@ -16,6 +16,7 @@ require 'producer/core/actions/file_writer'
|
|
16
16
|
|
17
17
|
# condition tests (need to be defined before the condition DSL)
|
18
18
|
require 'producer/core/test'
|
19
|
+
require 'producer/core/tests/condition_test'
|
19
20
|
require 'producer/core/tests/file_contains'
|
20
21
|
require 'producer/core/tests/has_dir'
|
21
22
|
require 'producer/core/tests/has_env'
|
@@ -8,64 +8,89 @@ module Producer::Core
|
|
8
8
|
let(:recipe_file) { fixture_path_for 'recipes/some_recipe.rb' }
|
9
9
|
let(:options) { [] }
|
10
10
|
let(:arguments) { [*options, recipe_file] }
|
11
|
+
let(:stdin) { StringIO.new}
|
11
12
|
let(:stdout) { StringIO.new }
|
13
|
+
let(:stderr) { StringIO.new }
|
12
14
|
|
13
|
-
subject(:cli) { CLI.new(arguments, stdout: stdout) }
|
15
|
+
subject(:cli) { CLI.new(arguments, stdin: stdin, stdout: stdout) }
|
14
16
|
|
15
17
|
describe '.run!' do
|
16
|
-
let(:cli)
|
17
|
-
let(:output) { StringIO.new }
|
18
|
-
subject(:run) { described_class.run! arguments, output: output }
|
18
|
+
let(:cli) { double('cli').as_null_object }
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
subject(:run) do
|
21
|
+
described_class.run! arguments,
|
22
|
+
stdin: stdin,
|
23
|
+
stdout: stdout,
|
24
|
+
stderr: stderr
|
25
|
+
end
|
26
|
+
|
27
|
+
before { allow(described_class).to receive(:new) { cli } }
|
28
|
+
|
29
|
+
it 'builds a new CLI with given arguments and streams' do
|
30
|
+
expect(described_class).to receive(:new).with(arguments,
|
31
|
+
stdin: stdin,
|
32
|
+
stdout: stdout,
|
33
|
+
stderr: stderr
|
34
|
+
)
|
23
35
|
run
|
24
36
|
end
|
25
37
|
|
26
38
|
it 'runs the CLI' do
|
27
|
-
allow(described_class).to receive(:new) { cli }
|
28
39
|
expect(cli).to receive :run
|
29
40
|
run
|
30
41
|
end
|
31
42
|
|
32
43
|
it 'parses CLI arguments' do
|
33
|
-
allow(described_class).to receive(:new) { cli }
|
34
44
|
expect(cli).to receive :parse_arguments!
|
35
45
|
run
|
36
46
|
end
|
37
47
|
|
38
48
|
context 'when an argument error is raised' do
|
39
49
|
before do
|
40
|
-
allow(described_class).to receive(:new) { cli }
|
41
50
|
allow(cli).to receive(:parse_arguments!)
|
42
51
|
.and_raise described_class::ArgumentError
|
43
52
|
end
|
44
53
|
|
45
54
|
it 'exits with a return status of 64' do
|
46
|
-
expect { run }.to raise_error(SystemExit)
|
55
|
+
expect { run }.to raise_error(SystemExit) do |e|
|
47
56
|
expect(e.status).to eq 64
|
48
|
-
|
57
|
+
end
|
49
58
|
end
|
50
59
|
|
51
|
-
it 'prints the usage' do
|
60
|
+
it 'prints the usage on the error stream' do
|
52
61
|
trap_exit { run }
|
53
|
-
expect(
|
62
|
+
expect(stderr.string).to match /\AUsage: .+/
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when a runtime error is raised' do
|
67
|
+
before do
|
68
|
+
allow(cli).to receive(:run)
|
69
|
+
.and_raise RuntimeError, 'some message'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'exits with a return status of 70' do
|
73
|
+
expect { run }.to raise_error(SystemExit) do |e|
|
74
|
+
expect(e.status).to eq 70
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'prints exception name and message and the error stream' do
|
79
|
+
trap_exit { run }
|
80
|
+
expect(stderr.string).to match /\ARuntimeError: some message/
|
54
81
|
end
|
55
82
|
end
|
56
83
|
end
|
57
84
|
|
58
85
|
describe '#initialize' do
|
59
|
-
|
60
|
-
expect(cli.env.output).to be stdout
|
61
|
-
end
|
86
|
+
subject(:cli) { described_class.new(arguments) }
|
62
87
|
|
63
|
-
|
64
|
-
|
88
|
+
it 'assigns $stdin as the default standard input' do
|
89
|
+
expect(cli.stdin).to be $stdin
|
90
|
+
end
|
65
91
|
|
66
|
-
|
67
|
-
|
68
|
-
end
|
92
|
+
it 'assigns $stdout as the default standard output' do
|
93
|
+
expect(cli.stdout).to be $stdout
|
69
94
|
end
|
70
95
|
end
|
71
96
|
|
@@ -81,6 +106,20 @@ module Producer::Core
|
|
81
106
|
end
|
82
107
|
end
|
83
108
|
|
109
|
+
describe '#env' do
|
110
|
+
it 'returns the assigned env' do
|
111
|
+
expect(cli.env).to be_an Env
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'assigns CLI stdin as the env input' do
|
115
|
+
expect(cli.env.input).to be stdin
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'assigns CLI stdout as the env output' do
|
119
|
+
expect(cli.env.output).to be stdout
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
84
123
|
describe '#parse_arguments!' do
|
85
124
|
context 'with options' do
|
86
125
|
let(:options) { %w[-v] }
|
@@ -92,15 +131,15 @@ module Producer::Core
|
|
92
131
|
end
|
93
132
|
|
94
133
|
context 'verbose' do
|
95
|
-
it '
|
96
|
-
expect(cli.env
|
134
|
+
it 'enables env verbose mode' do
|
135
|
+
expect(cli.env).to be_verbose
|
97
136
|
end
|
98
137
|
end
|
99
138
|
|
100
139
|
context 'dry run' do
|
101
140
|
let(:options) { %w[-n] }
|
102
141
|
|
103
|
-
it 'enables env dry run' do
|
142
|
+
it 'enables env dry run mode' do
|
104
143
|
expect(cli.env).to be_dry_run
|
105
144
|
end
|
106
145
|
end
|
@@ -116,21 +155,12 @@ module Producer::Core
|
|
116
155
|
end
|
117
156
|
|
118
157
|
describe '#run' do
|
119
|
-
it 'loads the recipe' do
|
120
|
-
cli.run
|
121
|
-
expect(cli.recipe).to be_a Recipe
|
122
|
-
end
|
123
|
-
|
124
158
|
it 'process recipe tasks with given worker' do
|
125
159
|
worker = double 'worker'
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
describe '#env' do
|
132
|
-
it 'returns an env' do
|
133
|
-
expect(cli.env).to be_an Env
|
160
|
+
allow(cli).to receive(:worker) { worker }
|
161
|
+
expect(worker).to receive(:process)
|
162
|
+
.with([an_instance_of(Task), an_instance_of(Task)])
|
163
|
+
cli.run
|
134
164
|
end
|
135
165
|
end
|
136
166
|
|
@@ -141,19 +171,18 @@ module Producer::Core
|
|
141
171
|
cli.load_recipe
|
142
172
|
end
|
143
173
|
|
144
|
-
it '
|
145
|
-
cli.load_recipe
|
146
|
-
expect(cli.recipe.tasks.count).to be 2
|
174
|
+
it 'returns the recipe' do
|
175
|
+
expect(cli.load_recipe).to be_a Recipe
|
147
176
|
end
|
148
177
|
end
|
149
178
|
|
150
|
-
describe '#
|
179
|
+
describe '#worker' do
|
151
180
|
it 'returns a worker' do
|
152
|
-
expect(cli.
|
181
|
+
expect(cli.worker).to be_a Worker
|
153
182
|
end
|
154
183
|
|
155
184
|
it 'assigns the CLI env' do
|
156
|
-
expect(cli.
|
185
|
+
expect(cli.worker.env).to eq cli.env
|
157
186
|
end
|
158
187
|
end
|
159
188
|
end
|
@@ -22,9 +22,9 @@ module Producer::Core
|
|
22
22
|
end
|
23
23
|
|
24
24
|
describe '.define_test' do
|
25
|
-
let(:
|
25
|
+
let(:some_test) { Test }
|
26
26
|
|
27
|
-
before { described_class.define_test(:some_test,
|
27
|
+
before { described_class.define_test(:some_test, some_test) }
|
28
28
|
|
29
29
|
it 'defines a new test keyword' do
|
30
30
|
expect(dsl).to respond_to :some_test
|
@@ -41,19 +41,38 @@ module Producer::Core
|
|
41
41
|
|
42
42
|
it 'registers the test with current env' do
|
43
43
|
dsl.some_test
|
44
|
-
expect(dsl.tests.
|
44
|
+
expect(dsl.tests.last.env).to be env
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'registers the test with given arguments' do
|
48
48
|
dsl.some_test :some, :args
|
49
|
-
expect(dsl.tests.
|
49
|
+
expect(dsl.tests.last.arguments).to eq [:some, :args]
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when given test is callable' do
|
53
|
+
let(:some_test) { proc {} }
|
54
|
+
|
55
|
+
before { dsl.some_test }
|
56
|
+
|
57
|
+
it 'registers a condition test' do
|
58
|
+
expect(dsl.tests.last).to be_a Tests::ConditionTest
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'registers the test with given block' do
|
62
|
+
expect(dsl.tests.last.condition_block).to be some_test
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'registers the test with given arguments' do
|
66
|
+
dsl.some_test :some, :args
|
67
|
+
expect(dsl.tests.last.condition_args).to eq [:some, :args]
|
68
|
+
end
|
50
69
|
end
|
51
70
|
end
|
52
71
|
|
53
72
|
context 'when a negated test keyword is called' do
|
54
73
|
it 'registers a negated test' do
|
55
74
|
dsl.no_some_test
|
56
|
-
expect(dsl.tests.
|
75
|
+
expect(dsl.tests.last).to be_negated
|
57
76
|
end
|
58
77
|
end
|
59
78
|
end
|
@@ -81,6 +100,15 @@ module Producer::Core
|
|
81
100
|
it 'returns the value returned by the assigned block' do
|
82
101
|
expect(dsl.evaluate).to eq block.call
|
83
102
|
end
|
103
|
+
|
104
|
+
context 'when arguments are given' do
|
105
|
+
let(:block) { proc { |e| throw e } }
|
106
|
+
|
107
|
+
it 'passes arguments as block parameters' do
|
108
|
+
expect { dsl.evaluate :some_argument }
|
109
|
+
.to throw_symbol :some_argument
|
110
|
+
end
|
111
|
+
end
|
84
112
|
end
|
85
113
|
end
|
86
114
|
end
|
@@ -3,10 +3,10 @@ require 'spec_helper'
|
|
3
3
|
module Producer::Core
|
4
4
|
describe Env do
|
5
5
|
let(:output) { StringIO.new }
|
6
|
-
subject(:env) {
|
6
|
+
subject(:env) { described_class.new(output: output) }
|
7
7
|
|
8
8
|
describe '#initialize' do
|
9
|
-
it 'assigns $stdin as the default
|
9
|
+
it 'assigns $stdin as the default input' do
|
10
10
|
expect(env.input).to be $stdin
|
11
11
|
end
|
12
12
|
|
@@ -18,12 +18,16 @@ module Producer::Core
|
|
18
18
|
expect(env.registry).to be_empty
|
19
19
|
end
|
20
20
|
|
21
|
+
it 'assigns verbose as false' do
|
22
|
+
expect(env.verbose).to be false
|
23
|
+
end
|
24
|
+
|
21
25
|
it 'assigns dry run as false' do
|
22
26
|
expect(env.dry_run).to be false
|
23
27
|
end
|
24
28
|
|
25
29
|
context 'when output is not given as argument' do
|
26
|
-
subject(:env) {
|
30
|
+
subject(:env) { described_class.new }
|
27
31
|
|
28
32
|
it 'assigns $stdout as the default output' do
|
29
33
|
expect(env.output).to be $stdout
|
@@ -60,31 +64,12 @@ module Producer::Core
|
|
60
64
|
describe '#target' do
|
61
65
|
let(:target) { double 'target' }
|
62
66
|
|
63
|
-
it 'returns the
|
67
|
+
it 'returns the assigned target' do
|
64
68
|
env.target = target
|
65
69
|
expect(env.target).to be target
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
69
|
-
describe '#logger' do
|
70
|
-
it 'returns a logger' do
|
71
|
-
expect(env.logger).to be_a Logger
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'uses env output' do
|
75
|
-
env.logger.error 'some message'
|
76
|
-
expect(output.string).to include 'some message'
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'has a log level of ERROR' do
|
80
|
-
expect(env.log_level).to eq Logger::ERROR
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'uses our formatter' do
|
84
|
-
expect(env.logger.formatter).to be_a LoggerFormatter
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
73
|
describe '#remote' do
|
89
74
|
it 'builds a Remote with the current target' do
|
90
75
|
env.target = 'some_hostname.example'
|
@@ -118,6 +103,33 @@ module Producer::Core
|
|
118
103
|
end
|
119
104
|
end
|
120
105
|
|
106
|
+
describe '#logger' do
|
107
|
+
it 'returns a logger' do
|
108
|
+
expect(env.logger).to be_a Logger
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'uses env output' do
|
112
|
+
env.logger.error 'some message'
|
113
|
+
expect(output.string).to include 'some message'
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'has a log level of ERROR' do
|
117
|
+
expect(env.logger.level).to eq Logger::ERROR
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'uses our formatter' do
|
121
|
+
expect(env.logger.formatter).to be_a LoggerFormatter
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'when verbose mode is enabled' do
|
125
|
+
before { env.verbose = true }
|
126
|
+
|
127
|
+
it 'has a log level of INFO' do
|
128
|
+
expect(env.logger.level).to eq Logger::INFO
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
121
133
|
describe '#log' do
|
122
134
|
it 'logs an info message through the assigned logger' do
|
123
135
|
expect(env.logger).to receive(:info).with 'message'
|
@@ -125,24 +137,17 @@ module Producer::Core
|
|
125
137
|
end
|
126
138
|
end
|
127
139
|
|
128
|
-
describe '#
|
129
|
-
it 'returns
|
130
|
-
|
131
|
-
|
132
|
-
end
|
133
|
-
|
134
|
-
describe '#log_level=' do
|
135
|
-
it 'sets the logger level' do
|
136
|
-
env.log_level = Logger::DEBUG
|
137
|
-
expect(env.logger.level).to eq Logger::DEBUG
|
140
|
+
describe '#verbose?' do
|
141
|
+
it 'returns true when verbose is enabled' do
|
142
|
+
env.verbose = true
|
143
|
+
expect(env).to be_verbose
|
138
144
|
end
|
139
145
|
end
|
140
146
|
|
141
147
|
describe '#dry_run?' do
|
142
|
-
before { env.dry_run = true }
|
143
|
-
|
144
148
|
it 'returns true when dry run is enabled' do
|
145
|
-
|
149
|
+
env.dry_run = true
|
150
|
+
expect(env).to be_dry_run
|
146
151
|
end
|
147
152
|
end
|
148
153
|
end
|
@@ -102,6 +102,16 @@ module Producer::Core
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
+
describe '#test_macro' do
|
106
|
+
it 'defines the new test' do
|
107
|
+
condition_dsl = double 'condition dsl'
|
108
|
+
test_block = proc {}
|
109
|
+
expect(condition_dsl)
|
110
|
+
.to receive(:define_test).with(:some_test, test_block)
|
111
|
+
dsl.test_macro(:some_test, dsl: condition_dsl, &test_block)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
105
115
|
describe '#set' do
|
106
116
|
it 'registers a key/value pair in env registry' do
|
107
117
|
dsl.set :some_key, :some_value
|
@@ -106,14 +106,23 @@ module Producer::Core
|
|
106
106
|
expect(output.string).to eq arguments
|
107
107
|
end
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
ch
|
112
|
-
|
113
|
-
|
109
|
+
context 'when command execution fails' do
|
110
|
+
before do
|
111
|
+
story_with_new_channel do |ch|
|
112
|
+
ch.sends_exec command
|
113
|
+
ch.gets_data arguments
|
114
|
+
ch.gets_exit_status 1
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'raises an exception' do
|
119
|
+
expect { remote.execute command }
|
120
|
+
.to raise_error(RemoteCommandExecutionError)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'includes the command in the exception message' do
|
124
|
+
expect { remote.execute command }.to raise_error /#{command}/
|
114
125
|
end
|
115
|
-
expect { remote.execute command }
|
116
|
-
.to raise_error(RemoteCommandExecutionError)
|
117
126
|
end
|
118
127
|
end
|
119
128
|
|