switch to OO classes modelling Pacemaker objects
This commit is contained in:
23
Guardfile
23
Guardfile
@@ -7,25 +7,24 @@ guard_opts = {
|
||||
all_after_pass: true,
|
||||
}
|
||||
|
||||
def startup_guards
|
||||
watch(%r{^Gemfile$}) { yield }
|
||||
watch(%r{^Gemfile.lock$}) { yield }
|
||||
watch(%r{^spec/spec_helper\.rb$}) { yield }
|
||||
end
|
||||
|
||||
def all_specs
|
||||
'spec'
|
||||
end
|
||||
|
||||
group :rspec do
|
||||
guard 'rspec', guard_opts do
|
||||
startup_guards { all_specs }
|
||||
watch(%r{^spec_helper\.rb$}) { all_specs }
|
||||
watch(%r{^helpers/(.+)\.rb$}) { all_specs }
|
||||
watch(%r{^Gemfile$}) { all_specs }
|
||||
watch(%r{^Gemfile.lock$}) { all_specs }
|
||||
watch(%r{^spec/spec_helper\.rb$}) { all_specs }
|
||||
watch(%r{^spec/helpers/(.+)\.rb$}) { all_specs }
|
||||
watch(%r{^libraries/pacemaker\.rb$}) { all_specs }
|
||||
watch(%r{^spec/.+_spec\.rb$})
|
||||
watch(%r{^(libraries|providers)/(.+)\.rb$}) do |m|
|
||||
"spec/#{m[1]}/#{m[2]}_spec.rb"
|
||||
end
|
||||
watch(%r{^libraries/pacemaker/(.+)\.rb$}) { |m|
|
||||
"spec/libraries/#{m[1]}_spec.rb"
|
||||
}
|
||||
watch(%r{^(resources|providers)/(.+)\.rb$}) { |m|
|
||||
"spec/providers/#{m[1]}_spec.rb"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
@@ -1,94 +0,0 @@
|
||||
require 'shellwords'
|
||||
|
||||
module Chef::Libraries
|
||||
module Pacemaker
|
||||
module CIBObjects
|
||||
include Chef::Mixin::ShellOut
|
||||
|
||||
def get_cib_object_definition(name)
|
||||
cmd = Mixlib::ShellOut.new("crm configure show #{name}")
|
||||
cmd.environment['HOME'] = ENV.fetch('HOME', '/root')
|
||||
cmd.run_command
|
||||
begin
|
||||
cmd.error!
|
||||
cmd.stdout
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def cib_object_exists?(name)
|
||||
dfn = get_cib_object_definition(name)
|
||||
!! (dfn && ! dfn.empty?)
|
||||
end
|
||||
|
||||
def cib_object_type(obj_definition)
|
||||
unless obj_definition =~ /\A(\w+)\s/
|
||||
raise "Couldn't extract CIB object type from '#{obj_definition}'"
|
||||
end
|
||||
return $1
|
||||
end
|
||||
|
||||
def pacemaker_resource_running?(name)
|
||||
cmd = shell_out! "crm", "resource", "status", name
|
||||
Chef::Log.info cmd.stdout
|
||||
cmd.stdout.include? "resource #{name} is running"
|
||||
end
|
||||
|
||||
def resource_params_string(params)
|
||||
return "" if ! params or params.empty?
|
||||
s = " params"
|
||||
params.sort.each do |key, value|
|
||||
s << %' #{key}="#{value}"'
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
def resource_meta_string(meta)
|
||||
return "" if ! meta or meta.empty?
|
||||
s = " meta"
|
||||
meta.sort.each do |key, value|
|
||||
s << %' #{key}="#{value}"'
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
def resource_op_string(ops)
|
||||
return "" if ! ops or ops.empty?
|
||||
s = " op"
|
||||
ops.sort.each do |op, attrs|
|
||||
s << " #{op}"
|
||||
attrs.sort.each do |key, value|
|
||||
s << %' #{key}="#{value}"'
|
||||
end
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
# CIB object definitions look something like:
|
||||
#
|
||||
# primitive keystone ocf:openstack:keystone \
|
||||
# params os_username="crowbar" os_password="crowbar" os_tenant_name="openstack" \
|
||||
# meta target-role="Started" is-managed="true" \
|
||||
# op monitor interval="10" timeout=30s \
|
||||
# op start interval="10s" timeout="240" \
|
||||
#
|
||||
# This method extracts a Hash from one of the params / meta / op lines.
|
||||
def extract_hash(name, obj_definition, data_type)
|
||||
unless obj_definition =~ /^\s+#{data_type} (.+?)(\s*\\)?$/
|
||||
raise "Couldn't retrieve #{data_type} for '#{name}' CIB object from [#{obj_definition}]"
|
||||
end
|
||||
|
||||
h = {}
|
||||
Shellwords.split($1).each do |kvpair|
|
||||
unless kvpair =~ /^(.+?)=(.+)$/
|
||||
raise "Couldn't understand '#{kvpair}' for #{data_type} section of '#{name}' primitive"
|
||||
end
|
||||
h[$1] = $2.sub(/^"(.*)"$/, "\1")
|
||||
end
|
||||
h
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
2
libraries/pacemaker.rb
Normal file
2
libraries/pacemaker.rb
Normal file
@@ -0,0 +1,2 @@
|
||||
require_relative 'pacemaker/resource/primitive'
|
||||
require_relative 'pacemaker/resource/clone'
|
91
libraries/pacemaker/cib_object.rb
Normal file
91
libraries/pacemaker/cib_object.rb
Normal file
@@ -0,0 +1,91 @@
|
||||
require 'mixlib/shellout'
|
||||
|
||||
module Pacemaker
|
||||
class ObjectTypeMismatch < StandardError
|
||||
end
|
||||
|
||||
class CIBObject
|
||||
attr_accessor :name, :definition
|
||||
|
||||
@@subclasses = { }
|
||||
|
||||
class << self
|
||||
attr_reader :object_type
|
||||
|
||||
def register_type(type_name)
|
||||
@object_type = type_name
|
||||
@@subclasses[type_name] = self
|
||||
end
|
||||
|
||||
def get_definition(name)
|
||||
cmd = Mixlib::ShellOut.new("crm configure show #{name}")
|
||||
cmd.environment['HOME'] = ENV.fetch('HOME', '/root')
|
||||
cmd.run_command
|
||||
begin
|
||||
cmd.error!
|
||||
cmd.stdout
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def type(definition)
|
||||
unless definition =~ /\A(\w+)\s/
|
||||
raise "Couldn't extract CIB object type from '#{definition}'"
|
||||
end
|
||||
return $1
|
||||
end
|
||||
|
||||
def from_name(name)
|
||||
definition = get_definition(name)
|
||||
return nil unless definition
|
||||
obj_type = type(definition)
|
||||
subclass = @@subclasses[obj_type]
|
||||
unless subclass
|
||||
raise "No subclass of #{self.name} was registered with type '#{obj_type}'"
|
||||
end
|
||||
obj = subclass.from_definition(definition)
|
||||
unless name == obj.name
|
||||
raise "Name '#{obj.name}' in definition didn't match name '#{name}' used for retrieval"
|
||||
end
|
||||
obj
|
||||
end
|
||||
|
||||
def from_definition(definition)
|
||||
obj = new(name)
|
||||
obj.definition = definition
|
||||
obj.parse_definition
|
||||
obj
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(name)
|
||||
@name = name
|
||||
@definition = nil
|
||||
end
|
||||
|
||||
def load_definition
|
||||
@definition = self.class.get_definition(name)
|
||||
|
||||
if @definition and ! @definition.empty? and type != self.class.object_type
|
||||
raise ObjectTypeMismatch, "Expected #{self.class.object_type} type but loaded definition was type #{type}"
|
||||
end
|
||||
end
|
||||
|
||||
def parse_definition
|
||||
raise NotImplementedError, "#{self.class} must implement #parse_definition"
|
||||
end
|
||||
|
||||
def exists?
|
||||
!! (definition && ! definition.empty?)
|
||||
end
|
||||
|
||||
def type
|
||||
self.class.type(definition)
|
||||
end
|
||||
|
||||
def delete_command
|
||||
"crm configure delete '#{name}'"
|
||||
end
|
||||
end
|
||||
end
|
23
libraries/pacemaker/resource.rb
Normal file
23
libraries/pacemaker/resource.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
require 'chef/mixin/shell_out'
|
||||
require_relative 'cib_object'
|
||||
|
||||
module Pacemaker
|
||||
class Resource < Pacemaker::CIBObject
|
||||
include Chef::Mixin::ShellOut
|
||||
|
||||
def running?
|
||||
cmd = shell_out! "crm", "resource", "status", name
|
||||
Chef::Log.info cmd.stdout
|
||||
!! cmd.stdout.include?("resource #{name} is running")
|
||||
end
|
||||
|
||||
def start_command
|
||||
"crm resource start '#{name}'"
|
||||
end
|
||||
|
||||
def stop_command
|
||||
"crm resource stop '#{name}'"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
8
libraries/pacemaker/resource/clone.rb
Normal file
8
libraries/pacemaker/resource/clone.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
require_relative File::join(%w(.. resource))
|
||||
|
||||
class Pacemaker::Resource::Clone < Pacemaker::Resource
|
||||
register_type 'clone'
|
||||
|
||||
attr_accessor :primitive
|
||||
|
||||
end
|
124
libraries/pacemaker/resource/primitive.rb
Normal file
124
libraries/pacemaker/resource/primitive.rb
Normal file
@@ -0,0 +1,124 @@
|
||||
require 'shellwords'
|
||||
require_relative File::join(%w(.. resource))
|
||||
|
||||
class Pacemaker::Resource::Primitive < Pacemaker::Resource
|
||||
TYPE = 'primitive'
|
||||
|
||||
register_type TYPE
|
||||
|
||||
attr_accessor :agent, :params, :meta, :op
|
||||
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
|
||||
@agent = nil
|
||||
end
|
||||
|
||||
def self.from_chef_resource(resource)
|
||||
primitive = new(resource.name)
|
||||
%w(agent params meta op).each do |data|
|
||||
value = resource.send(data.to_sym)
|
||||
writer = (data + '=').to_sym
|
||||
primitive.send(writer, value)
|
||||
end
|
||||
return primitive
|
||||
end
|
||||
|
||||
def parse_definition
|
||||
unless definition =~ /\Aprimitive (\S+) (\S+)/
|
||||
raise RuntimeError, "Couldn't parse definition '#{definition}'"
|
||||
end
|
||||
self.name = $1
|
||||
self.agent = $2
|
||||
|
||||
%w(params meta).each do |data_type|
|
||||
hash = self.class.extract_hash(definition, data_type)
|
||||
writer = (data_type + '=').to_sym
|
||||
send(writer, hash)
|
||||
end
|
||||
|
||||
# FIXME: deal with op
|
||||
end
|
||||
|
||||
def params_string
|
||||
self.class.params_string(params)
|
||||
end
|
||||
|
||||
def meta_string
|
||||
self.class.meta_string(meta)
|
||||
end
|
||||
|
||||
def op_string
|
||||
self.class.op_string(op)
|
||||
end
|
||||
|
||||
def definition_string
|
||||
return <<EOF
|
||||
primitive #{name} #{agent} \\
|
||||
#{params_string} \\
|
||||
#{meta_string} \\
|
||||
#{op_string}
|
||||
EOF
|
||||
end
|
||||
|
||||
def crm_configure_command
|
||||
args = %w(crm configure primitive)
|
||||
args << [name, agent, params_string, meta_string, op_string]
|
||||
args.join " "
|
||||
end
|
||||
|
||||
def self.params_string(params)
|
||||
return "" if ! params or params.empty?
|
||||
s = " params"
|
||||
params.sort.each do |key, value|
|
||||
s << %' #{key}="#{value}"'
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
def self.meta_string(meta)
|
||||
return "" if ! meta or meta.empty?
|
||||
s = " meta"
|
||||
meta.sort.each do |key, value|
|
||||
s << %' #{key}="#{value}"'
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
def self.op_string(ops)
|
||||
return "" if ! ops or ops.empty?
|
||||
s = " op"
|
||||
ops.sort.each do |op, attrs|
|
||||
s << " #{op}"
|
||||
attrs.sort.each do |key, value|
|
||||
s << %' #{key}="#{value}"'
|
||||
end
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
# CIB object definitions look something like:
|
||||
#
|
||||
# primitive keystone ocf:openstack:keystone \
|
||||
# params os_username="crowbar" os_password="crowbar" os_tenant_name="openstack" \
|
||||
# meta target-role="Started" is-managed="true" \
|
||||
# op monitor interval="10" timeout=30s \
|
||||
# op start interval="10s" timeout="240" \
|
||||
#
|
||||
# This method extracts a Hash from one of the params / meta / op lines.
|
||||
def self.extract_hash(obj_definition, data_type)
|
||||
unless obj_definition =~ /^\s+#{data_type} (.+?)(\s*\\)?$/
|
||||
raise "Couldn't retrieve #{data_type} for '#{name}' CIB object from [#{obj_definition}]"
|
||||
end
|
||||
|
||||
h = {}
|
||||
Shellwords.split($1).each do |kvpair|
|
||||
unless kvpair =~ /^(.+?)=(.+)$/
|
||||
raise "Couldn't understand '#{kvpair}' for #{data_type} section of '#{name}' primitive"
|
||||
end
|
||||
h[$1] = $2.sub(/^"(.*)"$/, "\1")
|
||||
end
|
||||
h
|
||||
end
|
||||
|
||||
end
|
@@ -17,7 +17,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries cib_objects))
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries pacemaker cib_object))
|
||||
|
||||
action :create do
|
||||
name = new_resource.name
|
||||
|
@@ -17,7 +17,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries cib_objects))
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries pacemaker cib_object))
|
||||
|
||||
action :create do
|
||||
name = new_resource.name
|
||||
|
@@ -17,7 +17,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries cib_objects))
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries pacemaker cib_object))
|
||||
|
||||
action :create do
|
||||
name = new_resource.name
|
||||
|
@@ -17,7 +17,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries cib_objects))
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries pacemaker cib_object))
|
||||
|
||||
action :create do
|
||||
name = new_resource.name
|
||||
|
@@ -17,7 +17,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries cib_objects))
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries pacemaker cib_object))
|
||||
|
||||
action :create do
|
||||
name = new_resource.name
|
||||
|
@@ -17,9 +17,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries cib_objects))
|
||||
|
||||
include Chef::Libraries::Pacemaker::CIBObjects
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries pacemaker cib_object))
|
||||
|
||||
# For vagrant env, switch to the following 'require' command.
|
||||
#require "/srv/chef/file_store/cookbooks/pacemaker/providers/helper"
|
||||
@@ -43,10 +41,11 @@ end
|
||||
action :delete do
|
||||
name = new_resource.name
|
||||
next unless @current_resource
|
||||
if pacemaker_resource_running?(name)
|
||||
rsc = Pacemaker::Resource::Primitive.new(name)
|
||||
if rsc.running?
|
||||
raise "Cannot delete running resource primitive #{name}"
|
||||
end
|
||||
execute "crm configure delete #{name}" do
|
||||
execute rsc.delete_command do
|
||||
action :nothing
|
||||
end.run_action(:run)
|
||||
new_resource.updated_by_last_action(true)
|
||||
@@ -58,8 +57,9 @@ action :start do
|
||||
unless @current_resource
|
||||
raise "Cannot start non-existent resource primitive '#{name}'"
|
||||
end
|
||||
next if pacemaker_resource_running?(name)
|
||||
execute "crm resource start #{name}" do
|
||||
rsc = Pacemaker::Resource::Primitive.new(name)
|
||||
next if rsc.running?
|
||||
execute rsc.start_command do
|
||||
action :nothing
|
||||
end.run_action(:run)
|
||||
new_resource.updated_by_last_action(true)
|
||||
@@ -71,8 +71,9 @@ action :stop do
|
||||
unless @current_resource
|
||||
raise "Cannot stop non-existent resource primitive '#{name}'"
|
||||
end
|
||||
next unless pacemaker_resource_running?(name)
|
||||
execute "crm resource stop #{name}" do
|
||||
rsc = Pacemaker::Resource::Primitive.new(name)
|
||||
next unless rsc.running?
|
||||
execute rsc.stop_command do
|
||||
action :nothing
|
||||
end.run_action(:run)
|
||||
new_resource.updated_by_last_action(true)
|
||||
@@ -88,32 +89,36 @@ end
|
||||
def load_current_resource
|
||||
name = @new_resource.name
|
||||
|
||||
obj_definition = get_cib_object_definition(name)
|
||||
return if ! obj_definition or obj_definition.empty?
|
||||
Chef::Log.debug "CIB object definition #{obj_definition}"
|
||||
|
||||
unless obj_definition =~ /\Aprimitive #{name} (\S+)/
|
||||
Chef::Log.warn "Resource '#{name}' was not a primitive"
|
||||
primitive = Pacemaker::Resource::Primitive.new(name)
|
||||
begin
|
||||
primitive.load_definition
|
||||
rescue Pacemaker::ObjectTypeMismatch => e
|
||||
Chef::Log.warn e.message
|
||||
return
|
||||
end
|
||||
agent = $1
|
||||
|
||||
@current_resource_definition = obj_definition
|
||||
if ! primitive.definition or primitive.definition.empty?
|
||||
Chef::Log.debug "CIB object definition nil or empty"
|
||||
return
|
||||
end
|
||||
Chef::Log.debug "CIB object definition #{primitive.definition}"
|
||||
@current_resource_definition = primitive.definition
|
||||
primitive.parse_definition
|
||||
|
||||
@current_primitive = primitive
|
||||
@current_resource = Chef::Resource::PacemakerPrimitive.new(name)
|
||||
@current_resource.agent(agent)
|
||||
|
||||
@current_resource.agent(primitive.agent)
|
||||
%w(params meta).each do |data_type|
|
||||
h = extract_hash(name, obj_definition, data_type)
|
||||
@current_resource.send(data_type.to_sym, h)
|
||||
Chef::Log.debug "detected #{name} has #{data_type} #{h}"
|
||||
method = data_type.to_sym
|
||||
value = primitive.send(method)
|
||||
@current_resource.send(method, value)
|
||||
Chef::Log.debug "detected #{name} has #{data_type} #{value}"
|
||||
end
|
||||
end
|
||||
|
||||
def create_resource(name)
|
||||
cmd = "crm configure primitive #{name} #{new_resource.agent}"
|
||||
cmd << resource_params_string(new_resource.params)
|
||||
cmd << resource_meta_string(new_resource.meta)
|
||||
cmd << resource_op_string(new_resource.op)
|
||||
primitive = Pacemaker::Resource::Primitive.from_chef_resource(new_resource)
|
||||
cmd = primitive.crm_configure_command
|
||||
|
||||
Chef::Log.info "Creating new resource primitive #{name}"
|
||||
|
||||
@@ -121,7 +126,7 @@ def create_resource(name)
|
||||
action :nothing
|
||||
end.run_action(:run)
|
||||
|
||||
if cib_object_exists?(name)
|
||||
if primitive.exists?
|
||||
new_resource.updated_by_last_action(true)
|
||||
Chef::Log.info "Successfully configured primitive '#{name}'."
|
||||
else
|
||||
|
@@ -17,7 +17,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries cib_objects))
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. libraries pacemaker cib_object))
|
||||
|
||||
action :create do
|
||||
name = new_resource.name
|
||||
|
13
spec/helpers/clone_resource.rb
Normal file
13
spec/helpers/clone_resource.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
#require ::File.join(::File.dirname(__FILE__), *%w(.. .. libraries pacemaker clone))
|
||||
require_relative 'keystone_primitive'
|
||||
|
||||
module Chef::RSpec
|
||||
module Pacemaker
|
||||
module Config
|
||||
include Chef::RSpec::Pacemaker::Config
|
||||
|
||||
CLONE = ::Pacemaker::Clone.new('clone1')
|
||||
CLONE.primitive = KEYSTONE
|
||||
end
|
||||
end
|
||||
end
|
@@ -1,38 +0,0 @@
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. .. libraries cib_objects))
|
||||
|
||||
module Chef::RSpec
|
||||
module Pacemaker
|
||||
module Config
|
||||
extend Chef::Libraries::Pacemaker::CIBObjects
|
||||
|
||||
RA = {
|
||||
:name => "keystone",
|
||||
:agent => "ocf:openstack:keystone",
|
||||
:params => [
|
||||
[ "os_password", "adminpw" ],
|
||||
[ "os_auth_url", "http://node1:5000/v2.0" ],
|
||||
[ "os_username", "admin" ],
|
||||
[ "os_tenant_name", "openstack" ],
|
||||
[ "user", "openstack-keystone" ],
|
||||
],
|
||||
:meta => [
|
||||
[ "target-role", "Started" ],
|
||||
[ "is-managed", "true" ]
|
||||
],
|
||||
:op => [
|
||||
[ "monitor", { "timeout" => "60", "interval" => "10s" } ],
|
||||
[ "start", { "timeout" => "240", "interval" => "10s" } ]
|
||||
],
|
||||
}
|
||||
RA[:params_string] = resource_params_string(RA[:params])
|
||||
RA[:meta_string] = resource_meta_string(RA[:meta])
|
||||
RA[:op_string] = resource_op_string(RA[:op])
|
||||
RA[:config] = <<EOF
|
||||
primitive keystone ocf:openstack:keystone \\
|
||||
#{RA[:params_string]} \\
|
||||
#{RA[:meta_string]} \\
|
||||
#{RA[:op_string]}
|
||||
EOF
|
||||
end
|
||||
end
|
||||
end
|
31
spec/helpers/keystone_primitive.rb
Normal file
31
spec/helpers/keystone_primitive.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
require ::File.join(::File.dirname(__FILE__), *%w(.. .. libraries pacemaker resource primitive))
|
||||
|
||||
module Chef::RSpec
|
||||
module Pacemaker
|
||||
module Config
|
||||
KEYSTONE_PRIMITIVE = ::Pacemaker::Resource::Primitive.new('keystone')
|
||||
KEYSTONE_PRIMITIVE.agent = "ocf:openstack:keystone"
|
||||
KEYSTONE_PRIMITIVE.params = [
|
||||
[ "os_password", "adminpw" ],
|
||||
[ "os_auth_url", "http://node1:5000/v2.0" ],
|
||||
[ "os_username", "admin" ],
|
||||
[ "os_tenant_name", "openstack" ],
|
||||
[ "user", "openstack-keystone" ],
|
||||
]
|
||||
KEYSTONE_PRIMITIVE.meta = [
|
||||
[ "target-role", "Started" ],
|
||||
[ "is-managed", "true" ]
|
||||
]
|
||||
KEYSTONE_PRIMITIVE.op = [
|
||||
[ "monitor", { "timeout" => "60", "interval" => "10s" } ],
|
||||
[ "start", { "timeout" => "240", "interval" => "10s" } ]
|
||||
]
|
||||
KEYSTONE_PRIMITIVE_DEFINITION = <<'EOF'
|
||||
primitive keystone ocf:openstack:keystone \
|
||||
params os_auth_url="http://node1:5000/v2.0" os_password="adminpw" os_tenant_name="openstack" os_username="admin" user="openstack-keystone" \
|
||||
meta is-managed="true" target-role="Started" \
|
||||
op monitor interval="10s" timeout="60" start interval="10s" timeout="240"
|
||||
EOF
|
||||
end
|
||||
end
|
||||
end
|
112
spec/libraries/cib_object_spec.rb
Normal file
112
spec/libraries/cib_object_spec.rb
Normal file
@@ -0,0 +1,112 @@
|
||||
require 'spec_helper'
|
||||
require 'mixlib/shellout'
|
||||
|
||||
require_relative File.join(%w(.. .. libraries pacemaker))
|
||||
require_relative File.join(%w(.. helpers keystone_primitive))
|
||||
|
||||
describe Pacemaker::CIBObject do
|
||||
|
||||
before(:each) do
|
||||
Mixlib::ShellOut.any_instance.stub(:run_command)
|
||||
end
|
||||
|
||||
let(:cib_object) { Chef::RSpec::Pacemaker::Config::KEYSTONE_PRIMITIVE.dup }
|
||||
|
||||
#####################################################################
|
||||
# examples start here
|
||||
|
||||
context "no CIB object" do
|
||||
before(:each) do
|
||||
expect_any_instance_of(Mixlib::ShellOut) \
|
||||
.to receive(:error!) \
|
||||
.and_raise(RuntimeError)
|
||||
end
|
||||
|
||||
describe "#load_definition" do
|
||||
it "should return nil cluster config" do
|
||||
cib_object.load_definition
|
||||
expect(cib_object.definition).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#exists?" do
|
||||
it "should return false" do
|
||||
cib_object.load_definition
|
||||
expect(cib_object.exists?).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "keystone primitive resource CIB object" do
|
||||
before(:each) do
|
||||
Mixlib::ShellOut.any_instance.stub(:error!)
|
||||
expect_any_instance_of(Mixlib::ShellOut) \
|
||||
.to receive(:stdout) \
|
||||
.and_return(cib_object.definition_string)
|
||||
end
|
||||
|
||||
context "with definition loaded" do
|
||||
before(:each) do
|
||||
cib_object.load_definition
|
||||
end
|
||||
|
||||
describe "#exists?" do
|
||||
it "should return true" do
|
||||
expect(cib_object.exists?).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#load_definition" do
|
||||
it "should retrieve cluster config" do
|
||||
expect(cib_object.definition).to eq(cib_object.definition_string)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#type" do
|
||||
it "should return primitive" do
|
||||
expect(cib_object.type).to eq("primitive")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "::from_name" do
|
||||
it "should instantiate a Pacemaker::Resource::Primitive" do
|
||||
obj = Pacemaker::CIBObject.from_name(cib_object.name)
|
||||
expect(obj.is_a? Pacemaker::Resource::Primitive).to be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "CIB object with unregistered type" do
|
||||
before(:each) do
|
||||
Mixlib::ShellOut.any_instance.stub(:error!)
|
||||
end
|
||||
|
||||
describe "::from_name" do
|
||||
it "should refuse to instantiate from any subclass" do
|
||||
expect_any_instance_of(Mixlib::ShellOut) \
|
||||
.to receive(:stdout) \
|
||||
.and_return("unregistered #{cib_object.name} <definition>")
|
||||
expect {
|
||||
Pacemaker::CIBObject.from_name(cib_object.name)
|
||||
}.to raise_error "No subclass of Pacemaker::CIBObject was registered with type 'unregistered'"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "invalid CIB object definition" do
|
||||
before(:each) do
|
||||
Mixlib::ShellOut.any_instance.stub(:error!)
|
||||
expect_any_instance_of(Mixlib::ShellOut) \
|
||||
.to receive(:stdout) \
|
||||
.and_return("nonsense")
|
||||
end
|
||||
|
||||
describe "#type" do
|
||||
it "should raise an error without a valid definition" do
|
||||
expect { cib_object.load_definition }.to \
|
||||
raise_error(RuntimeError, "Couldn't extract CIB object type from 'nonsense'")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@@ -1,167 +0,0 @@
|
||||
require 'spec_helper'
|
||||
require_relative File.join(%w(.. .. libraries cib_objects))
|
||||
require_relative File.join(%w(.. helpers keystone_config))
|
||||
|
||||
describe Chef::Libraries::Pacemaker::CIBObjects do
|
||||
include Chef::Libraries::Pacemaker::CIBObjects
|
||||
|
||||
shared_context "shellout stubs" do
|
||||
before(:each) do
|
||||
Mixlib::ShellOut.any_instance.stub(:run_command)
|
||||
end
|
||||
end
|
||||
|
||||
shared_context "keystone config" do
|
||||
let(:ra) { Chef::RSpec::Pacemaker::Config::RA }
|
||||
end
|
||||
|
||||
shared_context "keystone primitive" do
|
||||
include_context "shellout stubs"
|
||||
include_context "keystone config"
|
||||
|
||||
before(:each) do
|
||||
Mixlib::ShellOut.any_instance.stub(:error!)
|
||||
expect_any_instance_of(Mixlib::ShellOut) \
|
||||
.to receive(:stdout) \
|
||||
.and_return(ra[:config])
|
||||
end
|
||||
end
|
||||
|
||||
shared_context "no keystone primitive" do
|
||||
include_context "shellout stubs"
|
||||
before(:each) do
|
||||
expect_any_instance_of(Mixlib::ShellOut) \
|
||||
.to receive(:error!) \
|
||||
.and_raise(RuntimeError)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#get_cib_object_definition" do
|
||||
include_context "keystone primitive"
|
||||
|
||||
it "should retrieve cluster config" do
|
||||
expect(get_cib_object_definition("keystone")).to eq(ra[:config])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#get_cib_object_definition" do
|
||||
include_context "no keystone primitive"
|
||||
|
||||
it "should return nil cluster config" do
|
||||
expect(get_cib_object_definition("keystone")).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#cib_object_exists?" do
|
||||
include_context "keystone primitive"
|
||||
|
||||
it "should return true" do
|
||||
expect(cib_object_exists?("keystone")).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#cib_object_exists?" do
|
||||
include_context "no keystone primitive"
|
||||
|
||||
it "should return false" do
|
||||
expect(cib_object_exists?("keystone")).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#cib_object_type" do
|
||||
include_context "keystone config"
|
||||
|
||||
it "should return primitive" do
|
||||
expect(cib_object_type(ra[:config])).to eq("primitive")
|
||||
end
|
||||
|
||||
it "should raise an error without valid config" do
|
||||
expect { cib_object_type("nonsense") }.to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe "#pacemaker_resource_running?" do
|
||||
before(:each) do
|
||||
@cmd = double(Mixlib::ShellOut)
|
||||
expect(self).to receive(:shell_out!) \
|
||||
.with(*%w(crm resource status keystone)).ordered \
|
||||
.and_return(@cmd)
|
||||
end
|
||||
|
||||
it "should return true" do
|
||||
expect(@cmd).to receive(:stdout).at_least(:once).and_return("resource keystone is running")
|
||||
expect(pacemaker_resource_running?("keystone")).to be(true)
|
||||
end
|
||||
|
||||
it "should return false" do
|
||||
expect(@cmd).to receive(:stdout).at_least(:once).and_return("resource keystone is not running")
|
||||
expect(pacemaker_resource_running?("keystone")).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#resource_params_string" do
|
||||
it "should return empty string with nil params" do
|
||||
expect(resource_params_string(nil)).to eq("")
|
||||
end
|
||||
|
||||
it "should return empty string with empty params" do
|
||||
expect(resource_params_string({})).to eq("")
|
||||
end
|
||||
|
||||
it "should return a resource params string" do
|
||||
params = {
|
||||
"foo" => "bar",
|
||||
"baz" => "qux",
|
||||
}
|
||||
expect(resource_params_string(params)).to eq(%' params baz="qux" foo="bar"')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#resource_meta_string" do
|
||||
it "should return empty string with nil meta" do
|
||||
expect(resource_meta_string(nil)).to eq("")
|
||||
end
|
||||
|
||||
it "should return empty string with empty meta" do
|
||||
expect(resource_meta_string({})).to eq("")
|
||||
end
|
||||
|
||||
it "should return a resource meta string" do
|
||||
meta = {
|
||||
"foo" => "bar",
|
||||
"baz" => "qux",
|
||||
}
|
||||
expect(resource_meta_string(meta)).to eq(%' meta baz="qux" foo="bar"')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#resource_op_string" do
|
||||
it "should return empty string with nil op" do
|
||||
expect(resource_op_string(nil)).to eq("")
|
||||
end
|
||||
|
||||
it "should return empty string with empty op" do
|
||||
expect(resource_op_string({})).to eq("")
|
||||
end
|
||||
|
||||
it "should return a resource op string" do
|
||||
op = {
|
||||
"monitor" => {
|
||||
"foo" => "bar",
|
||||
"baz" => "qux",
|
||||
}
|
||||
}
|
||||
expect(resource_op_string(op)).to eq(%' op monitor baz="qux" foo="bar"')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#extract_hash" do
|
||||
include_context "keystone config"
|
||||
|
||||
it "should extract a hash from config" do
|
||||
expect(extract_hash("keystone", ra[:config], "params")).to eq(Hash[ra[:params]])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
108
spec/libraries/primitive_spec.rb
Normal file
108
spec/libraries/primitive_spec.rb
Normal file
@@ -0,0 +1,108 @@
|
||||
require 'spec_helper'
|
||||
require_relative File.join(%w(.. .. libraries pacemaker resource primitive))
|
||||
require_relative File.join(%w(.. helpers keystone_primitive))
|
||||
|
||||
describe Pacemaker::Resource::Primitive do
|
||||
before(:each) do
|
||||
@primitive = Chef::RSpec::Pacemaker::Config::KEYSTONE_PRIMITIVE.dup
|
||||
Mixlib::ShellOut.any_instance.stub(:run_command)
|
||||
end
|
||||
|
||||
it "should barf if the loaded definition's type is not primitive" do
|
||||
Mixlib::ShellOut.any_instance.stub(:error!)
|
||||
expect_any_instance_of(Mixlib::ShellOut) \
|
||||
.to receive(:stdout) \
|
||||
.and_return("clone foo blah blah")
|
||||
expect { @primitive.load_definition }.to \
|
||||
raise_error(Pacemaker::ObjectTypeMismatch,
|
||||
"Expected primitive type but loaded definition was type clone")
|
||||
end
|
||||
|
||||
describe "#params_string" do
|
||||
it "should return empty string with nil params" do
|
||||
@primitive.params = nil
|
||||
expect(@primitive.params_string).to eq("")
|
||||
end
|
||||
|
||||
it "should return empty string with empty params" do
|
||||
@primitive.params = {}
|
||||
expect(@primitive.params_string).to eq("")
|
||||
end
|
||||
|
||||
it "should return a resource params string" do
|
||||
@primitive.params = {
|
||||
"foo" => "bar",
|
||||
"baz" => "qux",
|
||||
}
|
||||
expect(@primitive.params_string).to eq(%' params baz="qux" foo="bar"')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#meta_string" do
|
||||
it "should return empty string with nil meta" do
|
||||
@primitive.meta = nil
|
||||
expect(@primitive.meta_string).to eq("")
|
||||
end
|
||||
|
||||
it "should return empty string with empty meta" do
|
||||
@primitive.meta = {}
|
||||
expect(@primitive.meta_string).to eq("")
|
||||
end
|
||||
|
||||
it "should return a resource meta string" do
|
||||
@primitive.meta = {
|
||||
"foo" => "bar",
|
||||
"baz" => "qux",
|
||||
}
|
||||
expect(@primitive.meta_string).to eq(%' meta baz="qux" foo="bar"')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#op_string" do
|
||||
it "should return empty string with nil op" do
|
||||
@primitive.op = nil
|
||||
expect(@primitive.op_string).to eq("")
|
||||
end
|
||||
|
||||
it "should return empty string with empty op" do
|
||||
@primitive.op = {}
|
||||
expect(@primitive.op_string).to eq("")
|
||||
end
|
||||
|
||||
it "should return a resource op string" do
|
||||
@primitive.op = {
|
||||
"monitor" => {
|
||||
"foo" => "bar",
|
||||
"baz" => "qux",
|
||||
}
|
||||
}
|
||||
expect(@primitive.op_string).to eq(%' op monitor baz="qux" foo="bar"')
|
||||
end
|
||||
end
|
||||
|
||||
describe "::extract_hash" do
|
||||
it "should extract a hash from config" do
|
||||
expect(@primitive.class.extract_hash(@primitive.definition_string, "params")).to \
|
||||
eq(Hash[@primitive.params])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#definition_string" do
|
||||
it "should return the definition string" do
|
||||
expect(@primitive.definition_string).to \
|
||||
eq(Chef::RSpec::Pacemaker::Config::KEYSTONE_PRIMITIVE_DEFINITION)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#parse_definition" do
|
||||
before(:each) do
|
||||
@parsed = Pacemaker::Resource::Primitive.new(@primitive.name)
|
||||
@parsed.definition = Chef::RSpec::Pacemaker::Config::KEYSTONE_PRIMITIVE_DEFINITION
|
||||
@parsed.parse_definition
|
||||
end
|
||||
|
||||
it "should parse the agent" do
|
||||
expect(@parsed.agent).to eq(@primitive.agent)
|
||||
end
|
||||
end
|
||||
end
|
27
spec/libraries/resource_spec.rb
Normal file
27
spec/libraries/resource_spec.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
require 'spec_helper'
|
||||
require_relative File.join(%w(.. .. libraries pacemaker resource))
|
||||
|
||||
describe Pacemaker::Resource do
|
||||
describe "#running?" do
|
||||
let(:rsc) { Pacemaker::Resource.new('keystone') }
|
||||
|
||||
before(:each) do
|
||||
@cmd = double(Mixlib::ShellOut)
|
||||
expect(rsc).to receive(:shell_out!) \
|
||||
.with(*%w(crm resource status keystone)) \
|
||||
.and_return(@cmd)
|
||||
end
|
||||
|
||||
it "should return true" do
|
||||
expect(@cmd).to receive(:stdout).at_least(:once) \
|
||||
.and_return("resource #{rsc.name} is running on: d52-54-00-e5-6b-a0")
|
||||
expect(rsc.running?).to be(true)
|
||||
end
|
||||
|
||||
it "should return false" do
|
||||
expect(@cmd).to receive(:stdout).at_least(:once) \
|
||||
.and_return("resource #{rsc.name} is NOT running")
|
||||
expect(rsc.running?).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
@@ -1,12 +1,12 @@
|
||||
require 'chef/application'
|
||||
require_relative File.join(%w(.. spec_helper))
|
||||
require_relative File.join(%w(.. helpers keystone_config))
|
||||
require_relative File.join(%w(.. helpers keystone_primitive))
|
||||
|
||||
describe "Chef::Provider::PacemakerPrimitive" do
|
||||
# for use inside examples:
|
||||
let(:ra) { Chef::RSpec::Pacemaker::Config::RA }
|
||||
let(:rsc) { Chef::RSpec::Pacemaker::Config::KEYSTONE_PRIMITIVE }
|
||||
# for use outside examples (e.g. when invoking shared_examples)
|
||||
ra = Chef::RSpec::Pacemaker::Config::RA
|
||||
rsc = Chef::RSpec::Pacemaker::Config::KEYSTONE_PRIMITIVE
|
||||
|
||||
before(:each) do
|
||||
runner_opts = {
|
||||
@@ -17,27 +17,48 @@ describe "Chef::Provider::PacemakerPrimitive" do
|
||||
@node = @chef_run.node
|
||||
@run_context = @chef_run.run_context
|
||||
|
||||
@resource = Chef::Resource::PacemakerPrimitive.new(ra[:name], @run_context)
|
||||
@resource.agent ra[:agent]
|
||||
@resource.params Hash[ra[:params]]
|
||||
@resource.meta Hash[ra[:meta]]
|
||||
@resource.op Hash[ra[:op]]
|
||||
@resource = Chef::Resource::PacemakerPrimitive.new(rsc.name, @run_context)
|
||||
@resource.agent rsc.agent
|
||||
@resource.params Hash[rsc.params]
|
||||
@resource.meta Hash[rsc.meta]
|
||||
@resource.op Hash[rsc.op]
|
||||
end
|
||||
|
||||
let (:provider) { Chef::Provider::PacemakerPrimitive.new(@resource, @run_context) }
|
||||
|
||||
# "crm configure show" is executed by load_current_resource, and
|
||||
# again later on for the :create action, to see whether to create or
|
||||
# modify.
|
||||
def expect_definition(definition)
|
||||
Mixlib::ShellOut.any_instance.stub(:run_command)
|
||||
Mixlib::ShellOut.any_instance.stub(:error!)
|
||||
expect_any_instance_of(Mixlib::ShellOut) \
|
||||
.to receive(:stdout) \
|
||||
.and_return(definition)
|
||||
end
|
||||
|
||||
def expect_exists(exists)
|
||||
expect_any_instance_of(Pacemaker::Resource::Primitive) \
|
||||
.to receive(:exists?) \
|
||||
.and_return(exists)
|
||||
end
|
||||
|
||||
def expect_running(running)
|
||||
expect_any_instance_of(Pacemaker::Resource::Primitive) \
|
||||
.to receive(:running?) \
|
||||
.and_return(running)
|
||||
end
|
||||
|
||||
describe ":create action" do
|
||||
it "should modify the primitive if it already exists" do
|
||||
new_params = Hash[ra[:params]].merge("os_password" => "newpasswd")
|
||||
new_params = Hash[rsc.params].merge("os_password" => "newpasswd")
|
||||
new_params.delete("os_tenant_name")
|
||||
@resource.params new_params
|
||||
@resource.meta Hash[ra[:meta]].merge("target-role" => "Stopped")
|
||||
@resource.meta Hash[rsc.meta].merge("target-role" => "Stopped")
|
||||
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
# and later used to see whether to create or modify.
|
||||
expect(provider).to receive(:get_cib_object_definition).and_return(ra[:config])
|
||||
expect_definition(rsc.definition_string)
|
||||
|
||||
configure_cmd_prefix = "crm_resource --resource #{ra[:name]}"
|
||||
configure_cmd_prefix = "crm_resource --resource #{rsc.name}"
|
||||
expected_configure_cmd_args = [
|
||||
%'--set-parameter "os_password" --parameter-value "newpasswd"',
|
||||
%'--delete-parameter "os_tenant_name"',
|
||||
@@ -45,6 +66,7 @@ describe "Chef::Provider::PacemakerPrimitive" do
|
||||
]
|
||||
|
||||
provider.run_action :create
|
||||
|
||||
expected_configure_cmd_args.each do |args|
|
||||
cmd = configure_cmd_prefix + " " + args
|
||||
expect(@chef_run).to run_execute(cmd)
|
||||
@@ -53,33 +75,24 @@ describe "Chef::Provider::PacemakerPrimitive" do
|
||||
end
|
||||
|
||||
it "should create a primitive if it doesn't already exist" do
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
# and later used to see whether to create or modify.
|
||||
expect(provider).to receive(:get_cib_object_definition).and_return("")
|
||||
|
||||
# Later, the :create action calls cib_object_exists? to check
|
||||
expect_definition("")
|
||||
# Later, the :create action calls Pacemaker::Resource::Primitive#exists? to check
|
||||
# that creation succeeded.
|
||||
expect(provider).to receive(:cib_object_exists?).and_return(true)
|
||||
expect_exists(true)
|
||||
|
||||
provider.run_action :create
|
||||
|
||||
cmd = "crm configure primitive #{ra[:name]} #{ra[:agent]}" + \
|
||||
ra[:params_string] + ra[:meta_string] + ra[:op_string]
|
||||
expect(@chef_run).to run_execute(cmd)
|
||||
|
||||
expect(@chef_run).to run_execute(rsc.crm_configure_command)
|
||||
expect(@resource).to be_updated
|
||||
end
|
||||
|
||||
it "should barf if the primitive has the wrong agent" do
|
||||
it "should barf if the primitive is already defined with the wrong agent" do
|
||||
existing_agent = "ocf:openstack:something-else"
|
||||
config = ra[:config].sub(ra[:agent], existing_agent)
|
||||
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
# and later used to see whether to create or modify.
|
||||
expect(provider).to receive(:get_cib_object_definition).and_return(config)
|
||||
definition = rsc.definition_string.sub(rsc.agent, existing_agent)
|
||||
expect_definition(definition)
|
||||
|
||||
expected_error = \
|
||||
"Existing resource primitive '#{ra[:name]}' has agent '#{existing_agent}' " \
|
||||
"Existing resource primitive '#{rsc.name}' has agent '#{existing_agent}' " \
|
||||
"but recipe wanted '#{@resource.agent}'"
|
||||
expect { provider.run_action :create }.to \
|
||||
raise_error(RuntimeError, expected_error)
|
||||
@@ -90,8 +103,7 @@ describe "Chef::Provider::PacemakerPrimitive" do
|
||||
|
||||
shared_examples "action on non-existent resource" do |action, cmd, expected_error|
|
||||
it "should not attempt to #{action.to_s} a non-existent resource" do
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
expect(provider).to receive(:get_cib_object_definition).once.and_return("")
|
||||
expect_definition("")
|
||||
|
||||
if expected_error
|
||||
expect { provider.run_action action }.to \
|
||||
@@ -107,28 +119,28 @@ describe "Chef::Provider::PacemakerPrimitive" do
|
||||
|
||||
describe ":delete action" do
|
||||
it_should_behave_like "action on non-existent resource", \
|
||||
:delete, "crm configure delete #{ra[:name]}", nil
|
||||
:delete, "crm configure delete #{rsc.name}", nil
|
||||
|
||||
it "should not delete a running resource" do
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
expect(provider).to receive(:get_cib_object_definition).once.and_return(ra[:config])
|
||||
expect_definition(rsc.definition_string)
|
||||
expect_running(true)
|
||||
|
||||
expect(provider).to receive(:pacemaker_resource_running?).once.and_return(true)
|
||||
cmd = "crm configure delete #{ra[:name]}"
|
||||
expected_error = "Cannot delete running resource primitive #{ra[:name]}"
|
||||
expected_error = "Cannot delete running resource primitive #{rsc.name}"
|
||||
expect { provider.run_action :delete }.to \
|
||||
raise_error(RuntimeError, expected_error)
|
||||
|
||||
cmd = "crm configure delete '#{rsc.name}'"
|
||||
expect(@chef_run).not_to run_execute(cmd)
|
||||
expect(@resource).not_to be_updated
|
||||
end
|
||||
|
||||
it "should delete a non-running resource" do
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
expect(provider).to receive(:get_cib_object_definition).once.and_return(ra[:config])
|
||||
expect_definition(rsc.definition_string)
|
||||
expect_running(false)
|
||||
|
||||
expect(provider).to receive(:pacemaker_resource_running?).once.and_return(false)
|
||||
cmd = "crm configure delete #{ra[:name]}"
|
||||
provider.run_action :delete
|
||||
|
||||
cmd = "crm configure delete '#{rsc.name}'"
|
||||
expect(@chef_run).to run_execute(cmd)
|
||||
expect(@resource).to be_updated
|
||||
end
|
||||
@@ -137,30 +149,28 @@ describe "Chef::Provider::PacemakerPrimitive" do
|
||||
describe ":start action" do
|
||||
it_should_behave_like "action on non-existent resource", \
|
||||
:start,
|
||||
"crm resource start #{ra[:name]}", \
|
||||
"Cannot start non-existent resource primitive '#{ra[:name]}'"
|
||||
"crm resource start #{rsc.name}", \
|
||||
"Cannot start non-existent resource primitive '#{rsc.name}'"
|
||||
|
||||
it "should do nothing to a started resource" do
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
expect(provider).to receive(:get_cib_object_definition).and_return(ra[:config])
|
||||
expect_definition(rsc.definition_string)
|
||||
expect_running(true)
|
||||
|
||||
expect(provider).to receive(:pacemaker_resource_running?).once.and_return(true)
|
||||
|
||||
cmd = "crm resource start #{ra[:name]}"
|
||||
provider.run_action :start
|
||||
|
||||
cmd = "crm resource start #{rsc.name}"
|
||||
expect(@chef_run).not_to run_execute(cmd)
|
||||
expect(@resource).not_to be_updated
|
||||
end
|
||||
|
||||
it "should start a stopped resource" do
|
||||
config = ra[:config].sub("Started", "Stopped")
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
expect(provider).to receive(:get_cib_object_definition).and_return(config)
|
||||
config = rsc.definition_string.sub("Started", "Stopped")
|
||||
expect_definition(config)
|
||||
expect_running(false)
|
||||
|
||||
expect(provider).to receive(:pacemaker_resource_running?).once.and_return(false)
|
||||
|
||||
cmd = "crm resource start #{ra[:name]}"
|
||||
provider.run_action :start
|
||||
|
||||
cmd = "crm resource start '#{rsc.name}'"
|
||||
expect(@chef_run).to run_execute(cmd)
|
||||
expect(@resource).to be_updated
|
||||
end
|
||||
@@ -169,29 +179,27 @@ describe "Chef::Provider::PacemakerPrimitive" do
|
||||
describe ":stop action" do
|
||||
it_should_behave_like "action on non-existent resource", \
|
||||
:stop,
|
||||
"crm resource stop #{ra[:name]}", \
|
||||
"Cannot stop non-existent resource primitive '#{ra[:name]}'"
|
||||
"crm resource stop #{rsc.name}", \
|
||||
"Cannot stop non-existent resource primitive '#{rsc.name}'"
|
||||
|
||||
it "should do nothing to a stopped resource" do
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
expect(provider).to receive(:get_cib_object_definition).and_return(ra[:config])
|
||||
expect_definition(rsc.definition_string)
|
||||
expect_running(false)
|
||||
|
||||
expect(provider).to receive(:pacemaker_resource_running?).once.and_return(false)
|
||||
|
||||
cmd = "crm resource start #{ra[:name]}"
|
||||
provider.run_action :stop
|
||||
|
||||
cmd = "crm resource start #{rsc.name}"
|
||||
expect(@chef_run).not_to run_execute(cmd)
|
||||
expect(@resource).not_to be_updated
|
||||
end
|
||||
|
||||
it "should stop a started resource" do
|
||||
# get_cib_object_definition is invoked by load_current_resource
|
||||
expect(provider).to receive(:get_cib_object_definition).and_return(ra[:config])
|
||||
expect_definition(rsc.definition_string)
|
||||
expect_running(true)
|
||||
|
||||
expect(provider).to receive(:pacemaker_resource_running?).once.and_return(true)
|
||||
|
||||
cmd = "crm resource stop #{ra[:name]}"
|
||||
provider.run_action :stop
|
||||
|
||||
cmd = "crm resource stop '#{rsc.name}'"
|
||||
expect(@chef_run).to run_execute(cmd)
|
||||
expect(@resource).to be_updated
|
||||
end
|
||||
|
@@ -17,7 +17,7 @@ RSpec.configure do |config|
|
||||
#config.role_path = '/var/roles'
|
||||
|
||||
# Specify the Chef log_level (default: :warn)
|
||||
#config.log_level = :debug
|
||||
config.log_level = ENV['CHEF_LOG_LEVEL'].to_sym if ENV['CHEF_LOG_LEVEL']
|
||||
|
||||
# Specify the path to a local JSON file with Ohai data (default: nil)
|
||||
#config.path = 'ohai.json'
|
||||
|
Reference in New Issue
Block a user