Creating Images, Workflows and Webapps via SDK

To start creating Images, Workflows and Webapps through SDK, we first need to instantiate their respective clients.

The Reference Documentation for these resources can be found here and the usage examples can be found here.

API Documentation is linked with every function in the Reference Documentation which would help in understanding the schema of the payload.

Creating Resource Dependencies with Artifacts

If we want to create a resource such as image, but we don’t want it to be source directly from the code repository, we can package the required files for image creation into a zip archive known as an Artifact.

More information for Artifact can be found in Artifact and Compression Doc.

Providing Instance Type and Storage in Workflow

When defining a workflow step, we have the option to set the instance type and storage by including them in the resources key in the following format:

"resources": {
    "instanceTypeId": 23,
    "storage": "20GB"
}

A list of all available instances along with their corresponding instanceTypeId can be obtained using the list-instance-options function.

Adding the resources section is optional. If we don’t specify it for a particular step, the default values will be used. We can retrieve the default values by using get_default_resources function.

Providing Instance Type in Webapp

When creating a webapp, we have the option to set the instance type by including them in the resources key in the following format:

"resources": {
    "instanceTypeId": 1,
}

Session Stickiness in Webapp

By default, session stickiness is disabled (false). You can activate session stickiness by setting the sessionStickiness parameter to true.

Session stickiness ensures that each user’s requests are consistently directed to a particular server. This feature is especially valuable for stateful applications like web applications that rely on server-stored session data.

Note that employing session stickiness may lead to unpredictable behavior and is not recommended if you plan to scale your application.

Images

Creating an image

We can create an image by using create_image function. We need to provide the payload containing the configuration of the image. If version is not provided in the request body, 0.0.1 would be used as the default version.

image_body = {
    "version": "0.0.1",
    "name": "image-sdk-101",
    "description": "Hello from SDK",
    "type": "workflow",
    "buildDetails": {
        "source": "upload",
        "useCache": False,
        "buildArguments": [
            {
                "name": "HELLO",
                "value": "world",
            },
        ],
        "context": ".",
    },
}

image = image_client.create_image(
    body=image_body,
    artifact={"path": "../peak", "ignore_files": [".dockerignore"]},
)

This returns the imageId and versionId of the newly created image which can be used to create a workflow or a webapp.

{
    "buildId": 1,
    "imageId": 1,
    "versionId": 1
}

buildDetails and source are optional. By default, source will be set to upload. If buildDetails is not provided, it will be set to following:

{
    "source": "upload"
}

Creating an image version

Once an image is created, we can create its subsequent version by using create_version function. We need to provide the image id and payload containing the configuration of the image version. If version is not provided in the request body, the version will be automatically incremented. If source is not provided in the build details, it will be set to upload.

version_body = {
    "version": "0.0.2",
    "buildDetails": {
        "source": "upload",
        "useCache": False,
        "buildArguments": [
            {
                "name": "HELLO",
                "value": "again",
            },
        ],
        "context": ".",
    },
}

image_version = image_client.create_version(
    image_id=1,
    body=version_body,
    artifact={"path": "../peak", "ignore_files": [".dockerignore"]},
)

This returns the imageId and versionId of the newly created image version which can be used to create a workflow or a webapp.

{
    "buildId": 2,
    "imageId": 1,
    "versionId": 2
}

buildDetails and source are optional. By default, source will be set to upload. If buildDetails is not provided, it will be set to following:

{
    "source": "upload"
}

Workflows

Creating a workflow

With the help of above created image versions, we can create a workflow by using create_workflow function. We need to provide the payload containing the configuration of the workflow.

Triggers can be one of the following: Time based, Webhook based or Manual.

// For Time Based Trigger, cron expression is required
"triggers": [
    {
        "cron": "0 0 * * *",
    },
]

// For Webhook Based Trigger, we need to provide webhook key which is a boolean and webhookPolicy which would be either "generate" (in case of creating a new webhook) or "preserve" (in case of using an existing webhook)
"triggers": [
    {
        "webhook": true,
        "webhookPolicy": "generate",
    },
]

// For Manual Trigger, we can either skip this key or provide an empty list
"triggers": []
workflow_body = {
    "name": "new-workflow",
    "triggers": [
        {
            "cron": "0 0 * * *",
        },
    ],
    "watchers": [
        {
            "user": "abc@peak.ai",
            "events": {
                "success": False,
                "fail": True,
            },
        },
        {
            "webhook": {
                "name": "info",
                "url": "https://abc.com/post",
                "payload": '{ "pingback-url": "https:/workflow/123" }',
            },
            "events": {
                "success": False,
                "fail": True,
                "runtimeExceeded": 10,
            },
        },
    ],
    "tags": [
        {
            "name": "foo",
        },
        {
            "name": "bar",
        },
    ],
    "steps": {
        "stepName": {
            "type": "standard",
            "imageId": 1,
            "imageVersionId": 1,
            "command": "python script.py",
            "resources": {
                "instanceTypeId": 21,
                "storage": "10GB",
            },
            "parents": [],
            "stepTimeout": 30,
            "clearImageCache": True,
            "parameters": {
                "env": {
                    "key": "value",
                },
                "secrets": [
                    "secret-1",
                    "secret-2",
                ],
            },
            "repository": {
                "branch": "main",
                "token": "github",
                "url": "https://github.com/org/repo",
            },
        },
    },
}

workflow = workflow_client.create_workflow(workflow_body)

It returns the workflowId of the newly created workflow which can be used to execute the workflow.

{
    "id": 1
}

Executing a workflow

Once a workflow is created, we can run or execute it by providing workflow id. We can provide dynamic parameters that needs to be passed as environment variables to steps. We can execute the workflow by using execute_workflow function.

# Optional parameters
body = {
    "params": {
        "global": {
            "key": "value",
        },
        "stepWise": {
            "step1": {
                "key1": "value1",
            },
        },
    },
}

workflow_client.execute_workflow(workflow_id=1, body=body)

It returns the executionId of the newly executed workflow.

{
    "executionId": "d6116a56-6b1d-41b4-a599-fb949f08863f"
}

Webapps

Note: Only generic (EKS-based) webapps are supported with SDK.

Creating a webapp

With the help of previously created image versions, we can create a webapp by using create_webapp function. We need to provide the payload containing the configuration of the webapp.

# webapp.yaml.j2

body = {
    "name": "webapp101",
    "title": "Hello from SDK",
    "description": "Hi there",
    "imageDetails": {"imageId": 1, "versionId": 1},
    "resources": {
        "instanceTypeId": 1,
    },
    "sessionStickiness": True,
}

webapp = webapp_client.create_webapp(body)

It returns the id of the newly created webapp.

{
    "id": "84a41de7-d67f-4aa0-aebe-83c1474f0eaf"
}