From deprecated cliOnline to OnlineNodeCommand - jenkins

So I created this groovy script but read that the cliOnline() command is deprecated.
But I can't seem to figure out how to actually change my code to use hudson.model.Hudson.instance.OnlineNodeCommand()?
deprecated cliOnline
def nodes_checklist = ["PD100069", "PD100070", "PD100090", "PD10756"]; // List of nodes which should be turned online
def jenkinsNodes = jenkins.model.Jenkins.instance.getNodes() // Get all existing nodes on this Jenkins URL
for(def node_checker: nodes_checklist) {
for(def node: jenkinsNodes) {
if(node.getNodeName().contains(node_checker)) {
println "The node " + node.getNodeName() + "'s offline status: " + node.toComputer().isOffline()
if (node.toComputer().isOffline()){
println "Turning " + node.getNodeName() + " online"
node.toComputer().cliOnline() // If node is offline, turn it online
println node.getNodeName() + "'s online status: " node.toComputer().isOnline()
}
}
}
}
Does anyone know how to rewrite this to use the non-deprecated version?

If you look at this depricated method, it simply calls a non depricated method setTemporarilyOffline(boolean temporarilyOffline, OfflineCause cause). So not sure why this was depricated. Anyway instead of using cliOnline() you can use setTemporarilyOffline. Check the following.
node.getComputer().setTemporarilyOffline(false, null)
Some proper code with a proper cause. Cause is not really needed when setting the node online though.
import hudson.slaves.OfflineCause.UserCause
def jenkinsNodes = Jenkins.instance.getNodes()
for(def node: jenkinsNodes) {
if (node.getComputer().isTemporarilyOffline()){
node.getComputer().setTemporarilyOffline(false, null)
}
}
Setting to temporarily offline
UserCause cause = new UserCause(User.current(), "This is a automated process!!")
node.getComputer().setTemporarilyOffline(true, cause)

Related

How to use `StaplerResponse rsp` in `AsyncResourceDisposer.doStopTracking()`

I'm trying to remove (stop tracking) trackig item from Jenkins AsyncResourceDisposer (${JENKINS_URL}/administrativeMonitor/AsyncResourceDisposer) via groovy scripts (${JENKINS_URL}/script).
According to the Javadoc and source code
// Javadoc
#Restricted(value=org.kohsuke.accmod.restrictions.DoNotUse.class)
public org.kohsuke.stapler.HttpResponse doStopTracking(#QueryParameter
int id,
org.kohsuke.stapler.StaplerResponse rsp
)
// source code
#Restricted(DoNotUse.class)
#RequirePOST
public HttpResponse doStopTracking(#QueryParameter int id, StaplerResponse rsp) {
...
}
I'd like to know how to add org.kohsuke.stapler.StaplerResponse rsp in doStopTracking(int id, org.kohsuke.stapler.StaplerResponse rsp):
import org.jenkinsci.plugins.resourcedisposer.AsyncResourceDisposer
AsyncResourceDisposer disposer = AsyncResourceDisposer.get()
disposer.backlog.each {
disposer.doStopTracking( it.id, <what should I put here> )
}
Current I can get the item id, and the other informaitons like below:
import org.jenkinsci.plugins.resourcedisposer.AsyncResourceDisposer
AsyncResourceDisposer disposer = AsyncResourceDisposer.get()
String url = Jenkins.instance.rootUrl + disposer.url
disposer.getBacklog().each { item ->
println "\n${item.id} : \t${url}/stopTracking/?id=${item.id} : \t${item.class.simpleName} : \n" +
"\t${item.getLastState().getDisplayName()} : \n" +
"\t${item.getDisposable().node} : ${item.getDisposable().path}\n" +
"\t${item.toString()}"
}
If I'm go to the url "${url}/stopTracking/?id=${item.id}" in browser (login first), the item can be removed after click RETRY USING POST (as below)
So... I'm using the API call curl -H <crumbIssues> -X POST <url> by passed the disposer.doStopTracking(int, org.kohsuke.stapler.StaplerResponse) (still really wants know how to use it)
Before running the following script, Strict Crumb Issuers Plugin is necessary to be installed and configured (or setup -Dhudson.security.csrf.DefaultCrumbIssuer.EXCLUDE_SESSION_ID=true) due to SECURITY-626 : Improved CSRF protection since:
obtain a crumb using the /crumbIssuer/api URL will now fail to perform actions protected from CSRF unless the scripts retain the web session ID in subsequent requests.
Here is details:
import org.jenkinsci.plugins.resourcedisposer.AsyncResourceDisposer
import org.jenkinsci.plugins.strictcrumbissuer.StrictCrumbIssuer
AsyncResourceDisposer disposer = AsyncResourceDisposer.get()
StrictCrumbIssuer issuer = jenkins.model.Jenkins.instance.crumbIssuer
String jenkinsCrumb = "${issuer.crumbRequestField}:${issuer.crumb}"
String url = Jenkins.instance.rootUrl + disposer.url
disposer.getBacklog().each { item ->
println "\n ~~> removeing ${item.id} : "
[ 'bash', '-c', 'curl -s ' +
'-u <user>:<token> ' +
'-X POST ' +
"-H \"Content-Type: application/json\" " +
"-H \"Accept: application/json\" " +
"-H \"${jenkinsCrumb}\" " +
"${url}/stopTracking/?id=${item.id} "
].execute().with{
def stdout = new StringBuffer()
def stderr = new StringBuffer()
it.waitForProcessOutput( stdout, stderr )
println "EXIT CODE: ${it.exitValue()}"
println "ERROR: ${stderr}"
println "OUTPUT: ${stdout}"
}
}
Although, I still have a question... As we know that if the groovy script running in ${JENKINS_URL}/script, which means the "runner" is the administrator, so, how I can remove the specific user authorication '-u <user>:<token>' (by using the jenkins administrator authorication) in curl ?

How to get number of failed builds by cause with Jenkins

I have the Build Failure Analyzer plugin installed in my Jenkins instance, and I have a number of different failures entered into the plugin. Does anyone know if it is possible to get the total number of failures across all jobs that have the same cause?
For example, I occasionally get "ChannelClosedException" failures if the build node goes offline during a build or test unexpectedly and I would like to determine how often this is happening across all my jobs. Is there some way to aggregate this value? I imagine it could be done through groovy if you can iterate over each build for each job and collect the Build Failure cause if one is detected.
Has anyone else done something like this before?
Not the exact answer... but should be able to modify to get what you are looking for:
Jenkins.instance.getAllItems(Job).each{
def jobBuilds=it.getBuilds()
//for each job get the things (you can limit at your convenience)
jobBuilds.each { build ->
def runningSince = groovy.time.TimeCategory.minus( new Date(), build.getTime() )
def currentStatus = build.buildStatusSummary.message
def cause = build.getCauses()[0] //we keep the first cause
def user = cause instanceof Cause.UserIdCause? cause.getUserId():""
println "Build: ${build} | Since: ${runningSince} | Status: ${currentStatus} | Cause: ${cause} | User: ${user}"
def parameters = build.getAction(ParametersAction)?.parameters
parameters.each {
println "Type: ${it.class} Name: ${it.name}, Value: ${it.dump()}"
}
}
}
Using some google-fu and some of the info from VinDev, I came up with this solution:
// get all jobs in Jenkins
Jenkins.instance.getAllItems(Job).each {
// get all builds for each job
def jobBuilds=it.getBuilds()
//for each build, get the name and status + and failure messages
jobBuilds.each { build ->
// get the build status
def currentStatus = build.buildStatusSummary.message
// we only care about the broken builds because we want failure messages
if (currentStatus.contains("broken")) {
println "Build: ${build} | Status: ${currentStatus}"
def BFA = build.actions.find{ it instanceof com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction };
if (BFA != null) {
for (failureCause in BFA.getFoundFailureCauses()) {
println("name: " + failureCause.getName() + ", description: " + failureCause.getDescription())
}
}
}
}
}

function lines after httpRequest are not executed in groovy jenkins pipeline

None of the lines after making httpRequest are getting executed. Everything else works fine in this function. What could be going wrong here?
However, network request is going fine and I am able to see the response in the console. httpRequest is being made via plugin
I've even tried CURL - but lines after curl are not executed.
#NonCPS
def doPRCommentBasedTesting() {
def causes = currentBuild.rawBuild.getCauses()
def commentURL
for(cause in causes) {
if (cause.class.toString().contains("GitHubPullRequestCommentCause")) {
commentURL = cause.getCommentUrl()
commentURL = commentURL.substring(commentURL.lastIndexOf("-") + 1)
println "This job was caused by job " + commentURL
def url1 = "https://<git_url>/api/v3/repos/<owner>/<repo>/issues/comments/" + commentURL
def commentText = httpRequest authentication: '<auth_cred>', url: url1, consoleLogResponseBody: true
println commentText
println commentText.getClass()
println "hello world, how are you doing today?"
}
else {
println "Root cause : " + cause.toString()
}
}
println "==============================="
return 0
}
A non cps function does not have the ability to pause in between because it runs in a go. You need to put network call into a different function that is not marked as nonCPS and then it will work. In general the nonCPS block should be very small and limited to code that cannot be serialised

Jenkins lockable resource - lock without unlocking

I'm using the "Locable Resources Plugin" together with the Jenkins multipipeline functionality:
lock('my-resource-name') {
}
I have a situation where I need to lock a resource in one pipeline and unlock it in another. I have workarounds, but I would prefer using the lock plugin, if possible.
I imagagine something like this
lock("my-resource-name")
.....
unlock("my-resource-name)
The why of it
I'm implementing canary releases, and there are three different paths through my pipeline (I considered other solutions, like pausing the pipeline with the input plugin - providing me with more is out of scope for this question).
I would like to lock/halt the pipeline while the canary is evaluated, and then, when the promotion or rollback is done, unlock it again.
Omitting the body for the lock statement just gives me java.lang.IllegalStateException: There is no body to invoke
One way of doing it is this:
curl -XGET https://your-jenkins/lockable-resources/reserve?resource=myresource
curl -XGET https://your-jenkins/lockable-resources/unreserve?resource=myresource
The GET is not a mistake, it really is GET.
To wait for a lock
lock("my-resource-name") {}
I also know Jenkins support something called "milestones" apparently is something used to communicate between builds. But I have no idea if it can be used to solve this problem in any meaningful way.
The lock can be done this way
import org.jenkins.plugins.lockableresources.LockableResource
import org.jenkins.plugins.lockableresources.LockableResourcesManager
...
LockableResourcesManager lockableResourcesManager = LockableResourcesManager.get()
LockableResource lockableResource = lockableResourcesManager.fromName(resourceName)
// if the resource doesn't exists, create it
if (lockableResource == null) {
lockableResourcesManager.createResource(resourceName)
lockableResource = lockableResourcesManager.fromName(resourceName)
}
// wait until lock is successful
waitUntil { lockableResourcesManager.lock([lockableResource].toSet(), currentBuild.rawBuild, null) }
The unlock is much simpler because you know the resource exists (if it doesn't there is no reason to try to unlock it)
LockableResourcesManager lockableResourcesManager = LockableResourcesManager.get()
LockableResource lockableResource = lockableResourcesManager.fromName(resourceName)
// do not pass currentBuild.rawBuild as in your case is not the build that locked this resource
// so I am passing null instead
lockableResourcesManager.unlock([lockableResource], null)
Note that I used to test this org.6wind.jenkins:lockable-resources:2.7, the implementation details may vary depending on the version used.
<dependency>
<groupId>org.6wind.jenkins</groupId>
<artifactId>lockable-resources</artifactId>
<version>2.7</version>
<scope>provided</scope>
</dependency>
from LockableResourcesManager get each lock, then
foreach lock do if lock.getName matches then do lock.reset() to release the lock
e.g. some groovy to find locked locks not owned by any builds and clean them up:
print "START\n"
def all_lockable_resources = org.jenkins.plugins.lockableresources.LockableResourcesManager.get().resources
all_lockable_resources.each { r->
if (r.isLocked() || r.isReserved()) {
println "Lock " + r + " is locked or reserved by " + r.getBuild() + " B CARSE " + r.getLockCause()
b = r.getBuild()
if (b) {
if (b.isBuilding()) { println "build:" + b + " is building" }
if (b.getResult().equals(null)) { println "build:" + b + " result is not in yet" }
if ( ! b.isBuilding() && ! b.getResult().equals(null)) {
println "build:" + b + " is not building and result is " + b.getResult() + " yet the lock " + r + " is locked."
println "ACTION RELEASE LOCK " + r
println "getLockCause:" + r.getLockCause()
println "getDescription:" + r.getDescription()
println "getReservedBy:" + r.getReservedBy()
println "isReserved:" + r.isReserved()
println "isLocked:" + r.isLocked()
println "isQueued:" + r.isQueued()
//release the lock
r.reset()
println "getLockCause:" + r.getLockCause()
println "getDescription:" + r.getDescription()
println "getReservedBy:" + r.getReservedBy()
println "isReserved:" + r.isReserved()
println "isLocked:" + r.isLocked()
println "isQueued:" + r.isQueued()
}
}
}
}
API: http://javadoc.jenkins.io/plugin/lockable-resources/org/jenkins/plugins/lockableresources/LockableResource.html
or navigate to https://jenkins-host/lockable-resources/ page. here we can find list of all the lockable resources. we can manually lock or reserve these.

How to Configure Jenkins Login in iPad using Unity

I had installed Jenkins in network and making build successfully.
I want to have authentication for my iPad app, developed with unity. I searched the plugin respective to this, but i can't find it. whether this can be attained by means of plugin or otherways?
As i need to login into my jenkins and afterward use the data of pipelines and all in my app accessed through URL so need login first.
Please do let me know the ways to do. Thanks in advance
After some searching and all i found the solution for this and i used following code to check authentication.
public void TryLogin ()
{
UnityWebRequest req = UnityWebRequest.Get ("Your jenkins login url of network");
req.method = "GET";
req.SetRequestHeader("Authorization", "Basic " + Convert.ToBase64String (Encoding.UTF8.GetBytes ("jenkinsId:jenkinsPassword")));
StartCoroutine (WaitForLoginRequest (req));
}
IEnumerator WaitForLoginRequest(UnityWebRequest req)
{
yield return req.Send ();
if (req.isError)
{
Debug.Log ("WWW Error: " + req.error);
}
else
{
Debug.Log("WWW Ok!:");
string response = Encoding.UTF8.GetString (req.downloadHandler.data);
Debug.Log ("Response code = " + req.responseCode);
Debug.Log ("String = " + response);
}
}
And check the response code for authentication.

Resources