Preview of snippet not rendered correctly

We use embedded Ruby to make our provisioning templates more dynamic; and it’s been working reliably, so thanks to the people who made this possible.

Problem:

We are experiencing a bug in the templates preview - or we need some more explanation. Developing snippet code (which isn’t yet used inside any template) on the fly by switching between editor and preview, the preview renders in some unexpected ways. Please see examples below.

Background: An external system (vRealize Orchestrator) writes the JSON-formatted host parameter “storages” to each host. A snippet is used to iterate over this structure. The aim is to use this information in order to format lvm-based disks automatically.

Expected outcome:

  1. Previewing below snippet for a host with below parameter, the sub-items contained in “storages” are only accessed if safe mode is enabled. In normal mode, only the “debug” line is rendered. Shouldn’t safe mode display less (potentially dangerous) code than normal mode?
  2. Notice the “print” line at the end of the snippet? It has no function, but if we leave it out the “debug” line is printed twice and the line which represents the output of the for loop disappears. Why that?
  3. As safe mode only shows the lines which would be printed encapsulated in brackets, is there a way to use normal mode, so that we could see the actual line breaks?

Foreman and Proxy versions:

both 3.5.3

Foreman and Proxy plugin versions:

not applicable

Distribution and version:

RHEL 8

Other relevant data:

example: parameter “storages”

[{"size":30,"mountpoint":"/","diskUuid":"6000C29..."},
{"size":50,"mountpoint":"/db","diskUuid":"6000C29..."},
{"size":10,"mountpoint":"/pkg","diskUuid":"6000C29..."}]

example: snippet “lvm”

<%#
kind: snippet
name: lvm
model: ProvisioningTemplate
snippet: true
-%>
<%# debug: check that the parameter is populated -%>
<%= host_param('storage') %>
<%=
lvm = host_param('storage')
for item in lvm do
  print item["size"]
  print item["mountpoint"]
  print item["diskUuid"]
end
print
%>

rendered preview (safe mode):

[{"size"=>30, "mountpoint"=>"/", "diskUuid"=>"6000C29..."}, {"size"=>50, "mountpoint"=>"/db", "diskUuid"=>"6000C29..."}, {"size"=>10, "mountpoint"=>"/pkg", "diskUuid"=>"6000C29..."}]
[30]["/"]["6000C29..."][50]["/db"]["6000C29..."][10]["/pkg"]["6000C29..."][]

The first thing I notice:
You are using a <%= tag for a block of logic and print statements, which is not how erb is intended to be used. What you probably wanted to do:

<% for item in host_param(storage) -%>
<%= item["size"] %>
<%= item["mountpoint"] %>
<%= item["diskUuid"] %>
<% end ->

Also, it seems you are misunderstanding, what safemode does. Safemode simply restricts which functions (and sometimes values of objects) are allowed in templates. It does not check your logic or similar.
You can find a lot of information on general template writing and the allowed methods for safemode rendering in the help tab of the template editing page.

1 Like

Thank you very much for this concise explanation, @areyus.

I wish we had found the solution ourselves because now it seems quite straightforward. Our past uses of Ruby in Foreman/ERB were less complex than this one, so here we just went ahead and put a “normal” Ruby script using print inside ERB tags. The decisive insight you provided us with is the fact that one can simply interrupt a sequence of Ruby instructions with <%= tags (we call them “squids”, btw) to print dynamic values. Now our snippet works as expected.

We did, however, understand that safe mode only restricts some functions, but without a good reference we could not be sure which of them. So you are right, the help tab is indeed a useful resource (especially for its examples). Up until this point we had been using the “Templates DSL” (Administer > About) as our main reference. Thanks again for your help. :slight_smile:

1 Like