Skip to content

Starlark Expressions

Starlark expressions provide a powerful, flexible way to handle complex logic within the Rafay environment, utilizing a subset of Python for programmability and computations. This language offers the advantage of enabling users to interact directly with Rafay APIs through expressions, creating dynamic and adaptable workflows. Starlark is designed to be accessible, especially for those familiar with Python-like syntax, though it is also simple enough for users with limited programming experience to quickly understand. Its hermetic execution ensures security by preventing access to external systems, making it a reliable choice for running untrusted code. With Starlark, users can easily implement sophisticated data manipulations and computations, all within a controlled, safe environment.

Though CUE expressions are designed for accessing environment-related data, Starlark expressions offer greater versatility by enabling interaction with a broader range of first-class objects in Rafay, such as workloads, namespaces, and clusters.


List of Starlark Expressions

The following starlark expressions allow dynamic referencing of values across different resources, outputs, triggers, and environment details. These expressions help automate workflows by replacing hardcoded values with dynamic, context-specific information.

Description Starlark Expression
dynamic resource’s output value using object notation #{resource.”rt-1”.output.otest1.value}#
dynamic resource’s output value using index notation #{resource[”rt-1”].output.otest1.value}#
static resource output value #{resource[”static-rt-1”].output.otest1.value}#
static environment output value #{resource[”static-env-0”].resource[”rt-0”].output.otest2.value}#
resource artifacts from artifact activity #{resource[”rt-1”].artifact.workdir.token}#
resource artifacts from output activity #{resource[”rt-1”].output.workdir.token}#
#{resource[”rt-1”].output.workdir.url}#
#{resource[”rt-1”].output.files.stdout.url}#
#{resource[”rt-1”].output.files.stdout.token}#
trigger details #{trigger.id}#
#{trigger.created_at}#
#{trigger.modified_at}#
#{trigger.payload}#
#{trigger.payload.action}#
#{trigger.payload.type}#
#{trigger.payload.userid}#
#{trigger.payload.username}#
#{trigger.payload.is_sso_user}#
#{trigger.status}#
#{trigger.reason}#
environment details #{environment.name}#
#{environment.id}#
#{environment.project.name}#
#{environment.project.id}#
#{environment.labels.key}#
user details #{user.id}#
#{user.name}#
#{user.is_sso}#
#{user.is_sso_user}#
workload details (for workload trigger) #{workload.name}#
#{workload.id}#
repository details (for repository trigger) #{repository.name}#
#{repository.id}#
project details #{project.id}#
#{project.name}#
#{project.tags.tag_name}#
partner details #{partner.id}#
#{partner.name}#
organization details #{organization.id}#
#{organization.name}#
custom resource’s output value #{resource["rt-wf"].task["crucial-task"].output.host}#
environment lifecycle hook outputs #{environment.hook.onInit.hook_name.output}#
#{environment.hook.onSuccess.hook_name.output}#
#{environment.hook.onFailure.hook_name.output}#
#{environment.hook.onCompletion.hook_name.output}#
resource lifecycle hook outputs #{resource.resource_name.hook.onInit.hook_name.output}#
#{resource.resource_name.hook.onSuccess.hook_name.output}#
#{resource.resource_name.hook.onFailure.hook_name.output}#
#{resource.resource_name.hook.onCompletion.hook_name.output}#
resource provider’s deploy lifecycle hook outputs #{resource.template_name.hook.deploy.init.before.hook_name.output}#
#{resource.template_name.hook.deploy.init.after.hook_name.output}#
#{resource.template_name.hook.deploy.plan.before.hook_name.output}#
#{resource.template_name.hook.deploy.plan.after.hook_name.output}#
#{resource.template_name.hook.deploy.apply.before.hook_name.output}#
#{resource.template_name.hook.deploy.apply.after.hook_name.output}#
#{resource.template_name.hook.deploy.output.before.hook_name.output}#
#{resource.template_name.hook.deploy.output.after.hook_name.output}#
resource provider’s destroy lifecycle hook outputs #{resource.template_name.hook.destroy.init.before.hook_name.output}#
#{resource.template_name.hook.destroy.init.after.hook_name.output}#
#{resource.template_name.hook.destroy.plan.before.hook_name.output}#
#{resource.template_name.hook.destroy.plan.after.hook_name.output}#
#{resource.template_name.hook.destroy.destroy.before.hook_name.output}#
#{resource.template_name.hook.destroy.destroy.after.hook_name.output}#
workload expressions to refer resource’s output #{environment["rt-1"]["otest1"]}#
drivers can use input variables as expressions #{current.input["variable-name"]}#
driver output as expressions #{current.output["variable-name"]}#
Get the ith VM object from the list, replace i with number in the expression (starts from 0). #{x.vms[i]}#
Get list of all VMs #{x.vms}#
Get list of all VM names #{[vm.name for vm in vms]}#
Get list of all VMs that are of type t2.micro #{[vm for vm in x.vms if vm.type == "t2.micro"]}#
Get list of all VM ids that are in running status #{[vm.id for vm in x.vms if vm.status == "running"]}#
Get list of all VMs that are in running status in dev environment #{[vm for vm in x.vms if vm.status == "running" and vm.tags.environment == "dev"]}#
Get only the first VM that is of type t2.micro #{[vm for vm in x.vms if vm.type == "t2.micro"][0]}#
Get map of all VMs with ids as keys and VM objects as values #{{vm.id: vm for vm in x.vms}}#
Convert the JSON object to string #{str(x.vms[i])}#
Concatenate strings #{"name is " + x.vms[0].name}#
"name is $(x.vms[0].name)$"
Add 2 numbers #{3 + x.vms[0].cpu_cores}#

Expression Examples

The following examples demonstrate how to use Starlark expressions to dynamically reference and retrieve values from resources, outputs, and triggers during runtime. These expressions can be passed via the GET API to dynamically retrieve data, supporting more complex and adaptable workflows.

  • Cluster Data as JSON Output Using Expressions
#{fetch.system.get_cluster("clustername")}#

Here, fetch initiates the data retrieval, system specifies the Rafay System as the source, and get_cluster fetches all details of the cluster identified by "clustername". Replace clustername with the actual cluster name. This expression retrieves the complete JSON object for a specific cluster in the Rafay System.

  • Accessing Specific Cluster Attributes Using Expressions
#{fetch.system.get_cluster("clustername").spec.config.kind}#

This expression retrieves the value of the kind field located within the spec -> config hierarchy of a specific cluster in the Rafay System. Here, fetch initiates the data retrieval, system specifies the source as the Rafay System, and get_cluster("clustername") fetches the cluster's complete JSON object. The .spec.config.kind path navigates to the kind field within the JSON structure. Replace clustername with the actual cluster name to get the specific value of kind.

  • Dynamic resource’s output value using object notation
#{resource["rt-1"].output.otest1.value}#

This expression retrieves the value from the output of a resource with the identifier rt-1, specifically from the otest1 output object. In Starlark, the resource dictionary holds the outputs from various resources, and users can access specific output values by referencing the resource name (rt-1) and the key path to the output (otest1.value).

  • Static resource output value
#{resource["static-rt-1"].output.otest1.value}#

This expression retrieves the output value otest1.value from a static resource named static-rt-1. Static resources have fixed values defined at the time of configuration, and their output values can be accessed similarly to dynamic resources. If static-rt-1 represents a predefined configuration, such as a network or database configuration, this expression allows referencing specific static values (like a hostname or port) that were configured beforehand.

  • Project tag based expression
#{project.tags.tag_name}#

This expression retrieves the value of a specific tag (tag_name) associated with a project. Tags are metadata labels that can be assigned to projects to provide contextual information, such as cost centers or environment-specific settings. By referencing a project tag in a template, users can dynamically retrieve the tag value to customize the environment creation process for each project. For example, the #{project.tags.aws-account}# expression can retrieve an 'AWS account ID' set as a tag, streamlining the environment configuration without requiring manual input from the developer.


Accessing Rafay Objects Using Expression

Users can access both environment-specific data and data from other Rafay objects, such as clusters, namespaces, and blueprints, expanding the flexibility and scope of expressions. These expressions enable dynamic and efficient data retrieval by automatically fetching up-to-date information without manual effort. Designed for read-only access, expressions ensure secure and controlled environments by only allowing data fetching, without the ability to modify, create, or delete objects. This feature streamlines automation and simplifies integration with Rafay APIs and other services, offering a consistent, efficient way to retrieve necessary data across systems.

Examples

  • Expressions for Fetching Namespace Artifacts

    • #{fetch.system.get_namespace_artifacts("namespace1")}#

    This expression retrieves a list of artifacts associated with a specific namespace. The API being accessed is GET /v3/projects/{project}/namespaces/{name}/artifacts, which provides all artifacts for the specified namespace. The function name is plural, get_namespace_artifacts, as it fetches multiple artifacts. The namespace is identified by its name, namespace1. This expression dynamically fetches the artifacts, ensuring efficient and accurate data retrieval without specifying a limit.

    • #{fetch.system.get_namespace_artifact("namespace1", "artifact1")}#

    This expression is used to fetch details of a specific artifact within a namespace. The API being accessed is GET /v3/projects/{project}/namespaces/{name}/artifacts/{artifact}, which retrieves information about a single artifact. The function name is singular, get_namespace_artifact, targeting a specific resource. The namespace and artifact are identified by their names, namespace1 and artifact1, respectively.

  • Expressions for Fetching Blueprints: Single vs. Multiple Resources

    • #{fetch.system.get_blueprints(limit=10, offset=0)}#

    This expression fetches a list of blueprints within a project, with pagination. The API being accessed is GET /v3/projects/{project}/blueprints?limit=10&offset=0, which retrieves a paginated list of blueprints associated with the specified project. Since the function fetches multiple resources, the function name is plural, get_blueprints. The query parameters limit=10 and offset=0 define the number of blueprints to retrieve (10) and the starting point (0). This expression allows dynamic retrieval of blueprint data, ensuring real-time and efficient access to the first 10 blueprints without manually specifying each one.

    • #{fetch.system.get_blueprint("blueprint1")}#

    This expression retrieves details of a specific blueprint by name. The API being accessed is GET /v3/projects/{project}/blueprints/{name}, which fetches data about a single blueprint in the project. The function name is singular, get_blueprint, because it is querying for a single resource. The blueprint is specified by its name, blueprint1, and the project scope is handled internally by the system. This expression dynamically fetches the details of a particular blueprint, providing real-time access to accurate data.

  • Expressions for Managing Cluster Add-ons

    • #{fetch.system.get_cluster_addon_cloudevents("project1", "cluster1", "addon1")}#

    This expression retrieves a list of CloudEvents related to a specific cluster add-on. The API being accessed is GET /v3/projects/{project}/clusters/{cluster}/addons/{addon_name}/cloudevents, which fetches CloudEvents data associated with the specified cluster add-on. The function name is plural, get_cluster_addon_cloudevents, as it fetches multiple CloudEvents resources. The project, cluster, and add-on are identified by their names, project1, cluster1, and addon1, respectively. This expression dynamically fetches CloudEvents data, ensuring real-time and efficient access to the resources.

  • Expressions for Managing AKS Workload Identity Role Assignments

    • #{fetch.system.get_aks_workload_identity_role_assignment("project1", "cluster1", "identity1", "assignment1")}#

    This expression retrieves details of a specific role assignment for an AKS workload identity. The API being accessed is GET /v3/projects/{project}/clusters/{name}/aksworkloadidentities/{identity_name}/roleassignments/{role_assignment_name}, which fetches data about a single role assignment for the specified AKS workload identity. The function name is singular, get_aks_workload_identity_role_assignment, as it queries for a single resource. The project, cluster, identity, and role assignment are identified by their names, project1, cluster1, identity1, and assignment1, respectively. This expression dynamically fetches role assignment details, providing real-time access to accurate data.

💡 Note:
Expressions in Rafay allow users to call all GET APIs to access Rafay objects, including clusters, namespaces, blueprints, and more, ensuring dynamic and efficient data retrieval. Reosurce Temp