This document explains how variables, variable mapping, and dependencies work within SaaS Runtime.
SaaS Runtime lets you to deploy and manage complex SaaS applications by organizing them into modular units. These units, defined by Terraform configurations within blueprints, can be interconnected through dependencies, allowing for sophisticated orchestration and automated provisioning. A key aspect of managing these units and their interactions is through variables and variable mapping.
You can build complex, modular, and scalable deployments with automated provisioning, inter-unit communication, and flexible configuration options. Carefully consider your variable hierarchy, dependency relationships, and variable mappings to optimize your SaaS architecture and management workflows within SaaS Runtime.
Units and variables
At the heart of SaaS Runtime are units. Units utilize
variables to customize their deployment and behavior. These variables are
essentially Terraform variables that you can define in your blueprint's
variables.tf
file. They allow you to parameterize your Terraform
configurations, making them reusable and adaptable across different environments
and deployments.
Mandatory variables for unit provisioning
While you can define custom variables for your units, SaaS Runtime also relies on a set of mandatory variables. These variables are automatically recognized and handled by SaaS Runtime, even if they are not explicitly defined in your Terraform configuration.
The mandatory variables are:
project_id
andproject_number
(or,tenant_project_id
andtenant_project_id
): This variable specifies the Google Cloud project ID where your unit's resources will be deployed. You can use eitherproject_id
andproject_number
, ortenant_id
andtenant_project_id
. This field is necessary for resource creation and management within the correct Google Cloud project.You can find your project ID in the the Google Cloud console on the Dashboard page. Look for the Project ID field in the Project info card within the Cloud overview section.
project_number
ortenant_project_number
: Similar toproject_id
, this variable represents the Google Cloud project number. You can useproject_number
ortenant_project_number
interchangeably.You can find your project number alongside your project ID in the Project info card within the Cloud overview section of the the Google Cloud console Dashboard page.
actuation_sa
: This variable represents the email address of the actuation service account. This service account is a user-managed service account that SaaS Runtime uses (via Infrastructure Manager) to execute your Terraform configurations when provisioning, updating, or deprovisioning units.We recommend that you use a dedicated actuation service account per tenant (or unit) to implement the principle of least privilege. This limits the potential impact of security breaches and provides better isolation between your deployments.
For more information about configuring and granting permissions to actuation service accounts, see Product overview.
Unit variables hierarchy
Unit variables can be defined and sourced from multiple locations. When you use SaaS Runtime, it's important to understand the hierarchy of variable values used during unit operations.
The order is as follows (from lowest to highest precedence):
SaaS Runtime resolves variable values in this order:
Existing input variables on the unit: If a variable is already defined on the unit resource itself (from a previous operation or configuration, for example), this value takes the lowest precedence. If a variable value is set directly on the unit, it will be overridden if a value is found from sources higher in the hierarchy.
Release defaults: Release default values are applied if a variable isn't already set on the unit, but they will override existing unit variables.
Unit operations: When you perform a unit operation such as
provision
orupgrade
, you can explicitly provide input variables as part of the operation request. Variables provided in a unit operation will override release defaults and existing unit variables.Dependencies' input variable mappings: When a unit has dependencies on other units, variable mappings defined in the unit kind can source variable values from the output variables of dependency units. This is the highest precedence source. Variables obtained through dependency mappings will override values from unit operations, release defaults, and existing unit variables.
This hierarchical approach provides flexibility and control over your variable management. You can establish persistent configurations directly on the unit (lowest priority), define baseline defaults using releases, customize for specific operations, and dynamically source the most important and overriding values from unit dependencies (highest priority).
Unit dependencies
SaaS Runtime lets you to define dependencies between units. This is important for building complex SaaS applications where different components rely on each other. Dependencies ensure that related units are provisioned and managed in a coordinated manner.
You define dependencies within a unit kind. When you create a unit of a particular unit kind, SaaS Runtime automatically manages its dependencies.
Dependency definition in unit kind
In the UnitKind
definition, you specify a list of dependencies, each
referencing another UnitKind
and assigning it an alias. This alias is used
for referencing the dependency in variable mappings:
message UnitKind {
// ... other fields ...
// List of other unit kinds that this release will depend on.
repeated Dependency dependencies = 4
[(.google.api.field_behavior) = OPTIONAL];
// ...
}
message Dependency {
// The unit kind of the dependency.
string unit_kind = 1 [
(.google.api.field_behavior) = REQUIRED,
(.google.api.field_behavior) = IMMUTABLE,
(.google.api.resource_reference) = {
type: "saasservicemgmt.googleapis.com/UnitKind"
}
];
// An alias for the dependency. Used for input variable mapping.
string alias = 2 [(.google.api.field_behavior) = REQUIRED];
}
Automatic dependency provisioning
When you request to provision a unit that has dependencies defined in its
UnitKind
, SaaS Runtime automatically checks for the existence of
those dependency units.
If a dependency unit is not found, SaaS Runtime will automatically provision it before provisioning the dependent unit.
SaaS Runtime ensures that dependency units are provisioned before their dependent units, maintaining the correct order of operations.
Variable mapping
Variable mapping is the mechanism to pass data (variable values) between dependent units and their dependencies. This is essential for configuring dependent units based on outputs from their dependencies.
Variable mapping is defined within the dependent unit kind and uses
FromMapping
and ToMapping
:
FromMapping
:FromMapping
is used to retrieve output variables from a dependency unit and map them to input variables of the dependent unit. This is how a dependent unit can obtain information from its dependencies, such as connection endpoints or resource IDs.message VariableMapping { // ... oneof mapping_type { // Output variables which will get their values from dependencies FromMapping from = 2 [(.google.api.field_behavior) = OPTIONAL]; // ... } } message FromMapping { // Alias of the dependency that the outputVariable will pass its value to string dependency = 1 [(.google.api.field_behavior) = REQUIRED]; // Name of the outputVariable on the dependency string output_variable = 2 [(.google.api.field_behavior) = REQUIRED]; }
In the provided codelab example, the
App UnitKind
has aFromMapping
to retrieve thecluster_endpoint
output variable from theCluster UnitKind
dependency. This allows the application to connect to the newly provisioned Kubernetes cluster.ToMapping
:ToMapping
is used to pass input variables from the dependent unit to the input variables of a dependency unit. This lets you configure dependency units based on parameters provided for the dependent unit.message VariableMapping { // ... oneof mapping_type { // ... // Input variables whose values will be passed on to dependencies. ToMapping to = 3 [(.google.api.field_behavior) = OPTIONAL]; } } message ToMapping { // Alias of the dependency that the inputVariable will pass its value to string dependency = 1 [(.google.api.field_behavior) = REQUIRED]; // Name of the inputVariable on the dependency string input_variable = 2 [(.google.api.field_behavior) = REQUIRED]; // Tells EasySaaS if this mapping should be used during lookup or not bool ignore_for_lookup = 3 [(.google.api.field_behavior) = OPTIONAL]; }
In the codelab, the
App UnitKind
usesToMapping
to pass thetenant_project_id
andtenant_project_number
input variables to theCluster UnitKind
dependency. This ensures that the Kubernetes cluster is created within the correct project.ignore_for_lookup
inToMapping
: Theignore_for_lookup
field inToMapping
controls dependency lookup behavior. It is a boolean value:false
(or not specified): When set tofalse
, SaaS Runtime will use the input variables specified in theToMapping
as lookup keys to find an existing dependency unit. If a unit with matching input variables is found, it will be reused as the dependency. If no matching unit is found, a new dependency unit will be provisioned. This is useful for reusing shared resources like clusters.true
: When set totrue
, the input variable in theToMapping
won't be used for dependency lookup. This means that a new dependency unit will always be provisioned, even if units with the same input variables already exist. This is useful when you need dedicated, non-shared dependencies for each dependent unit.
Example: Shared Kubernetes cluster
If you want to reuse a Kubernetes cluster for multiple application units within
the same project, you would use ToMapping
with ignore_for_lookup
set to
false
and map variables like tenant_project_id
and region
to the cluster
unit kind. Units in the same project and region would then reuse the same
cluster.
Example: Dedicated Kubernetes cluster per application
If you need a dedicated Kubernetes cluster for each application unit, you would
use ToMapping
with ignore_for_lookup
set to true
or avoid ToMapping
lookup variables altogether. Each application unit would then trigger the
provisioning of a new, isolated Kubernetes cluster.
Manage secrets
SaaS Runtime variables are not intended for storing sensitive information like passwords, API keys, or certificates. Storing secrets directly in variables poses security risks. Variable values can be logged and potentially exposed through system outputs, increasing the chance of unauthorized access.
For secure secret management in your SaaS Runtime applications, we strongly recommend using Secret Manager.
What's next
- To understand more about SaaS Runtime, see SaaS Runtime overview.
- To get try a tutorial see Deploy a VM with SaaS Runtime.
- For details about defining the SaaS offering with Terraform configurations, see Blueprints in SaaS Runtime.