diff --git a/Guardfile b/Guardfile index 74c8988..7e506c4 100644 --- a/Guardfile +++ b/Guardfile @@ -7,9 +7,16 @@ guard_opts = { all_after_pass: true, } -def all_specs; 'spec' end -def library_specs; 'spec/libraries' end -def provider_specs; 'spec/providers' end +DEBUG = false + +def reload(target) + puts "-> #{target}" if DEBUG + target +end + +def all_specs; reload 'all_specs'; 'spec' end +def library_specs; reload 'library_specs'; 'spec/libraries' end +def provider_specs; reload 'provider_specs'; 'spec/providers' end group :rspec do guard 'rspec', guard_opts do @@ -20,14 +27,14 @@ group :rspec do watch(%r{^spec/fixtures/(.+)\.rb$}) { all_specs } watch(%r{^libraries/pacemaker\.rb$}) { all_specs } watch(%r{^libraries/(.*mixin.*)\.rb$}) { library_specs } - watch(%r{^spec/.+_spec\.rb$}) + watch(%r{^(spec/.+_spec\.rb)$}) { |m| reload m[1] } watch(%r{^libraries/(.+)\.rb$}) { |m| - "spec/libraries/#{m[1]}_spec.rb" + reload "spec/libraries/#{m[1]}_spec.rb" } watch(%r{^providers/common\.rb$}) { provider_specs } watch(%r{^providers/(.*mixin.*)\.rb$}) { provider_specs } watch(%r{^(?:resources|providers)/(.+)\.rb$}) { |m| - "spec/providers/#{m[1]}_spec.rb" + reload "spec/providers/#{m[1]}_spec.rb" } end end diff --git a/libraries/chef/mixin/pacemaker.rb b/libraries/chef/mixin/pacemaker.rb index 3751d07..7c936b0 100644 --- a/libraries/chef/mixin/pacemaker.rb +++ b/libraries/chef/mixin/pacemaker.rb @@ -1,2 +1,3 @@ -require File.expand_path('pacemaker/standard_cib_object.rb', File.dirname(__FILE__)) -require File.expand_path('pacemaker/runnable_resource.rb', File.dirname(__FILE__)) +this_dir = File.dirname(__FILE__) +require File.expand_path('pacemaker/standard_cib_object.rb', this_dir) +require File.expand_path('pacemaker/runnable_resource.rb', this_dir) diff --git a/libraries/chef/mixin/pacemaker/runnable_resource.rb b/libraries/chef/mixin/pacemaker/runnable_resource.rb index 43a77b6..ad09e4f 100644 --- a/libraries/chef/mixin/pacemaker/runnable_resource.rb +++ b/libraries/chef/mixin/pacemaker/runnable_resource.rb @@ -1,5 +1,4 @@ -require 'chef/application' -require ::File.expand_path('standard_cib_object', ::File.dirname(__FILE__)) +require ::File.expand_path('standard_cib_object', File.dirname(__FILE__)) # Common code used by Pacemaker LWRP providers for resources supporting # the :run action. diff --git a/libraries/chef/mixin/pacemaker/standard_cib_object.rb b/libraries/chef/mixin/pacemaker/standard_cib_object.rb index 26bc409..e34e1b6 100644 --- a/libraries/chef/mixin/pacemaker/standard_cib_object.rb +++ b/libraries/chef/mixin/pacemaker/standard_cib_object.rb @@ -1,6 +1,5 @@ -require 'chef/application' require ::File.expand_path('../../../pacemaker/cib_object', - ::File.dirname(__FILE__)) + File.dirname(__FILE__)) # Common code used by Pacemaker LWRP providers diff --git a/libraries/pacemaker/constraint/order.rb b/libraries/pacemaker/constraint/order.rb new file mode 100644 index 0000000..6eedd91 --- /dev/null +++ b/libraries/pacemaker/constraint/order.rb @@ -0,0 +1,31 @@ +require File.expand_path('../constraint', File.dirname(__FILE__)) + +class Pacemaker::Constraint::Order < Pacemaker::Constraint + TYPE = 'order' + register_type TYPE + + attr_accessor :score, :ordering + + def self.attrs_to_copy_from_chef + %w(score ordering) + end + + def parse_definition + # FIXME: add support for symmetrical= + # Currently we take the easy way out and don't bother parsing the ordering. + # See the crm(8) man page for the official BNF grammar. + score_regexp = %r{\d+|[-+]?inf|Mandatory|Optional|Serialize} + unless definition =~ /^#{self.class::TYPE} (\S+) (#{score_regexp}): (.+?)\s*$/ + raise Pacemaker::CIBObject::DefinitionParseError, \ + "Couldn't parse definition '#{definition}'" + end + self.name = $1 + self.score = $2 + self.ordering = $3 + end + + def definition_string + "#{self.class::TYPE} #{name} #{score}: #{ordering}" + end + +end diff --git a/libraries/pacemaker/resource/clone.rb b/libraries/pacemaker/resource/clone.rb index 54fc945..2252b75 100644 --- a/libraries/pacemaker/resource/clone.rb +++ b/libraries/pacemaker/resource/clone.rb @@ -1,5 +1,6 @@ -require File.expand_path('../resource', File.dirname(__FILE__)) -require File.expand_path('../mixins/resource_meta', File.dirname(__FILE__)) +this_dir = File.dirname(__FILE__) +require File.expand_path('../resource', this_dir) +require File.expand_path('../mixins/resource_meta', this_dir) class Pacemaker::Resource::Clone < Pacemaker::Resource TYPE = 'clone' diff --git a/libraries/pacemaker/resource/group.rb b/libraries/pacemaker/resource/group.rb index be72e19..bfeff8f 100644 --- a/libraries/pacemaker/resource/group.rb +++ b/libraries/pacemaker/resource/group.rb @@ -1,5 +1,6 @@ -require File.expand_path('../resource', File.dirname(__FILE__)) -require File.expand_path('../mixins/resource_meta', File.dirname(__FILE__)) +this_dir = File.dirname(__FILE__) +require File.expand_path('../resource', this_dir) +require File.expand_path('../mixins/resource_meta', this_dir) class Pacemaker::Resource::Group < Pacemaker::Resource TYPE = 'group' diff --git a/libraries/pacemaker/resource/primitive.rb b/libraries/pacemaker/resource/primitive.rb index 08d0568..59cd73a 100644 --- a/libraries/pacemaker/resource/primitive.rb +++ b/libraries/pacemaker/resource/primitive.rb @@ -1,6 +1,8 @@ require 'shellwords' -require File.expand_path('../resource', File.dirname(__FILE__)) -require File.expand_path('../mixins/resource_meta', File.dirname(__FILE__)) + +this_dir = File.dirname(__FILE__) +require File.expand_path('../resource', this_dir) +require File.expand_path('../mixins/resource_meta', this_dir) class Pacemaker::Resource::Primitive < Pacemaker::Resource TYPE = 'primitive' diff --git a/providers/clone.rb b/providers/clone.rb index 9217ca0..ebfd365 100644 --- a/providers/clone.rb +++ b/providers/clone.rb @@ -17,9 +17,9 @@ # limitations under the License. # -require ::File.expand_path('../libraries/pacemaker', ::File.dirname(__FILE__)) -require ::File.expand_path('../libraries/chef/mixin/pacemaker', - ::File.dirname(__FILE__)) +this_dir = ::File.dirname(__FILE__) +require ::File.expand_path('../libraries/pacemaker', this_dir) +require ::File.expand_path('../libraries/chef/mixin/pacemaker', this_dir) include Chef::Mixin::Pacemaker::RunnableResource diff --git a/providers/colocation.rb b/providers/colocation.rb index ffb5383..3a35355 100644 --- a/providers/colocation.rb +++ b/providers/colocation.rb @@ -17,9 +17,9 @@ # limitations under the License. # -require ::File.expand_path('../libraries/pacemaker', ::File.dirname(__FILE__)) -require ::File.expand_path('../libraries/chef/mixin/pacemaker', - ::File.dirname(__FILE__)) +this_dir = ::File.dirname(__FILE__) +require ::File.expand_path('../libraries/pacemaker', this_dir) +require ::File.expand_path('../libraries/chef/mixin/pacemaker', this_dir) include Chef::Mixin::Pacemaker::StandardCIBObject diff --git a/providers/group.rb b/providers/group.rb index 6b3cb2c..af7bc98 100644 --- a/providers/group.rb +++ b/providers/group.rb @@ -16,9 +16,9 @@ # limitations under the License. # -require ::File.expand_path('../libraries/pacemaker', ::File.dirname(__FILE__)) -require ::File.expand_path('../libraries/chef/mixin/pacemaker', - ::File.dirname(__FILE__)) +this_dir = ::File.dirname(__FILE__) +require ::File.expand_path('../libraries/pacemaker', this_dir) +require ::File.expand_path('../libraries/chef/mixin/pacemaker', this_dir) include Chef::Mixin::Pacemaker::RunnableResource diff --git a/providers/location.rb b/providers/location.rb index fcf7e1e..5df7597 100644 --- a/providers/location.rb +++ b/providers/location.rb @@ -17,9 +17,9 @@ # limitations under the License. # -require ::File.expand_path('../libraries/pacemaker', ::File.dirname(__FILE__)) -require ::File.expand_path('../libraries/chef/mixin/pacemaker', - ::File.dirname(__FILE__)) +this_dir = ::File.dirname(__FILE__) +require ::File.expand_path('../libraries/pacemaker', this_dir) +require ::File.expand_path('../libraries/chef/mixin/pacemaker', this_dir) include Chef::Mixin::Pacemaker::StandardCIBObject diff --git a/providers/ms.rb b/providers/ms.rb index 1d772fd..430e47b 100644 --- a/providers/ms.rb +++ b/providers/ms.rb @@ -17,9 +17,9 @@ # limitations under the License. # -require ::File.expand_path('../libraries/pacemaker', ::File.dirname(__FILE__)) -require ::File.expand_path('../libraries/chef/mixin/pacemaker', - ::File.dirname(__FILE__)) +this_dir = ::File.dirname(__FILE__) +require ::File.expand_path('../libraries/pacemaker', this_dir) +require ::File.expand_path('../libraries/chef/mixin/pacemaker', this_dir) include Chef::Mixin::Pacemaker::RunnableResource diff --git a/providers/order.rb b/providers/order.rb index c4d07eb..377d150 100644 --- a/providers/order.rb +++ b/providers/order.rb @@ -1,8 +1,8 @@ -# Author:: Robert Choi # Cookbook Name:: pacemaker # Provider:: order # # Copyright:: 2013, Robert Choi +# Copyright:: 2014, SUSE # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,46 +17,57 @@ # limitations under the License. # -require ::File.expand_path('../libraries/pacemaker/cib_object', - ::File.dirname(__FILE__)) +this_dir = ::File.dirname(__FILE__) +require ::File.expand_path('../libraries/pacemaker/cib_object', this_dir) +require ::File.expand_path('../libraries/pacemaker', this_dir) +require ::File.expand_path('../libraries/chef/mixin/pacemaker', this_dir) + +include Chef::Mixin::Pacemaker::StandardCIBObject action :create do name = new_resource.name - priority = new_resource.priority - resources = new_resource.resources - unless resource_exists?(name) - cmd = "crm configure order #{name} #{priority}:" - resources.each do |rsc| - cmd << " #{rsc}" - end - - cmd_ = Mixlib::ShellOut.new(cmd) - cmd_.environment['HOME'] = ENV.fetch('HOME', '/root') - cmd_.run_command - begin - cmd_.error! - if resource_exists?(name) - new_resource.updated_by_last_action(true) - Chef::Log.info "Successfully configured order '#{name}'." - else - Chef::Log.error "Failed to configure order #{name}." - end - rescue - Chef::Log.error "Failed to configure order #{name}." - end + if @current_resource_definition.nil? + create_resource(name) + else + maybe_modify_resource(name) end end action :delete do - name = new_resource.name - cmd = "crm resource stop #{name}; crm configure delete #{name}" - - e = execute "delete order #{name}" do - command cmd - only_if { resource_exists?(name) } - end - - new_resource.updated_by_last_action(true) - Chef::Log.info "Deleted order '#{name}'." + next unless @current_resource + standard_delete_resource +end + +def cib_object_class + ::Pacemaker::Constraint::Order +end + +def load_current_resource + standard_load_current_resource +end + +def init_current_resource + name = @new_resource.name + @current_resource = Chef::Resource::PacemakerOrder.new(name) + attrs = [:score, :ordering] + @current_cib_object.copy_attrs_to_chef_resource(@current_resource, *attrs) +end + +def create_resource(name) + standard_create_resource +end + +def maybe_modify_resource(name) + Chef::Log.info "Checking existing #{@current_cib_object} for modifications" + + desired_order = cib_object_class.from_chef_resource(new_resource) + if desired_order.definition_string != @current_cib_object.definition_string + Chef::Log.debug "changed from [#{@current_cib_object.definition_string}] to [#{desired_order.definition_string}]" + cmd = desired_order.reconfigure_command + execute cmd do + action :nothing + end.run_action(:run) + new_resource.updated_by_last_action(true) + end end diff --git a/providers/primitive.rb b/providers/primitive.rb index a4a93e8..5206a35 100644 --- a/providers/primitive.rb +++ b/providers/primitive.rb @@ -17,9 +17,9 @@ # limitations under the License. # -require ::File.expand_path('../libraries/pacemaker', ::File.dirname(__FILE__)) -require ::File.expand_path('../libraries/chef/mixin/pacemaker', - ::File.dirname(__FILE__)) +this_dir = ::File.dirname(__FILE__) +require ::File.expand_path('../libraries/pacemaker', this_dir) +require ::File.expand_path('../libraries/chef/mixin/pacemaker', this_dir) include Chef::Mixin::Pacemaker::RunnableResource diff --git a/providers/property.rb b/providers/property.rb index cf27ee6..2ecd44e 100644 --- a/providers/property.rb +++ b/providers/property.rb @@ -17,8 +17,8 @@ # limitations under the License. # -require ::File.expand_path('../libraries/pacemaker/cib_object', - ::File.dirname(__FILE__)) +this_dir = ::File.dirname(__FILE__) +require ::File.expand_path('../libraries/pacemaker/cib_object', this_dir) action :create do name = new_resource.name diff --git a/resources/order.rb b/resources/order.rb index 41287fe..caf25f1 100644 --- a/resources/order.rb +++ b/resources/order.rb @@ -21,6 +21,6 @@ actions :create, :delete default_action :create -attribute :name, :kind_of => String, :name_attribute => true -attribute :priority, :kind_of => String -attribute :resources, :kind_of => Array +attribute :name, :kind_of => String, :name_attribute => true +attribute :score, :kind_of => String +attribute :ordering, :kind_of => String diff --git a/spec/fixtures/colocation_constraint.rb b/spec/fixtures/colocation_constraint.rb index 7c88d29..74d99d3 100644 --- a/spec/fixtures/colocation_constraint.rb +++ b/spec/fixtures/colocation_constraint.rb @@ -1,5 +1,5 @@ require ::File.expand_path('../../libraries/pacemaker/constraint/colocation', - ::File.dirname(__FILE__)) + File.dirname(__FILE__)) module Chef::RSpec module Pacemaker diff --git a/spec/fixtures/keystone_primitive.rb b/spec/fixtures/keystone_primitive.rb index 8d25e53..fc6424d 100644 --- a/spec/fixtures/keystone_primitive.rb +++ b/spec/fixtures/keystone_primitive.rb @@ -1,5 +1,5 @@ require ::File.expand_path('../../libraries/pacemaker/resource/primitive', - ::File.dirname(__FILE__)) + File.dirname(__FILE__)) module Chef::RSpec module Pacemaker diff --git a/spec/fixtures/location_constraint.rb b/spec/fixtures/location_constraint.rb index faea088..f08159a 100644 --- a/spec/fixtures/location_constraint.rb +++ b/spec/fixtures/location_constraint.rb @@ -1,5 +1,5 @@ require ::File.expand_path('../../libraries/pacemaker/constraint/location', - ::File.dirname(__FILE__)) + File.dirname(__FILE__)) module Chef::RSpec module Pacemaker diff --git a/spec/fixtures/order_constraint.rb b/spec/fixtures/order_constraint.rb new file mode 100644 index 0000000..d390ef6 --- /dev/null +++ b/spec/fixtures/order_constraint.rb @@ -0,0 +1,14 @@ +require ::File.expand_path('../../libraries/pacemaker/constraint/order', + File.dirname(__FILE__)) + +module Chef::RSpec + module Pacemaker + module Config + ORDER_CONSTRAINT = \ + ::Pacemaker::Constraint::Order.new('order1') + ORDER_CONSTRAINT.score = 'Mandatory' + ORDER_CONSTRAINT.ordering = 'primitive1 clone1' + ORDER_CONSTRAINT_DEFINITION = 'order order1 Mandatory: primitive1 clone1' + end + end +end diff --git a/spec/helpers/cib_object.rb b/spec/helpers/cib_object.rb index 1c2d526..aa02a5e 100644 --- a/spec/helpers/cib_object.rb +++ b/spec/helpers/cib_object.rb @@ -1,79 +1,13 @@ -# Shared code used to test providers of CIB objects +# Shared code used to test subclasses of Pacemaker::CIBObject require 'mixlib/shellout' -require File.expand_path('../../libraries/pacemaker/cib_object', - File.dirname(__FILE__)) - -module Chef::RSpec - module Pacemaker - module CIBObject - # Return a Mixlib::ShellOut double which mimics successful - # execution of a command, returning the given string on STDOUT. - def succeeding_shellout_double(string) - shellout = double(Mixlib::ShellOut) - shellout.stub(:environment).and_return({}) - shellout.stub(:run_command) - shellout.stub(:error!) - expect(shellout).to receive(:stdout).and_return(string) - shellout - end - - # Return a Mixlib::ShellOut double which mimics failed - # execution of a command, raising an exception when #error! is - # called. We expect #error! to be called, because if it isn't, - # that probably indicates the code isn't robust enough. This - # may need to be relaxed in the future. - def failing_shellout_double(stdout='', stderr='', exitstatus=1) - shellout = double(Mixlib::ShellOut) - shellout.stub(:environment).and_return({}) - shellout.stub(:run_command) - shellout.stub(:stdout).and_return(stdout) - shellout.stub(:stderr).and_return(stderr) - shellout.stub(:exitstatus).and_return(exitstatus) - exception = Mixlib::ShellOut::ShellCommandFailed.new( - "Expected process to exit with 0, " + - "but received '#{exitstatus}'" - ) - expect(shellout).to receive(:error!).and_raise(exception) - shellout - end - - # This stubs Mixlib::ShellOut.new with a sequence of doubles - # with a corresponding sequence of behaviours. This allows us - # to simulate the output of a series of shell commands being run - # via Mixlib::ShellOut. Each double either mimics a successful - # command execution whose #stdout method returns the given - # string, or a failed execution with the given exit code and - # STDOUT/STDERR. - # - # results is an Array describing the sequence of behaviours; - # each element is either a string mimicking STDOUT from - # successful command execution, or a [stdout, stderr, exitcode] - # status mimicking command execution failure. - # - # For example, "crm configure show" is executed by - # #load_current_resource, and again later on for the :create - # action, to see whether to create or modify. So the first - # double in the sequence would return an empty definition if we - # wanted to test creation of a new CIB object, or an existing - # definition if we wanted to test modification of an existing - # one. If the test needs subsequent doubles to return different - # values then stdout_strings can have more than one element. - def stub_shellout(*results) - doubles = results.map { |result| - result.is_a?(String) ? - succeeding_shellout_double(result) - : failing_shellout_double(*result) - } - Mixlib::ShellOut.stub(:new).and_return(*doubles) - end - end - end -end +this_dir = File.dirname(__FILE__) +require File.expand_path('../../libraries/pacemaker/cib_object', this_dir) +require File.expand_path('shellout', this_dir) shared_examples "a CIB object" do - include Chef::RSpec::Pacemaker::CIBObject + include Chef::RSpec::Mixlib::ShellOut def expect_to_match_fixture(obj) expect(obj.class).to eq(pacemaker_object_class) @@ -101,21 +35,3 @@ shared_examples "a CIB object" do "Expected #{object_type} type but loaded definition was type sometype") end end - -shared_examples "action on non-existent resource" do |action, cmd, expected_error| - include Chef::RSpec::Pacemaker::CIBObject - - it "should not attempt to #{action.to_s} a non-existent resource" do - stub_shellout("") - - if expected_error - expect { provider.run_action action }.to \ - raise_error(RuntimeError, expected_error) - else - provider.run_action action - end - - expect(@chef_run).not_to run_execute(cmd) - expect(@resource).not_to be_updated - end -end diff --git a/spec/helpers/non_runnable_resource.rb b/spec/helpers/non_runnable_resource.rb new file mode 100644 index 0000000..594406a --- /dev/null +++ b/spec/helpers/non_runnable_resource.rb @@ -0,0 +1,26 @@ +# Shared code used to test providers of non-runnable Chef resources +# representing Pacemaker CIB objects. For example the provider for +# primitives is runnable (since primitives can be started and stopped) +# but constraints cannot. + +this_dir = File.dirname(__FILE__) +require File.expand_path('provider', this_dir) +require File.expand_path('shellout', this_dir) + +shared_examples "a non-runnable resource" do |fixture| + include Chef::RSpec::Mixlib::ShellOut + + it_should_behave_like "all Pacemaker LWRPs", fixture + + describe ":delete action" do + it "should delete a resource" do + stub_shellout(fixture.definition_string) + + provider.run_action :delete + + cmd = "crm configure delete '#{fixture.name}'" + expect(@chef_run).to run_execute(cmd) + expect(@resource).to be_updated + end + end +end diff --git a/spec/helpers/provider.rb b/spec/helpers/provider.rb new file mode 100644 index 0000000..38f8fc3 --- /dev/null +++ b/spec/helpers/provider.rb @@ -0,0 +1,71 @@ +# Shared code used to test providers of CIB objects + +this_dir = File.dirname(__FILE__) +require File.expand_path('shellout', this_dir) +require File.expand_path('cib_object', this_dir) + +shared_context "a Pacemaker LWRP" do + before(:each) do + runner_opts = { + :step_into => [lwrp_name] + } + @chef_run = ::ChefSpec::Runner.new(runner_opts) + @chef_run.converge "pacemaker::default" + @node = @chef_run.node + @run_context = @chef_run.run_context + + camelized_subclass_name = "Pacemaker" + lwrp_name.capitalize + @resource_class = ::Chef::Resource.const_get(camelized_subclass_name) + @provider_class = ::Chef::Provider.const_get(camelized_subclass_name) + + @resource = @resource_class.new(fixture.name, @run_context) + end + + let (:provider) { @provider_class.new(@resource, @run_context) } +end + +module Chef::RSpec + module Pacemaker + module CIBObject + include Chef::RSpec::Mixlib::ShellOut + + def test_modify(expected_cmds) + yield + + stub_shellout(fixture.definition_string) + + provider.run_action :create + + expected_cmds.each do |cmd| + expect(@chef_run).to run_execute(cmd) + end + expect(@resource).to be_updated + end + end + end +end + +shared_examples "action on non-existent resource" do |action, cmd, expected_error| + include Chef::RSpec::Mixlib::ShellOut + + it "should not attempt to #{action.to_s} a non-existent resource" do + stub_shellout("") + + if expected_error + expect { provider.run_action action }.to \ + raise_error(RuntimeError, expected_error) + else + provider.run_action action + end + + expect(@chef_run).not_to run_execute(cmd) + expect(@resource).not_to be_updated + end +end + +shared_examples "all Pacemaker LWRPs" do |fixture| + describe ":delete action" do + it_should_behave_like "action on non-existent resource", \ + :delete, "crm configure delete #{fixture.name}", nil + end +end diff --git a/spec/helpers/runnable_resource.rb b/spec/helpers/runnable_resource.rb index d454557..ec831d5 100644 --- a/spec/helpers/runnable_resource.rb +++ b/spec/helpers/runnable_resource.rb @@ -1,25 +1,24 @@ -require File.expand_path('cib_object', File.dirname(__FILE__)) +# Shared code used to test providers of runnable Chef resources +# representing Pacemaker CIB objects. For example the provider +# for primitives is runnable (since primitives can be started +# and stopped) but constraints cannot. -module Chef::RSpec - module Pacemaker - module RunnableResource - def expect_running(running) - expect_any_instance_of(cib_object_class) \ - .to receive(:running?) \ - .and_return(running) - end - end - end -end +this_dir = File.dirname(__FILE__) +require File.expand_path('provider', this_dir) +require File.expand_path('shellout', this_dir) shared_examples "a runnable resource" do |fixture| + def expect_running(running) + expect_any_instance_of(cib_object_class) \ + .to receive(:running?) \ + .and_return(running) + end - include Chef::RSpec::Pacemaker::RunnableResource + it_should_behave_like "all Pacemaker LWRPs", fixture + + include Chef::RSpec::Mixlib::ShellOut describe ":delete action" do - it_should_behave_like "action on non-existent resource", \ - :delete, "crm configure delete #{fixture.name}", nil - it "should not delete a running resource" do stub_shellout(fixture.definition_string) expect_running(true) diff --git a/spec/helpers/shellout.rb b/spec/helpers/shellout.rb new file mode 100644 index 0000000..ffc4e93 --- /dev/null +++ b/spec/helpers/shellout.rb @@ -0,0 +1,68 @@ +require 'mixlib/shellout' + +module Chef::RSpec + module Mixlib + module ShellOut + # Return a Mixlib::ShellOut double which mimics successful + # execution of a command, returning the given string on STDOUT. + def succeeding_shellout_double(string) + shellout = double(Mixlib::ShellOut) + shellout.stub(:environment).and_return({}) + shellout.stub(:run_command) + shellout.stub(:error!) + expect(shellout).to receive(:stdout).and_return(string) + shellout + end + + # Return a Mixlib::ShellOut double which mimics failed + # execution of a command, raising an exception when #error! is + # called. We expect #error! to be called, because if it isn't, + # that probably indicates the code isn't robust enough. This + # may need to be relaxed in the future. + def failing_shellout_double(stdout='', stderr='', exitstatus=1) + shellout = double(Mixlib::ShellOut) + shellout.stub(:environment).and_return({}) + shellout.stub(:run_command) + shellout.stub(:stdout).and_return(stdout) + shellout.stub(:stderr).and_return(stderr) + shellout.stub(:exitstatus).and_return(exitstatus) + exception = ::Mixlib::ShellOut::ShellCommandFailed.new( + "Expected process to exit with 0, " + + "but received '#{exitstatus}'" + ) + expect(shellout).to receive(:error!).and_raise(exception) + shellout + end + + # This stubs Mixlib::ShellOut.new with a sequence of doubles + # with a corresponding sequence of behaviours. This allows us + # to simulate the output of a series of shell commands being run + # via Mixlib::ShellOut. Each double either mimics a successful + # command execution whose #stdout method returns the given + # string, or a failed execution with the given exit code and + # STDOUT/STDERR. + # + # results is an Array describing the sequence of behaviours; + # each element is either a string mimicking STDOUT from + # successful command execution, or a [stdout, stderr, exitcode] + # status mimicking command execution failure. + # + # For example, "crm configure show" is executed by + # #load_current_resource, and again later on for the :create + # action, to see whether to create or modify. So the first + # double in the sequence would return an empty definition if we + # wanted to test creation of a new CIB object, or an existing + # definition if we wanted to test modification of an existing + # one. If the test needs subsequent doubles to return different + # values then stdout_strings can have more than one element. + def stub_shellout(*results) + doubles = results.map { |result| + result.is_a?(String) ? + succeeding_shellout_double(result) + : failing_shellout_double(*result) + } + ::Mixlib::ShellOut.stub(:new).and_return(*doubles) + end + end + end +end diff --git a/spec/libraries/pacemaker/cib_object_spec.rb b/spec/libraries/pacemaker/cib_object_spec.rb index 0362b3c..d27d2b9 100644 --- a/spec/libraries/pacemaker/cib_object_spec.rb +++ b/spec/libraries/pacemaker/cib_object_spec.rb @@ -1,8 +1,10 @@ -require 'spec_helper' require 'mixlib/shellout' -require File.expand_path('../../../libraries/pacemaker', File.dirname(__FILE__)) -require File.expand_path('../../fixtures/keystone_primitive', File.dirname(__FILE__)) +require 'spec_helper' + +this_dir = File.dirname(__FILE__) +require File.expand_path('../../../libraries/pacemaker', this_dir) +require File.expand_path('../../fixtures/keystone_primitive', this_dir) describe Pacemaker::CIBObject do diff --git a/spec/libraries/pacemaker/constraint/colocation_spec.rb b/spec/libraries/pacemaker/constraint/colocation_spec.rb index 51133e7..7e4df54 100644 --- a/spec/libraries/pacemaker/constraint/colocation_spec.rb +++ b/spec/libraries/pacemaker/constraint/colocation_spec.rb @@ -1,8 +1,10 @@ require 'spec_helper' + +this_dir = File.dirname(__FILE__) require File.expand_path('../../../../libraries/pacemaker/constraint/colocation', - File.dirname(__FILE__)) -require File.expand_path('../../../fixtures/colocation_constraint', File.dirname(__FILE__)) -require File.expand_path('../../../helpers/cib_object', File.dirname(__FILE__)) + this_dir) +require File.expand_path('../../../fixtures/colocation_constraint', this_dir) +require File.expand_path('../../../helpers/cib_object', this_dir) describe Pacemaker::Constraint::Colocation do let(:fixture) { Chef::RSpec::Pacemaker::Config::COLOCATION_CONSTRAINT.dup } @@ -10,10 +12,6 @@ describe Pacemaker::Constraint::Colocation do Chef::RSpec::Pacemaker::Config::COLOCATION_CONSTRAINT_DEFINITION } - before(:each) do - Mixlib::ShellOut.any_instance.stub(:run_command) - end - def object_type 'colocation' end diff --git a/spec/libraries/pacemaker/constraint/location_spec.rb b/spec/libraries/pacemaker/constraint/location_spec.rb index c6a6572..dc91a39 100644 --- a/spec/libraries/pacemaker/constraint/location_spec.rb +++ b/spec/libraries/pacemaker/constraint/location_spec.rb @@ -1,8 +1,10 @@ require 'spec_helper' + +this_dir = File.dirname(__FILE__) require File.expand_path('../../../../libraries/pacemaker/constraint/location', - File.dirname(__FILE__)) -require File.expand_path('../../../fixtures/location_constraint', File.dirname(__FILE__)) -require File.expand_path('../../../helpers/cib_object', File.dirname(__FILE__)) + this_dir) +require File.expand_path('../../../fixtures/location_constraint', this_dir) +require File.expand_path('../../../helpers/cib_object', this_dir) describe Pacemaker::Constraint::Location do let(:fixture) { Chef::RSpec::Pacemaker::Config::LOCATION_CONSTRAINT.dup } @@ -10,10 +12,6 @@ describe Pacemaker::Constraint::Location do Chef::RSpec::Pacemaker::Config::LOCATION_CONSTRAINT_DEFINITION } - before(:each) do - Mixlib::ShellOut.any_instance.stub(:run_command) - end - def object_type 'location' end diff --git a/spec/libraries/pacemaker/constraint/order_spec.rb b/spec/libraries/pacemaker/constraint/order_spec.rb new file mode 100644 index 0000000..219bf8a --- /dev/null +++ b/spec/libraries/pacemaker/constraint/order_spec.rb @@ -0,0 +1,61 @@ +require 'spec_helper' + +this_dir = File.dirname(__FILE__) +require File.expand_path('../../../../libraries/pacemaker/constraint/order', + this_dir) +require File.expand_path('../../../fixtures/order_constraint', this_dir) +require File.expand_path('../../../helpers/cib_object', this_dir) + +describe Pacemaker::Constraint::Order do + let(:fixture) { Chef::RSpec::Pacemaker::Config::ORDER_CONSTRAINT.dup } + let(:fixture_definition) { + Chef::RSpec::Pacemaker::Config::ORDER_CONSTRAINT_DEFINITION + } + + def object_type + 'order' + end + + def pacemaker_object_class + Pacemaker::Constraint::Order + end + + def fields + %w(name score ordering) + end + + it_should_behave_like "a CIB object" + + describe "#definition_string" do + it "should return the definition string" do + expect(fixture.definition_string).to eq(fixture_definition) + end + + it "should return a short definition string" do + order = pacemaker_object_class.new('foo') + order.definition = \ + %!order order1 Mandatory: rsc1 rsc2! + order.parse_definition + expect(order.definition_string).to eq(<<'EOF'.chomp) +order order1 Mandatory: rsc1 rsc2 +EOF + end + end + + describe "#parse_definition" do + before(:each) do + @parsed = pacemaker_object_class.new(fixture.name) + @parsed.definition = fixture_definition + @parsed.parse_definition + end + + it "should parse the score" do + expect(@parsed.score).to eq(fixture.score) + end + + it "should parse the ordering" do + expect(@parsed.ordering).to eq(fixture.ordering) + end + + end +end diff --git a/spec/libraries/pacemaker/resource/clone_spec.rb b/spec/libraries/pacemaker/resource/clone_spec.rb index f328cca..0828b29 100644 --- a/spec/libraries/pacemaker/resource/clone_spec.rb +++ b/spec/libraries/pacemaker/resource/clone_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -require File.expand_path('../../../../libraries/pacemaker/resource/clone', - File.dirname(__FILE__)) -require File.expand_path('../../../fixtures/clone_resource', File.dirname(__FILE__)) -require File.expand_path('../../../helpers/cib_object', File.dirname(__FILE__)) -require File.expand_path('../../../helpers/meta_examples', - File.dirname(__FILE__)) + +this_dir = File.dirname(__FILE__) +require File.expand_path('../../../../libraries/pacemaker/resource/clone', this_dir) +require File.expand_path('../../../fixtures/clone_resource', this_dir) +require File.expand_path('../../../helpers/cib_object', this_dir) +require File.expand_path('../../../helpers/meta_examples', this_dir) describe Pacemaker::Resource::Clone do let(:fixture) { Chef::RSpec::Pacemaker::Config::CLONE_RESOURCE.dup } @@ -12,10 +12,6 @@ describe Pacemaker::Resource::Clone do Chef::RSpec::Pacemaker::Config::CLONE_RESOURCE_DEFINITION } - before(:each) do - Mixlib::ShellOut.any_instance.stub(:run_command) - end - def object_type 'clone' end diff --git a/spec/libraries/pacemaker/resource/group_spec.rb b/spec/libraries/pacemaker/resource/group_spec.rb index 2dc7eae..cd764fc 100644 --- a/spec/libraries/pacemaker/resource/group_spec.rb +++ b/spec/libraries/pacemaker/resource/group_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' + require File.expand_path('../../../../libraries/pacemaker/resource/group', File.dirname(__FILE__)) require File.expand_path('../../../fixtures/resource_group', File.dirname(__FILE__)) @@ -12,10 +13,6 @@ describe Pacemaker::Resource::Group do Chef::RSpec::Pacemaker::Config::RESOURCE_GROUP_DEFINITION } - before(:each) do - Mixlib::ShellOut.any_instance.stub(:run_command) - end - def object_type 'group' end diff --git a/spec/libraries/pacemaker/resource/ms_spec.rb b/spec/libraries/pacemaker/resource/ms_spec.rb index cb1619f..966b8f8 100644 --- a/spec/libraries/pacemaker/resource/ms_spec.rb +++ b/spec/libraries/pacemaker/resource/ms_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -require File.expand_path('../../../../libraries/pacemaker/resource/ms', - File.dirname(__FILE__)) -require File.expand_path('../../../fixtures/ms_resource', File.dirname(__FILE__)) -require File.expand_path('../../../helpers/cib_object', File.dirname(__FILE__)) -require File.expand_path('../../../helpers/meta_examples', - File.dirname(__FILE__)) + +this_dir = File.dirname(__FILE__) +require File.expand_path('../../../../libraries/pacemaker/resource/ms', this_dir) +require File.expand_path('../../../fixtures/ms_resource', this_dir) +require File.expand_path('../../../helpers/cib_object', this_dir) +require File.expand_path('../../../helpers/meta_examples', this_dir) describe Pacemaker::Resource::MasterSlave do let(:fixture) { Chef::RSpec::Pacemaker::Config::MS_RESOURCE.dup } @@ -12,10 +12,6 @@ describe Pacemaker::Resource::MasterSlave do Chef::RSpec::Pacemaker::Config::MS_RESOURCE_DEFINITION } - before(:each) do - Mixlib::ShellOut.any_instance.stub(:run_command) - end - def object_type 'ms' end diff --git a/spec/libraries/pacemaker/resource/primitive_spec.rb b/spec/libraries/pacemaker/resource/primitive_spec.rb index 1ec1fc7..364ac45 100644 --- a/spec/libraries/pacemaker/resource/primitive_spec.rb +++ b/spec/libraries/pacemaker/resource/primitive_spec.rb @@ -1,12 +1,11 @@ require 'spec_helper' + +this_dir = File.dirname(__FILE__) require File.expand_path('../../../../libraries/pacemaker/resource/primitive', - File.dirname(__FILE__)) -require File.expand_path('../../../fixtures/keystone_primitive', - File.dirname(__FILE__)) -require File.expand_path('../../../helpers/cib_object', - File.dirname(__FILE__)) -require File.expand_path('../../../helpers/meta_examples', - File.dirname(__FILE__)) + this_dir) +require File.expand_path('../../../fixtures/keystone_primitive', this_dir) +require File.expand_path('../../../helpers/cib_object', this_dir) +require File.expand_path('../../../helpers/meta_examples', this_dir) describe Pacemaker::Resource::Primitive do let(:fixture) { Chef::RSpec::Pacemaker::Config::KEYSTONE_PRIMITIVE.dup } diff --git a/spec/libraries/pacemaker/resource_spec.rb b/spec/libraries/pacemaker/resource_spec.rb index a49aa5f..35d2816 100644 --- a/spec/libraries/pacemaker/resource_spec.rb +++ b/spec/libraries/pacemaker/resource_spec.rb @@ -1,8 +1,10 @@ +require 'mixlib/shellout' + require 'spec_helper' -require File.expand_path('../../../libraries/pacemaker/resource', - File.dirname(__FILE__)) -require File.expand_path('../../fixtures/keystone_primitive', - File.dirname(__FILE__)) + +this_dir = File.dirname(__FILE__) +require File.expand_path('../../../libraries/pacemaker/resource', this_dir) +require File.expand_path('../../fixtures/keystone_primitive', this_dir) describe Pacemaker::Resource do describe "#running?" do diff --git a/spec/providers/clone_spec.rb b/spec/providers/clone_spec.rb index b0a9c22..4431d1b 100644 --- a/spec/providers/clone_spec.rb +++ b/spec/providers/clone_spec.rb @@ -1,8 +1,8 @@ -require 'chef/application' -require File.expand_path('../spec_helper', File.dirname(__FILE__)) -require File.expand_path('../helpers/cib_object', File.dirname(__FILE__)) -require File.expand_path('../helpers/runnable_resource', File.dirname(__FILE__)) -require File.expand_path('../fixtures/clone_resource', File.dirname(__FILE__)) +require 'spec_helper' + +this_dir = File.dirname(__FILE__) +require File.expand_path('../helpers/runnable_resource', this_dir) +require File.expand_path('../fixtures/clone_resource', this_dir) describe "Chef::Provider::PacemakerClone" do # for use inside examples: @@ -10,41 +10,25 @@ describe "Chef::Provider::PacemakerClone" do # for use outside examples (e.g. when invoking shared_examples) fixture = Chef::RSpec::Pacemaker::Config::CLONE_RESOURCE.dup - before(:each) do - runner_opts = { - :step_into => ['pacemaker_clone'] - } - @chef_run = ::ChefSpec::Runner.new(runner_opts) - @chef_run.converge "pacemaker::default" - @node = @chef_run.node - @run_context = @chef_run.run_context - - @resource = Chef::Resource::PacemakerClone.new(fixture.name, @run_context) - @resource.rsc fixture.rsc.dup - @resource.meta Hash[fixture.meta.dup] + def lwrp_name + 'clone' end - let (:provider) { Chef::Provider::PacemakerClone.new(@resource, @run_context) } + include_context "a Pacemaker LWRP" + + before(:each) do + @resource.rsc fixture.rsc.dup + @resource.meta Hash[fixture.meta.dup] + + + end def cib_object_class Pacemaker::Resource::Clone end - include Chef::RSpec::Pacemaker::CIBObject - describe ":create action" do - def test_modify(expected_cmds) - yield - - stub_shellout(fixture.definition_string) - - provider.run_action :create - - expected_cmds.each do |cmd| - expect(@chef_run).to run_execute(cmd) - end - expect(@resource).to be_updated - end + include Chef::RSpec::Pacemaker::CIBObject it "should modify the clone if the resource is changed" do expected = fixture.dup diff --git a/spec/providers/colocation_spec.rb b/spec/providers/colocation_spec.rb index 4a0d3fd..aa43d7e 100644 --- a/spec/providers/colocation_spec.rb +++ b/spec/providers/colocation_spec.rb @@ -1,7 +1,9 @@ -require 'chef/application' -require File.expand_path('../spec_helper', File.dirname(__FILE__)) -require File.expand_path('../helpers/cib_object', File.dirname(__FILE__)) -require File.expand_path('../fixtures/colocation_constraint', File.dirname(__FILE__)) +require 'spec_helper' + +this_dir = File.dirname(__FILE__) +require File.expand_path('../helpers/provider', this_dir) +require File.expand_path('../helpers/non_runnable_resource', this_dir) +require File.expand_path('../fixtures/colocation_constraint', this_dir) describe "Chef::Provider::PacemakerColocation" do # for use inside examples: @@ -9,41 +11,25 @@ describe "Chef::Provider::PacemakerColocation" do # for use outside examples (e.g. when invoking shared_examples) fixture = Chef::RSpec::Pacemaker::Config::COLOCATION_CONSTRAINT.dup - before(:each) do - runner_opts = { - :step_into => ['pacemaker_colocation'] - } - @chef_run = ::ChefSpec::Runner.new(runner_opts) - @chef_run.converge "pacemaker::default" - @node = @chef_run.node - @run_context = @chef_run.run_context - - @resource = Chef::Resource::PacemakerColocation.new(fixture.name, @run_context) - @resource.score fixture.score - @resource.resources fixture.resources.dup + def lwrp_name + 'colocation' end - let (:provider) { Chef::Provider::PacemakerColocation.new(@resource, @run_context) } + include_context "a Pacemaker LWRP" + + before(:each) do + @resource.score fixture.score + @resource.resources fixture.resources.dup + + + end def cib_object_class Pacemaker::Constraint::Colocation end - include Chef::RSpec::Pacemaker::CIBObject - describe ":create action" do - def test_modify(expected_cmds) - yield - - stub_shellout(fixture.definition_string) - - provider.run_action :create - - expected_cmds.each do |cmd| - expect(@chef_run).to run_execute(cmd) - end - expect(@resource).to be_updated - end + include Chef::RSpec::Pacemaker::CIBObject it "should modify the constraint if it has a different score" do new_score = '100' @@ -75,9 +61,6 @@ describe "Chef::Provider::PacemakerColocation" do end - describe ":delete action" do - it_should_behave_like "action on non-existent resource", \ - :delete, "crm configure delete #{fixture.name}", nil - end + it_should_behave_like "a non-runnable resource", fixture end diff --git a/spec/providers/group_spec.rb b/spec/providers/group_spec.rb index 6976876..c9ba86e 100644 --- a/spec/providers/group_spec.rb +++ b/spec/providers/group_spec.rb @@ -1,8 +1,8 @@ -require 'chef/application' -require File.expand_path('../spec_helper', File.dirname(__FILE__)) -require File.expand_path('../helpers/cib_object', File.dirname(__FILE__)) -require File.expand_path('../helpers/runnable_resource', File.dirname(__FILE__)) -require File.expand_path('../fixtures/resource_group', File.dirname(__FILE__)) +require 'spec_helper' + +this_dir = File.dirname(__FILE__) +require File.expand_path('../helpers/runnable_resource', this_dir) +require File.expand_path('../fixtures/resource_group', this_dir) describe "Chef::Provider::PacemakerGroup" do # for use inside examples: @@ -10,41 +10,25 @@ describe "Chef::Provider::PacemakerGroup" do # for use outside examples (e.g. when invoking shared_examples) fixture = Chef::RSpec::Pacemaker::Config::RESOURCE_GROUP.dup - before(:each) do - runner_opts = { - :step_into => ['pacemaker_group'] - } - @chef_run = ::ChefSpec::Runner.new(runner_opts) - @chef_run.converge "pacemaker::default" - @node = @chef_run.node - @run_context = @chef_run.run_context - - @resource = Chef::Resource::PacemakerGroup.new(fixture.name, @run_context) - @resource.members fixture.members.dup - @resource.meta Hash[fixture.meta.dup] + def lwrp_name + 'group' end - let (:provider) { Chef::Provider::PacemakerGroup.new(@resource, @run_context) } + include_context "a Pacemaker LWRP" + + before(:each) do + @resource.members fixture.members.dup + @resource.meta Hash[fixture.meta.dup] + + + end def cib_object_class Pacemaker::Resource::Group end - include Chef::RSpec::Pacemaker::CIBObject - describe ":create action" do - def test_modify(expected_cmds) - yield - - stub_shellout(fixture.definition_string) - - provider.run_action :create - - expected_cmds.each do |cmd| - expect(@chef_run).to run_execute(cmd) - end - expect(@resource).to be_updated - end + include Chef::RSpec::Pacemaker::CIBObject it "should modify the group if it has a member resource added" do expected = fixture.dup diff --git a/spec/providers/location_spec.rb b/spec/providers/location_spec.rb index 9585336..fa3c1fe 100644 --- a/spec/providers/location_spec.rb +++ b/spec/providers/location_spec.rb @@ -1,7 +1,9 @@ -require 'chef/application' -require File.expand_path('../spec_helper', File.dirname(__FILE__)) -require File.expand_path('../helpers/cib_object', File.dirname(__FILE__)) -require File.expand_path('../fixtures/location_constraint', File.dirname(__FILE__)) +require 'spec_helper' + +this_dir = File.dirname(__FILE__) +require File.expand_path('../helpers/provider', this_dir) +require File.expand_path('../helpers/non_runnable_resource', this_dir) +require File.expand_path('../fixtures/location_constraint', this_dir) describe "Chef::Provider::PacemakerLocation" do # for use inside examples: @@ -9,42 +11,25 @@ describe "Chef::Provider::PacemakerLocation" do # for use outside examples (e.g. when invoking shared_examples) fixture = Chef::RSpec::Pacemaker::Config::LOCATION_CONSTRAINT.dup - before(:each) do - runner_opts = { - :step_into => ['pacemaker_location'] - } - @chef_run = ::ChefSpec::Runner.new(runner_opts) - @chef_run.converge "pacemaker::default" - @node = @chef_run.node - @run_context = @chef_run.run_context + def lwrp_name + 'location' + end - @resource = Chef::Resource::PacemakerLocation.new(fixture.name, @run_context) + include_context "a Pacemaker LWRP" + + before(:each) do @resource.rsc fixture.rsc @resource.score fixture.score @resource.node fixture.node.dup - end - let (:provider) { Chef::Provider::PacemakerLocation.new(@resource, @run_context) } + end def cib_object_class Pacemaker::Constraint::Location end - include Chef::RSpec::Pacemaker::CIBObject - describe ":create action" do - def test_modify(expected_cmds) - yield - - stub_shellout(fixture.definition_string) - - provider.run_action :create - - expected_cmds.each do |cmd| - expect(@chef_run).to run_execute(cmd) - end - expect(@resource).to be_updated - end + include Chef::RSpec::Pacemaker::CIBObject it "should modify the constraint if it has a different resource" do new_resource = 'group2' @@ -75,9 +60,6 @@ describe "Chef::Provider::PacemakerLocation" do end - describe ":delete action" do - it_should_behave_like "action on non-existent resource", \ - :delete, "crm configure delete #{fixture.name}", nil - end + it_should_behave_like "a non-runnable resource", fixture end diff --git a/spec/providers/ms_spec.rb b/spec/providers/ms_spec.rb index 5f15e89..45aca27 100644 --- a/spec/providers/ms_spec.rb +++ b/spec/providers/ms_spec.rb @@ -1,8 +1,8 @@ -require 'chef/application' -require File.expand_path('../spec_helper', File.dirname(__FILE__)) -require File.expand_path('../helpers/cib_object', File.dirname(__FILE__)) -require File.expand_path('../helpers/runnable_resource', File.dirname(__FILE__)) -require File.expand_path('../fixtures/ms_resource', File.dirname(__FILE__)) +require 'spec_helper' + +this_dir = File.dirname(__FILE__) +require File.expand_path('../helpers/runnable_resource', this_dir) +require File.expand_path('../fixtures/ms_resource', this_dir) describe "Chef::Provider::PacemakerMs" do # for use inside examples: @@ -10,41 +10,25 @@ describe "Chef::Provider::PacemakerMs" do # for use outside examples (e.g. when invoking shared_examples) fixture = Chef::RSpec::Pacemaker::Config::MS_RESOURCE.dup - before(:each) do - runner_opts = { - :step_into => ['pacemaker_ms'] - } - @chef_run = ::ChefSpec::Runner.new(runner_opts) - @chef_run.converge "pacemaker::default" - @node = @chef_run.node - @run_context = @chef_run.run_context - - @resource = Chef::Resource::PacemakerMs.new(fixture.name, @run_context) - @resource.rsc fixture.rsc.dup - @resource.meta Hash[fixture.meta.dup] + def lwrp_name + 'ms' end - let (:provider) { Chef::Provider::PacemakerMs.new(@resource, @run_context) } + include_context "a Pacemaker LWRP" + + before(:each) do + @resource.rsc fixture.rsc.dup + @resource.meta Hash[fixture.meta.dup] + + + end def cib_object_class Pacemaker::Resource::MasterSlave end - include Chef::RSpec::Pacemaker::CIBObject - describe ":create action" do - def test_modify(expected_cmds) - yield - - stub_shellout(fixture.definition_string) - - provider.run_action :create - - expected_cmds.each do |cmd| - expect(@chef_run).to run_execute(cmd) - end - expect(@resource).to be_updated - end + include Chef::RSpec::Pacemaker::CIBObject it "should modify the resource if it's changed" do expected = fixture.dup diff --git a/spec/providers/order_spec.rb b/spec/providers/order_spec.rb new file mode 100644 index 0000000..b26bce4 --- /dev/null +++ b/spec/providers/order_spec.rb @@ -0,0 +1,66 @@ +require 'spec_helper' + +this_dir = File.dirname(__FILE__) +require File.expand_path('../helpers/provider', this_dir) +require File.expand_path('../helpers/non_runnable_resource', this_dir) +require File.expand_path('../fixtures/order_constraint', this_dir) + +describe "Chef::Provider::PacemakerOrder" do + # for use inside examples: + let(:fixture) { Chef::RSpec::Pacemaker::Config::ORDER_CONSTRAINT.dup } + # for use outside examples (e.g. when invoking shared_examples) + fixture = Chef::RSpec::Pacemaker::Config::ORDER_CONSTRAINT.dup + + def lwrp_name + 'order' + end + + include_context "a Pacemaker LWRP" + + before(:each) do + @resource.score fixture.score + @resource.ordering fixture.ordering.dup + + + end + + def cib_object_class + Pacemaker::Constraint::Order + end + + describe ":create action" do + include Chef::RSpec::Pacemaker::CIBObject + + it "should modify the constraint if it has a different score" do + new_score = '100' + fixture.score = new_score + expected_configure_cmd_args = [fixture.reconfigure_command] + test_modify(expected_configure_cmd_args) do + @resource.score new_score + end + end + + it "should modify the constraint if it has a resource added" do + new_resource = 'bar:Stopped' + expected = fixture.dup + expected.ordering = expected.ordering.dup + ' ' + new_resource + expected_configure_cmd_args = [expected.reconfigure_command] + test_modify(expected_configure_cmd_args) do + @resource.ordering expected.ordering + end + end + + it "should modify the constraint if it has a different ordering" do + new_ordering = 'clone1 primitive1' + fixture.ordering = new_ordering + expected_configure_cmd_args = [fixture.reconfigure_command] + test_modify(expected_configure_cmd_args) do + @resource.ordering new_ordering + end + end + + end + + it_should_behave_like "a non-runnable resource", fixture + +end diff --git a/spec/providers/primitive_spec.rb b/spec/providers/primitive_spec.rb index 22b8554..8b7c528 100644 --- a/spec/providers/primitive_spec.rb +++ b/spec/providers/primitive_spec.rb @@ -1,8 +1,8 @@ -require 'chef/application' -require File.expand_path('../spec_helper', File.dirname(__FILE__)) -require File.expand_path('../helpers/cib_object', File.dirname(__FILE__)) -require File.expand_path('../helpers/runnable_resource', File.dirname(__FILE__)) -require File.expand_path('../fixtures/keystone_primitive', File.dirname(__FILE__)) +require 'spec_helper' + +this_dir = File.dirname(__FILE__) +require File.expand_path('../helpers/runnable_resource', this_dir) +require File.expand_path('../fixtures/keystone_primitive', this_dir) describe "Chef::Provider::PacemakerPrimitive" do # for use inside examples: @@ -10,43 +10,26 @@ describe "Chef::Provider::PacemakerPrimitive" do # for use outside examples (e.g. when invoking shared_examples) fixture = Chef::RSpec::Pacemaker::Config::KEYSTONE_PRIMITIVE - before(:each) do - runner_opts = { - :step_into => ['pacemaker_primitive'] - } - @chef_run = ::ChefSpec::Runner.new(runner_opts) - @chef_run.converge "pacemaker::default" - @node = @chef_run.node - @run_context = @chef_run.run_context + def lwrp_name + 'primitive' + end - @resource = Chef::Resource::PacemakerPrimitive.new(fixture.name, @run_context) + include_context "a Pacemaker LWRP" + + before(:each) do @resource.agent fixture.agent @resource.params Hash[fixture.params] @resource.meta Hash[fixture.meta] @resource.op Hash[fixture.op] end - let (:provider) { Chef::Provider::PacemakerPrimitive.new(@resource, @run_context) } - def cib_object_class Pacemaker::Resource::Primitive end - include Chef::RSpec::Pacemaker::CIBObject - describe ":create action" do - def test_modify(expected_cmds) - yield - - stub_shellout(fixture.definition_string) - - provider.run_action :create - - expected_cmds.each do |cmd| - expect(@chef_run).to run_execute(cmd) - end - expect(@resource).to be_updated - end + include Chef::RSpec::Pacemaker::CIBObject + include Chef::RSpec::Mixlib::ShellOut it "should modify the primitive if it has different params" do expected_configure_cmd_args = [