Previously Terraform would react to an invalid top-level command the same
way as for typing no command at all: just printing out the long top-level
help directory.
If someone's tried to type a command, it's more helpful to respond to that
request by explaining directly that the command is invalid, rather than
leaving the user to puzzle that out themselves by referring to the help
text.
As a bonus, this also allows us to use our "didyoumean" package to suggest
possible alternatives if it seems like the user made a typo.
Terraform considers backend configurations only in the root module, so any
declarations in child modules are entirely ignored.
To avoid users mistakenly thinking that a root module backend
configuration has taken effect, we'll now emit a warning about it. This is
a warning rather than an error because it's reasonable to call a module
that would normally be a root module instead as a child module when
writing a wrapper module to handle integration testing.
The local-exec provisioner documentation includes an example which refers
to an attribute of the current resource using its full traversal path,
rather than using "self" as we typically expect.
Due to some coincidences in how Terraform builds the dependency graph,
referring to the resource in this way happens to work when the resource
has only a single instance (the graph builder just skips that
self-referential dependency edge), but it fails if the user later tries
to add "count" or "for_each" to the resource, because at that point all
of the instances become dependent on one another, which creates a
dependency cycle.
Using "self" to access the current instance attributes is the usual
approach, so I've updated the documentation to show that.
As written previously this seemed to suggest using "app.terraform.io" (the
"hostname you use to access the Terraform Cloud application) to access a
private registry in Terraform Enterprise, but that isn't true and I assume
isn't what was intended.
Instead, the hostname for a Terraform Enterprise instance is the hostname
where the Terraform Enterprise application is running, which is both the
hostname where users would find its web UI and the hostname they'd use
to configure the "remote" backend for remote operations and state storage.
In order to be able to predict a result type even if arguments are not yet
known, coalesce requires all of its arguments to be of the same type. Our
usual automatic conversion rules mean that in some cases the result is
a silent type conversion rather than an explicit error, so we'll at least
document that so that folks who encounter it can understand what is
causing the likely-surprising behavior.
If we were building this function over again today I expect we'd make it
always return an error under type mismatch, but to do so now would be a
breaking change and the potential cost of that seems too high for
something that doesn't seem to arise incredibly often in practice.
We have an existing warning message to encourage moving away from the old
0.11-and-earlier style of redundantly wrapping standalone expressions in
templates, but due to the special rules for object keys the warning
message was giving misleading advice in that context: a user following the
advice as given would then encounter an error about the object key being
ambiguous.
To account for that, this introduces a special alternative version of the
warning just for that particular position, directing the user to replace
the template interpolation markers with parenthesis instead. That will
then get the same result as the former interpolation sequence, rather than
producing the ambiguity error.
This one is a lot like the previous two commits, but slightly more complex:
- Only adding one new meta-argument page, for `providers`; otherwise, it just
re-uses the dual-purpose pages I made in the resources commit.
- About that `providers` argument: The stuff that was relevant to consumers of a
module went in that meta-argument page, but there was also a huge deep dive on
how the _author_ of a re-usable module should handle provider configurations
in cases where inheriting the default providers isn't sufficient. THAT, I
moved into a new page in the module development section. (For the consumer of
a module, this should all be an implementation detail; the module README
should tell you which aliased providers you need to configure and pass, and
then you just do it, without worrying about proxy configuration blocks etc.)
- The "standard module structure" recommendations in the main module development
page gets a page of its own, to make it more prominent and discoverable.
- Same deal with using the old URL as a landing page, at least for the main
module calls page. It didn't seem necessary for the module development page.
- Resource behavior gets its own page.
- Meta-arguments all get their own pages.
- Stuff about resource syntax itself gets a page.
In the process of breaking the meta-arguments out into their own pages, I
revised them (with the exception of `provider`) so that they apply to both
resources and modules.
Like with Expressions, this commit repurposes the old resources.html URL as a
landing page for old links.
This commit converts the previous URL for this content to a landing page, which
captures all of the previous in-page anchors and directs readers to the new home
for each section.
For some time now we've been recommending explicitly passing data between
configurations using separate resource types and data sources, rather than
always using terraform_remote_state, for reasons including reducing
coupling between subsystems and allowing a configuration's state snapshots
to be under restrictive access controls.
However, those recommendations have so far not appeared directly in the
documentation for terraform_remote_state, and have instead just been
alluded to elsewhere in the documentation when discussing ways to pass
data between configurations.
This change, then, is an attempt to be clear and explicit about the
recommendation and to give a variety of specific examples of how to
implement it. The terraform_remote_state data source page is admittedly
not the most obvious place in the information architecture to put a set
of alternatives to it, but it does appear that this documentation page is
where people most commonly end up when researching options in this area
and so I've put this here in an attempt to "meet people where they are".
Possibly in a future documentation reorganization we might have an
separate page specifically about sharing data between configurations, but
we don't currently have time to do that bigger reorganization. If we do so
later, the content on this page could potentially be replaced with a
summary of the recommendation and a link to another place for the details,
but the goal here is to make this information visible in the existing
location people look for it, rather than blocking until there's a better
place for it to live.
This also includes a small amount of editing of some existing content on
the page to use terminology and style more similar to how our main
configuration language documentation is written,.
Before configuring a provider, we need to unmark the configuration
object, in case it includes any sensitive values. This is required
because configuration occurs over gRPC, which doesn't support sensitive
marks.
Some hasty, incorrect merge conflict fixing caused this page to have a
strange mix of terminology between "system" and "provider". Along with
that, there were also several editorial errors caused by text on this
page having originally been derived from the provider registry
documentation.
This documentation will now consistently talk about being a module
registry protocol rather than a provider registry protocol, and it will
consistently use the term "system" as a generic term for the final part
of the module source address, aside from noting that there is an optional
convention to name it after the "type" part of an official provider when
possible.
This is a new part of the existing module_variable_optional_attrs
experiment, because it's intended to complement the ability to declare
an input variable whose type constraint is an object type with optional
attributes. Module authors can use this to replace null values (that were
either explicitly set or implied by attribute omission) with other
non-null values of the same type.
This function is a bit more type-fussy than our functions typically are
because it's intended for use primarily with input variables that have
fully-specified type constraints, and thus it uses that type information
to help inform how the defaults data structure should be interpreted.
Other uses of this function will probably be harder today because it takes
a lot of extra annotation to build a value of a specific type if it isn't
passing through a variable type constraint. Perhaps later language
features for more general type conversion will make this more applicable,
but for now the more general form of this problem is better solved other
ways.
So far all of our language experiments have been new constructs handled
statically up in the configs package, but functions are another common
extention point where experiments could be useful to gather feedback and
so this intends to pass the information down into the right place to allow
for that to happen, even though as of this commit there are no
experimental functions to use it.
The new nav structure demanded a few new pages that give context about a feature
or workflow. In a few cases, they take text from an existing page.
Co-authored-by: Tu Nguyen <im2nguyen@users.noreply.github.com>
Co-authored-by: Judith Malnick <judith.patudith@gmail.com>
We're splitting the current Terraform CLI docs into two top-level categories,
and these are the new nav sidebars for those sections.
As of this commit, they refer to some new "glue" pages that don't exist yet.
This is needed to make it possible to use the scram-sha-256
authentication method for the pg backend. It's not easy to write
unit-tests for this since it requires a specific configuration of the
PostgreSQL server, I did test it manually thought and everything seems
to work like it should.
Closes https://github.com/hashicorp/terraform/issues/24016
The HashiCorp engineering services team has set up APT and Yum
repositories as alternative installation methods for various HashiCorp
products, now including Terraform.
We don't really have a great place to talk about these in our current
website structure. There is a longer-term plan to revamp the downloads
page to include other options, but we are already getting lots of
questions about how to use these repositories and so my goal here is to
publish at least a first pass of documentation, linked from the Downloads
page sidebar as a placeholder for now, so we'll have somewhere to refer to
when answering such questions.
My intent is that even once we have a revamped Downloads page that
mentions these options more clearly, we'll still need to link out to
another page to talk about various details, and so the two new URLs this
creates would be the home of that content, even if we rewrite the specific
prose here to work better in the context of the new Downloads page.
When a resource has no `provider` argument specified, its provider is
derived from the implied provider type based on the resource type. For
example, a `boop_instance` resource has an implied provider local name
of `boop`. Correspondingly, its provider configuration is specified with
a `provider "boop"` block.
However, users can use the `required_providers` configuration to give a
different local name to a given provider than its defined type. For
example, a provider may be published at `foobar/beep`, but provide
resources such as `boop_instance`. The most convenient way to use this
provider is with a `required_providers` map:
terraform {
required_providers {
boop = {
source = "foobar/beep"
}
}
}
Once that local name is defined, it is used for provider configuration
(a `provider "boop"` block, not `provider "beep"`). It should also be
used when looking up a resource's provider configuration or provider.
This commit fixes a bug with this edge case, where previously we were
looking up the local provider configuration block using the resource's
assigned provider type. Instead, if no provider argument is specified,
we should be using the implied provider type, as that is what binds the
resource to the local provider configuration.