In this post we are going to develop a simple workflow using CronDock
After signing up the CronDock web portal will provide you with an "API key" which can be used to call the CronDock RESTful API. Note that at this moment you can only communicate with CronDock through our API. Using the API key you can call the CronDock via different tools such as "curl", python libraries such as "requests" or tools such as postman .
The CronDock API end point is https://api.crondock.com/
.
Keep in mind that in all your API calls to CronDock API endpoint, you should add your "API key" in
a Header called "Authorization" and you need to add "Api-Key
" at its begining. So for instance in
"curl" you will have something like (replace XXXXX
with your "API key"):
curl -X GET -H "Content-Type: application/json" -H "Authorization: Api-Key XXXXX" https://api.crondock.com/workflow/Or in python:
import requests headers = { 'Content-Type': 'application/json', 'Authorization': 'Api-Key XXXXX', } response = requests.get('https://api.crondock.com/workflow/', headers=headers)
Now, let's define a "Workflow", a workflow is a collection of "Tasks" (read this post to learn more about tasks) that have dependencies with each other. For instance let's say you want to automatically check whether your website is up or not every day and if it is down you want to receive a slack message. In this case you want to first run a task that sends a request to your website, and if the request failed you want to spin up another task that sends you a slack message notifying you that the website is down. In this example the second task has a dependency to the first task and it only runs when the first task fails. In such cases you can use a workflow.
To create a workflow using CronDock, you need to submit a POST
request to
/workflow/
endpoint and pass the tasks (and other workflow parameters)
as part of the payload. The workflow parameters are as follow:
name
: a name for your workflow, note that this name will get updated with a suffix by the
system to avoid having the same name for different runs.type
: the type of the workflow which can be either simple
or cron
,
note that simple
workflows run only once after being created and cron
workflows run frequently based on the provided
schedule
schedule
: the schedule to run the cron workflows. This should be a string that defines the schedule
of the workflow and should follow the cron format (you can read more about cron format here: https://crontab.guru/).
Note that this only can be used in workflowss with type
set as cron
.tasks
: a list of tasks to run as part of the workflow. The format for each task is very similar to
the format of simple tasks (again, read this post to learn more about simple tasks) with only
one new element which is dependencies
. We will discuss the task section and task dependencies
more below.
name
: a name for the task, this name will be used to define the dependencies.image
: path to the container image you want to run, note that with a free account you can only
run public images and you need a basic or enterprise account for running images from private repositories.args
: the argument to pass to the container, note that the arguments should be provided as
a list of string values.dependencies
: a string to define the dependencies for the task to run. Dependency to another task
should be defined in {task-name}.{status}
format where {task-name}
is the name of another task that this task is
dependent on and the {status}
is the final status of that task for which this task should run. The {status}
can
be either succeed
or failed
. Note that you can also have multiple dependencies by using &
(as and
)
, |
(as or
) operators and !
(as not
) operators. For instance if the task is dependent
on 3 tasks and should run only if the first task (named task-1
) succeed and one of the second task (named task-2
)
or third task (named task-3
) failed, the dependency would look like this: "task-1.succeed & (task-2.failed | !task-3.succeed)"
.
curl
from docker hub (curlimages/curl:latest
)
to send requests to CronDock and send messages to slack via the webhook. You can learn more about the official curl docker image
here.
The first step is to create an incoming webhook for your slack channel. You can follow
this simple insturction from slack to create an
incoming webhook. Sending messages to slack via webhook is very easy, you only need to push a POST
request like this to the webhook:
curl -X POST --data-urlencode "payload={\"text\":\"Hello, World! \"}" https://hooks.slack.com/services/XXX/XXXXWhere
https://hooks.slack.com/services/XXX/XXXX
is the webhook you have created for your channel, and text
in the payload
is the message you want to send to slack. Run it and you will recive receive a "Hello, World!" message on your slack channel.
So having that we need to create a workflow with two tasks, one that sends a GET
request to https://crondock.com and one
that pushes a POST
request to our slack webhook with a text
like "Your website is down!". The seconds task should run only
if the first task fails, so we will have a dependency for the second task to run only if the first task failed
.
We want our workflow to run on daily basis, so we should set the workflow type
to cron
and the schedule
to
something like "30 2 * * *"
which means run the workflow at 02:30 AM UTC every day.
To make sure that we are going to get the slack message through the second task we can first create a simple task and test it using that.
The task can be something like this (replace Api-Key XXXXX
with your Api Key and https://hooks.slack.com/services/XXX/XXXX
with your slack webhook url):
curl -X POST -H "Content-Type: application/json" -H "Authorization: Api-Key XXXXX" -d '{ "name": "slack-test", "image": "curlimages/curl:latest", "args": ["--data-urlencode", "payload={\"text\":\"Your website is down! \"}" , "https://hooks.slack.com/services/XXX/XXXX"], "type": "simple" }' https://api.crondock.com/task/
And you should receive a message on your slack channel like this:
So based on our discussion above you can create the workflow like this:
curl -X POST -H "Content-Type: application/json" -H "Authorization: Api-Key XXXXX" -d '{ "name": "check-crondock-website", "type": "cron", "schedule": "30 2 * * *", "tasks":[ { "name": "task-1", "image": "curlimages/curl:latest", "args": ["-L", "-v", "https://crondock.com"], "dependencies": "" }, { "name": "task-2", "image": "curlimages/curl:latest", "args": ["--data-urlencode", "payload={\"text\":\"Your website is down! \"}" , "https://hooks.slack.com/services/XXX/XXXX"], "dependencies": "task-1.failed" } ] }' https://api.crondock.com/workflow/
Now looking at created workflows we have:
curl -X GET -H "Content-Type: application/json" -H "Authorization: Api-Key XXXXX" https://api.crondock.com/workflow/ {"count":1,"next":null,"previous":null,"results":[ { "id":1, "tasks":[ { "id":1, "created_at":"2022-07-20T01:05:17.966297Z", "name":"task-1", "image":"curlimages/curl:latest", "args":["-L","-v","https://crondock.com"], "dependencies":"", "user":2, "workflow":1 }, { "id":2, "created_at":"2022-07-20T01:05:17.976800Z", "name":"task-2", "image":"curlimages/curl:latest", "args":["--data-urlencode","payload={\"text\":\"Your website is down! \"}","https://hooks.slack.com/services/XXX/XXXX"], "dependencies":"task-1.failed", "user":2, "workflow":1 } ], "created_at":"2022-07-20T01:05:17.786737Z", "name":"check-crondock-website-rtoatd", "type":"cron", "schedule":"30 2 * * *", "user":2 } ]}
Now after the workflow runs we can take alook at its results so far. Note that in the above we have "id":1
for the workflow, we can get the results for all the workflows by submitting a GET
request to
/result/
endpoint. When we want to get the results for a specific workflow we can
filter the results by passing the workflow. For instance for the workflow above with "id":1
we can pass
?workflow=1
in the url. So we are going to have:
curl -X GET -H "Content-Type: application/json" -H "Authorization: Api-Key XXXXX" https://api.crondock.com/result/?workflow=1 {"count":1,"next":null,"previous":null,"results":[ { "id":1, "results":[ { "id":9, "created_at":"2022-07-20T02:30:05.319748Z", "name":"task-1-bsrukc", "image":"curlimages/curl:latest", "args":["-L","-v","https://crondock.com"], "type":"workflow", "schedule":"", "user":2, "workflow_task":1, "workflow_result":1, "secret":null } ], "created_at":"2022-07-20T02:30:03.691986Z", "user":2, "workflow":1 }] }
So based on the results, for that workflow so far one task have been ran with "id":9
and based on the name
it was the task-1
from the workflow. Note that the system will add a randomly generated sequence of alphabet
as a suffix of the name to avoid using similar names for the same tasks.
So now let's pull more information on that task:
curl -X GET -H "Content-Type: application/json" -H "Authorization: Api-Key XXXXX" https://api.crondock.com/task/9/ {"count":1,"next":null,"previous":null,"results":[ { "id":9, "created_at":"2022-07-20T02:30:05.319748Z", "name":"task-1-bsrukc", "image":"curlimages/curl:latest", "args":["-L","-v","https://crondock.com"], "type":"workflow", "schedule":"", "user":2, "workflow_task":1, "workflow_result":1, "secret":null, "results":[ { "status":{ "start_time":"2022-07-20 02:30:05+00:00", "phase":"Succeeded" }, "metadata":{ "name":"task-1-bsrukc-9fck2" } }] }] }
Based on the "phase":"Succeeded"
in the status
section, task-1
was
successful, meaining it was able to load the website so the website was up and running. As a result, since the
condition we have for dependencies
in task-2
is "task-1.failed"
, that task did not
meet the condition and as expected task-2
didn't run and we didn't get any message regurding the website
being down on slack.
If needed we can also pull the full output of the task by passing log=true
in the url like This:
curl -X GET -H "Content-Type: application/json" -H "Authorization: Api-Key XXXXX" https://api.crondock.com/task/9/?log=true
and that will show the html code of the website pulled by the task.
This article shows how you can create a workflow on CronDock. Please let me know if you have any question at support@crondock.com
I also have a good document which provides more detailed information on all the requests you can make to CronDock API.