diff --git a/features/cli/usage.feature b/features/cli/usage.feature index 4f677eb..9da7ac5 100644 --- a/features/cli/usage.feature +++ b/features/cli/usage.feature @@ -5,5 +5,5 @@ Feature: CLI usage Then the exit status must be 64 And the output must contain exactly: """ - Usage: producer recipe_file + Usage: producer [-v] recipe_file """ diff --git a/features/cli/verbose.feature b/features/cli/verbose.feature new file mode 100644 index 0000000..a16ae88 --- /dev/null +++ b/features/cli/verbose.feature @@ -0,0 +1,33 @@ +Feature: CLI verbose option + + Scenario: prints tasks name + Given a recipe with: + """ + task :say_hello do + end + """ + When I successfully execute the recipe with option -v + Then the output must match /Task:.+say_hello/ + + Scenario: prints whether condition is met + Given a recipe with: + """ + task :task_ok do + condition { true } + end + task :task_ko do + condition { false } + end + """ + When I successfully execute the recipe with option -v + Then the output must match /task_ok.+ condition: met.*task_ko.* condition: NOT met/ + + Scenario: prints actions info + Given a recipe with: + """ + task :say_hello do + echo 'hello message' + end + """ + When I successfully execute the recipe with option -v + Then the output must match /say_hello.+ action: echo/ diff --git a/features/steps/recipe_steps.rb b/features/steps/recipe_steps.rb index 6303ab1..3c0fb21 100644 --- a/features/steps/recipe_steps.rb +++ b/features/steps/recipe_steps.rb @@ -11,6 +11,11 @@ When /^I successfully execute the recipe$/ do assert_exit_status 0 end +When /^I successfully execute the recipe with option (-\w)$/ do |option| + run_simple "producer #{option} recipe.rb", false + assert_exit_status 0 +end + When /^I execute the recipe interactively$/ do run_interactive 'producer recipe.rb' end diff --git a/lib/producer/core/action.rb b/lib/producer/core/action.rb index bd5916a..7fbb6ad 100644 --- a/lib/producer/core/action.rb +++ b/lib/producer/core/action.rb @@ -11,6 +11,14 @@ module Producer @env = env @arguments = args end + + def name + self.class.name.split('::').last.downcase + end + + def to_s + name + end end end end diff --git a/lib/producer/core/actions/echo.rb b/lib/producer/core/actions/echo.rb index 4547179..92ff802 100644 --- a/lib/producer/core/actions/echo.rb +++ b/lib/producer/core/actions/echo.rb @@ -2,6 +2,10 @@ module Producer module Core module Actions class Echo < Action + def name + 'echo' + end + def apply output.puts arguments.first end diff --git a/lib/producer/core/actions/file_append.rb b/lib/producer/core/actions/file_append.rb index c78362f..830196e 100644 --- a/lib/producer/core/actions/file_append.rb +++ b/lib/producer/core/actions/file_append.rb @@ -2,6 +2,10 @@ module Producer module Core module Actions class FileAppend < Action + def name + 'file_append' + end + def apply fs.file_write path, combined_content end diff --git a/lib/producer/core/actions/file_replace_content.rb b/lib/producer/core/actions/file_replace_content.rb index 00fcdf0..7342f3a 100644 --- a/lib/producer/core/actions/file_replace_content.rb +++ b/lib/producer/core/actions/file_replace_content.rb @@ -2,6 +2,10 @@ module Producer module Core module Actions class FileReplaceContent < Action + def name + 'file_replace_content' + end + def apply fs.file_write path, replaced_content end diff --git a/lib/producer/core/actions/file_writer.rb b/lib/producer/core/actions/file_writer.rb index 2fea259..966b969 100644 --- a/lib/producer/core/actions/file_writer.rb +++ b/lib/producer/core/actions/file_writer.rb @@ -2,6 +2,10 @@ module Producer module Core module Actions class FileWriter < Action + def name + 'file_write' + end + def apply case arguments.size when 2 diff --git a/lib/producer/core/actions/mkdir.rb b/lib/producer/core/actions/mkdir.rb index fad206e..ccb7baa 100644 --- a/lib/producer/core/actions/mkdir.rb +++ b/lib/producer/core/actions/mkdir.rb @@ -2,6 +2,10 @@ module Producer module Core module Actions class Mkdir < Action + def name + 'mkdir' + end + def apply case arguments.size when 1 diff --git a/lib/producer/core/actions/shell_command.rb b/lib/producer/core/actions/shell_command.rb index 718ca86..3ff2599 100644 --- a/lib/producer/core/actions/shell_command.rb +++ b/lib/producer/core/actions/shell_command.rb @@ -2,6 +2,10 @@ module Producer module Core module Actions class ShellCommand < Action + def name + 'sh' + end + def apply remote.execute(arguments.first, output) end diff --git a/lib/producer/core/cli.rb b/lib/producer/core/cli.rb index c54eeaa..4fddaa6 100644 --- a/lib/producer/core/cli.rb +++ b/lib/producer/core/cli.rb @@ -3,7 +3,7 @@ module Producer class CLI ArgumentError = Class.new(::ArgumentError) - USAGE = "Usage: #{File.basename $0} recipe_file" + USAGE = "Usage: #{File.basename $0} [-v] recipe_file" EX_USAGE = 64 @@ -11,6 +11,7 @@ module Producer def run!(arguments, output: $stderr) begin cli = new(arguments) + cli.parse_arguments! rescue ArgumentError output.puts USAGE exit EX_USAGE @@ -25,6 +26,19 @@ module Producer @arguments = args @stdout = stdout @env = Env.new(output: stdout) + end + + def parse_arguments! + @arguments = arguments.inject([]) do |m, e| + case e + when '-v' + env.log_level = Logger::INFO + else + m << e + end + m + end + raise ArgumentError unless arguments.any? end diff --git a/lib/producer/core/worker.rb b/lib/producer/core/worker.rb index dfe1c9b..eab81b4 100644 --- a/lib/producer/core/worker.rb +++ b/lib/producer/core/worker.rb @@ -12,7 +12,16 @@ module Producer end def process_task(task) - task.actions.each(&:apply) if task.condition_met? + env.log "Task: #{task} applying" + if task.condition_met? + env.log ' condition: met' + task.actions.each do |e| + env.log " action: #{e} applying" + e.apply + end + else + env.log ' condition: NOT met' + end end end end diff --git a/spec/producer/core/action_spec.rb b/spec/producer/core/action_spec.rb index 884c4ad..47d637c 100644 --- a/spec/producer/core/action_spec.rb +++ b/spec/producer/core/action_spec.rb @@ -3,5 +3,13 @@ require 'spec_helper' module Producer::Core describe Action do it_behaves_like 'action' + + describe '#name' do + subject(:action) { described_class.new(double 'env') } + + it 'infers action name from class name' do + expect(action.name).to eq 'action' + end + end end end diff --git a/spec/producer/core/cli_spec.rb b/spec/producer/core/cli_spec.rb index 6cac850..11524ae 100644 --- a/spec/producer/core/cli_spec.rb +++ b/spec/producer/core/cli_spec.rb @@ -12,23 +12,34 @@ module Producer::Core subject(:cli) { CLI.new(arguments, stdout: stdout) } describe '.run!' do + let(:cli) { double('cli').as_null_object } let(:output) { StringIO.new } subject(:run) { described_class.run! arguments, output: output } it 'builds a new CLI with given arguments' do - expect(CLI).to receive(:new).with(arguments).and_call_original + expect(described_class) + .to receive(:new).with(arguments).and_call_original run end it 'runs the CLI' do - cli = double 'cli' - allow(CLI).to receive(:new) { cli } + allow(described_class).to receive(:new) { cli } expect(cli).to receive :run run end - context 'when recipe argument is missing' do - let(:arguments) { [] } + it 'parses CLI arguments' do + allow(described_class).to receive(:new) { cli } + expect(cli).to receive :parse_arguments! + run + end + + context 'when an argument error is raised' do + before do + allow(CLI).to receive(:new) { cli } + allow(cli).to receive(:parse_arguments!) + .and_raise described_class::ArgumentError + end it 'exits with a return status of 64' do expect { run }.to raise_error(SystemExit) { |e| @@ -55,14 +66,6 @@ module Producer::Core expect(cli.stdout).to be $stdout end end - - context 'without arguments' do - let(:arguments) { [] } - - it 'raises our ArgumentError exception' do - expect { cli }.to raise_error described_class::ArgumentError - end - end end describe '#arguments' do @@ -77,6 +80,32 @@ module Producer::Core end end + describe '#parse_arguments!' do + context 'with options' do + let(:arguments) { ['-v', recipe_file] } + + before { cli.parse_arguments! } + + it 'removes options from arguments' do + expect(cli.arguments).to eq [recipe_file] + end + + context 'verbose' do + it 'sets env logger level to INFO' do + expect(cli.env.log_level).to eq Logger::INFO + end + end + end + + context 'without arguments' do + let(:arguments) { [] } + + it 'raises the argument error exception' do + expect { cli.parse_arguments! }.to raise_error described_class::ArgumentError + end + end + end + describe '#run' do it 'loads the recipe' do cli.run diff --git a/spec/producer/core/worker_spec.rb b/spec/producer/core/worker_spec.rb index 66d09a4..afb2021 100644 --- a/spec/producer/core/worker_spec.rb +++ b/spec/producer/core/worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' module Producer::Core describe Worker do - let(:env) { Env.new } + let(:env) { double 'env', log: nil } subject(:worker) { described_class.new(env) } describe '#process' do @@ -13,23 +13,44 @@ module Producer::Core end describe '#process_task' do - let(:action) { double 'action' } - let(:task) { double('task', actions: [action]).as_null_object } + let(:action) { double('action', to_s: 'echo').as_null_object } + let(:task_name) { 'some_task' } + let(:task) { Task.new(task_name, [action]) } + + it 'logs task info' do + expect(env).to receive(:log).with /\ATask: #{task_name}/ + worker.process_task task + end context 'when task condition is met' do it 'applies the actions' do expect(action).to receive :apply worker.process_task task end + + it 'logs condition info' do + expect(env).to receive(:log).with(' condition: met') + worker.process_task task + end + + it 'logs action info' do + expect(env).to receive(:log).with /\A action: echo/ + worker.process_task task + end end context 'when task condition is not met' do - before { allow(task).to receive(:condition_met?) { false } } + let(:task) { Task.new(task_name, [action], false) } it 'does not apply the actions' do expect(action).not_to receive :apply worker.process_task task end + + it 'logs condition info' do + expect(env).to receive(:log).with(' condition: NOT met') + worker.process_task task + end end end diff --git a/spec/support/shared_action.rb b/spec/support/shared_action.rb index c8c6224..d6d8539 100644 --- a/spec/support/shared_action.rb +++ b/spec/support/shared_action.rb @@ -40,5 +40,17 @@ module Producer::Core expect(action.fs).to be env.remote.fs end end + + describe '#name' do + it 'returns a word' do + expect(action.name).to match /\A\w+\z/ + end + end + + describe '#to_s' do + it 'returns a word' do + expect(action.to_s).to eq action.name + end + end end end