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

Support Terraform Validate Command #323

Merged
merged 11 commits into from
Dec 8, 2020
Merged

Support Terraform Validate Command #323

merged 11 commits into from
Dec 8, 2020

Conversation

appilon
Copy link
Contributor

@appilon appilon commented Dec 2, 2020

This PR adds support to call terraform validate via executeCommand. It expects a uri to the dir to run it from to be passed. It will error if the specified dir is an uninitialized module.

Closes #27

@appilon appilon requested a review from a team December 2, 2020 02:59
go.mod Outdated Show resolved Hide resolved
@appilon appilon force-pushed the validate-on-save branch 2 times, most recently from 5254615 to 42af1b9 Compare December 6, 2020 19:46
@appilon appilon marked this pull request as ready for review December 8, 2020 01:54
@appilon
Copy link
Contributor Author

appilon commented Dec 8, 2020

Just need a release of terraform-exec, as well as a PR for terraform-schema, then will bump the dependency references

@appilon appilon changed the title Support Terraform Validate Diags Support Terraform Validate Command Dec 8, 2020
Copy link
Member

@radeksimko radeksimko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left you some mostly minor comments inline. Aside from these it LGTM.

sessCtx context.Context
diags chan diagContext
diagsCache map[string]map[string][]lsp.Diagnostic
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for readability, would you mind creating some custom types here and compose the final diagsCache type from these?

For example:

type fileURI string
type diagnosticSource string
type fileDiagnostics map[diagnosticSource][]lsp.Diagnostic

diagsCache map[fileURI]fileDiagnostics

internal/langserver/diagnostics/diagnostics.go Outdated Show resolved Hide resolved
internal/langserver/diagnostics/diagnostics.go Outdated Show resolved Hide resolved
internal/langserver/diagnostics/diagnostics.go Outdated Show resolved Hide resolved
@@ -378,6 +378,67 @@ func (rm *rootModule) ExecuteTerraformInit(ctx context.Context) error {
return rm.tfExec.Init(ctx)
}

func (rm *rootModule) ExecuteTerraformValidate(ctx context.Context) (map[string]hcl.Diagnostics, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reckon we'll need to find a more flexible way of integrating tfexec and the rootmodule functionality as adding proxy method for every command probably won't scale. Which is certainly not a criticism of your change here - This is fine in this PR as it maintains consistency, I'm just thinking out loud about the future. 😄

Comment on lines +406 to +410
// tfjson.Diagnostic is a conversion of an internal diag to terraform core,
// tfdiags, which is effectively based on hcl.Diagnostic.
// This process is really just converting it back to hcl.Diagnotic
// since it is the defacto diagnostic type for our codebase currently
// https://github.com/hashicorp/terraform/blob/ae025248cc0712bf53c675dc2fe77af4276dd5cc/command/validate.go#L138
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be convertible now, but even Terraform itself has its own type for interpreting diags, so I wouldn't be surprised if at some point we find out that hcl types just aren't sufficient to interpret validate diags.

I think that returning []tfjson.Diagnostic and then merging it into []lsp.Diagnostic outside of this package only when we need to, may be safer approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we punt on that for a future PR? It helped to only work in hcl until it gets to the diagnostics notifier package. But if you felt strongly I could create a second Publish method.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I suppose it's fine - I reckon we'll need to revisit this logic soon anyway to deliver on the promise of integrating tflint and somehow more "generalizing" the interface, or at least making it extendable.

So I am fairly confident this will need to change in the future, but I'm ok with leaving it for another PR. 👌

return nil, err
}

wasInit, _ := rm.WasInitialized()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember we had a conversation about this, but what was the reasoning behind ignoring the error here? Would we not want to differentiate e.g. between a state where the module doesn't exist at all and when it exists, but isn't initialized?

Copy link
Contributor Author

@appilon appilon Dec 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there really a difference? As long as the URI is a folder, it is either initialized and a place where you can call terraform validate, or it isn't? I'm still foggy on these distinctions even after our numerous sessions 😄

Copy link
Member

@radeksimko radeksimko Dec 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, in most cases there probably won't be a difference, but that's just because we rely on the client always calling didOpen (which automatically creates/loads the parent folder as a module) on a file from any folder that we run validate on.

In theory a client might integrate the command in such a way that it allows user to run it in folders which were never opened in the editor (but may in fact be initialized, just not discovered yet?).

We should probably somehow account for this edge case and automatically load the module and make it known, but I think that raising a correct error is a solid start?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh okay makes sense now, I will raise the error

@radeksimko radeksimko added the enhancement New feature or request label Dec 8, 2020
@appilon appilon merged commit 87c4e22 into main Dec 8, 2020
@appilon appilon deleted the validate-on-save branch December 8, 2020 21:12
@appilon appilon mentioned this pull request Dec 16, 2020
@ghost
Copy link

ghost commented Jan 7, 2021

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 context necessary to investigate further.

@ghost ghost locked as resolved and limited conversation to collaborators Jan 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Validate configuration and publish diagnostics
2 participants