Dynamic parameter value depending on Jenkins agent label - jenkins

I got choice parameter defined in pipeline consisting of couple of items. I got 2 types of jenkins agents, each of the with custom label set on. Is it possible to set ordering of choice items depending on which agent is running pipeline. I'm thinking of sth like this:
def VALUES
pipeline {
agent {
label 'agentone || agenttwo'}
}
//not an actual code
if agent_name == agentone
VALUES=['item1', 'item2']
if agent_name == agentwo
VALUES=['item2', 'item1']
////////
.....
parameters {
choice(name: 'ITEMS', choices: "${VALUES}.join('\n')")
}
Thanks in advance for any suggestions.

Related

Using jenkins pipeline agent label based on parameter value choice

I have this example pipeline(part of it):
pipeline {
parameters {
choice(name: 'myParam', choices: ['1','2'], description: 'param desc')
}
options { timestamps () }
agent {
node {
label 'myLabel'
}
}
my question is this:
I would like to change myLabel for my agent label based on users choice of myParam.
in this case i want that when myParam is 1 then myLabel would be equal to "linux_first" and when myParam is 2 then myLabel would be "linux_second".
Does anyone know a way to do it?
Thanks in advance,
Alon
You can parameterize the agent this way in the declarative pipeline
properties([
string(description: 'build Agent', name: 'build_agent')
])
pipeline {
agent {
label params['build_agent']
}
stages {
// steps
}
}
Approach 1-
You can try "nodeLabelParameter" plugin. It might help you based on your requirement.
https://plugins.jenkins.io/nodelabelparameter/
This plugin adds two new parameter types to job configuration - node and label. The new parameters allow dynamic selection of the node or label where a job should be executed.
Approach 2-
Also Basic syntax would be to define parameter for pipeline and consume it.
agent {
label "${build_agent}"
}

Using same Jenkinsfile for two separate jobs in same repo

I have two separate Jenkins jobs that will run on one repository: My Jenkinsfile has a step that will run with this property enabled: enableZeroDownTime. The purpose of the 2nd Jenkins Job is to run the step with this property enableZeroDownTime disabled. Does anyone know how I can control it using the same Jenkinsfile? Can I pass that using some parameter based on any properties file? I am really confused on this.
stage('CreateCustomer') {
steps {
script {
common.runStage("#CreateCustomer")
common.runStage("#SetOnboardingCustomerManifest")
common.runStage("#enableZeroDownTime")
}
}
}
Solution
I currently run multiple pipelines that use the same Jenkinsfile. The change to conditionally execute a stage is trivial.
stage('CreateCustomer') {
when {
environment name: 'enableZeroDownTime', value: 'true'
}
steps {
script {
common.runStage("#CreateCustomer")
common.runStage("#SetOnboardingCustomerManifest")
common.runStage("#enableZeroDownTime")
}
}
}
The CreateCustomer stage will only run when the enableZeroDownTime parameter is set to true ( it can be a String parameter with value true, or a boolean parameter ).
The trick here is that you cannot add the parameters{} block to your declarative pipeline. For example if you had the following
parameters {
string(name: 'enableZeroDownTime', defaultValue: 'true')
}
Both pipelines would default to true. If you had the following
parameters {
string(name: 'enableZeroDownTime', defaultValue: '')
}
Both pipelines would default to a blank default value.
Even if you manually save a different default value to the pipeline after creation it will be overwritten next run with a blank default value.
Instead you simply need to remove the parameters{} block altogether and manually add the parameters through the web interface
Additionally...
Additionally it is possible to have two pipelines use the same Jenkinsfile with different parameters. For example, lets say Pipeline A had a enableZeroDownTime parameter defaulted to true and Pipeline B had no parameters at all. In this case you can add an environment variable of the same name and set the value equal to the following ternary expression
environment {
enableZeroDownTime = "${params.enableZeroDownTime != null ? "${params.enableZeroDownTime}" : false}"
}
You can then reference this parameter in the when declarative ( or anywhere in the pipeline ) without fear of the pipeline throwing a null pointer exception.

Execute a stage if environment variable contains specific substring

I have a jenkins declarative pipeline which I am interested to be able to perform a stage only if a specific environment variable contains a specific substring(not fully equals to it, just contains it).
Does anyone got any idea on how can I implement it(maybe using the when condition if possible).
Thanks in advance,
Alon
As you mentioned, in declarative pipeline you can use the when directive to establish a condition in which the stage will be executed.
Among the built in condition options like triggeredBy,branch and tag there is the generic expression option, which allows you to run any groovy code and calculate the relevant Boolean value according to your needs.
So for your case for example you can just use the groovy contains methods to achieve what you want, something like:
pipeline {
agent any
stages {
stage('Conditional Stage') {
when {
expression { return env.MyParamter.contains('MySubstring') }
}
steps {
echo "Running the conditional stage"
}
}
}
}

run 2 jobs with same jenkinsfile and different parameters

I want to configure 2 jobs in Jenkins that use the same jenkinsfile but the only difference is the parameters to these jobs.
for example:
create 2 jobs named: A and B that each one of them gets param of X.
in A the job get X as 1 and in B the X is 2.
I want to create it in this way instead of one job that has multi-checkbox because the jobs are independent and I don't want to leave any option to make mistakes.
How can I achieve that only via jenkinsfile?
I read about load jenkinsfile within other jenkinsfile but can't find a way to pass parameters.
How can I achieve this?
If you use Build with Parameters you can reference these declared parameters in the Jenkinsfile with this syntax ${PARAM}.
You could also declare a Choice Parameter named CHOICE in a declaritive pipeline it would look like this:
pipeline {
agent any
parameters {
choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
}
stages {
stage('Example') {
steps {
echo "Choice: ${params.CHOICE}"
}
}
}
}
You would not need 2 jobs this way. It is the same job but it runs with different configurations for CHOICE.
This example is directly taken from the official docs:
https://www.jenkins.io/doc/book/pipeline/syntax/#parameters
my solution was:
in Jenkins file to set
environment {
X= getX(env.JOB_NAME)
Y= getY(env.JOB_NAME)
}
and create the following functions in the end of pipeline:
def getX(jobName)
{
if (jobName.contains("X1"))
{
return "X1";
}
else return "X2";
}
def getY(jobName)
{
if (jobName.contains("BLA"))
{
return "BLA1";
}
return "BLA2";
}

Jenkins: Is there a way to list "labels" in a dropdown, to select one as a parameter?

I'm looking to have all of the defined node labels as a dropdown, so that I can select one to pass to the build as a parameter. Then in the build I'd loop through all the hosts in that label.
Similar functionality to what you're looking for is NodeLabel Parameter Plugin. You can use multi node selection or use labels, but not sure if you can use dropdown for labels (as I understand, dropdown can be used only for nodes).
So here's the answer I finally worked out
Use "Extensible choice parameter" as the parameter (Install plugin if needed)
Choice Provider : "System Groovy Choice Parameter"
Do not run in Sandbox
And here's the Groovy code
import jenkins.model.*
def labelAndNodeList = []
for (label in Jenkins.getInstance().getLabels()) {
labelAndNodeList.add(label)
}
return labelAndNodeList
And to expand on this a bit... Maybe you've called your parameter "Label"
and you now want to loop through the nodes that are assigned that label in a pipeline
Here's the pipeline code
def label = "${params.Label}"
listOfNodeNames = jenkins.model.Jenkins.instance.nodes.collect {
node -> node.getLabelString().contains(label) ? node.name : null
}
listOfNodeNames.removeAll(Collections.singleton(null))
for (node_to_run_on in listOfNodeNames) {
println "Node: ${node_to_run_on}"
node ("${node_to_run_on}") {
stage("Uname on ${node_to_run_on}") {
sh ("uname -a")
}
}
}

Resources