I came across a groovy syntax that creates a link in gsp file like this:
class LoginTagLib {
def loginControl = {
out << """[${link(action:"login",controller:"user"){"Login"}}]"""
}}
I know that it will eventually turned into this in html:
Login
However, there are 2 portion of the syntax that I don't understand:
I don't understand ${link(action:"login",controller:"user"){"Login"}}:
I get the $(), which is used for string interpolation.
I get the link(action:"login",controller:"user") too, just 2 arguments passed into link
but what is the {"Login"} doing behind?
I don't understand the """[ ]""" that is used to enclose the whole thing, I tried to take away a pair of ", but it wounldn't work anymore. So it proves to me it has it's significance.
Anybody help to shed some light?
Thanks
In groovy if the last argument of a function is a closure you can you change this syntax foo(arg1, arg2, ..., { ... }) to foo(arg1, arg2, ...) { ... }. this is what happens here, the last argument of link() is a closure that should evaluate to the textual representation of the link
''' and ''' allow for multi-line string. """ """ are the same but also support variable substitution
Related
I'm developing a shared library to execute it from my Jenkinsfile. This library has a function with optional parameters and I want to be able to execute this function with any number of parameters by specifying my value. I've been googling a lot, but couldn't find a good answer, so maybe somebody here could help me.
Example:
The function looks this way:
def doRequest(def moduleName=env.MODULE_NAME, def environment=env.ENVIRONMENT, def repoName=env.REPO_NAME) {
<some code goes here>
}
If I execute it from my Jenkinsfile this way:
script {
sendDeploymentStatistics.doRequest service_name
}
the function puts "service_name" value to the moduleName, but how do I specify "repoName" parameter?
In Python you would do it somehow like:
function_name(moduleName=service_name, repoName=repo_name)
but in Groovy + Jenkinsfile I can't find the right way.
Can anybody please help me to find out the right syntax?
Thank you!
Groovy has the concept of Default Parameters. If you change the order of the parameters, such that the environment comes last:
def doRequest(def moduleName=env.MODULE_NAME, def repoName=env.REPO_NAME, def environment=env.ENVIRONMENT) {
<some code goes here>
}
Then your call to function_name will take the default value for environment:
function_name(moduleName=service_name, repoName=repo_name)
Groovy however also has some sort of support for Named Parameters. It is not as nice as Python but you can get it to work as follows:
env = [MODULE_NAME: 'foo', ENVIRONMENT: 'bar', REPO_NAME: 'baz']
def doRequest(Map args = [:]) {
defaultMap = [moduleName: env.MODULE_NAME, environment: env.ENVIRONMENT, repoName: env.REPO_NAME]
args = defaultMap << args
return "${args.moduleName} ${args.environment} ${args.repoName}"
}
assert 'foo bar baz' == doRequest()
assert 'foo bar qux' == doRequest(repoName: 'qux')
assert '1 2 3' == doRequest(repoName: '3', moduleName: '1', environment: '2')
For Named Parameters you need a parameter of type Map (with a default value of the empty map). Groovy will then map the arguments upon calling the function to entries in a Map.
To use default values you need to create a map with the default values, and merge that defaultMap with the passed-in arguments.
Noob in Shared library,
I am puzzled with Jenkins document section 'Loading Libraries dynamically'.
Followed the Stackoverflow_answer, but I have some different needs, just wanted to call a function from library to pipeline with an argument.
Note: Jenkins library configuration is correct and library access is already checked with another example with call method
vars/foo.groovy contains function
//{Root}/vars/foo.groovy
def Foo_Func(Body){
Body= Body + "This is a Message from Shared Lib."
return Body
}
Body Variable is already defined into main Pipeline 'bar.jenkinsfile'
My real problem is how to call the function from foo.groovy without using call method,
I have tried following -
//somefolder_in_scm/bar.jenkinsfile
#Library('jenkins-shared-libs') _
def Body_Main=""
deg SUBJECT="Title 1"
def NativeReceivers = "abc#xyz.com"
pipeline{
node any
stage{
script {
/*Some script*/
}
}
post {
always {
script {
foo.Foo_Func(Body_Main)
// send email
emailext attachLog: true,
mimeType: 'text/html',
subject: SUBJECT,
body: Body_Main,
to: NativeReceivers
}
}
}
}
Since I have used _, I expect that no import needed.
Error which is occurred after triggering pipeline,
groovy.lang.MissingMethodException: No signature of method: java.lang.Class.Foo_Func() is applicable for argument types:
In the error, why function Foo_Func is treated as a class? It might possible that the argument need to be given in different way.
Any help is appreciated.
Have you tried declaring a Field ?
#groovy.transform.Field
def myVar = "something"
script.myScript.myVar
Assuming your file is myScript.groovy.
I am writing an shared lib too.
I think the problem is in the:
def Foo_Func(Body)
what works for me is:
def Foo_Func(Map Body)
so if you try:
def Foo_Func(String Body)
it should work. I think it can't find the function with the right signature.
def a = "a string"
def b = 'another'
Is there any difference? Or just like javascript to let's input ' and " easier in strings?
Single quotes are a standard java String
Double quotes are a templatable String, which will either return a GString if it is templated, or else a standard Java String. For example:
println 'hi'.class.name // prints java.lang.String
println "hi".class.name // prints java.lang.String
def a = 'Freewind'
println "hi $a" // prints "hi Freewind"
println "hi $a".class.name // prints org.codehaus.groovy.runtime.GStringImpl
If you try templating with single quoted strings, it doesn't do anything, so:
println 'hi $a' // prints "hi $a"
Also, the link given by julx in their answer is worth reading (esp. the part about GStrings not being Strings about 2/3 of the way down.
My understanding is that double-quoted string may contain embedded references to variables and other expressions. For example: "Hello $name", "Hello ${some-expression-here}". In this case a GString will be instantiated instead of a regular String. On the other hand single-quoted strings do not support this syntax and always result in a plain String. More on the topic here:
http://docs.groovy-lang.org/latest/html/documentation/index.html#all-strings
I know this is a very old question, but I wanted to add a caveat.
While it is correct that single (or triple single) quotes prevent interpolation in groovy, if you pass a shell command a single quoted string, the shell will perform parameter substitution, if the variable is an environment variable. Local variables or params will yield a bad substitution.
what is wrong with below code, comparing 2 strings in groovy
I am trying do the comparison between the 2 parameters in a single line to make it look tidier
if (params.dirname == ((params.path =~ ~/${params.dirname}/).with { matches() ? it[0] : null })) {
print success
}
Throwing Exception -
java.lang.NoSuchMethodError: No such DSL method 'matches' found among steps
There is no need to over-complicate your use case. According to:
params.dirname = hde, params.path = /usr/tmp/jenkins/hde/filename.txt or /usr/hde/jenkins/ing/filename.txt or any random path which has hde in it
you are trying to find if given string a contains substring b. It can be done using Java's method String.contains(String substring). Alternatively you can use regular expression for that, but String.contains() just looks a few times simpler to understand what is your intention. Consider following Groovy script:
def params = [
dirname: 'hde',
path: '/usr/tmp/jenkins/hde/filename.txt'
]
// Using String.contains()
if (params.path.contains(params.dirname)) {
println "Path '${params.path}' contains '${params.dirname}'"
}
// Using regular expression
if (params.path ==~ /(.*)${params.dirname}(.*)/) {
println "Path '${params.path}' contains '${params.dirname}'"
}
When you run it both if statements evaluates to true:
Path '/usr/tmp/jenkins/hde/filename.txt' contains 'hde'
Path '/usr/tmp/jenkins/hde/filename.txt' contains 'hde'
The following code will produce an assertion error
def foo(a,b,c='awesome',d=null) {
assert d
}
foo(1,2,d='bar')
Why does it give an error? Why is the keyword assignment of d not working? I find this very different from Python keyword argument.
Groovy doesn't do keyword arguments quite the same as python.
First, the syntax is map-like. Instead of
foo(1,2,d='bar')
you need
foo(1,2,d:'bar')
Second, groovy can't map the arguments to keywords by name. A way to accomplish this in groovy is to accept the keyword arguments as a map:
def foo(Map kwargs, a, b, c='awesome') { [a,b,c,kwargs.d] }
assert foo(1,2,d:'bar') == [1,2,'awesome','bar']
More details on how groovy handles this is here: http://groovy.codehaus.org/Extended+Guide+to+Method+Signatures.