producer-core 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +12 -144
- data/bin/producer +1 -1
- data/lib/producer/core/action.rb +4 -3
- data/lib/producer/core/actions/file_writer.rb +1 -7
- data/lib/producer/core/cli.rb +19 -71
- data/lib/producer/core/env.rb +7 -23
- data/lib/producer/core/errors.rb +11 -9
- data/lib/producer/core/remote.rb +7 -1
- data/lib/producer/core/task.rb +0 -1
- data/lib/producer/core/testing/cucumber/etc_steps.rb +1 -1
- data/lib/producer/core/testing/cucumber/recipe_steps.rb +18 -19
- data/lib/producer/core/testing/cucumber/remote_steps.rb +9 -15
- data/lib/producer/core/testing/cucumber/ssh_steps.rb +9 -1
- data/lib/producer/core/testing/cucumber.rb +1 -29
- data/lib/producer/core/version.rb +1 -1
- data/lib/producer/core.rb +1 -1
- metadata +25 -42
- data/lib/producer/core/actions/yaml_writer.rb +0 -22
- data/lib/producer/core/testing/aruba_program_wrapper.rb +0 -24
- data/lib/producer/core/testing/cucumber/execution_steps.rb +0 -3
- data/lib/producer/core/testing/cucumber/output_steps.rb +0 -47
- data/lib/producer/core/testing.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2cad65cc103070c2e168b124dec1d018d3a133cae0a6d8135766c321b1e62898
|
4
|
+
data.tar.gz: a1d7a87ac02475c992a3c448ddd0a1ca6c7b750d2a7d568bd846ec94911390e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 786dbe20ba244351fd32a7f05f2cba1ea947515cf090ea1d9274f55d28ca6bf92e3a8f1e45c091dc75ac69e461303e65c24fb39cc0612652edfc7a6822fcc3e0
|
7
|
+
data.tar.gz: 0c220841cab6fe26cb7261598a945d9b21d99fdb8469c1e3710533421347726d74b22e28c7262b1795393c186a82a980f8760d448fef6f1f5474e603d3a351bf
|
data/README.md
CHANGED
@@ -1,47 +1,23 @@
|
|
1
1
|
producer
|
2
2
|
========
|
3
3
|
|
4
|
-
|
5
|
-
DSL to
|
6
|
-
|
7
|
-
[![Version ][badge-version-img]][badge-version-uri]
|
8
|
-
[![Build status ][badge-build-img]][badge-build-uri]
|
9
|
-
[![Code Climate ][badge-cclimate-img]][badge-cclimate-uri]
|
4
|
+
producer-core is a software configuration management tool providing
|
5
|
+
a DSL to describe infrastructure as code. It helps automating software
|
6
|
+
deployment, configuration and management.
|
10
7
|
|
11
8
|
|
12
9
|
Getting started
|
13
10
|
---------------
|
14
11
|
|
15
|
-
### Installation (requires ruby
|
16
|
-
|
17
|
-
$ gem install producer-core
|
12
|
+
### Installation (requires ruby and rubygems)
|
18
13
|
|
19
|
-
|
20
|
-
### Simple recipe
|
21
|
-
|
22
|
-
Recipes are composed by tasks and a task includes actions. Here we
|
23
|
-
use the `echo` action, which output the given string to standard
|
24
|
-
output. All the power of the Ruby language is available.
|
25
|
-
|
26
|
-
```ruby
|
27
|
-
hello_message = 'hello world!'
|
28
|
-
|
29
|
-
task :hello_world do
|
30
|
-
echo hello_message
|
31
|
-
echo hello_message.upcase
|
32
|
-
end
|
33
|
-
```
|
34
|
-
|
35
|
-
$ producer simple_recipe.rb
|
36
|
-
hello world!
|
37
|
-
HELLO WORLD!
|
14
|
+
gem install producer-core
|
38
15
|
|
39
16
|
|
40
17
|
### Shell command execution on remote host
|
41
18
|
|
42
|
-
The `sh` action will execute a shell command
|
43
|
-
|
44
|
-
CLI option `-t`.
|
19
|
+
The `sh` action will execute a shell command on the targeted remote
|
20
|
+
host. The remote host can be specified with the CLI option `-t`.
|
45
21
|
|
46
22
|
```ruby
|
47
23
|
task :show_zsh_pkg do
|
@@ -49,7 +25,7 @@ task :show_zsh_pkg do
|
|
49
25
|
end
|
50
26
|
```
|
51
27
|
|
52
|
-
|
28
|
+
% producer -t localhost show_zsh_pkg.rb
|
53
29
|
zsh-5.0.7 The Z shell
|
54
30
|
|
55
31
|
When execution fails, recipe processing is stopped and the action
|
@@ -62,9 +38,9 @@ task :sh_fail do
|
|
62
38
|
end
|
63
39
|
```
|
64
40
|
|
65
|
-
|
41
|
+
% producer -t localhost sh_fail.rb
|
66
42
|
RemoteCommandExecutionError: false
|
67
|
-
|
43
|
+
%
|
68
44
|
|
69
45
|
Only the first action is applied.
|
70
46
|
|
@@ -74,8 +50,6 @@ end
|
|
74
50
|
A task can be bound to a condition: when the condition fails actions
|
75
51
|
are skipped, otherwise actions are applied as usual.
|
76
52
|
|
77
|
-
This condition can be a simple ruby expression :
|
78
|
-
|
79
53
|
```ruby
|
80
54
|
task :condition_pass do
|
81
55
|
condition { true }
|
@@ -88,16 +62,13 @@ task :condition_fail do
|
|
88
62
|
end
|
89
63
|
```
|
90
64
|
|
65
|
+
|
91
66
|
#### Built-in tests
|
92
67
|
|
93
68
|
Specific test keywords are also available in the condition block
|
94
69
|
context, `producer-core` ships with a few common tests,
|
95
70
|
`producer-stdlib` provides more, and custom tests can be defined.
|
96
71
|
|
97
|
-
Here we use the `sh` condition keyword which will pass when the
|
98
|
-
execution of the given shell command succeed, and fail when the
|
99
|
-
execution fails.
|
100
|
-
|
101
72
|
```ruby
|
102
73
|
task :condition_sh_pass do
|
103
74
|
condition { sh 'true' }
|
@@ -128,105 +99,11 @@ task :main_task do
|
|
128
99
|
end
|
129
100
|
end
|
130
101
|
```
|
131
|
-
|
102
|
+
% producer nested_tasks.rb
|
132
103
|
do foo
|
133
104
|
do bar
|
134
105
|
|
135
106
|
|
136
|
-
Usage
|
137
|
-
-----
|
138
|
-
|
139
|
-
Usage: producer [options] [recipes] [-- recipe_arguments...]
|
140
|
-
|
141
|
-
options:
|
142
|
-
-v, --verbose enable verbose mode
|
143
|
-
-d, --debug enable debug mode
|
144
|
-
-n, --dry-run enable dry run mode
|
145
|
-
-t, --target HOST target host
|
146
|
-
|
147
|
-
|
148
|
-
Actions
|
149
|
-
-------
|
150
|
-
|
151
|
-
See:
|
152
|
-
https://github.com/tjouan/producer-core/tree/master/features/actions
|
153
|
-
|
154
|
-
|
155
|
-
Tests
|
156
|
-
-----
|
157
|
-
|
158
|
-
See:
|
159
|
-
https://github.com/tjouan/producer-core/tree/master/features/tests
|
160
|
-
|
161
|
-
|
162
|
-
Templates
|
163
|
-
---------
|
164
|
-
|
165
|
-
The following example can setup jails on a FreeBSD host.
|
166
|
-
|
167
|
-
In `templates/freebsd/jail.conf.erb`:
|
168
|
-
|
169
|
-
```erb
|
170
|
-
exec.start = "/bin/sh /etc/rc";
|
171
|
-
exec.stop = "/bin/sh /etc/rc.shutdown";
|
172
|
-
exec.clean;
|
173
|
-
mount.devfs;
|
174
|
-
allow.chflags;
|
175
|
-
|
176
|
-
path = "/var/jails/$name";
|
177
|
-
|
178
|
-
<% @jails.each do |jail| -%>
|
179
|
-
<%= jail[:name] %> {
|
180
|
-
interface "<%= @if %>";
|
181
|
-
ip4.addr = <%= jail[:addr4] %>;
|
182
|
-
}
|
183
|
-
<% end -%>
|
184
|
-
```
|
185
|
-
|
186
|
-
Simple usage:
|
187
|
-
|
188
|
-
```ruby
|
189
|
-
INTERFACE = 're0'.freeze
|
190
|
-
JAILS = [{
|
191
|
-
name: 'freebsd-10r1',
|
192
|
-
src: true,
|
193
|
-
addr4: '10.0.0.1'
|
194
|
-
}].freeze
|
195
|
-
|
196
|
-
task :jails_conf do
|
197
|
-
conf = template 'freebsd/jail.conf', if: INTERFACE, jails: JAILS
|
198
|
-
file_write_once '/etc/jail.conf', conf
|
199
|
-
end
|
200
|
-
```
|
201
|
-
|
202
|
-
|
203
|
-
Macros
|
204
|
-
------
|
205
|
-
|
206
|
-
FIXME
|
207
|
-
|
208
|
-
|
209
|
-
Test macros
|
210
|
-
-----------
|
211
|
-
|
212
|
-
FIXME
|
213
|
-
|
214
|
-
|
215
|
-
Macro composition
|
216
|
-
-----------------
|
217
|
-
|
218
|
-
FIXME
|
219
|
-
|
220
|
-
|
221
|
-
Background
|
222
|
-
----------
|
223
|
-
|
224
|
-
producer started as a collection of heterogeneous scripts (Ruby,
|
225
|
-
POSIX shell, Perl…) in the late '90s. I wanted to experiment with the
|
226
|
-
design and usage of Domain Specific Languages in Ruby, and refactor
|
227
|
-
all my scripts as "recipes" in a common language.
|
228
|
-
|
229
|
-
|
230
107
|
Similar or related code and tools
|
231
108
|
---------------------------------
|
232
109
|
|
@@ -272,12 +149,3 @@ Similar or related code and tools
|
|
272
149
|
* https://github.com/auxesis/cucumber-nagios (Cucumber, Net::SSH,
|
273
150
|
Webrat)
|
274
151
|
* http://larsyencken.github.io/marelle/ (Prolog, babushka inspired)
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
[badge-version-img]: https://img.shields.io/gem/v/producer-core.svg?style=flat-square
|
279
|
-
[badge-version-uri]: https://rubygems.org/gems/producer-core
|
280
|
-
[badge-build-img]: https://img.shields.io/travis/tjouan/producer-core/master.svg?style=flat-square
|
281
|
-
[badge-build-uri]: https://travis-ci.org/tjouan/producer-core
|
282
|
-
[badge-cclimate-img]: https://img.shields.io/codeclimate/github/tjouan/producer-core.svg?style=flat-square
|
283
|
-
[badge-cclimate-uri]: https://codeclimate.com/github/tjouan/producer-core
|
data/bin/producer
CHANGED
data/lib/producer/core/action.rb
CHANGED
@@ -4,15 +4,16 @@ module Producer
|
|
4
4
|
INSPECT_ARGUMENTS_SUM_LEN = 68
|
5
5
|
|
6
6
|
extend Forwardable
|
7
|
-
def_delegators :@env, :input, :output, :
|
7
|
+
def_delegators :@env, :input, :output, :remote
|
8
|
+
def_delegator :@env, :output_error, :error_output
|
8
9
|
def_delegators :remote, :fs
|
9
10
|
|
10
11
|
attr_reader :env, :arguments, :options
|
11
12
|
|
12
|
-
def initialize env, *args
|
13
|
+
def initialize env, *args
|
13
14
|
@env = env
|
14
15
|
@arguments = args
|
15
|
-
@options =
|
16
|
+
@options = @arguments[-1].kind_of?(Hash) ? @arguments.pop : {}
|
16
17
|
setup if respond_to? :setup
|
17
18
|
end
|
18
19
|
|
@@ -3,7 +3,7 @@ module Producer
|
|
3
3
|
module Actions
|
4
4
|
class FileWriter < Action
|
5
5
|
def setup
|
6
|
-
check_arguments_size!
|
6
|
+
check_arguments_size! 2
|
7
7
|
@path, @content = arguments
|
8
8
|
convert_options mode: :permissions, user: :owner
|
9
9
|
end
|
@@ -16,12 +16,6 @@ module Producer
|
|
16
16
|
fs.file_write @path, @content
|
17
17
|
fs.setstat @path, options unless options.empty?
|
18
18
|
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def arguments_size
|
23
|
-
2
|
24
|
-
end
|
25
19
|
end
|
26
20
|
end
|
27
21
|
end
|
data/lib/producer/core/cli.rb
CHANGED
@@ -1,106 +1,54 @@
|
|
1
1
|
module Producer
|
2
2
|
module Core
|
3
|
-
class CLI
|
3
|
+
class CLI < Baf::CLI
|
4
4
|
ArgumentError = Class.new(ArgumentError)
|
5
5
|
|
6
6
|
USAGE =
|
7
7
|
"Usage: #{File.basename $0} [options] [recipes] [-- recipe_argument...]"
|
8
8
|
.freeze
|
9
9
|
|
10
|
-
EX_USAGE = 64
|
11
|
-
EX_SOFTWARE = 70
|
12
|
-
|
13
10
|
ARGUMENTS_SEPARATOR = '--'.freeze
|
14
11
|
|
15
|
-
ENV_VERBOSE_KEY = 'PRODUCER_VERBOSE'.freeze
|
16
|
-
ENV_DEBUG_KEY = 'PRODUCER_DEBUG'.freeze
|
17
|
-
ENV_DRYRUN_KEY = 'PRODUCER_DRYRUN'.freeze
|
18
|
-
|
19
12
|
class << self
|
20
|
-
def
|
21
|
-
|
22
|
-
cli.parse_arguments!
|
23
|
-
cli.run
|
24
|
-
rescue ArgumentError => e
|
25
|
-
stderr.puts e.message
|
26
|
-
exit EX_USAGE
|
27
|
-
rescue StandardError => e
|
28
|
-
stderr.puts ErrorFormatter.new(debug: cli.env.debug?).format e
|
29
|
-
exit EX_SOFTWARE
|
13
|
+
def handle_error env, ex
|
14
|
+
env.puts_error ErrorFormatter.new(debug: env.debug?).format ex
|
30
15
|
end
|
31
16
|
end
|
32
17
|
|
33
|
-
|
18
|
+
def setup
|
19
|
+
banner USAGE
|
34
20
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@stdin = stdin
|
39
|
-
@stdout = stdout
|
40
|
-
@stderr = stderr
|
41
|
-
@env = build_env
|
21
|
+
flag_verbose
|
22
|
+
flag_debug
|
23
|
+
flag_version Producer::Core::VERSION
|
42
24
|
|
43
|
-
|
25
|
+
flag :n, :dry_run, 'enable dry run mode'
|
26
|
+
option :t, :target, 'HOST', 'target host'
|
44
27
|
end
|
45
28
|
|
46
29
|
def parse_arguments!
|
47
|
-
if
|
48
|
-
@arguments,
|
30
|
+
if arguments.include? ARGUMENTS_SEPARATOR
|
31
|
+
@arguments, env.recipe_argv = split_arguments_lists arguments
|
49
32
|
end
|
50
|
-
|
51
|
-
|
52
|
-
rescue OptionParser::InvalidOption
|
53
|
-
raise ArgumentError, option_parser
|
33
|
+
super
|
34
|
+
usage! if arguments.empty?
|
54
35
|
end
|
55
36
|
|
56
|
-
def run worker: Worker.new(
|
37
|
+
def run worker: Worker.new(env)
|
57
38
|
evaluate_recipes.each { |recipe| worker.process recipe.tasks }
|
58
39
|
ensure
|
59
|
-
|
40
|
+
env.cleanup
|
60
41
|
end
|
61
42
|
|
62
43
|
def evaluate_recipes
|
63
|
-
|
44
|
+
arguments.map { |e| Recipe::FileEvaluator.evaluate(e, env) }
|
64
45
|
end
|
65
46
|
|
66
47
|
private
|
67
48
|
|
68
|
-
def build_env
|
69
|
-
Env.new(input: @stdin, output: @stdout, error_output: @stderr)
|
70
|
-
end
|
71
|
-
|
72
|
-
def configure_environment! environment
|
73
|
-
@env.verbose = true if environment.key? ENV_VERBOSE_KEY
|
74
|
-
@env.debug = true if environment.key? ENV_DEBUG_KEY
|
75
|
-
@env.dry_run = true if environment.key? ENV_DRYRUN_KEY
|
76
|
-
end
|
77
|
-
|
78
49
|
def split_arguments_lists arguments
|
79
|
-
arguments
|
80
|
-
|
81
|
-
.reject { |a, _| a }
|
82
|
-
.map &:last
|
83
|
-
end
|
84
|
-
|
85
|
-
def option_parser
|
86
|
-
OptionParser.new do |opts|
|
87
|
-
opts.banner = USAGE
|
88
|
-
opts.separator ''
|
89
|
-
opts.separator 'options:'
|
90
|
-
|
91
|
-
option_parser_add_boolean_options opts
|
92
|
-
opts.on '-t', '--target HOST', 'target host' do |e|
|
93
|
-
env.target = e
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def option_parser_add_boolean_options opts
|
99
|
-
{ v: 'verbose', d: 'debug', n: 'dry run' }.each do |k, v|
|
100
|
-
opts.on "-#{k}", "--#{v.tr ' ', '-'}", "enable #{v} mode" do
|
101
|
-
env.send "#{v.tr ' ', '_'}=", true
|
102
|
-
end
|
103
|
-
end
|
50
|
+
head, tail = arguments.slice_after(ARGUMENTS_SEPARATOR).to_a
|
51
|
+
[head[0..-2], tail]
|
104
52
|
end
|
105
53
|
end
|
106
54
|
end
|
data/lib/producer/core/env.rb
CHANGED
@@ -1,20 +1,16 @@
|
|
1
1
|
module Producer
|
2
2
|
module Core
|
3
|
-
class Env
|
3
|
+
class Env < Baf::Env
|
4
4
|
extend Forwardable
|
5
5
|
def_delegators :@registry, :[]=, :key?
|
6
6
|
|
7
|
-
attr_reader
|
8
|
-
attr_accessor :
|
7
|
+
attr_reader :input, :output, :output_error, :registry, :logger
|
8
|
+
attr_accessor :recipe_argv
|
9
9
|
|
10
|
-
def initialize
|
11
|
-
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@output = output
|
15
|
-
@error_output = error_output
|
16
|
-
@remote = remote
|
17
|
-
@registry = registry
|
10
|
+
def initialize remote: nil, registry: {}, **opts
|
11
|
+
super **opts
|
12
|
+
@remote = remote
|
13
|
+
@registry = registry
|
18
14
|
end
|
19
15
|
|
20
16
|
def remote
|
@@ -39,18 +35,6 @@ module Producer
|
|
39
35
|
logger.send severity, message
|
40
36
|
end
|
41
37
|
|
42
|
-
def verbose?
|
43
|
-
@verbose
|
44
|
-
end
|
45
|
-
|
46
|
-
def debug?
|
47
|
-
@debug
|
48
|
-
end
|
49
|
-
|
50
|
-
def dry_run?
|
51
|
-
@dry_run
|
52
|
-
end
|
53
|
-
|
54
38
|
def cleanup
|
55
39
|
remote.cleanup
|
56
40
|
end
|
data/lib/producer/core/errors.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
module Producer
|
2
2
|
module Core
|
3
|
-
Error
|
4
|
-
RuntimeError
|
3
|
+
Error = Class.new StandardError
|
4
|
+
RuntimeError = Class.new RuntimeError
|
5
5
|
|
6
|
-
ArgumentError
|
7
|
-
ConditionNotMetError
|
8
|
-
RecipeEvaluationError
|
9
|
-
|
10
|
-
|
11
|
-
RemoteInvalidError
|
12
|
-
|
6
|
+
ArgumentError = Class.new Error
|
7
|
+
ConditionNotMetError = Class.new Error
|
8
|
+
RecipeEvaluationError = Class.new RuntimeError
|
9
|
+
RegistryKeyError = Class.new RuntimeError
|
10
|
+
RemoteCommandExecutionError = Class.new RuntimeError
|
11
|
+
RemoteInvalidError = Class.new ArgumentError
|
12
|
+
RemoteMismatchError = Class.new RuntimeError
|
13
|
+
RemoteUnknownError = Class.new RuntimeError
|
14
|
+
TemplateMissingError = Class.new RuntimeError
|
13
15
|
end
|
14
16
|
end
|
data/lib/producer/core/remote.rb
CHANGED
@@ -11,7 +11,13 @@ module Producer
|
|
11
11
|
def session
|
12
12
|
@session ||= begin
|
13
13
|
check_hostname!
|
14
|
-
Net::SSH.start
|
14
|
+
Net::SSH.start @hostname, user_name, verify_host_key: :always
|
15
|
+
rescue Net::SSH::HostKeyError => e
|
16
|
+
error = '`%s\' authenticity can\'t be established' % hostname
|
17
|
+
case e
|
18
|
+
when Net::SSH::HostKeyUnknown then fail RemoteUnknownError, error
|
19
|
+
when Net::SSH::HostKeyMismatch then fail RemoteMismatchError, error
|
20
|
+
end
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
data/lib/producer/core/task.rb
CHANGED
@@ -28,7 +28,6 @@ module Producer
|
|
28
28
|
define_action :file_append, Actions::FileAppend
|
29
29
|
define_action :file_replace_content, Actions::FileReplaceContent
|
30
30
|
define_action :file_write, Actions::FileWriter
|
31
|
-
define_action :yaml_write, Actions::YAMLWriter
|
32
31
|
|
33
32
|
attr_reader :name, :actions, :condition
|
34
33
|
|
@@ -1,34 +1,33 @@
|
|
1
|
-
def run_recipe remote: false, options: nil, check: false, rargv: nil
|
2
|
-
command = %w[
|
1
|
+
def run_recipe remote: false, options: nil, check: false, rargv: nil, wait: true
|
2
|
+
command = $_baf[:program] + %w[recipe.rb]
|
3
3
|
case remote
|
4
4
|
when :unknown then command += %w[-t unknown_host.test]
|
5
5
|
when true then command += %w[-t some_host.test]
|
6
6
|
end
|
7
|
-
command
|
8
|
-
command
|
7
|
+
command += options if options
|
8
|
+
command += %w[--] + rargv if rargv
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
end
|
10
|
+
env_allow = Baf::Testing::ENV_WHITELIST + $_baf[:env_allow]
|
11
|
+
$_baf[:process] = Baf::Testing.run command, env_allow: env_allow, wait: wait
|
13
12
|
|
14
|
-
|
15
|
-
|
13
|
+
Baf::Testing.expect_ex $_baf[:process], 0 if check
|
14
|
+
expect($_baf[:process].output).to match /\ASocketError/ if remote == :unknown
|
16
15
|
end
|
17
16
|
|
18
17
|
Given /^a recipe with:$/ do |recipe_body|
|
19
|
-
write_file 'recipe.rb', recipe_body
|
18
|
+
Baf::Testing.write_file 'recipe.rb', recipe_body + $/
|
20
19
|
end
|
21
20
|
|
22
21
|
Given /^a recipe with an error$/ do
|
23
|
-
write_file 'recipe.rb', "fail 'some error'\n"
|
22
|
+
Baf::Testing.write_file 'recipe.rb', "fail 'some error'\n"
|
24
23
|
end
|
25
24
|
|
26
25
|
Given /^a recipe using a remote$/ do
|
27
|
-
write_file 'recipe.rb', "task(:some_task) { sh 'echo hello' }\n"
|
26
|
+
Baf::Testing.write_file 'recipe.rb', "task(:some_task) { sh 'echo hello' }\n"
|
28
27
|
end
|
29
28
|
|
30
29
|
Given /^a recipe named "([^"]+)" with:$/ do |recipe_path, recipe_body|
|
31
|
-
write_file recipe_path, recipe_body
|
30
|
+
Baf::Testing.write_file recipe_path, recipe_body
|
32
31
|
end
|
33
32
|
|
34
33
|
When /^I execute the recipe$/ do
|
@@ -44,11 +43,11 @@ When /^I execute the recipe on unknown remote target$/ do
|
|
44
43
|
end
|
45
44
|
|
46
45
|
When /^I execute the recipe with options? (-.+)$/ do |options|
|
47
|
-
run_recipe options: options
|
46
|
+
run_recipe options: options.split(' ')
|
48
47
|
end
|
49
48
|
|
50
49
|
When /^I execute the recipe on unknown remote target with options? (-.+)$/ do |options|
|
51
|
-
run_recipe remote: :unknown, options: options
|
50
|
+
run_recipe remote: :unknown, options: options.split(' ')
|
52
51
|
end
|
53
52
|
|
54
53
|
When /^I successfully execute the recipe$/ do
|
@@ -60,17 +59,17 @@ When /^I successfully execute the recipe on remote target$/ do
|
|
60
59
|
end
|
61
60
|
|
62
61
|
When /^I successfully execute the recipe on remote target with options? (-.+)$/ do |options|
|
63
|
-
run_recipe remote: true, options: options, check: true
|
62
|
+
run_recipe remote: true, options: options.split(' '), check: true
|
64
63
|
end
|
65
64
|
|
66
65
|
When /^I successfully execute the recipe with options? (-.+)$/ do |options|
|
67
|
-
run_recipe options: options, check: true
|
66
|
+
run_recipe options: options.split(' '), check: true
|
68
67
|
end
|
69
68
|
|
70
69
|
When /^I successfully execute the recipe with arguments "([^"]+)"$/ do |rargv|
|
71
|
-
run_recipe rargv: rargv, check: true
|
70
|
+
run_recipe rargv: rargv.split(' '), check: true
|
72
71
|
end
|
73
72
|
|
74
73
|
When /^I execute the recipe interactively$/ do
|
75
|
-
|
74
|
+
run_recipe remote: true, wait: false
|
76
75
|
end
|
@@ -1,43 +1,37 @@
|
|
1
1
|
def stat_mode path
|
2
|
-
|
3
|
-
('%o' % [File::Stat.new(path).mode])[-4, 4]
|
4
|
-
end
|
2
|
+
('%o' % [File::Stat.new(path).mode])[-4, 4]
|
5
3
|
end
|
6
4
|
|
7
5
|
Given /^a remote directory named "([^"]+)"$/ do |path|
|
8
|
-
|
6
|
+
FileUtils.mkdir_p path
|
9
7
|
end
|
10
8
|
|
11
9
|
Given /^a remote file named "([^"]+)"$/ do |file_name|
|
12
|
-
write_file file_name, ''
|
10
|
+
Baf::Testing.write_file file_name, ''
|
13
11
|
end
|
14
12
|
|
15
13
|
Given /^a remote file named "([^"]+)" with "([^"]+)"$/ do |file_name, content|
|
16
|
-
write_file file_name, content
|
14
|
+
Baf::Testing.write_file file_name, content
|
17
15
|
end
|
18
16
|
|
19
17
|
Then /^the remote directory "([^"]+)" must exist$/ do |path|
|
20
|
-
expect(path).to
|
18
|
+
expect(Dir.exist? path).to be true
|
21
19
|
end
|
22
20
|
|
23
21
|
Then /^the remote file "([^"]+)" must exist$/ do |path|
|
24
|
-
|
22
|
+
expect(File.file? path).to be true
|
25
23
|
end
|
26
24
|
|
27
25
|
Then /^the remote file "([^"]+)" must contain "([^"]+)"$/ do |path, content|
|
28
|
-
expect(path).to
|
26
|
+
expect(IO.read path).to include content
|
29
27
|
end
|
30
28
|
|
31
29
|
Then /^the remote file "([^"]+)" must contain exactly "([^"]+)"$/ do |path, content|
|
32
|
-
expect(path).to
|
30
|
+
expect(IO.read path).to include content
|
33
31
|
end
|
34
32
|
|
35
33
|
Then /^the remote file "([^"]+)" must contain exactly:$/ do |path, content|
|
36
|
-
expect(path).to
|
37
|
-
end
|
38
|
-
|
39
|
-
Then /^the remote file "([^"]+)" must match \/([^\/]+)\/$/ do |path, pattern|
|
40
|
-
expect(path).to have_file_content /#{pattern}/
|
34
|
+
expect(IO.read path).to eq content
|
41
35
|
end
|
42
36
|
|
43
37
|
Then /^the remote file "([^"]+)" must have (\d+) mode$/ do |path, mode|
|
@@ -1,3 +1,11 @@
|
|
1
|
+
Given /^SSH known hosts:$/ do |db|
|
2
|
+
Baf::Testing.write_file '.ssh/known_hosts', db
|
3
|
+
end
|
4
|
+
|
1
5
|
Given /^an SSH config with:$/ do |config|
|
2
|
-
write_file '.ssh/config', config
|
6
|
+
Baf::Testing.write_file '.ssh/config', config
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^no SSH known hosts$/ do
|
10
|
+
Baf::Testing.write_file '.ssh/known_hosts', ''
|
3
11
|
end
|
@@ -1,35 +1,7 @@
|
|
1
|
-
require '
|
2
|
-
require 'aruba/in_process'
|
1
|
+
require 'cucumber/sshd/cucumber'
|
3
2
|
|
4
3
|
require 'producer/core'
|
5
|
-
require 'producer/core/testing/aruba_program_wrapper'
|
6
4
|
require 'producer/core/testing/cucumber/etc_steps'
|
7
|
-
require 'producer/core/testing/cucumber/execution_steps'
|
8
|
-
require 'producer/core/testing/cucumber/output_steps'
|
9
5
|
require 'producer/core/testing/cucumber/recipe_steps'
|
10
6
|
require 'producer/core/testing/cucumber/remote_steps'
|
11
7
|
require 'producer/core/testing/cucumber/ssh_steps'
|
12
|
-
|
13
|
-
# Raise aruba default timeout so test suite can run on a slow machine.
|
14
|
-
Before do
|
15
|
-
@aruba_timeout_seconds = 8
|
16
|
-
end
|
17
|
-
|
18
|
-
# Use aruba "in process" optimization only for scenarios not tagged @exec.
|
19
|
-
# We need a real process in a few cases: real program name, interactive usage…
|
20
|
-
Before('@exec') do
|
21
|
-
aruba.config.command_launcher = :spawn
|
22
|
-
end
|
23
|
-
|
24
|
-
Before('~@exec') do
|
25
|
-
aruba.config.command_launcher = :in_process
|
26
|
-
aruba.config.main_class = Producer::Core::Testing::ArubaProgramWrapper
|
27
|
-
end
|
28
|
-
|
29
|
-
# Enable cucumber-sshd "fast" mode (persists sshd across scenarios), and
|
30
|
-
# register hooks for @sshd tagged scenarios.
|
31
|
-
Before do
|
32
|
-
@_sshd_fast = true
|
33
|
-
@_sshd_wait_ready = true if ENV.key? 'TRAVIS'
|
34
|
-
end
|
35
|
-
require 'cucumber/sshd/cucumber'
|
data/lib/producer/core.rb
CHANGED
@@ -5,6 +5,7 @@ require 'optparse'
|
|
5
5
|
require 'pathname'
|
6
6
|
require 'yaml'
|
7
7
|
|
8
|
+
require 'baf/cli'
|
8
9
|
require 'net/ssh'
|
9
10
|
require 'net/sftp'
|
10
11
|
|
@@ -16,7 +17,6 @@ require 'producer/core/actions/mkdir'
|
|
16
17
|
require 'producer/core/actions/file_append'
|
17
18
|
require 'producer/core/actions/file_replace_content'
|
18
19
|
require 'producer/core/actions/file_writer'
|
19
|
-
require 'producer/core/actions/yaml_writer'
|
20
20
|
|
21
21
|
# condition tests
|
22
22
|
require 'producer/core/test'
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: producer-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thibault Jouan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-ssh
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 4.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 4.2.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: net-sftp
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,25 +39,19 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: baf
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0.
|
48
|
-
|
49
|
-
- !ruby/object:Gem::Version
|
50
|
-
version: '0.9'
|
51
|
-
type: :development
|
47
|
+
version: '0.15'
|
48
|
+
type: :runtime
|
52
49
|
prerelease: false
|
53
50
|
version_requirements: !ruby/object:Gem::Requirement
|
54
51
|
requirements:
|
55
52
|
- - "~>"
|
56
53
|
- !ruby/object:Gem::Version
|
57
|
-
version: '0.
|
58
|
-
- - "<"
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '0.9'
|
54
|
+
version: '0.15'
|
61
55
|
- !ruby/object:Gem::Dependency
|
62
56
|
name: cucumber
|
63
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,34 +72,28 @@ dependencies:
|
|
78
72
|
requirements:
|
79
73
|
- - "~>"
|
80
74
|
- !ruby/object:Gem::Version
|
81
|
-
version: '
|
82
|
-
- - ">="
|
83
|
-
- !ruby/object:Gem::Version
|
84
|
-
version: 1.1.1
|
75
|
+
version: '2.0'
|
85
76
|
type: :development
|
86
77
|
prerelease: false
|
87
78
|
version_requirements: !ruby/object:Gem::Requirement
|
88
79
|
requirements:
|
89
80
|
- - "~>"
|
90
81
|
- !ruby/object:Gem::Version
|
91
|
-
version: '
|
92
|
-
- - ">="
|
93
|
-
- !ruby/object:Gem::Version
|
94
|
-
version: 1.1.1
|
82
|
+
version: '2.0'
|
95
83
|
- !ruby/object:Gem::Dependency
|
96
84
|
name: rake
|
97
85
|
requirement: !ruby/object:Gem::Requirement
|
98
86
|
requirements:
|
99
|
-
- - "
|
87
|
+
- - ">="
|
100
88
|
- !ruby/object:Gem::Version
|
101
|
-
version: '
|
89
|
+
version: '0'
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
93
|
requirements:
|
106
|
-
- - "
|
94
|
+
- - ">="
|
107
95
|
- !ruby/object:Gem::Version
|
108
|
-
version: '
|
96
|
+
version: '0'
|
109
97
|
- !ruby/object:Gem::Dependency
|
110
98
|
name: rspec
|
111
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,9 +108,10 @@ dependencies:
|
|
120
108
|
- - "~>"
|
121
109
|
- !ruby/object:Gem::Version
|
122
110
|
version: '3.1'
|
123
|
-
description: |
|
124
|
-
|
125
|
-
|
111
|
+
description: |
|
112
|
+
producer-core is a software configuration management tool providing a DSL
|
113
|
+
to describe infrastructure as code.
|
114
|
+
It helps automating software deployment, configuration and management.
|
126
115
|
email: tj@a13.fr
|
127
116
|
executables:
|
128
117
|
- producer
|
@@ -140,7 +129,6 @@ files:
|
|
140
129
|
- lib/producer/core/actions/file_writer.rb
|
141
130
|
- lib/producer/core/actions/mkdir.rb
|
142
131
|
- lib/producer/core/actions/shell_command.rb
|
143
|
-
- lib/producer/core/actions/yaml_writer.rb
|
144
132
|
- lib/producer/core/cli.rb
|
145
133
|
- lib/producer/core/condition.rb
|
146
134
|
- lib/producer/core/env.rb
|
@@ -159,12 +147,8 @@ files:
|
|
159
147
|
- lib/producer/core/template/raw_renderer.rb
|
160
148
|
- lib/producer/core/template/yaml_renderer.rb
|
161
149
|
- lib/producer/core/test.rb
|
162
|
-
- lib/producer/core/testing.rb
|
163
|
-
- lib/producer/core/testing/aruba_program_wrapper.rb
|
164
150
|
- lib/producer/core/testing/cucumber.rb
|
165
151
|
- lib/producer/core/testing/cucumber/etc_steps.rb
|
166
|
-
- lib/producer/core/testing/cucumber/execution_steps.rb
|
167
|
-
- lib/producer/core/testing/cucumber/output_steps.rb
|
168
152
|
- lib/producer/core/testing/cucumber/recipe_steps.rb
|
169
153
|
- lib/producer/core/testing/cucumber/remote_steps.rb
|
170
154
|
- lib/producer/core/testing/cucumber/ssh_steps.rb
|
@@ -185,7 +169,7 @@ homepage: https://rubygems.org/gems/producer-core
|
|
185
169
|
licenses:
|
186
170
|
- BSD-3-Clause
|
187
171
|
metadata: {}
|
188
|
-
post_install_message:
|
172
|
+
post_install_message:
|
189
173
|
rdoc_options: []
|
190
174
|
require_paths:
|
191
175
|
- lib
|
@@ -200,9 +184,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
200
184
|
- !ruby/object:Gem::Version
|
201
185
|
version: '0'
|
202
186
|
requirements: []
|
203
|
-
|
204
|
-
|
205
|
-
signing_key:
|
187
|
+
rubygems_version: 3.3.17
|
188
|
+
signing_key:
|
206
189
|
specification_version: 4
|
207
|
-
summary:
|
190
|
+
summary: Software configuration management tool
|
208
191
|
test_files: []
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Producer
|
2
|
-
module Core
|
3
|
-
module Actions
|
4
|
-
class YAMLWriter < FileWriter
|
5
|
-
def setup
|
6
|
-
super
|
7
|
-
@content = options.delete(:data).to_yaml
|
8
|
-
end
|
9
|
-
|
10
|
-
def name
|
11
|
-
'yaml_write'
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def arguments_size
|
17
|
-
1
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Producer
|
2
|
-
module Core
|
3
|
-
module Testing
|
4
|
-
class ArubaProgramWrapper
|
5
|
-
def initialize argv, stdin = $stdin, stdout = $stdout, stderr = $stderr,
|
6
|
-
kernel = Kernel
|
7
|
-
@argv = argv
|
8
|
-
@stdin = stdin
|
9
|
-
@stdout = stdout
|
10
|
-
@stderr = stderr
|
11
|
-
@kernel = kernel
|
12
|
-
end
|
13
|
-
|
14
|
-
def execute!
|
15
|
-
Producer::Core::CLI.run!(
|
16
|
-
@argv.dup, stdin: @stdin, stdout: @stdout, stderr: @stderr
|
17
|
-
)
|
18
|
-
rescue SystemExit => e
|
19
|
-
@kernel.exit e.status
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
Then /^the output must contain exactly the usage$/ do
|
2
|
-
assert_exact_output <<-eoh, all_output
|
3
|
-
Usage: producer [options] [recipes] [-- recipe_argument...]
|
4
|
-
|
5
|
-
options:
|
6
|
-
-v, --verbose enable verbose mode
|
7
|
-
-d, --debug enable debug mode
|
8
|
-
-n, --dry-run enable dry run mode
|
9
|
-
-t, --target HOST target host
|
10
|
-
eoh
|
11
|
-
end
|
12
|
-
|
13
|
-
Then /^the output must match \/([^\/]+)\/$/ do |pattern|
|
14
|
-
assert_matching_output pattern, all_output
|
15
|
-
end
|
16
|
-
|
17
|
-
Then /^the output must contain "([^"]+)"$/ do |content|
|
18
|
-
assert_partial_output content, all_output
|
19
|
-
end
|
20
|
-
|
21
|
-
Then /^the output must contain:$/ do |content|
|
22
|
-
assert_partial_output content, all_output
|
23
|
-
end
|
24
|
-
|
25
|
-
Then /^the output must not contain "([^"]+)"$/ do |content|
|
26
|
-
assert_no_partial_output content, all_output
|
27
|
-
end
|
28
|
-
|
29
|
-
Then /^the output must contain exactly "([^"]+)"$/ do |content|
|
30
|
-
assert_exact_output content, all_output
|
31
|
-
end
|
32
|
-
|
33
|
-
Then /^the output must contain exactly:$/ do |content|
|
34
|
-
assert_exact_output content, all_output
|
35
|
-
end
|
36
|
-
|
37
|
-
Then /^the error output must contain exactly "([^"]+)"$/ do |content|
|
38
|
-
assert_exact_output content, all_stderr
|
39
|
-
end
|
40
|
-
|
41
|
-
Then /^the output must contain ruby lib directory$/ do
|
42
|
-
assert_partial_output RbConfig::CONFIG['rubylibdir'], all_output
|
43
|
-
end
|
44
|
-
|
45
|
-
Then /^the output must not contain ruby lib directory$/ do
|
46
|
-
assert_no_partial_output RbConfig::CONFIG['rubylibdir'], all_output
|
47
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
require 'producer/core/testing/mock_remote'
|