diff --git a/acceptance/tests/language/resource_refs_with_nested_arrays.rb b/acceptance/tests/language/resource_refs_with_nested_arrays.rb new file mode 100644 index 000000000..7bc797885 --- /dev/null +++ b/acceptance/tests/language/resource_refs_with_nested_arrays.rb @@ -0,0 +1,27 @@ +test_name "#7681: Allow using array variables in resource references" + +test_manifest = < "echo the first command", + path => "/usr/bin:/bin", + logoutput => true, +} +exec { "second": + command => "echo the second command", + path => "/usr/bin:/bin", + logoutput => true, +} +exec { "third": + command => "echo the final command", + path => "/usr/bin:/bin", + logoutput => true, + require => Exec[$exec_names], +} +MANIFEST + +results = apply_manifest_on agents, test_manifest + +results.each do |result| + assert_match(/Exec\[third\].*the final command/, "#{result.stdout}") +end diff --git a/lib/puppet/parser/ast/resource_reference.rb b/lib/puppet/parser/ast/resource_reference.rb index 0f8e655bf..256a99d75 100644 --- a/lib/puppet/parser/ast/resource_reference.rb +++ b/lib/puppet/parser/ast/resource_reference.rb @@ -1,28 +1,28 @@ require 'puppet/parser/ast' require 'puppet/parser/ast/branch' class Puppet::Parser::AST::ResourceReference < Puppet::Parser::AST::Branch attr_accessor :title, :type # Evaluate our object, but just return a simple array of the type # and name. def evaluate(scope) - titles = Array(title.safeevaluate(scope)) + titles = Array(title.safeevaluate(scope)).flatten a_type, titles = scope.resolve_type_and_titles(type, titles) resources = titles.collect{ |a_title| Puppet::Resource.new(a_type, a_title) } return(resources.length == 1 ? resources.pop : resources) end def to_s if title.is_a?(Puppet::Parser::AST::ASTArray) "#{type.to_s.capitalize}#{title}" else "#{type.to_s.capitalize}[#{title}]" end end end diff --git a/spec/unit/parser/ast/resource_reference_spec.rb b/spec/unit/parser/ast/resource_reference_spec.rb index 627754dd1..4d1c191cf 100755 --- a/spec/unit/parser/ast/resource_reference_spec.rb +++ b/spec/unit/parser/ast/resource_reference_spec.rb @@ -1,40 +1,54 @@ #!/usr/bin/env rspec require 'spec_helper' describe Puppet::Parser::AST::ResourceReference do ast = Puppet::Parser::AST before :each do @scope = Puppet::Parser::Scope.new end + def ast_name(value) + Puppet::Parser::AST::Name.new(:value => value) + end + def newref(type, title) - title = stub 'title', :safeevaluate => title - ref = Puppet::Parser::AST::ResourceReference.new(:type => type, :title => title) + title_array = Puppet::Parser::AST::ASTArray.new(:children => [title]) + ref = Puppet::Parser::AST::ResourceReference.new(:type => type, :title => title_array) end it "should correctly produce reference strings" do - newref("File", "/tmp/yay").evaluate(@scope).to_s.should == "File[/tmp/yay]" + newref("File", ast_name("/tmp/yay")).evaluate(@scope).to_s.should == "File[/tmp/yay]" end it "should produce a single resource when the title evaluates to a string" do - newref("File", "/tmp/yay").evaluate(@scope).should == Puppet::Resource.new("file", "/tmp/yay") + newref("File", ast_name("/tmp/yay")).evaluate(@scope).should == Puppet::Resource.new("file", "/tmp/yay") end it "should return an array of resources if given an array of titles" do - titles = mock 'titles', :safeevaluate => ["title1","title2"] + titles = Puppet::Parser::AST::ASTArray.new(:children => [ast_name("title1"), ast_name("title2")]) ref = ast::ResourceReference.new( :title => titles, :type => "File" ) ref.evaluate(@scope).should == [ Puppet::Resource.new("file", "title1"), Puppet::Resource.new("file", "title2") ] end + it "should return an array of resources if given a variable containing an array of titles" do + @scope.setvar("my_files", ["foo", "bar"]) + titles = Puppet::Parser::AST::Variable.new(:value => "my_files") + ref = newref('File', titles) + ref.evaluate(@scope).should == [ + Puppet::Resource.new("file", "foo"), + Puppet::Resource.new("file", "bar") + ] + end + it "should return a correct representation when converting to string" do type = stub 'type', :is_a? => true, :to_s => "file" title = stub 'title', :is_a? => true, :to_s => "[/tmp/a, /tmp/b]" ast::ResourceReference.new( :type => type, :title => title ).to_s.should == "File[/tmp/a, /tmp/b]" end end