Hello! Does anyone have recommendations for steps on writing a python action? Is there a good way to set up a development environment? Is there a way to test the action outside of st2?
⚠️ We've moved!
Hi there!
To reduce project dependency on 3rd party paid services the StackStorm TSC has decided to move the Q/A from this forum to Github Discussions. This will make user experience better integrated with the native Github flow, as well as the questions closer to the community where they can provide answers.
Use 🔗 Github Discussions to ask your questions.
You can write your Python script like any other script, and then graft on StackStorm support. Similar to this action from our end-to-end tests (the only interesting parts of that for you will be the top of that file and the bottom of that file, the details of the test case aren’t relevant).
First, write your script normally:
import ...
args = {}
# parse arguments from the environment here
args[...] = os.environ.get('...')
# parse arguments from the command line here with argparse, click, etc.
args = ...
# your script logic goes here
Then wrap up the logic into its own function and call that function directly, like so:
import ...
def do_things():
# your script logic goes here
# If this script is being run directly, parse the command line arguments
# and then pass them to the do_things function
if __name__ == '__main__':
args = {}
# parse arguments from the environment here
args[...] = os.environ.get('...')
# Parse script arguments here with argparse, click, etc.
args = ...
do_things(...)
Then you can graft StackStorm support onto it by adding a subclass of
st2common.actions.Action
, defining a run
function on it, and having the run
function call the do_things
function itself:
import ...
def do_things():
# your script logic goes here
try:
# If this script is being run from a StackStorm python-script runner,
# get the arguments from StackStorm and pass them to the do_things
# function
from st2common.runners.base_action import Action
class DoThingsAction(Action):
def run(self, *args, **kwargs):
return do_things(*args, **kwargs)
except ImportError:
pass
# If this script is being run directly, parse the command line arguments
# and then pass them to the do_things function
if __name__ == '__main__':
args = {}
# parse arguments from the environment here
args[...] = os.environ.get('...')
# Parse script arguments here with argparse, click, etc.
args = ...
do_things(...)
Hope this helps. Please feel free to ask further questions that may arise.
Oh, and you will also still need an action metadata file, just like every other StackStorm action,
setting the runner_type
to python-script
and defining the action parameters
like normal.
Here is the metadata file for the script I linked to in the previous post:
Thanks!! Is it more proper / useful to write the action as a subclass of BaseAction? Any tips on development with that paradigm?
Yes, you absolutely can do that, but it slows down development since then (unless you add some hacks to the code) you can only really run the code through StackStorm. So your REPL latency is higher.
I developed the script I linked to just running in a local virtualenv on my laptop, and then grafted the StackStorm integration in later, which let me debug the script first, and then once I knew the script was working as intended I knew that whatever bugs remained were in the StackStorm integration section. So it can be helpful to organize the code that way to make it easier to divide and conquer when troubleshooting.
Once your script is written out and pretty well debugged, and you have the StackStorm integration setup
and working, then yes, you can certainly simply move the meat of your script into the run
function:
import ...
from st2common.runners.base_action import Action
class MyAction(Action):
def run(self, *args, **kwargs):
# your script logic goes here
return ...
Personally, I didn’t find it beneficial enough to do that, especially since I do still run that script outside of StackStorm. But I could certainly see it being beneficial if the Python script is small and simple enough.
I highly recommend adding tests for your action. There’s an entire section in our documentation on testing packs.
I did not add tests for the action I linked to because the action itself was a test for some of our other code. Otherwise I definitely would have done so.
@blag I develop the same way as you do
create a script with cli arguments and then transfer it to stack storm action.
https://docs.stackstorm.com/actions.html#converting-existing-scripts-into-actions
and then go to
https://docs.stackstorm.com/actions.html#writing-custom-python-actions
The main problem I face is that there is NO ‘pdb’ Python debugger into the st2 action. It will be very nice if I could run somehow action in pdb shell or any other way to debug the script. Because sometimes you need to update or change the logic of the script but you already transform it to action and you don’t have the original script. You can always modify it to become a script again but you get my point.
@eazysnatch If you write your script how I explained then you can run it as if it is a normal Python script, or you can run it as a StackStorm action, without modifying the script at all.
Just found this and now I can remotely debug this new action using intellij! Thanks a ton.