Hello Experts,
I'm trying to enable a scheduled search via a rest call. I'm given the name of the search, and when I called something as simple as:
request = urllib2.Request(base_url + '/servicesNS/' + owner + '/MyApp/saved/searches',
data = urllib.urlencode({'name': searchname, 'is_scheduled': "1", 'disabled': 0}),
headers = { 'Authorization': ('Splunk %s' %settings['sessionKey'])})
The error logs informed that they needed a search string. So I pulled the existing search string and fed it, and then it asked for the cron_schedule, and when I fed it that, it created a new copy of the search, but private. What's the right way to modify an existing search, to just enable it?
In response to Martin's question, urllib2 does make a post request when configured with a payload. I can set macros easily by using the following code:
request = urllib2.Request(base_url + '/servicesNS/-/MyApp/properties/macros/' + macroname,
data = urllib.urlencode({'definition': macrovalue}),
headers = { 'Authorization': ('Splunk %s' %settings['sessionKey'])})
search_results = urllib2.urlopen(request)
Additionally, I can see the proper paths being followed in the logs (except for the lack of the modification):
09-09-2014 23:37:08.530 -0700 DEBUG REST_Calls - app=MyApp POST saved/searches id=My Search Name: cron_schedule -> ['9 * * * *'], disabled -> [0], is_scheduled -> [1], search -> [My Search String]
09-09-2014 23:37:08.532 -0700 INFO SavedSearchAdminHandler - handleEdit called for id="My Search Name"
I've also tried mimicing exactly the format of the Macro search above, to no avail:
request = urllib2.Request(base_url + '/servicesNS/' + owner + '/MyApp/saved/searches/My%20Search%20Name',
data = urllib.urlencode({'is_scheduled': "1", 'disabled': 0}),
headers = { 'Authorization': ('Splunk %s' %settings['sessionKey'])})
Turns out that ultimately there were two problems being faced in the above. The first is the proper endpoint to hit. Rather than hitting the name of the search, the right approach was to provide an empty post to ../saved../searches/Name/enable. The second is that rather than specifying a user, it's necessary to use user context nobody when modifying an existing search.
Here was the final functioning code:
request = urllib2.Request(base_url + '/servicesNS/nobody/splunk_search_usage/saved/searches/' + searchname + '/enable', data="",
headers = { 'Authorization': ('Splunk %s' %settings['sessionKey'])})
search_results = urllib2.urlopen(request)
Turns out that ultimately there were two problems being faced in the above. The first is the proper endpoint to hit. Rather than hitting the name of the search, the right approach was to provide an empty post to ../saved../searches/Name/enable. The second is that rather than specifying a user, it's necessary to use user context nobody when modifying an existing search.
Here was the final functioning code:
request = urllib2.Request(base_url + '/servicesNS/nobody/splunk_search_usage/saved/searches/' + searchname + '/enable', data="",
headers = { 'Authorization': ('Splunk %s' %settings['sessionKey'])})
search_results = urllib2.urlopen(request)
I agree.. this absolutely seems like something that should work. This particular search is owned by admin (on my local instance, anyway) and is app-public. I tried using the "-" variant, and that returns a 400 error with an error logged: 09-10-2014 21:18:00.198 -0700 ERROR SavedSearchAdminHandler - Cannot edit/create a saved search for wildcarded users or applications. Pumping up the debug, even the logs say that they're editing the existing search...
Interesting. Comparing these two docs sections
http://docs.splunk.com/Documentation/Splunk/6.1.3/RESTAPI/RESTsearch#POST_saved.2Fsearches
http://docs.splunk.com/Documentation/Splunk/6.1.3/RESTAPI/RESTsearch#POST_saved.2Fsearches.2F.7Bname...
only the former should create a search.
Is the to-be-updated search private, or app-public? If the latter then give POSTing to /servicesNS/-/app/saved/searhes/name
a shot.
Have you considered using one of the many Splunk SDKs available? Specifically this: http://dev.splunk.com/view/python-sdk/SP-CAAAEBB
For the last block I added, I used /saved/searches/name and it still created a new private one.
Is the URL called .../saved/searches
or .../saved/searches/name
? The former creates a search on POST, the latter updates an existing search on POST.
Martin, yes it is. Just added a working example (for Macros).
Is urllib2.Request()
making a POST request by default?