Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Split relationship matching into helper module
  • Loading branch information
rodjek committed Sep 19, 2017
commit ddf6ed402fc7daeba6d90b42afe5bda33f997772
1 change: 1 addition & 0 deletions lib/rspec-puppet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require 'fileutils'
require 'tmpdir'
require 'rspec-puppet/errors'
require 'rspec-puppet/helpers'
require 'rspec-puppet/matchers'
require 'rspec-puppet/example'
require 'rspec-puppet/setup'
Expand Down
6 changes: 6 additions & 0 deletions lib/rspec-puppet/helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module RSpec::Puppet
module Helpers
end
end

require 'rspec-puppet/helpers/relationships'
112 changes: 112 additions & 0 deletions lib/rspec-puppet/helpers/relationships.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
module RSpec::Puppet::Helpers
module Relationships
def resource_ref(resource)
resource.respond_to?(:to_ref) ? resource.to_ref : resource
end

def resource_from_ref(ref)
ref.is_a?(Puppet::Resource) ? ref : catalogue.resource(ref)
end

def canonicalize_resource(resource)
res = resource_from_ref(resource_ref(resource))

if res.nil?
resource = Struct.new(:type, :title).new(*catalogue.title_key_for_ref(resource)) if resource.is_a?(String)

res = catalogue.resource_keys.select { |type, title|
type == resource.type
}.map { |type, title|
catalogue.resource(type, title)
}.compact.find { |cat_res|
cat_res.builtin_type? && cat_res.uniqueness_key.first == resource.title
}
end

res
end

def canonicalize_resource_ref(ref)
resource_ref(resource_from_ref(ref))
end

def relationship_refs(resource, relationship_type, visited = Set.new)
resource = canonicalize_resource(resource)
results = Set.new
return results if resource.nil?

if visited.include?(resource.object_id)
return [canonicalize_resource_ref(resource)]
end

visited << resource.object_id

Array[resource[relationship_type]].flatten.compact.each do |r|
results << canonicalize_resource_ref(r)
results << relationship_refs(r, relationship_type, visited)

res = canonicalize_resource(r)
if res && res.builtin_type?
results << res.to_ref
results << "#{res.type.to_s.capitalize}[#{res.uniqueness_key.first}]"
end
end

# Add any autorequires
Puppet::Type.suppress_provider
if relationship_type == :require && resource.resource_type.respond_to?(:eachautorequire)
resource.resource_type.eachautorequire do |t, b|
Array(resource.to_ral.instance_eval(&b)).each do |dep|
res = "#{t.to_s.capitalize}[#{dep}]"

if r = relationship_refs(res, relationship_type, visited)
results << res
results << r
end
end
end
end
Puppet::Type.unsuppress_provider

results.flatten
end

def self_or_upstream(vertex)
[vertex] + catalogue.upstream_from_vertex(vertex).keys
end

def precedes?(first, second)
return false if first.nil? || second.nil?

self_or_upstream(first).each do |u|
self_or_upstream(second).each do |v|
before_refs = relationship_refs(u, :before) + relationship_refs(u, :notify)
require_refs = relationship_refs(v, :require) + relationship_refs(u, :subscribe)

if before_refs.include?(v.to_ref) || require_refs.include?(u.to_ref) || (before_refs & require_refs).any?
return true
end
end
end

false
end

def notifies?(first, second)
return false if first.nil? || second.nil?

self_or_upstream(first).each do |u|
self_or_upstream(second).each do |v|
notify_refs = relationship_refs(u, :notify)
subscribe_refs = relationship_refs(v, :subscribe)

if notify_refs.include?(v.to_ref) || subscribe_refs.include?(u.to_ref)
return true
end
end
end

false
end
end
end
111 changes: 3 additions & 108 deletions lib/rspec-puppet/matchers/create_generic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ module RSpec::Puppet
module ManifestMatchers
class CreateGeneric
include RSpec::Puppet::Errors
include RSpec::Puppet::Helpers::Relationships

attr_reader :catalogue

def initialize(*args, &block)
@exp_resource_type = args.shift.to_s.gsub(/^(create|contain)_/, '')
Expand Down Expand Up @@ -244,114 +247,6 @@ def check_subscribes(catalogue, resource)
end
end

def resource_ref(resource)
resource.respond_to?(:to_ref) ? resource.to_ref : resource
end

def resource_from_ref(ref)
ref.is_a?(Puppet::Resource) ? ref : @catalogue.resource(ref)
end

def canonicalize_resource(resource)
res = resource_from_ref(resource_ref(resource))
if res.nil?
resource = Struct.new(:type, :title).new(*@catalogue.title_key_for_ref(resource)) if resource.is_a?(String)
res = @catalogue.resource_keys.select { |type, name|
type == resource.type
}.map { |type, name|
@catalogue.resource(type, name)
}.compact.find { |cat_res|
cat_res.builtin_type? && cat_res.uniqueness_key.first == resource.title
}
end
res
end

def canonicalize_resource_ref(ref)
resource_ref(resource_from_ref(ref))
end

def relationship_refs(resource, type, visited = Set.new)
resource = canonicalize_resource(resource)
results = Set.new
return results unless resource

# guard to prevent infinite recursion
if visited.include?(resource.object_id)
return [canonicalize_resource_ref(resource)]
else
visited << resource.object_id
end

Array[resource[type]].flatten.compact.each do |r|
results << canonicalize_resource_ref(r)
results << relationship_refs(r, type, visited)

res = canonicalize_resource(r)
if res && res.builtin_type?
results << res.to_ref
results << "#{res.type.to_s.capitalize}[#{res.uniqueness_key.first}]"
end
end

Puppet::Type.suppress_provider
# Add autorequires if any
if type == :require and resource.resource_type.respond_to? :eachautorequire
resource.resource_type.eachautorequire do |t, b|
Array(resource.to_ral.instance_eval(&b)).each do |dep|
res = "#{t.to_s.capitalize}[#{dep}]"
if r = relationship_refs(res, type, visited)
results << res
results << r
end
end
end
end
Puppet::Type.unsuppress_provider

results.flatten
end

def self_or_upstream(vertex)
[vertex] + @catalogue.upstream_from_vertex(vertex).keys
end

def precedes?(first, second)
return false if first.nil? || second.nil?

self_or_upstream(first).each do |u|
self_or_upstream(second).each do |v|
before_refs = relationship_refs(u, :before) + relationship_refs(u, :notify)
require_refs = relationship_refs(v, :require) + relationship_refs(u, :subscribe)

if before_refs.include?(v.to_ref) || require_refs.include?(u.to_ref) || (before_refs & require_refs).any?
return true
end
end
end

# Nothing found
return false
end

def notifies?(first, second)
return false if first.nil? || second.nil?

self_or_upstream(first).each do |u|
self_or_upstream(second).each do |v|
notify_refs = relationship_refs(u, :notify)
subscribe_refs = relationship_refs(v, :subscribe)

if notify_refs.include?(v.to_ref) || subscribe_refs.include?(u.to_ref)
return true
end
end
end

# Nothing found
return false
end

# @param resource [Hash<Symbol, Object>] The resource in the catalog
# @param list [Array<String, Object>] The expected values of the resource
# @param type [:should, :not] Whether the given parameters should/not match
Expand Down