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
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}"
}
}
}
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}
"""
}
}
}
}
}
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 "<a href='${BUILD_URL}consoleText'>${JOB_NAME} [${BUILD_NUMBER}]</a>"</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. 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: ""
)
}
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
}