Commit Graph

8 Commits

Author SHA1 Message Date
Pieter Noordhuis f5f57b6bf9
Populate struct field with `config.Value` instance if possible (#1010)
## Changes

If a struct has a field of type `config.Value`, then we set it to the
source value while converting a `config.Value` instance to a struct as
part of a call to `convert.ToTyped`.

This is convenient when dealing with deeply nested structs where
functions on inner structs need access to the metadata provided by their
corresponding `config.Value` (e.g. where they were defined).

## Tests

Added unit tests pass.
2023-11-27 10:06:29 +00:00
Pieter Noordhuis ef97e249ec
Add function to check if `config.Value` is valid (#1009)
## Changes

Small function broken out from other work in progress.
2023-11-24 13:21:47 +00:00
Pieter Noordhuis 2c908f8fea
Function to convert Go struct back to `config.Value` (#935)
## Changes

This PR is the counterpart to #904. With this change, we are able to
convert a `config.Value` into a Go struct, make modifications to the Go
struct, and reflect those changes in a new `config.Value`.

This functionality allows us to incrementally introduce this
configuration representation to existing bundle mutators. Bundle
mutators expect a `*bundle.Bundle` argument and mutate its configuration
directly. These mutations are not reflected in the corresponding
`config.Value` (once introduced), which means we cannot use the
`config.Value` as source of truth until we update _all_ mutators. To
address this, we can run `convert.ToTyped` and `convert.FromTyped` at
the mutator boundary (from `bundle.Apply`) and capture changes made to
the Go struct. Then we can incrementally make mutators aware of the
`config.Value` configuration and have them mutate that structure
directly.

## Tests

New unit tests pass.

Manual spot checks against the bundle configuration type.
2023-11-15 09:19:51 +00:00
Pieter Noordhuis 8e1156edbd
Function to merge two instances of `config.Value` (#938)
## Changes

Semantics for merging two instances of `config.Value`:
* Merging x with nil or nil with x always yields x
* Merging maps a and b means entries from map b take precedence
* Merging sequences a and b means concatenating them

These are the same semantics that we use today when calling into mergo
in `bundle/config`.

## Tests

Unit tests pass.
2023-11-03 19:15:47 +00:00
Pieter Noordhuis a60c40e71e
Add configuration normalization code (#915)
## Changes

This is similar to #904 but instead of converting the dynamic
configuration to Go structs, this normalizes a `config.Value` according
to the type of a Go struct and returns the new, normalized
`config.Value`.

This will be used to ensure that two `config.Value` trees are
type-compatible before we can merge them (i.e. instances from different
files).

Warnings and errors during normalization are accumulated and returned as
a `diag.Diagnostics` structure. We can use this to surface warnings
about unknown fields, or errors about invalid types, in aggregate
instead of one-by-one. This approach is inspired by the pattern to
accumulate diagnostics in Terraform provider code.

## Tests

New unit tests.
2023-10-25 11:56:42 +00:00
Pieter Noordhuis 3411b8aa37
Loading an empty file yields a nil (#906)
## Changes

Empty YAML files are valid and should return a nil-equivalent when
loaded.

## Tests

Tests pass.
2023-10-24 11:24:43 +00:00
Pieter Noordhuis 5018059444
Library to convert config.Value to Go struct (#904)
## Changes

Now that we have a new YAML loader (see #828), we need code to turn this
into our Go structs.

## Tests

New unit tests pass.

Confirmed that we can replace our existing loader/converter with this
one and that existing unit tests for bundle loading still pass.
2023-10-24 11:12:36 +00:00
Pieter Noordhuis ab05f8e6e7
New YAML loader to support configuration location (#828)
## Changes

In order to support variable interpolation on fields that aren't a
string in the resource types, we need a separate representation of the
bundle configuration tree with the type equivalent of Go's `any`. But
instead of using `any` directly, we can do better and use a custom type
equivalent to `any` that captures additional metadata. In this PR, the
additional metadata is limited to the origin of the configuration value
(file, line number, and column).

The YAML in this commit uses the upstream YAML parser's `yaml.Node` type
to get access to location information. It reimplements the loader that
takes the `yaml.Node` structure and turns it into the configuration tree
we need.

Next steps after this PR:
* Implement configuration tree type checking (against a Go type)
* Implement configuration tree merging (to replace the current merge
functionality)
* Implement conversion to and from the bundle configuration struct
* Perform variable interpolation against this configuration tree (to
support variable interpolation for ints)
* (later) Implement a `jsonloader` that produces the same tree and
includes location information

## Tests

The tests in `yamlloader` perform an equality check on the untyped
output of loading a YAML file between the upstream YAML loader and this
loader. The YAML examples were generated by prompting ChatGPT for
examples that showcase anchors, primitive values, edge cases, etc.
2023-10-20 12:56:59 +00:00