producer-core 0.2.10 → 0.2.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 746db32442ceec92cc0067f515e69d43c052afee
4
- data.tar.gz: 8c3b7aaf1f0e4b6722609243204b635f1d5db6af
3
+ metadata.gz: a8faaa83c5e385860c285a917432f88805b1445d
4
+ data.tar.gz: b52d94053b00d17230c749c322951a9bb827cf62
5
5
  SHA512:
6
- metadata.gz: ddfa5f0ffa6e5bd5b67f93d2c89b580ded6edc99876dad0e38daf5f2a3c0b36eb87b73cf0bb7ad97a257efaebe53a454263a81a838accf980dc87ee8bb531290
7
- data.tar.gz: ffe69bcb350968fa1e3e97cc5ea5668efa4ac191d1e21731c7cedf797e0f9609b3a356d0441e0ec4b1bd4b3e72f910f2ba037a070edff111a4d922947a599e12
6
+ metadata.gz: f6b3876fbe282f363d89b8fde05c0c39d9631e13cb64fa42b7bc5fae4773b76ceba55895906afa1a51b34429de16b5ca24cb75ba3f68d78222cd9148fe0e26ad
7
+ data.tar.gz: 4ad7ba7ef20948f5ad4ddc795fb7a6a075f5de6fd06591e86edd8b8114e20e5aa22c405652c074b5624915f44223de00dd250071997146d4baaa7b942173adb2
@@ -7,11 +7,9 @@ Feature: `file_append' task action
7
7
  Scenario: appends given content to requested file
8
8
  Given a recipe with:
9
9
  """
10
- target 'some_host.test'
11
-
12
10
  task :file_append_action do
13
11
  file_append 'some_file', ' added'
14
12
  end
15
13
  """
16
- When I successfully execute the recipe
14
+ When I successfully execute the recipe on remote target
17
15
  Then the remote file "some_file" must contain exactly "some content added"
@@ -6,8 +6,6 @@ Feature: `file_replace_content' task action
6
6
  And a remote file named "other_file" with "some content"
7
7
  And a recipe with:
8
8
  """
9
- target 'some_host.test'
10
-
11
9
  task :file_replace_content_action_string do
12
10
  file_replace_content 'some_file', 'content', 'other content'
13
11
  end
@@ -18,9 +16,9 @@ Feature: `file_replace_content' task action
18
16
  """
19
17
 
20
18
  Scenario: replaces a string by another in the requested file
21
- When I successfully execute the recipe
19
+ When I successfully execute the recipe on remote target
22
20
  Then the remote file "some_file" must contain exactly "some other content"
23
21
 
24
22
  Scenario: replaces a regular expression by a string in the requested file
25
- When I successfully execute the recipe
23
+ When I successfully execute the recipe on remote target
26
24
  Then the remote file "other_file" must contain exactly "some other content"
@@ -4,8 +4,6 @@ Feature: `file_write' task action
4
4
  Background:
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :file_write_action do
10
8
  file_write 'some_file', 'some_content'
11
9
  file_write 'some_file_0600', 'some_content', 0600
@@ -14,10 +12,10 @@ Feature: `file_write' task action
14
12
  """
15
13
 
16
14
  Scenario: writes given data to given file path
17
- When I successfully execute the recipe
15
+ When I successfully execute the recipe on remote target
18
16
  Then the remote file "some_file" must contain "some_content"
19
17
 
20
18
  Scenario: creates file with given permissions
21
- When I successfully execute the recipe
19
+ When I successfully execute the recipe on remote target
22
20
  Then the remote file "some_file_0600" must have 0600 mode
23
21
  And the remote file "some_file_0700" must have 0700 mode
@@ -4,8 +4,6 @@ Feature: `mkdir' task action
4
4
  Background:
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :mkdir_action do
10
8
  mkdir 'some_directory'
11
9
  mkdir 'some_directory_0700', 0700
@@ -14,10 +12,10 @@ Feature: `mkdir' task action
14
12
  """
15
13
 
16
14
  Scenario: creates directory given as argument
17
- When I successfully execute the recipe
15
+ When I successfully execute the recipe on remote target
18
16
  Then the remote directory "some_directory" must exists
19
17
 
20
18
  Scenario: creates directory with given permissions
21
- When I successfully execute the recipe
19
+ When I successfully execute the recipe on remote target
22
20
  Then the remote directory "some_directory_0700" must have 0700 mode
23
21
  And the remote directory "some_directory_0500" must have 0500 mode
@@ -4,36 +4,40 @@ Feature: `sh' task action
4
4
  Scenario: forwards standard ouput
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :sh_action do
10
8
  sh '\echo hello from remote'
11
9
  end
12
10
  """
13
- When I successfully execute the recipe
11
+ When I successfully execute the recipe on remote target
14
12
  Then the output must contain exactly "hello from remote\n"
15
13
 
16
- Scenario: aborts on failed command execution
14
+ Scenario: forwards error ouput
17
15
  Given a recipe with:
18
16
  """
19
- target 'some_host.test'
17
+ task :sh_action do
18
+ sh '\echo error from remote >&2'
19
+ end
20
+ """
21
+ When I successfully execute the recipe on remote target
22
+ Then the error output must contain exactly "error from remote\n"
20
23
 
24
+ Scenario: aborts on failed command execution
25
+ Given a recipe with:
26
+ """
21
27
  task :sh_action_aborting do
22
28
  sh '\false'
23
29
  sh '\echo after_fail'
24
30
  end
25
31
  """
26
- When I execute the recipe
32
+ When I execute the recipe on remote target
27
33
  Then the output must not contain "after_fail"
28
34
 
29
35
  Scenario: prints command when execution fail
30
36
  Given a recipe with:
31
37
  """
32
- target 'some_host.test'
33
-
34
38
  task :sh_action_command_error do
35
39
  sh '\false'
36
40
  end
37
41
  """
38
- When I execute the recipe
42
+ When I execute the recipe on remote target
39
43
  Then the output must match /\A\w+Error:\s+\\false/
@@ -10,6 +10,6 @@ Feature: CLI target option
10
10
  end
11
11
  """
12
12
 
13
- Scenario: prints tasks name
13
+ Scenario: override the recipe target
14
14
  When I successfully execute the recipe with option -t other_host.example
15
15
  Then the output must contain exactly "other_host.example\n"
@@ -22,8 +22,6 @@ Feature: `test_macro' recipe keyword
22
22
  Scenario: has access to core tests
23
23
  Given a recipe with:
24
24
  """
25
- target 'some_host.test'
26
-
27
25
  test_macro(:other_env?) { |k| env? k }
28
26
 
29
27
  [:shell, :non_existent_var].each do |k|
@@ -33,7 +31,7 @@ Feature: `test_macro' recipe keyword
33
31
  end
34
32
  end
35
33
  """
36
- When I successfully execute the recipe
34
+ When I successfully execute the recipe on remote target
37
35
  Then the output must contain "shell_ok"
38
36
  Then the output must not contain "non_existent_var_ok"
39
37
 
@@ -21,3 +21,7 @@ end
21
21
  Then /^the output must contain exactly:$/ do |content|
22
22
  assert_exact_output content, all_output
23
23
  end
24
+
25
+ Then /^the error output must contain exactly "([^"]+)"$/ do |content|
26
+ assert_exact_output content, all_stderr
27
+ end
@@ -6,11 +6,20 @@ When /^I execute the recipe$/ do
6
6
  run_simple 'producer recipe.rb', false
7
7
  end
8
8
 
9
+ When /^I execute the recipe on remote target$/ do
10
+ run_simple 'producer recipe.rb -t some_host.test', false
11
+ end
12
+
9
13
  When /^I successfully execute the recipe$/ do
10
14
  step 'I execute the recipe'
11
15
  assert_exit_status 0
12
16
  end
13
17
 
18
+ When /^I successfully execute the recipe on remote target$/ do
19
+ step 'I execute the recipe on remote target'
20
+ assert_exit_status 0
21
+ end
22
+
14
23
  When /^I successfully execute the recipe with option (-.+)$/ do |option|
15
24
  run_simple "producer #{option} recipe.rb", false
16
25
  assert_exit_status 0
@@ -4,8 +4,6 @@ Feature: `dir?' condition keyword
4
4
  Background:
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :dir_test do
10
8
  condition { dir? 'some_directory' }
11
9
 
@@ -15,9 +13,9 @@ Feature: `dir?' condition keyword
15
13
 
16
14
  Scenario: succeeds when directory exists
17
15
  Given a remote directory named "some_directory"
18
- When I successfully execute the recipe
16
+ When I successfully execute the recipe on remote target
19
17
  Then the output must contain "evaluated"
20
18
 
21
19
  Scenario: fails when directory does not exist
22
- When I successfully execute the recipe
20
+ When I successfully execute the recipe on remote target
23
21
  Then the output must not contain "evaluated"
@@ -4,8 +4,6 @@ Feature: `env?' condition keyword
4
4
  Background:
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :env_test_definition_ok do
10
8
  condition { env? :shell }
11
9
 
@@ -32,17 +30,17 @@ Feature: `env?' condition keyword
32
30
  """
33
31
 
34
32
  Scenario: succeeds when remote environment variable is defined
35
- When I successfully execute the recipe
33
+ When I successfully execute the recipe on remote target
36
34
  Then the output must contain "definition_ok"
37
35
 
38
36
  Scenario: fails when remote environment variable is not defined
39
- When I successfully execute the recipe
37
+ When I successfully execute the recipe on remote target
40
38
  Then the output must not contain "definition_ko"
41
39
 
42
40
  Scenario: succeeds when remote environment variable value match
43
- When I successfully execute the recipe
41
+ When I successfully execute the recipe on remote target
44
42
  Then the output must contain "value_ok"
45
43
 
46
44
  Scenario: fails when remote environment variable value does not match
47
- When I successfully execute the recipe
45
+ When I successfully execute the recipe on remote target
48
46
  Then the output must not contain "value_ko"
@@ -4,8 +4,6 @@ Feature: `executable?' condition keyword
4
4
  Background:
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :executable_test_ok do
10
8
  condition { executable? 'true' }
11
9
 
@@ -20,9 +18,9 @@ Feature: `executable?' condition keyword
20
18
  """
21
19
 
22
20
  Scenario: succeeds when remote executable is available
23
- When I successfully execute the recipe
21
+ When I successfully execute the recipe on remote target
24
22
  Then the output must contain "test_ok"
25
23
 
26
24
  Scenario: fails when remote executable is not available
27
- When I successfully execute the recipe
25
+ When I successfully execute the recipe on remote target
28
26
  Then the output must not contain "test_ko"
@@ -4,8 +4,6 @@ Feature: `file?' condition keyword
4
4
  Background:
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :file_test do
10
8
  condition { file? 'some_file' }
11
9
 
@@ -15,9 +13,9 @@ Feature: `file?' condition keyword
15
13
 
16
14
  Scenario: succeeds when file exists
17
15
  Given a remote file named "some_file"
18
- When I successfully execute the recipe
16
+ When I successfully execute the recipe on remote target
19
17
  Then the output must contain "evaluated"
20
18
 
21
19
  Scenario: fails when file does not exist
22
- When I successfully execute the recipe
20
+ When I successfully execute the recipe on remote target
23
21
  Then the output must not contain "evaluated"
@@ -4,8 +4,6 @@ Feature: `file_contains' condition keyword
4
4
  Background:
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :file_contains_test do
10
8
  condition { file_contains 'some_file', 'some_content' }
11
9
 
@@ -15,14 +13,14 @@ Feature: `file_contains' condition keyword
15
13
 
16
14
  Scenario: succeeds when file contains expected content
17
15
  Given a remote file named "some_file" with "some_content"
18
- When I successfully execute the recipe
16
+ When I successfully execute the recipe on remote target
19
17
  Then the output must contain "evaluated"
20
18
 
21
19
  Scenario: fails when file does not contain expected content
22
20
  Given a remote file named "some_file" with "some_other_content"
23
- When I successfully execute the recipe
21
+ When I successfully execute the recipe on remote target
24
22
  Then the output must not contain "evaluated"
25
23
 
26
24
  Scenario: fails when file does not exist
27
- When I successfully execute the recipe
25
+ When I successfully execute the recipe on remote target
28
26
  Then the output must not contain "evaluated"
@@ -4,8 +4,6 @@ Feature: negated test prefix (no_)
4
4
  Scenario: prefixed test fails when non-prefixed test is successful
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :successful_test do
10
8
  condition { env? :shell }
11
9
 
@@ -18,15 +16,13 @@ Feature: negated test prefix (no_)
18
16
  echo 'negated_test'
19
17
  end
20
18
  """
21
- When I successfully execute the recipe
19
+ When I successfully execute the recipe on remote target
22
20
  Then the output must contain "successful_test"
23
21
  And the output must not contain "negated_test"
24
22
 
25
23
  Scenario: prefixed test fails when non-prefixed test is failing
26
24
  Given a recipe with:
27
25
  """
28
- target 'some_host.test'
29
-
30
26
  task :failing_test do
31
27
  condition { env? :inexistent_var }
32
28
 
@@ -39,6 +35,6 @@ Feature: negated test prefix (no_)
39
35
  echo 'negated_test'
40
36
  end
41
37
  """
42
- When I successfully execute the recipe
38
+ When I successfully execute the recipe on remote target
43
39
  Then the output must not contain "failing_test"
44
40
  And the output must contain "negated_test"
@@ -4,8 +4,6 @@ Feature: `sh' and `` condition keyword
4
4
  Background:
5
5
  Given a recipe with:
6
6
  """
7
- target 'some_host.test'
8
-
9
7
  task :sh_test_ok do
10
8
  condition { sh 'true' }
11
9
 
@@ -32,17 +30,17 @@ Feature: `sh' and `` condition keyword
32
30
  """
33
31
 
34
32
  Scenario: succeeds when remote command execution is a success
35
- When I successfully execute the recipe
33
+ When I successfully execute the recipe on remote target
36
34
  Then the output must contain "test_ok"
37
35
 
38
36
  Scenario: fails when remote executable is not available
39
- When I successfully execute the recipe
37
+ When I successfully execute the recipe on remote target
40
38
  Then the output must not contain "test_ko"
41
39
 
42
40
  Scenario: `` alias, succeeds when remote executable is available
43
- When I successfully execute the recipe
41
+ When I successfully execute the recipe on remote target
44
42
  Then the output must contain "test_backtick_ok"
45
43
 
46
44
  Scenario: `` alias, fails when remote executable is not available
47
- When I successfully execute the recipe
45
+ When I successfully execute the recipe on remote target
48
46
  Then the output must not contain "test_backtick_ko"
@@ -2,7 +2,7 @@ module Producer
2
2
  module Core
3
3
  class Action
4
4
  extend Forwardable
5
- def_delegators :@env, :input, :output, :remote
5
+ def_delegators :@env, :input, :output, :error_output, :remote
6
6
  def_delegators :remote, :fs
7
7
 
8
8
  attr_reader :env, :arguments
@@ -7,7 +7,7 @@ module Producer
7
7
  end
8
8
 
9
9
  def apply
10
- remote.execute(arguments.first, output)
10
+ remote.execute(arguments.first, output, error_output)
11
11
  end
12
12
  end
13
13
  end
@@ -31,7 +31,7 @@ module Producer
31
31
  @arguments = args
32
32
  @stdin = stdin
33
33
  @stdout = stdout
34
- @env = Env.new(input: stdin, output: stdout)
34
+ @env = Env.new(input: stdin, output: stdout, error_output: stderr)
35
35
  end
36
36
 
37
37
  def parse_arguments!
@@ -1,15 +1,16 @@
1
1
  module Producer
2
2
  module Core
3
3
  class Env
4
- attr_reader :input, :output, :registry, :logger
4
+ attr_reader :input, :output, :error_output, :registry, :logger
5
5
  attr_accessor :target, :verbose, :dry_run
6
6
 
7
- def initialize(input: $stdin, output: $stdout, remote: nil, registry: {})
8
- @verbose = @dry_run = false
9
- @input = input
10
- @output = output
11
- @remote = remote
12
- @registry = registry
7
+ def initialize(input: $stdin, output: $stdout, error_output: $stderr, remote: nil, registry: {})
8
+ @verbose = @dry_run = false
9
+ @input = input
10
+ @output = output
11
+ @error_output = error_output
12
+ @remote = remote
13
+ @registry = registry
13
14
  end
14
15
 
15
16
  def remote
@@ -24,13 +24,17 @@ module Producer
24
24
  @fs ||= Remote::FS.new(session.sftp.connect)
25
25
  end
26
26
 
27
- def execute(command, output = '')
27
+ def execute(command, output = '', error_output = '')
28
28
  channel = session.open_channel do |channel|
29
29
  channel.exec command do |ch, success|
30
30
  ch.on_data do |c, data|
31
31
  output << data
32
32
  end
33
33
 
34
+ ch.on_extended_data do |c, type, data|
35
+ error_output << data
36
+ end
37
+
34
38
  ch.on_request 'exit-status' do |c, data|
35
39
  exit_status = data.read_long
36
40
  fail RemoteCommandExecutionError, command if exit_status != 0
@@ -6,13 +6,18 @@ module Producer
6
6
  fail 'no session for mock remote!'
7
7
  end
8
8
 
9
- def execute(command, output = '')
10
- tokens = command.split
9
+ def execute(command, output = '', error_output = '')
10
+ tokens = command.gsub(/\d?>.*/, '').split
11
11
  program = tokens.shift
12
12
 
13
13
  case program
14
14
  when 'echo'
15
- output << tokens.join(' ') << "\n"
15
+ out = tokens.join(' ') << "\n"
16
+ if command =~ />&2\z/
17
+ error_output << out
18
+ else
19
+ output << out
20
+ end
16
21
  when 'true'
17
22
  output << ''
18
23
  when 'false'
@@ -1,5 +1,5 @@
1
1
  module Producer
2
2
  module Core
3
- VERSION = '0.2.10'.freeze
3
+ VERSION = '0.2.11'.freeze
4
4
  end
5
5
  end
@@ -19,6 +19,15 @@ module Producer::Core
19
19
  sh.apply
20
20
  expect(output).to eq "#{command_args}\n"
21
21
  end
22
+
23
+ context 'when content is written to standard error' do
24
+ let(:command) { "echo #{command_args} >&2" }
25
+
26
+ it 'writes errors to given error stream' do
27
+ sh.apply
28
+ expect(error_output).to eq "#{command_args}\n"
29
+ end
30
+ end
22
31
  end
23
32
  end
24
33
  end
@@ -12,7 +12,9 @@ module Producer::Core
12
12
  let(:stdout) { StringIO.new }
13
13
  let(:stderr) { StringIO.new }
14
14
 
15
- subject(:cli) { CLI.new(arguments, stdin: stdin, stdout: stdout) }
15
+ subject(:cli) { described_class.new(
16
+ arguments,
17
+ stdin: stdin, stdout: stdout, stderr: stderr) }
16
18
 
17
19
  describe '.run!' do
18
20
  let(:cli) { double('cli').as_null_object }
@@ -118,6 +120,10 @@ module Producer::Core
118
120
  it 'assigns CLI stdout as the env output' do
119
121
  expect(cli.env.output).to be stdout
120
122
  end
123
+
124
+ it 'assigns CLI stderr as the env error output' do
125
+ expect(cli.env.error_output).to be stderr
126
+ end
121
127
  end
122
128
 
123
129
  describe '#parse_arguments!' do
@@ -10,6 +10,10 @@ module Producer::Core
10
10
  expect(env.input).to be $stdin
11
11
  end
12
12
 
13
+ it 'assigns $stderr as the default error output' do
14
+ expect(env.error_output).to be $stderr
15
+ end
16
+
13
17
  it 'assigns no default target' do
14
18
  expect(env.target).not_to be
15
19
  end
@@ -51,6 +55,15 @@ module Producer::Core
51
55
  end
52
56
  end
53
57
 
58
+ context 'when error output is given as argument' do
59
+ let(:error_output) { StringIO.new }
60
+ subject(:env) { described_class.new(error_output: error_output) }
61
+
62
+ it 'assigns the given error output' do
63
+ expect(env.error_output).to be error_output
64
+ end
65
+ end
66
+
54
67
  context 'when remote is given as argument' do
55
68
  let(:remote) { double 'remote' }
56
69
  subject(:env) { described_class.new(remote: remote) }
@@ -106,6 +106,16 @@ module Producer::Core
106
106
  expect(output.string).to eq arguments
107
107
  end
108
108
 
109
+ it 'writes command error output to provided error output' do
110
+ error_output = StringIO.new
111
+ story_with_new_channel do |ch|
112
+ ch.sends_exec command
113
+ ch.gets_extended_data arguments
114
+ end
115
+ remote.execute command, output, error_output
116
+ expect(error_output.string).to eq arguments
117
+ end
118
+
109
119
  context 'when command execution fails' do
110
120
  before do
111
121
  story_with_new_channel do |ch|
@@ -29,6 +29,12 @@ module Producer::Core
29
29
  end
30
30
  end
31
31
 
32
+ describe '#error_output' do
33
+ it 'returns env error output' do
34
+ expect(action.error_output).to be env.error_output
35
+ end
36
+ end
37
+
32
38
  describe '#remote' do
33
39
  it 'returns env remote' do
34
40
  expect(action.remote).to be env.remote
@@ -9,6 +9,10 @@ module TestEnvHelpers
9
9
  env.output.string
10
10
  end
11
11
 
12
+ def error_output
13
+ env.error_output.string
14
+ end
15
+
12
16
  def remote_fs
13
17
  env.remote.fs
14
18
  end
@@ -17,14 +21,18 @@ module TestEnvHelpers
17
21
  opts = { expected_from: caller.first }
18
22
  RSpec::Mocks
19
23
  .expect_message(env.remote, :execute, opts)
20
- .with(command, env.output)
24
+ .with(command, env.output, env.error_output)
21
25
  end
22
26
 
23
27
 
24
28
  private
25
29
 
26
30
  def build_env
27
- Producer::Core::Env.new(output: StringIO.new, remote: build_remote)
31
+ Producer::Core::Env.new(
32
+ output: StringIO.new,
33
+ error_output: StringIO.new,
34
+ remote: build_remote
35
+ )
28
36
  end
29
37
 
30
38
  def build_remote
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: producer-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.10
4
+ version: 0.2.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thibault Jouan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-14 00:00:00.000000000 Z
11
+ date: 2014-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-ssh