# Advanced usage
The examples in this section are not fully functional files, and only demonstrate the behavior of the various functionalities.
# Special variables
To simplify the usage of StackForms, you might want to be able to always use the organization, project's name, etc instead of specifying it every time you configure a new project.
This is achieved by a previously established concept: special variables that will be substituted in both the destination/content of your files.
Special variables format if the following:
($ variable_name $)
Here is the list of all the available special vars:
|project||The project canonical|
|project_owner_canonical||The canonical of the project owner|
|project_owner_name||The name of the project owner|
|project_owner_surname||The surname of the project owner|
|project_owner_email||The email of the project owner|
|organization_canonical||The canonical of the organization|
|scs_url||The URL of the catalog repository where the stack is located|
|scs_branch||The branch of the catalog repository where the stack resides|
|scs_cred_type||The type of credential used to access the stack's service catalog|
|scs_cred_path||The path in Vault of the credential used to access the service catalog|
|stack_path||The path of the stack in the service catalog, basically the path to the |
|cr_url||The URL of the config repository configured for this stack|
|cr_branch||The branch in the config repo holding the configuration for the stack|
|cr_cred_type||The type of credential used to access the stack's config repo|
|cr_cred_path||The path in Vault of the credential used to access the config repo|
|inventory_jwt||The JSON Web Token used to access the inventory|
|api_url||The URL of the Cycloid API|
|console_url||The URL of the Cycloid console|
|use_case||The use case name of the stack|
The URL and branch will be the ones that you have set up on the service catalog page. So for example the URL could be:
firstname.lastname@example.org:cycloidio/cycloid-stacks.git and the branch
So, as a value in your
.forms.yml file, you could use:
default: ($ project $)/terraform/($ environment $)/main.tf
# Using common use case
Depending on the configuration for your use-cases, you might run into a configuration of variables that are very repetitive.
This issue is addressed with a special common use-case called
cycloid-common, which will be merged with the other ones.
This happens in various situations, you have a stack that can deploy either
mutualized, or a stack that can deploy on different cloud providers, etc. In such scenarios, you will have to specify your application every time: image to use for your components, cache retention, etc. This can be leveraged by defining them only once in the
cycloid-common instead of doing so in every section.
If a section/group was defined in
cycloid-common, and not in the others, those would be added to them.
However if those were already defined only the missing ones would be added, meaning any groups or variables defined in the other use-cases have priorities over the common one.
The process of merging elements is done prior to returning it to the user, so they will only see the final result.
The following examples will illustrate what the file looks like, prior to the various injection of the
cycloid-common use-case into the other ones. To allow understanding the merging more easily, a 'name' has been added to each variable, which is of the format:
use-case.section.group.key, so that it is easier on the final file, to know where a variable is coming from.
Example of a file defined with the cycloid-common use case:
version: "2" use_cases: - name: cycloid-common sections: # This section exist, so groups will be checked - name: pipeline groups: # Group exist but the variable 'three' doesn't so it will be added - name: backend vars: - key: one name: common.pipeline.backend.one - key: three name: common.pipeline.backend.three # Group exist and variable 'four' too, so nothing change - name: frontend vars: - key: four name: common.pipeline.frontend.four # This section doesn't exist, so everything will be added - name: terraform groups: - name: backend vars: - key: five name: common.terraform.backend.five - name: frontend vars: - key: six name: common.frontend.backend.six - name: first sections: - name: pipeline groups: - name: backend vars: - key: one name: first.pipeline.backend.one - key: two name: first.pipeline.backend.two - name: frontend vars: - key: four name: first.pipeline.frontend.four
The final merged file is the one that will be delivered to the user, please note that it won't contain
cycloid-common use-case anymore, as its elements will have been integrated into other ones.
If you pay attention to the variables name, you'll notice some come from the common use-case, while some remain from the use-case's definition. Sections or groups that weren't defined will also be added to each use-case.
version: "2" use_cases: - name: first sections: - name: pipeline groups: - name: backend vars: - key: one name: first.pipeline.backend.one - key: two name: first.pipeline.backend.two - key: three name: common.pipeline.backend.three - name: frontend vars: - key: four name: first.pipeline.frontend.four - name: terraform groups: - name: backend vars: - key: five name: common.terraform.backend.five - name: frontend vars: - key: six name: common.frontend.backend.six
# Sharing technologies
It is possible to also share variables across technologies; to do so add technologies to the list within the group and they will be automatically written/read from their respective files. This can be quite useful as you might not want to repeat the filling of identical variables for different technologies when they are all the same. In the scenario where those shared variables wouldn't be the same anymore (got manually edited for example), the user would be notified and have to manually solve the conflict of settings.
Currently only 'simple' widgets/types support sharing:
|Widgets||Can be shared?|
|auto_complete, dropdown, number, radios, simple_text, slider_list, slider_range, switch, text_area||✅|
|cy_cred, cy_scs, cy_crs, cy_branch||❌|
Groups can have an attribute called
condition. When configuring a project, variables belonging to the group with a
condition will only be processed if that group's
condition is met, otherwise, variables will simply be ignored.
Conditions are a form of expression that allow to preconfigure certain validations and enable/disable groups accordingly.
You can use complex logical expressions (as opposed to previous versions, where only one expression was accepted). For example, the following condition is considered valid:
$var1 == 'hello world' && $var2 > 10 || ($var3 != true && $var4 == 'value').
To better understand how to use the conditions you can check on the following subsections the format of the variables, the available operators and values to use. For an example of conditions in the stackforms please check the examples section.
# Condition variables
The variables used in the conditions expressions correspond to the stackforms variables and its their corresponding value that will be verified in the condition.
The condition variables should be prefixed with
$ symbol and cannot contain spaces or special characters, e.g
$var_1 are valid variables.
Only the following variables types can be used in the expressions:
Variables of type
raw are not supported yet.
The variables cannot belong to the same group of the
condition, since they're used to enable/disable other groups.
# Condition operators
There's two operators to use in conditions:
Comparatorsthat are used to compare variables to values in a expression, as follows
$variable $comparator $valueAvailable comparators are:
>=greater than or equal
<=less than or equal
Logical operatorsthat are used to establish logical value, as follows
$expressionA $logicalOperator $expressionB. You can group expressions by using parentesis:
($expression) ...Available logical operators:
# Conditions values
The supported values formats to use in the expressions are:
-100to check negative
'2022-10-04_13:37:37Z'. RFC3339, ISO8601, ruby date, or unix date formats are supported.
Note!Date values can only be compared when using string variables
All string/date values are required to be enclosed within single quotes, for example
'value one' or
'2022-10-04_13:37:37Z' are considered valid, while
value one or
2022-10-04_13:37:37Z aren't (no quotes).
# Group scope
Groups can have an attribute called
condition. Condition is a form of expression allowing to preconfigure certain validations.
This way when configuring a project, variables belonging to the group with a
condition will only be processed if that group's
condition is met;
otherwise, variables will simply be ignored.
# Variable scope
The variables you define can have dynamic values and default, based on a set of conditions. Those values will change depending on the user's input. For example if you were to allow the configuration of the environment, you could have different instance size based on the environment name.
The default & values allow 2 kinds of input: static & dynamic. You can use either dynamic default alone, dynamic values alone or both together.
Here is the preview of the previous example with dynamic elements:
# YAML anchors and aliases
To reduce and factorize your .forms.yml definition, YAML Anchors and aliases can be used.
Item can be identified with an anchor, and then refer to that item with an alias later in the
forms.yml. Anchors can be used repeatedly by multiple aliases. Anchors are identified by an
& character, and aliases by an
Lets take an example, my stack has 3 use cases. Both A and B share the same
section FOO but C is different.
Here is a sample of
.forms.yml using anchor to add a
FOO section in both A and B only.
# YAML anchors shared: - &foo-section name: FOO groups: - name: Group1 technologies: [pipeline] vars: - name: Widget1 ... version: "2" use_cases: - name: A sections: - *foo-section - name: B sections: - *foo-section - name: C sections:
Anchors and aliases could be used at any levels from your
.forms (not only sections).
Feel free to check the yaml documentation (opens new window) for more advanced needs.