Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
55 changes: 38 additions & 17 deletions lib/puppet/parser/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -204,25 +204,25 @@ def evaluate_classes(classes, scope, lazy_evaluate = true, fqname = false)
class_parameters = classes
classes = classes.keys
end
classes.each do |name|
# If we can find the class, then make a resource that will evaluate it.
if klass = scope.find_hostclass(name, :assume_fqname => fqname)

# If parameters are passed, then attempt to create a duplicate resource
# so the appropriate error is thrown.
if class_parameters
resource = klass.ensure_in_catalog(scope, class_parameters[name] || {})
else
next if scope.class_scope(klass)
resource = klass.ensure_in_catalog(scope)
end

# If they've disabled lazy evaluation (which the :include function does),
# then evaluate our resource immediately.
resource.evaluate unless lazy_evaluate
else
raise Puppet::Error, "Could not find class #{name} for #{node.name}"
hostclasses = classes.collect do |name|
scope.find_hostclass(name, :assume_fqname => fqname) or raise Puppet::Error, "Could not find class #{name} for #{node.name}"
end

if class_parameters
resources = ensure_classes_with_parameters(scope, hostclasses, class_parameters)
if !lazy_evaluate
resources.each(&:evaluate)
end

resources
else
already_included, newly_included = ensure_classes_without_parameters(scope, hostclasses)
if !lazy_evaluate
newly_included.each(&:evaluate)
end

already_included + newly_included
end
end

Expand Down Expand Up @@ -299,6 +299,27 @@ def is_binder_active?

private

def ensure_classes_with_parameters(scope, hostclasses, parameters)
hostclasses.collect do |klass|
klass.ensure_in_catalog(scope, parameters[klass.name] || {})
end
end

def ensure_classes_without_parameters(scope, hostclasses)
already_included = []
newly_included = []
hostclasses.each do |klass|
class_scope = scope.class_scope(klass)
if class_scope
already_included << class_scope.resource
else
newly_included << klass.ensure_in_catalog(scope)
end
end

[already_included, newly_included]
end

# If ast nodes are enabled, then see if we can find and evaluate one.
def evaluate_ast_node
return unless ast_nodes?
Expand Down
10 changes: 5 additions & 5 deletions lib/puppet/parser/functions/contain.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
) do |classes|
scope = self

scope.function_include(classes)
containing_resource = scope.resource

classes.each do |class_name|
class_resource = scope.catalog.resource("Class", class_name)
if ! scope.catalog.edge?(scope.resource, class_resource)
scope.catalog.add_edge(scope.resource, class_resource)
included = scope.function_include(classes)
included.each do |resource|
if ! scope.catalog.edge?(containing_resource, resource)
scope.catalog.add_edge(containing_resource, resource)
end
end
end
34 changes: 8 additions & 26 deletions lib/puppet/parser/functions/include.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,12 @@
where they are declared. For that, see the `contain` function. It also
does not create a dependency relationship between the declared class and the
surrounding class; for that, see the `require` function.") do |vals|
if vals.is_a?(Array)
# Protect against array inside array
vals = vals.flatten
else
vals = [vals]
end

# The 'false' disables lazy evaluation.
klasses = compiler.evaluate_classes(vals, self, false)

missing = vals.find_all do |klass|
! klasses.include?(klass)
end

unless missing.empty?
# Throw an error if we didn't evaluate all of the classes.
str = "Could not find class"
str += "es" if missing.length > 1

str += " " + missing.join(", ")

if n = namespaces and ! n.empty? and n != [""]
str += " in namespaces #{@namespaces.join(", ")}"
end
self.fail Puppet::ParseError, str
end
if vals.is_a?(Array)
# Protect against array inside array
vals = vals.flatten
else
vals = [vals]
end

compiler.evaluate_classes(vals, self, false)
end
4 changes: 2 additions & 2 deletions spec/unit/parser/compiler_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ def compile
it "should skip classes that have already been evaluated" do
@compiler.catalog.stubs(:tag)

@scope.stubs(:class_scope).with(@class).returns("something")
@scope.stubs(:class_scope).with(@class).returns(@scope)

@compiler.expects(:add_resource).never

Expand All @@ -694,7 +694,7 @@ def compile
it "should skip classes previously evaluated with different capitalization" do
@compiler.catalog.stubs(:tag)
@scope.stubs(:find_hostclass).with("MyClass",{:assume_fqname => false}).returns(@class)
@scope.stubs(:class_scope).with(@class).returns("something")
@scope.stubs(:class_scope).with(@class).returns(@scope)
@compiler.expects(:add_resource).never
@resource.expects(:evaluate).never
Puppet::Parser::Resource.expects(:new).never
Expand Down
37 changes: 37 additions & 0 deletions spec/unit/parser/functions/contain_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
require 'puppet_spec/compiler'
require 'puppet/parser/functions'
require 'matchers/containment_matchers'
require 'matchers/resource'
require 'matchers/include_in_order'

describe 'The "contain" function' do
include PuppetSpec::Compiler
include ContainmentMatchers
include Matchers::Resource

it "includes the class" do
catalog = compile_to_catalog(<<-MANIFEST)
Expand All @@ -25,6 +27,41 @@ class container {
expect(catalog.classes).to include("contained")
end

it "includes the class when using a fully qualified anchored name" do
catalog = compile_to_catalog(<<-MANIFEST)
class contained {
notify { "contained": }
}

class container {
contain ::contained
}

include container
MANIFEST

expect(catalog.classes).to include("contained")
end

it "ensures that the edge is with the correct class" do
catalog = compile_to_catalog(<<-MANIFEST)
class outer {
class named { }
contain named
}

class named { }

include named
include outer
MANIFEST

expect(catalog).to have_resource("Class[Named]")
expect(catalog).to have_resource("Class[Outer]")
expect(catalog).to have_resource("Class[Outer::Named]")
expect(catalog).to contain_class("outer::named").in("outer")
end

it "makes the class contained in the current class" do
catalog = compile_to_catalog(<<-MANIFEST)
class contained {
Expand Down