Very often, my esteemed colleague aleck.lin and I are asked how to make the CMDB closer to being a real-time repository. As service architectures evolve and become more dynamic, running a broad subnet discovery once a day might not be anywhere near often enough to capture the data you need (particularly when you use your CMDB like we do: to make real operational decisions). Towards this end, it can be very useful to drive discovery in a more event-driven way. Wouldn't it be nice if every new system just kicked off a discovery of itself after being provisioned? The ServiceNow platform already does this for services like vCenter and AWS (there are turn-key integrations for registering as a vCenter event listener and integrating with AWS Config [edit 7/6: Check out my colleague's great how-to]), but what about plain old fashioned system discovery?


Fortunately, ServiceNow provides a simple mechanism to do just about anything with a simple REST call. I'm not just talking about the standard APIs that are available over REST... I'm talking about Scripted REST APIs! This was probably my favorite platform feature introduced in Geneva. These allow you to unleash any corner of the platform with a simple REST request.


So, let's get started, but where to begin? Well, we already know that we can do an ad-hoc system discovery by clicking the Quick Discovery UI action on the Discovery Schedules page:

Screen Shot 2016-05-24 at 3.37.42 PM.png

... so let's just re-use the same logic! Looking at the UI action itself, is a little disappointing:

Screen Shot 2016-05-24 at 2.27.37 PM.png


Because we ordinarily display some nice modal windows to go through the quick discovery process, we need to dig a little bit deeper. First, let's step into the referenced UI page (quick_discovery), which calls the DiscoveryAjax script include, which calls the Discovery script include's discoveryFromIP function. Pay dirt!


Now we have everything we need. Just create a new Scripted REST API, define a Scripted REST Resource, add a couple Query Parameter Associations (if you want to get fancy), and take it for a spin in the REST API Explorer. Here's an example Scripted REST Resource script where we're relying on the query parameters mid_server and target_ip, and returning a URL that will take us to the discovery status record:

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

  var statusId = new Discovery().discoveryFromIP(request.queryParams.target_ip + '', request.queryParams.mid_server + '', '');
  var statusUrl = gs.getProperty('glide.servlet.uri') + '' + statusId;
  return {'status_url': statusUrl};

})(request, response);


EDIT 1/12/18: Beginning in Kingston, line 3 above can be changed to take advantage of the new Discovery API which simplifies things by using the MID server selection algorithm (meaning it's no longer a necessary request parameter):

  var statusId = sn_discovery.DiscoveryAPI.discoverIpAddress(request.queryParams.target_ip + '');


Now from your REST API Explorer you can easily test. Just populate the query parameters, and hit Send:

Screen Shot 2016-05-24 at 3.45.21 PM.png

With any luck, you got a 200 response with a link back to the discovery status record (note that instance names have been removed to protect the innocent):

Screen Shot 2016-05-24 at 3.45.48 PM.png

Just like that, with a few lines of code, you can perform discovery on-demand with a simple REST call! To top it off, the REST API Explorer will give you code samples to make this call from a number of scripting languages, making it easy to have systems kick off a discovery against themselves e.g. as the last step in your new system bootstrap process. This same approach will work anywhere you can use script within the ServiceNow platform. Enjoy!