Micah Longmire
Micah Longmire

Reputation: 21

How to run a python script from s3 in an AWS SSM Automation Runbook using executeScript?

I have scoured the documentation from top to bottom at this point and I still can't figure out how to abstract my python scripts to s3 so I don't have to include them inline in my runbook.

I love SSM runbooks and their ability to perform logic during deployments based on parameters and branching paths, but I desperately want to abstract out my scripts. I have inline script execution down, but attached script execution is always met with this result:

Failure message Step fails when it is Poll action status for completion. Traceback (most recent call last): AttributeError: module 'test' has no attribute 'main' Handler main is not found in provided script. Please refer to Automation Service Troubleshooting Guide for more diagnosis details.

Here is the code I am trying:

description: A simple SSM runbook that calls a templated script to print and output a message.
schemaVersion: '0.3'
parameters:
  Message:
    type: String
    description: The message to print and output.
    default: "Hello from the runbook!"
mainSteps:
  - name: ExecuteTemplateScript
    action: aws:executeScript
    isEnd: true
    inputs:
      Runtime: python3.10
      Handler: test.main  # [file].[function] format
      InputPayload:
        Message: '{{ Message }}'
      Script: ''
      Attachment: test.py  # Name of the attached file
    outputs:
      - Name: OutputMessage
        Selector: $.Payload.OutputMessage
        Type: String
files:
  test.py:
    checksums:
      sha256: 590708757b79b9438bf299ee496a121c98cf865899db8fea5d788d0cb616d1f5

I have tried variations of:

handler: test.py.main handler: test handler: test.main handler: main

Here is the test script.

#!/usr/bin/env python3
"""Simple templated script for SSM that prints and outputs a message."""

import json

def process_message(payload: dict) -> dict:
    """Process the input message and return it."""
    message = payload.get('Message', 'No message provided')
    print(f"Message received: {message}")  # Printed to SSM logs
    return {'OutputMessage': message}

def main(events, context):
    """Main function for SSM execution."""
    # SSM passes InputPayload as 'events'
    payload = events
    result = process_message(payload)
    return result  # SSM captures this as output

if __name__ == "__main__":
    # For local testing, simulate SSM input
    import sys
    if not sys.stdin.isatty():
        payload = json.load(sys.stdin)
    else:
        payload = {'Message': 'Hello, world!'}
    result = process_message(payload)
    print(json.dumps(result))

Here are the docs I have tried parsing:

https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_AttachmentsSource.html https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-authoring-runbooks-scripted-example.html https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-document-script-considerations.html https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-action-executeScript.html

The script is attached and the checksum checks out. So I have come to my last resort. Asking the experts directly. Help please.

Upvotes: 0

Views: 34

Answers (1)

Daniel Lefebvre
Daniel Lefebvre

Reputation: 374

How long does the script need to run? If it relatively fast you may want to look into using an AWS lamba

Upvotes: 0

Related Questions