Adding a slave to a Jenkins master always required to add the slave via the GUI and then gather the secret in order to be able to connect the slave. So I was wondering whether a slave could be created programmatically. My initial search brought me to this Stackoverflow post However, I figured you can also create an agent using the REST API. This is especially useful when having an apache proxy in front (see issue JENKINS-47279) 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 to create a jenkins slave programatically:

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\$[email protected]',
+'home':+'/usr/bin/git'},+{'key':+'hudson.model.JDK\$[email protected]',
+'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"
    };

Hope this is useful for you.