KOP Environment Manager - CUE Expressions - Rafay Product Documentation

CUE Expressions

CUE expressions are a powerful feature used to manage and deploy applications, resources, and environments by dynamically referencing values from resources or environment templates. With CUE, users can avoid hardcoding configurations and instead leverage expressions to automate processes, making it easier to integrate and manage complex workflows. By using CUE expressions, users can reference outputs from various resources (like VPC, RDS, and Kubernetes clusters) to dynamically populate configuration files, such as workload Helm values or Terraform outputs. This flexibility allows for the creation of reusable and adaptable templates that can scale across multiple environments without manual intervention.

For example, CUE expressions can be used to pull resource-specific outputs, like the RDS hostname or IP addresses, directly into workload configurations. They can also handle complex scenarios like referencing static and dynamic resources or incorporating artifact variables into deployment processes.

Additionally, CUE expressions can be employed for trigger-based actions, environment resource management, and integrating external systems, enhancing the overall orchestration of cloud infrastructure and application deployments. Through CUE expressions, users gain enhanced control over their infrastructure, enabling more efficient and consistent resource provisioning, management, and scaling across various platforms.

Application deployments

Let's take the example of an environment named env1 based on an environment template named envtemp. This environment includes resources such as vpc, rds, and a Rafay managed K8s cluster, where the K8s cluster and RDS depend on VPC.

A developer/data scientist wishing to deploy an application to the K8s cluster can avoid hardcoding the workload/application manifest with the environment details and instead use the following expression.

$(#environment["resource_name"]["varname"])$

Let's assume that the application needs to include details of the RDS instance. Below is an example snippet of the Terraform output for the RDS resource template.

output "rds_hostname" {
  description = "RDS instance hostname"
  value       = aws_db_instance.db.address
  sensitive   = true
}

For this specific output example, the workload expression would be:

$(#environment["rds"]["rds_hostname"])$

Below is an example of a workload Helm value file with expressions, where RDS Terraform output values are passed as input values.

env:
  celeryBrokerUrl: 'redis://$(#environment["ec-resoource-tmpl"].configuration_endpoint_address):6379/0'
  celeryResultBackend: 'redis://$(#environment["ec-resoource-tmpl"].configuration_endpoint_address):6379/0'
  debug: "True"
  djangoDb: postgresql
  postgresHost: '$(#environment["rds-resource-tmpl"].rds_hostname)'
  postgresName: postgres
  postgresPassword: '$(#environment["rds-resource-tmpl"].rds_password)'
  postgresPort: '$(#environment["rds-resource-tmpl"].rds_port)'
  postgresUser: '$(#environment["rds-resource-tmpl"].rds_username)'

In case the variable type is a list (array), utilize indexing to reference various values. For example, to bring up a load balancer that has multiple IPs, use the following expression:

$(#environment["loadbalancer"]["public_ips"][0])$

If you are leveraging Rafay Workloads, ensure to select the correct Environment Configuration based on the requirement.

Important

For example, for a tag named aws-account, the correct CUE syntax is:

$(project.tags["aws-account"])$ or $(project.tags."aws-account")$

Dynamic and Static Resource

There could be scenarios where the output of a dynamic/static resource needs to be passed to another resource as part of the environment creation process. You can use the below expression for such scenarios:

$(resource."resource_name".output.otest1.value)$

Let's take an example where a resource template includes dynamic resources vpc and rds, and there is a requirement to pass the vpc ID to rds so that rds is installed in that particular vpc ID. To achieve this, pass the output of the vpc to the rds using the following expression:

$(resource."vpc".output.vpc_id.value)$

The above expression references the output value 'vpc_id' from the 'vpc' resource.

Similarly to dynamic resources, static resource outputs can also be passed to another resource.

Static Environment Resource

To pass the output of a static environment resource to another resource, use the below expression:

$(resource."static-env-0".resource."resource-2".output.test3.value)$

Lets' take the example where an environment named "env1" has already been created. If the user intends to create an additional environment with the "rds" resource on top of "env1" without modifying the existing "env1", follow the expression outlined below:

$(resource."env1".resource."rds".output.rds_hostname.value)$

The above expression employs the 'env1' environment name, the static resource name 'rds', and references the output value labeled as 'rds_hostname'. The values can be of any type, such as array, map, and string.

Users can utilize this expression to include 'env1' as a static resource in the new environment alongside the RDS.

Important:

When the following expressions are used as a variable type, do not enable the "required" and "allowed" fields:

In these expressions:

If these expressions are used with the "required" or "allowed" fields enabled, the environment publish operation will fail due to a known limitation. The system does not support resolving resource-based expressions at the time of publishing, preventing successful deployment.

Dedicated Resource(s)

When creating an environment template, user has the ability to add dynamic or static resources (pre-existing resources).

When the "dynamic" option is selected for resources, users are allowed to enable the dedicated option. When the dedicated option is enabled, dedicated resources are only brought up when a workload is published to that environment.

To use the workload attributes as part of the dedicated resource(s), use the following expression:

$(workload.name)$

(or)

$(workload.id)$

If ElastiCache is a dedicated resource that needs to be brought up for a workload, the user can use the workload name $(workload.name)$ as input to the name variable of the ElastiCache. So, whenever a workload is published, the dedicated ElastiCache comes up with the name of the workload.

Note: When the workload is unpublished/destroyed, the dedicated resources within that workload will also be destroyed.

Environment Resource(s)

Assume a scenario where a user attempts to set up three to four environments using an environment template, and all the resources are being launched in the same AWS region. To prevent naming conflicts, utilize the following expression to create them with dynamic names and IDs.

Resource Artifact Variables

There are instances where the user intends to download Terraform working directory at different stages such as Init, Plan (pre-hook & post-hook), Apply, and Output. Users can download the required artifacts via container hooks using the expression below (from the working directory as a token and url). This enables users to access the artifacts and perform necessary actions such as scanning of terraform code, calculate the cost of the infrastructure etc.

You can use the expressions below to download artifacts:

Artifact Activity

$(resource."rtdependson-0".artifact.workdir.token)$
$(resource."rtdependson-0".artifact.workdir.url)$

Plan Activity

$(resource."rtdependson-0".plan.workdir.token)$
$(resource."rtdependson-0".plan.workdir.url)$

Trigger Expressions

Trigger expressions are used to enable dynamic event-driven responses within systems by allowing users to leverage the output of trigger events as input for subsequent actions or workflows.

Use the below trigger expressions to dynamically configure actions and workflows based on event triggers.

Drivers Inputs and Outputs

Inputs

Dynamic inputs (expressions) can be configured across all fields within the driver. Users can provide values for these inputs during environment deployment or define them within the variables of the config context attached to the driver or defined directly inline. These expressions are evaluated within the execution context during workflow execution.

The standard format for these expressions is $(current.input.<variable-name>)$, where is the name of the variable whose value the user wants to use.

Outputs

Drivers' output can be utilized as inputs for subsequent drivers within the workflow. The HTTP driver's response payload is saved as output, while the Container driver uploads the output.json file to the designated endpoint. This output can be referenced using specific expressions for different hooks.

$(resource.test_resource.hook.onInit.create_ticket.output.ticket_id)$

This expression is used to retrieve the value of the ticket_id generated by the create_ticket hook during the onInit stage of the test_resource resource template.

Resource Template Lifecycle Hooks

$(resource.resource_name.hook.onInit.hook_name.output)$

Terraform Lifecycle Hooks

Deploy Hooks

$(resource.template_name.hook.deploy.init.before.hook_name.output)$

Destroy Hooks

$(resource.template_name.hook.destroy.init.before.hook_name.output)$

Environment Template Lifecycle Hooks

$(environment.hook.onInit.hook_name.output)$

Custom Provider

The expression $(resource.resource_name.task.task_name.output)$ is used to access the output of a specific task within a resource template. Here's how it breaks down:

This expression allows subsequent tasks or components to use the output from a previous task, enabling data flow and dependency management within the workflow.