Skip to main content

Declarative Hooks

In this section, you will find how to define Declarative Hooks.

About Declarative Hooks

Declarative Hooks define actions to be executed at specific times when applying a Plugin.

Is it possible to work with Declarative Hooks in Infrastructure Plugins?

Yes, it is possible to use Declarative Hooks in Infrastructure Plugins, but they are only executed when the Plugin is applied, not during deployment. When you create the Infrastructure and deploy it through the StackSpot interface, the system performs the command stk apply plugin and then the stk apply plugin deploy in a hidden manner.

When are Declarative Hooks executed in StackSpot?

Declarative Hooks are executed at the time of application of the Plugin in the Application or Infrastructure. When you create the Application, the deployment is not done yet, and the Declarative Hooks work normally. However, when you run the command stk deploy app, the Plugin is already applied and is only used to generate the Terraform files, and at that time, the Declarative Hooks are not executed. They only execute during the creation of the Application or Infrastructure.

The Plugin application has two distinct phases:

Phase 1. Asking the user for input parameters.
Phase 2. Interpolate the Jinja templates using the values entered by the user to generate files.

You can perform the actions defined in the Declarative Hooks:

  • Before input parameters (before-input).
  • Before interpolating the Jinja templates to generate the files (before-render).
  • After generating the files (after-render).

Next, see the Templates and Plugins Rendering Cycle:

Image describes the sequence in which JINJA templates are rendered in Plugins. The steps in the image are numbered from 1 to 8.
Step 1. The configuration file (**`plugin.yaml`**) is loaded;
Step 2. Hooks with **`before-input`** trigger are executed;
Step 3. The inputs defined in the configuration are asked to the user;
Step 4. The **`computed-inputs`** are calculated;
Step 5. Hooks with **`before-render`** trigger are executed;
Step 6. Jinja templates contained in the Plugin's **`templates`** folder are rendered;
Step 7. Hooks with **`after-render`** trigger are executed.
Step 8. Merge files if they exist in the destination.Image describes the sequence in which JINJA templates are rendered in Plugins. The steps in the image are numbered from 1 to 8.
Step 1. The configuration file (**`plugin.yaml`**) is loaded;
Step 2. Hooks with **`before-input`** trigger are executed;
Step 3. The inputs defined in the configuration are asked to the user;
Step 4. The **`computed-inputs`** are calculated;
Step 5. Hooks with **`before-render`** trigger are executed;
Step 6. Jinja templates contained in the Plugin's **`templates`** folder are rendered;
Step 7. Hooks with **`after-render`** trigger are executed.
Step 8. Merge files if they exist in the destination.
warning

The input parameters entered by the user in step 3 are used as variables, they can be used in Jinja expressions both in the templates used for file generation and at some points in the Plugins configuration.

Setting a Declarative Hook

Definitions of Declarative Plugin Hooks can be made in the configuration file plugin.yaml, as per the example below:

schema-version: v3
kind: plugin
metadata:
name: Declarative Hooks Plugin example
display-name: Declarative Hooks Plugin example
description: My Plugin with Declarative Hooks
version: 3.0.0
spec:
type: app
compatibility:
- python
docs:
pt-br: docs/pt-br/docs.md
en-us: docs/en-us/docs.md
technologies: # Ref: https://docs.stackspot.com/create-use/create-content/yaml-files/plugin-yaml/#technologies-1
- React
- Web
- JavaScript
hooks:
- type: run
trigger: before-input
working-dir: "{{project_name}}"
commands:
- echo plugin-python before-input!
- type: run-script
trigger: before-render
script: script.py
- type: edit
trigger: after-render
path: src/some-file.txt
changes:
- insert:
line: 0
value: "# Text inserted in first line\n\n"
when:
not-exists: "# Text inserted in first line"
- search:
string: "# Text inserted in first line"
insert-before:
snippet: snippets/insert-before-first-line.txt
when:
not-exists: "# Text inserted before first line"
- search:
pattern: (Text )inserted in( first line)
replace-by:
value: \1moved from\2
when:
not-exists: print(f"Hello {name}!")
- type: render-templates
trigger: after-render
path: templates-java
condition:
variable: language
operator: "=="
value: java
info

It is possible to define several hooks in the same Plugin.

Triggers

Triggers of Declarative Hooks are defined by the trigger attribute and indicate at what point the Declarative Hook will execute, and can take on one of the following values:

  • before-input: Before asking the user for parameters.
  • before-render: Before generating the files.
  • after-render: After generating the files.

Conditions

The execution of a Declarative Hook can be conditional and is controlled by the optional condition attribute. You must define a condition with:

1. A variable (variable);

2. An operator (operator);

3. Then, the reference value (value).

The variables accessible are those defined by the inputs computed-inputs of the Plugin. In the example snippet shown below, it is checked whether the value of the input language is equal to the string java. If so, the files defined by the templates that are in the templates-java folder are generated.

hooks:
- type: render-templates
trigger: after-render
path: templates-java
condition:
variable: language
operator: "=="
value: java

The operators available for conditions are:

  • "==": Validates if the values are equal.
  • "!=: Validates if the values are different.
  • ">": Validates if variable is greater than the value.
  • "<": Validates if variable is less than value.
  • ">=": Validates if variable is greater than or equal to the value.
  • "<=": Validates if variable is less than or equal to the value.
  • containsAny: Validates if the list-type variable contains any values in value. If value is not a list, it treats value as a list with a single element. If value is an empty list, it returns false.
  • containsAll: Validates if the list-type variable contains all the values in value. If value is not a list, it treats value as a list with a single element. If value is an empty list, it returns true.
  • containsOnly: Validates if the list-type variable is a permutation of the items in value. If value is not a list, it treats value as a list with a single element.
warning

You must use double quotes for the following operators: "==", "!=", ">", ">=", "<", "<=".

Check the types of Declarative Hooks below:

Types of HooksWhat they do
runExecute some commands.
run-scriptExecute Python scripts, inside a plugin.yaml file.
editDefine changes made to existing files.
edit-xmlDefine changes made to existing XML files.
edit-jsonDefine changes made to existing JSON files.
edit-yamlDefine changes made to existing YAML files.
render-templatesPerforms conditional file generation.
code-transformationAllows you to insert, remove and modify any source code.