When models are declared, it's not always practical, desirable or even possible to declare a property as plain text.
Take for example the declaration of a pipeline where the catalog name is the environment in which the pipeline will be deployed.

```yaml
name: my-job-dev
tasks:
  - task_key: pipeline
    pipeline_task:
      pipeline_id: 7dee2833-8287-4d50-8985-4a418e14f8c3

...
```
You probably want to re-use the same configuration file for all your environments, but with a different value for the task key and the pipeline id. 
Laktory makes it possible by introducing the concept of models variables.

## User-defined variables
### Declaration
User-defined variables or `vars` are declared in a model as `${vars.variable_name}`.

We can re-write the job declaration by replacing the explicit environment expression `dev` by a variable named `env` and expressed as `${vars.env}`

```yaml
name: my-job-${vars.env}
tasks:
  - task_key: pipeline
    pipeline_task:
      pipeline_id: 7dee2833-8287-4d50-8985-4a418e14f8c3

...
```

### Value Definition
There are a few options when it comes to defining the value of these variables.

#### Environment variable
Laktory will search for an environment variable named `VARIABLE_NAME` or `ENV` in this case.

#### Model variables
Once a model is instantiated, it is possible to assign variables to this model.
```py title="main.py"
from laktory import models

with open("my-job.yaml", "r") as fp:
    job = models.Job.model_validate_yaml(fp)

job.variables = {"env": "dev"}
```

#### Stack variables
If the model is declared as part of a stack model, the variables can also be defined at the stack level:

```py title="main.py"
from laktory import models

with open("my-job.yaml", "r") as fp:
    job = models.Job.model_validate_yaml(fp)

stack = models.Stack(
    name="my-stack", resources={"jobs": {"my-job": job}}, variables={"env": "dev"}
)
```

## Resources variables
This is great, but what if the variable value needs to be the output of another deployed resource? Laktory got you 
covered with resources variables.  

### Declaration
In this case, the notation is `${resources.resource_name.resource_output}`. Our previous job example may be expressed as

```yaml
name: my-job-${vars.env}
tasks:
  - task_key: pipeline
    pipeline_task:
      pipeline_id: {resources.my-pipeline.id}
...
```
In this case, the static pipeline id is replaced with a dynamic reference to the to-be-deployed pipeline named `my-pipeline`.

### Value Definition
As opposed to user-defined variables, values for resources variables are populated automatically by Laktory. The 
available outputs are the outputs generated by the selected IaC backend (pulumi or terraform). Obviously, for the 
resources outputs for resource `x` to be available, resource `x` needs to be deployed as part of the current stack.

## Variable injection
??? "API Documentation"
    [`laktory.models.BaseModel.inject_vars`][laktory.models.BaseModel]<br>

Variable values injection typically during deployment, just after serialization (`model_dump`). It can also be triggered
manually by invoking `job.inject_vars()` method.