AWS Lambda Finite State Machines

A Python framework for developing finite state machine-based workflows on AWS Lambda.

View project on GitHub
« FSM YAML Running on AWS »

Running Locally

1. Install Docker

Install Docker.

2. Install Virtualenv

Installing Virtualenv and Virtualenv Wrapper allows all the python dependencies to be installed locally, so that state machines can be run and debugged locally using dev_lambda.py (see below).

$ pip install virtualenv
$ pip install virtualenvwrapper
$ mkvirtualenv aws-lambda-fsm
$ pip install -Ur requirements_dev.txt

3. Localstack + Memcache + Redis

A docker-compose.yaml file is supplied that runs LocalStack, which contains stubs for AWS services like SQS, Kinesis, etc.

It also runs Memcached and Redis instances, since AWS Elasticache is not supported by LocalStack.

$ docker-compose -f tools/experimental/docker-compose.yaml up localstack memcached redis

4. Settings

See Settings

It is possible to use local stubs for various AWS services. An example that can be used for local development is included in the tools/experimental folder. You can simply symlink it as follows.

$ ln -s tools/experimental/settings.py.dev_ecs settings.py

It contains a mapping of ARN to localstack/memcache endpoint

ENDPOINTS = {
     'arn:partition:dynamodb:testing:account:table/aws-lambda-fsm.env': 'http://%s:4569' % os.environ.get('DYNAMODB_HOST', 'localstack'),
     'arn:partition:kinesis:testing:account:stream/aws-lambda-fsm': 'http://%s:4568' % os.environ.get('KINESIS_HOST', 'localstack'),
     'arn:partition:elasticache:testing:account:cluster:aws-lambda-fsm': '%s:11211' % os.environ.get('MEMCACHE_HOST', 'memcached'),
     'arn:aws:ecs:testing:account:cluster/aws-lambda-fsm': 'http://%s:8888' % os.environ.get('ECS_HOST', 'ecs')
}

5. Running create_resources.py

See Setup

You can setup all the resource in settings(local).py using the create_resources.py script. Feel free to export to the environment variables rather than adding them to every comment. They are only listed to be explicit about requirements.

$ workon aws-lambda-fsm
$ PATH=tools:${PATH} PYTHONPATH=. DYNAMODB_HOST=localhost KINESIS_HOST=localhost MEMCACHE_HOST=localhost ECS_HOST=localhost \
  python tools/create_resources.py
...
INFO:root:********************************************************************************
INFO:root:CREATING arn:partition:dynamodb:testing:account:table/aws-lambda-fsm.env
INFO:root:********************************************************************************
...

6. Running dev_lambda.py

This runs a local AWS Lambda-like service. In the following example we have started up a dev_lambda.py listening to the default settings.PRIMARY_STREAM_SOURCE. It is possible to start multiple dev_lambda.py instances, each listening to different event sources, as per the configuration in your settings.

$ workon aws-lambda-fsm
$ AWS_DEFAULT_REGION=testing PYTHONPATH=. DYNAMODB_HOST=localhost KINESIS_HOST=localhost MEMCACHE_HOST=localhost ECS_HOST=localhost \
  python tools/dev_lambda.py --run_kinesis_lambda=1
INFO:root:fsm data={u'current_state': u's1', u'current_event': u'e1', u'machine_name': u'm1'}
INFO:root:action.name=s1-exit-action
INFO:root:action.name=t1-action
INFO:root:action.name=s2-entry-action
INFO:root:action.name=a5-do-action
INFO:root:fsm data={u'current_state': u's2', u'current_event': u'e2', u'machine_name': u'm1', u'context': {}}
INFO:root:action.name=s2-exit-action
INFO:root:action.name=t2-action
INFO:root:action.name=s1-entry-action
...

7. Running start_state_machine.py

This injects a message into AWS Kinesis, AWS DynamoDB, AWS SNS, or AWS SQS to kick off a state machine.

$ workon aws-lambda-fsm
$ PYTHONPATH=. DYNAMODB_HOST=localhost KINESIS_HOST=localhost MEMCACHE_HOST=localhost ECS_HOST=localhost \
  python tools/start_state_machine.py --machine_name=tracer

8. (EXPERIMENTAL) Running dev_ecs.py

This runs a local AWS ECS-like service.

Build the docker image that knows how to run other docker images and emit events back onto the FSM’s event dispatching machinery.

$ docker build -t fsm_docker_runner -f ./tools/experimental/Dockerfile.fsm_docker_runner ./tools/experimental
$ docker build -t dev_ecs -f ./tools/experimental/Dockerfile.dev_ecs ./tools/experimental

dev_ecs.py is configured to run in the supplied docker-compose.yaml. Just start it up alongside LocalStack etc. using

$ docker-compose -f tools/experimental/docker-compose.yaml up

It can also be run directly in a terminal like dev_lambda.py above.

« FSM YAML Running on AWS »