Not able to compare the passwords in Jenkins Pipeline - jenkins

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

Related

Jenkinsfile: parameter precedence

Say I have a Jenkinsfile with stages based on a conditional such as the following. Then, in the Jenkins UI for a particular Pipeline Project, I may or may not have a (Global Variable String Parameter) parameter named CITY defined for a particular job.
If the CITY parameter is defined in the Jenkins project in the UI, I'd like it to use whatever city the user inputs. If the user doesn't input anything, I'd like it to default to a value in "Global Properties" (in "Manage Jenkins > Configure System > Global Properties")
If the CITY parameter is NOT defined in the UI (like if someone forgot to define that parameter in the Pipeline Project UI), I'd like it to somehow default to a value defined in the Jenkinsfile.
Simply put, I'd like to define a default in the Jenkinsfile such that if someone forgets to configure a Global Variable String Parameter in the Job UI, the default will be used.
I'm pretty new to Jenkins and Groovy, I'm not quite sure how to do this. How can I go about defining a default parameter in a Jenkinsfile that can be overridden by user input in the UI or a default from "Global Properties"? Any advice is appreciated.
pipeline {
agent any
stages {
stage('Always') {
steps {
script {
sh 'echo Welcome CITY=$CITY'
}
}
stage('Chicago') {
when {
expression {
params.CITY == "CHICAGO"
}
}
steps {
script {
sh 'echo Welcome to Chicago "CITY=$CITY"'
}
}
}
stage('NYC') {
when {
expression {
params.CITY == "NYC"
}
}
steps {
script {
sh 'echo Welcome to NYC "CITY=$CITY"'
}
}
}
}
}
there is no need to declare each city just add a string parameter with a default value and create a single stage that will take the default parameter if the user did not enter one
if this works for you please mark answer as correct :-)
pipeline {
agent any
parameters {
string(name: 'CITY', defaultValue: 'TEL_AVIV', description: 'this is the default if user dosnt enter parameter in the UI')
}
stages {
stage('CITY') {
steps {
script {
sh 'echo Welcome $CITY'
}
}
}
}
}

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
}
}
}

how to get jenkins parameter's default value

I want to have a check in jenkins job, where if the jenkins parameters have been modified then I want to display an Input modal to proceed or abort the job .But for that I need to verify if the parameters have been modified.
So, I can get modified parameters value in jenkins job, but how to retrieve default values of those parameters so that I can verify if any parameters have been modified?
def DEFAULT_VALUE = "42"
pipeline {
agent any
parameters { string(name: 'MY_PARAM', defaultValue: DEFAULT_VALUE, description: '') }
stages {
stage('Example') {
steps {
script {
if (params.MY_PARAM == DEFAULT_VALUE) {
echo 'Default value used'
} else {
echo 'Non-default value used'
}
}
}
}
}

Value returned from a script does not assigned to a variable declared in jenkins declarative pipeline stage

I am working on adding a jenkins Declarative pipeline for automation testing. In the test run stage i want to extract the failed tests from the log. i am using a groovy function for extracting the test result. this function is not a part of the jenkins pipeline. It is another script file. The function works fine and it build a string containing the failure details. Inside a pipeline stage i am calling this function and assinging the returned string to another variable. But when i echo the variable value it prints empty string.
pipeline {
agent {
kubernetes {
yamlFile 'kubernetesPod.yml'
}
}
environment{
failure_msg = ""
}
stages {
stage('Run Test') {
steps {
container('ansible') {
script {
def notify = load('src/TestResult.groovy')
def result = notify.extractTestResult("${WORKSPACE}/testreport.xml")
sh "${result}"
if (result != "") {
failure_msg = failure_msg + result
}
}
}
}
}
post {
always {
script {
sh 'echo Failure message.............${failure_msg}'
}
}
}
}
here 'sh 'echo ${result}'' print empty string. But 'extractTestResult()' returns a non-empty string.
Also i am not able to use the environment variable 'failure_msg' in post section it return an error 'groovy.lang.MissingPropertyException: No such property: failure_msg for class: groovy.lang.Binding'
can anyone please help me with this ?
EDIT:
Even after i fixed the string interpolation, i was getting the same
error. That was because jenkins does not allow using 'sh' inside
docker container. there is an open bug ticket in jenkins issue
board
I would suggest to use a global variable for holding the error message. My guess is that the variable is not existing in your scope.
def FAILURE_MSG // Global Variable
pipeline {
...
stages {
stage(...
steps {
container('ansible') {
script {
...
if (result != "") {
FAILURE_MSG = FAILURE_MSG + result
}
}
}
}
}
post {
always {
script {
sh "${FAILURE_MSG}" // Hint: Use correct String Interpolation
}
}
}
}
(Similar SO question can be found here)

Jenkins pipeline: return value of build step

In this integration pipeline in Jenkins, I am triggering different builds in parallel using the build step, as follows:
stage('trigger all builds')
{
parallel
{
stage('componentA')
{
steps
{
script
{
def myjob=build job: 'componentA', propagate: true, wait: true
}
}
}
stage('componentB')
{
steps
{
script
{
def myjob=build job: 'componentB', propagate: true, wait: true
}
}
}
}
}
I would like to access the return value of the build step, so that I can know in my Groovy scripts what job name, number was triggered.
I have found in the examples that the object returned has getters like getProjectName() or getNumber() that I can use for this.
But how do I know the exact class of the returned object and the list of methods I can call on it? This seems to be missing from the Pipeline documentation. I am asking for this case in particular, but generally speaking, how can I know the class of the returned object and its documentation?
The step documentation is generated based on some files that are bundled with the plugin, which sometimes isn't enough. One easy way would be to just print out the class of the result object by calling getClass:
def myjob=build job: 'componentB', propagate: true, wait: true
echo "${myjob.getClass()}"
This output would tell you that the result (in this case) is a org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper which has published Javadoc.
For other cases, I usually have to dive into the Jenkins source code. Here is my general strategy:
Figure out which plugin the step comes from either by the step documentation, jenkins.io steps reference, or just searching the internet
From the plugin site, go to the source code repository
Search for the String literal of the step name, and find the step type that returns it. In this case, it looks to be coming from the BuildTriggerStep class, which extends AbstractStepImpl
#Override
public String getFunctionName() {
return "build";
}
Look at the nested DescriptorImpl to see what execution class is returned
public DescriptorImpl() {
super(BuildTriggerStepExecution.class);
}
Go to BuildTriggerStepExecution and look at the execution body in the start() method
Reading over the workflow step README shows that something should call context.onSuccess(value) to return a result. There is one place in that file, but that is only on the "no-wait" case, which always returns immediately and is null (source).
if (step.getWait()) {
return false;
} else {
getContext().onSuccess(null);
return true;
}
Ok, so it isn't completing in the step execution, so it must be somwhere else. We can also search the repository for onSuccess and see what else might trigger it from this plugin. We find that a RunListener implementation handles setting the result asynchronously for the step execution if it has been configured that way:
for (BuildTriggerAction.Trigger trigger : BuildTriggerAction.triggersFor(run)) {
LOGGER.log(Level.FINE, "completing {0} for {1}", new Object[] {run, trigger.context});
if (!trigger.propagate || run.getResult() == Result.SUCCESS) {
if (trigger.interruption == null) {
trigger.context.onSuccess(new RunWrapper(run, false));
} else {
trigger.context.onFailure(trigger.interruption);
}
} else {
trigger.context.onFailure(new AbortException(run.getFullDisplayName() + " completed with status " + run.getResult() + " (propagate: false to ignore)"));
}
}
run.getActions().removeAll(run.getActions(BuildTriggerAction.class));
The trigger.context.onSuccess(new RunWrapper(run, false)); is where the RunWrapper result comes from
The result of the downstream job is given in the result attribute of the returned object.
I recommend to use propagate: false to get control of how the result of the downstream job affects the current build.
Example:
pipeline{
[...]
stages {
stage('Dummy') {
steps {
echo "Hello world #1"
}
}
stage('Fails') {
steps {
script {
downstream = build job: 'Pipeline Test 2', propagate: false
if (downstream.result != 'SUCCESS') {
unstable(message: "Downstream job result is ${downstream.result}")
}
}
}
}
}
[...]
}
In this example, the current build is set to UNSTABLE whenever the downstream build has not been successful.
The result can be: SUCCESS, FAILURE, UNSTABLE, or ABORTED.
For your other question see Is there a built-in function to print all the current properties and values of an object? and Groovy / grails how to determine a data type?
I got the class path from build log:
13:20:52 org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper#5fe8d20f
and then I found the doc from https://javadoc.jenkins.io/, you can get all you need from this page
link: https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html

Resources