support the requested platform.
If the newest version of a provider which matches the version
constraints does not support the requested platform, filter the list of
available versions by platform support and try again.
In order to not require state migrations to be supported in both
MigrateState and StateUpgraders, the legacy provider codepath needs to
handle the StateUpgraders transparently during Refresh.
This adds some of the required shim functions to the schema package.
While this further bloats the already huge package, adding the helpers
here was significantly less disruptive than refactoring types into
separate packages to prevent import cycles.
The majority of tests here are directly adapted from existing schema
tests to provide as many known good values to the shims as possible.
It turns out that state upgrades need to be handled differently since
providers are going to be backwards compatible. This means that new
state upgrades may still be stored in the flatmap format when used wih
terraform 0.11. Because we can't account for the specific version which
could produce a legacy state, all future state upgrades need to record
the schema types for decoding.
Rather than defining a single Upgrade function for states, we now have a
list of functions, each of which handle upgrading a specific version to
the next. In practice this isn't much different from the way many
resources implement upgrades themselves, with a separate function for
each version dispatched from the MigrateState function. The only added
burden is the recording of the schema type, and we intend to supply
tools and helper function to prevent the need to copy the entire
existing schema in all cases.
This is the provider-side UpgradeState implementation for a particular
resource. This new function will be called to upgrade a saved state with
an old schema version to the current schema.
UpgradeState also requires a record of the last schema and version that
could have been stored as a flatmapped state. If the stored state is in
the legacy flatmap format, this will allow the provider to properly
decode the flatmapped state into the expected structure for the new json
encoded state. If the stored state's version is below that of the
LegacySchema.Version value, it will first be processed by the legacy
MigrateState function.
Make the function work specifically how we need for RequiresReplace.
Skip index changes, any set changes are only recorded as the set itself,
and filter out duplicate paths.
Add a few more tests to check for various nested structures.
Rather than try and make a generalized path function here, what we
really need in a function to generate the paths needed for
RequiresReplace. This needs to take into account that sets elements
don't need to be indexed themselves, and changes to collection index
values aren't needed.
PathFromFlatmapKey is used to convert a flatmap key to a cty.Path, and
ensures it conforms to the type schema.
This is used when handling Diffs, where the ResourceAttrDiffs are
indexed by the flatmapped key values, and we need to convert those to
addresses to apply to a cty.Value.
Very few resources need connection info, and rather than relying on
providers to set default for some resources, we are going to require
that connection blocks be explicitly set in the configuration.
When creating a flatmap from a cty.Value, there may be Null collections
which don't need to be added to the flatmap at all. Skip over these to
avoid panicking in ElementIterator with a Null value.
Any value that is not set in the configuration should decode as a Null
value. Unknown should still be returned if a computed value expression
is unknown.
This includes updates to various diagnostic messages to improve precision
and consistency of terminology.
It also includes some other changes to portions of HCL API that Terraform
isn't yet using.
In order for providers to determine if a computed value was unset in the
configuration, the configuration must be passed along with the prior and
proposed states. Terraform core will still handle the creation of the
ProposedNewState to ensure correctness, but the raw configuration value
will also be supplied for comparison.
* builtin/providers: implement terraform remote state datasource as providers.Interface
* append and return diags separately (to match the idiomatic usage
elsewhere in Terraform)
* diagnostic summary style improvements
* update tests to pass config to schema.CoerceValue
* trust that the schema will be enforced and there is no need to check
that a given attribute exists
* added dataSourceRemoteStateGetSchema() (effectively replacing a
function that was inappropriately removed) for consistency with other
terraform providers
* builtin/provider terraform test: added InternalValidate() test for dataSourceRemoteStateGetSchema
In the old state package we had this as a separate manager
state.BackupState, but that doesn't work with our new interfaces because
we handle lineage and serial within the state managers themselves and
don't expose them to callers anymore.
In practice it being built in to the filesystem manager is not a problem
because we only use the backup functionality for local state anyway.
This also slightly adjusts the behavior to be more intuitive. The old
BackupState relied on the implementation detail that Terraform re-persists
the original state early in an apply operation, which meant that by
coincidence it would back up the right snapshot. In this new approach,
we instead take an in-memory copy during State and then write _that_ to
disk in WriteState if the new state seems different, so we're guaranteed
that we'll always write out what we read before any changes were made.
In future we may improve this further, such as keeping multiple
generations of backups, etc. But for now this is intended to preserve the
goals of the original implementation while making its behavior
self-contained and not dependent on coincidences.
The update protocol shims will also check for this this, but eventually
"id" will only be a normal attribute, and we shouldn't have to special
case this.
When converting a legacy schemaMap to a configschema, we need to add
"id" as a required attribute to top-level resources if it's not
declared.
The "id" field will be required to interoperate with the legacy helper
schema, since the presence of an id was used to indicate the existence
of a resource.
We shouldn't really need these because the plan is already filtered to
include diffs only for targeted resources, but we currently rely on this
to filter out non-resource items from the diff, and so we'll retain it
for now to avoid reworking how the apply-time graph builder works.
On the first pass here we erroneously assumed that this was redundant with
the backend settings embedded in the configuration itself. In practice,
users can override backend configuration when running "terraform init"
and so we need to record the _effective_ backend configuration.
Along with this, we also return the selected workspace name at the time
the plan was created so we'll later be able to produce a specialized error
for the situation of having the wrong workspace selected. This isn't
strictly required because we'll also check the lineage of the state, but
the error message that would result from that failure would be relatively
opaque and thus less helpful to the user.
A nil flatmap will be encoded as a NullVal of the correct type. When
Converting a NullVal back to a flatmap, return nil immediately rather
than attempting to build the values.
The "config" package is no longer used and will be removed as part
of the 0.12 release cleanup. Since configschema is part of the
"new world" of configuration modelling, it makes more sense for
it to live as a subdirectory of the newer "configs" package.
Since the "References" function on graph nodes can't return errors, we
need to catch invalid depends_on references during the validation pass.
In this case, we're checking that the address is exact, rather than being
part of a traversal into an attribute of the object. In other words,
aws_instance.example is valid but aws_instance.example.id is not.
The only contextual information returned by the plugins in a diagnostic
is an attribute path. In order to test the conversions, we need to be
able to extract the cty.Path from a diagnostic if it exists.
In order to properly migrate the contents of resource, data, provider and
provisioner blocks we will need the provider's schema in order to
understand what is expected, so we can resolve some ambiguities inherent
in the legacy HCL AST.
This includes an initial prototype of migrating the content of resource
blocks just to verify that the information is being gathered correctly.
As with the rest of the upgrade_native.go file, this will be reorganized
significantly once the basic end-to-end flow is established and we can
see how to organize this code better.
This is based on c811440188 made against the
old "config" package implementations, but also catches a few other cases
where we would previously have printed the private key into the error
messages.
Previously we would attempt to DynamicExpand during the validate walk and
then validate each expanded instance separately. However, this meant that
we would not be able to validate the contents of a block where count = 0
or if count is not yet known.
Here we instead do a more static validation pass against the resource
configuration itself, setting count.index to cty.UnknownVal(cty.Number) so
we can type-check everything inside the block as being correct regardless
of the final count.
This is another step towards repairing the "validate" command for our
changed assumptions in a world where we have a more sophisticated type
checker.
This doesn't yet address the remaining problem that the expression
evaluator can't, with the current state structures, distinguish between
a completed resource with count = 0 and a resource that doesn't exist
at all (during validate), and so we'll still get errors if an expression
elsewhere in configuration refers to a dynamic index of a resource with
"count" set. That's a pre-existing condition that's no longer being masked
by _this_ problem, but can't be addressed until we've introduced the new
state types (states.State, etc) and thus we _can_ distinguish these two
situations. That will therefore be addressed in a later commit.
Previously we had the evaluate methods accept directly an
addrs.InstanceKey and had our evaluator infer a suitable value for
count.index for it, but that prevents us from setting the index to be
unknown in the validation scenario where we may not be able to predict
the number of instances yet but we still want to be able to check that
the configuration block is type-safe for all possible count values.
To achieve this, we separate the concern of deciding on a value for
count.index from the concern of evaluating it, which then allows for
other implementations of this in future. For the purpose of this commit
there is no change in behavior, with the count.index value being populated
whenever the instance key is a number.
This commit does a little more groundwork for the future implementation
of the for_each feature (which'll support each.key and each.value) but
still doesn't yet implement it, leaving it just stubbed out for the
moment.
Since the intent of the validate command is to check config validity
regardless of context (input variables, state, etc), we use unknown values
of the requested type here, which will then allow us to complete type
checking against the specified types of the variables without assuming
any particular values.
Since schemas are required to interpret provider, resource, and
provisioner attributes in configs, states, and plans, these helpers intend
to make it easier to gather up the the necessary provider types in order
to preload all of the needed schemas before beginning further processing.
Config.ProviderTypes returns directly the list of provider types, since
at this level further detail is not useful: we've not yet run the
provider allocation algorithm, and so the only thing we can reliably
extract here is provider types themselves.
State.ProviderAddrs and Plan.ProviderAddrs each return a list of
absolute provider addresses, which can then be turned into a list of
provider types using the new helper providers.AddressedTypesAbs.
Since we're already using configs.Config throughout core, this also
updates the terraform.LoadSchemas helper to use Config.ProviderTypes
to find the necessary providers, rather than implementing its own
discovery logic. states.State is not yet plumbed in, so we cannot yet
use State.ProviderAddrs to deal with the state but there's a TODO comment
to remind us to update that in a later commit when we swap out
terraform.State for states.State.
A later commit will probably refactor this further so that we can easily
obtain schema for the providers needed to interpret a plan too, but that
is deferred here because further work is required to make core work with
the new plan types first. At that point, terraform.LoadSchemas may become
providers.LoadSchemas with a different interface that just accepts lists
of provider and provisioner names that have been gathered by the caller
using these new helpers.
This allows us to record the resource-to-provider associations we made
during the plan phase and ensure that we use the same config during
apply.
This isn't technically necessary, since we can in principle just repeat
the same matching algorithm against the config, but that algorithm is
relatively complicated and so if we execute it just once during plan we
remove the risk of bugs causing different decisions to be made during
the apply phase.
This also includes updates to the plan file format to include the provider
addresses. Since we've not actually shipped any version of Terraform
using our protobuf schema yet, we renumber here all of the fields after
the new one to keep them incrementing consecutively. This example should
not be followed after we have a released version of Terraform using this,
as a courtesy to anyone trying to parse these files (even though we're
not yet guaranteeing compatibility between releases).
This is the frontend to the work-in-progress codepath for upgrading the
source code for a module written for Terraform v0.11 or earlier to use
the new syntax and idiom of v0.12.
The underlying upgrade code is not yet complete as of this commit, and
so the command is not yet very useful. We will continue to iterate on
the upgrade code in subsequent commits.
This covers all of the expression node types in HIL's AST, and also
includes initial support for some of our top-level blocks so that we can
easily test that.
The initial implementations of the "variable" and "output" blocks are
pretty redundant and messy, so we can hopefully improve on these in a
later pass.