In a Jenkins Pipeline we want to create a config File with variable content and so we use StreamingTemplateEngine. Now we have to build a Config File with optional lines depending on the variable map. This example was our first try (during development / testing first written in plain groovy):
import groovy.text.StreamingTemplateEngine
def vars=[
"KEY2": "VAL2",
]
templateText='''
FIXKEY=FIXVAL
<%
if(KEY1) out.print "KEY1="+KEY1+"\\n";
if(KEY2) out.print "KEY2="+KEY2+"\\n";
%>
'''
def engine = new StreamingTemplateEngine()
def template=engine.createTemplate(templateText)
configContent = template.make(vars).toString()
println "CONTENT FROM TEMPLATE IS:"
println configContent;
So as "KEY1" does not exist in the map we wanted the resulting config String to be:
FIXKEY=FIXVAL
KEY2=VAL2
But we got this exception:
Exception in thread "main" groovy.text.TemplateExecutionException: Template execution error at line 4:
3: <%
--> 4: if(KEY1) out.print "KEY1="+KEY1+"\n";
5: if(KEY2) out.print "KEY2="+KEY2+"\n";
at main.run(main.groovy:34)
at main.main(main.groovy)
Caused by: groovy.lang.MissingPropertyException: No such property: KEY1 for class: groovy.tmp.templates.StreamingTemplateScript1
So we learned, that every variable used in the template has to be defined in the map, as this code works:
import groovy.text.StreamingTemplateEngine
def vars=[
"KEY1": "VAL1",
"KEY2": "VAL2",
]
templateText='''
FIXKEY=FIXVAL
<%
if(KEY1) out.print "KEY1="+KEY1+"\\n";
if(KEY2) out.print "KEY2="+KEY2+"\\n";
%>
'''
def engine = new StreamingTemplateEngine()
def template=engine.createTemplate(templateText)
configContent = template.make(vars).toString()
println "CONTENT FROM TEMPLATE IS:"
println configContent;
But results in:
FIXKEY=FIXVAL
KEY1=VAL1
KEY2=VAL2
Now we could define "KEY2":false in the map, but with a huge amount of vars this would be quite much more work as just to define the neccessary vars and leaving the not needed vars completely out.
After a bit of searching we found this:
StreamingTemplateEngine exception MissingPropertyException
We tried the second solution mentioned in this thread:
import groovy.text.StreamingTemplateEngine
def vars=[
"KEY2": "VAL2",
].withDefault { false }
templateText='''
FIXKEY=FIXVAL
<%
if(KEY1) out.print "KEY1="+KEY1+"\\n";
if(KEY2) out.print "KEY2="+KEY2+"\\n";
%>
'''
def engine = new StreamingTemplateEngine()
def template=engine.createTemplate(templateText)
configContent = template.make(vars).toString()
println "CONTENT FROM TEMPLATE IS:"
println configContent;
And that works as expected, the resulting config content is:
FIXKEY=FIXVAL
KEY2=VAL2
Perfect, we thought, so now we want to use this snippet in a Jenkins Pipeline, but Jenkins behaves somehow different using this test stage code:
import groovy.text.StreamingTemplateEngine
[...]
stage('test') {
def vars=[
"KEY2": "VAL2",
].withDefault { false }
templateText='''
FIXKEY=FIXVAL
<%
if(KEY1) out.print "KEY1="+KEY1+"\\n";
if(KEY2) out.print "KEY2="+KEY2+"\\n";
%>
'''
def engine = new StreamingTemplateEngine()
def template=engine.createTemplate(templateText)
configContent = template.make(vars).toString()
println "CONTENT FROM TEMPLATE IS:"
println configContent;
}
But the result in Jenkins is this:
[Pipeline] {
[Pipeline] stage
[Pipeline] { (test)
[Pipeline] echo
15:07:10 CONTENT FROM TEMPLATE IS:
[Pipeline] echo
15:07:10 false
[Pipeline] }
Notice the single "false" ??!!
When "completing" the map like this:
import groovy.text.StreamingTemplateEngine
[...]
stage('test') {
def vars=[
"KEY1": "VAL1",
"KEY2": "VAL2",
].withDefault { false }
templateText='''
FIXKEY=FIXVAL
<%
if(KEY1) out.print "KEY1="+KEY1+"\\n";
if(KEY2) out.print "KEY2="+KEY2+"\\n";
%>
'''
def engine = new StreamingTemplateEngine()
def template=engine.createTemplate(templateText)
configContent = template.make(vars).toString()
println "CONTENT FROM TEMPLATE IS:"
println configContent;
}
the content String is as expected:
[Pipeline] stage
[Pipeline] { (test)
[Pipeline] echo
15:09:06 CONTENT FROM TEMPLATE IS:
[Pipeline] echo
15:09:06
15:09:06 FIXKEY=FIXVAL
15:09:06 KEY1=VAL1
15:09:06 KEY2=VAL2
15:09:06
15:09:06
[Pipeline] }
So why does Jenkins Pipeline Groovy behave different with the same Code Snippet than "Plain" Groovy?
Or is there even a completely different approach to solve the request "variable lines based on var - existence in the map"?
Thx for any hint!
T0mcat