producer-core 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/features/{actions/echo.feature → action_echo.feature} +1 -1
  3. data/features/{actions/file_append.feature → action_file_append.feature} +1 -1
  4. data/features/{actions/file_replace_content.feature → action_file_replace_content.feature} +11 -14
  5. data/features/{actions/file_write.feature → action_file_write.feature} +7 -12
  6. data/features/{actions/mkdir.feature → action_mkdir.feature} +8 -13
  7. data/features/{actions/sh.feature → action_sh.feature} +14 -14
  8. data/features/{cli/dry_run.feature → cli_dry_run.feature} +0 -0
  9. data/features/{cli/usage.feature → cli_usage.feature} +1 -0
  10. data/features/{cli/verbose.feature → cli_verbose.feature} +12 -23
  11. data/features/{recipes/ask.feature → recipe_ask.feature} +1 -0
  12. data/features/{recipes/macro.feature → recipe_macro.feature} +4 -4
  13. data/features/{recipes/source.feature → recipe_source.feature} +3 -1
  14. data/features/{recipes/target.feature → recipe_target.feature} +3 -1
  15. data/features/recipe_test_macro.feature +52 -0
  16. data/features/{recipes/registry.feature → registry.feature} +9 -4
  17. data/features/{ssh/config.feature → ssh_config.feature} +3 -1
  18. data/features/support/env.rb +32 -0
  19. data/features/support/env_aruba_timeout.rb +3 -0
  20. data/features/{tasks/condition.feature → task_condition.feature} +1 -1
  21. data/features/{tests/dir.feature → test_dir.feature} +1 -1
  22. data/features/{tests/env.feature → test_env.feature} +24 -34
  23. data/features/{tests/executable.feature → test_executable.feature} +12 -14
  24. data/features/{tests/file.feature → test_file.feature} +1 -1
  25. data/features/{tests/file_contains.feature → test_file_contains.feature} +1 -1
  26. data/features/{tests/negated_test.feature → test_negated_test.feature} +0 -0
  27. data/features/test_shell_command_status.feature +48 -0
  28. data/lib/producer/core/cli.rb +19 -15
  29. data/lib/producer/core/condition/dsl.rb +17 -8
  30. data/lib/producer/core/condition.rb +2 -2
  31. data/lib/producer/core/env.rb +6 -10
  32. data/lib/producer/core/errors.rb +2 -1
  33. data/lib/producer/core/recipe/dsl.rb +4 -0
  34. data/lib/producer/core/remote.rb +1 -1
  35. data/lib/producer/core/tests/condition_test.rb +23 -0
  36. data/lib/producer/core/version.rb +1 -1
  37. data/lib/producer/core.rb +1 -0
  38. data/spec/producer/core/cli_spec.rb +73 -44
  39. data/spec/producer/core/condition/dsl_spec.rb +33 -5
  40. data/spec/producer/core/env_spec.rb +41 -36
  41. data/spec/producer/core/recipe/dsl_spec.rb +10 -0
  42. data/spec/producer/core/remote_spec.rb +16 -7
  43. data/spec/producer/core/tests/condition_test_spec.rb +55 -0
  44. metadata +56 -55
  45. data/features/recipes/evaluation.feature +0 -9
  46. data/features/tasks/evaluation.feature +0 -11
  47. data/features/tasks/registry.feature +0 -13
  48. data/features/tests/shell_command_status.feature +0 -58
@@ -0,0 +1,3 @@
1
+ Before do
2
+ @aruba_timeout_seconds = 8
3
+ end
@@ -3,7 +3,7 @@ Feature: `condition' task keyword
3
3
  Scenario: prevents task actions application when condition is not met
4
4
  Given a recipe with:
5
5
  """
6
- task :hello do
6
+ task :some_task do
7
7
  condition { false }
8
8
 
9
9
  echo 'evaluated'
@@ -6,7 +6,7 @@ Feature: `dir?' condition keyword
6
6
  """
7
7
  target 'some_host.test'
8
8
 
9
- task :testing_directory_existence do
9
+ task :dir_test do
10
10
  condition { dir? 'some_directory' }
11
11
 
12
12
  echo 'evaluated'
@@ -1,58 +1,48 @@
1
1
  @sshd
2
2
  Feature: `env?' condition keyword
3
3
 
4
- Scenario: succeeds when remote environment variable is defined
4
+ Background:
5
5
  Given a recipe with:
6
6
  """
7
7
  target 'some_host.test'
8
8
 
9
- task :testing_env_var_definition do
9
+ task :env_test_definition_ok do
10
10
  condition { env? :shell }
11
11
 
12
- echo 'evaluated'
12
+ echo 'definition_ok'
13
13
  end
14
- """
15
- When I successfully execute the recipe
16
- Then the output must contain "evaluated"
17
14
 
18
- Scenario: fails when remote environment variable is not defined
19
- Given a recipe with:
20
- """
21
- target 'some_host.test'
22
-
23
- task :testing_env_var_definition do
15
+ task :env_test_definition_ko do
24
16
  condition { env? :non_existent_var }
25
17
 
26
- echo 'evaluated'
18
+ echo 'definition_ko'
27
19
  end
28
- """
29
- When I successfully execute the recipe
30
- Then the output must not contain "evaluated"
31
-
32
- Scenario: succeeds when remote environment variable value match
33
- Given a recipe with:
34
- """
35
- target 'some_host.test'
36
20
 
37
- task :testing_env_var_value do
21
+ task :env_test_value do
38
22
  condition { env? :shell, '/bin/sh' }
39
23
 
40
- echo 'evaluated'
24
+ echo 'value_ok'
41
25
  end
42
- """
43
- When I successfully execute the recipe
44
- Then the output must contain "evaluated"
45
26
 
46
- Scenario: fails when remote environment variable value does not match
47
- Given a recipe with:
48
- """
49
- target 'some_host.test'
50
-
51
- task :testing_env_var_value do
27
+ task :env_test_value do
52
28
  condition { env? :shell, 'non_existent_shell' }
53
29
 
54
- echo 'evaluated'
30
+ echo 'value_ko'
55
31
  end
56
32
  """
33
+
34
+ Scenario: succeeds when remote environment variable is defined
35
+ When I successfully execute the recipe
36
+ Then the output must contain "definition_ok"
37
+
38
+ Scenario: fails when remote environment variable is not defined
39
+ When I successfully execute the recipe
40
+ Then the output must not contain "definition_ko"
41
+
42
+ Scenario: succeeds when remote environment variable value match
43
+ When I successfully execute the recipe
44
+ Then the output must contain "value_ok"
45
+
46
+ Scenario: fails when remote environment variable value does not match
57
47
  When I successfully execute the recipe
58
- Then the output must not contain "evaluated"
48
+ Then the output must not contain "value_ko"
@@ -1,30 +1,28 @@
1
1
  @sshd
2
2
  Feature: `executable?' condition keyword
3
3
 
4
- Scenario: succeeds when remote executable is available
4
+ Background:
5
5
  Given a recipe with:
6
6
  """
7
7
  target 'some_host.test'
8
8
 
9
- task :testing_executable_availability do
9
+ task :executable_test_ok do
10
10
  condition { executable? 'true' }
11
11
 
12
- echo 'evaluated'
12
+ echo 'test_ok'
13
13
  end
14
- """
15
- When I successfully execute the recipe
16
- Then the output must contain "evaluated"
17
-
18
- Scenario: succeeds when remote executable is available
19
- Given a recipe with:
20
- """
21
- target 'some_host.test'
22
14
 
23
- task :testing_executable_availability do
15
+ task :executable_test_ok do
24
16
  condition { executable? 'some_non_existent_executable' }
25
17
 
26
- echo 'evaluated'
18
+ echo 'test_ko'
27
19
  end
28
20
  """
21
+
22
+ Scenario: succeeds when remote executable is available
23
+ When I successfully execute the recipe
24
+ Then the output must contain "test_ok"
25
+
26
+ Scenario: fails when remote executable is not available
29
27
  When I successfully execute the recipe
30
- Then the output must not contain "evaluated"
28
+ Then the output must not contain "test_ko"
@@ -6,7 +6,7 @@ Feature: `file?' condition keyword
6
6
  """
7
7
  target 'some_host.test'
8
8
 
9
- task :testing_file_existence do
9
+ task :file_test do
10
10
  condition { file? 'some_file' }
11
11
 
12
12
  echo 'evaluated'
@@ -6,7 +6,7 @@ Feature: `file_contains' condition keyword
6
6
  """
7
7
  target 'some_host.test'
8
8
 
9
- task :testing_content_in_file_presense do
9
+ task :file_contains_test do
10
10
  condition { file_contains 'some_file', 'some_content' }
11
11
 
12
12
  echo 'evaluated'
@@ -0,0 +1,48 @@
1
+ @sshd
2
+ Feature: `sh' and `` condition keyword
3
+
4
+ Background:
5
+ Given a recipe with:
6
+ """
7
+ target 'some_host.test'
8
+
9
+ task :sh_test_ok do
10
+ condition { sh 'true' }
11
+
12
+ echo 'test_ok'
13
+ end
14
+
15
+ task :sh_test_ko do
16
+ condition { sh 'false' }
17
+
18
+ echo 'test_ko'
19
+ end
20
+
21
+ task :sh_test_backtick_ok do
22
+ condition { `true` }
23
+
24
+ echo 'test_backtick_ok'
25
+ end
26
+
27
+ task :sh_test_backtick_ko do
28
+ condition { `false` }
29
+
30
+ echo 'test_backtick_ko'
31
+ end
32
+ """
33
+
34
+ Scenario: succeeds when remote command execution is a success
35
+ When I successfully execute the recipe
36
+ Then the output must contain "test_ok"
37
+
38
+ Scenario: fails when remote executable is not available
39
+ When I successfully execute the recipe
40
+ Then the output must not contain "test_ko"
41
+
42
+ Scenario: `` alias, succeeds when remote executable is available
43
+ When I successfully execute the recipe
44
+ Then the output must contain "test_backtick_ok"
45
+
46
+ Scenario: `` alias, fails when remote executable is not available
47
+ When I successfully execute the recipe
48
+ Then the output must not contain "test_backtick_ko"
@@ -3,36 +3,41 @@ module Producer
3
3
  class CLI
4
4
  ArgumentError = Class.new(::ArgumentError)
5
5
 
6
- USAGE = "Usage: #{File.basename $0} [-v] [-n] recipe_file"
6
+ USAGE = "Usage: #{File.basename $0} [-v] [-n] recipe_file".freeze
7
7
 
8
- EX_USAGE = 64
8
+ EX_USAGE = 64
9
+ EX_SOFTWARE = 70
9
10
 
10
11
  class << self
11
- def run!(arguments, output: $stderr)
12
+ def run!(arguments, stdin: $stdin, stdout: $stdout, stderr: $stderr)
13
+ cli = new(arguments, stdin: stdin, stdout: stdout, stderr: stderr)
12
14
  begin
13
- cli = new(arguments)
14
15
  cli.parse_arguments!
16
+ cli.run
15
17
  rescue ArgumentError
16
- output.puts USAGE
18
+ stderr.puts USAGE
17
19
  exit EX_USAGE
20
+ rescue RuntimeError => e
21
+ stderr.puts "#{e.class.name.split('::').last}: #{e.message}"
22
+ exit EX_SOFTWARE
18
23
  end
19
- cli.run
20
24
  end
21
25
  end
22
26
 
23
- attr_reader :arguments, :stdout, :env, :recipe
27
+ attr_reader :arguments, :stdin, :stdout, :stderr, :env
24
28
 
25
- def initialize(args, stdout: $stdout)
29
+ def initialize(args, stdin: $stdin, stdout: $stdout, stderr: $stderr)
26
30
  @arguments = args
31
+ @stdin = stdin
27
32
  @stdout = stdout
28
- @env = Env.new(output: stdout)
33
+ @env = Env.new(input: stdin, output: stdout)
29
34
  end
30
35
 
31
36
  def parse_arguments!
32
37
  @arguments = arguments.inject([]) do |m, e|
33
38
  case e
34
39
  when '-v'
35
- env.log_level = Logger::INFO
40
+ env.verbose = true
36
41
  when '-n'
37
42
  env.dry_run = true
38
43
  else
@@ -44,16 +49,15 @@ module Producer
44
49
  raise ArgumentError unless arguments.any?
45
50
  end
46
51
 
47
- def run(worker: build_worker)
48
- load_recipe
49
- worker.process recipe.tasks
52
+ def run
53
+ worker.process load_recipe.tasks
50
54
  end
51
55
 
52
56
  def load_recipe
53
- @recipe = Recipe.evaluate_from_file(@arguments.first, env)
57
+ Recipe.evaluate_from_file(@arguments.first, env)
54
58
  end
55
59
 
56
- def build_worker
60
+ def worker
57
61
  Worker.new(env)
58
62
  end
59
63
  end
@@ -3,12 +3,21 @@ module Producer
3
3
  class Condition
4
4
  class DSL
5
5
  class << self
6
- def define_test(keyword, klass)
7
- define_method(keyword) do |*args|
8
- @tests << klass.new(@env, *args)
9
- end
10
- define_method("no_#{keyword}") do |*args|
11
- @tests << klass.new(@env, *args, negated: true)
6
+ def define_test(keyword, test)
7
+ {
8
+ keyword => false,
9
+ "no_#{keyword}" => true
10
+ }.each do |kw, negated|
11
+ define_method(kw) do |*args|
12
+ if test.respond_to? :call
13
+ args = [test, *args]
14
+ klass = Tests::ConditionTest
15
+ else
16
+ klass = test
17
+ end
18
+ t = klass.new(@env, *args, negated: negated)
19
+ @tests << t
20
+ end
12
21
  end
13
22
  end
14
23
  end
@@ -29,8 +38,8 @@ module Producer
29
38
  @tests = []
30
39
  end
31
40
 
32
- def evaluate
33
- instance_eval &@block
41
+ def evaluate(*args)
42
+ instance_exec *args, &@block
34
43
  end
35
44
  end
36
45
  end
@@ -2,9 +2,9 @@ module Producer
2
2
  module Core
3
3
  class Condition
4
4
  class << self
5
- def evaluate(env, &block)
5
+ def evaluate(env, *args, &block)
6
6
  dsl = DSL.new(env, &block)
7
- return_value = dsl.evaluate
7
+ return_value = dsl.evaluate *args
8
8
  Condition.new(dsl.tests, return_value)
9
9
  end
10
10
  end
@@ -2,14 +2,14 @@ module Producer
2
2
  module Core
3
3
  class Env
4
4
  attr_reader :input, :output, :registry, :logger
5
- attr_accessor :target, :dry_run
5
+ attr_accessor :target, :verbose, :dry_run
6
6
 
7
7
  def initialize(input: $stdin, output: $stdout, remote: nil, registry: {})
8
+ @verbose = @dry_run = false
8
9
  @input = input
9
10
  @output = output
10
- @registry = registry
11
11
  @remote = remote
12
- @dry_run = false
12
+ @registry = registry
13
13
  end
14
14
 
15
15
  def remote
@@ -27,7 +27,7 @@ module Producer
27
27
  def logger
28
28
  @logger ||= begin
29
29
  logger = Logger.new(output)
30
- logger.level = Logger::ERROR
30
+ logger.level = verbose? ? Logger::INFO : Logger::ERROR
31
31
  logger.formatter = LoggerFormatter.new
32
32
  logger
33
33
  end
@@ -37,12 +37,8 @@ module Producer
37
37
  logger.info message
38
38
  end
39
39
 
40
- def log_level
41
- logger.level
42
- end
43
-
44
- def log_level=(level)
45
- logger.level = level
40
+ def verbose?
41
+ @verbose
46
42
  end
47
43
 
48
44
  def dry_run?
@@ -1,7 +1,8 @@
1
1
  module Producer
2
2
  module Core
3
3
  Error = Class.new(StandardError)
4
+ RuntimeError = Class.new(RuntimeError)
4
5
  ConditionNotMetError = Class.new(Error)
5
- RemoteCommandExecutionError = Class.new(Error)
6
+ RemoteCommandExecutionError = Class.new(RuntimeError)
6
7
  end
7
8
  end
@@ -38,6 +38,10 @@ module Producer
38
38
  end
39
39
  end
40
40
 
41
+ def test_macro(name, dsl: Condition::DSL, &block)
42
+ dsl.define_test(name, block)
43
+ end
44
+
41
45
  def set(key, value)
42
46
  env[key] = value
43
47
  end
@@ -32,7 +32,7 @@ module Producer
32
32
 
33
33
  ch.on_request 'exit-status' do |c, data|
34
34
  exit_status = data.read_long
35
- raise RemoteCommandExecutionError if exit_status != 0
35
+ raise RemoteCommandExecutionError, command if exit_status != 0
36
36
  end
37
37
  end
38
38
  end
@@ -0,0 +1,23 @@
1
+ module Producer
2
+ module Core
3
+ module Tests
4
+ class ConditionTest < Test
5
+ def verify
6
+ condition.met?
7
+ end
8
+
9
+ def condition
10
+ Condition.evaluate(env, *condition_args, &condition_block)
11
+ end
12
+
13
+ def condition_args
14
+ arguments.drop 1
15
+ end
16
+
17
+ def condition_block
18
+ arguments.first
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end