I have a nodenames that is going to be changing in a variable with each node on each line for example:
node1
node2
node3
The node will be assigned to variable, but because the node name will be dynamic am looking for way that the prompt will ask the user to choose from the chocie node 1 or node 2 or node 3 in the params
For example
def choosenode(nodename) {
def nodechosen = input(
id: 'userInput',
message: 'Choose:',
parameters: [[
$class : 'ChoiceParameterDefinition',
choices : nodename.join("\n"),
description: 'choosing node during prompt',
name : 'nodename'
]]
)
return nodechosen
}
Do you want to do something like below?
pipeline {
agent any
stages {
stage('Stage') {
steps {
script {
def nodechosen = input message: 'Choose', ok: 'Next',
parameters: [choice(name: 'Node', choices: gerNodeNames(), description: 'Select something')]
node(nodechosen) {
echo "Running in Selected node"
}
}
}
}
}
}
def gerNodeNames() {
// Dummy code to create a file with node names
sh "echo 'node1' >> nodeList.txt"
sh "echo 'node2' >> nodeList.txt"
sh "echo 'node3' >> nodeList.txt"
// Reading the file
def data = readFile(file: 'nodeList.txt')
return data
}
Related
SSHUER in stage one prints as required. But in stage two it doesn't print and gives me a null value. All three attempt statements in stage two are not working. I can't use script block as I have some special characters in the actual code. Any suggestions as to how to fetch the value of SSHUSER in stage two.
def SSHUSER
environment {
if(params.CLOUD == 'google') {
SSHUSER = "test1"
} else if (params.CLOUD == 'azure') {
SSHUSER = "test2"
}
}
pipeline {
stage('stage one') {
steps {
echo "first attempt '${SSHUSER}'"
}
}
stage('stage two') {
steps {
sh '''#!/bin/bash
echo "first attempt '${SSHUSER}'"
echo "second attempt \${SSHUSER}"
echo "thrid attempt \$SSHUSER"
if ssh \${SSHUSER}#$i 'test -e /tmp/test'";
then
echo "$i file exists "
fi
'''
}
}
}
your usage of the environment block is a bit weird, it should reside inside the pipeline block and variables should be initialized inside the environment block.
If it is defined outside the variables will not be passed to the shell script as environment variables.
If you want to use the environment block inside the `pipeline' block just define the parameters (as strings) you want and they will be available for all stages, and they will be passed as environment variables for the shell.
For example:
pipeline {
agent any
parameters{
string(name: 'CLOUD', defaultValue: 'google', description: '')
}
environment {
SSHUSER = "${params.CLOUD == 'google' ? 'test1' : 'test2'}"
}
stages {
stage('stage one') {
steps {
echo "first attempt '${SSHUSER}'"
}
}
stage('stage two') {
steps {
sh '''#!/bin/bash
echo "first attempt '${SSHUSER}'"
echo "second attempt \${SSHUSER}"
echo "thrid attempt \$SSHUSER"
if ssh \${SSHUSER}#$i 'test -e /tmp/test'";
then
echo "$i file exists "
fi
'''
}
}
}
}
If you don't want to use the environment block or mange the parameters by yourself you can do it outside the pipeline block using Global variables but then they will not be passed environment variables and you will need to use string interpolation (""" instead of ''') to calculate the values when passing the command to the shell:
SSHUSER = ''
if(params.CLOUD == 'google') {
SSHUSER = "test1"
} else if (params.CLOUD == 'azure') {
SSHUSER = "test2"
}
pipeline {
agent any
parameters{
string(name: 'CLOUD', defaultValue: 'google', description: 'Bitbucket Payload', trim: true)
}
stages {
stage('stage one') {
steps {
echo "first attempt '${SSHUSER}'"
}
}
stage('stage two') {
steps {
sh """#!/bin/bash
echo "first attempt '${SSHUSER}'"
echo "second attempt ${SSHUSER}"
echo "thrid attempt $SSHUSER"
if ssh ${SSHUSER}#\$i 'test -e /tmp/test'";
then
echo "\$i file exists "
fi
"""
}
}
}
}
I'm trying to convert my jenkins pipeline to a shared library since it can be reusable on most of the application. As part of that i have created groovy file in vars folder and kept pipeline in jenkins file in github and able to call that in jenkins successfully
As part of improving this i want to pass params, variables, node labels through a file so that we should not touch jenkins pipeline and if we want to modify any vars, params, we have to do that in git repo itself
pipeline {
agent
{
node
{
label 'jks_deployment'
}
}
environment{
ENV_CONFIG_ID = 'jenkins-prod'
ENV_CONFIG_FILE = 'test.groovy'
ENV_PLAYBOOK_NAME = 'test.tar.gz'
}
parameters {
string (
defaultValue: 'test.x86_64',
description: 'Enter app version',
name: 'app_version'
)
choice (
choices: ['10.0.0.1','10.0.0.2','10.0.0.3'],
description: 'Select a host to be delpoyed',
name: 'host'
)
}
stages {
stage("reading properties from properties file") {
steps {
// Use a script block to do custom scripting
script {
def props = readProperties file: 'extravars.properties'
env.var1 = props.var1
env.var2 = props.var2
}
echo "The variable 1 value is $var1"
echo "The variable 2 value is $var2"
}
In above code,i used pipeline utility steps plugin and able to read variables from extravars.properties file. Is it same way we can do for jenkins parameters also? Or do we have any suitable method to take care of passing this parameters via a file from git repo?
Also is it possible to pass variable for node label also?
=====================================================================
Below are the improvements which i have made in this project
Used node label plugin to pass the node name as variable
Below is my vars/sayHello.groovy file content
def call(body) {
// evaluate the body block, and collect configuration into the object
def pipelineParams= [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = pipelineParams
body()
pipeline {
agent
{
node
{
label "${pipelineParams.slaveName}"
}
}
stages {
stage("reading properties from properties file") {
steps {
// Use a script block to do custom scripting
script {
// def props = readProperties file: 'extravars.properties'
// script {
readProperties(file: 'extravars.properties').each {key, value -> env[key] = value }
//}
// env.var1 = props.var1
// env.var2 = props.var2
}
echo "The variable 1 value is $var1"
echo "The variable 2 value is $var2"
}
}
stage ('stage2') {
steps {
sh "echo ${var1}"
sh "echo ${var2}"
sh "echo ${pipelineParams.appVersion}"
sh "echo ${pipelineParams.hostIp}"
}
}
}
}
}
Below is my vars/params.groovy file
properties( [
parameters([
choice(choices: ['10.80.66.171','10.80.67.6','10.80.67.200'], description: 'Select a host to be delpoyed', name: 'host')
,string(defaultValue: 'fxxxxx.x86_64', description: 'Enter app version', name: 'app_version')
])
] )
Below is my jenkinsfile
def _hostIp = params.host
def _appVersion = params.app_version
sayHello {
slaveName = 'master'
hostIp = _hostIp
appVersion = _appVersion
}
Now Is it till we can improve this?Any suggestions let me know.
I have the below Jenkins pipeline and I am trying to echo out SolutonName and TargetVersion value. I tried different approaches and it either gave me error or not the result I wanted.
If I use echo "Solution Name: $solution['SolutionName']", it gave a result of Solution Name: SolutionA={SolutionName=SolutionA, TargetVersion=1.0.0.0}['SolutionName'], which is the map itself with ['SolutionName'] at the end.
If I use echo "Solution Name: ${solution.SolutionName}", it throws an error of org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: No such field found: field java.util.AbstractMap$SimpleImmutableEntry SolutionName
def NodeLabel = 'windows'
// Solution
def SolutionMap = [
SolutionA: [
SolutionName: 'SolutionA',
TargetVersion: '1.0.0.0'
],
SolutionB: [
SolutionName: 'SolutionB',
TargetVersion: '2.1.0.0'
]
]
pipeline {
agent { node { label "${NodeLabel}" } }
stages {
stage('Test') {
steps {
script {
SolutionMap.each { solution ->
stage(solution.key) {
echo "Solution Name: ${solution['SolutionName']}"
echo "Solution Name: ${solution['TargetVersion']}"
}
}
}
}
}
}
}
I figured it out, apparently I need to call:
echo "Solution Name: $Solution.value.SolutionName"
So it seems like calling $Solution does not assume it wants its value so I need to call $Solution.value to get the value and from there call .SolutionName to get the child value.
I think i dont get how matrix builds work. When i set some variable in some stage depending on which node i run, then on rest of the stage sometimes this variable is set as it should and sometimes it gets values from other nodes (axes). In example below its like job which runs on ub18-1 sometimes has VARIABLE1='Linux node' and sometimes is VARIABLE1='Windows node'. Or gitmethod sometimes it is created from LinuxGitInfo and sometimes WindowsGitInfo.
Source i based on
https://jenkins.io/doc/book/pipeline/syntax/#declarative-matrix
Script almost exactly the same as real one
#Library('firstlibrary') _
import mylib.shared.*
pipeline {
parameters {
booleanParam name: 'AUTO', defaultValue: true, description: 'Auto mode sets some parameters for every slave separately'
choice(name: 'SLAVE_NAME', choices:['all', 'ub18-1','win10'],description:'Run on specific platform')
string(name: 'BRANCH',defaultValue: 'master', description: 'Preferably common label for entire group')
booleanParam name: 'SONAR', defaultValue: false, description: 'Scan and gateway'
booleanParam name: 'DEPLOY', defaultValue: false, description: 'Deploy to Artifactory'
}
agent none
stages{
stage('BuildAndTest'){
matrix{
agent {
label "$NODE"
}
when{ anyOf{
expression { params.SLAVE_NAME == 'all'}
expression { params.SLAVE_NAME == env.NODE}
}}
axes{
axis{
name 'NODE'
values 'ub18-1', 'win10'
}
}
stages{
stage('auto mode'){
when{
expression { return params.AUTO }
}
steps{
echo "Setting parameters for each slave"
script{
nodeLabelsList = env.NODE_LABELS.split()
if (nodeLabelsList.contains('ub18-1')){
println("Setting params for ub18-1");
VARIABLE1 = 'Linux node'
}
if (nodeLabelsList.contains('win10')){
println("Setting params for Win10");
VARIABLE1 = 'Windows node'
}
if (isUnix()){
gitmethod = new LinuxGitInfo(this,env)
} else {
gitmethod = new WindowsGitInfo(this, env)
}
}
}
}
stage('GIT') {
steps {
checkout scm
}
}
stage('Info'){
steps{
script{
sh 'printenv'
echo "branch: " + env.BRANCH_NAME
echo "SLAVE_NAME: " + env.NODE_NAME
echo VARIABLE1
gitinfo = new GitInfo(gitmethod)
gitinfo.init()
echo gitinfo.author
echo gitinfo.id
echo gitinfo.msg
echo gitinfo.buildinfo
}
}
}
stage('install'){
steps{
sh 'make install'
}
}
stage('test'){
steps{
sh 'make test'
}
}
}
}
}
}
}
Ok i solved the problem by defining variables maps with node/slave names as keys. Some friend even suggested to define variables in yml/json file in repository and parse them. Maybe i will, but so far this works well
example:
before the pipelines
def DEPLOYmap = [
'ub18-1': false,
'win10': true
]
in stages
when {
equals expected: true, actual: DEPLOYmap[NODE]
}
I need to clean up some Kubernete namespaces(hello_namespace, second,my_namespace1, my_namespace45,my_namespace44 for example and I do it with a jenkins job.
I read with kubectl the namespace I need to clean up and then I want to fire a job to delete it, My code should be something like that
pipeline {
agent { label 'master' }
stages {
stage('Clean e2e') {
steps {
script {
sh "kubectl get namespace |egrep 'my_namespace[0-9]+'|cut -f1 -d ' '>result.txt"
def output=readFile('result.txt').trim()
}
}
}
The ouput of this code will be the variable $output with the values:
my_namespace1
my_namespace45
my_namespace44
Separated by line, now I want to fire a job with the namespace like parameter , how can I do that? (My problem is to read the file and fire independent job for each namespace)
while (output.nextLine() callJob)
The job call should be like
build job: 'Delete temp Stage', parameters:
[string(name: 'Stage', value: "${env.stage_name}")]
I already got it :)
#!groovy
pipeline {
agent { label 'master' }
stages {
stage('Clean up stages') {
steps {
script {
sh '(kubectl get namespace |egrep "namespace[0-9]+"|cut -f1 -d " "|while read i;do echo -n $i";" ; done;)>result.txt'
def stages = readFile('result.txt').trim().split(';')
for (stage in stages) {
if (stage?.trim()) {
echo "deleting stage: $stage"
build job: 'Delete temp Stage', parameters:
[string(name: 'Stage', value: "$stage")]
}
}
}
}
}
}
}