withCredentials failing for credential type(userNamePassword vs stringCredential) - jenkins

I am trying to access Grafana from a Jenkins pipeline(withCredentials + httpRequest).
This is how the credential(the Grafana's actual admin username, and password) looks in Jenkins:
The partial pipeline code:
script.withCredentials([script.string(
credentialsId: "${credentialsEnvironment}",
variable: 'usernamePassword')
]) {
String auth = "${script.usernamePassword}".bytes.encodeBase64().toString()
Map params = defaultArgs + httpParams
def response = []
try {
response = script.httpRequest(
params +
[
url: "${apiEndpoint}/${url}",
customHeaders: [[name: 'Authorization', value: "Basic ${auth}"]]
]
)
if (response && (response.status != 200 && response.status != 201)) {
script.echo "Response status: ${response.status}"
script.echo "Response message: ${response.content}"
}
return response
} catch (ex) {
LogUtil.echoStacktraceToScript(script, ex)
throw new ObservabilityException("Error: An exception occured when sending request with params: ${params}", ex)
}
}
The exception:
10:49:56 credentialsEnvironment: sb_1365_kraken_monitoring_scp_west_zone01_z01_grafana_admin
10:49:56 [Pipeline] withCredentials
10:49:56 [Pipeline] // withCredentials
10:49:56 [Pipeline] echo
10:49:56 org.jenkinsci.plugins.credentialsbinding.impl.CredentialNotFoundException: Credentials 'sb_1365_kraken_monitoring_scp_west_zone01_z01_grafana_admin' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
10:49:56 at org.jenkinsci.plugins.credentialsbinding.MultiBinding.getCredentials(MultiBinding.java:208)
10:49:56 at org.jenkinsci.plugins.credentialsbinding.impl.StringBinding.bindSingle(StringBinding.java:57)
10:49:56 at org.jenkinsci.plugins.credentialsbinding.Binding.bind(Binding.java:149)
10:49:56 at org.jenkinsci.plugins.credentialsbinding.impl.BindingStep$Execution2.doStart(BindingStep.java:132)
10:49:56 at org.jenkinsci.plugins.workflow.steps.GeneralNonBlockingStepExecution.lambda$run$0(GeneralNonBlockingStepExecution.java:77)
10:49:56 at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
10:49:56 at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
10:49:56 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
10:49:56 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
10:49:56 at java.base/java.lang.Thread.run(Thread.java:829)
What exactly am I missing here?
------Edit-1--------
I modified the code but now I am clueless about how to pass the username, and password as the httpRequest doc. says nothing about it.
script.println "Attempting to use ${credentialsEnvironment}"
script.withCredentials([script.usernamePassword(
credentialsId: "${credentialsEnvironment}",
passwordVariable: 'passw', usernameVariable: 'user')
]) {
script.println "user: ${script.user}"
String auth = "${script.user}".bytes.encodeBase64().toString()
script.println "auth: ${auth}"
Map params = defaultArgs + httpParams
def response = []
try {
response = script.httpRequest(
params +
[
url: "${apiEndpoint}/${url}",
customHeaders: [[name: 'Authorization', value: "Basic ${auth}"]]
]
)
if (response && (response.status != 200 && response.status != 201)) {
script.echo "Response status: ${response.status}"
script.echo "Response message: ${response.content}"
}
return response
} catch (ex) {
LogUtil.echoStacktraceToScript(script, ex)
throw new ObservabilityException("Error: An exception occured when sending request with params: ${params}", ex)
}
}
Output:
credentialsEnvironment: sb_1365_kraken_monitoring_scp_west_zone01_z01_grafana_admin
13:05:52 [Pipeline] echo
13:05:52 Attempting to use sb_1365_kraken_monitoring_scp_west_zone01_z01_grafana_admin
13:05:52 [Pipeline] withCredentials
13:05:52 Masking supported pattern matches of $user or $passw
13:05:52 [Pipeline] {
13:05:52 [Pipeline] echo
13:05:52 user: ****
13:05:52 [Pipeline] echo
13:05:52 auth: YWRtaW50ZXN0
13:05:52 [Pipeline] httpRequest
13:05:52 HttpMethod: GET
13:05:52 URL: https://plg-grafana-sb-1365-kraken-monitoring.apps.scp-west-zone01-z01.net/api/folders
13:05:52 Content-Type: application/json
13:05:52 Accept: application/json
13:05:52 Authorization: *****
13:05:52 Sending request to url: https://plg-grafana-sb-1365-kraken-monitoring.apps.scp-west-zone01-z01.net/api/folders
13:05:52 Response Code: HTTP/1.1 401 Unauthorized
13:05:52 Success: Status code 401 is in the accepted range: 100:500
13:05:52 [Pipeline] echo
13:05:52 Response status: 401
13:05:52 [Pipeline] echo
13:05:52 Response message: {"message":"Invalid Basic Auth Header","traceID":""}

You don`t need withCredentials with httpRequest plugin; just pass the credential id. Try something like this:
httpRequest url:"${apiEndpoint}/${url}", ..., authentication: credentialsEnvironment
See how to use httpRequest in Jenkinsfile pipeline with basic auth

Related

How to make a REST API call from jenkins pipeline

I'm trying to make a REST API call from jenkins pipeline once a build job is finished. Since I'm new to the content, I'm unable to complete the build with my below script:
pipeline {
agent any
stages {
stage('BUILD') {
steps {
echo 'Demo Staging Build Running'
}
}
}
post {
always {
echo 'Demo Staging Build Completed'
echo "Build Result: ${currentBuild.result}"
echo "Build Url: ${env.BUILD_URL}"
def response = httpRequest acceptType: 'APPLICATION_JSON', httpMode: 'GET', url: 'http://localhost:9091/demo/jenkins-res'
echo "Status: ${response.status}"
}
}
}
While running the script, I'm getting the below error:
Running in Durability level: MAX_SURVIVABILITY
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 27: Expected a step # line 27, column 13.
def response = httpRequest acceptType: 'APPLICATION_JSON', httpMode: 'GET', url: 'http://localhost:9091/ucreator/jenkins-res'
Rectified the issue with a script tag surrounding the request
pipeline {
agent any
stages {
stage('BUILD') {
steps {
echo 'Demo Staging Build Running'
}
}
}
post {
always {
echo 'Demo Staging Build Completed'
echo "Build Result: ${currentBuild.result}"
echo "Build Url: ${env.BUILD_URL}"
script {
def response = httpRequest acceptType: 'APPLICATION_JSON', httpMode: 'GET', url: 'http://localhost:9091/demo/jenkins-res'
}
echo "Status: ${response.status}"
}
}
}

Jenkinsfile Credentials as parameter is not read

I am trying to use the credentials parameter for a git clone. But i am getting the error that the variables are not found
Param definition
credentials (credentialType: 'Username with password', defaultValue: 'fcb2d7c3-4b35-4ef2-bdf0-24fc4ff1137c', description: 'Git credential', name: 'git_credential', required: true)
Usage in stage
withCredentials([usernamePassword(credentialsId: params.git_credential, passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
sh 'git reset --hard; git clone https://${DOCKER_USERNAME}:${DOCKER_PASSWORD}#repo_url/scm/${params.repository}.git --branch master'
Error: Wrong variable used
This works for me:
pipeline {
agent any
parameters {
// credentials : defaultValue is Credentials ID
credentials(name: 'git_credential', description: 'Git credential', defaultValue: 'fcb2d7c3-4b35-4ef2-bdf0-24fc4ff1137c', credentialType: "Username with password", required: true )
}
stages {
stage('Print') {
steps {
withCredentials([usernamePassword(
credentialsId: '${git_credential}',
usernameVariable: 'DOCKER_USERNAME',
passwordVariable: 'DOCKER_PASSWORD',
)]) {
sh """
echo id:${DOCKER_USERNAME} pw:${DOCKER_PASSWORD}
"""
}
}
}
}
}

Jenkins Declarative pipeline deployment approval for only one environment

Below is my declarative pipeline code to deploy code to 2 environments upon approval from UAT lead. But UAT lead would like to approve to deploy one environment . Second environment he would like to after a day or so ( this can be day or few days . Unpredictable) . How can it be achieved ? . Sleep / timeout does work here . Two separate approval stage can be done ?
#Library('xxxxxx') _
import jenkins.model.*
def userInput
def builduserid
def buildusername
def MANIFESTFILE
def SNAPSHOT
def BUILD_TIMESTAMP
def ucdDeployProcess
def deplprocess = env.DEPLOYPROCESS.split(",").findAll { it }.collect { it.trim() }
node("BDP") {
wrap([$class: 'BuildUser']) {
builduserid = env.BUILD_USER_ID
buildusername = env.BUILD_USER
}
}
pipeline {
agent { label 'BDP'}
stages {
stage ('Generate and Create Consolidated Snapshot') {
steps {
println "Cleaning workspace"
step([$class: 'WsCleanup'])
dir('') {
git url: 'xxxxx'
}
dir('scripts') {
git url: 'xxxxx'
}
script {
def now = new Date()
BUILD_TIMESTAMP=now.format("yyyyMMddHHmm", TimeZone.getTimeZone('UTC'))
env.MANIFESTFILE="${ucdApplication}_${RELEASE}_Manifest.csv"
env.SNAPSHOT="${ucdApplication}_${RELEASE}_${BUILD_TIMESTAMP}"
sh(script: '$WORKSPACE/scripts/scripts/SelfServiceBaselineVerificationPrePareForSnapshot.ksh "$ucdApplication" "${COMPSNAPSHOT}" "$ucdApplication"/"${MANIFESTFILE}"')
def props = readProperties file: 'env.cfg' //readProperties is a step in Pipeline Utility Steps plugin
env.SnapshotContent = props.COMBINEDSNAPSHOTVERSION
}
}
post {
failure {
emailext body: '''
<div>Hi Application Team</div>
<br>
<div>
<br>
<br>
<h4>Failed Checks: </h4>
<div style="margin-left: 50px;">
${BUILD_LOG_REGEX, regex="FAILED!", showTruncatedLines=false, escapeHtml=true, defaultValue="Nothing found, please check logs for other errors", matchedLineHtmlStyle="color:red;"}
</div>
<br>
<br>
</div>
<br>
<div>Thank you</div>
''',
mimeType: 'text/html',
to: "${builduserid}",
subject: '$ucdApplication Component Baseline Verification FAILED'
}
}
}
stage ('Create Consolidated Snapshot') {
steps {
ucdCreateCustomSnapshot()
}
}
stage ('Approval Stage') {
steps {
script {
emailext body: """
Hi Approver,<br/><br/><br/>
You have request from application team (${buildusername}) to deploy $ucdApplication application snapshot ${env.SNAPSHOT} to ${deploymentEnv} environment.<br/><br/><br/>
Please approve or reject deployement request: Click here.<br/><br/><br/>
Thanks,<br/><br/>
Happy Automation<br/>
""",
mimeType: 'text/html',
subject: "Deployment Approval Request",
from: "${builduserid}",
to: "${approverRecipients}"
userInput = input id: 'userInput',
message: 'Let\'s promote?.Please select to approve',
submitterParameter: 'submitter',
submitter: approverRecipients,
parameters: [
[$class: 'BooleanParameterDefinition', defaultValue: false, description: "Select this to deploy the code ${deploymentEnv} environment", name: deploymentEnv]]
if (userInput[deploymentEnv] == false ) {
currentBuild.result = 'ABORTED'
}
}
}
}
stage("Deploy to Acceptance") {
when {
expression { userInput[deploymentEnv] == true }
}
steps {
script {
for (int i = 0; i < deplprocess.size(); i++) {
env.ucdDeployProcess = deplprocess[i]
ucdCustomDeploySnapshot("${deploymentEnv}")
}
}
}
}
stage('Post Activities') {
steps {
println "Cleaning workspace"
step([$class: 'WsCleanup'])
}
}
}
post {
failure {
emailext body: """
Hi Team,<br/><br/><br/>
Code Deployment is failed for ${ucdApplication} application.<br/><br/><br/>
<p><font size="5" color="red">Deployment Request is failed for ${ucdApplication} application with snapshot ${env.SNAPSHOT}!</font></p>
<p>Check console output at &QUOT;<a href='${BUILD_URL}consoleText'>${JOB_NAME} [${BUILD_NUMBER}]</a>&QUOT;</p>
Thanks,<br/>
Happy Automation<br/><br/><br/>
""",
mimeType: 'text/html',
to: "${mailToRecipients},${builduserid}",
from: "${builduserid}",
subject: "FAILURE: Code Deployment is failed for '$ucdApplication' application with snapshot ${env.SNAPSHOT}"
}
success {
emailext body: """
Hi Team,<br/><br/><br/>
<p><font size="5" color="green">Code Deployment is success for $ucdApplication application for ${deploymentEnv} environment with snapshot ${env.SNAPSHOT}!</font></p>
Thanks,<br/>
Happy Automation<br/><br/><br/>
""",
mimeType: 'text/html',
to: "${mailToRecipients},${builduserid}",
from: "${builduserid}",
subject: "SUCCESSFUL: Code Deployment is success for '$ucdApplication' application with snapshot ${env.SNAPSHOT}"
}
aborted {
emailext body: """
Hi Team,<br/><br/><br/>
<p><font size="5" color="red">Deployment Request is rejected for ${ucdApplication} application by approver !</font></p>
Thanks,<br/>
Happy Automation<br/><br/><br/>
""",
mimeType: 'text/html',
to: "${mailToRecipients},${builduserid}",
from: "${builduserid}",
subject: "REJECTED: Code Deployment is rejected for $ucdApplication application with snapshot ${env.SNAPSHOT} by approver"
}
}
enter code here
}
jenkins-pipeline

How to send allure or html report as an attachment in the Jenkins email notifications

How to send allure or html report as an attachment in the Jenkins email notifications. This is example of the pipeline i am using in my Pipeline script in Jenkins. I have setup my email notifcations, however i want to get some sort of report in the email. Please note that providing a link is not enough because my tests are setup on a different machine with the reports.
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'echo "Fail!"; exit 1'
}
}
}
post {
always {
echo 'This will always run'
}
success {
echo 'This will run only if successful'
}
failure {
mail bcc: '', body: "<b>Example</b><br>Project: ${env.JOB_NAME} <br>Build Number: ${env.BUILD_NUMBER} <br> URL de build: ${env.BUILD_URL}", cc: '', charset: 'UTF-8', from: '', mimeType: 'text/html', replyTo: '', subject: "ERROR CI: Project name -> ${env.JOB_NAME}", to: "foo#foomail.com";
}
unstable {
echo 'This will run only if the run was marked as unstable'
}
changed {
echo 'This will run only if the state of the Pipeline has changed'
echo 'For example, if the Pipeline was previously failing but is now successful'
}
}
}
You should use emailext plugin not mail
failure {
emailext(
attachmentsPattern: "<path to report>",
body: '',
subject: "",
to: ""
)
}

jenkins notifying error occured in different steps by sending mail in Pipeline (former known as Workflow)

I have a pipeline with multiple steps, for example:
stage 'dev - compile'
node('master') {
//do something
}
stage 'test- compile'
node('master') {
//do something
}
stage 'prod- compile'
node('master') {
//do something
}
I want to send a email if something goes wrong in the job, how can I send an email no matter where the error got triggered, something like:
try {
/**
all the code above
**/
} catch(Exception e) {
mail the error
}
I think it is a better way to use the jenkins build in post section instead of using try catch:
pipeline {
agent any
stages {
stage('whatever') {
steps {
...
}
}
}
post {
always {
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: "example#example.com",
sendToIndividuals: true])
}
}
}
}
}
What I did to include useful information in my mail about the failure:
try {
stage 'checkout cvs'
node('master') {
/** CODE **/
}
stage 'compile'
node('master') {
/** CODE **/
}
stage 'test unit'
node('master') {
/** CODE **/
}
stage 'package'
node('master') {
/** CODE **/
}
stage 'nexus publish'
node('master') {
/** CODE **/
}
stage 'Deploy to App Server'
node('master') {
/** CODE **/
}
} catch(e) {
String error = "${e}";
// Make the string with job info, example:
// ${env.JOB_NAME}
// ${env.BUILD_NUMBER}
// ${env.BUILD_URL}
// and other variables in the code
mail bcc: '',
cc: '',
charset: 'UTF-8',
from: '',
mimeType: 'text/html',
replyTo: '',
subject: "ERROR CI: Project name -> ${env.JOB_NAME}",
to: "${mails_to_notify}",
body: "<b>${pivote}</b><br>\n\nMensaje de error: ${error}\n\n<br>Projecto: ${env.JOB_NAME} <br>Build Number: ${env.BUILD_NUMBER} <br> URL de build: ${env.BUILD_URL}";
error "${error}"
}
Well, your idea is absolutely correct, you just need to move mail after the catch block or use finally. Examples (in pseudocode):
try {
//code
email = 'success'
} catch(Exception e) {
// error handler: logging
email = 'failure'
}
send email
Or the same approach using the catchError pipeline built-in:
result = 'failure'
catchError { // this catches all exceptions and set the build result
//code
result = 'success' // we will reach this point only if no exception was thrown
}
send result
Or using finally:
try {
//code
} finally {
send email
}

Resources