I have a setup at work where the vSphere host are manually restarted before execution of a specific jenkins job, as a noob in the office I automated this process by adding a extra build step to restart vm's with the help of https://wiki.jenkins-ci.org/display/JENKINS/vSphere+Cloud+Plugin! (vSphere cloud plugin).
I would like to now integrate this as a pipeline code, please advise.
I have already checked that this plugin is Pipeline compatible.
I currently trigger the vSphere host restart in pipeline by making it to remotely trigger a job configured with vSphere cloud plugin.
pipeline {
agent any
stages {
stage('Restarting vSphere') {
steps {
script {
sh "curl -v 'http://someserver.com/job/Vivin/job/executor_configurator/buildWithParameters?Host=build-114&token=bonkers'"
}
}
}
stage('Setting Executors') {
steps {
script {
def jenkins = Jenkins.getInstance()
jenkins.getNodes().each {
if (it.displayName == 'brewery-133') {
echo 'brewery-133'
it.setNumExecutors(8)
}
}
}
}
}
}
}
I would like to integrate the vSphere cloud plugin directly in the Pipeline code itself, please help me to integrate.
pipeline {
agent any
stages {
stage('Restarting vSphere') {
steps {
vSphere cloud plugin code that is requested
}
}
}
stage('Setting Executors') {
steps {
script {
def jenkins = Jenkins.getInstance()
jenkins.getNodes().each {
if (it.displayName == 'brewery-133') {
echo 'brewery-133'
it.setNumExecutors(8)
}
}
}
}
}
}
}
Well I found the solution myself with the help of 'pipeline-syntax' feature found in the menu of a Jenkins pipeline job.
'Pipeline-syntax' feature page contains syntax of all the possible parameters made available via the API of the installed plugins of a Jenkins server, using which we can generate or develop the syntax based on our needs.
http://<jenkins server url>/job/<pipeline job name>/pipeline-syntax/
My Jenkinsfile (Pipeline) now look like this
pipeline {
agent any
stages {
stage('Restarting vSphere') {
steps {
vSphere buildStep: [$class: 'PowerOff', evenIfSuspended: false, ignoreIfNotExists: false, shutdownGracefully: true, vm: 'brewery-133'], serverName: 'vspherecentral'
vSphere buildStep: [$class: 'PowerOn', timeoutInSeconds: 180, vm: 'brewery-133'], serverName: 'vspherecentral'
}
}
stage('Setting Executors') {
steps {
script {
def jenkins = Jenkins.getInstance()
jenkins.getNodes().each {
if (it.displayName == 'brewery-133') {
echo 'brewery-133'
it.setNumExecutors(1)
}
}
}
}
}
}
}
Related
I have a simple shared library and want to call a function which creates a file.
My pipeline script looks like this:
#Library('jenkins-shared-library')_
pipeline {
agent {
node {
label 'node1'
}
}
stages {
stage('test') {
steps {
script {
def host = sh(script: 'hostname', returnStdout: true).trim()
echo "Hostname is: ${host}"
def testlib = new TestLibrary(script:this)
testlib.createFile("/tmp/file1")
}
}
}
}
}
This pipeline job is triggered by another job which runs on the built-in master node.
The stage 'test' is correctly executed on the 'node1'.
Problem: The created file "/tmp/file1" is created on the jenkins master, instead of "node1"
I also tried it without the shared library and load a groovy script
directly in a step:
pipeline {
agent {
node {
label 'node1'
}
}
stages {
stage('test') {
steps {
script {
def script = load "/path/to/script.groovy"
script.createFile("/tmp/file1")
}
}
}
}
}
This also creates the file on the master node, instead on "node1".
Is there no way of loading external libs or classes and execute them on the node where the stage is running on ? I dont want to place all the code directly into the step.
Ok I found it myself, groovy scripts run by definition always on the master node. No way to run scripts or shared-library code on a node other than master.
I am writing a Jenkinsfile and trying to enable deployment from the branch names(starting with master and hotfix). How can I do that? Below is my groovy code. This works if I specify only one branch. How can I do that for multiple branches?
// Create and Deploy to STAGE Environment
stage ('Create and Deploy to k8s stage Environment') {
when {
allOf {
expression {
branch_name.startsWith('master')
}
}
}
options {
skipDefaultCheckout()
}
steps {
withCredentials([string(credentialsId: "$env.K8S_STAGE_NS_TOKEN" , variable: 'STAGE_TOKEN')]) {
kubernetesDeploy(hcEnv: 'stage', hcToken: "${STAGE_TOKEN}")
}
}
}
The below code doesn't work if I specify 2 branch names but the above one works.
// Create and Deploy to PROD Environment
stage ('Create and Deploy to k8s production Environment') {
when {
allOf {
expression {
branch_name.startsWith('hotfix')
branch_name.startsWith('master')
}
}
}
options {
skipDefaultCheckout()
}
steps {
withCredentials([string(credentialsId: "$env.K8S_PROD_NS_TOKEN" , variable: 'PROD_TOKEN')]) {
kubernetesDeploy(hcEnv: 'prod', hcToken: "${PROD_TOKEN}")
}
}
}
You can use this
expression { return (env.GIT_BRANCH.startsWith('origin/master') || env.GIT_BRANCH.startsWith('hotfix'))}
OR
you can also try this
expression { return (env.BRANCH_NAME.startsWith('origin/master') || env.GIT_BRANCH.startsWith('origin/hotfix'))}
I am not sure if your branch name starts with origin or without origin so use it according to you. I would suggest instead of startsWith use contains.
Also instead of allOf i guess you need anyOf because you want to run stage for either if it's master branch or hotfix branch and both at the same time can't be true so
I have the following pipeline:
pipeline {
agent any
stages {
stage('CI') {
parallel {
stage('גמלאות') {
steps {
input message: "Pass Sanity?"
}
}
stage('וועדות') {
steps {
input message: "Pass Sanity?"
}
}
stage('מבוטח') {
steps {
input message: "Pass Sanity?"
}
}
}
}
}
}
I'm expecting to see in the UI 3 option to select in each stage. but getting only one instead.
If I will look at tradinall console then I will be able to select if to proceed or to abort.
Is there a way to get this function thru the UI?
Here is an example of the UI:
It seems that the code is correct. The problem is with the Jenkins plugin.
I mooved to work with Blueocean plugin, and now it seems to work fine:
I'm relatively new to Jenkins pipelines, but having implemented already a few, I've realised I need to start using jenkins shared library before I go mad.
Have already figured out how to define some repetitive steps in the library and call them with less clutter from Jenkinsfile, but not sure if the same thing can be done for the entire post build section (thought I've read about to how to define the entire pipeline in the lib and similar), as this is pretty much static end of every single pipeline code:
#Library('jenkins-shared-library')_
pipeline {
agent none
stages {
stage ('System Info') { agent any
steps { printSysInfo() }
}
stage ('Init'){ agent {label 'WinZipSE'}
steps { init('SCMroot') }
}
stage('Build') { agent any
steps { doMagic() }
}
}
// This entire 'post {}' section needs to go to a shared lib
// and be called just with a simple methed call, e.g.
// doPostBuild()
post {
always {
node ('master') {
googlechatnotification (
message: '[$BUILD_STATUS] Build $JOB_NAME $BUILD_NUMBER has finished',
url: 'id:credential_id_for_Ubuntu')
step (
[$class: 'Mailer',
recipients: 'sysadmins#example.com me#example.com',
notifyEveryUnstableBuild: true,
sendToIndividuals: true]
)
}
}
success {
node ('master') {
echo 'This will run only if successful'
}
}
failure {
node ('master') {
echo 'This will run only if failed'
}
}
// and so on
}
}
I just dunno how to syntactically achieve that. For sure, I can define the entire post build section an a lib/var like: doPotBuild.groovy
def call () {
post {...}
}
but how I will eventually call it from within my Jenkinsfile outside of that defined post {} build block section (AKA stages).
I can call it within some stage('post build){doPostBuild()}, but it won't serve the way how the true post {} section is supposed to work, e.g. it won't get executed it there was failure in one of the previous stages.
Any thoughts on that and mainly working examples?
I am not entirely if this will work as I don't use declarative pipelines, so am unsure how rigid the top level structure is. But I would revert to a script block.
#Library('jenkins-shared-library')_
pipeline {
agent none
stages {
stage ('System Info') { agent any
steps { printSysInfo() }
}
stage ('Init'){ agent {label 'WinZipSE'}
steps { init('SCMroot') }
}
stage('Build') { agent any
steps { doMagic() }
}
}
// This entire 'post {}' section needs to go to a shared lib
// and be called just with a simple methed call, e.g.
// doPostBuild()
script {
doPostBuild()
}
}
I have 2 pipelines one for review and one for deploy. So when the pipeline ends with review, I want to skip Jenkinsfile execution. However, when it ends with deploy, it should execute the stage or the Jenkinsfile.
I tried to use if, but this is a declarative pipeline, so when should be used. I want to avoid execution of stage using when condition if I encounter deploy pipeline end.
#!/usr/bin/env groovy
final boolean Deploy = (env.JOB_NAME as String).endsWith("-deploy")
pipeline {
agent any
parameters {
choice(
choices: ['greeting' , 'silence'],
description: '',
name: 'REQUESTED_ACTION')
}
stages {
//how to ouse when here to use deploy vairable to avoide execution of stage below
stage ('Speak') {
steps {
echo "Hello, bitwiseman!"
}
}
}
}
You can skip stages in declarative pipelines using when, so the following should work.
stages {
stage('Deploy') {
when { equals expected: true, actual: Deploy }
steps {
// ...
}
}
}
An alternative to #StephenKing’s answer, which is also correct, you can rewrite the when block when evaluating Booleans as follows:
stages {
stage('Deploy') {
when {
expression {
return Deploy
}
}
steps {
echo "Hello, bitwiseman!" // Step executes only when Deploy is true
}
}
}
This will execute the stage Deploy only when the variable Deploy evaluates to true, else the stage will be skipped.
I've got quite a hard time to find it too, but finally:
stage('Speak') {
when {
expression { params.REQUESTED_ACTION != 'SILENCE' }
}
steps {
echo "Hello, bitwiseman!"
}
}
Jenkins docs with examples here: https://jenkins.io/doc/book/pipeline/syntax/#when-example
Here is an example for a Jenkins scripted pipeline:
stage('Input of Scratch instance and Access token') {
timeout(time: 60, unit: 'SECONDS') {
script {
try {
env.SCRATCH_INSTANCE_URL = input message: 'Please enter the SCRATCH_INSTANCE_URL',
parameters: [string(defaultValue: '',
description: '',
name: 'SCRATCH_INSTANCE_URL')]
env.SCRATCH_ACCESS_TOKEN = input message: 'Please enter the SCRATCH_ACCESS_TOKEN',
parameters: [string(defaultValue: '',
description: '',
name: 'SCRATCH_ACCESS_TOKEN')]
} catch (Throwable e) {
echo "Caught ${e.toString()}"
currentBuild.result = "SUCCESS"
}
}
}
}
// -------------------------------------------------------------------------
// Logout from Dev Hub.
// -------------------------------------------------------------------------
stage('Logout from DevHub') {
if (env.SCRATCH_INSTANCE_URL == null) {
rc = command '''export SFDX_USE_GENERIC_UNIX_KEYCHAIN=true
sfdx force:auth:logout --targetusername ${DEV_HUB_USERNAME} -p
echo ${SCRATCH_INSTANCE_URL}
echo ${SCRATCH_ACCESS_TOKEN}
'''
} else {
echo "Skipping this stage"
}
}
Even you can skip some parts of the steps using below code. Let's say REQUIRED_UPLOAD_INSTALL is a parameter.
stage('Checking Mail List') {
steps {
script {
if(!(env.REQUIRED_UPLOAD_INSTALL.toBoolean())) {
env.mail_list = 'test#testg.com'
}
}
}
}
But it doesn't support in post steps, not even in the when syntax.