I am trying to build a function that accepts parameters to override defaults but I keep getting "null".
I have written a simple function:
// vars/Run.groovy
def test(String type, String parallel = 'yes') {
println(type)
println(parallel)
}
My pipeline looks like this:
node('master') {
Run.test('unit')
Run.test('unit', parallel = 'no')
}
The result I get is:
unit
yes
unit
null
What am I missing?
You just have to pass the value. This will override your default value.
Run.test('unit', 'no')
Related
I have jenkinsfile with defined Globals varible for timeout
class Globals {
static String TEST_TIMEOUT = ""
}
I am using functions from shared library
I am using the global variable to set a timeout for function. Since the shared library used by other projects that doesn't define the Globals variable I defined environment variable in the function file to be used as default value for time out.
env.TESTS_TIME_OUT="10080"
Then in function I want to check if Globals variable exists, I want to use the value as time out, if not the to use the default value.
if(Globals.TEST_TIMEOUT){
env.TESTS_TIME_OUT= "${Globals.TEST_TIMEOUT}"
}
timeout(time: "${env.TESTS_TIME_OUT}", unit: 'MINUTES') {
.
.
.
}
I`ve done it before with success on env parameters, but this time I am getting an error
No such field found: field java.lang.Class TEST_TIMEOUT
Any ideas how to solve this ? Or Any other way to check if Globals variable exists ?
Thank you
You can catch groovy.lang.MissingPropertyException which will be thrown if either Globals or Globals.TEST_TIMEOUT does not exist:
try {
env.TESTS_TIME_OUT = Globals.TEST_TIMEOUT
}
catch( groovy.lang.MissingPropertyException e ) {
env.TESTS_TIME_OUT = "10080"
}
You could even move this pattern into a generic function...
def getPropOrDefault( Closure c, def defaultVal ) {
try {
return c()
}
catch( groovy.lang.MissingPropertyException e ) {
return defaultVal
}
}
... which could be called like this:
env.TESTS_TIME_OUT = getPropOrDefault({ Globals.TEST_TIMEOUT }, '10080')
This could be useful if there are many different globals that you want to treat similar. Safes you from writing many try/catch blocks.
The closure is required to make sure that the expression Globals.TEST_TIMEOUT will be evaluated inside of the try/catch block of getPropOrDefault instead of before the function call.
In Jenkins pipelines, if I assign any key-value to env, I can access it like normal variables in string interpolation and environment variables in shell script. How does this work?
I see the probable implementation here but can't figure out how it works.
[Update]
In below code snippet, I can access the env properties without accessor -->
node {
stage('Preparation') {
env.foo = "bar"
echo "foo is $foo"
}
}
I haven't delved into the Jenkins code, but you could implement something like this by implementing the propertyMissing() method in a class, which would write to the script binding. The propertyMissing method gets called when the code is trying to access a property that is not declared in the class.
class MyEnv {
groovy.lang.Script script
MyEnv( groovy.lang.Script script ) {
this.script = script
}
def propertyMissing( String name ) {
script.getProperty( name )
}
def propertyMissing( String name, value ) {
script.setProperty( name, value )
}
}
def env = new MyEnv( this ) // pass the script context to the class
env.foo = 42 // actually assigns to the script binding
println "env.foo: $env.foo" // prints 42
println "foo: $foo" // prints 42
// It also works the other way around...
foo = 21 // assign to the script binding (Note: "def foo" would not work!)
println "env.foo: $env.foo" // prints 21
Is it possible to have a single .groovy file that has some utility functions defined and have one of those functions call another in that file?
note: for context, this is being used for Jenkins Pipeline library under vars folder. I wanted to have a function used for param validation call another function in the same groovy script file.
i.e. have the someFunction make use of the doSomething function, some pseudo code below.
//utils.groovy
def doSomething(def a) {
def aPrime = a
if (a == 'somethingSpecial') {
//handle it
//some logic goes here
aPrime = b
}
return aPrime
}
def someFunction(def x) {
y = doSomething(x);
more stuff.. using y
return someResult
}
def dodad() {
...
}
def whatsIt(){
...
}
In my actual code I get error like No signature of method: groovysh_evaluate.myCommonFunct() is applicable for argument types: () values: []
Nevermind this does work.
I got the error when I tried to run the contents of the file locally in groovysh. But no errors when it ran in the Jenkins pipeline
Hi!
I need to pass data from one step to another in a Jenkins pipeline. Something like this:
node {
// myPipelineStep is "my" own hello world pipeline step based on hello-world archetype, and I want it to return a variable that I have inside the plugin
def return_value = myPipelineStep inputVariable: value
// Then I want to do something else, a new step, where I use this value
sh 'echo $return_value'
//But the problem is I dont know how to return something from my pipeline step
}
But in the archetype empty-plugin the perform()-function where the action should take place is void.. So it is not possible to return something here.
And the same goes for the hello-world acrhetype.
Anyone with any leads?
Can you modify what is in the method ?? if so, create a global variable outside and assign the value inside the method.
Now the variable will have the value and you can use it in the other method
E.g.
node{
def isVaild
void perform(.....) {
//do stuff
isValid =true;
}
#Override
void perform(.....) {
//do stuff
if(isValid){
}
}
}
It should work :)
So the problem is, I am not able to get the default value for controllerIP variable using the getControllerIP method without calling setControllerIP. I tried similar groovy code locally and it works, but not working on my jenkins server. Also tried lots of other combination in my groovy script but nothing worked.
Note that we are using Jenkins: pipeline shared groovy libraries plugin.
This is my pipeline job on Jenkins:
node{
def controllerParameters = new com.company.project.controller.DeploymentParameters() as Object
controllerParameters.setOSUsername('jenkins')
controllerParameters.setOSPassword('jenkins123')
controllerParameters.setBuildNumber(33)
//controllerParameters.setControllerIP('192.44.44.44')
//if I uncomment above line everything works fine but I need to get default value in a case
echo "I want the default value from other file"
controllerParameters.getControllerIP()
echo "my code hangs on above line"
}
This is my other file ../controller/DeploymentParameters.groovy
package com.company.project.controller
import groovy.transform.Field
def String osUsername
def String osPassword
#Field String controllerIP = "NotCreated" //tried few combinations
//Open Stack username
def String setOSUsername(String osUsername) {
this.osUsername = osUsername
}
def String getOSUsername() {
return this.osUsername
}
//Open Stack password
void setOSPassword(String osPassword) {
this.osPassword = osPassword
}
def String getOSPassword() {
return this.osPassword
}
//Open Stack floating ip of master vm
void setControllerIP(String controllerIP) {
this.controllerIP = controllerIP
}
def String getControllerIP() {
return this.controllerIP
}
When groovy executes lines like this.osUsername = osUsername or return this.osUsername it actually calls getters and setters instead of direct field access.
So this:
def String getOSPassword() {
return this.osPassword
}
behaves like this:
def String getOSPassword() {
return this.getOsPassword()
}
And you code enters infinite recursion (same for setter and assignment).
Within your setters and getters you need to use Groovy direct field access operator
def String getOSPassword() {
return this.#osPassword
}