Jenkins Shared Library return executable docker command - jenkins

Is it possible to get a shared library to retune a docker run command?
I have the following,
scr/docker_run.groovy
def ubuntu() {
echo "docker run --rm " +
'--env APP_PATH="`pwd`" ' +
'--env RELEASE=true ' +
"-v \"`pwd`:`pwd`\" " +
"-v /var/run/docker.sock:/var/run/docker.sock " +
"ubuntu"
}
Jenkinsfile
#Library('pipeline-library-demo') _
pipeline {
agent {
node {
label params.SLAVE
}
}
parameters {
string(name: 'SLAVE', defaultValue: 'so_slave')
}
stages {
stage('ubuntu') {
steps {
script {
sh docker_run.ubuntu ls -lah
}
}
}
}
}
I have tried different things inside the groovy file, such as echo, sh, call, all returning errors.
Any help would be great

If you are using DSL style pipeline you should define Steps in your shared library not directly a function in the src/ directory. Should follow the directory structure defined here https://jenkins.io/doc/book/pipeline/shared-libraries/
Then you can define a Step like
vars/mystep.groovy
def call() {
this.sh("docker_run.ubuntu ls -lah");
}
And calling from you pipeline as:
#Library('pipeline-library-demo') _
pipeline {
agent {
node {
label params.SLAVE
}
}
parameters {
string(name: 'SLAVE', defaultValue: 'so_slave')
}
stages {
stage('ubuntu') {
steps {
mystep
}
}
}
}
Best

Related

How to run all stages from jenkins job on same node when using agent docker?

I have a Jenkins pipeline that runs on docker agents and everytime it enters a stage with a different agent it changes Jenkins node. How can I force it to run always on the same node?
I have 3 nodes: master, slave-1 and slave-2. My pipeline sometimes, just an example, starts by using master, then when it calls agent image-docker-1 it uses slave-1 and then when it calls agent image-docker-2 it uses master again.
How can I force it to use always slave-1? I know that, if I weren't using docker as agent, I could use something like:
node (label: "slave-1") {
(...)
pipeline {
agent { label "slave-1 }
(...)
But I think this is not the case.
Here's my pipeline:
node {
properties([
pipelineTriggers(
[cron('H 00 * * 1-5') ]
)]
)
workloadPipeline = load("ImagePull.groovy")
workloadPipeline
}
pipeline {
options {
ansiColor('xterm')
timestamps()
}
agent none
environment {
TOKEN = credentials("token")
HOME = '.'
}
stages {
stage("initiating"){
agent {
docker {
image 'image-docker-1'
args '--entrypoint="" -u root -v /var/run/docker.sock:/var/run/docker.sock'
}
}
stages {
stage('docker 1 scanning') {
steps {
script {
workloadPipeline.loopImages(Images)
}
}
}
stage ('docker 1 test'){
(...)
}
}
}
stage('docker 2 scanning') {
agent {
docker {
image 'image-docker-2'
args '--entrypoint="" -u root -v /var/run/docker.sock:/var/run/docker.sock'
}
}
steps {
script {
workloadPipeline.Scanning()
}
}
}
}
}
found an easy solution from this example by using reuseNode true
pipeline {
agent none
stages {
stage("Fix the permission issue") {
agent any
steps {
sh "sudo chown root:jenkins /run/docker.sock"
}
}
stage('Step 1') {
agent {
docker {
image 'nezarfadle/tools'
reuseNode true
}
}
steps {
sh "ls /"
}
}
}
}
Use:
agent {
docker {
image 'image-docker-1'
args '--entrypoint="" -u root -v /var/run/docker.sock:/var/run/docker.sock'
label 'slave-1'
}
}
Put that or at the pipeline level, for having all your stages using it, or at each stage if you want to seperate by stage
Thanks João for the small correction :)
Thanks for the answer #Washwater. In fact I needed to make a little change.
If I use what you suggested, it returns an error "No agent type specified. Must be one of [any, docker, dockerfile, label, none]"
agent {
node { label "slave-1" }
docker {
image 'image-docker-1'
args '--entrypoint="" -u root -v /var/run/docker.sock:/var/run/docker.sock'
}
}
So, the correct syntax must be:
agent {
docker {
image 'image-docker-1'
args '--entrypoint="" -u root -v /var/run/docker.sock:/var/run/docker.sock'
label "slave-1"
}
}
-The following code works for me when i have multiple nodes labeled with 'slaves'
'init' stage will pick one node from 'slaves', following stages will use the same node with env.NODE_NAME( set by the init state)
pipeline {
agent {
node {
labe 'slaves'
}
stages {
stage ('init') { steps {echo "node is $NODE_NAME"} }
stage ( 'test1') {
agent {
docker {
label env.NODE_NAME
image nginx
}
steps {
echo "test done"
}
}
}
}
}

Pass a string parameter to Jenkins declarative script

I am declaring a String Parameter in Jenkins -
Name is SLACKTOKEN
Value is qwsaw2345
My Jenkins file has script
pipeline {
agent { label 'trial' }
stages {
stage("Build Docker Image") {
steps{
sh 'docker build -t trial:latest --build-arg SLACK_SIGNING_SECRET=${SLACKTOKEN}'
}
}
}
}
I tried like this, but it didnt work. Could you please let me know how can I pass a value from Jenkins string parameter to Jenkins declarative script file.
I have added the Password parameter in job like below
Inside parameters directive you can provide parameters, details is here.
To pass parameter use params.SLACKTOKEN inside double quotes, not single:
pipeline {
agent { label 'trial' }
parameters {
password(name: 'SLACKTOKEN', defaultValue: '', description: 'Slack Token')
}
stages {
stage("Build Docker Image") {
steps{
sh "docker build -t trial:latest --build-arg SLACK_SIGNING_SECRET=${params.SLACKTOKEN}"
}
}
}
}
Where have you declared your variable?
There are a lot of options:
Example: Use env section from declarative syntax:
pipeline {
agent {
label 'trial'
}
environment {
SLACKTOKEN = 'qwsaw2345'
}
stages {
stage('Build') {
steps {
sh "docker build -t trial:latest --build-arg SLACK_SIGNING_SECRET=${SLACKTOKEN}"
}
}
}
}

Declarative Pipeline shared library

I'm facing an issue when trying to implement shared library in my Jenkins servers.
The error I'm getting is around the following
No such DSL method 'agent' found among steps
I have tried to remove the agent and just run on node, but still issue.
I was following the following: https://jenkins.io/blog/2017/09/25/declarative-1/
could someone please point out where I'm be going wrong
vars/jenkinsJob.groovy
def call() {
// Execute build pipeline job
build_pipeline()
}
def build_pipeline() {
agent {
node {
label params.SLAVE
}
}
parameters {
string(name: 'SETTINGS_CONFIG_FILE_NAME', defaultValue: 'maven.settings')
string(name: 'SLAVE', defaultValue: 'new_slave')
}
environment {
mvn = "docker run -it --rm --name my-maven-project -v "$(pwd)":/usr/src/mymaven -w /usr/src/mymaven maven:3.3-jdk-8"
}
stages {
stage('Inject Settings.xml File') {
steps {
configFileProvider([configFile(fileId: "${env.SETTINGS_CONFIG_FILE_NAME}", targetLocation: "${env.WORKSPACE}")]) {
}
}
}
stage('Clean') {
steps {
sh "${mvn} clean"
}
}
stage('Lint') {
steps {
sh "${mvn} lint"
}
}
stage('Build package and execute tests') {
steps {
sh "${mvn} build"
}
}
}
post {
always {
archive "**/target/surefire-reports/*"
junit '**/target/surefire-reports/*.xml'
step([$class: 'JacocoPublisher'])
}
}
}
Jenkinsfile
#Library('pipeline-library-demo') _
jenkinsJob.call()
All valid Declarative Pipelines must be enclosed within a pipeline block
eg:
pipeline {
/* insert Declarative Pipeline here */
/* import libraries and call functions */
}
The file jenkinsJob.groovy needs to have a single method only by the name:
def call(Map params[:]){
// method body
}

Jenkins Shared Library failed to reference

I'm failing to reference a second groovy file in my src of my repo.
My set up is this: library name pipeline-library-demo
github
I have added a second groovy file to the src folder
app_config.groovy
#!/usr/bin/groovy
def bob(opt) {
sh "docker run --rm " +
'--env APP_PATH="`pwd`" ' +
'--env RELEASE=${RELEASE} ' +
"-v \"`pwd`:`pwd`\" " +
"-v /var/run/docker.sock:/var/run/docker.sock " +
"docker_repo/bob:1.4.0-8" ${opt}
}
def test(name) {
echo "Hello ${name}"
}
The Jenkins file I am using is:
pipeline {
Library('pipeline-library-demo') _
agent {
node {
label params.SLAVE
config = new app_config()
}
}
parameters {
string(name: 'SLAVE', defaultValue: 'so_slave')
}
stages {
stage('Demo') {
steps {
echo 'Hello World'
sayHello 'Dave'
}
}
stage('bob') {
steps {
config.test 'bob'
config.bob '--help'
}
}
}
}
I think I am not referencing the app_config.groovy correctly and it's not finding
Library call should come in starting of the jenkins file, please follow below
If you have added the library configuration in jenkins configuration then call should be like below:-
#Library('pipeline-library-demo')_
If you want to call the library dynamically you should call like below:-
library identifier: 'custom-lib#master', retriever:
modernSCM([$class:'GitSCMSource',remote:
'git#git.mycorp.com:my-jenkins-utils.git', credentialsId:
'my-private-key'])
please refer this link
And please define package in your app_config.groovy. (ex. package com.cleverbuilder)

How can I mount a secret file into a docker image in a declarative Jenkins pipeline?

Currently I have a pipeline working something like this:
pipeline {
agent {
docker {
label 'linux'
image 'java:8'
args '-v /home/tester/.gradle:/.gradle'
}
}
environment {
HOME = '/'
GRADLE_USER_HOME = '/.gradle'
GRADLE_PROPERTIES = credentials('gradle.properties')
}
stages {
stage('Build') {
steps {
sh 'cp ${GRADLE_PROPERTIES} ${GRADLE_USER_HOME}/'
sh './gradlew clean check'
}
}
}
}
Problem is, gradle.properties ends up being put in a more known location on the host system for the duration of the build.
I know that Docker lets me 'mount' files from the host. So I'd like to do this instead:
agent {
docker {
label 'linux'
image 'java:8'
args '-v /home/tester/.gradle:/.gradle ' +
'-v ' + credentials('gradle.properties') +
':/.gradle/gradle.properties'
}
}
Unfortunately, this ends up running this:
$ docker run -t -d -u 1001:1001 -v /home/tester/.gradle:/.gradle -v #credentials(<anonymous>=gradle.properties):/.gradle/gradle.properties -w
Is there a way to have it expand it?
I couldn't find a way to make the environment work for docker args.
My workaround ended up being switching back to scripted pipeline:
agent {
label 'linux'
}
environment {
GRADLE_PROPERTIES = credentials('gradle.properties')
}
steps{
script {
docker.image('java:8').inside('-v /home/tester/.gradle:/.gradle ' +
"-v $GRADLE_PROPERTIES:/.gradle/gradle.properties"){
}
}
}

Resources