* lang/funcs: testing of functions through the lang package API
The function-specific unit tests do not cover the HCL conversion that happens when the functions are called in a terraform configuration. For e.g., HCL converts sets to lists before passing it to the function. This means that we could not test passing a set in the function _unit_ tests.
This adds a higher-level acceptance test, plus a check that every (pure) function has a test.
* website/docs: update function documentation
There was some leftover v0.11-style interpolation syntax here.
We prefer to use a "naked" expression in situations like this where the result
isn't a string, because interpolations returning non-strings is a common source
of confusion for new users.
* funcs/coalesce: return the first non-null, non-empty element from a
sequence.
The go-cty coalesce function, which was originally used here, returns the
first non-null element from a sequence. Terraform 0.11's coalesce,
however, returns the first non-empty string from a list of strings.
This new coalesce function aims to preserve terraform's documented
functionality while adding support for additional argument types. The
tests include those in go-cty and adapted tests from the 0.11 version of
coalesce.
* website/docs: update coalesce function document
The re-introduction of some of the ambiguity between argument and nested
block syntax (for compatibility with existing provider patterns)
unfortunately leads to some interesting consequences for attributes using
this mode.
While the behavior is generally as before in straightforward cases, this
page aims to spell out some of the different usage patterns explicitly
for the benefit of those writing more complex configurations, such as
generic re-usable modules where using argument vs. block syntax leads to
some real differences.
This page is intentionally not linked from anywhere in the part of the
website maintained in the Terraform repository. Instead, it can be linked
from the provider documentation for any argument where this pattern is
used, to help users understand the ways in which that argument might
deviate from the usual behaviors of arguments vs. nested blocks.
Some users are not accustomed to thinking of IP addresses in a bitwise
fashion, so the hope here is to give enough of an introduction to that way
of thinking for the reader to understand what the "newbits" and "netnum"
arguments represent.
For 0.11 I just specified the naming rules; for 0.12, I added some info about
referencing values and tightened up the layout of the optional arguments.
This commit also syncs up descriptions of `depends_on`.
As part of this, I'm copying the entire text of the 0.12
docs/configuration/modules.html page into docs/configuration-0-11/modules.html —
some of the 0.11 pages needed to be able to link to the moved content, I
didn't want to jump versions jarringly, and a close reading didn't reveal
anything in there that's inaccurate for 0.11.
The "terraform fmt" command produces a different canonical form than we
were showing in our examples here. Our examples should always reflect the
conventions applied by "terraform fmt" to avoid confusion.
(This particular decision is a pragmatic one because the formatter design
needs to use the same rules for the colon in the ? : conditional operator
as for the colon in "for" expressions.)
Since references to attributes of resources are by far the most common
reference type, and the mapping of resource type config to the attributes
is not always obvious, here we give some real examples of patterns for
accessing different configuration constructs within resource blocks along
with the resource type's exported attributes.
Since we don't have any real examples of labelled nested blocks yet (the
current SDK doesn't support them) I've included a hypothetical example for
now just to establish the patterns around them in preparation for
beginning to introduce them as we roll out this feature in the SDK.
As well as some general consolidation and reorganizing, this also includes
some updated advice for making the best use of new Terraform v0.12
features to create infrastructure building-blocks.
In particular, the "Module Usage" documentation is now consolidated into
the configuration section in order to bring all of our general language
documentation together, and the top-level "Modules" section is now
primarily focused on module _authors_ as an audience, covering topics such
as publishing modules and designing them for reuse.
* docs: update plan command documentation. Fixes#19235
* docs: added a missing reserved variable name. Fixes#19159.
* website: add note that resource names cannot start with a number
* website: add some notes to the 0.12 upgrade guide
In prior versions, we recommended using hash functions in conjunction with
the file function as an idiom for detecting changes to upstream blobs
without fetching and comparing the whole blob.
That approach relied on us being able to return raw binary data from
file(...). Since Terraform strings pass through intermediate
representations that are not binary-safe (e.g. the JSON state), there was
a risk of string corruption in prior versions which we have avoided for
0.12 by requiring that file(...) be used only with UTF-8 text files.
The specific case of returning a string and immediately passing it into
another function was not actually subject to that corruption risk, since
the HIL interpreter would just pass the string through verbatim, but this
is still now forbidden as a result of the stricter handling of file(...).
To avoid breaking these use-cases, here we introduce variants of the hash
functions a with "file" prefix that take a filename for a disk file to
hash rather than hashing the given string directly. The configuration
upgrade tool also now includes a rule to detect the documented idiom and
rewrite it into a single function call for one of these new functions.
This does cause a bit of function sprawl, but that seems preferable to
introducing more complex rules for when file(...) can and cannot read
binary files, making the behavior of these various functions easier to
understand in isolation.
It's not normally necessary to make explicit type conversions in Terraform
because the language implicitly converts as necessary, but explicit
conversions are useful in a few specialized cases:
- When defining output values for a reusable module, it may be desirable
to force a "cleaner" output type than would naturally arise from a
computation, such as forcing a string containing digits into a number.
- Our 0.12upgrade mechanism will use some of these to replace use of the
undocumented, hidden type conversion functions in HIL, and force
particular type interpretations in some tricky cases.
- We've found that type conversion functions can be useful as _temporary_
workarounds for bugs in Terraform and in providers where implicit type
conversion isn't working correctly or a type constraint isn't specified
precisely enough for the automatic conversion behavior.
These all follow the same convention of being named "to" followed by a
short type name. Since we've had a long-standing convention of running all
the words together in lowercase in function names, we stick to that here
even though some of these names are quite strange, because these should
be rarely-used functions anyway.
The sethaselement, setintersection, and setunion functions are defined in
the cty stdlib. Making them available in Terraform will make it easier to
work with sets, and complement the currently-Terraform-specific setproduct
function.
In the long run setproduct should probably move into the cty stdlib too,
but since it was submitted as a Terraform function originally we'll leave
it here now for simplicity's sake and reorganize later.
In our new world it produces either a set of a tuple type or a list of a
tuple type, depending on the given argument types.
The resulting collection's element tuple type is decided by the element
types of the given collections, allowing type information to propagate
even if unknown values are present.
We missed this one on a previous pass of bringing in most of the cty
stdlib functions.
This will resolve#17625 by allowing conversion from Terraform's
conventional RFC 3339 timestamps into various other formats.
This function is similar to the template_file data source offered by the
template provider, but having it built in to the language makes it more
convenient to use, allowing templates to be rendered from files anywhere
an inline template would normally be allowed:
user_data = templatefile("${path.module}/userdata.tmpl", {
hostname = format("petserver%02d", count.index)
})
Unlike the template_file data source, this function allows values of any
type in its variables map, passing them through verbatim to the template.
Its tighter integration with Terraform also allows it to return better
error messages with source location information from the template itself.
The template_file data source was originally created to work around the
fact that HIL didn't have any support for map values at the time, and
even once map support was added it wasn't very usable. With HCL2
expressions, there's little reason left to use a data source to render
a template; the only remaining reason left to use template_file is to
render a template that is constructed dynamically during the Terraform
run, which is a very rare need.
This commit is a wide-ranging set of edits to the pages under
/docs/configuration. Among other things, it
- Separates style conventions out into their own page.
- Separates type constraints and conversion info into their own page.
- Conflates similar complex types a little more freely, since the distinction is
only relevant when restricting inputs for a reusable module or resource.
- Clarifies several concepts that confused me during edits.
...and one other reference to the application data directory.
Context:
https://docs.microsoft.com/en-us/windows/desktop/shell/knownfolderid#folderid_roamingappdata
In newer Windows versions, the folder accessible as `%APPDATA%` (and via various
APIs) is actually at something like "documents and settings\user\application
data\roaming", while earlier versions omit the "\roaming" part of the path. This
means you can confuse people by referring to the "application data" directory by
its human name, because "roaming" is the real application data directory, but it
looks like a subdirectory of "application data".
Thus, it's less confusing to just use the `%APPDATA%` variable, with the added
benefit that you can copy and paste the path and it'll just work in most places.
Since the index page is long, by the time the reader reaches the end of
it the relevant portion if the navigation is unlikely to be visible. To
compensate for this, we'll link to the first sub-section and thus give
the user an opportunity to notice the navigation structure for the rest
of the pages.
This has now been superseded by the expressions.html.md file in the same
directory. As part of deploying this, the former URL for this page must
be redirected to the expressions page to retain a target for any
existing links on third-party sites.
This kinda-weird feature was previously quite severely under-documented in
terms of exactly what effect it has. This new documentation for it first
attempts to frame it as something that should be rarely used, and then
explains in more detail exactly how it behaves for different top-level
block types within the configuration.
As part of revamping the "Configuration" portion of the website for the
v0.12 release, here we update the Terraform Settings page to use a similar
"guide-like" writing style as the other updated pages in this section.
Previously we just listed out all of the functions in alphabetical order
inside the "Interpolation Syntax" page, but that format doesn't leave much
room for details and usage examples.
Now we give each function its own page, and categorize them for easier
navigation. While many functions are very simple and don't really warrant
a full page, certain functions do have additional details that are worth
mentioning and this structure scales better for those more complicated
functions.
So far this includes only the numeric and string functions. Other
categories will follow in subsequent commits.
This rewrite of the "Configuration Syntax" page now gives some more detail
on the top-level structural constructs and de-emphasizes the name "HCL"
as subordinate to "the Terraform language".
It also now includes some commentary on valid identifiers and comments,
and issues around character encodings and line endings.
In addition, we now have a new "Expressions" page that replaces the old
"Interpolation Syntax" page, covering the expression language features
we inherit from HCL and how they behave in the context of Terraform.
The "Expressions" page currently links to a page about the built-in
functions which does not yet exist. This will be created in a later
commit.
This adopts a more guide-like writing style, similar to what prior commits
have done to some other subsections of this section.
The data sources page has not got any real attention since the feature
was first added, and our vocabulary for describing them and their
lifecycle hadn't quite settled when the page was originally written. This
new version is consistent in how it uses "data source" to describe the
feature that providers offer and "data resource" to describe what is
created by a "data" block in configuration, which then allows us to
draw on the many shared features between both data and managed resources.
For the moment this waits until "data resource" is defined in order to
first introduce the qualifier "managed resource". We may wish to revise
this again to mention that more specific nomenclature in passing on the
"Resources" page, in case a user encounters it elsewhere and wants to
learn what it means without needing to be familiar with data resources
first.
This adopts a more guide-like writing style, similar to what prior commits
have done to some other subsections of this section.
Since we already have a whole top-level section devoted to modules, there
is no need for full coverage of all of their features here. Instead, this
section focuses on an an initial introduction to what modules are and
the basics of their usage within the Terraform language. We then link
to the main modules section for the full details.
This adopts a more guide-like writing style, similar to what prior commits
have done to some other subsections of this section.
In the process of writing this, I identified some unclear statements in
the "Resources" subsection, and so these are also revised here for
consistency with the output values documentation.
These revisions reflect this sub-section's new earlier placement in the
sub-section list, leading to a more guide-like style for the initial
sections.
Also includes some minor copy-editing to align terminology with that
introduced in the prior commit for the "Resources" docs page.
This is now the leading subsection of the Configuration section of the
docs, and so this rewrite intends to make it more "guide-like" and as
accessible as possible to those who are not yet familiar with other
Terraform concepts.
This rewrite also attempts to introduce some consistency into our
vocabulary, which should eventually be reflected throughout our
documentation. In particular:
- "Resource" refers to the block the user writes in configuration, while
"Resource _Type_" refers to what the provider defines. We previously
used "resource" for both of these interchangeably.
- "Resource" is no longer used to refer to what gets created and managed
in remote APIs as a result of a resource block in configuration. Lacking
a good distinct name for these, this guide uses the word "object",
qualifying it as "infrastructure object" or "remote object" where
necessary to retain clarity. This distinction is important to enable
a clear description of resource lifecycle.
- "Argument" refers to an element (attribute or block) within a resource
block. This terminology was already being used in some places, so we
embrace it here as a way to distinguish from "attribute", which is
what a resource _exports_ for use in expressions.
- Since interpolation is no longer needed to use expressions in the
language, the word "expression" is used to describe the definition of
a value that might involve some computation. Where necessary, this is
used with a modifier "arbitrary expression" to contrast with situations
where the set of allowed expression constructs is constrained.
The prior content on this page was little more than an instruction to
begin navigating the sub-sections of this section.
The new content aims to give a broad overview of some of the language
concepts and a syntax example, in order to create some context to help
the user navigate the subsections more easily.
This also introduces for the first time usage of the term "the Terraform
language". This was previously left un-named, leading to some awkward
sentence constructions elsewhere in the docs. This new name gives us
some specific terminology to use in order to contrast the language that
exists at Terraform's level of abstraction, defining the semantics, from
the underlying grammar provided by HCL.
With the additional configuration language features coming in Terraform
v0.12, our existing documentation structure is beginning to strain.
Here we reorganize the navigation slightly in order to introduce the
concepts in a more appropriate order so that we can reveal complexity
more gradually. Subsequent commits will revise the content of these
pages to better reflect the new sequencing.
The "Environment Variables" page is moved from the Configuration section
into the "Commands" section, since it is not considered a part of the
configuration language and thus more appropriate in the CLI documentation.
The old placement is reflective of the broader purpose that the
"Configuration" section had originally, but its new focus will be on
the Terraform language (.tf files) in particular, with other aspects of
customizing Terraforms behavior covered in other sections.
website: Reconcile docs about plugin discovery and downloading
I'm attempting to keep things simple for normal users while making sure we've
got the full behavior written down somewhere for plugin developers.
This commit doesn't stand alone; it's paired with a commit in the
terraform-website repo, to deal with some related content in the "extend"
section.
Create-before-destroy dependencies are automatically ordered correctly
by terraform. Remove the old notice about requiring all dependencies to
have the same setting for create_before_destroy.
Also:
- In the getting started guide, the TFE content was all tailored to the older
run-locally workflow. I've replaced it with some brief explanation and a link
to the dedicated TFE getting started guide.
- Fixed a sidebar link glitch in the configuration section. (Both "Terraform"
and "Terraform Enterprise" were marked as active if you were on the TFE page.)
- Renamed the "Terraform Enterprise" page "Terraform Push." (Some people have
gotten confused and landed on this page when trying to set up the `atlas`
remote backend.)
We've historically been somewhat inconsistent in how we refer to the
type of object defined by "variable" blocks in configuration. Parts of
our documentation refer to them as "input variables" or just "variables",
while our implementation refers to them as "user variables".
Since Terraform Registry is now also referring to these as "Inputs", here
we standardize on "Input Variable" as the fully-qualified name for this
concept, with "variable" being a shorthand for this where context is
obvious. Outside of this context, anything that can be referred to in
an interpolation expression is generically known as a "variable", with
Input Variables being just one kind, specified by the "var." prefix.
While this terminology shift is not critical yet, it will become more
important as we start to document the new version of the configuration
language so we can use the generic meaning of "variable" there.
The bulk of the text on this page hasn't been revised for some time and
so parts of it were using non-idiomatic terminology or not defining terms
at all.
The main goal of this revision is to standardize on the following terms:
- "provider configuration" refers to a specific provider block in config,
as a distinct idea from the provider _itself_, which is a singleton.
- "Default" vs. "additional" provider configurations, distinguishing
those without and with "alias" arguments respectively. These are named
here so that we can use this terminology to describe the different
behaviors of each for the purposes of provider inheritance between
modules.
This allows the user to customize the location where Terraform stores
the files normally placed in the ".terraform" subdirectory, if e.g. the
current working directory is not writable.
The modules mechanism has changed quite a bit for version 0.11 and so
although simple usage remains broadly compatible there are some
significant changes in the behavior of more complex modules.
Since large parts of this were rewritten anyway, I also took the
opportunity to do some copy-editing to make the prose on this page more
consistent with our usual editorial voice and to wrap the long
lines.
Since we don't currently auto-install provisioner plugins this is
currently placed on the providers documentation page and referred to as
the "Provider Plugin Cache". In future this mechanism may also apply to
provisioners, in which case we'll figure out at that point where better
to place this information so it can be referenced from both the provider
and provisioner documentation pages.
This mechanism for configuring plugins is now deprecated, since it's not
capable of declaring plugin versions. Instead, we recommend just placing
plugins into a particular directory, which is now documented on the
main providers documentation page and linked from the more detailed docs
on plugins in general.
This function takes a map of lists of strings and inverts it so that
the string values become keys and the keys become items within the
corresponding lists.
Previously the -upgrade option was covered only on the "terraform init" usage page. It seems also worth mentioning in the main docs on provider versioning, since we're already explaining here other mechanics of the versioning/constraints system.
This escapes all characters that might have a special interpretation when embedded into a portion of a URL, including slashes, equals signs and ampersands.
Since Terraform's internals are not 8-bit clean (it assumes UTF-8
strings), we can't implement raw gzip directly. We're going to add
support where it makes sense for passing data to attributes as
base64 so that the result of this function can be used.