|
1 | 1 | package helper
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "fmt" |
| 5 | + |
4 | 6 | "github.com/hashicorp/go-version"
|
5 | 7 | "github.com/hashicorp/hcl/v2"
|
6 | 8 | "github.com/hashicorp/hcl/v2/gohcl"
|
7 | 9 | "github.com/terraform-linters/tflint-plugin-sdk/terraform"
|
| 10 | + "github.com/terraform-linters/tflint-plugin-sdk/terraform/configs" |
8 | 11 | "github.com/terraform-linters/tflint-plugin-sdk/tflint"
|
9 | 12 | "github.com/zclconf/go-cty/cty/gocty"
|
10 | 13 | )
|
@@ -203,6 +206,74 @@ func (r *Runner) Backend() (*terraform.Backend, error) {
|
203 | 206 | return nil, nil
|
204 | 207 | }
|
205 | 208 |
|
| 209 | +// Config returns the Terraform configuration |
| 210 | +func (r *Runner) Config() (*configs.Config, error) { |
| 211 | + config := &configs.Config{ |
| 212 | + Module: &configs.Module{}, |
| 213 | + } |
| 214 | + |
| 215 | + for _, file := range r.Files { |
| 216 | + content, diags := file.Body.Content(configFileSchema) |
| 217 | + if diags.HasErrors() { |
| 218 | + return nil, diags |
| 219 | + } |
| 220 | + |
| 221 | + for _, block := range content.Blocks { |
| 222 | + switch block.Type { |
| 223 | + case "terraform": |
| 224 | + content, diags := block.Body.Content(terraformBlockSchema) |
| 225 | + if diags.HasErrors() { |
| 226 | + return nil, diags |
| 227 | + } |
| 228 | + |
| 229 | + for _, block := range content.Blocks { |
| 230 | + switch block.Type { |
| 231 | + case "backend": |
| 232 | + config.Module.Backend = &terraform.Backend{ |
| 233 | + Type: block.Labels[0], |
| 234 | + TypeRange: block.LabelRanges[0], |
| 235 | + Config: block.Body, |
| 236 | + DeclRange: block.DefRange, |
| 237 | + } |
| 238 | + case "required_providers": |
| 239 | + // TODO |
| 240 | + case "provider_meta": |
| 241 | + // TODO |
| 242 | + default: |
| 243 | + continue |
| 244 | + } |
| 245 | + } |
| 246 | + case "provider": |
| 247 | + // TODO |
| 248 | + case "variable": |
| 249 | + // TODO |
| 250 | + case "locals": |
| 251 | + // TODO |
| 252 | + case "output": |
| 253 | + // TODO |
| 254 | + case "module": |
| 255 | + call, diags := simpleDecodeModuleCallBlock(block) |
| 256 | + if diags.HasErrors() { |
| 257 | + return nil, diags |
| 258 | + } |
| 259 | + config.Module.ModuleCalls[call.Name] = call |
| 260 | + case "resource": |
| 261 | + resource, diags := simpleDecodeResouceBlock(block) |
| 262 | + if diags.HasErrors() { |
| 263 | + return nil, diags |
| 264 | + } |
| 265 | + config.Module.ManagedResources[fmt.Sprintf("%s.%s", resource.Type, resource.Name)] = resource |
| 266 | + case "data": |
| 267 | + // TODO |
| 268 | + default: |
| 269 | + continue |
| 270 | + } |
| 271 | + } |
| 272 | + } |
| 273 | + |
| 274 | + return nil, nil |
| 275 | +} |
| 276 | + |
206 | 277 | // EvaluateExpr returns a value of the passed expression.
|
207 | 278 | // Note that there is no evaluation, no type conversion, etc.
|
208 | 279 | func (r *Runner) EvaluateExpr(expr hcl.Expression, ret interface{}) error {
|
@@ -505,3 +576,65 @@ func decodeProviderConfigRef(expr hcl.Expression) (*terraform.ProviderConfigRef,
|
505 | 576 |
|
506 | 577 | return ref, nil
|
507 | 578 | }
|
| 579 | + |
| 580 | +// configFileSchema is the schema for the top-level of a config file. |
| 581 | +// @see https://github.com/hashicorp/terraform/blob/v0.13.2/configs/parser_config.go#L197-L239 |
| 582 | +var configFileSchema = &hcl.BodySchema{ |
| 583 | + Blocks: []hcl.BlockHeaderSchema{ |
| 584 | + { |
| 585 | + Type: "terraform", |
| 586 | + }, |
| 587 | + { |
| 588 | + Type: "required_providers", |
| 589 | + }, |
| 590 | + { |
| 591 | + Type: "provider", |
| 592 | + LabelNames: []string{"name"}, |
| 593 | + }, |
| 594 | + { |
| 595 | + Type: "variable", |
| 596 | + LabelNames: []string{"name"}, |
| 597 | + }, |
| 598 | + { |
| 599 | + Type: "locals", |
| 600 | + }, |
| 601 | + { |
| 602 | + Type: "output", |
| 603 | + LabelNames: []string{"name"}, |
| 604 | + }, |
| 605 | + { |
| 606 | + Type: "module", |
| 607 | + LabelNames: []string{"name"}, |
| 608 | + }, |
| 609 | + { |
| 610 | + Type: "resource", |
| 611 | + LabelNames: []string{"type", "name"}, |
| 612 | + }, |
| 613 | + { |
| 614 | + Type: "data", |
| 615 | + LabelNames: []string{"type", "name"}, |
| 616 | + }, |
| 617 | + }, |
| 618 | +} |
| 619 | + |
| 620 | +// terraformBlockSchema is the schema for a top-level "terraform" block in a configuration file. |
| 621 | +// @see https://github.com/hashicorp/terraform/blob/v0.13.2/configs/parser_config.go#L241-L261 |
| 622 | +var terraformBlockSchema = &hcl.BodySchema{ |
| 623 | + Attributes: []hcl.AttributeSchema{ |
| 624 | + {Name: "required_version"}, |
| 625 | + {Name: "experiments"}, |
| 626 | + }, |
| 627 | + Blocks: []hcl.BlockHeaderSchema{ |
| 628 | + { |
| 629 | + Type: "backend", |
| 630 | + LabelNames: []string{"type"}, |
| 631 | + }, |
| 632 | + { |
| 633 | + Type: "required_providers", |
| 634 | + }, |
| 635 | + { |
| 636 | + Type: "provider_meta", |
| 637 | + LabelNames: []string{"provider"}, |
| 638 | + }, |
| 639 | + }, |
| 640 | +} |
0 commit comments