Skip to content

Commit

Permalink
Added Resources & Data Sources type checking
Browse files Browse the repository at this point in the history
  • Loading branch information
juliosueiras committed Sep 18, 2019
1 parent ce56f2c commit 7d1c199
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 5 deletions.
6 changes: 5 additions & 1 deletion Plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Right now, alot of terraform state operation uses the Meta and Command UI compon

For now, try using brute force resource gather and check for types

Phase 1: Get only resources references(ex. aws_ami.test.<dynamic>)
Phase 1: Get only resources references(ex. aws_ami.test.<dynamic>) [Done]

Phase 2: Add resources types (ex. aws_ami.test.name, etc)

Phase 3: Add vars, locals, etc for error checking

Phase 4: Optimization
2 changes: 1 addition & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ with import <nixpkgs> {};

buildGoModule rec {
name = "terraform-lsp";
version = "0.0.3";
version = "0.0.6";
src = ./.;

modSha256 = "1mwhpabi7n0flw83q6850gg85c0v8b6hvyxjjglzzixjn58nmjxb";
Expand Down
69 changes: 66 additions & 3 deletions tfstructs/diags.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package tfstructs
import (
"fmt"
"github.com/hashicorp/terraform/configs"
"github.com/zclconf/go-cty/cty"
//"github.com/juliosueiras/terraform-lsp/helper"
"github.com/sourcegraph/go-lsp"
"os"
"path/filepath"
Expand All @@ -11,6 +13,7 @@ import (
func GetDiagnostics(fileName string, originalFile string) []lsp.Diagnostic {
parser := configs.NewParser(nil)
result := make([]lsp.Diagnostic, 0)
originalFileName := originalFile
if _, err := os.Stat(fileName); os.IsNotExist(err) {
return result
}
Expand Down Expand Up @@ -40,6 +43,66 @@ func GetDiagnostics(fileName string, originalFile string) []lsp.Diagnostic {
}

cfg, tfDiags := parser.LoadConfigFile(fileName)
parser.ForceFileSource(originalFileName, []byte(""))
extra, _ := parser.LoadConfigDir(filepath.Dir(originalFileName))

resourceTypes := map[string]map[string]cty.Value{}

for _, v := range extra.ManagedResources {
if resourceTypes[v.Type] == nil {
resourceTypes[v.Type] = map[string]cty.Value{}
}

resourceTypes[v.Type][v.Name] = cty.DynamicVal
}

for _, v := range cfg.ManagedResources {
if resourceTypes[v.Type] == nil {
resourceTypes[v.Type] = map[string]cty.Value{}
}

resourceTypes[v.Type][v.Name] = cty.DynamicVal
}

variables := map[string]cty.Value{
"path": cty.ObjectVal(map[string]cty.Value{
"cwd": cty.StringVal(""),
"module": cty.StringVal(""),
}),
"var": cty.DynamicVal, // Need to check for undefined vars
"module": cty.DynamicVal,
"local": cty.DynamicVal,
}

for k, v := range resourceTypes {
variables[k] = cty.ObjectVal(v)
}

dataTypes := map[string]map[string]cty.Value{}

for _, v := range extra.DataResources {
if dataTypes[v.Type] == nil {
dataTypes[v.Type] = map[string]cty.Value{}
}

dataTypes[v.Type][v.Name] = cty.DynamicVal
}

for _, v := range cfg.DataResources {
if dataTypes[v.Type] == nil {
dataTypes[v.Type] = map[string]cty.Value{}
}

dataTypes[v.Type][v.Name] = cty.DynamicVal
}

resultDataTypes := map[string]cty.Value{}

for k, v := range dataTypes {
resultDataTypes[k] = cty.ObjectVal(v)
}

variables["data"] = cty.ObjectVal(resultDataTypes)

for _, diag := range tfDiags {
result = append(result, lsp.Diagnostic{
Expand Down Expand Up @@ -85,7 +148,7 @@ func GetDiagnostics(fileName string, originalFile string) []lsp.Diagnostic {
for _, v := range cfg.ProviderConfigs {
providerType := v.Name

tfSchema := GetProviderSchema(providerType, v.Config, filepath.Dir(originalFile))
tfSchema := GetProviderSchemaForDiags(providerType, v.Config, filepath.Dir(originalFile), variables)

if tfSchema != nil {
for _, diag := range tfSchema.Diags {
Expand Down Expand Up @@ -132,7 +195,7 @@ func GetDiagnostics(fileName string, originalFile string) []lsp.Diagnostic {
providerType = v.ProviderConfigRef.Name
}

tfSchema := GetResourceSchema(resourceType, v.Config, filepath.Dir(originalFile), providerType)
tfSchema := GetResourceSchemaForDiags(resourceType, v.Config, filepath.Dir(originalFile), providerType, variables)

if tfSchema != nil {
for _, diag := range tfSchema.Diags {
Expand Down Expand Up @@ -178,7 +241,7 @@ func GetDiagnostics(fileName string, originalFile string) []lsp.Diagnostic {
providerType = v.ProviderConfigRef.Name
}

tfSchema := GetDataSourceSchema(resourceType, v.Config, filepath.Dir(originalFile), providerType)
tfSchema := GetDataSourceSchemaForDiags(resourceType, v.Config, filepath.Dir(originalFile), providerType, variables)

if tfSchema != nil {
for _, diag := range tfSchema.Diags {
Expand Down
103 changes: 103 additions & 0 deletions tfstructs/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,46 @@ func GetModuleVariables(moduleAddr string, config hcl.Body, targetDir string) (m
return t.Variables, true
}

func GetResourceSchemaForDiags(resourceType string, config hcl.Body, targetDir string, overrideProvider string, variables map[string]cty.Value) *TerraformSchema {
var provider *Client
var err error
if overrideProvider != "" {
provider, err = GetProvider(overrideProvider, targetDir)
} else {
provider, err = GetProvider(resourceType, targetDir)
}

if err != nil {
helper.DumpLog(err)
return nil
}

providerResource, err := provider.GetRawResourceTypeSchema(resourceType)
if err != nil {
helper.DumpLog(err)
provider.Kill()
return nil
}

provider.Kill()

res2 := providerResource.Block.DecoderSpec()
// Add Resources and Data Sources & Variables/Functions
scope := lang.Scope{}

res, _, diags := hcldec.PartialDecode(config, res2, &hcl.EvalContext{
// Build Full Tree
Variables: variables,
Functions: scope.Functions(),
})

return &TerraformSchema{
Schema: providerResource,
DecodedSchema: res,
Diags: diags,
}
}

func GetResourceSchema(resourceType string, config hcl.Body, targetDir string, overrideProvider string) *TerraformSchema {
var provider *Client
var err error
Expand Down Expand Up @@ -85,6 +125,42 @@ func GetResourceSchema(resourceType string, config hcl.Body, targetDir string, o
}
}

func GetDataSourceSchemaForDiags(dataSourceType string, config hcl.Body, targetDir string, overrideProvider string, variables map[string]cty.Value) *TerraformSchema {
var provider *Client
var err error
if overrideProvider != "" {
provider, err = GetProvider(overrideProvider, targetDir)
} else {
provider, err = GetProvider(dataSourceType, targetDir)
}
if err != nil {
helper.DumpLog(err)
return nil
}

providerDataSource, err := provider.GetRawDataSourceTypeSchema(dataSourceType)
if err != nil {
helper.DumpLog(err)
provider.Kill()
return nil
}

provider.Kill()

res2 := providerDataSource.Block.DecoderSpec()
scope := lang.Scope{}
res, _, diags := hcldec.PartialDecode(config, res2, &hcl.EvalContext{
Variables: variables,
Functions: scope.Functions(),
})

return &TerraformSchema{
Schema: providerDataSource,
DecodedSchema: res,
Diags: diags,
}
}

func GetDataSourceSchema(dataSourceType string, config hcl.Body, targetDir string, overrideProvider string) *TerraformSchema {
var provider *Client
var err error
Expand Down Expand Up @@ -173,6 +249,33 @@ func GetProvisionerSchema(provisionerType string, config hcl.Body, targetDir str
}
}

// Need to combine with GetProviderSchema after testing
func GetProviderSchemaForDiags(providerType string, config hcl.Body, targetDir string, variables map[string]cty.Value) *TerraformSchema {
provider, err := GetProvider(providerType, targetDir)
if err != nil {
helper.DumpLog(err)
return nil
}

providerSchema := provider.provider.GetSchema().Provider

provider.Kill()

res2 := providerSchema.Block.DecoderSpec()
scope := lang.Scope{}

res, _, diags := hcldec.PartialDecode(config, res2, &hcl.EvalContext{
Variables: variables,
Functions: scope.Functions(),
})

return &TerraformSchema{
Schema: &providerSchema,
DecodedSchema: res,
Diags: diags,
}
}

func GetProviderSchema(providerType string, config hcl.Body, targetDir string) *TerraformSchema {
provider, err := GetProvider(providerType, targetDir)
if err != nil {
Expand Down

0 comments on commit 7d1c199

Please sign in to comment.