Splunk Dev

How to call a python script from an html view?

dsollen
Explorer

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?

1 Solution

alacercogitatus
SplunkTrust
SplunkTrust

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.

View solution in original post

dsollen
Explorer

just so you know the post you mentioned isn't linked, and a quick search doesn't reveal it; making it hard to check it out 🙂 My good friend google says the link is https://answers.splunk.com/answers/306952/return-binary-data-such-as-images-via-rest-api-or.html

and yes I wish there was better documentation. I feel blind following suggestions here without full understanding of them. but I can't find any documentation of these things even after they are explained to me, so maybe the documentation doesn't entirely exist?

0 Karma

arkadyz1
Builder

Your friend google was correct, as usual :). From alacer's reply to my comment I can see that the documentation is indeed scarce. As I got used to saying in my company (not only about Splunk), "underdocumented" is a huge understatement :). Gone are the companies like DEC which had really exhaustive User Guides and Reference Manuals...

0 Karma

alacercogitatus
SplunkTrust
SplunkTrust

It's not really, tbh. It's from years of Splunk App Dev and experimentation with other Apps and finding what works.

0 Karma

dsollen
Explorer

I do have a few questions. since I already am using an app I assume I want to use $app_home/local/web.conf to make the change?

More importantly, I'm not certain I understand the format of the my_script.py example you gave; what is or isn't required to make my python script function as an endpoint. the web.conf definition says that endpoints registers a default cherrypy script, but your example doesn't import cherrypy. Is there a link that defines the format required and what the imported controller and other mrssparkle libs you used do? (I couldn't find an API for them either, my google-fu is really failing me today)

One last question, what do I need to do to ensure splunk sees my changes to the app after I do this? would 'splunk install' with an -update work?

0 Karma

alacercogitatus
SplunkTrust
SplunkTrust

Yes, use the $APP_HOME/local/web.conf if you didn't make the app, but use $APP_HOME/default/web.conf if this is an app you created. DO NOT USE etc/system/local!

In the example script, just copy and paste that entire thing into the controllers folder. Your bin/my_script.py steps go into the section under the def at # DO YOUR THINGS WITH THE KWARGS PASSED.

Don't need to import cherrypy for this example, because I'm not using anything from cherrypy. The cherrypy in the documentation is simply stating that this endpoint is exposed via the Splunk Web Server.

You will need to do a full restart (on the search head) for these changes to be picked up. A simple update won't work.

Here is about as close to documentation as you will get: http://docs.splunk.com/Documentation/Splunk/6.3.2/ModuleRef/Extensiondictionary

arkadyz1
Builder

I'm pretty sure it's etc/system/local/web.conf

0 Karma

alacercogitatus
SplunkTrust
SplunkTrust

Yeah, don't do that.

Get Updates on the Splunk Community!

Announcing Scheduled Export GA for Dashboard Studio

We're excited to announce the general availability of Scheduled Export for Dashboard Studio. Starting in ...

Extending Observability Content to Splunk Cloud

Watch Now!   In this Extending Observability Content to Splunk Cloud Tech Talk, you'll see how to leverage ...

More Control Over Your Monitoring Costs with Archived Metrics GA in US-AWS!

What if there was a way you could keep all the metrics data you need while saving on storage costs?This is now ...