Initialize a new Tapis Actor project
This guide will demonstrate how to create a custom actor from scratch. It is assumed you are already familiar with how to Work with Actors. In this example, we will build a simple word count actor that counts and prints the number of words in a provided message.
We will demonstrate how to initialize an actor project from scratch.
Create a project “hello_world_actor”
To get started with creating an actor, running the tapis actors init
command will fetch a very simple
code skeleton you can fill in and deploy.
For example:
$ tapis actors init
+-------+-----------------------------------------------------+
| stage | message |
+-------+-----------------------------------------------------+
| setup | Project path: ./new_actor |
| setup | CookieCutter variable name=new_actor |
| setup | CookieCutter variable project_slug=new_actor |
| setup | CookieCutter variable docker_namespace=reshg |
| setup | CookieCutter variable docker_registry=e |
| clone | Project path: ./new_actor |
+-------+-----------------------------------------------------+
Note
There are many project templates you can start working with. See tapis actors init –list-templates for an up to date listing.
$ tapis actors init --list-templates
+--------------------+--------------------+--------------------------------------------------------+----------+
| id | name | description | level |
+--------------------+--------------------+--------------------------------------------------------+----------+
| default | Default | Basic code and configuration skeleton | beginner |
| echo | Echo | Echo message | beginner |
| hello_world | Hello World | Say Hello, World! | beginner |
| sd2e_base | sd2e_base | Default reactor context for | beginner |
| | | docker://sd2e/reactors:python3 | |
| tacc_reactors_base | tacc_reactors_base | Default actor context for | beginner |
| | | docker://sd2e/reactors:python3 | |
+--------------------+--------------------+--------------------------------------------------------+----------+
To use one of these templates:
$ tapis actors init --template hello_world
Components of an Actor
The new_actor/ project would contain the following files:
$ tree ../new_actor/
new-actor/
├── Dockerfile
├── project.ini
├── config.yml
├── default.py
├── requirements.txt
├── secrets.jsonsample
└── message.jsonschema
Write the Actor Function
The default.py
script can be renamed to hello_world.py
. The python script is where the code for your
main function can be found. An example of a functional actor that says “Hello, World” is:
"""Say Hello, World or the message received from user input"""
from agavepy.actors import get_context
# function to print the message
def say_hello_world(m):
"""Print message from user if present, else echo "Hello, World"""
if m == " ":
print("Actor says: Hello, World")
else:
print("Actor received message: {}".format(m))
def main():
"""Main entry to grab message context from user input"""
context = get_context()
message = context['raw_message']
say_hello_world(message)
if __name__ == '__main__':
main()
This code makes use of the agavepy python library which we will install in
the Docker container. The library includes an “actors” object which is useful to
grab the message and other context from the environment. And, it can be used to
interact with other parts of the Tapis platform. Add the above code to your
hello_world.py
file.
Define Requirements
The requirements.txt
file may contain the dependencies required for a project.
The default requirements.txt
contains agavepy python package.
Create a Dockerfile
The only requirements are python and the agavepy python library, which is
available through
PyPi. These are mentioned in the requirements.txt
file
A bare-bones Dockerfile needs to satisfy those dependencies, add the actor
python script, and set a default command to run the actor python script.
The following lines should be present in your Dockerfile
:
# pull base image
FROM python:3.7-alpine
# add requirements.txt to docker container
ADD requirements.txt /requirements.txt
# install requirements.txt
RUN pip3 install -r /requirements.txt
# add the python script to docker container
ADD hello_world.py /hello_world.py
# command to run the python script
CMD ["python", "/hello_world.py"]
Tip
Creating small Docker images is important for maintaining actor speed and efficiency
Runtime Preparation
Define secrets.json: Rename secrets.json.sample to secrets.json, and obtain the required values from the Infrastructure team for secrets.json.
Define message.jsonschema: Define the Schema for Actor launch message.
Build and Push the Dockerfile
The Docker image must be pushed to a public repository in order for the actor to use it. Use the following Docker commands in your local actor folder to build and push to a repository that you have access to:
# Build and tag the image
$ docker build -t taccuser/hello-world:1.0 .
Sending build context to Docker daemon 4.096kB
Step 1/5 : FROM python:3.7-slim
...
Successfully built b0a76425e8b3
Successfully tagged taccuser/hello-world:1.0
# Push the tagged image to Docker Hub
$ docker push taccuser/hello-world:1.0
The push refers to repository [docker.io/taccuser/word-count]
...
1.0: digest: sha256:67cc6f6f00589d9ae83b99d779e4893a25e103d07e4f660c14d9a0ee06a9ddaf size: 1995
Create the Actor
Next, create an actor referring to the Docker repository above.
$ tapis actors create --repo taccuser/hello-world:1.0 \
-n hello-world \
-d "Actor to say Hello, World"
+----------------+----------------------------+
| Field | Value |
+----------------+----------------------------+
| id | NN5N0kGDvZQpA |
| name | hello-world |
| owner | taccuser |
| image | taccuser/hello-world:1.0 |
| lastUpdateTime | 2021-07-14T22:25:06.171534 |
| status | SUBMITTED |
| cronOn | False |
+----------------+-----------------------------+
After a few seconds, the actor should be in state “READY”, meaning it is ready
to accept and process messages. Verbosely show the actor metadata to see that
it’s status is “READY”, it is pointing to the correct docker image, and that it
received the environment variables from environment.json
:
$ tapis actors show -v NN5N0kGDvZQpA
{
"id": "NN5N0kGDvZQpA",
"name": "example-actor",
"description": "Test actor that says Hello, World",
"owner": "sgopal",
"image": "tacc/hello-world:latest",
"createTime": "2021-07-14T22:25:06.171Z",
"lastUpdateTime": "2021-07-14T22:25:06.171Z",
"defaultEnvironment": {},
"gid": 862347,
"hints": [],
"link": "",
"mounts": [],
"privileged": false,
"queue": "default",
"stateless": true,
"status": "READY",
"statusMessage": " ",
"token": true,
"uid": 862347,
"useContainerUid": false,
"webhook": "",
"cronOn": false,
"cronSchedule": null,
"cronNextEx": null,
"_links": {
"executions": "https://api.tacc.utexas.edu/actors/v2/NN5N0kGDvZQpA/executions",
"owner": "https://api.tacc.utexas.edu/profiles/v2/sgopal",
"self": "https://api.tacc.utexas.edu/actors/v2/NN5N0kGDvZQpA"
}
}
Run a Test Execution
Finally, pass a message to the actor to run a test execution. The number of words in the message should be returned in the actor execution logs:
# Send a message to the word-count actor
$ tapis actors submit -m "Hello, World" NN5N0kGDvZQpA
+-------------+-------------------------------------+
| Field | Value |
+-------------+-------------------------------------+
| executionId | NN5N0kGDvZQpA |
| msg | Hello, World |
+-------------+-------------------------------------+
# List executions of the word-count actor
$ tapis actors execs list NN5N0kGDvZQpA
+---------------+----------+
| executionId | status |
+---------------+----------+
| N4xQ5WM5Np1X0 | COMPLETE |
+---------------+----------+
# Get the logs from the completed actor execution
$ tapis actors execs logs NN5N0kGDvZQpA N4xQ5WM5Np1X0
Logs for execution N4xQ5WM5Np1X0
Actor received message: Hello, World
The actor can also be run synchronously using tapis actors run
:
$ tapis actors run -m "Hello, World" NN5N0kGDvZQpA
Actor received message: Hello, World
Next Steps
Remember to put your actor under version control. Use a .gitignore
file to
avoid accidentally committing anything that contains API keys or passwords.
Please refer to the Abaco Documentation for more information on creating and working with actors.