Bug #10547

inline_template newlines issue with ruby dsl

Added by Matthew Black over 1 year ago. Updated over 1 year ago.

Status:AcceptedStart date:11/04/2011
Priority:LowDue date:
Assignee:-% Done:

0%

Category:language
Target version:-
Affected Puppet version: Branch:
Keywords:ruby dsl

Description

When using an inline template, it does not like multiline statements.

The following example will throw an erb error when the master tries to compile it.

node “default” do

    temp = "<% scope.to_hash.keys.each do |k| %>\n<%= k %>\n<% end %>"
    file '/tmp/test.txt',
            :content => inline_template(temp)

end

If there are no newlines it will compile without issue.


Related issues

Related to Puppet - Feature #16937: Improved Ruby DSL Closed 10/11/2012

History

#1 Updated by Matthew Black over 1 year ago

Another interesting note is in puppet dsl inline_template behaves correctly and will compile the same template.

#2 Updated by Matthew Black over 1 year ago

I figured out a work around, which might be the solution instead of a bug, which is to do this

:content => inline_template([temp])

It is different behavior than the Puppet DSL counter part.

#3 Updated by Daniel Pittman over 1 year ago

  • Category set to language
  • Status changed from Unreviewed to Accepted
  • Assignee set to Randall Hansen
  • Keywords set to ruby dsl

Matthew Black wrote:

I figured out a work around, which might be the solution instead of a bug, which is to do this

:content => inline_template([temp])

It is different behavior than the Puppet DSL counter part.

Actually, that is identical behaviour to the Puppet DSL counterpart – it just looks different, because the Puppet DSL transparently wraps any argument in an array.

Thanks to the wonders of Ruby, though, there are some extra magic bits that make this extra-specially confusing:

The parser function is declared with a block taking a single argument, vals. With Ruby 1.9.2 or later this result in an inline_template function that accepts one and only one argument. With the Ruby 1.8 series, if you define a method from a block, and that block takes a single argument, Ruby transparently makes that an implicit *vals argument – it collects multiple arguments and turns them into an array, but only if you have more than one.

That means we have exciting DSL behaviour differences in that inline_template(part1, part2) will actually work as expected for a template with embedded newlines in Ruby 1.8, but it won’t with a single argument, because…

…the implementation uses vals.collect to iterate over the array of templates supplied, compiling each one, and then concatenates the result at the far end.

For the Puppet DSL use case this means that you get one or more strings in an array, and everything works as expected.

When the Ruby DSL invokes the method “incorrectly” – in the way that is natural from Ruby, but not actually what Puppet expects – you get the effect of calling String#collect, not Array#collect, which is implicitly String.split("\n").collect, and so tries to process every line of your input string as an independent template.

Fun fact, if you had newlines, but didn’t have any constructs that split template stuff over lines, it would work just fine. So, not only is this an awesome way to mess with people, it is a very difficult problem to build a mental model about the failure states of if you don’t read the implementation and know a bunch about how Ruby handles these objects.

This can be partly fixed by changing the method to work nicely from both the Ruby and Puppet DSL, but we should probably change the entire function calling prototype model that we use so that this doesn’t hit, eg, user defined parser functions in the same way.

#4 Updated by Daniel Pittman over 1 year ago

Randall, tagged to you because there are obvious UX implications, and integration between the Ruby and Puppet DSL is right in your space.

#5 Updated by Randall Hansen over 1 year ago

  • Assignee deleted (Randall Hansen)

#6 Updated by Randall Hansen over 1 year ago

  • Priority changed from Normal to Low

Also available in: Atom PDF