Merge pull request #21508 from dvdksn/bake-variable-validation

build: add variable validation in bake
This commit is contained in:
David Karlsson
2024-11-28 11:54:17 +01:00
committed by GitHub
2 changed files with 125 additions and 17 deletions

View File

@@ -288,43 +288,63 @@ which is the short commit hash generated by `git rev-parse --short HEAD`.
Overriding non-string variables with environment variables is supported. Values
passed as environment variables are coerced into suitable types first.
The following example defines a `PORT` variable with a default value of `8080`.
The `default` target uses a [ternary operator](expressions.md#ternary-operators)
to set the `PORT` variable to the value of the environment variable `PORT`
if it is greater than `1024`, otherwise it uses the default value.
In this case, the `PORT` variable is coerced to an integer before the ternary
operator is evaluated.
The following example defines a `PORT` variable. The `backend` target uses the
`PORT` variable as-is, and the `frontend` target uses the value of `PORT`
incremented by one.
```hcl
default_port = 8080
variable "PORT" {
default = default_port
default = 3000
}
target "default" {
group "default" {
targets = ["backend", "frontend"]
}
target "backend" {
args = {
PORT = PORT > 1024 ? PORT : default_port
PORT = PORT
}
}
target "frontend" {
args = {
PORT = add(PORT, 1)
}
}
```
Attempting to set the `PORT` variable with a value less than `1024` will result
in the default value being used.
Overriding `PORT` using an environment variable will first coerce the value
into the expected type, an integer, before the expression in the `frontend`
target runs.
```console
$ PORT=80 docker buildx bake --print
$ PORT=7070 docker buildx bake --print
```
```json
{
"target": {
"group": {
"default": {
"targets": [
"backend",
"frontend"
]
}
},
"target": {
"backend": {
"context": ".",
"dockerfile": "Dockerfile",
"args": {
"PORT": "8080"
"PORT": "7070"
}
},
"frontend": {
"context": ".",
"dockerfile": "Dockerfile",
"args": {
"PORT": "7071"
}
}
}

View File

@@ -78,6 +78,94 @@ $ docker buildx bake --print
}
```
## Validating variables
To verify that the value of a variable conforms to an expected type, value
range, or other condition, you can define custom validation rules using the
`validation` block.
In the following example, validation is used to enforce a numeric constraint on
a variable value; the `PORT` variable must be 1024 or higher.
```hcl
# Define a variable `PORT` with a default value and a validation rule
variable "PORT" {
default = 3000 # Default value assigned to `PORT`
# Validation block to ensure `PORT` is a valid number within the acceptable range
validation {
condition = PORT >= 1024 # Ensure `PORT` is at least 1024
error_message = "The variable 'PORT' must be 1024 or higher." # Error message for invalid values
}
}
```
If the `condition` expression evaluates to `false`, the variable value is
considered invalid, whereby the build invocation fails and `error_message` is
emitted. For example, if `PORT=443`, the condition evaluates to `false`, and
the error is raised.
Values are coerced into the expected type before the validation is set. This
ensures that any overrides set with environment variables work as expected.
### Validate multiple conditions
To evaluate more than one condition, define multiple `validation` blocks for
the variable. All conditions must be `true`.
Heres an example:
```hcl
# Define a variable `VAR` with multiple validation rules
variable "VAR" {
# First validation block: Ensure the variable is not empty
validation {
condition = VAR != ""
error_message = "The variable 'VAR' must not be empty."
}
# Second validation block: Ensure the value contains only alphanumeric characters
validation {
# VAR and the regex match must be identical:
condition = VAR == regex("[a-zA-Z0-9]+", VAR)
error_message = "The variable 'VAR' can only contain letters and numbers."
}
}
```
This example enforces:
- The variable must not be empty.
- The variable must match a specific character set.
For invalid inputs like `VAR="hello@world"`, the validation would fail.
### Validating variable dependencies
You can reference other Bake variables in your condition expression, enabling
validations that enforce dependencies between variables. This ensures that
dependent variables are set correctly before proceeding.
Heres an example:
```hcl
# Define a variable `FOO`
variable "FOO" {}
# Define a variable `BAR` with a validation rule that references `FOO`
variable "BAR" {
# Validation block to ensure `FOO` is set if `BAR` is used
validation {
condition = FOO != "" # Check if `FOO` is not an empty string
error_message = "The variable 'BAR' requires 'FOO' to be set."
}
}
```
This configuration ensures that the `BAR` variable can only be used if `FOO`
has been assigned a non-empty value. Attempting to build without setting `FOO`
will trigger the validation error.
## Escape variable interpolation
If you want to bypass variable interpolation when parsing the Bake definition,