producer-core 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/features/action_yaml_write.feature +14 -0
- data/features/cli_debug.feature +11 -0
- data/features/cli_error_reporting.feature +20 -0
- data/features/cli_usage.feature +1 -0
- data/features/steps/recipe_steps.rb +4 -0
- data/features/steps/remote_steps.rb +4 -0
- data/features/task_template.feature +32 -10
- data/features/test_yaml_eq.feature +26 -0
- data/lib/producer/core.rb +7 -1
- data/lib/producer/core/actions/file_writer.rb +8 -1
- data/lib/producer/core/actions/yaml_writer.rb +23 -0
- data/lib/producer/core/cli.rb +10 -2
- data/lib/producer/core/condition.rb +1 -0
- data/lib/producer/core/env.rb +6 -2
- data/lib/producer/core/error_formatter.rb +53 -0
- data/lib/producer/core/errors.rb +2 -0
- data/lib/producer/core/recipe/file_evaluator.rb +8 -1
- data/lib/producer/core/task.rb +2 -16
- data/lib/producer/core/template.rb +53 -0
- data/lib/producer/core/tests/yaml_eq.rb +12 -0
- data/lib/producer/core/version.rb +1 -1
- data/spec/fixtures/templates/basic.erb +1 -0
- data/spec/fixtures/templates/basic_yaml.yaml +1 -0
- data/spec/fixtures/templates/variables.erb +1 -0
- data/spec/producer/core/actions/yaml_writer_spec.rb +25 -0
- data/spec/producer/core/cli_spec.rb +12 -3
- data/spec/producer/core/env_spec.rb +11 -0
- data/spec/producer/core/error_formatter_spec.rb +59 -0
- data/spec/producer/core/template_spec.rb +41 -0
- data/spec/producer/core/tests/yaml_eq_spec.rb +47 -0
- metadata +28 -2
@@ -0,0 +1,14 @@
|
|
1
|
+
@sshd
|
2
|
+
Feature: `yaml_write' task action
|
3
|
+
|
4
|
+
Background:
|
5
|
+
Given a recipe with:
|
6
|
+
"""
|
7
|
+
task :yaml_write_action do
|
8
|
+
yaml_write 'some_file', data: { foo: 'bar' }
|
9
|
+
end
|
10
|
+
"""
|
11
|
+
|
12
|
+
Scenario: writes given data as YAML
|
13
|
+
When I successfully execute the recipe on remote target
|
14
|
+
Then the remote file "some_file" must match /^:foo: bar$/
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Feature: CLI debug option
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a recipe with:
|
5
|
+
"""
|
6
|
+
task(:trigger_error) { fail 'some error' }
|
7
|
+
"""
|
8
|
+
|
9
|
+
Scenario: reports recipe errors
|
10
|
+
When I execute the recipe with option -d
|
11
|
+
Then the output must match /\ARuntimeError:.*\n\ncause:\nRuntimeError:/
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature: CLI error reporting
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given a recipe with:
|
5
|
+
"""
|
6
|
+
task(:trigger_error) { fail 'some error' }
|
7
|
+
"""
|
8
|
+
|
9
|
+
Scenario: reports recipe errors
|
10
|
+
When I execute the recipe
|
11
|
+
Then the exit status must be 70
|
12
|
+
And the output must match /\ARuntimeError: some error\n/
|
13
|
+
|
14
|
+
Scenario: reports errors with a backtrace
|
15
|
+
When I execute the recipe
|
16
|
+
Then the output must match /^\s+recipe\.rb:\d+:in /
|
17
|
+
|
18
|
+
Scenario: prepends recipe file path in the backtrace
|
19
|
+
When I execute the recipe
|
20
|
+
Then the output must match /^\s+recipe\.rb \(recipe\)\n\s+recipe\.rb:/
|
data/features/cli_usage.feature
CHANGED
@@ -24,6 +24,10 @@ When /^I successfully execute the recipe on remote target$/ do
|
|
24
24
|
assert_exit_status 0
|
25
25
|
end
|
26
26
|
|
27
|
+
When /^I execute the recipe with option (-.+)$/ do |option|
|
28
|
+
run_simple "producer #{option} recipe.rb", false
|
29
|
+
end
|
30
|
+
|
27
31
|
When /^I successfully execute the recipe with option (-.+)$/ do |option|
|
28
32
|
run_simple "producer #{option} recipe.rb", false
|
29
33
|
assert_exit_status 0
|
@@ -22,6 +22,10 @@ Then /^the remote file "([^"]+)" must contain exactly "([^"]+)"$/ do |path, cont
|
|
22
22
|
check_exact_file_content path, content
|
23
23
|
end
|
24
24
|
|
25
|
+
Then /^the remote file "([^"]+)" must match \/([^\/]+)\/$/ do |path, pattern|
|
26
|
+
check_file_content path, /#{pattern}/, true
|
27
|
+
end
|
28
|
+
|
25
29
|
def stat_mode(path)
|
26
30
|
in_current_dir do
|
27
31
|
('%o' % [File::Stat.new(path).mode])[-4, 4]
|
@@ -1,17 +1,11 @@
|
|
1
1
|
Feature: `template' task keyword
|
2
2
|
|
3
|
-
|
4
|
-
Given a file named "basic.erb" with:
|
3
|
+
Scenario: renders an ERB template file
|
4
|
+
Given a file named "templates/basic.erb" with:
|
5
5
|
"""
|
6
6
|
basic template
|
7
7
|
"""
|
8
|
-
|
9
|
-
"""
|
10
|
-
<%= @foo %>
|
11
|
-
"""
|
12
|
-
|
13
|
-
Scenario: renders an ERB template file
|
14
|
-
Given a recipe with:
|
8
|
+
And a recipe with:
|
15
9
|
"""
|
16
10
|
task(:echo_template) { echo template 'basic' }
|
17
11
|
"""
|
@@ -19,9 +13,37 @@ Feature: `template' task keyword
|
|
19
13
|
Then the output must contain "basic template"
|
20
14
|
|
21
15
|
Scenario: renders ERB with given attributes as member data
|
22
|
-
Given a
|
16
|
+
Given a file named "templates/variables.erb" with:
|
17
|
+
"""
|
18
|
+
<%= @foo %>
|
19
|
+
"""
|
20
|
+
And a recipe with:
|
23
21
|
"""
|
24
22
|
task(:echo_template) { echo template('variables', foo: 'bar') }
|
25
23
|
"""
|
26
24
|
When I execute the recipe
|
27
25
|
Then the output must contain "bar"
|
26
|
+
|
27
|
+
Scenario: renders without `templates' search path
|
28
|
+
Given a file named "templates/basic.erb" with:
|
29
|
+
"""
|
30
|
+
basic template
|
31
|
+
"""
|
32
|
+
And a recipe with:
|
33
|
+
"""
|
34
|
+
task(:echo_template) { echo template './templates/basic' }
|
35
|
+
"""
|
36
|
+
When I execute the recipe
|
37
|
+
Then the output must contain "basic template"
|
38
|
+
|
39
|
+
Scenario: parses a yaml file
|
40
|
+
Given a file named "templates/basic.yaml" with:
|
41
|
+
"""
|
42
|
+
foo: bar
|
43
|
+
"""
|
44
|
+
And a recipe with:
|
45
|
+
"""
|
46
|
+
task(:echo_template) { echo template('basic')['foo'] }
|
47
|
+
"""
|
48
|
+
When I execute the recipe
|
49
|
+
Then the output must match /^bar$/
|
@@ -0,0 +1,26 @@
|
|
1
|
+
@sshd
|
2
|
+
Feature: `yaml_eq' condition keyword
|
3
|
+
|
4
|
+
Background:
|
5
|
+
Given a recipe with:
|
6
|
+
"""
|
7
|
+
task :yaml_eq_test do
|
8
|
+
condition { yaml_eq 'some_file', { foo: 'bar' } }
|
9
|
+
|
10
|
+
echo 'evaluated'
|
11
|
+
end
|
12
|
+
"""
|
13
|
+
|
14
|
+
Scenario: succeeds when YAML data is equivalent
|
15
|
+
Given a remote file named "some_file" with ":foo: bar"
|
16
|
+
When I successfully execute the recipe on remote target
|
17
|
+
Then the output must contain "evaluated"
|
18
|
+
|
19
|
+
Scenario: fails when YAML data differs
|
20
|
+
Given a remote file named "some_file" with ":foo: baz"
|
21
|
+
When I successfully execute the recipe on remote target
|
22
|
+
Then the output must not contain "evaluated"
|
23
|
+
|
24
|
+
Scenario: fails when YAML file does not exist
|
25
|
+
When I successfully execute the recipe on remote target
|
26
|
+
Then the output must not contain "evaluated"
|
data/lib/producer/core.rb
CHANGED
@@ -3,6 +3,7 @@ require 'etc'
|
|
3
3
|
require 'forwardable'
|
4
4
|
require 'optparse'
|
5
5
|
require 'pathname'
|
6
|
+
require 'yaml'
|
6
7
|
|
7
8
|
require 'net/ssh'
|
8
9
|
require 'net/sftp'
|
@@ -16,6 +17,7 @@ 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'
|
20
|
+
require 'producer/core/actions/yaml_writer'
|
19
21
|
|
20
22
|
# condition tests
|
21
23
|
require 'producer/core/test'
|
@@ -28,11 +30,14 @@ require 'producer/core/tests/has_env'
|
|
28
30
|
require 'producer/core/tests/has_executable'
|
29
31
|
require 'producer/core/tests/has_file'
|
30
32
|
require 'producer/core/tests/shell_command_status'
|
33
|
+
require 'producer/core/tests/yaml_eq'
|
34
|
+
|
35
|
+
require 'producer/core/errors'
|
31
36
|
|
32
37
|
require 'producer/core/cli'
|
33
38
|
require 'producer/core/condition'
|
34
39
|
require 'producer/core/env'
|
35
|
-
require 'producer/core/
|
40
|
+
require 'producer/core/error_formatter'
|
36
41
|
require 'producer/core/logger_formatter'
|
37
42
|
require 'producer/core/prompter'
|
38
43
|
require 'producer/core/recipe'
|
@@ -41,5 +46,6 @@ require 'producer/core/remote'
|
|
41
46
|
require 'producer/core/remote/environment'
|
42
47
|
require 'producer/core/remote/fs'
|
43
48
|
require 'producer/core/task'
|
49
|
+
require 'producer/core/template'
|
44
50
|
require 'producer/core/version'
|
45
51
|
require 'producer/core/worker'
|
@@ -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! arguments_size
|
7
7
|
@path, @content = arguments
|
8
8
|
@options[:permissions] = @options.delete :mode if options.key? :mode
|
9
9
|
@options[:owner] = @options.delete :user if options.key? :user
|
@@ -17,6 +17,13 @@ module Producer
|
|
17
17
|
fs.file_write @path, @content
|
18
18
|
fs.setstat @path, @options unless @options.empty?
|
19
19
|
end
|
20
|
+
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def arguments_size
|
25
|
+
2
|
26
|
+
end
|
20
27
|
end
|
21
28
|
end
|
22
29
|
end
|
@@ -0,0 +1,23 @@
|
|
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
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def arguments_size
|
18
|
+
1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/producer/core/cli.rb
CHANGED
@@ -17,8 +17,12 @@ module Producer
|
|
17
17
|
rescue ArgumentError => e
|
18
18
|
stderr.puts e.message
|
19
19
|
exit EX_USAGE
|
20
|
-
rescue
|
21
|
-
|
20
|
+
rescue Exception => e
|
21
|
+
ef = ErrorFormatter.new(
|
22
|
+
debug: cli.env.debug?,
|
23
|
+
force_cause: [RecipeEvaluationError]
|
24
|
+
)
|
25
|
+
stderr.puts ef.format e
|
22
26
|
exit EX_SOFTWARE
|
23
27
|
end
|
24
28
|
end
|
@@ -65,6 +69,10 @@ module Producer
|
|
65
69
|
env.verbose = true
|
66
70
|
end
|
67
71
|
|
72
|
+
opts.on '-d', '--debug', 'enable debug mode' do |e|
|
73
|
+
env.debug = true
|
74
|
+
end
|
75
|
+
|
68
76
|
opts.on '-n', '--dry-run', 'enable dry run mode' do |e|
|
69
77
|
env.dry_run = true
|
70
78
|
end
|
data/lib/producer/core/env.rb
CHANGED
@@ -2,10 +2,10 @@ module Producer
|
|
2
2
|
module Core
|
3
3
|
class Env
|
4
4
|
attr_reader :input, :output, :error_output, :registry, :logger
|
5
|
-
attr_accessor :target, :verbose, :dry_run
|
5
|
+
attr_accessor :target, :verbose, :debug, :dry_run
|
6
6
|
|
7
7
|
def initialize(input: $stdin, output: $stdout, error_output: $stderr, remote: nil, registry: {})
|
8
|
-
@verbose
|
8
|
+
@verbose = @debug = @dry_run = false
|
9
9
|
@input = input
|
10
10
|
@output = output
|
11
11
|
@error_output = error_output
|
@@ -45,6 +45,10 @@ module Producer
|
|
45
45
|
@verbose
|
46
46
|
end
|
47
47
|
|
48
|
+
def debug?
|
49
|
+
@debug
|
50
|
+
end
|
51
|
+
|
48
52
|
def dry_run?
|
49
53
|
@dry_run
|
50
54
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Producer
|
2
|
+
module Core
|
3
|
+
class ErrorFormatter
|
4
|
+
def initialize(debug: false, force_cause: [])
|
5
|
+
@debug = debug
|
6
|
+
@force_cause = force_cause
|
7
|
+
end
|
8
|
+
|
9
|
+
def debug?
|
10
|
+
!!@debug
|
11
|
+
end
|
12
|
+
|
13
|
+
def format(exception)
|
14
|
+
lines = format_exception exception
|
15
|
+
|
16
|
+
if debug? && exception.cause
|
17
|
+
lines << ''
|
18
|
+
lines << 'cause:'
|
19
|
+
lines << format_exception(exception.cause, filter: false)
|
20
|
+
end
|
21
|
+
|
22
|
+
lines.join("\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def format_exception(exception, filter: true)
|
28
|
+
[
|
29
|
+
format_message(exception),
|
30
|
+
*format_backtrace(exception.backtrace, filter: filter)
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
def format_message(exception)
|
35
|
+
exception = exception.cause if @force_cause.include? exception.class
|
36
|
+
"#{exception.class.name.split('::').last}: #{exception.message}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def format_backtrace(backtrace, filter: true)
|
40
|
+
backtrace = filter_backtrace backtrace if filter
|
41
|
+
indent_backtrace backtrace
|
42
|
+
end
|
43
|
+
|
44
|
+
def filter_backtrace(backtrace)
|
45
|
+
backtrace.reject { |l| l =~ /\/producer-\w+\/(?:bin|lib)\// }
|
46
|
+
end
|
47
|
+
|
48
|
+
def indent_backtrace(backtrace)
|
49
|
+
backtrace.map { |e| ' %s' % e }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/producer/core/errors.rb
CHANGED
@@ -2,8 +2,10 @@ module Producer
|
|
2
2
|
module Core
|
3
3
|
Error = Class.new(StandardError)
|
4
4
|
RuntimeError = Class.new(RuntimeError)
|
5
|
+
|
5
6
|
ArgumentError = Class.new(Error)
|
6
7
|
ConditionNotMetError = Class.new(Error)
|
8
|
+
RecipeEvaluationError = Class.new(RuntimeError)
|
7
9
|
RemoteCommandExecutionError = Class.new(RuntimeError)
|
8
10
|
RegistryKeyError = Class.new(RuntimeError)
|
9
11
|
end
|
@@ -5,7 +5,14 @@ module Producer
|
|
5
5
|
class << self
|
6
6
|
def evaluate(file_path, env)
|
7
7
|
content = File.read(file_path)
|
8
|
-
|
8
|
+
begin
|
9
|
+
Recipe.new(env).tap { |o| o.instance_eval content, file_path }
|
10
|
+
rescue Exception => e
|
11
|
+
fail RecipeEvaluationError, e.message, [
|
12
|
+
'%s (recipe)' % file_path,
|
13
|
+
*e.backtrace
|
14
|
+
]
|
15
|
+
end
|
9
16
|
end
|
10
17
|
end
|
11
18
|
end
|
data/lib/producer/core/task.rb
CHANGED
@@ -23,6 +23,7 @@ module Producer
|
|
23
23
|
define_action :file_append, Actions::FileAppend
|
24
24
|
define_action :file_replace_content, Actions::FileReplaceContent
|
25
25
|
define_action :file_write, Actions::FileWriter
|
26
|
+
define_action :yaml_write, Actions::YAMLWriter
|
26
27
|
|
27
28
|
attr_reader :name, :actions, :condition
|
28
29
|
|
@@ -59,22 +60,7 @@ module Producer
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def template(path, variables = {})
|
62
|
-
path
|
63
|
-
tpl = ERB.new(File.read(path), nil, '-')
|
64
|
-
tpl.filename = path
|
65
|
-
tpl.result build_erb_binding variables
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def build_erb_binding(variables)
|
72
|
-
Object.new.instance_eval do |o|
|
73
|
-
variables.each do |k, v|
|
74
|
-
o.instance_variable_set "@#{k}", v
|
75
|
-
end
|
76
|
-
binding
|
77
|
-
end
|
63
|
+
Template.new(path).render variables
|
78
64
|
end
|
79
65
|
end
|
80
66
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Producer
|
2
|
+
module Core
|
3
|
+
class Template
|
4
|
+
SEARCH_PATH = 'templates'.freeze
|
5
|
+
|
6
|
+
def initialize(path, search_path: SEARCH_PATH)
|
7
|
+
@path = Pathname.new(path)
|
8
|
+
@search_path = Pathname.new(search_path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def render(variables = {})
|
12
|
+
case (file_path = resolve_path).extname
|
13
|
+
when '.yaml' then render_yaml file_path
|
14
|
+
when '.erb' then render_erb file_path, variables
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def render_erb(file_path, variables = {})
|
22
|
+
tpl = ERB.new(File.read(file_path), nil, '-')
|
23
|
+
tpl.filename = file_path.to_s
|
24
|
+
tpl.result build_erb_binding variables
|
25
|
+
end
|
26
|
+
|
27
|
+
def render_yaml(file_path)
|
28
|
+
YAML.load(File.read(file_path))
|
29
|
+
end
|
30
|
+
|
31
|
+
def resolve_path
|
32
|
+
if @path.to_s =~ /\A\.\//
|
33
|
+
resolve_suffix @path
|
34
|
+
else
|
35
|
+
resolve_suffix @search_path + @path
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def resolve_suffix(path)
|
40
|
+
Pathname.glob("#{path}.{erb,yaml}").first
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_erb_binding(variables)
|
44
|
+
Object.new.instance_eval do |o|
|
45
|
+
variables.each do |k, v|
|
46
|
+
o.instance_variable_set "@#{k}", v
|
47
|
+
end
|
48
|
+
binding
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
basic template
|
@@ -0,0 +1 @@
|
|
1
|
+
foo: bar
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @foo %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Producer::Core
|
4
|
+
module Actions
|
5
|
+
describe YAMLWriter, :env do
|
6
|
+
let(:path) { 'some_path' }
|
7
|
+
let(:data) { { foo: 'bar' } }
|
8
|
+
let(:arguments) { [path] }
|
9
|
+
let(:options) { { data: data } }
|
10
|
+
subject(:writer) { described_class.new(env, *arguments, options) }
|
11
|
+
|
12
|
+
it_behaves_like 'action'
|
13
|
+
|
14
|
+
it { is_expected.to be_a FileWriter}
|
15
|
+
|
16
|
+
describe '#apply' do
|
17
|
+
it 'writes data as YAML to file on remote filesystem' do
|
18
|
+
expect(remote_fs)
|
19
|
+
.to receive(:file_write).with(path, data.to_yaml)
|
20
|
+
writer.apply
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -44,7 +44,7 @@ module Producer::Core
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
context 'when
|
47
|
+
context 'when an error is raised' do
|
48
48
|
let(:recipe_file) { fixture_path_for 'recipes/raise.rb' }
|
49
49
|
|
50
50
|
it 'exits with a return status of 70' do
|
@@ -52,9 +52,9 @@ module Producer::Core
|
|
52
52
|
.to raise_error(SystemExit) { |e| expect(e.status).to eq 70 }
|
53
53
|
end
|
54
54
|
|
55
|
-
it 'prints
|
55
|
+
it 'prints a report to the error stream' do
|
56
56
|
expect { trap_exit { run! } }
|
57
|
-
.to output(
|
57
|
+
.to output(/\ARemoteCommandExecutionError: false$/).to_stderr
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
@@ -112,6 +112,15 @@ module Producer::Core
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
+
context 'with debug option' do
|
116
|
+
let(:options) { %w[-d] }
|
117
|
+
|
118
|
+
it 'assigns the given target to the env' do
|
119
|
+
cli.parse_arguments!
|
120
|
+
expect(cli.env).to be_debug
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
115
124
|
context 'with combined options' do
|
116
125
|
let(:options) { %w[-vn]}
|
117
126
|
|
@@ -26,6 +26,10 @@ module Producer::Core
|
|
26
26
|
expect(env.verbose).to be false
|
27
27
|
end
|
28
28
|
|
29
|
+
it 'assigns debug as false' do
|
30
|
+
expect(env.debug).to be false
|
31
|
+
end
|
32
|
+
|
29
33
|
it 'assigns dry run as false' do
|
30
34
|
expect(env.dry_run).to be false
|
31
35
|
end
|
@@ -168,6 +172,13 @@ module Producer::Core
|
|
168
172
|
end
|
169
173
|
end
|
170
174
|
|
175
|
+
describe '#debug?' do
|
176
|
+
it 'returns true when debug is enabled' do
|
177
|
+
env.debug = true
|
178
|
+
expect(env).to be_debug
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
171
182
|
describe '#dry_run?' do
|
172
183
|
it 'returns true when dry run is enabled' do
|
173
184
|
env.dry_run = true
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Producer
|
4
|
+
module Core
|
5
|
+
describe ErrorFormatter do
|
6
|
+
let(:debug) { false }
|
7
|
+
let(:force_cause) { [] }
|
8
|
+
let(:options) { { debug: debug, force_cause: force_cause } }
|
9
|
+
subject(:formatter) { described_class.new(options) }
|
10
|
+
|
11
|
+
describe '#debug?' do
|
12
|
+
it 'returns false' do
|
13
|
+
expect(formatter.debug?).to be false
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when debug is enabled' do
|
17
|
+
let(:debug) { true }
|
18
|
+
|
19
|
+
it 'returns true' do
|
20
|
+
expect(formatter.debug?).to be true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#format' do
|
26
|
+
def exception
|
27
|
+
begin fail 'original exception' rescue fail 'some exception' end
|
28
|
+
rescue
|
29
|
+
$!.tap { |o| o.set_backtrace %w[back trace] }
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'formats the message' do
|
33
|
+
expect(formatter.format exception)
|
34
|
+
.to match /^RuntimeError: some exception$/
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'indents the backtrace' do
|
38
|
+
expect(formatter.format exception).to match /^\s+back$/
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'filtering' do
|
42
|
+
before { exception.set_backtrace %w[back trace /producer-core/lib/] }
|
43
|
+
|
44
|
+
it 'excludes producer code from the backtrace' do
|
45
|
+
expect(formatter.format exception).not_to include 'producer-core'
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when debug is enabled' do
|
49
|
+
let(:debug) { true }
|
50
|
+
|
51
|
+
it 'does not exclude producer code from the backtrace' do
|
52
|
+
expect(formatter.format exception).to include 'producer-core'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Producer::Core
|
4
|
+
describe Template do
|
5
|
+
include FixturesHelpers
|
6
|
+
|
7
|
+
let(:path) { 'basic' }
|
8
|
+
let(:search_path) { fixture_path_for 'templates' }
|
9
|
+
subject(:template) { described_class.new path, search_path: search_path }
|
10
|
+
|
11
|
+
describe '#render' do
|
12
|
+
it 'renders ERB templates' do
|
13
|
+
expect(template.render).to eq "basic template\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'yaml templates' do
|
17
|
+
let(:path) { 'basic_yaml' }
|
18
|
+
|
19
|
+
it 'renders yaml templates' do
|
20
|
+
expect(template.render).to eq({ 'foo' => 'bar' })
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when variables are given' do
|
25
|
+
let(:path) { 'variables' }
|
26
|
+
|
27
|
+
it 'declares given variables in ERB render binding' do
|
28
|
+
expect(template.render foo: 'bar').to eq "bar\n"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when relative path is requested' do
|
33
|
+
let(:path) { fixture_path_for('templates/basic').insert 0, './' }
|
34
|
+
|
35
|
+
it 'does not enforce `template\' search path' do
|
36
|
+
expect(template.render).to eq "basic template\n"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Producer::Core
|
4
|
+
module Tests
|
5
|
+
describe YAMLEq, :env do
|
6
|
+
let(:filepath) { 'some_file' }
|
7
|
+
let(:data) { { foo: 'bar' } }
|
8
|
+
subject(:test) { described_class.new(env, filepath, data, {}) }
|
9
|
+
|
10
|
+
it_behaves_like 'test'
|
11
|
+
|
12
|
+
describe '#verify' do
|
13
|
+
context 'when file content matches' do
|
14
|
+
before do
|
15
|
+
allow(remote_fs)
|
16
|
+
.to receive(:file_read).with(filepath) { ':foo: bar' }
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns true' do
|
20
|
+
expect(test.verify).to be true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when file content does not match' do
|
25
|
+
before do
|
26
|
+
allow(remote_fs)
|
27
|
+
.to receive(:file_read).with(filepath) { ':foo: baz' }
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns false' do
|
31
|
+
expect(test.verify).to be false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when file does not exist' do
|
36
|
+
before do
|
37
|
+
allow(remote_fs).to receive(:file_read).with(filepath) { nil }
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns false' do
|
41
|
+
expect(test.verify).to be false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: producer-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-10-
|
12
|
+
date: 2014-10-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-ssh
|
@@ -143,7 +143,10 @@ files:
|
|
143
143
|
- features/action_file_write.feature
|
144
144
|
- features/action_mkdir.feature
|
145
145
|
- features/action_sh.feature
|
146
|
+
- features/action_yaml_write.feature
|
147
|
+
- features/cli_debug.feature
|
146
148
|
- features/cli_dry_run.feature
|
149
|
+
- features/cli_error_reporting.feature
|
147
150
|
- features/cli_target.feature
|
148
151
|
- features/cli_usage.feature
|
149
152
|
- features/cli_verbose.feature
|
@@ -179,6 +182,7 @@ files:
|
|
179
182
|
- features/test_file_eq.feature
|
180
183
|
- features/test_file_match.feature
|
181
184
|
- features/test_shell_command_status.feature
|
185
|
+
- features/test_yaml_eq.feature
|
182
186
|
- lib/producer/core.rb
|
183
187
|
- lib/producer/core/action.rb
|
184
188
|
- lib/producer/core/actions/echo.rb
|
@@ -187,9 +191,11 @@ files:
|
|
187
191
|
- lib/producer/core/actions/file_writer.rb
|
188
192
|
- lib/producer/core/actions/mkdir.rb
|
189
193
|
- lib/producer/core/actions/shell_command.rb
|
194
|
+
- lib/producer/core/actions/yaml_writer.rb
|
190
195
|
- lib/producer/core/cli.rb
|
191
196
|
- lib/producer/core/condition.rb
|
192
197
|
- lib/producer/core/env.rb
|
198
|
+
- lib/producer/core/error_formatter.rb
|
193
199
|
- lib/producer/core/errors.rb
|
194
200
|
- lib/producer/core/logger_formatter.rb
|
195
201
|
- lib/producer/core/prompter.rb
|
@@ -199,6 +205,7 @@ files:
|
|
199
205
|
- lib/producer/core/remote/environment.rb
|
200
206
|
- lib/producer/core/remote/fs.rb
|
201
207
|
- lib/producer/core/task.rb
|
208
|
+
- lib/producer/core/template.rb
|
202
209
|
- lib/producer/core/test.rb
|
203
210
|
- lib/producer/core/testing.rb
|
204
211
|
- lib/producer/core/testing/mock_remote.rb
|
@@ -211,6 +218,7 @@ files:
|
|
211
218
|
- lib/producer/core/tests/has_executable.rb
|
212
219
|
- lib/producer/core/tests/has_file.rb
|
213
220
|
- lib/producer/core/tests/shell_command_status.rb
|
221
|
+
- lib/producer/core/tests/yaml_eq.rb
|
214
222
|
- lib/producer/core/version.rb
|
215
223
|
- lib/producer/core/worker.rb
|
216
224
|
- producer-core.gemspec
|
@@ -218,6 +226,9 @@ files:
|
|
218
226
|
- spec/fixtures/recipes/raise.rb
|
219
227
|
- spec/fixtures/recipes/some_recipe.rb
|
220
228
|
- spec/fixtures/recipes/throw.rb
|
229
|
+
- spec/fixtures/templates/basic.erb
|
230
|
+
- spec/fixtures/templates/basic_yaml.yaml
|
231
|
+
- spec/fixtures/templates/variables.erb
|
221
232
|
- spec/producer/core/action_spec.rb
|
222
233
|
- spec/producer/core/actions/echo_spec.rb
|
223
234
|
- spec/producer/core/actions/file_append_spec.rb
|
@@ -225,9 +236,11 @@ files:
|
|
225
236
|
- spec/producer/core/actions/file_writer_spec.rb
|
226
237
|
- spec/producer/core/actions/mkdir_spec.rb
|
227
238
|
- spec/producer/core/actions/shell_command_spec.rb
|
239
|
+
- spec/producer/core/actions/yaml_writer_spec.rb
|
228
240
|
- spec/producer/core/cli_spec.rb
|
229
241
|
- spec/producer/core/condition_spec.rb
|
230
242
|
- spec/producer/core/env_spec.rb
|
243
|
+
- spec/producer/core/error_formatter_spec.rb
|
231
244
|
- spec/producer/core/logger_formatter_spec.rb
|
232
245
|
- spec/producer/core/prompter_spec.rb
|
233
246
|
- spec/producer/core/recipe/file_evaluator_spec.rb
|
@@ -236,6 +249,7 @@ files:
|
|
236
249
|
- spec/producer/core/remote/fs_spec.rb
|
237
250
|
- spec/producer/core/remote_spec.rb
|
238
251
|
- spec/producer/core/task_spec.rb
|
252
|
+
- spec/producer/core/template_spec.rb
|
239
253
|
- spec/producer/core/test_spec.rb
|
240
254
|
- spec/producer/core/testing/mock_remote_spec.rb
|
241
255
|
- spec/producer/core/tests/condition_test_spec.rb
|
@@ -247,6 +261,7 @@ files:
|
|
247
261
|
- spec/producer/core/tests/has_executable_spec.rb
|
248
262
|
- spec/producer/core/tests/has_file_spec.rb
|
249
263
|
- spec/producer/core/tests/shell_command_status_spec.rb
|
264
|
+
- spec/producer/core/tests/yaml_eq_spec.rb
|
250
265
|
- spec/producer/core/worker_spec.rb
|
251
266
|
- spec/spec_helper.rb
|
252
267
|
- spec/support/exit_helpers.rb
|
@@ -286,7 +301,10 @@ test_files:
|
|
286
301
|
- features/action_file_write.feature
|
287
302
|
- features/action_mkdir.feature
|
288
303
|
- features/action_sh.feature
|
304
|
+
- features/action_yaml_write.feature
|
305
|
+
- features/cli_debug.feature
|
289
306
|
- features/cli_dry_run.feature
|
307
|
+
- features/cli_error_reporting.feature
|
290
308
|
- features/cli_target.feature
|
291
309
|
- features/cli_usage.feature
|
292
310
|
- features/cli_verbose.feature
|
@@ -322,10 +340,14 @@ test_files:
|
|
322
340
|
- features/test_file_eq.feature
|
323
341
|
- features/test_file_match.feature
|
324
342
|
- features/test_shell_command_status.feature
|
343
|
+
- features/test_yaml_eq.feature
|
325
344
|
- spec/fixtures/recipes/empty.rb
|
326
345
|
- spec/fixtures/recipes/raise.rb
|
327
346
|
- spec/fixtures/recipes/some_recipe.rb
|
328
347
|
- spec/fixtures/recipes/throw.rb
|
348
|
+
- spec/fixtures/templates/basic.erb
|
349
|
+
- spec/fixtures/templates/basic_yaml.yaml
|
350
|
+
- spec/fixtures/templates/variables.erb
|
329
351
|
- spec/producer/core/action_spec.rb
|
330
352
|
- spec/producer/core/actions/echo_spec.rb
|
331
353
|
- spec/producer/core/actions/file_append_spec.rb
|
@@ -333,9 +355,11 @@ test_files:
|
|
333
355
|
- spec/producer/core/actions/file_writer_spec.rb
|
334
356
|
- spec/producer/core/actions/mkdir_spec.rb
|
335
357
|
- spec/producer/core/actions/shell_command_spec.rb
|
358
|
+
- spec/producer/core/actions/yaml_writer_spec.rb
|
336
359
|
- spec/producer/core/cli_spec.rb
|
337
360
|
- spec/producer/core/condition_spec.rb
|
338
361
|
- spec/producer/core/env_spec.rb
|
362
|
+
- spec/producer/core/error_formatter_spec.rb
|
339
363
|
- spec/producer/core/logger_formatter_spec.rb
|
340
364
|
- spec/producer/core/prompter_spec.rb
|
341
365
|
- spec/producer/core/recipe/file_evaluator_spec.rb
|
@@ -344,6 +368,7 @@ test_files:
|
|
344
368
|
- spec/producer/core/remote/fs_spec.rb
|
345
369
|
- spec/producer/core/remote_spec.rb
|
346
370
|
- spec/producer/core/task_spec.rb
|
371
|
+
- spec/producer/core/template_spec.rb
|
347
372
|
- spec/producer/core/test_spec.rb
|
348
373
|
- spec/producer/core/testing/mock_remote_spec.rb
|
349
374
|
- spec/producer/core/tests/condition_test_spec.rb
|
@@ -355,6 +380,7 @@ test_files:
|
|
355
380
|
- spec/producer/core/tests/has_executable_spec.rb
|
356
381
|
- spec/producer/core/tests/has_file_spec.rb
|
357
382
|
- spec/producer/core/tests/shell_command_status_spec.rb
|
383
|
+
- spec/producer/core/tests/yaml_eq_spec.rb
|
358
384
|
- spec/producer/core/worker_spec.rb
|
359
385
|
- spec/spec_helper.rb
|
360
386
|
- spec/support/exit_helpers.rb
|