Active Choice Parameter with Azure VM LIST - jenkins

I'm trying to create a VM list out of active choice parameter:
def command = 'az vm list --resource-group test-test-test \
--query '[].{computerName:osProfile.computerName}' \
--output tsv'
def proc = command.execute()
proc.waitFor()
def output = proc.in.text
def exitcode= proc.exitValue()
def error = proc.err.text
if (error) {
println "Std Err: ${error}"
println "Process exit code: ${exitcode}"
return exitcode
}
//println output.split()
return output.split()
How am I supposed to write the groovy script inside the Active choice parameter in Jenkins? I just want to fetch all azure VMS in a list and send them to active choice parameter. One more question does the active choice paramter authenticate only on master? Can it authenticate on a node that has the AZ binary

Yes the script will always run on the Master and it can be included like shown below.
properties([
parameters([
[$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Select the Host',
name: 'Host',
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: false,
script:
'return [\'Could not get Host\']'
],
script: [
classpath: [],
sandbox: false,
script:
'''
def command = 'az vm list --resource-group dhl-dhlcom-bbb \
--query '[].{computerName:osProfile.computerName}' \
--output tsv'
def proc = command.execute()
proc.waitFor()
def output = proc.in.text
def exitcode= proc.exitValue()
def error = proc.err.text
if (error) {
println "Std Err: ${error}"
println "Process exit code: ${exitcode}"
return exitcode
}
return output.split()
'''
]
]
]
])
])
pipeline {
agent any
stages {
stage('Build') {
steps {
script {
echo "Host:::: ${params.Host}"
}
}
}
}
}

Related

Jenkins File - Execute shell command in active choice script

everyone, I'm using plugin "Active Choices" in my Jenkins, I try to do something condition, and the return based on environment host that will be executed in shell command in my Jenkins file. the command like "echo ${BUILD_ENVIRONMENT}, echo ${BUILD_VERSION}..etc".
Already doing this but the list is still empty. now, what do I have to do to make this work? thank you.
JenkinsFile:
properties([
parameters([
[$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
name: 'ENVIRONMENT',
description: 'Select Environment',
script: [
$class: 'GroovyScript',
script: [
classpath: [],
sandbox: true,
script: '''
def getEnvVar(String name) {
return sh(script: "echo \${$name}", returnStdout: true).trim()
}
def env = getEnvVar("ENVIRONMENT")
if (envs != "testing") {
return ["stage", "dev", "prod"]
}else{
return ["testing"]
}
''',
],
]
]
])
])
Output:
im fix it with another solution, but maybe isnt the best option.
1st create a method to load the env file (i set the values on it), then define to jenkins global variable.
getEnvHosts = { ->
node {
script {
// Get the environment hosts file
def props = readProperties file: '/var/lib/jenkins/env/dast-service-env'
//define to jenkins global variable
env.BUILD_ENVIRONMENT = props['BUILD_ENVIRONMENT']
}
}
}
and then i call the "BUILD_ENVIRONMENT" with ${env.BUILD_ENVIRONMENT} like this in active choice parameter:
getEnvHosts()
properties([
parameters([
[$class : 'ChoiceParameter',
choiceType : 'PT_SINGLE_SELECT',
name : 'BUILD_ENVIRONMENT',
description: "Select Environment default is ${env.BUILD_ENVIRONMENT}",
script : [
$class: 'GroovyScript',
script: [
classpath: [],
sandbox : true,
script : """
def envs = "${env.BUILD_ENVIRONMENT}"
if (envs == "stage") {
choices = ["stage", "dev", "prod", "testing"]
}else if (envs == "dev") {
choices = ["dev", "prod", "stage", "testing"]
}else if (envs == "prod") {
choices = ["prod", "dev", "stage", "testing"]
}else{
choices = ["testing", "stage", "dev", "prod"]
}
return choices
""",
],
]
],
])
])

Jenkins variable not being transferred between stages

I have this code:
#Library('cm-library') _
def GITOPS_GITHUB_TOKEN = credentials('someToken')
def GITOPS_GITHUB_BRANCH = "dev"
def X_GW_IMS_ORG_ID = "someId"
def SPRING_PROFILES_ACTIVE = "dev"
def GITOPS_INPUT_JOBSTORUN = "someJobToRun"
def IMG = "someImage"
def GITOPS_IMS_CLIENT_SECRET = ""
def GITOPS_IMS_CLIENTCODE = ""
def ARTIFACTORY_API_TOKEN = ""
pipeline {
agent any
stages {
stage('Prepare Variables') {
steps {
script {
dockerRegistryVaultAuth("some-vault.com", "dev") {
def configuration = [$class : 'VaultConfiguration',
vaultUrl : "some-vault.com",
vaultCredentialId: env.VAULT_ROLE]
def secrets = [
[
$class: 'VaultSecret', path: "${env.VAULT_PATH}/keys", secretValues:
[
[$class: 'VaultSecretValue', envVar: 'GITOPS_IMS_CLIENT_SECRET', vaultKey: 'someKey'],
[$class: 'VaultSecretValue', envVar: 'GITOPS_IMS_CLIENTCODE', vaultKey: 'someOtherKey'],
[$class: 'VaultSecretValue', envVar: 'ARTIFACTORY_API_TOKEN', vaultKey: 'someToken']
]
]
]
wrap([$class: 'VaultBuildWrapper', vaultSecrets: secrets, configuration: configuration]) {
sh "echo working"
}
}
}
}
}
stage('Build and push docker') {
steps {
echo "stage 2!!!"
echo "---------env.GITOPS_IMS_CLIENTCODE=$env.GITOPS_IMS_CLIENTCODE"
echo "---------GITOPS_IMS_CLIENT_SECRET=$GITOPS_IMS_CLIENT_SECRET"
sh "docker run -it -e GITOPS_GITHUB_BRANCH=${GITOPS_GITHUB_BRANCH} \
-e GITOPS_GITHUB_TOKEN=${GITOPS_GITHUB_TOKEN} \
-e GITOPS_IMS_CLIENT_SECRET=${GITOPS_IMS_CLIENT_SECRET} \
-e GITOPS_IMS_CLIENTCODE=${GITOPS_IMS_CLIENTCODE} \
-e X_GW_IMS_ORG_ID=${X_GW_IMS_ORG_ID} \
-e ARTIFACTORY_API_TOKEN=${ARTIFACTORY_API_TOKEN} \
-e REGION_NAME=local \
${IMG}"
}
}
stage('Stage 3') {
steps {
echo 'stage three here!'
}
}
}
}
I'm trying to make a docker container run from my Jenkins platform.
It seems like the variable values aren't being transferred from one stage to another. I also doubt the script I'm trying to run is right, but that's another problem.
Anyone any clue how to fix it?
When you declare a variable with the def keyword, it will be bound to the scope it's declared in. So simply remove the def keyword from the declaration.
pipeline {
agent any
stages {
stage('11') {
steps {
script {
vr = "test"
}
}
}
stage('22') {
steps {
script {
echo "$vr"
}
}
}
}
}

Jenkins parameters using groovy script

UPDATE
I have a simple pipeline where I want to receive in parameters multiple choices from a file.
In my file I have
#Test1,Accounts
#Test2,Services
#Test3,Accesses
and I want to have all of "#Test1", "#Test2" and "#Test3" in checkboxes as parameters so I would run only the tests selected.
But I'm not understanding what I'm doing wrong.
Pipeline
def code = """tests = getChoices()
return tests
def getChoices() {
def filecontent = readFile "/var/jenkins_home/test.txt"
def stringList = []
for (line in filecontent.readLines()) {stringList.add(line.split(",")[0].toString())}
List modifiedList = stringList.collect{'"' + it + '"'}
return modifiedList
}""".stripIndent()
properties([
parameters([
[$class : 'CascadeChoiceParameter',
choiceType : 'PT_CHECKBOX',
description : 'Select a choice',
filterLength : 1,
filterable : false,
name : 'choice1',
referencedParameters: 'role',
script : [$class : 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox : true,
script : 'return ["ERROR"]'
],
script : [
classpath: [],
sandbox : true,
script : code
]
]
]
])
])
pipeline {
agent {
docker { image 'node:latest' }
}
stages {
stage('Tags') {
steps {
getChoices()
}
}
}
}
def getChoices() {
def filecontent = readFile "/var/jenkins_home/test.txt"
def stringList = []
for (line in filecontent.readLines()) {
stringList.add(line.split(',')[0].toString())
}
List modifiedList = stringList.collect { '"' + it + '"' }
echo "$modifiedList"
return modifiedList
}
With this approach I know I can use multi-select checkboxes because I tried to substitute
def code = """ tests = ["Test1", "Test2", "Test3"]
return tests""".stripIndent()
and I get the output that I wanted.
But when I run my pipeline I get build SUCCESS but always get fallbackScript in my Build parameters checkbox. Can anyone help me out understand what is causing fallbackScript to run always? Thanks :)
If you want to auto-populate build parameters you have to return a list of parameters from your function. When you execute the pipeline the build with parameters will be populated. Note in this was only from the second execution of the pipeline the new parameters will be available. Refer following.
pipeline {
agent any
parameters{
choice(name: 'TESTES', choices: tests() , description: 'example')
}
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
def tests() {
return ["Test01", "Test2", "Test4"]
}
If you want to get user input each time you execute a build you should move your choice parameter into a stage. Please refer to the following.
pipeline {
agent any
stages {
stage('Get Parameters') {
steps {
script{
def choice = input message: 'Please select', ok: 'Next',
parameters: [choice(name: 'PRODUCT', choices: tests(), description: 'Please select the test')]
echo '$choice'
}
}
}
}
}
def tests() {
return ["Test01", "Test2", "Test4"]
}
Update 02
Following is how to read from a file and dynamically create the choice list.
pipeline {
agent any
stages {
stage('Get Parameters') {
steps {
script{
sh'''
echo "#Test1,Accounts" >> test.txt
echo "#Test2,Services" >> test.txt
'''
def choice = input message: 'Please select', ok: 'Next',
parameters: [choice(name: 'PRODUCT', choices: getChoices(), description: 'Please select the test')]
}
}
}
}
}
def getChoices() {
def filecontent = readFile "test.txt"
def choices = []
for(line in filecontent.readLines()) {
echo "$line"
choices.add(line.split(',')[0].split('#')[1])
}
return choices
}

Jenkins is not getting the url value passed, it says null

While running my tests in jenkins pipeline, it says you have passed the cy.request() url as null. I have mentioned all of the env variables in jenkins. Could someone please advise what is the problem here ?
Error:
CypressError: cy.request()requires aurl. You did not provide a url.
my .env file:
CYPRESS_TEST_USERNAME=Test1
CYPRESS_TEST_PASSWORD=BooksTest1234
CYPRESS_BASE_URL=https://my-test-url.com/books/
CYPRESS_API_URL=https://my-test-url.com/api/v1.0/books/
my jenkins file
def channel = '#jenkins-cypress'
def ARTEFACT_DIR=""
pipeline {
agent any
stages {
stage('Clone books-suite') {
steps {
dir('books-co') {
script {
checkout([
$class: 'GitSCM',
branches: [
[name: "origin/develop"]
],
extensions: [
[$class: 'CleanCheckout'],
[$class: 'LocalBranch', localBranch: '**'],
[$class: 'CloneOption', depth: 1, noTags: false, reference: '', shallow: true, timeout: 10]
],
userRemoteConfigs: [[
credentialsId: 'fsdf68fs61-esdfsdf56546-92ea-7345bcfsfsdfb3d391',
url: 'ssh://git#bitbucket_url_location'
]],
doGenerateSubmoduleConfigurations: false,
submoduleCfg: []
])
ARTEFACT_DIR="${env.WORKSPACE}/artefacts/${BUILD_NUMBER}"
}
}
}
}
stage('Run cypress') {
steps {
script {
mattermostSend color: 'good', channel: channel, message: "**STARTING** - Cypress starts (<${env.BUILD_URL}|build ${env.BUILD_NUMBER}>)"
sh "mkdir -p \"${ARTEFACT_DIR}/videos\""
sh "mkdir -p \"${ARTEFACT_DIR}/screenshots\""
def baseUrlConfig="-e CYPRESS_baseUrl=https://my-test-url.com/books/"
def screenshotsFolderConfig="screenshotsFolder=/artefacts/screenshots"
def videosFolderConfig="videosFolder=/artefacts/videos"
def config = "--config ${screenshotsFolderConfig},${videosFolderConfig}"
def cypressArgs = "run --headless --browser chrome ${config} --project /books-suite"
sh """
docker run ${baseUrlConfig} \
-v \"${ARTEFACT_DIR}:/artefacts\" \
-e CYPRESS_OUTPUT_FILE=\"/artefacts/report.html\" \
-e CYPRESS_TEST_USERNAME=\"Test1\" \
-e CYPRESS_TEST_PASSWORD=\"BooksTest1234\" \
-e CYPRESS_BASE_URL=\"https://my-test-url.com/books/\" \
-e CYPRESS_API_URL=\"https://my-test-url.com/api/v1.0/books/\" \
cypress:latest \
/node_modules/.bin/cypress ${cypressArgs}
"""
mattermostSend color: 'good', channel: channel, message: "**SUCCESSED** - Cypress CI passed successfully (<${env.BUILD_URL}|build ${env.BUILD_NUMBER}>)"
}
}
}
}
post {
always {
script {
USER_ID = get_uid()
GROUP_ID = get_gid()
sh """
docker run --user ${USER_ID}:${GROUP_ID} \
-v \"${ARTEFACT_DIR}:/artefacts\" \
-v \"${env.WORKSPACE}/books-co:/books\" \
-e JSON_DIR=\"/books/tests/cypress/cucumber-json\" \
-e OUTPUT_FILE=\"/artefacts/report.html\" \
cypress-books-report:latest
"""
}
archiveArtifacts artifacts: "artefacts/${BUILD_NUMBER}/**/*", fingerprint: true
emailext attachmentsPattern: "artefacts/${BUILD_NUMBER}/**/*",
body: '${FILE, path="' + "artefacts/${BUILD_NUMBER}/report.html" + '"}',
mimeType: 'text/html',
to: 'first.lastman#books.com',
subject: "Cypress Jenkins Build ${currentBuild.currentResult}: Job ${env.JOB_NAME}"
sh "rm -Rf artefacts/${BUILD_NUMBER}"
mattermostSend color: 'good', channel: channel, message: "**SUCCESSED** - Cypress CI report generated (<${env.BUILD_URL}|build ${env.BUILD_NUMBER}>)"
}
failure {
mattermostSend color: 'danger', channel: channel, message: "**FAILED** - cypress CI failed (<${env.BUILD_URL}|build ${env.BUILD_NUMBER}> - <${env.BUILD_URL}console|click here to see the console output>)"
}
}
}
def get_uid() {
node('master') {
return sh(script: "id -u ${USER}", returnStdout: true).trim()
}
}
def get_gid() {
node('master') {
return sh(script: "id -g ${USER}", returnStdout: true).trim()
}
}
plugins/index.js :
module.exports = (on, config) => {
on('file:preprocessor', cucumber()),
on('before:browser:launch', (browser, launchOptions) => {
console.log("Print browser name: "+browser.name);
if (browser.name === 'chrome' || browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--disable-features=SameSiteByDefaultCookies') // bypass 401 unauthorised access on chromium-based browsers
return launchOptions
}
if (browser.name === 'chrome') {
// launch chrome using incognito
launchOptions.args.push(' --incognito')
return launchOptions
}
if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--disable-gpu');
return launchOptions
}
});
config = dotenvPlugin(config)
return config
};
commands.js file
Cypress.Commands.add("loginReq", () => {
cy.request({
method: 'POST',
url: Cypress.env('BASE_URL'), // baseUrl is prepended to url
form: true,
body: {
loginUsername: Cypress.env('TEST_USERNAME'),
loginPassword: Cypress.env('TEST_PASSWORD')
}
}).then((response)=>{
console.log("login success: "+response);
})
});
When you set CYPRESS_BASE_URL, Cypress config will look like:
{
"baseUrl": "your set base url",
"env": {
}
}
You can have a look when you run cypress open and then go to Settings in the opened test runner.
The problem is that Cypress.env() reads variables from env object, where your base url is not set because CYPRESS_BASE_URL sets baseUrl property, not env.baseUrl property.
If you want to set CYPRESS_BASE_URL and access it from your tests, then you have to invoke it with Cypress.config().baseUrl.
However, you don't really need to call (not in your example) Cypress.config().baseUrl because Cypress does that automatically for you, so:
cy
.visit('/');
really means that Cypress prepends the base url for you. The same goes for cy.request(), so in your example, you can delete it from there.

groovy: MissingPropertyException: No such property:

I am facing an issue when shell command is returning non existent value because output produces no value as env.version == '1.0.0.232'-->false, does not exist in pypy server.
but when env.version == '1.0.0.23'--> true, does exist in pypy server, code proceed as normal.
Jenkins code:
pipeline {
agent { label 'master' }
parameters {
string(defaultValue: 'DEV', description: '', name: 'ENV', trim: true)
string(defaultValue: 'sys', description: '', name: 'platform_type', trim: true)
string(defaultValue: 'server2', description: '', name: 'dev_app_host', trim: true)
string(defaultValue: 'server1', description: '', name: 'dev_xbar_host', trim: true)
string(defaultValue: '1.0.0.23', description: '', name: 'VERSION', trim: true)
booleanParam(defaultValue: false, description: 'force build if possible', name: 'force_build')
}
environment {
}
stages {
stage('build') {
steps {
script {
try{
try{
def version_exists = sh(script: "ssh -o StrictHostKeyChecking=no ansible#pip_server ls /var/pypi/packages/dev/ | grep ${env.app_module_name} | grep ${env.VERSION}" , returnStdout: true) ?: 'no_files_found'
echo version_exists
echo version_exists.inspect()
echo version_exists.dump()
} catch(e){
echo "inner exception: ${e}"
}
} catch (e) {
echo "outer exception: ${e}"
currentBuild.result = 'FAILURE'
}
}
}
}
}
}
Jenkins relevant long:
+ grep 1.0.0.232
+ grep dvmt_event_processor
+ ssh -o StrictHostKeyChecking=no ansible#pip_server ls /var/pypi/packages/dev/
[Pipeline] echo
inner exception: hudson.AbortException: script returned exit code 1
[Pipeline] echo
outer exception: groovy.lang.MissingPropertyException: No such property: version_exists for class: groovy.lang.Binding
PS: can the shell command be improved upon?
grep returns status code 1 when it finds no matching lines. Jenkins interprets a non-0 status as the script failing, so it throws a hudson.AbortException rather than assigning the output to version_exists.
Try something like this:
def version_exists = sh( " ... | grep ${env.VERSION} || echo not_found", returnStdout: true)

Resources