Jenkins: Populate Choice Parameter from Shell Command
For my requirement I needed to populate a choice parameter (select list) with the list of compartments from my Oracle Cloud Infrastructure tenancy. To do this I invoke the OCI CLI command line client to fetch the list of compartments. I then populate an Active Choice parameters with the key/value pairs of compartment name and compartment ID, so that the ID is passed along to the Jenkins pipeline.
Prerequisites
The OCI CLI client needs to be accessible by the Jenkins user on the server. To do this, simply install the CLI client as the Jenkins user. The installation is fairly easy when using the Quickstart guide from Oracle.
In my case, I installed the CLI client in /var/lib/jenkins/bin.
For further CLI info check out OCI Command Line Interface (CLI) Basics.
To fetch the compartments, the CLI command requires the Tenancy OCID. You could simply add id in plain text to the Groovy script below, but I chose to store it in a Jenkins Secret Text credential.
Test the CLI functionality by logging into the command line on the Jenkins server and run
/var/lib/jenkins/bin/oci --profile DEFAULT iam compartment list --compartment-id ocid1.tenancy.oc1..example
This should result in a JSON list of compartments. We’ll fine-tune this command in the Groovy script later.
The Job
Create a new Jenkins Pipeline job.
Check This project is parameterized, and select the Active Choices parameter.
Give the parameter a name (e.g. compartment) and make it a Single Select choice type.
Now click the Groovy Script radio button and add the following Groovy script:
import groovy.json.JsonSlurper
import jenkins.model.*
import hudson.model.*
//Pull in credentials, filter out the secret containing the tenancy OCID, and return the secret text.
def tenancy_ocid = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.Credentials.class,
Jenkins.instance,
null,
).find {it.id == 'tenancy_ocid'}.secret;
def oci = '/var/lib/jenkins/bin/oci' //oci command shortcut
def sout = new StringBuilder(), serr = new StringBuilder() //standard out and error strings
//Assemble OCI CLI command to fetch compartments
def cmd = "$oci iam compartment list -c $tenancy_ocid --compartment-id-in-subtree true"
def proc = cmd.execute() //Execute OS command
proc.waitForProcessOutput(sout, serr) //Wait for command to complete
proc.waitForOrKill(10000) //Set timeout
//Catch errors and return error text
if (serr) {
return ['Error $serr']
}
//Process JSON output from CLI command
def parser = new JsonSlurper()
def Object jsonResp = parser.parseText(sout.toString())
def compartments = new HashMap() //A HashMap is list of key/value pairs
def comps = jsonResp.data
//Assemble Hash Map of compartments with return and display values
comps.each {cmp ->
compartments.put("$cmp.id","$cmp.name")
}
//Return Hash Map. This populates the select list.
return compartments
Finally add a simple Pipeline Script to output the the OCID of the selected compartment.
node {
stage ("Compartment") {
echo "Compartment OCID ${compartment}"
}
}
Now save the pipeline and built it. The first time you build it, you man not see the Build with parameters link. It should appear the second time you build the job.
The compartment select list will now display the compartment names, and the returned value will be the compartment OCID.
You now have the tools to build all kinds of dynamic parameters.
Cheers!