Create jenkins JLNP slave programmatically
Creating an agent programmatically
You can use the create-node
CLI command to create new agents with a given configuration.
For example, given this minimal JNLP agent configuration in a file config.xml
:
<slave>
<remoteFS>/opt/jenkins</remoteFS>
<numExecutors>2</numExecutors>
<launcher class="hudson.slaves.JNLPLauncher" />
</slave>
you can run the create-node
command via the CLI client, or the SSH interface:
cat config.xml | java -jar jenkins-cli.jar -s https://jenkins/ create-node my-agent
Viewing agent configuration
To see what the XML configuration looks like for an existing agent, you can append config.xml
to an agent URL, e.g. https://jenkins/computer/some-agent-name/config.xml, or you can use the get-node
CLI command.
Fetching the per-agent secret programmatically
To fetch the secret hex value without using the Jenkins web UI, you can run a script via the groovy
CLI command:
echo 'println jenkins.model.Jenkins.instance.nodesObject.getNode("my-agent")?.computer?.jnlpMac' \
| java -jar ~/Downloads/jenkins-cli.jar -s https://jenkins/ groovy =
This will return the secret value directly. Note that in order to use the groovy
command via the SSH interface, you need Jenkins 2.46 or newer. In earlier versions, it only works via the CLI client.
You can also create an agent using the REST API. This is especially useful when having an apache proxy in front (see issue JENKINS47279) and no direct access to the jenkins otherwise (e.g. in a corporate network) where CLI will not work.
I recommend to create an API token for this purpose. Then you can do something like this
Linux (Bash)
export JENKINS_URL=https://jenkins.intra
export JENKINS_USER=papanito
export JENKINS_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxx
export NODE_NAME=testnode
export JSON_OBJECT="{ 'name':+'${NODE_NAME}',+'nodeDescription':+'Linux+slave',+'numExecutors':+'5',+'remoteFS':+'/home/jenkins/agent',+'labelString':+'SLAVE-DOCKER+linux',+'mode':+'EXCLUSIVE',+'':+['hudson.slaves.JNLPLauncher',+'hudson.slaves.RetentionStrategy\$Always'],+'launcher':+{'stapler-class':+'hudson.slaves.JNLPLauncher',+'\$class':+'hudson.slaves.JNLPLauncher',+'workDirSettings':+{'disabled':+true,+'workDirPath':+'',+'internalDir':+'remoting',+'failIfWorkDirIsMissing':+false},+'tunnel':+'',+'vmargs':+'-Xmx1024m'},+'retentionStrategy':+{'stapler-class':+'hudson.slaves.RetentionStrategy\$Always',+'\$class':+'hudson.slaves.RetentionStrategy\$Always'},+'nodeProperties':+{'stapler-class-bag':+'true',+'hudson-slaves-EnvironmentVariablesNodeProperty':+{'env':+[{'key':+'JAVA_HOME',+'value':+'/docker-java-home'},+{'key':+'JENKINS_HOME',+'value':+'/home/jenkins'}]},+'hudson-tools-ToolLocationNodeProperty':+{'locations':+[{'key':+'hudson.plugins.git.GitTool\$DescriptorImpl@Default',+'home':+'/usr/bin/git'},+{'key':+'hudson.model.JDK\$DescriptorImpl@JAVA-8',+'home':+'/usr/bin/java'},+{'key':+'hudson.tasks.Maven\$MavenInstallation\[email protected]',+'home':+'/usr/bin/mvn'}]}}}"
curl -L -s -o /dev/null -v -k -w "%{http_code}" -u "${JENKINS_USER}:${JENKINS_API_TOKEN}" -H "Content-Type:application/x-www-form-urlencoded" -X POST -d "json=${JSON_OBJECT}" "${JENKINS_URL}/computer/doCreateItem?name=${NODE_NAME}&type=hudson.slaves.DumbSlave"
In order to get the agent secret via REST API checkout this, which would look something like this:
curl -L -s -u ${JENKINS_USER}:${JENKINS_API_TOKEN} -X GET ${JENKINS_URL}/computer/${NODE_NAME}/slave-agent.jnlp | sed "s/.*<application-desc main-class=\"hudson.remoting.jnlp.Main\"><argument>\([a-z0-9]*\).*/\1/"
Windows (PS)
And here my solution for Windows using Powershell:
$JENKINS_URL="https://jenkins.intra"
$JENKINS_USER="papanito"
$JENKINS_API_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxx"
$NODE_NAME="testnode-ps"
# https://stackoverflow.com/questions/27951561/use-invoke-webrequest-with-a-username-and-password-for-basic-authentication-on-t
$bytes = [System.Text.Encoding]::ASCII.GetBytes("${JENKINS_USER}:${JENKINS_API_TOKEN}")
$base64 = [System.Convert]::ToBase64String($bytes)
$basicAuthValue = "Basic $base64"
$headers = @{ Authorization = $basicAuthValue; }
$hash=@{
name="${NODE_NAME}";
nodeDescription="Linux slave";
numExecutors="5";
remoteFS="/home/jenkins/agent";
labelString="SLAVE-DOCKER linux";
mode="EXCLUSIVE";
""=@(
"hudson.slaves.JNLPLauncher";
'hudson.slaves.RetentionStrategy$Always'
);
launcher=@{
"stapler-class"="hudson.slaves.JNLPLauncher";
"\$class"="hudson.slaves.JNLPLauncher";
"workDirSettings"=@{
"disabled"="true";
"workDirPath"="";
"internalDir"="remoting";
"failIfWorkDirIsMissing"="false"
};
"tunnel"="";
"vmargs"="-Xmx1024m"
};
"retentionStrategy"=@{
"stapler-class"= 'hudson.slaves.RetentionStrategy$Always';
'$class'= 'hudson.slaves.RetentionStrategy$Always'
};
"nodeProperties"=@{
"stapler-class-bag"= "true";
"hudson-slaves-EnvironmentVariablesNodeProperty"=@{
"env"=@(
@{
"key"="JAVA_HOME";
"value"="/docker-java-home"
};
@{
"key"="JENKINS_HOME";
"value"="/home/jenkins"
}
)
};
"hudson-tools-ToolLocationNodeProperty"=@{
"locations"=@(
@{
"key"= 'hudson.plugins.git.GitTool$DescriptorImpl@Default';
"home"= "/usr/bin/git"
};
@{
"key"= 'hudson.model.JDK\$DescriptorImpl@JAVA-8';
"home"= "/usr/bin/java"
};
@{
"key"= '[email protected]';
"home"= "/usr/bin/mvn"
}
)
}
}
}
#https://stackoverflow.com/questions/17929494/powershell-convertto-json-with-embedded-hashtable
$JSON_OBJECT = $hash | convertto-json -Depth 5
$JSON_OBJECT
Invoke-WebRequest -Headers $headers -ContentType "application/x-www-form-urlencoded" -Method POST -Body "json=${JSON_OBJECT}" -Uri "${JENKINS_URL}/computer/doCreateItem?name=${NODE_NAME}&type=hudson.slaves.DumbSlave"