Getting OR to work properly on Jenkins Pipeline - jenkins

I'm trying to disallow certain names to be used on a pipeline.
simply put: " If it is name1 or NAME1, ignore - otherwise, proceed"
But apparently it is not working properly. (still prints hello, according to the example)
It does work if I put "params.project != 'name1' || params.project != 'name1' " Which I really don't understand why.
What am I missing here ?
pipeline {
agent { label 'master'}
parameters {
string(defaultValue: '', description: '', name: 'project')
}
stages {
stage ('project stage') {
steps {
script {
if (params.project != 'name1' || params.project != 'NAME1')
println "Hello"
}
}
}
}
}
It is not duplicate of THIS since I'm trying to understand the logic behind this behavior.
In the end I went with
if (params.project!= 'name') {
if (params.project!= 'NAME1') {
}
}
But I believe there is a better way than that..
Update:
I found another way, which is to use contains
if (project.contains('name'))

If your objective is to disallow both values from being used for the project parameter, then you need the && logical operator ("and"):
if (params.project != 'name1' && params.project != 'NAME1')
This will prevent both values for the parameter as desired.
Alternatively, you could also use a regular expression similar to the following:
if !(params.project ==~ /name1|NAME1/) // =~ if instead do not want to additionally require type match

Related

Not able to compare the passwords in Jenkins Pipeline

I have a scenario where I am trying to check if the parameterised password value (which is entered while executing the pipeline) is equal or same as the password stored in credentials manager.
def ex(param){
currentBuild.result = 'ABORTED'
error('BAD PARAM: ' + param)
}
pipeline {
agent any
parameters {
password(name: 'key', description: 'Encryption key')
}
stages {
stage("check params") {
steps {
withCredentials([string(credentialsId: 'api_key', variable: 'api_key')]) {
script {
if ("${params.key}" != "$api_key") {ex("key")}
}
}
}
}
}
}
}
I tried comparing these values in different ways like
if ('${params.key}' != '$api_key') {ex("key")}
if ("${params.key}" != env.api_key) {ex("key")}
and so on
The credentials I am providing as parameters are correct.
If I check passwords by providing static value, it works properly
Ex
if ('${params.key}' != "my_secret_value") {ex("key")}
I tried lot of ways but nothing is working for me and I am not able to figure it out what's the issue and how will I able to check the if condition and compare the password.
I am troubleshooting this from a longer time.
Please help me out with this
Thanks in Advance

Multiple when clause inside single stage in Jenkins file

I want to put multiple when clause in a single stage. Here is the basic example
def foo = 0
pipeline {
agent any
stages {
stage('Hello') {
when {
expression {foo == 0}
}
steps {
echo 'foo is 0'
}
when {
expression {foo == 1}
}
steps {
echo 'foo is 1'
}
}
}
}
When I try this I recieve an error
Multiple occurrences of the when section
Actually my real problem is different but solving this will probably solve my real problem. Thanks in advance
It looks you'll be much better off using the directives as intended:
Multiple when is disallowed by design, if you looking a simple if else logic it's there:
Straghtforward if statement:
stage {
steps {
script {
if (foo == 0){
echo 'foo is 0'
}
else if (foo == 1){
echo 'foo is 1'
}
}
}
}
If you'd like to use nested conditions in when:
2. Here you go:
stage {
when {
anyOf {
environment name: 'VAR_1', value: '1'
branch 'production'
}
}
steps {
<your steps>
}

fetch source values from jenkins extended choice parameter

I have added an extended choice paramter. Now the source values are lin1, lin2, lin3 as listed in screenshot
now when I run,
If I select lin1 then I get param3 = lin1,
If I select lin1 and lin2 then I get param2 - lin1,lin2 ( delimiter is comma )
The question here is, inside jenkins pipeline how can get what all source values were set when the param was created. In short, without selecting any of the checkboxes, want to get the list of the possible values probably in a list
Eg:
list1 = some_method(param3)
// expected output >> list1 = [lin,lin2,lin3]
Let me know if this description is not clear.
The user who runs this does not have configure access ( we dont want to give configure access to anonynmous user ) Hence the job/config.xml idea will not work here
As requested you can also get the values dynamically:
import hudson.model.*
import org.jenkinsci.plugins.workflow.job.*
import com.cwctravel.hudson.plugins.extended_choice_parameter.ExtendedChoiceParameterDefinition
def getJob(name) {
def hi = Hudson.instance
return hi.getItemByFullName(name, Job)
}
def getParam(WorkflowJob job, String paramName) {
def prop = job.getProperty(ParametersDefinitionProperty.class)
for (param in prop.getParameterDefinitions()) {
if (param.name == paramName) {
return param
}
}
return null
}
pipeline {
agent any
parameters {
choice(name: 'FOO', choices: ['1','2','3','4'])
}
stages {
stage('test') {
steps {
script {
def job = getJob(JOB_NAME)
def param = getParam(job, "FOO")
if (param instanceof ChoiceParameterDefinition) {
// for the standard choice parameter
print param.getChoices()
} else if (param instanceof ExtendedChoiceParameterDefinition) {
// for the extended choice parameter plugin
print param.getValue()
}
}
}
}
}
}
As you can see it requires a lot of scripting, so just must either disable the Groovy sandbox or approve most of the calls on the script approval page.
I couldn't find any variable or method to get the parameter list. I guess it's somehow possible through a undocumented method on the param or currentBuild maps.
A possible solution to your problem could be defining the map outside of the pipeline and then just use that variables like this:
def param3Choices = ['lin1', 'lin2', 'lin3']
pipeline {
parameters {
choice(name: 'PARAM3', choices: param3Choices, description: '')
}
stage('Debug') {
steps {
echo param.PARAM3
print param3Choices
}
}
}

Need Condition based Input Step in Jenkins pipeline script

I have three stages in jenkins pipeline script viz (1) precheck, (2) build-prod & (3) build-dr.
I have stated the input step for manual trigger at stage "build-dr"
My pipeline is condition based i.e based on user parameter in precheck stage .
Condition1: "precheck" -> "build-prod" and then "build-dr" is executed.
Condition2: "precheck" and then "build-dr" is executed (skips build-prod).
I need the input step in Condition1 and is working fine however the input step should not be executed for Condition2 i.e no popup msg with input step. Please let me know how can we put a condition around input step in stage 3 build-dr so it does not execute input step when the pipleline skips (2) build-prod.
Jenkins pipeline Script Code:
agent any
stages {
stage ("Pre-Check Parameters") {
steps {
echo "Pre-Check called in pipeline"
}
}
stage ("build-prod") {
when {
expression { params.region == 'prod_only' || params.region == 'prod_and_dr' }
}
steps {
build 'job4'
}
}
stage ("build-dr") {
input{
message "Proceed or Abort"
submitter "user1,admin"
parameters {
string(name:'username', defaultValue: 'user1', description: 'Username of the user pressing Ok')
}
}
when {
expression { params.region == 'dr_only' || params.region == 'prod_and_dr'}
}
steps {
build 'job5'
}
}
}
}
Kindly suggest.
You are currently using the input directive as described here but this prevents you to make this input conditional. You actually have to use the Input Step. Instead of adding the input field directly below the stage directive you move this into the steps block of your stage and add a script block around it to use if/else conditionals.
And take care to remove the curly brackets around you input step and to add a colon after each property.
What you have to do now is to adapt this line to your requirements:
if(Condition1 == true) Depenending on the value of your parameter.
stage("build-dr") {
when {
expression { params.region == 'dr_only' || params.region == 'prod_and_dr'}
}
steps {
script {
if(Condition1 == true) {
input message: "Proceed or Abort", submitter: "user1,admin",
parameters: [string(name:'username', defaultValue: 'user1', description: 'Username of the user pressing Ok')]
}
}
build 'job5'
}
}
Alternatively you can use an environment declaration block to declare a variable and assign a specific value to it if your second stage will be executed. But any environment value will always be typed as a String this is important for the if/else conditional. A good way to assign a value to the variable would be to add a post section to your second stage.
pipeline {
agent any
environment {
STAGE_2_EXECUTED = "0"
}
stages{
stage("....") {
steps {
....
}
}
stage("Second stage") {
when {
expression { /* Your condition */ }
}
steps {
....
}
post {
always {
script {
STAGE_2_EXECUTED = "1";
}
}
}
}
stage("Third Stage") {
steps {
script {
if(STAGE_2_EXECUTED == "1") {
input message: "Proceed or Abort", submitter: "user1,admin",
parameters: [string(name:'username', defaultValue: 'user1', description: 'Username of the user pressing Ok')]
}
}
build 'job5'
}
}
}
}

Jenkins pipeline lock is not getting released

I am getting this null pointer exception and the lock is not getting freed, it was working correctly for a long and suddenly started to throw this exceptions
any one has any idea?
stage('Deploy to iDev') {
steps {
script {
lock(resource: "$DEV_LOCK", inversePrecedence: true) {
milestone (15)
ansiColor('xterm') {
ansibleTower credential: '',
extraVars: "$DEV_ANSIBLE_PARAMS",
importTowerLogs: true,
importWorkflowChildLogs: false,
inventory: '',
jobTags: '',
jobTemplate: "$DEV_ANSIBLE_ID",
jobType: 'run',
limit: '',
removeColor: false,
skipJobTags: '',
templateType: 'job',
towerServer: "$TOWER_SERVER",
verbose: true
}
}
if ("$DEV_CONTAINER_JOB" != 'NA') {
build job: "$DEV_CONTAINER_JOB"
}
if ("$DEV_TEST_JOB" != 'NA') {
build job: DEV_TEST_JOB, parameters: [[$class: DEV_TEST_PARAMS_CLASS, name: DEV_TEST_PARAMS_NAME, value: DEV_TEST_PARAMS_VALUE]]
}
}
}
post {
failure {
// We want to email the development team.
}
aborted {
echo "aborted.. during deploy to iDev"
}
}
}
errors are below:
java.lang.NullPointerException
at org.jenkins.plugins.lockableresources.LockableResourcesManager.freeResources(LockableResourcesManager.java:323)
at org.jenkins.plugins.lockableresources.LockableResourcesManager.unlockNames(LockableResourcesManager.java:367)
at org.jenkins.plugins.lockableresources.LockStepExecution$Callback.finished(LockStepExecution.java:125)
at org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback$TailCall.onSuccess(BodyExecutionCallback.java:114)
at org.jenkinsci.plugins.workflow.cps.CpsBodyExecution$SuccessAdapter.receive(CpsBodyExecution.java:368)
at com.cloudbees.groovy.cps.Outcome.resumeFrom(Outcome.java:73)
As per this
you need to do this as the lock is a declarative step or wrapper
stage('Deploy to iDev') {
steps {
lock(resource: "$DEV_LOCK", inversePrecedence: true) {
script {
.
.
.
}
}
}
}
You might run into problems with $DEV_LOCK too, depending how you defined it. You might be able to do "${env.DEV_LOCK}" or "${DEV_LOCK}"
Looking a bit closer, I think you only need to script the if statements. You could even put build job... into separate stages using when clauses with expressions and lose the script altogether and lock the whole pipeline as per my first link answer
As a first look, I would say that $DEV_LOCK doesn't exist at the moment it is evaluated. Just for the sake of argument, you can try to change it for a static string temporary, let's say
lock(resource: "foo", inversePrecedence: true)
Getting a bit deeper into it, and
seeing this line of the error stack trace
org.jenkins.plugins.lockableresources.LockableResourcesManager.freeResources(LockableResourcesManager.java:323)
judging by the date of this post,
and the commit history of the plugin...
...I would say that we are talking about this line in the plugin's code: https://github.com/jenkinsci/lockable-resources-plugin/blob/79034dcd1c12f88030b0990356ad9f7c63d1937e/src/main/java/org/jenkins/plugins/lockableresources/LockableResourcesManager.java#L323
The line is
323. private synchronized void freeResources(List<String> unlockResourceNames, #Nullable Run<?, ?> build) {
321. for (String unlockResourceName : unlockResourceNames) {
322. for (LockableResource resource : this.resources) {
323. if (resource != null && resource.getName() != null && resource.getName().equals(unlockResourceName)) {
we can see that resource is not null, and resource.getName() is not null, so the only possible null thing there is unlockResourceName, which makes sense since it is not checked in the lines above.
So it looks like the resource name of your resource (remember that your resource was $DEV_LOCK) happens to be null.
so I would say that the test proposed above, using just lock(resource: "foo", inversePrecedence: true) to see if the problems come from there, would be a good starting point. If it works, then you can decide if you really need $DEV_LOCK as a env variable, or you can change it for something static. If you needed it then take it from there trying to find out where it is unset, or if it is actually set somewhere.

Resources