Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lang/eval: Apply attr-as-nested-block fixup in EvalBlock #20837

Merged
merged 5 commits into from
Mar 28, 2019

Conversation

apparentlymart
Copy link
Contributor

For any block content we evaluate dynamically via this API, we'll make a special allowance for users to optionally write members of a list attribute instead as a sequence of nested blocks, thus allowing some
existing provider features that were assuming this capability to continue to support it after v0.12.

This should not be used for any new provider features, and subsequent work we will define a new pattern that allows the same or better expressiveness without relying on distinguishing between two configurations that appear logically equivalent.


This provides a path forward for the few cases in existing providers where a nested block type was declared as Optional+Computed in the schema and the provider logic then distinguished between unset (no blocks at all) vs. explicitly empty by relying on the Terraform v0.11 bug that allowed attribute syntax to be used to define blocks in some cases:

nested_object {
  # ...
}

nested_object = []

For this specific confluence of assumptions only, we can set the schema ConfigMode for nested_object to be SchemaConfigModeAttr, ensure that SkipCoreTypeCheck remains false (because this fixup depends on having accurate type information in Terraform Core), and then continue to show in the resource type documentation the use of nested block syntax even though the schema actually describes the name as being an attribute.


So far this does not include a corresponding fixup for the terraform 0.12upgrade tool, so it will attempt to migrate use of these attributes to attribute syntax. Before v0.12.0 final release we'll decide on a suitable heuristic for the upgrade tool to recognize when this workaround seems to be in use in the provider and make it prefer to use nested block syntax in that scenario, in spite of what the resource type schema seems to require.

@apparentlymart apparentlymart added this to the v0.12.0 milestone Mar 27, 2019
@apparentlymart apparentlymart self-assigned this Mar 27, 2019
@apparentlymart apparentlymart requested a review from a team March 27, 2019 00:35
…butes

This preprocessing step allows users to use nested block syntax to specify
elements of an attribute that is defined as being a list or set of an
object type.

This restores part of the unintended flexibility permitted in Terraform
v0.11 so that we can work around a few tricky edges where provider
implementations were relying on Terraform's failure to validate this in
earlier versions.

For any body that is pre-processed using this new helper, we will
recognize when a configuration author uses nested block syntax with a
name that is specified in the schema as an attribute of a suitable type
and tweak the schema just in time before decoding to expect that usage
and then fix up the result on the way out to conform to the original
schema.

Achieving this requires an abstraction inversion because only Terraform's
high-level schema has enough information to decide how to rewrite the
incoming low-level schema. We must therefore here implement HCL's
lowest-level API interface in terms of the higher-level abstractions of
hcldec and Terraform's configschema.

Because of the abstraction inversion this fixup mechanism cannot be used
generally for arbitrary HCL bodies but we can use it carefully inside the
lang package where its own API can guarantee the necessary invariants for
this to work.
For any block content we evaluate dynamically via this API, we'll make a
special allowance for users to optionally write members of a list
attribute instead as a sequence of nested blocks, thus allowing some
existing provider features that were assuming this capability to continue
to support it after v0.12.

This should not be used for any new provider features, and should ideally
be eventually phased out so that there aren't two
similar-but-slightly-different syntaxes for saying the same thing.
This gives us an extra hook in the dynblock variables analysis that should
allow us to also make it subject also to the lang/blocktoattr fixup, to
ensure we'll find all the references in spite of these various
pre-processing wrappers.
Because we handle FixUpBlockAttrs after dynamic block expansion, when
resolving variables we unfortunately need to consider the possibility of
both dynamic block expansion _and_ the block attrs fixup.

To accommodate this we have a variant of dynblock.VariablesHCLDec that
instead walks using the configschema.Block representation of the schema
and applies the same opportunistic schema rewrite used by FixUpBlockAttrs
at each body encountered during the walk.
For compatibility with documented patterns from existing providers we are
now allowing (via a pre-processing step) any attribute whose type is a
list-of-object or set-of-object type to optionally be assigned using one
or more blocks whose type is the attribute name.

The pre-processing functionality was implemented in previous commits but
we were not correctly detecting references within these blocks that are,
from the perspective of the primary schema, invalid. Now we'll use an
alternative implementation of variable detection that is able to apply the
same schema rewriting technique we used to implement the transform and
thus can find all of the references as if they were already in their
final locations.
@apparentlymart
Copy link
Contributor Author

Travis-CI is down right now, so the automatic CI check here won't be completing for a long time. Instead, I ran a similar set of test steps locally to approximate that so we can make progress here.

@ghost
Copy link

ghost commented Jul 24, 2019

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Jul 24, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants