Using Images, Workflows and Webapps via CLI

To create images, workflows or webapps via the Command Line Interface (CLI), we can define a YAML file or pass the required options through command line arguments. This YAML file includes the payload, metadata, and configuration of the image. By utilizing jinja syntax, we have the ability to pass parameter value as {{value}}, with the actual value being specified in a separate YAML file.

Defining Parameters in Resource Creation

While creating resources, we can define parameters in a separate file and then use them by specifying the file path after the -v flag in the command. We can also add parameters by adding the desired key-value pair after the -p flag. If we specify both -v and -p, the parameters defined on the command line will overwrite the parameters defined in the file.

# params.yaml

git_token: "random_git_token"
npm_token: "random_npm_token"

Using a combination of command line options and yaml

For creating resources such as images and webapps, we can use a combination of command line options and the yaml. In this case the command line options will take precedence over the yaml values.

Consider the following example for creating a webapp:

# webapp_params.yaml

imageId: 2
versionId: 2
# webapp.yaml.j2
body:
    title: Updated webapp
    description: This is an updated webapp
    imageDetails:
        imageId: {{imageId}}
        versionId: {{versionId}}
peak webapps update -v path/to/webapp_params.yaml <webapp-id> path/to/webapp.yaml.j2 --image-id 3

In the above example, the imageId will be overwritten by the command line options and the final webapp body will look like:

{
    "title": "Updated webapp",
    "description": "This is an updated webapp",
    "imageDetails": {
        "imageId": 3,
        "versionId": 2
    }
}

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 source code repository, then we will need to pack all the files we might need to build the image and pack them into an zip archive which is called Artifact.

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

Providing Instance Type and Storage to Workflow

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

resources:
    instanceTypeId: 23,
    storage: 20GB,

To obtain a list of all available instances along with their corresponding instanceTypeId, we can use the following command:

peak workflows list-resources

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 through the following command:

peak workflows list-default-resources

Images

Creating an image

We can create an image by providing payload containing its configuration. If version is not provided in the request body, the version will be set to 0.0.1.

# image_params.yaml

token: my_token
param1: my_parameter1
param2: my_parameter2
# upload_image.yaml.j2

body:
    name: upload-image
    version: "0.0.1-test"
    description: Creating a new upload type image
    type: workflow
    buildDetails:
        source: upload
        useCache: false
        buildArguments:
            - name: PARAM1
              value: {{param1}}
            - name: PARAM2
              value: {{param2}}
        context: .
artifact:
    path: "."
    ignore_files:
        - ".gitignore"
        - ".dockerignore"
# github_image.yaml.j2

body:
    name: github-image
    version: "0.0.1-test"
    description: Creating a new github type image
    type: workflow
    buildDetails:
        source: github
        repository: https://example.com
        branch: main
        token: {{token}}
        dockerfilePath: Dockerfile
        buildArguments:
            - name: PARAM1
              value: {{param1}}
            - name: PARAM2
              value: {{param2}}
        useCache: true
# dockerfile_image.yaml.j2

body:
    name: dockerfile-image
    version: "0.0.1-test"
    description: Creating a new dockerfile type image
    type: workflow
    buildDetails:
        source: dockerfile
        useCache: false
        buildArguments:
            - name: PARAM1
              value: {{param1}}
            - name: PARAM2
              value: {{param2}}
        dockerfile: "FROM nginx"

We can use the following command to create an image:

peak images create path/to/upload_image.yaml.j2 -v path/to/image_params.yaml

We can create an image directly from the command line by specifying all the required parameters:

peak images create --name example-image --version 0.0.1-test --type workflow --description "Creating a new image" --source github --repository https://example.com --branch main --build-arguments arg1=value1 --build-arguments arg2=value2 --secrets secret_1,secret_2

We can also combine the YAML template and command line arguments, where the command line arguments will take precedence over the YAML file. Create the YAML template file with the following content:

# image.yaml.j2

body:
    name: my-image
    version: 0.0.1-test
    type: workflow
    description: Creating a new image
    buildDetails:
        source: github
        repository: https://example.com
        branch: main
        useCache: true
peak images create path/to/image.yaml.j2 --name my-awesome-image

In this case, the final image body will look like:

{
    "name": "my-awesome-image",
    "version": "0.0.1-test",
    "type": "workflow",
    "description": "Creating a new image",
    "buildDetails": {
        "source": "github",
        "repository": "https://example.com",
        "branch": "main",
        "useCache": true
    }
}

Creating an image version

Once an image is created, we can create its subsequent version by providing the image id and payload containing its configuration. If version is not provided in the request body, the version will be automatically incremented.

# image_params.yaml

token: my_token
param1: my_parameter1
param2: my_parameter2
# upload_image_version.yaml.j2

body:
    version: 0.0.2-test-upload
    description: Creating a new image version
    buildDetails:
        source: upload
        context: "."
        dockerfilePath: Dockerfile
        buildArguments:
            - name: PARAM1
              value: {{param1}}
            - name: PARAM2
              value: {{param2}}
        useCache: true
artifact:
    path: "."
    ignore_files:
        - ".gitignore"
        - ".dockerignore"
# github_image_version.yaml.j2

body:
    version: 0.0.2-test-github
    description: Creating a new image version
    buildDetails:
        source: github
        repository: https://example.com
        branch: main
        token: {{token}}
        dockerfilePath: Dockerfile
        buildArguments:
            - name: PARAM1
              value: {{param1}}
            - name: PARAM2
              value: {{param2}}
        useCache: true
# dockerfile_image_version.yaml.j2

body:
    version: 0.0.2-test-dockerfile
    description: Creating a new image version
    buildDetails:
        source: dockerfile
        useCache: false
        buildArguments:
            - name: PARAM1
              value: {{param1}}
            - name: PARAM2
              value: {{param2}}
        dockerfile: "FROM nginx"

We can use the following command to create an image version:

peak images create-version -v path/to/image_params.yaml <image-id> path/to/image_version.yaml.j2

We can create an image version directly from the command line by specifying all the required parameters:

peak images create-version 123 --version 0.0.2-test --description "Creating a new image version" --source github --repository https://example.com --branch main --build-arguments arg1=value1 --build-arguments arg2=value2 --secrets secret_1,secret_2

Similar to creating an image, we can also combine the YAML template and command line options to create the image version, with the command line options taking precedence.

Updating an image version

An image version can be modified if it was not build successfully and is in not-ready state. We can update an image version by providing the image id, version id and payload containing its configuration.

# image_params.yaml

token: my_token
param1: my_parameter1
# upload_image_version.yaml.j2

body:
    description: Updating the image version
    buildDetails:
        source: upload
        context: "."
        dockerfilePath: Dockerfile
        buildArguments:
            - name: PARAM1
              value: {{param1}}
        useCache: true
artifact:
    path: "."
    ignore_files:
        - ".gitignore"
        - ".dockerignore"
# github_image_version.yaml.j2

body:
    description: Updating the image version
    buildDetails:
        source: github
        repository: https://example.com
        branch: main
        token: {{token}}
        dockerfilePath: Dockerfile
        buildArguments:
            - name: PARAM1
              value: {{param1}}
            - name: PARAM2
              value: {{param2}}
        useCache: true
# dockerfile_image_version.yaml.j2

body:
    description: Updating the image version
    buildDetails:
        source: dockerfile
        useCache: false
        buildArguments:
            - name: PARAM1
              value: {{param1}}
            - name: PARAM2
              value: {{param2}}
        dockerfile: "FROM nginx"

We can use the following command to update an image version:

peak images update-version --image-id -v path/to/image_params.yaml <image-id> --version-id <version-id> path/to/image_version.yaml.j2

We can update an image version directly from the command line by specifying all the required parameters:

peak images update-version --image-id 123 --version-id 456 --description "Updating the image version" --source github --repository https://example.com --branch main --build-arguments arg1=value1 --build-arguments arg2=value2 --secrets secret_1,secret_2

Similar to creating an image, we can also combine the YAML template and command line options to update the version, with the command line options taking precedence.

Using the create-or-update operation

The operation creates a new resource if it doesn’t exist and updates the resource in case it exists. The search is based on resource name and version fields.

Consider the following example for creating a new image version:

# image_params.yaml

token: my_token
param1: my_parameter1
param2: my_parameter2
# upload_image_version.yaml.j2

body:
    name: test-image
    version: 0.0.2-test-upload
    description: Creating a new image version
    buildDetails:
        source: upload
        context: "."
        dockerfilePath: Dockerfile
        buildArguments:
            - name: PARAM1
              value: {{param1}}
            - name: PARAM2
              value: {{param2}}
        useCache: true
artifact:
    path: "."
    ignore_files:
        - ".gitignore"
        - ".dockerignore"

We can use the following command to create or update a image version:

peak images create-or-update -v path/to/image_params.yaml path/to/image_version.yaml.j2

We can create or update a image version directly from the command line by specifying all the required parameters:

peak images create-or-update --name test-image --version 0.0.2-test --description "Creating a new image version" --source github --repository https://example.com --branch main --build-arguments arg1=value1 --build-arguments arg2=value2 --secrets secret_1,secret_2

Similar to creating an image, we can also combine the YAML template and command line options to create the image version, with the command line options taking precedence.

Workflows

Note: Workflows with only standard steps are supported.

Creating a workflow

We can create a workflow by providing payload containing its configuration.

# workflow_params.yaml

imageId: 1
versionId: 1
token: my_token
# workflow.yaml.j2

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: {{imageId}}
            imageVersionId: {{versionId}}
            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: {{token}}
                url: "https://github.com/org/repo"

We can use the following command to create a workflow:

peak workflows create path/to/workflow.yaml.j2 -v path/to/workflow_params.yaml

Updating a workflow

We can update a workflow by providing payload containing its configuration.

# workflow_params.yaml

imageId: 1
versionId: 1
token: my_token
# workflow.yaml.j2

body:
    name: updated-workflow
    triggers:
        - webhook: true
          webhookPolicy: "generate"
    tags:
        - name: CLI
    steps:
        step1:
            command: echo hello world
            type: standard
            repository:
                branch: main
                token: {{token}}
                url: https://example.com
            imageId: {{imageId}}
            imageVersionId: {{versionId}}
            resources:
                instanceTypeId: 21
                storage: 10GB
        step2:
            command: echo world
            type: standard
            imageId: {{imageId}}
            imageVersionId: {{versionId}}
            resources:
                instanceTypeId: 21
                storage: 40GB

We can use the following command to update a workflow:

peak workflows update  -v path/to/workflow_params.yaml <workflow-id> path/to/workflow.yaml.j2

Using the create-or-update operation

We can create or update a workflow by providing payload containing its configuration. The search operation will be based on name.

# workflow_params.yaml

imageId: 1
versionId: 1
token: my_token
# workflow.yaml.j2

body:
    name: my-new-workflow
    triggers:
        - webhook: true
          webhookPolicy: "generate"
    tags:
        - name: CLI
    steps:
        step1:
            command: echo hello world
            type: standard
            repository:
                branch: main
                token: {{token}}
                url: https://example.com
            imageId: {{imageId}}
            imageVersionId: {{versionId}}
            resources:
                instanceTypeId: 21
                storage: 10GB
        step2:
            command: echo world
            type: standard
            imageId: {{imageId}}
            imageVersionId: {{versionId}}
            resources:
                instanceTypeId: 21
                storage: 40GB

We can use the following command to create or update a workflow:

peak workflows create-or-update  -v path/to/workflow_params.yaml path/to/workflow.yaml.j2

Partial Workflow Update using patch workflow

Consider an existing workflow with step details:

"name": "existing-workflow",
"triggers": [],
"steps": {
    "step1": {
        "imageId": 1,
        "imageVersionId": 1,
        "command": "python test1.py",
        "resources": {
            "instanceTypeId": 21,
            "storage": "10GB",
        }
    },
    "step2": {
        "imageId": 2,
        "imageVersionId": 2,
        "command": "python test2.py",
         "resources": {
            "instanceTypeId": 22,
            "storage": "10GB",
        }
    },
}

We can partially update a workflow in the following ways.

  1. Command Line Arguments Approach

By passing the parameters to be updated as command line arguments. We can provide step names --step-names, which would update the steps with the provided parameters. In case step names are not provided, all the steps of the workflow would be updated.

peak workflows patch <workflow_id> --name updated-workflow --image-id 100 --image-version-id 100 --step-names step1

This would update imageId and imageVersionId of step1 and step2 of the workflow.

"name": "updated-workflow",
"steps": {
    "step1": {
        "imageId": 100,
        "imageVersionId": 100,
        "command": "python test1.py",
        "resources": {
            "instanceTypeId": 21,
            "storage": "10GB",
        },
    },
    "step2": {
        "imageId": 2,
        "imageVersionId": 2,
        "command": "python test2.py",
        "resources": {
            "instanceTypeId": 22,
            "storage": "10GB",
        },
    },
}
  1. YAML File Approach

We can update parameters via a YAML file:

# patch-workflow.yaml.j2

body:
    name: "updated-workflow"
    triggers:
        - {}
    steps:
        step1:
            imageId: 100
            imageVersionId: 100
        step4:
            imageId: 400
            imageVersionId: 400
            command: "python test4.py"
            resources:
                instanceTypeId: 24
            repository:
                url: "https://github.com/org/repo"
                branch: main
                token: "some-token"

Use the following command to update the workflow:

peak workflows patch <workflow_id> path/to/patch-workflow.yaml.j2

The updated workflow would look like following:

"name": "updated-workflow",
"triggers": [],
"steps": {
    "step1": {
        "imageId": 100,
        "imageVersionId": 100,
        "command": "python test1.py",
        "resources": {
            "instanceTypeId": 21,
            "storage": "10GB",
        },
    },
    "step2": {
        "imageId": 2,
        "imageVersionId": 2,
        "command": "python test2.py",
        "resources": {
            "instanceTypeId": 22,
            "storage": "10GB",
        },
    },
    "step4": {
        "imageId": 400,
        "imageVersionId": 400,
        "command": "python test4.py",
        "resources": {
            "instanceTypeId": 24,
            "storage": "10GB",
        },
        "repository": {
            "branch": "main",
            "token": "github",
            "url": "https://github.com/org/repo",
        },
    },
}

Through the above approach, specific keys of step1 and step2 are updated, while step3 remains unchanged, and step4 is added as a new step.

We can also combine the YAML file and command line options, with command line options taking precedence.

Note that the keys and values in the above examples are for illustrative purposes.

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.

# execute_workflow.yaml.j2

body:
    params:
        global:
            param1: value1
        stepWise:
            step1:
                param2: value2
            step2:
                param3: value3

We can use the following command to execute the workflow:

peak workflows execute <workflow-id> path/to/execute_workflow.yaml.j2

Webapps

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

Creating a webapp

We can create a webapp by providing payload like following.

# webapp_params.yaml

imageId: 1
versionId: 1
# webapp.yaml.j2

body:
    name: my-webapp
    title: New webapp
    description: This is a new webapp
    imageDetails:
        imageId: {{imageId}}
        versionId: {{versionId}}

We can use the following command to create a webapp:

peak webapps create path/to/webapp.yaml.j2 -v path/to/webapp_params.yaml

Alternatively, we can also use the create command without having the need to provide a yaml. This is possible using the command line options or optionally combining them with yaml template, with the command line options taking precedence.

peak webapps create --name my-webapp --description some-description --title my-title --image-id <image-id> --version-id <version-id>

Above command will generate the following json body:

{
    "name": "my-webapp",
    "title": "my-title",
    "description": "some-description",
    "imageDetails": {
        "imageId": "<image-id>",
        "versionId": "<version-id>"
    }
}

Updating a webapp

We can update the webapp by providing webapp id and payload like following.

# webapp_params.yaml

imageId: 2
versionId: 2
# webapp.yaml.j2

body:
    title: Updated webapp
    description: This is an updated webapp
    imageDetails:
        imageId: {{imageId}}
        versionId: {{versionId}}

We can use the following command to update a webapp:

peak webapps update -v path/to/webapp_params.yaml <webapp-id> path/to/webapp.yaml.j2

Alternatively, we can also use the update command without having the need to provide a yaml. This is possible using the command line options or optionally combining them with yaml template, with the command line options taking precedence.

peak webapps update <webapp-id> --description some-description --title my-title --image-id <image-id> --version-id <version-id>

Above command will generate the following json body:

{
    "title": "my-title",
    "description": "some-description",
    "imageDetails": {
        "imageId": "<image-id>",
        "versionId": "<version-id>"
    }
}

Using the create-or-update operation

The operation creates a new resource if it doesn’t exist and updates the resource in case it exists. The search is based on resource name field.

Consider the following example for creating a webapp:

# webapp_params.yaml

imageId: 2
versionId: 2
# webapp.yaml.j2
body:
    title: New webapp
    description: This is an new  webapp
    imageDetails:
        imageId: {{imageId}}
        versionId: {{versionId}}
peak webapps create-or-update -v path/to/webapp_params.yaml <webapp-id> path/to/webapp.yaml.j2 --image-id 3 --name my-webapp

Now we could update the webapp created with above command as follows:

# webapp_params.yaml

imageId: 2
versionId: 2
# webapp.yaml.j2
body:
    title: Updated webapp
    description: This is an updated webapp
    imageDetails:
        imageId: {{imageId}}
        versionId: {{versionId}}
peak webapps create-or-update -v path/to/webapp_params.yaml <webapp-id> path/to/webapp.yaml.j2 --image-id 3 --name my-webapp

In the above example, the imageId will be overwritten by the command line options and the final webapp body will look like:

{
    "title": "Updated webapp",
    "description": "This is an updated webapp",
    "imageDetails": {
        "imageId": 3,
        "versionId": 2
    }
}