We have a Splunk html view. We are trying to call a python script. Currently the code looks like this (retyped since our Splunk server doesn't have web access, I tried to avoid typos):
function callScript(){
$.ajax({
type: "POST",
url: "bin/my_script.py",
data: {'flag': defaultTokenModel.get("form.flag"))
},
success: function() {
alert("success returned");
}
});
}
This doesn't work. The success message is returned, but the actual python script isn't called.
From what I can tell, it looks like there may be a method called ajax in simplifyxml/mvc.js which is conflicting with the JQuery method, though I'm not certain that is the case.
What is the proper way to make a script call like this?
This won't work as you think. Access to local folders within an app is not allowed for security and technical reasons.
When you make that POST call, you are actually trying to get a Web UI relative script! https:///en-US/app/myapp/bin/my_script.py
for example. This just doesn't work.
So, you cannot directly call a python script from the web ui, it is not accessible. There is a way to do this. It is a method not fully documented, but involves creating a custom endpoint for Splunk, and then calling that endpoint.
Let me start with a quick tutorial. I'll gloss over a few things, make assumptions, drink some beer. Comment with questions. 😄
web.conf
[endpoint:my_script]
So, that is the only line you need in web.conf
. This tells Splunk that you are creating a new web endpoint. The my_script
definition needs to have the same name as the python file located in $APP_HOME/appserver/controllers
. (Where $APP_HOME
is the folder of the app you are creating this in - I'd suggest a new app, not search).
$APP_HOME/appserver/controllers/my_script.py
import logging
import os
import sys
# from splunk import AuthorizationFailed as AuthorizationFailed
import splunk.appserver.mrsparkle.controllers as controllers
import splunk.appserver.mrsparkle.lib.util as util
from splunk.appserver.mrsparkle.lib.util import make_splunkhome_path
from splunk.appserver.mrsparkle.lib.decorators import expose_page
_APPNAME = 'MyAppName'
def setup_logger(level):
"""
Setup a logger for the REST handler.
"""
logger = logging.getLogger('splunk.appserver.%s.controllers.my_script' % _APPNAME)
logger.propagate = False # Prevent the log messages from being duplicated in the python.log file
logger.setLevel(level)
file_handler = logging.handlers.RotatingFileHandler(
make_splunkhome_path(['var', 'log', 'splunk', 'my_script_controller.log']), maxBytes=25000000, backupCount=5)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
logger = setup_logger(logging.DEBUG)
class my_script(controllers.BaseController):
# /custom/MyAppName/my_script/my_endpoint
@expose_page(must_login=True, methods=['GET'])
def my_endpoint(self, **kwargs):
# DO YOUR THINGS WITH THE KWARGS PASSED
Whoa. WTF is that!? Python! YAY! So, now you have an endpoint enabled. Now you can call it from your HTML view.
function callScript(){
$.get("/custom/MyAppName/my_script/my_endpoint",
{'flag': defaultTokenModel.get("form.flag")) } )
.done(function(data){
});
}
Pay attention to these strings throughout this tutorial: my_script
, my_endpoint
, MyAppName
. This all need to be changed to your specification, they are merely examples. Again, this should at least point you in the right direction on doing this call. If you have questions, please follow up here, or find me on IRC (#splunk on efnet - I'm alacer) or via the Splunk Slack channel for usergroups, just ping me @alacercogitatus.