A value-less, untyped variable has always been converted to an empty
string. The intention was that value-less, typed variables convert to a
typed null, which was even specified in a code comment, but was never
actually implemented.
This resulted in a null value with a nil type. A value with a nil type
cannot be coerced ("unified") with any other standard types. When this
mismatch occurs, HCL attempts to return a diagnostic error, which in
turn panics as the nil type is literally a nil pointer.
Signed-off-by: Roberto Villarreal <rrjjvv@yahoo.com>
If a type was explicitly provided, it will be displayed in the variable
listing. Inferred type names are not displayed, as they likely would
not match the user's intent.
Previously only `string` and `bool` default values were displayed in the
listing. All default values, regardless of type, are now displayed.
Signed-off-by: Roberto Villarreal <rrjjvv@yahoo.com>
A variable with a type but no default value or override resulted in an
empty string. This matches the legacy behavior of untyped variables,
but does not make sense when using types (an empty string is itself a
type violation for everything except `string`). All variables defined
with a type but with no value are now a typed `null`.
A variable explicitly typed `any` was previously treated as if the
typing was omitted; with no defined value or override, that resulted in
an empty string. The `any` type is now distinguished from an omitted
type; these variables, with no default or override, are also `null`.
In other respects, the behavior of `any` is unchanged and largely
behaves as if the type was omitted. It's not clear whether it should be
supported, let alone how it should behave, so these tests were removed.
It's being treated as undefined behavior.
Signed-off-by: Roberto Villarreal <rrjjvv@yahoo.com>
The primary intent is to make JSON parsing explicitly opt-in rather than
using heuristics to determine intent.
With some exceptions, given bake variable `VAR`, an environment variable
`VAR_JSON` must be used to provide JSON content. The value in
`VAR_JSON` will be ignored when:
* a bake built-in of that same name exists
* a user-provided variable of that same name exists
* typing (attribute `type`) is not present
The first is unlikely to happen as built-ins will likely start with
`BUILDX_BAKE_`, an unlikely prefix for end users. The second may be a
real scenario, where users have `VAR_JSON` dedicated to accepting a
string with JSON content and decoding via an HCL function. This will
continue to work as-is, but can be simplified by removing the variable
from their bake file (`VAR_JSON`) and applying typing (to `VAR`).
Signed-off-by: Roberto Villarreal <rrjjvv@yahoo.com>
Though CSV is favored for 'simple' lists, a JSON value will be used if
it parses without error. This assumes that it is extremely unlikely
that something that parses as JSON would be intended to be parsed as
CSV, e.g. `["a"` and `"b"]`, as opposed to `a` and `b`. If
parsing/conversion fails, it is treated as if it was a CSV.
Since the CSV approach required processing of each element, code was
refactored to reuse the same logic used for individual non-typed
variables.
Signed-off-by: Roberto Villarreal <rrjjvv@yahoo.com>
This allows variables to have explicit types, similar to Terraform
variables. It uses HCL's `typeexpr` extension for the specification.
For conversion of overrides to complex types (when explicit typing is
provided), HCL's native JSON-based unmarshalling is used.
Typing is independent of any default, but if a default is provided, it
will be validated. Similarly, if an override is provided, it will be
converted to that type.
When typing is not provided, previous behavior is used, namely
passing through as a string when no default, converting to primitives if
the default was primitive, and failing otherwise (complex types).
For complex types, the happy path is lists of primitives, but in theory
any complex/composite type can be used provided they are expressed
correctly in JSON. In the interest of simplicity and correctness, there
are no shortcuts for lists. There *is* a shortcut for strings as users
don't provide them for untyped variables and would be unintuitive.
Signed-off-by: Roberto Villarreal <rrjjvv@yahoo.com>
There was inconsistency between variables used for function
definitions in HCL and JSON format. Updated JSON to match HCL,
fixed documentation and removed the unused code from userfunc
pkg (based on HCL upstream) to avoid confusion.
Theoretically we could add some temporary backwards compatibility
for the JSON format but I think it is unlikely that someone uses
JSON format for this and also defined variadic parameters.
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This changes how the composable attributes are implemented and provides
various fixes to the first iteration.
Cache-from and cache-to now no longer print sensitive values that are
automatically added. These automatically added attributes are added when
the protobuf is created rather than at the time of parsing so they will
no longer be printed. If they are part of the original configuration
file, they will still be printed.
Empty strings will now be skipped. This was the original behavior and
composable attributes removed this functionality accidentally. This
functionality is now restored.
This also expands the available syntax that works with each of the
composable attributes. It is now possible to interleave the csv syntax
with the object syntax without any problems. The canonical form is still
the object syntax and variables are resolved according to that syntax.
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This allows using either the csv syntax or object syntax to specify
certain attributes.
This applies to the following fields:
- output
- cache-from
- cache-to
- secret
- ssh
There are still some remaining fields to translate. Specifically
ulimits, annotations, and attest.
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This adds the following constraints to the new features:
- Explicit renaming with the `name` property is *only* permitted when
used with the `matrix` property.
- Group does not support either `name` or `matrix` (we may choose to
relax this constraint over time).
- All generated names must be unique.
Signed-off-by: Justin Chadwell <me@jedevc.com>
Previously, the name property could not be set in the body of a bake
target and could only be set for a label. This patch allows the body to
override the values of label fields, though the default is still the
label.
Signed-off-by: Justin Chadwell <me@jedevc.com>
This patch allows high level clients to define an EvalContext method
which can derive a new context given a block and the base parent
context.
This allows users of the package to intercept evaluation before it
begins, and define additional variables and functions that are bound to
a single block.
Signed-off-by: Justin Chadwell <me@jedevc.com>
With changes to the lazy evaluation, the evaluation order is no longer
fixed - this means that we can follow long and confusing paths to get to
an error.
Because of the co-recursive nature of the lazy evaluation, we need to
take special care that the original HCL diagnostics are not discarded
and are preserved so that the original source of the error can be
detected. Preserving the full trace is not necessary, and probably not
useful to the user - all of the file that is not lazily loaded will be
eagerly loaded after all struct blocks are loaded - so the error would
be found regardless.
Signed-off-by: Justin Chadwell <me@jedevc.com>
With changes made to allow lazy evaluation, we were early exiting if an
undefined name was detected, either for a variable or a function.
This had two key implications:
1. The error messages changed, and became significantly less
informative.
For example, we went from:
> Unknown variable; There is no variable named "FO". Did you mean "FOO"?, and 1 other diagnostic(s)
To
> Invalid expression; undefined variable "FO"
2. Any issues in our function detection from funcCalls which cause JSON
functions to be erroneously detected cause invalid functions to be
resolved, which causes new name resolution errors.
To avoid the above problems, we can defer the error from an undefined
name until HCL evaluation - which produces the more informative errors,
and does not suffer from incorrectly detecting JSON functions.
Signed-off-by: Justin Chadwell <me@jedevc.com>
This patch adds support for block-based interpolation, so that
properties of blocks can be referenced in the current block and across
other blocks.
Previously, order-of-evaluation did not matter for blocks, and could be
evaluated in any order. However, now that blocks can refer to each
other, we split out this dynamic evaluation order into a separate
resolveBlock function.
Additionally, we need to support partial block evaluations - if block A
refers to property X of block B, when we should only evaluate property
X, and not the entire block. This ensures that we can safely evaluate
blocks that refer to other properties within themselves, and allows
sequences that would otherwise be co-recursive. We take special care in
this logic to ensure that each property is evaluated once *and only*
once - this could otherwise present inconsistencies with stateful
functions, and could risk inconsistent results.
Signed-off-by: Justin Chadwell <me@jedevc.com>