Detecting when a task has finished through REST APIs - rest

The Nexus repository server by Sonatype offers a classical REST API. When an operation is triggered through the REST API, the call returns immediately, indicating through its status code whether or not the operation was started successfully. I am looking for a way to detect whether and when a job finished successfully.
In my concrete case, I am starting a backup task that writes out configuration databases in a serialized format to disk:
curl -X POST "$mynexus/service/rest/v1/tasks/$task-id/run" -H "accept: application/json"
which returns a 204 "task was run" immediately.
However, minutes after that happens, a manual check indicates that the on-disk file created by that task is still growing. Of course, I could try watching the output of lsof until that task seems finished, but that would be highly impractical, require root access to the server and also break the REST design.
A similar question here has not received an answer since 2016, so I'll ask in a more general way, in the hope that the answer will be more generally applicable:
How can a REST client detect that an operation has completely finished on the server side when talking to a Sonatype Nexus 3.x series server?
If there is no such way, would you consider that an issue with Nexus or would you recommend to create a custom workaround?

Nexus 3 has a get task API endpoint which will give you different info about a specific task, including its currentState
GET /service/v1/tasks/{id}
Example API response taken from the below linked documentation:
{
"id" : "0261aed9-9f29-447b-8794-f21693b1f9ac",
"name" : "Hello World",
"type" : "script",
"message" : null,
"currentState" : "WAITING",
"lastRunResult" : null,
"nextRun" : null,
"lastRun" : null
}
Reference: Nexus get task API endpoint documentation

Related

Swagger call fails - net::ERR_EMPTY_RESPONSE

I have defined swagger for REST APIs. Swagger explorer is working fine. 1 of the APIs is doing bulk update of dynamo DB records. It takes around 3-4 minutes to complete dynamoDB operation. For this API, swagger call runs for sometime and then it says
Response Code
0
Response Headers
{
"error": "no response from server"
}
When I checked logs, there is no any exception from swagger. This API update operation runs in background and completes processing in 3-4 minutes. I have verified it using logs and metric datapoint. I want swagger also to pause/ continuous active load instead of getting timed out.
After checking Inspect part of page, it says
net::ERR_EMPTY_RESPONSE
Is there any way to update swagger timeout/ anything?

Get Jenkins Job Build ID from Queue ID

I'm successfully able to use this to kick off a Jenkins Job:
curl -X POST "http://jenkins_srv:8080/job/MY_JOB/buildwithParameters?this=1&that=2" --user name:pass
I can also get the consoleText from this job using:
curl -X POST "http://jenkins_srv:8080/job/MY_JOB/lastBuild/consoleText"
However, this doesn't scale if I run multiple jobs back to back. I've noticed that the first curl command has a return that includes:
Location: http://jenkins_srv:8080/queue/item/123/
I'm assuming that 123 is the job queue id.
My question is, if I queue jobs 121, 122, & 123 back to back, what do I use to check the status of job queue item 122? Also, what do I use to determine the actual build id that eventually resulted from job queue item 122?
I chose Kdawg's answer, because it helped lead me in the direction that I needed. Thank you!
I'm also including my own answer, because the solution I implemented was different than Kdawg's answer, and I feel it will add value for other people.
First off, I'm new to Jenkins. So if I misspeak, please feel free to correct me. Second, I had a slight learning curve in that there is a difference between a Jenkins "queue item" and a Jenkins "build job". The instant that a "queue item" has been created, there is no "build job" ID, because no build job has started. Also, once a build job has started, the queue item has 5 minutes before it is deleted.
When I perform these tasks:
curl -X POST "http://jenkins_srv:8080/job/MY_JOB/buildwithParameters?this=1&that=2" --user name:pass
curl -X POST "http://jenkins_srv:8080/job/MY_JOB/buildwithParameters?this=1&that=2" --user name:pass
curl -X POST "http://jenkins_srv:8080/job/MY_JOB/buildwithParameters?this=1&that=2" --user name:pass
Jenkins will schedule 3 build jobs to be run in a queue. These will be "queue items". These "queue items" will have a "Queue ID". In the example given in my original question, lets suppose that these three curl commands create "queue items" with "Queue ID"s 121, 122, & 123.
Why is this important?
Because depending on the load of your Jenkins server, the item that was queued may or may not be run immediately. If it runs immediately, then Kdawg's answer is definitely correct. Running his commands:
curl -X GET http://jenkins_srv:8080/queue/item/121/api/json?pretty=true --user name:pass
curl -X GET http://jenkins_srv:8080/queue/item/122/api/json?pretty=true --user name:pass
curl -X GET http://jenkins_srv:8080/queue/item/123/api/json?pretty=true --user name:pass
This will get queue information about each "queue item", and in what returns, there is definitely a way to obtain a "build job" ID, if the build job has started. If a build job has not yet started, this information will be blank.
Here's the additional part that, I feel, adds value.
Once a build job has started, the information in Kdawg's answer will be populated in the response to the three curl -X GET commands. Also, by default, Jenkins is designed to scavenge (garbage collection, choose your own term) the "queue item"s every 5 minutes. So in other words, if all you have is a "queue item" ID and the 5 minute data retention window passes, then you need another mechanism in order to get a "build job" ID from a "queue item" ID.
So, in my case, I'm using Jenkins as a front end, and Ansible on the back end to perform server configuration and application deployments. Some of these application deployments can take 30 minutes or more, well beyond the 5 minute data retention period of the "queue items".
So the problem that I had to solve, if all I have is a "queue item" ID, then how do I find a "build job" ID, regardless of when I'm checking, seconds later or hours later?
Here was my solution (Note that I required XML output, FYI).
I ran this command:
curl -X POST "http://jenkins_srv:8080/job/MY_JOB/buildwithParameters?this=1&that=2" --user name:pass
This command would return this information:
Runtime responseHeaders Date: Day, ## Non Year xx:yy:zz GMT
X-Content-Type-Options: nosniff
Location: http://jenkins_srv:port/queue/item/123/
Content-Length: 0
Server: Jetty(9.4.z-SNAPSHOT)
From here, I can parse out 123 from the Location field.
I then slept for 10 seconds. After the sleep, I run this command on a 10 second loop:
curl -X GET http://jenkins_srv:8080/queue/item/123/api/xml
I did that until I either:
I got a queue item return that included the xpath //executable/number that's shown in Kdawg's example, or
I got HTML 404 status code for more than 10 minutes, meaning the job hasn't been queue'd yet or I passed the 5 minute data retention window.
The loop in this way handles a burdened Jenkins server that's sluggish on handling queue requests. So presumably if I get to the end of 10 minutes, then my approach will still handle the use case that my automation approach has successfully queue'd and run the job, but it's checking Jenkins outside the data retention window. In this case, I would run this command:
curl -X GET http://jenkins_srv:port/job/MY_JOB/api/xml?tree=builds[id,number,result,queueId]&xpath=//build[queueId=123]
This returns the XML info for any "build job" that also contains a queueId of 123, as shown below:
<?xml version="1.0"?>
<build _class="hudson.model.FreeStyleBuild">
<id>456</id>
<number>456</number>
<queueId>123</queueId>
<result>SUCCESS</result>
</build>
In this way, I was able to authoritatively get a "build job" ID while only having a "queue item" ID regardless of the time difference between when I started and when I checked back.
Assuming that you have a location of http://jenkins_srv:8080/queue/item/123/, you can GET http://jenkins_srv:8080/queue/item/123/api/json?pretty=true to return information about that queue item (you can also not include ?pretty=true if you don't care about formatting, or use api/xml if you want the results in XML).
I don't know if there's standard documentation on the queue API, but it appears that if the queue item has completed (maybe also if it's currently being built?) it will have an executable node. One for my server looked like this:
"executable" : {
"_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",
"number" : 10,
"url" : "http://192.168.99.100:32769/job/configure/10/"
}
You can then GET the API for the URL specified in executable.url. In my case, GET http://192.168.99.100:32769/job/configure/10/api/json?pretty=true. From there, you should have all the information you need, including whether or not the build is currently being built, how long the build took/has taken, the result, etc.
Also, if you want information on your entire build queue, you can GET http://jenkins_srv:8080/queue/api/json?pretty=true
Astonishing that Jenkins doesn't track a request to its conclusion with a unique ID.
One element that persists between the queued item and the build item is the list of parameters. If you have the ability/authority to change the config of the jobs, then add an optional parameter REQUEST_ID that the client plucks from the air (e.g. a UUID) and passes in over REST. Then you can quiz the queue and look for the one with your REQUEST_ID, and you can quiz the list of builds and look for the one with your REQUEST_ID.
There's an interesting thing about this that if you want to queue multiple builds in the loop, you might end up getting SAME QUEUE_ID, This happens especially when you have the same parameter and queued builds have not started up. Basically, Jenkins assumes that you are just trying to build this and instead of multiple builds it just assumes that it needs to spin up only a single build, hence the SAME QUEUE_ID, To overcome this, if you add an extra parameter while building the job like UQ_ID=CURRENT_TIMESTAMP (This param doesn't need to be in build) then you will get the unique build number
If there's no param at all in the build you should define at least one param, Because parameterless build won't allow ANY parameter to be passed in the api
you can fetch job details by id
http://localhost:8080/job/{jobName}/{jobId}/api/json
curl --location --request GET 'http://localhost:8080/job/testPipeline/2/api/json' \
--header 'Authorization: Basic 1234' \

Orion v2 registrations are not working in server:port/v2/registrations

when I make a GET operation on my local Orion ContextBroker(I tried also at the fiware-lab one[orion.lab.fi-ware.org:1026]) on this url http://10.174.123.243:1026/v2/ or it works fine and show me the allowed operations by ORION:
{
"entities_url": "/v2/entities",
"types_url": "/v2/types",
"subscriptions_url": "/v2/subscriptions",
"registrations_url": "/v2/registrations"
}
All of them are working except the /v2/registrations one. When I tried the following GET operation http://10.174.123.243:1026/v2/registrations I get a 400 error.
{
"error": "BadRequest",
"description": "service not found"
}
Is not avaliable the GET /v2/registrations operation at Orion Context Broker? I've tried with Orion 0.24 and 1.2 versions.
Registrations management has not been yet defined in NGSIv2. Although the work-in-progress version of the NGSIv2 specification shows some "draft operations" related with registrations (as the one you mention) and it is something that in some moment will be defined, Orion is not implementing them by the time being (i.e. Orion version 1.2).
Note that the current (May 2016) NGSIv2 specification release candidate doesn't include that operation.
However, Orion still supports NGSIv1 registration management (have a look to the Orion NGSIv1 walkthrough).

Finding latest TeamCity Backup via REST API

I found plenty of information and example about triggering TeamCity 8.1.2 backups via the REST API.
But leaving the backup files on the same server is pretty useless for disaster recovery.
So I'm looking for a way to copy over the generated backup file to another location.
My question is about finding the name of the latest available backup file via the REST API -
The Web GUI includes this information under "Last Backup Report" under the "Backup" page of the Server Administration.
I've dug through https://confluence.jetbrains.com/display/TCD8/REST+API#RESTAPI-DataBackup and the /httpAuth/app/rest/application.wadl on my server. I didn't find any mention of a way to get this info through the REST API.
I also managed to trigger a backup with a hope that perhaps the response gives this information, but it's not there - the response body is empty and the headers don't include this info.
Right now I intend to fetch the HTML page and extract this information from there, but this feels very hackish and fragile (the structure of the web page could change any time).
Is there a recommended way to get this information automatically?
Thanks.
JetBrains support got back to me with the right answer - I should use a POST method, not GET, even if the request body is empty.
Here is an example of a working request:
curl -u user:password --request POST http://localhost:8111/httpAuth/app/rest/server/backup?includeConfigs=true'&'includeDatabase=true'&'fileName=testBackup
And the response to that contains a plain file name in text: testBackup_20150108_141924.zip

OpenStack API CreateInstance

After I create an instance on OpenStack with the REST API Using the Nova endpoint the operation succeeds with the server id reference. If I immediately try to get any of the details of the network interfaces (using the /servers/server-id/ips) I get nothing, not even an error message that the resource is busy. If I put an arbitrary 30 second wait, I'll get the details. Is there any API call that can use on OpenStack to get a "is ready" state after a creation?
If there is no operation to determine that the server is ready, then is there a recommended wait time in the documentation?
You should wait for the instance to be in the "active" state. That's when the instance has been fully built, including network. You're probably hitting the instance while its still in the "building" state.