From 166dae681c56d07435baa841696acee44cd7e284 Mon Sep 17 00:00:00 2001 From: Thibault Jouan Date: Mon, 22 Sep 2014 13:13:03 +0000 Subject: [PATCH] Merge Recipe::DSL into Recipe --- lib/producer/core.rb | 2 +- lib/producer/core/cli.rb | 2 +- lib/producer/core/recipe.rb | 42 +++++- lib/producer/core/recipe/dsl.rb | 61 -------- lib/producer/core/recipe/file_evaluator.rb | 14 ++ spec/producer/core/recipe/dsl_spec.rb | 140 ------------------ .../core/recipe/file_evaluator_spec.rb | 22 +++ spec/producer/core/recipe_spec.rb | 93 +++++++++--- 8 files changed, 150 insertions(+), 226 deletions(-) delete mode 100644 lib/producer/core/recipe/dsl.rb create mode 100644 lib/producer/core/recipe/file_evaluator.rb delete mode 100644 spec/producer/core/recipe/dsl_spec.rb create mode 100644 spec/producer/core/recipe/file_evaluator_spec.rb diff --git a/lib/producer/core.rb b/lib/producer/core.rb index ca67a75..0d29d39 100644 --- a/lib/producer/core.rb +++ b/lib/producer/core.rb @@ -33,7 +33,7 @@ require 'producer/core/errors' require 'producer/core/logger_formatter' require 'producer/core/prompter' require 'producer/core/recipe' -require 'producer/core/recipe/dsl' +require 'producer/core/recipe/file_evaluator' require 'producer/core/remote' require 'producer/core/remote/environment' require 'producer/core/remote/fs' diff --git a/lib/producer/core/cli.rb b/lib/producer/core/cli.rb index a0de5fa..3e483cf 100644 --- a/lib/producer/core/cli.rb +++ b/lib/producer/core/cli.rb @@ -58,7 +58,7 @@ module Producer end def recipe - @recipe ||= Recipe.evaluate_from_file(@arguments.first, env) + @recipe ||= Recipe::FileEvaluator.evaluate(@arguments.first, env) end end end diff --git a/lib/producer/core/recipe.rb b/lib/producer/core/recipe.rb index 2618a14..b39da34 100644 --- a/lib/producer/core/recipe.rb +++ b/lib/producer/core/recipe.rb @@ -2,16 +2,46 @@ module Producer module Core class Recipe class << self - def evaluate_from_file(filepath, env) - dsl = DSL.new(env, File.read(filepath)).evaluate - Recipe.new(dsl.tasks) + def define_macro(name, block) + define_method(name) { |*args| task name, *args, &block } end end - attr_accessor :tasks + attr_reader :env, :tasks - def initialize(tasks = []) - @tasks = tasks + def initialize(env) + @env = env + @tasks = [] + end + + def source(filepath) + instance_eval File.read("./#{filepath}.rb"), "#{filepath}.rb" + end + + def target(hostname) + env.target ||= hostname + end + + def task(name, *args, &block) + @tasks << Task.evaluate(name, env, *args, &block) + end + + def macro(name, &block) + define_singleton_method(name) do |*args| + task("#{name}", *args, &block) + end + end + + def test_macro(name, dsl: Condition::DSL, &block) + dsl.define_test(name, block) + end + + def set(key, value) + env[key] = value + end + + def get(key) + env[key] end end end diff --git a/lib/producer/core/recipe/dsl.rb b/lib/producer/core/recipe/dsl.rb deleted file mode 100644 index e15cca9..0000000 --- a/lib/producer/core/recipe/dsl.rb +++ /dev/null @@ -1,61 +0,0 @@ -module Producer - module Core - class Recipe - class DSL - class << self - def define_macro(name, block) - define_method(name) { |*args| task name, *args, &block } - end - end - - attr_reader :env, :code, :block, :tasks - - def initialize(env, code = nil, &block) - @env = env - @code = code - @block = block - @tasks = [] - end - - def evaluate - if @code - instance_eval @code - else - instance_eval &@block - end - self - end - - def source(filepath) - instance_eval File.read("./#{filepath}.rb"), "#{filepath}.rb" - end - - def target(hostname) - env.target ||= hostname - end - - def task(name, *args, &block) - @tasks << Task.evaluate(name, env, *args, &block) - end - - def macro(name, &block) - define_singleton_method(name) do |*args| - task("#{name}", *args, &block) - end - end - - def test_macro(name, dsl: Condition::DSL, &block) - dsl.define_test(name, block) - end - - def set(key, value) - env[key] = value - end - - def get(key) - env[key] - end - end - end - end -end diff --git a/lib/producer/core/recipe/file_evaluator.rb b/lib/producer/core/recipe/file_evaluator.rb new file mode 100644 index 0000000..fb280c0 --- /dev/null +++ b/lib/producer/core/recipe/file_evaluator.rb @@ -0,0 +1,14 @@ +module Producer + module Core + class Recipe + class FileEvaluator + class << self + def evaluate(file_path, env) + content = File.read(file_path) + Recipe.new(env).tap { |o| o.instance_eval content, file_path } + end + end + end + end + end +end diff --git a/spec/producer/core/recipe/dsl_spec.rb b/spec/producer/core/recipe/dsl_spec.rb deleted file mode 100644 index 04445b5..0000000 --- a/spec/producer/core/recipe/dsl_spec.rb +++ /dev/null @@ -1,140 +0,0 @@ -require 'spec_helper' - -module Producer::Core - class Recipe - describe DSL do - include FixturesHelpers - - let(:code) { proc { :some_recipe_code } } - let(:env) { Env.new } - subject(:dsl) { DSL.new(env, &code) } - - describe '#initialize' do - it 'assigns the given env' do - expect(dsl.env).to be env - end - - it 'assigns no task' do - expect(dsl.tasks).to be_empty - end - - context 'when a string of code is given as argument' do - let(:code) { 'some_code' } - subject(:dsl) { described_class.new(env, code) } - - it 'assigns the string of code' do - expect(dsl.code).to eq code - end - end - - context 'when a code block is given as argument' do - it 'assigns the code block' do - expect(dsl.block).to be code - end - end - end - - describe '#tasks' do - let(:code) { proc { task(:some_task) {} } } - - it 'returns registered tasks' do - dsl.evaluate - expect(dsl.tasks[0].name).to eq :some_task - end - end - - describe '#evaluate' do - it 'evaluates its code' do - dsl = described_class.new(env) { throw :recipe_code } - expect { dsl.evaluate }.to throw_symbol :recipe_code - end - - it 'returns itself' do - expect(dsl.evaluate).to eq dsl - end - end - - describe '#source' do - let(:filepath) { fixture_path_for 'recipes/throw' } - - it 'sources the recipe given as argument' do - expect { dsl.source filepath }.to throw_symbol :recipe_code - end - end - - describe '#target' do - let(:host) { 'some_host.example' } - - context 'when env has no assigned target' do - it 'registers the target host in the env' do - dsl.target host - expect(env.target).to eq host - end - end - - context 'when env has an assigned target' do - before { env.target = 'already_assigned_host.example' } - - it 'does not change env target' do - expect { dsl.target host }.not_to change { env.target } - end - end - end - - describe '#task' do - it 'registers a new evaluated task' do - expect { dsl.task(:some_task) { :some_task_code } } - .to change { dsl.tasks.count }.by 1 - end - end - - describe '#macro' do - it 'defines the new recipe keyword' do - dsl.macro :hello - expect(dsl).to respond_to(:hello) - end - - context 'when a defined macro is called' do - before { dsl.macro(:hello) { :some_macro_code } } - - it 'registers the new task' do - expect { dsl.hello }.to change { dsl.tasks.count }.by 1 - end - end - - context 'when a defined macro is called with arguments' do - before { dsl.macro(:hello) { |a, b| echo a, b } } - - it 'evaluates task code with arguments' do - dsl.hello :some, :args - expect(dsl.tasks.first.actions.first.arguments).to eq [:some, :args] - end - end - end - - describe '#test_macro' do - it 'defines the new test' do - condition_dsl = double 'condition dsl' - test_block = proc {} - expect(condition_dsl) - .to receive(:define_test).with(:some_test, test_block) - dsl.test_macro(:some_test, dsl: condition_dsl, &test_block) - end - end - - describe '#set' do - it 'registers a key/value pair in env registry' do - dsl.set :some_key, :some_value - expect(env[:some_key]).to eq :some_value - end - end - - describe '#get' do - it 'fetches a value from the registry at given index' do - dsl.set :some_key, :some_value - expect(dsl.get :some_key).to eq :some_value - end - end - end - end -end diff --git a/spec/producer/core/recipe/file_evaluator_spec.rb b/spec/producer/core/recipe/file_evaluator_spec.rb new file mode 100644 index 0000000..a31b193 --- /dev/null +++ b/spec/producer/core/recipe/file_evaluator_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +module Producer::Core + class Recipe + describe FileEvaluator do + include FixturesHelpers + + describe '.evaluate' do + let(:env) { Env.new } + let(:file_path) { fixture_path_for 'recipes/some_recipe.rb' } + subject(:recipe) { described_class.evaluate(file_path, env) } + + it 'returns an evaluated recipe' do + expect(recipe.tasks).to match [ + an_object_having_attributes(name: :some_task), + an_object_having_attributes(name: :another_task) + ] + end + end + end + end +end diff --git a/spec/producer/core/recipe_spec.rb b/spec/producer/core/recipe_spec.rb index 9763359..2f086a9 100644 --- a/spec/producer/core/recipe_spec.rb +++ b/spec/producer/core/recipe_spec.rb @@ -4,33 +4,92 @@ module Producer::Core describe Recipe do include FixturesHelpers - subject(:recipe) { Recipe.new } + let(:env) { Env.new } + subject(:recipe) { described_class.new(env) } - describe '.evaluate_from_file' do - let(:env) { double 'env' } - let(:filepath) { fixture_path_for 'recipes/some_recipe.rb' } - subject(:recipe) { Recipe.evaluate_from_file(filepath, env) } - - it 'returns an evaluated recipe' do - expect(recipe.tasks.map(&:name)).to eq [:some_task, :another_task] + describe '#initialize' do + it 'assigns no task' do + expect(recipe.tasks).to be_empty end end - describe '#initialize' do - context 'without arguments' do - it 'assigns no task' do - expect(recipe.tasks).to be_empty + describe '#source' do + let(:filepath) { fixture_path_for 'recipes/throw' } + + it 'sources the recipe given as argument' do + expect { recipe.source filepath }.to throw_symbol :recipe_code + end + end + + describe '#target' do + let(:host) { 'some_host.example' } + + context 'when env has no assigned target' do + it 'registers the target host in the env' do + recipe.target host + expect(env.target).to eq host end end - context 'when tasks are given as argument' do - let(:tasks) { [double('task')] } - subject(:recipe) { Recipe.new(tasks) } + context 'when env has an assigned target' do + before { env.target = 'already_assigned_host.example' } - it 'assigns the tasks' do - expect(recipe.tasks).to eq tasks + it 'does not change env target' do + expect { recipe.target host }.not_to change { env.target } end end end + + describe '#task' do + it 'registers a new evaluated task' do + expect { recipe.task(:some_task) { :some_task_code } } + .to change { recipe.tasks.count }.by 1 + end + end + + describe '#macro' do + it 'defines the new recipe keyword' do + recipe.macro :hello + expect(recipe).to respond_to(:hello) + end + + context 'when a defined macro is called' do + before { recipe.macro(:hello) { :some_macro_code } } + + it 'registers the new task' do + expect { recipe.hello }.to change { recipe.tasks.count }.by 1 + end + end + + context 'when a defined macro is called with arguments' do + before { recipe.macro(:hello) { |a, b| echo a, b } } + + it 'evaluates task code with given arguments' do + recipe.hello :foo, :bar + expect(recipe.tasks.first.actions.first.arguments).to eq %i[foo bar] + end + end + end + + describe '#test_macro' do + it 'defines the new test' do + recipe.test_macro(:some_test) { } + expect(Condition::DSL.new(env)).to respond_to :some_test + end + end + + describe '#set' do + it 'registers a key/value pair in env registry' do + recipe.set :some_key, :some_value + expect(env[:some_key]).to eq :some_value + end + end + + describe '#get' do + it 'fetches a value from the registry at given index' do + recipe.set :some_key, :some_value + expect(recipe.get :some_key).to eq :some_value + end + end end end