type: "io.kestra.plugin.modal.cli.ModalCLI"
Execute Modal commands from the Command Line Interface
Examples
Run a Hello-World Modal example. Make sure to replace the MODAL_TOKEN_ID
and MODAL_TOKEN_SECRET
with your Modal credentials.
id: modal_hello_world
namespace: company.team
tasks:
- id: hello
type: io.kestra.plugin.modal.cli.ModalCLI
env:
MODAL_TOKEN_ID: "your_modal_token_id"
MODAL_TOKEN_SECRET: "your_modal_token_secret"
commands:
- modal run hello.py
inputFiles:
hello.py: |
import modal
app = modal.App("hello-world")
@app.function()
def hello():
print("hello from modal")
return "Success!"
Pass environment variables to the Modal CLI task from Kestra's inputs.
id: env_vars_modal
namespace: company.team
inputs:
- id: run_modal
displayName: Whether to run the Modal task
type: BOOLEAN
defaults: true
- id: cpu
type: SELECT
displayName: CPU request
description: The number of CPU cores to allocate to the container
defaults: "0.25"
values: ["0.25", "0.5", "0.75", "1.0", "1.5", "2.0", "4.0", "8.0", "16.0", "32.0"]
dependsOn:
inputs:
- run_modal
condition: "{{ inputs.run_modal equals true }}"
- id: memory
type: SELECT
displayName: Memory request
description: Amount of memory in MiB to allocate to the container
defaults: "512"
values: ["512", "1024", "2048", "4096", "8192", "16384", "32768"]
dependsOn:
inputs:
- run_modal
condition: "{{ inputs.run_modal }}"
tasks:
- id: set_compute_resources
type: io.kestra.plugin.modal.cli.ModalCLI
env:
MODAL_TOKEN_ID: "{{ secret('MODAL_TOKEN_ID') }}"
MODAL_TOKEN_SECRET: "{{ secret('MODAL_TOKEN_SECRET') }}"
CPU: "{{ inputs.cpu }}"
MEMORY: "{{ inputs.memory }}"
commands:
- modal run script.py
inputFiles:
script.py: |
import os
import modal
app = modal.App(
"env-vars",
secrets=[modal.Secret.from_local_environ(env_keys=["CPU", "MEMORY"])],
)
@app.function(cpu=float(os.getenv("CPU")), memory=int(os.getenv("MEMORY")))
def generate_data():
cpu = os.getenv("CPU")
memory = os.getenv("MEMORY")
resources = dict(cpu=cpu, memory=memory)
print(f"Running the function with CPU={cpu} and MEMORY={memory}")
return resources
@app.local_entrypoint()
def main():
output = generate_data.remote()
print(f"hello from main function - output is: {output}")
Execute a Python script from Git on a cloud VM using Modal.
id: modal_git
namespace: company.team
tasks:
- id: repository
type: io.kestra.plugin.core.flow.WorkingDirectory
tasks:
- id: clone
type: io.kestra.plugin.git.Clone
branch: main
url: https://github.com/kestra-io/scripts
- id: modal_cli
type: io.kestra.plugin.modal.cli.ModalCLI
commands:
- modal run modal/getting_started.py
env:
MODAL_TOKEN_ID: "{{ secret('MODAL_TOKEN_ID') }}"
MODAL_TOKEN_SECRET: "{{ secret('MODAL_TOKEN_SECRET') }}"
Execute a Python script on a GPU-powered instance in the cloud using Modal. First, add the script that you want to orchestrate as a Namespace File in the Editor and point to it in the commands
section.
id: modal
namespace: company.team
tasks:
- id: modal_cli
type: io.kestra.plugin.modal.cli.ModalCLI
namespaceFiles:
enabled: true
commands:
- modal run gpu.py
env:
MODAL_TOKEN_ID: "{{ secret('MODAL_TOKEN_ID') }}"
MODAL_TOKEN_SECRET: "{{ secret('MODAL_TOKEN_SECRET') }}"
Properties
commands
- Type: array
- SubType: string
- Dynamic: ✔️
- Required: ✔️
- Min items:
1
The commands to run
beforeCommands
- Type: array
- SubType: string
- Dynamic: ✔️
- Required: ❌
The commands to execute before the main list of commands
containerImage
- Type: string
- Dynamic: ✔️
- Required: ❌
- Default:
ghcr.io/kestra-io/modal
The task runner container image, only used if the task runner is container-based.
docker
- Type: DockerOptions
- Dynamic: ❌
- Required: ❌
Deprecated, use 'taskRunner' instead
env
- Type: object
- SubType: string
- Dynamic: ✔️
- Required: ❌
- Default:
{}
Additional environment variables for the current process.
inputFiles
- Type:
- object
- string
- Dynamic: ✔️
- Required: ❌
The files to create on the local filesystem. It can be a map or a JSON object.
namespaceFiles
- Type: NamespaceFiles
- Dynamic: ❌
- Required: ❌
Inject namespace files.
Inject namespace files to this task. When enabled, it will, by default, load all namespace files into the working directory. However, you can use the
include
orexclude
properties to limit which namespace files will be injected.
outputFiles
- Type: array
- SubType: string
- Dynamic: ✔️
- Required: ❌
The files from the local filesystem to send to Kestra's internal storage.
Must be a list of glob) expressions relative to the current working directory, some examples:
my-dir/
,my-dir/*/
ormy-dir/my-file.txt
.
taskRunner
- Type: TaskRunner
- Dynamic: ❌
- Required: ❌
- Default:
{ "type": "io.kestra.plugin.scripts.runner.docker.Docker" }
The task runner to use.
Task runners are provided by plugins, each have their own properties.
Outputs
exitCode
- Type: integer
- Required: ✔️
- Default:
0
outputFiles
- Type: object
- SubType: string
- Required: ❌
vars
- Type: object
- Required: ❌
Definitions
io.kestra.core.models.tasks.NamespaceFiles
enabled
- Type: boolean
- Dynamic: ❌
- Required: ❌
- Default:
true
exclude
- Type: array
- SubType: string
- Dynamic: ❌
- Required: ❌
include
- Type: array
- SubType: string
- Dynamic: ❌
- Required: ❌
io.kestra.plugin.scripts.runner.docker.Cpu
cpus
- Type: integer
- Dynamic: ❌
- Required: ❌
io.kestra.core.models.tasks.runners.TaskRunner
type
- Type: string
- Dynamic: ❌
- Required: ✔️
- Validation RegExp:
\p{javaJavaIdentifierStart}\p{javaJavaIdentifierPart}*(\.\p{javaJavaIdentifierStart}\p{javaJavaIdentifierPart}*)*
- Min length:
1
io.kestra.plugin.scripts.runner.docker.Memory
kernelMemory
- Type: string
- Dynamic: ✔️
- Required: ❌
memory
- Type: string
- Dynamic: ✔️
- Required: ❌
memoryReservation
- Type: string
- Dynamic: ✔️
- Required: ❌
memorySwap
- Type: string
- Dynamic: ✔️
- Required: ❌
memorySwappiness
- Type: string
- Dynamic: ✔️
- Required: ❌
oomKillDisable
- Type: boolean
- Dynamic: ❌
- Required: ❌
io.kestra.plugin.scripts.exec.scripts.models.DockerOptions
image
- Type: string
- Dynamic: ✔️
- Required: ✔️
- Min length:
1
config
- Type:
- string
- object
- Dynamic: ✔️
- Required: ❌
- Type:
cpu
- Type: Cpu
- Dynamic: ❌
- Required: ❌
credentials
- Type: Credentials
- Dynamic: ✔️
- Required: ❌
deviceRequests
- Type: array
- SubType: DeviceRequest
- Dynamic: ❌
- Required: ❌
entryPoint
- Type: array
- SubType: string
- Dynamic: ✔️
- Required: ❌
extraHosts
- Type: array
- SubType: string
- Dynamic: ✔️
- Required: ❌
host
- Type: string
- Dynamic: ✔️
- Required: ❌
memory
- Type: Memory
- Dynamic: ❌
- Required: ❌
networkMode
- Type: string
- Dynamic: ✔️
- Required: ❌
pullPolicy
- Type: string
- Dynamic: ❌
- Required: ❌
- Default:
ALWAYS
- Possible Values:
IF_NOT_PRESENT
ALWAYS
NEVER
shmSize
- Type: string
- Dynamic: ✔️
- Required: ❌
user
- Type: string
- Dynamic: ✔️
- Required: ❌
volumes
- Type: array
- SubType: string
- Dynamic: ✔️
- Required: ❌
io.kestra.plugin.scripts.runner.docker.Credentials
auth
- Type: string
- Dynamic: ✔️
- Required: ❌
identityToken
- Type: string
- Dynamic: ✔️
- Required: ❌
password
- Type: string
- Dynamic: ✔️
- Required: ❌
registry
- Type: string
- Dynamic: ✔️
- Required: ❌
registryToken
- Type: string
- Dynamic: ✔️
- Required: ❌
username
- Type: string
- Dynamic: ✔️
- Required: ❌
io.kestra.plugin.scripts.runner.docker.DeviceRequest
capabilities
- Type: array
- SubType: array
- Dynamic: ❌
- Required: ❌
count
- Type: integer
- Dynamic: ❌
- Required: ❌
deviceIds
- Type: array
- SubType: string
- Dynamic: ✔️
- Required: ❌
driver
- Type: string
- Dynamic: ✔️
- Required: ❌
options
- Type: object
- SubType: string
- Dynamic: ❌
- Required: ❌