producer-core 0.5.7 → 0.5.8
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/README.md +1 -1
- data/Rakefile +6 -3
- data/config/cucumber.yaml +2 -1
- data/features/cli/debug.feature +7 -1
- data/features/cli/dry_run.feature +5 -0
- data/features/cli/error_reporting.feature +1 -1
- data/features/cli/usage.feature +6 -10
- data/features/cli/verbose.feature +5 -0
- data/features/recipe/errors.feature +9 -0
- data/features/ssh/config.feature +1 -1
- data/features/steps/environment_steps.rb +3 -0
- data/lib/producer/core/action.rb +5 -7
- data/lib/producer/core/actions/file_append.rb +1 -1
- data/lib/producer/core/actions/file_writer.rb +1 -2
- data/lib/producer/core/actions/mkdir.rb +4 -4
- data/lib/producer/core/actions/shell_command.rb +1 -1
- data/lib/producer/core/actions/yaml_writer.rb +1 -2
- data/lib/producer/core/cli.rb +48 -37
- data/lib/producer/core/condition.rb +3 -3
- data/lib/producer/core/env.rb +5 -4
- data/lib/producer/core/error_formatter.rb +13 -14
- data/lib/producer/core/errors.rb +1 -0
- data/lib/producer/core/logger_formatter.rb +3 -4
- data/lib/producer/core/prompter.rb +4 -4
- data/lib/producer/core/recipe/file_evaluator.rb +3 -3
- data/lib/producer/core/recipe.rb +10 -10
- data/lib/producer/core/remote/environment.rb +1 -1
- data/lib/producer/core/remote/fs.rb +10 -10
- data/lib/producer/core/remote.rb +13 -7
- data/lib/producer/core/task.rb +15 -9
- data/lib/producer/core/template.rb +9 -10
- data/lib/producer/core/test.rb +1 -1
- data/lib/producer/core/testing/aruba_program_wrapper.rb +2 -2
- data/lib/producer/core/testing/cucumber/output_steps.rb +12 -0
- data/lib/producer/core/testing/cucumber/recipe_steps.rb +5 -5
- data/lib/producer/core/testing/cucumber/remote_steps.rb +8 -8
- data/lib/producer/core/testing/cucumber.rb +3 -3
- data/lib/producer/core/testing/mock_remote.rb +27 -25
- data/lib/producer/core/tests/condition_test.rb +1 -1
- data/lib/producer/core/tests/file_contains.rb +2 -3
- data/lib/producer/core/tests/file_eq.rb +1 -2
- data/lib/producer/core/tests/file_match.rb +1 -2
- data/lib/producer/core/tests/has_env.rb +3 -6
- data/lib/producer/core/tests/has_executable.rb +1 -1
- data/lib/producer/core/tests/shell_command_status.rb +1 -1
- data/lib/producer/core/version.rb +1 -1
- data/lib/producer/core/worker.rb +7 -7
- data/lib/producer/core.rb +0 -1
- data/producer-core.gemspec +2 -2
- data/spec/producer/core/cli_spec.rb +29 -4
- data/spec/producer/core/remote_spec.rb +9 -1
- data/spec/producer/core/testing/mock_remote_spec.rb +5 -4
- metadata +10 -6
@@ -4,41 +4,41 @@ module Producer
|
|
4
4
|
class FS
|
5
5
|
attr_reader :sftp
|
6
6
|
|
7
|
-
def initialize
|
7
|
+
def initialize sftp
|
8
8
|
@sftp = sftp
|
9
9
|
end
|
10
10
|
|
11
|
-
def dir?
|
11
|
+
def dir? path
|
12
12
|
sftp.stat!(path).directory?
|
13
13
|
rescue Net::SFTP::StatusException
|
14
14
|
false
|
15
15
|
end
|
16
16
|
|
17
|
-
def file?
|
17
|
+
def file? path
|
18
18
|
sftp.stat!(path).file?
|
19
19
|
rescue Net::SFTP::StatusException
|
20
20
|
false
|
21
21
|
end
|
22
22
|
|
23
|
-
def setstat
|
23
|
+
def setstat path, attributes
|
24
24
|
sftp.setstat! path, attributes
|
25
25
|
end
|
26
26
|
|
27
|
-
def chmod
|
27
|
+
def chmod path, mode
|
28
28
|
setstat path, permissions: mode
|
29
29
|
end
|
30
30
|
|
31
|
-
def mkdir
|
32
|
-
|
31
|
+
def mkdir path, attributes = {}
|
32
|
+
sftp.mkdir! path, attributes
|
33
33
|
end
|
34
34
|
|
35
|
-
def file_read
|
36
|
-
sftp.file.open(path) { |f|
|
35
|
+
def file_read path
|
36
|
+
sftp.file.open(path) { |f| f.read }
|
37
37
|
rescue Net::SFTP::StatusException
|
38
38
|
nil
|
39
39
|
end
|
40
40
|
|
41
|
-
def file_write
|
41
|
+
def file_write path, content
|
42
42
|
sftp.file.open path, 'w' do |f|
|
43
43
|
f.write content
|
44
44
|
end
|
data/lib/producer/core/remote.rb
CHANGED
@@ -4,12 +4,18 @@ module Producer
|
|
4
4
|
attr_reader :hostname
|
5
5
|
attr_writer :session
|
6
6
|
|
7
|
-
def initialize
|
7
|
+
def initialize hostname
|
8
8
|
@hostname = hostname
|
9
9
|
end
|
10
10
|
|
11
11
|
def session
|
12
|
-
@session ||=
|
12
|
+
@session ||= begin
|
13
|
+
if !@hostname
|
14
|
+
fail RemoteInvalidError,
|
15
|
+
"remote target is invalid: `#{@hostname.inspect}'"
|
16
|
+
end
|
17
|
+
Net::SSH.start(@hostname, user_name)
|
18
|
+
end
|
13
19
|
end
|
14
20
|
|
15
21
|
def config
|
@@ -24,18 +30,18 @@ module Producer
|
|
24
30
|
@fs ||= Remote::FS.new(session.sftp.connect)
|
25
31
|
end
|
26
32
|
|
27
|
-
def execute
|
33
|
+
def execute command, output = '', error_output = ''
|
28
34
|
session.open_channel do |channel|
|
29
|
-
channel.exec command do |ch,
|
30
|
-
ch.on_data do |
|
35
|
+
channel.exec command do |ch, _success|
|
36
|
+
ch.on_data do |_c, data|
|
31
37
|
output << data
|
32
38
|
end
|
33
39
|
|
34
|
-
ch.on_extended_data do |
|
40
|
+
ch.on_extended_data do |_c, _type, data|
|
35
41
|
error_output << data
|
36
42
|
end
|
37
43
|
|
38
|
-
ch.on_request 'exit-status' do |
|
44
|
+
ch.on_request 'exit-status' do |_c, data|
|
39
45
|
exit_status = data.read_long
|
40
46
|
fail RemoteCommandExecutionError, command if exit_status != 0
|
41
47
|
end
|
data/lib/producer/core/task.rb
CHANGED
@@ -2,13 +2,13 @@ module Producer
|
|
2
2
|
module Core
|
3
3
|
class Task
|
4
4
|
class << self
|
5
|
-
def define_action
|
6
|
-
define_method
|
5
|
+
def define_action keyword, klass
|
6
|
+
define_method keyword do |*args|
|
7
7
|
@actions << klass.new(@env, *args)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def evaluate
|
11
|
+
def evaluate env, name, *args, &block
|
12
12
|
new(env, name).tap { |o| o.instance_exec *args, &block }
|
13
13
|
end
|
14
14
|
end
|
@@ -32,7 +32,7 @@ module Producer
|
|
32
32
|
|
33
33
|
attr_reader :name, :actions, :condition
|
34
34
|
|
35
|
-
def initialize
|
35
|
+
def initialize env, name, actions = [], condition = true
|
36
36
|
@env = env
|
37
37
|
@name = name
|
38
38
|
@actions = actions
|
@@ -43,22 +43,28 @@ module Producer
|
|
43
43
|
!!@condition
|
44
44
|
end
|
45
45
|
|
46
|
-
def condition
|
46
|
+
def condition &block
|
47
47
|
@condition = Condition.evaluate(@env, &block) if block
|
48
48
|
@condition
|
49
49
|
end
|
50
50
|
|
51
|
-
def task
|
51
|
+
def task name, *args, &block
|
52
52
|
@actions << self.class.evaluate(@env, name, *args, &block)
|
53
53
|
end
|
54
54
|
|
55
|
-
def ask
|
56
|
-
prompter.prompt
|
55
|
+
def ask question, choices, prompter: build_prompter
|
56
|
+
prompter.prompt question, choices
|
57
57
|
end
|
58
58
|
|
59
|
-
def template
|
59
|
+
def template path, variables = {}
|
60
60
|
Template.new(path).render variables
|
61
61
|
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def build_prompter
|
66
|
+
Prompter.new(@env.input, @env.output)
|
67
|
+
end
|
62
68
|
end
|
63
69
|
end
|
64
70
|
end
|
@@ -3,28 +3,27 @@ module Producer
|
|
3
3
|
class Template
|
4
4
|
SEARCH_PATH = 'templates'.freeze
|
5
5
|
|
6
|
-
def initialize
|
6
|
+
def initialize path, search_path: SEARCH_PATH
|
7
7
|
@path = Pathname.new(path)
|
8
8
|
@search_path = Pathname.new(search_path)
|
9
9
|
end
|
10
10
|
|
11
|
-
def render
|
11
|
+
def render variables = {}
|
12
12
|
case (file_path = resolve_path).extname
|
13
|
-
|
14
|
-
|
13
|
+
when '.yaml' then render_yaml file_path
|
14
|
+
when '.erb' then render_erb file_path, variables
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
private
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
def render_erb(file_path, variables = {})
|
20
|
+
def render_erb file_path, variables = {}
|
22
21
|
tpl = ERB.new(File.read(file_path), nil, '-')
|
23
22
|
tpl.filename = file_path.to_s
|
24
23
|
tpl.result build_erb_binding variables
|
25
24
|
end
|
26
25
|
|
27
|
-
def render_yaml
|
26
|
+
def render_yaml file_path
|
28
27
|
YAML.load(File.read(file_path))
|
29
28
|
end
|
30
29
|
|
@@ -36,11 +35,11 @@ module Producer
|
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
|
-
def resolve_suffix
|
38
|
+
def resolve_suffix path
|
40
39
|
Pathname.glob("#{path}.{erb,yaml}").first
|
41
40
|
end
|
42
41
|
|
43
|
-
def build_erb_binding
|
42
|
+
def build_erb_binding variables
|
44
43
|
Object.new.instance_eval do |o|
|
45
44
|
variables.each do |k, v|
|
46
45
|
o.instance_variable_set "@#{k}", v
|
data/lib/producer/core/test.rb
CHANGED
@@ -2,8 +2,8 @@ module Producer
|
|
2
2
|
module Core
|
3
3
|
module Testing
|
4
4
|
class ArubaProgramWrapper
|
5
|
-
def initialize
|
6
|
-
kernel = Kernel
|
5
|
+
def initialize argv, stdin = $stdin, stdout = $stdout, stderr = $stderr,
|
6
|
+
kernel = Kernel
|
7
7
|
@argv = argv
|
8
8
|
@stdin = stdin
|
9
9
|
@stdout = stdout
|
@@ -1,3 +1,15 @@
|
|
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
|
+
|
1
13
|
Then /^the output must match \/([^\/]+)\/$/ do |pattern|
|
2
14
|
assert_matching_output pattern, all_output
|
3
15
|
end
|
@@ -1,13 +1,13 @@
|
|
1
|
-
def run_recipe
|
1
|
+
def run_recipe remote: false, options: nil, check: false, rargv: nil
|
2
2
|
command = %w[producer recipe.rb]
|
3
3
|
case remote
|
4
|
-
|
5
|
-
|
4
|
+
when :unknown then command += %w[-t unknown_host.test]
|
5
|
+
when true then command += %w[-t some_host.test]
|
6
6
|
end
|
7
7
|
command << options if options
|
8
8
|
command << ['--', *rargv] if rargv
|
9
9
|
|
10
|
-
|
10
|
+
with_environment 'HOME' => expand_path('.') do
|
11
11
|
run_simple command.join(' '), false
|
12
12
|
end
|
13
13
|
|
@@ -72,5 +72,5 @@ When /^I successfully execute the recipe with arguments "([^"]+)"$/ do |rargv|
|
|
72
72
|
end
|
73
73
|
|
74
74
|
When /^I execute the recipe interactively$/ do
|
75
|
-
|
75
|
+
run 'producer recipe.rb'
|
76
76
|
end
|
@@ -1,11 +1,11 @@
|
|
1
|
-
def stat_mode
|
2
|
-
|
1
|
+
def stat_mode path
|
2
|
+
cd '.' do
|
3
3
|
('%o' % [File::Stat.new(path).mode])[-4, 4]
|
4
4
|
end
|
5
5
|
end
|
6
6
|
|
7
7
|
Given /^a remote directory named "([^"]+)"$/ do |path|
|
8
|
-
|
8
|
+
create_directory path
|
9
9
|
end
|
10
10
|
|
11
11
|
Given /^a remote file named "([^"]+)"$/ do |file_name|
|
@@ -17,7 +17,7 @@ Given /^a remote file named "([^"]+)" with "([^"]+)"$/ do |file_name, content|
|
|
17
17
|
end
|
18
18
|
|
19
19
|
Then /^the remote directory "([^"]+)" must exist$/ do |path|
|
20
|
-
|
20
|
+
expect(path).to be_an_existing_directory
|
21
21
|
end
|
22
22
|
|
23
23
|
Then /^the remote file "([^"]+)" must exist$/ do |path|
|
@@ -25,19 +25,19 @@ Then /^the remote file "([^"]+)" must exist$/ do |path|
|
|
25
25
|
end
|
26
26
|
|
27
27
|
Then /^the remote file "([^"]+)" must contain "([^"]+)"$/ do |path, content|
|
28
|
-
|
28
|
+
expect(path).to have_file_content Regexp.new(content)
|
29
29
|
end
|
30
30
|
|
31
31
|
Then /^the remote file "([^"]+)" must contain exactly "([^"]+)"$/ do |path, content|
|
32
|
-
|
32
|
+
expect(path).to have_file_content content
|
33
33
|
end
|
34
34
|
|
35
35
|
Then /^the remote file "([^"]+)" must contain exactly:$/ do |path, content|
|
36
|
-
|
36
|
+
expect(path).to have_file_content content
|
37
37
|
end
|
38
38
|
|
39
39
|
Then /^the remote file "([^"]+)" must match \/([^\/]+)\/$/ do |path, pattern|
|
40
|
-
|
40
|
+
expect(path).to have_file_content /#{pattern}/
|
41
41
|
end
|
42
42
|
|
43
43
|
Then /^the remote file "([^"]+)" must have (\d+) mode$/ do |path, mode|
|
@@ -18,12 +18,12 @@ end
|
|
18
18
|
# Use aruba "in process" optimization only for scenarios not tagged @exec.
|
19
19
|
# We need a real process in a few cases: real program name, interactive usage…
|
20
20
|
Before('@exec') do
|
21
|
-
|
21
|
+
aruba.config.command_launcher = :spawn
|
22
22
|
end
|
23
23
|
|
24
24
|
Before('~@exec') do
|
25
|
-
|
26
|
-
|
25
|
+
aruba.config.command_launcher = :in_process
|
26
|
+
aruba.config.main_class = Producer::Core::Testing::ArubaProgramWrapper
|
27
27
|
end
|
28
28
|
|
29
29
|
# Enable cucumber-sshd "fast" mode (persists sshd across scenarios), and
|
@@ -3,35 +3,37 @@ module Producer
|
|
3
3
|
module Testing
|
4
4
|
class MockRemote < Remote
|
5
5
|
def session
|
6
|
-
fail 'no session for mock remote!'
|
6
|
+
fail RuntimeError, 'no session for mock remote!'
|
7
7
|
end
|
8
8
|
|
9
|
-
def execute
|
10
|
-
|
11
|
-
|
9
|
+
def execute command, output = '', error_output = ''
|
10
|
+
program, *args = command.gsub(/\d?>.*/, '').split
|
11
|
+
program_output = command =~ />&2\z/ ? error_output : output
|
12
|
+
send "handle_program_#{program}", args, program_output
|
13
|
+
output
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
when 'echo'
|
15
|
-
out = tokens.join(' ') << "\n"
|
16
|
-
if command =~ />&2\z/
|
17
|
-
error_output << out
|
18
|
-
else
|
19
|
-
output << out
|
20
|
-
end
|
21
|
-
when 'true'
|
22
|
-
output << ''
|
23
|
-
when 'false'
|
24
|
-
fail RemoteCommandExecutionError
|
25
|
-
when 'type'
|
26
|
-
fail RemoteCommandExecutionError unless %w[
|
27
|
-
echo
|
28
|
-
true
|
29
|
-
false
|
30
|
-
type
|
31
|
-
].include? tokens.first
|
32
|
-
end
|
16
|
+
private
|
33
17
|
|
34
|
-
|
18
|
+
def handle_program_echo args, output
|
19
|
+
output << args.join(' ') << "\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
def handle_program_true _, output
|
23
|
+
output << ''
|
24
|
+
end
|
25
|
+
|
26
|
+
def handle_program_false *_
|
27
|
+
fail RemoteCommandExecutionError
|
28
|
+
end
|
29
|
+
|
30
|
+
def handle_program_type args, _
|
31
|
+
fail RemoteCommandExecutionError unless %w[
|
32
|
+
echo
|
33
|
+
true
|
34
|
+
false
|
35
|
+
type
|
36
|
+
].include? args.first
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -4,15 +4,12 @@ module Producer
|
|
4
4
|
class HasEnv < Test
|
5
5
|
def verify
|
6
6
|
case arguments.size
|
7
|
-
|
8
|
-
remote.environment
|
9
|
-
when 2
|
10
|
-
remote.environment[key] == arguments.last
|
7
|
+
when 1 then remote.environment.key? key
|
8
|
+
when 2 then remote.environment[key] == arguments.last
|
11
9
|
end
|
12
10
|
end
|
13
11
|
|
14
|
-
|
15
|
-
private
|
12
|
+
private
|
16
13
|
|
17
14
|
def key
|
18
15
|
arguments.first.to_s.upcase
|
data/lib/producer/core/worker.rb
CHANGED
@@ -4,22 +4,23 @@ module Producer
|
|
4
4
|
DRY_RUN_WARNING =
|
5
5
|
'running in dry run mode, actions will NOT be applied'.freeze
|
6
6
|
|
7
|
-
def initialize
|
7
|
+
def initialize env
|
8
8
|
@env = env
|
9
9
|
end
|
10
10
|
|
11
|
-
def process
|
11
|
+
def process tasks
|
12
12
|
@env.log DRY_RUN_WARNING, :warn if @env.dry_run?
|
13
13
|
|
14
14
|
tasks.each { |t| process_task t }
|
15
15
|
end
|
16
16
|
|
17
|
-
def process_task
|
17
|
+
def process_task task, indent_level = 0
|
18
18
|
if task.condition_met?
|
19
19
|
log "Task: `#{task}' applying...", indent_level
|
20
20
|
task.actions.each do |e|
|
21
21
|
case e
|
22
|
-
when Task
|
22
|
+
when Task
|
23
|
+
process_task e, indent_level + 2
|
23
24
|
else
|
24
25
|
log " action: #{e}", indent_level
|
25
26
|
e.apply unless @env.dry_run?
|
@@ -30,10 +31,9 @@ module Producer
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
34
|
+
private
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
def log(message, indent_level)
|
36
|
+
def log message, indent_level
|
37
37
|
message = [' ' * indent_level, message].join
|
38
38
|
@env.log message
|
39
39
|
end
|
data/lib/producer/core.rb
CHANGED
data/producer-core.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
s.add_development_dependency 'rspec', '~> 3.1'
|
24
24
|
s.add_development_dependency 'cucumber', '~> 2.0'
|
25
|
-
s.add_development_dependency 'aruba', '~> 0.
|
26
|
-
s.add_development_dependency 'cucumber-sshd', '~> 1.1'
|
25
|
+
s.add_development_dependency 'aruba', '~> 0.8'
|
26
|
+
s.add_development_dependency 'cucumber-sshd', '~> 1.1.1'
|
27
27
|
s.add_development_dependency 'rake', '~> 10.1'
|
28
28
|
end
|
@@ -8,15 +8,16 @@ module Producer::Core
|
|
8
8
|
let(:options) { [] }
|
9
9
|
let(:recipe_file) { fixture_path_for 'recipes/some_recipe.rb' }
|
10
10
|
let(:arguments) { [*options, recipe_file] }
|
11
|
+
let(:environment) { {} }
|
11
12
|
|
12
|
-
subject(:cli) { described_class.new(arguments) }
|
13
|
+
subject(:cli) { described_class.new(arguments, environment) }
|
13
14
|
|
14
15
|
describe '.run!' do
|
15
16
|
subject(:run!) { described_class.run! arguments }
|
16
17
|
|
17
|
-
it 'builds a new CLI instance with given arguments' do
|
18
|
+
it 'builds a new CLI instance with given arguments and environment' do
|
18
19
|
expect(described_class)
|
19
|
-
.to receive(:new).with(arguments, anything).and_call_original
|
20
|
+
.to receive(:new).with(arguments, ENV, anything).and_call_original
|
20
21
|
run!
|
21
22
|
end
|
22
23
|
|
@@ -54,7 +55,7 @@ module Producer::Core
|
|
54
55
|
|
55
56
|
it 'prints a report to the error stream' do
|
56
57
|
expect { trap_exit { run! } }
|
57
|
-
.to output(/\
|
58
|
+
.to output(/\ARecipeEvaluationError: false$/).to_stderr
|
58
59
|
end
|
59
60
|
end
|
60
61
|
end
|
@@ -75,6 +76,30 @@ module Producer::Core
|
|
75
76
|
it 'assigns CLI stderr as the env error output' do
|
76
77
|
expect(cli.env.error_output).to be cli.stderr
|
77
78
|
end
|
79
|
+
|
80
|
+
context 'when PRODUCER_VERBOSE environment variable is set' do
|
81
|
+
before { environment['PRODUCER_VERBOSE'] = 'yes' }
|
82
|
+
|
83
|
+
it 'enables env verbose mode' do
|
84
|
+
expect(cli.env).to be_verbose
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when PRODUCER_DEBUG environment variable is set' do
|
89
|
+
before { environment['PRODUCER_DEBUG'] = 'yes' }
|
90
|
+
|
91
|
+
it 'enables env debug mode' do
|
92
|
+
expect(cli.env).to be_debug
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when PRODUCER_DRYRUN environment variable is set' do
|
97
|
+
before { environment['PRODUCER_DRYRUN'] = 'yes' }
|
98
|
+
|
99
|
+
it 'enables env dry run mode' do
|
100
|
+
expect(cli.env).to be_dry_run
|
101
|
+
end
|
102
|
+
end
|
78
103
|
end
|
79
104
|
|
80
105
|
describe '#parse_arguments!' do
|
@@ -27,6 +27,14 @@ module Producer::Core
|
|
27
27
|
allow(Net::SSH).to receive(:start) { Object.new }
|
28
28
|
expect(remote.session).to be remote.session
|
29
29
|
end
|
30
|
+
|
31
|
+
context 'when hostname is invalid' do
|
32
|
+
let(:hostname) { nil }
|
33
|
+
|
34
|
+
it 'raises RemoteInvalidError' do
|
35
|
+
expect { remote.session }.to raise_error RemoteInvalidError
|
36
|
+
end
|
37
|
+
end
|
30
38
|
end
|
31
39
|
|
32
40
|
describe '#config' do
|
@@ -128,7 +136,7 @@ module Producer::Core
|
|
128
136
|
|
129
137
|
it 'raises an exception' do
|
130
138
|
expect { remote.execute command }
|
131
|
-
.to raise_error
|
139
|
+
.to raise_error RemoteCommandExecutionError
|
132
140
|
end
|
133
141
|
|
134
142
|
it 'includes the command in the exception message' do
|