producer-core 0.2.5 → 0.2.6
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.
- 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
|
|