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

"HCL2"-based validate command #17539

Merged
merged 4 commits into from
Mar 13, 2018
Merged

"HCL2"-based validate command #17539

merged 4 commits into from
Mar 13, 2018

Conversation

apparentlymart
Copy link
Contributor

@apparentlymart apparentlymart commented Mar 9, 2018

Note: The target of this PR is the v0.12-dev branch, because this change is not shippable in isolation.

This is the first of many more changes required to fully integrate the "HCL2" implementation of HCL into Terraform. As a mostly-isolated starting point this changes the terraform validate command to use the new parser.

As proposed in #15895, this reduces slightly the scope of the terraform validate command to just "safe" static validation, which will eventually include checking configuration values against provider validation rules but will not do any "dynamic" validation that requires per-run context, state, etc.

This changeset anticipates (but does not yet implement) a terraform plan -validate-only mode that does a slightly-deeper validation with the full context of a particular run, including a set of variables, the current state, etc. The distinction between these two commands is:

  • terraform validate asks "is this configuration valid, regardless of what context it's applied in?", and is a good check for a text editor integration to run automatically on save, since it requires no credentials or other contextual information.
  • terraform plan -validate-only asks "is this proposed change valid?", and does all the same checks as terraform validate but also ensures that we have appropriate values for all variables. This might be a good command to run in order to smoke-test a pull request to the configuration of a real environment, for example.

Currently the distinction feels unclear because all operation context is local anyway, but it will become more significant in future when we implement backend-stored per-workspace variables and a backend that is able to run terraform plan remotely, both of which will require network requests to the backend in order to do full validation of a proposed change, as opposed to validation of just the configuration. terraform validate promises to always be local-only.


This set of changes was originally written in order to allow a first pass of batch-validating a set of "real-world" Terraform modules to pick some low-hanging parser bugs. (And it did! In hashicorp/hcl2#15, hashicorp/hcl2#16, hashicorp/hcl2#17, hashicorp/hcl2#18, hashicorp/hcl2#19, and hashicorp/hcl2#21.)

As a consequence of that goal, this patch also includes some extra functionality beyond just a port of the existing terraform validate command:

  • Some support code is added to command to allow us to convenient load configurations via a centralized loader. which then allows us to populate the source code cache we'll use for source code snippets in diagnostics.

  • The diagnostics printer is now able to print out source code snippets for errors that are able to generate them:

Screenshot of a terminal showing a Terraform error message with a copy of the line of source code where the error appears

  • The validate command has a JSON output mode. In future we will probably extend other commands with similar output, when Terraform's workflow is more stable and we're more confident that we won't need to break the format, but at least for this command the result format is unlikely to significantly change, because it's just a list of errors and warnings. This output format is hopefully useful for integrating "validate on save" functionality in text editor extensions.
{
  "valid": false,
  "error_count": 1,
  "warning_count": 0,
  "diagnostics": [
    {
      "severity": "error",
      "summary": "Unsupported block type",
      "detail": "Blocks of type \"vaariable\" are not expected here. Did you mean \"variable\"?",
      "range": {
        "filename": "variables.tf",
        "start": {
          "line": 1,
          "column": 1,
          "byte": 0
        },
        "end": {
          "line": 1,
          "column": 10,
          "byte": 9
        }
      }
    }
  ]
}
  • The temporary validation test harness also included some incomplete terraform init updates in order to install modules to validate, which are not included here. However this changeset does include a configload.InstallHooks implementation that can print installation progress to the UI. That's included here mainly just to keep it safe for later, when we make the more-complete terraform init updates.

This changeset temporarily breaks the "deep" validation done by walking the graph, instead just doing syntax validation. The validation of resource configurations against schema, etc, will be added back later once Terraform Core has been updated to work with the new configuration structures.

If we get a diagnostic message that references a source range, and if the
source code for the referenced file is available, we'll show a snippet of
the source code with the source range highlighted.

At the moment we have no cache of source code, so in practice this
codepath can never be visited. Callers to format.Diagnostic will be
gradually updated in subsequent commits.
We need to share a single config loader across all callers because that
allows us to maintain the source code cache we'll use for snippets in
error messages.

Nothing calls this yet. Callers will be gradually updated away from Module
and Config in subsequent commits.
@apparentlymart apparentlymart changed the title "HCL2"-based validate command [WIP] "HCL2"-based validate command Mar 9, 2018
As part of some light reorganization of our commands, this new
implementation no longer does validation of variables and will thus avoid
the need to spin up a fully-valid context. Instead, its focus is on
validating the configuration itself, regardless of any variables, state,
etc.

This change anticipates us later adding a -validate-only flag to
"terraform plan" which will then take over the related use-case of
checking if a particular execution of Terraform is valid, _including_ the
state, variables, etc.

Although leaving variables out of validate feels pretty arbitrary today
while all of the variable sources are local anyway, we have plans to
allow per-workspace variables to be stored in the backend in future and
at that point it will no longer be possible to fully validate variables
without accessing the backend. The "terraform plan" command explicitly
requires access to the backend, while "terraform validate" is now
explicitly for local-only validation of a single module.

In a future commit this will be extended to do basic type checking of
the configuration based on provider schemas, etc.
@apparentlymart apparentlymart changed the title [WIP] "HCL2"-based validate command "HCL2"-based validate command Mar 9, 2018
In the long run we'd like to offer machine-readable output for more
commands, but for now we'll just start with a tactical feature in
"terraform validate" since this is useful for automated testing scenarios,
editor integrations, etc, and doesn't include any representations of types
that are expected to have breaking changes in the near future.
@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