producer-core 0.4.1 → 0.4.2
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.
- 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
|