Commit Graph

12 Commits

Author SHA1 Message Date
Martin Atkins 0742e756e5 tfdiags: Sort order for diagnostics
Because we gather together diagnostics from many different parts of the
codebase, the list often ends up being in a non-ideal order. Here we
define a partial ordering for diagnostics that should hopefully make them
easier to scan when many are present, by grouping together diagnostics
that are of the same severity and belong to the same file.

We use sort.Stable here because we have a partial order and so we need
to make sure that diagnostics that do not have a relative ordering will
remain in their original order.

This sorting is applied just in time before rendering the diagnostics
in command.Meta.showDiagnostics.
2018-10-16 18:50:29 -07:00
Martin Atkins abf0284ca5 tfdiags: Unwrap NonFatalError on append
This is a variant of diagnosticsAsError that we use to signal to informed
callers that there might just be warnings inside, but we should also do
the right thing if a caller just appends it to an existing diagnostics
without checking first.
2018-10-16 18:48:28 -07:00
Martin Atkins 3822650e15 tfdiags: Diagnostics.ErrWithWarnings and .NonFatalErr
There is some existing practice in the "terraform" package of returning
a special error type ValidationError from EvalNode implementations in
order to return warnings without halting the graph walk even though a
non-nil error was returned.

This is a diagnostics-flavored version of that approach, allowing us to
avoid totally reworking the EvalNode concept around diagnostics and
retaining the ability to return non-fatal errors.

NonFatalErr is equivalent to the former terraform.ValidationError, while
ErrWithWarnings is a helper that automatically treats any errors as
fatal but returns NonFatalError if the diagnostics contains only warnings.
2018-10-16 18:44:26 -07:00
Martin Atkins 860a57d104 tfdiags: Simple helper for creating "sourceless" diagnostics
While diagnostics are primarily designed for reporting problems in
configuration, they can also be used for errors and warnings about the
environment Terraform is running in, such as inability to reach a remote
service, etc.

Function Sourceless makes it easy to produce such diagnostics with the
customary summary/detail structure. When these diagnostics are rendered
they will have no source code snippet and will instead just include the
English-language content.
2018-10-16 18:24:10 -07:00
Martin Atkins 9bd47bf17c tfdiags: helper functions for nicer display of cty.PathError
cty doesn't have a native string representation of a cty.Path because it
is the layer below any particular syntax, but up here in Terraform land
we know that we use HCL native syntax and so we can format a string in
a HCL-ish way for familiarity to the user.

We'll use this form automatically when such an error is used directly as a
diagnostic, but we also expose the function publicly so that other code
that incorporates errors into diagnostic detail strings can apply the
same formatting.
2018-10-16 18:24:10 -07:00
Martin Atkins e309675853 tfdiags: Contextual diagnostics
The usual usage of diagnostics requires us to pass around source location
information to everywhere that might generate a diagnostic, and that is
always the best way to get the most precise diagnostic source locations.

However, it's impractical to require source location information to be
retained in every Terraform subsystem, and so this new idea of "contextual
diagnostics" allows us to separate the generation of a diagnostic from
the resolution of its source location, instead resolving the location
information as a post-processing step once the call stack unwinds to a
place where there is enough context to find it.

This is necessarily a less precise approach than reading the source ranges
directly from the configuration AST, but gives us an alternative to no
diagnostics at all in portions of Terraform where full location
information is not available.

This is a best-effort sort of thing which will get as precise as it can
but may return a range in a parent block if the precise location of a
particular attribute cannot be found. Diagnostics that rely on this
mechanism should include some other contextual information in the detail
message to make up for any loss of precision that results.
2018-10-16 18:24:10 -07:00
Rob Campbell 5daeee5f6d Update various files for new version of "stringer"
The latest version of stringer now uses strconv instead of fmt.
2017-12-11 13:26:29 -08:00
Martin Atkins 094cdca688 tfdiags: show descriptions in diagnosticsAsError
Previously we were showing only the summaries when converting to a string
error, but HCL generates summaries that indicate only the _type_ of error,
expecting that the detail will give the details, and so we need to show
both in order to produce a useful error message.
2017-10-16 17:53:06 -07:00
Martin Atkins c007e3a7da tfdiags: Helper to construct SourceRange from hcl.Range
HCL will be the most frequent origin of a source range, so this helper
should make it easier to translate these between the two worlds so we
can more easily use them in native Terraform diagnostics and other
messaging.
2017-10-16 17:51:16 -07:00
Martin Atkins 780e758f1e tfdiags: Allow construction of RPC-friendly Diagnostics
Due to the use of interfaces, Diagnostics is not super-friendly to the gob
encoding we currently use for plugin RPC. To mitigate this, we provide
a helper that converts all of the wrapped objects into a predictable flat
structure that we can pre-emptively register with gob.

This means that the decoded Diagnostics still has the same meaning as
the original, though the original wrapped errors (if any) are lost and
thus our errwrap integration won't be effective any longer.
2017-10-06 11:46:07 -07:00
Martin Atkins ab5efb805c tfdiags: SourceRange.StartString
This helper provides a concise string showing the filename, start line and
start column for a range, for easy inclusion in error messages.
2017-10-06 11:46:07 -07:00
Martin Atkins 61cd3bf02a tfdiags: new package for normalizing error and warning messages
Currently we lean heavily on the Go error type as our primary means of
describing errors, and along with that use several more specialized
implementations of it in different spots for additional capabilities such
as multiple errors in one object, source code range references, etc.

We also have a rather ad-hoc approach of returning an array of warnings
from certain functions along with one or multiple errors.

This rather-disorganized approach makes it hard for us to present
user-facing error messages consistently. As a step towards mitigating
this, package tfdiags provides a model for user-facing error and warning
messages and helper functions for creating them from various other
error and warning types used elsewhere in Terraform.

This mechanism is intended to be used to report errors and warnings where
the audience is the Terraform user, and so it may go a few layers deep
down the call stack into codepaths like config parsing, interpolation, etc
but is primarily a UX concern. The deepest reaches of Terraform core will
continue using "error" as normal, with higher layers preparing error
messages for presentation to the user.

To avoid needing to change the interface of every function that might
generate error diagnostics, the Diagnostics type can be "smuggled" via
an error value through other APIs and then unwrapped at the other end,
though it will lose any naked warnings (without at least one error) along
the way, and so codepaths that are expected to generate warnings
(validation, primarily) should use the concrete Diagnostics type
throughout the call chain.
2017-10-06 11:46:07 -07:00