github.com/jpreese/tflint@v0.19.2-0.20200908152133-b01686250fb6/rules/awsrules/api/generator/main.go (about)

     1  // +build generators
     2  
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"path/filepath"
     8  	"sort"
     9  
    10  	"github.com/hashicorp/hcl/v2/gohcl"
    11  	"github.com/hashicorp/hcl/v2/hclparse"
    12  	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
    13  	utils "github.com/terraform-linters/tflint/rules/awsrules/generator-utils"
    14  	"github.com/terraform-providers/terraform-provider-aws/aws"
    15  )
    16  
    17  type definition struct {
    18  	Rules []rule `hcl:"rule,block"`
    19  }
    20  
    21  type rule struct {
    22  	Name         string `hcl:"name,label"`
    23  	Resource     string `hcl:"resource"`
    24  	Attribute    string `hcl:"attribute"`
    25  	SourceAction string `hcl:"source_action"`
    26  	Template     string `hcl:"template"`
    27  }
    28  
    29  type ruleMeta struct {
    30  	RuleName      string
    31  	RuleNameCC    string
    32  	ResourceType  string
    33  	AttributeName string
    34  	DataType      string
    35  	ActionName    string
    36  	Template      string
    37  }
    38  
    39  type providerMeta struct {
    40  	RuleNameCCList []string
    41  }
    42  
    43  var awsProvider = aws.Provider()
    44  
    45  func main() {
    46  	files, err := filepath.Glob("./definitions/*.hcl")
    47  	if err != nil {
    48  		panic(err)
    49  	}
    50  
    51  	providerMeta := &providerMeta{}
    52  	for _, file := range files {
    53  		parser := hclparse.NewParser()
    54  		f, diags := parser.ParseHCLFile(file)
    55  		if diags.HasErrors() {
    56  			panic(diags)
    57  		}
    58  
    59  		var def definition
    60  		diags = gohcl.DecodeBody(f.Body, nil, &def)
    61  		if diags.HasErrors() {
    62  			panic(diags)
    63  		}
    64  
    65  		for _, rule := range def.Rules {
    66  			meta := &ruleMeta{
    67  				RuleName:      rule.Name,
    68  				RuleNameCC:    utils.ToCamel(rule.Name),
    69  				ResourceType:  rule.Resource,
    70  				AttributeName: rule.Attribute,
    71  				DataType:      dataType(rule.Resource, rule.Attribute),
    72  				ActionName:    rule.SourceAction,
    73  				Template:      rule.Template,
    74  			}
    75  
    76  			utils.GenerateFile(
    77  				fmt.Sprintf("%s.go", rule.Name),
    78  				"rule.go.tmpl",
    79  				meta,
    80  			)
    81  
    82  			providerMeta.RuleNameCCList = append(providerMeta.RuleNameCCList, meta.RuleNameCC)
    83  		}
    84  	}
    85  
    86  	sort.Strings(providerMeta.RuleNameCCList)
    87  	utils.GenerateFile(
    88  		"../../provider_api.go",
    89  		"../../provider_api.go.tmpl",
    90  		providerMeta,
    91  	)
    92  }
    93  
    94  func dataType(resource, attribute string) string {
    95  	resourceSchema, ok := awsProvider.ResourcesMap[resource]
    96  	if !ok {
    97  		panic(fmt.Sprintf("resource `%s` not found in the Terraform schema", resource))
    98  	}
    99  	attrSchema, ok := resourceSchema.Schema[attribute]
   100  	if !ok {
   101  		panic(fmt.Sprintf("`%s.%s` not found in the Terraform schema", resource, attribute))
   102  	}
   103  
   104  	switch attrSchema.Type {
   105  	case schema.TypeString:
   106  		return "string"
   107  	case schema.TypeSet:
   108  		return "list"
   109  	default:
   110  		panic(fmt.Errorf("Unexpected data type: %#v", attrSchema.Type))
   111  	}
   112  }