Jenkins is a very powerful CI Server that allows to do a lot of interesting things.
But installing it or its slaves could be boring ๐ I wanna start sharing with you a scripts to automate these things.
Today’s post will be about creating ั simple Jenkins node using Powershell, but you can reimplement it on other languages.
Firstly, we need a groovy script, that Jenkins can execute.
1 2 3 4 5 6 7 8 9 10 11 12 |
import hudson.model.Node.Mode import hudson.slaves.* import jenkins.model.Jenkins DumbSlave dumb = new DumbSlave("$machineName", "$machineName Agent", "$remoteFolder", "$numberOfExecutors", Mode.NORMAL, "$label", new JNLPLauncher(), RetentionStrategy.INSTANCE) Jenkins.instance.addNode(dumb) |
Lets break this on parts:
1 2 3 |
import hudson.model.Node.Mode import hudson.slaves.* import jenkins.model.Jenkins |
This block will import all needed classes and namespaces to Jenkins shell.
Lets create an object that will represent the node (All fields could be seen in comments):
1 2 3 4 5 6 7 8 |
DumbSlave dumb = new DumbSlave("$machineName", // Agent name, usually matches the host computer's machine name "$machineName Agent", // Agent description "$remoteFolder", // Workspace on the agent's computer "$numberOfExecutors", // Number of executors Mode.NORMAL, // "Usage" field, EXCLUSIVE is "only tied to node", NORMAL is "any" "$label", // Labels new JNLPLauncher(), // Launch strategy, JNLP is the Java Web Start setting services use RetentionStrategy.INSTANCE) // Is the "Availability" field and INSTANCE means "Always" |
And the final step is creating a node:
1 |
Jenkins.instance.addNode(dumb) |
All vars that starts withย $ sign are Powershell vars, that you should set before.
You can check this script by running it with Jenkins console (http://your-jenkins-server.com/script), but replace vars with actual values ๐
The next step, we will create Powershell function, that will generate this script for us:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
function createAddNodeGroovySrcipt($machineName, $jenkinsFolder, $numberOfExecutors, $label){ Write-Host "Generating script for creating node.." -ForegroundColor DarkCyan $numberOfExecutors = 10; $remoteFolder = $jenkinsFolder.Replace("\", "\\"); $script = @" import hudson.model.Node.Mode import hudson.slaves.* import jenkins.model.Jenkins DumbSlave dumb = new DumbSlave("$machineName", "$machineName Agent", "$remoteFolder", "$numberOfExecutors", Mode.NORMAL, "$label", // Labels new JNLPLauncher(), RetentionStrategy.INSTANCE) Jenkins.instance.addNode(dumb) "@ Write-Host "Script generated" -ForegroundColor DarkGreen return $script; } |
Next step, is make REST call to Jenkins to create node:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function requestJenkinsToCreateNodeUsingRest($jenkinsUrl, $user, $apiToken, $machineName, $jenkinsFolder, $numberOfExecutors, $label){ Write-Host "Adding node.." -ForegroundColor DarkCyan $url = $jenkinsUrl +"/scriptText" $token = $user + ":" + $apiToken $tokenBytes=[System.Text.Encoding]::UTF8.GetBytes($token) $base64 = [System.Convert]::ToBase64String($tokenBytes) $script = createAddNodeGroovySrcipt $machineName $jenkinsFolder $numberOfExecutors $label $wc = New-Object System.Net.WebClient $wc.Headers.Add("Authorization", "Basic $base64") Write-Host "Making REST call to $url.." -ForegroundColor DarkCyan $NVC = New-Object System.Collections.Specialized.NameValueCollection $NVC.Add("script", $script); $byteRes = $wc.UploadValues($URL,"POST", $NVC); $res = [System.Text.Encoding]::UTF8.GetString($byteRes) Write-Host $res -ForegroundColor Gray Write-Host "Node added" -ForegroundColor Green } |
Where $apiToken – your Jenkins user’s API token that you can find under current user settings in Jenkins.
Also, it would be nice to have function, that will check if already created such node
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
function checkIfJenkinsHasNode($jenkinsUrl, $machineName, $user, $apiToken){ Write-Host "Checking Jenkins if it has slave already.." -ForegroundColor DarkCyan $url = $jenkinsUrl +"/computer/" + $machineName + '/api/json' $token = $user + ":" + $apiToken $tokenBytes=[System.Text.Encoding]::UTF8.GetBytes($token) $base64 = [System.Convert]::ToBase64String($tokenBytes) $req = [system.Net.WebRequest]::Create($url) $req.Headers.Add("Authorization", "Basic $base64") try { $res = $req.GetResponse() } catch [System.Net.WebException] { $res = $_.Exception.Response } $result = [int]$res.StatusCode -eq 200 if ($result){ Write-Host "Jenkins already has slave with name $machineName" -ForegroundColor Green } else { Write-Host "Need to add node to Jenkins" -ForegroundColor Yellow } return $result; } |
This one is very simple – just check if GET request to node page returns OK result.
And finaly, lets combine it in one function
1 2 3 4 5 6 |
function createJenkinsNode($jenkinsUrl, $user, $apiToken, $machineName, $jenkinsFolder, $numberOfExecutors, $label){ Write-Host "Creating Jenkins node.." -ForegroundColor DarkCyan if (!(checkIfJenkinsHasNode $jenkinsUrl $machineName $user $apiToken)){ requestJenkinsToCreateNodeUsingRest $jenkinsUrl $user $apiToken $machineName $jenkinsFolder $numberOfExecutors $label } } |
That’s it! Thanks for your attention!