github.com/terraform-linters/tflint-ruleset-azurerm@v0.26.0/rules/generator/main.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"go/format"
     7  	"io/ioutil"
     8  	"os"
     9  	"regexp"
    10  	"strings"
    11  	"text/template"
    12  
    13  	"github.com/dave/dst"
    14  	"github.com/dave/dst/decorator"
    15  )
    16  
    17  type metadata struct {
    18  	RuleName   string
    19  	RuleNameCC string
    20  }
    21  
    22  func main() {
    23  	buf := bufio.NewReader(os.Stdin)
    24  	fmt.Print("Rule name? (e.g. azurerm_linux_virtual_machine_invalid_size): ")
    25  	ruleName, err := buf.ReadString('\n')
    26  	if err != nil {
    27  		panic(err)
    28  	}
    29  	ruleName = strings.Trim(ruleName, "\n")
    30  
    31  	meta := &metadata{RuleNameCC: toCamelCase(ruleName), RuleName: ruleName}
    32  
    33  	GenerateFileWithLogs(fmt.Sprintf("rules/%s.go", ruleName), "rules/rule.go.tmpl", meta)
    34  	GenerateFileWithLogs(fmt.Sprintf("rules/%s_test.go", ruleName), "rules/rule_test.go.tmpl", meta)
    35  	GenerateFileWithLogs(fmt.Sprintf("docs/rules/%s.md", ruleName), "docs/rules/rule.md.tmpl", meta)
    36  
    37  	src, err := ioutil.ReadFile("rules/provider.go")
    38  	if err != nil {
    39  		panic(err)
    40  	}
    41  	dstf, err := decorator.Parse(src)
    42  	if err != nil {
    43  		panic(err)
    44  	}
    45  
    46  	dst.Inspect(dstf, func(n dst.Node) bool {
    47  		switch node := n.(type) {
    48  		case *dst.CompositeLit:
    49  			expr := &dst.CallExpr{
    50  				Fun: &dst.Ident{
    51  					Name: fmt.Sprintf("New%sRule", meta.RuleNameCC),
    52  				},
    53  			}
    54  			expr.Decs.Before = dst.NewLine
    55  			expr.Decs.After = dst.NewLine
    56  			node.Elts = append(node.Elts, expr)
    57  		}
    58  		return true
    59  	})
    60  
    61  	fset, astf, err := decorator.RestoreFile(dstf)
    62  	if err != nil {
    63  		panic(err)
    64  	}
    65  
    66  	fp, err := os.OpenFile("rules/provider.go", os.O_RDWR, 0755)
    67  	if err != nil {
    68  		panic(err)
    69  	}
    70  	if err := format.Node(fp, fset, astf); err != nil {
    71  		panic(err)
    72  	}
    73  	fmt.Println("Modified: rules/provider.go")
    74  
    75  	fmt.Println(`
    76  TODO:
    77  1. Remove all "TODO" comments from generated files.
    78  2. Write implementation of the rule.
    79  3. Add a link to the generated documentation into docs/rules/README.md`)
    80  }
    81  
    82  // GenerateFile generates a new file from the passed template and metadata
    83  func GenerateFile(fileName string, tmplName string, meta interface{}) {
    84  	file, err := os.Create(fileName)
    85  	if err != nil {
    86  		panic(err)
    87  	}
    88  
    89  	tmpl := template.Must(template.ParseFiles(tmplName))
    90  	err = tmpl.Execute(file, meta)
    91  	if err != nil {
    92  		panic(err)
    93  	}
    94  }
    95  
    96  // GenerateFileWithLogs generates a new file from the passed template and metadata
    97  // The difference from GenerateFile function is to output logs
    98  func GenerateFileWithLogs(fileName string, tmplName string, meta interface{}) {
    99  	GenerateFile(fileName, tmplName, meta)
   100  	fmt.Printf("Created: %s\n", fileName)
   101  }
   102  
   103  var heading = regexp.MustCompile("(^[A-Za-z])|_([A-Za-z])")
   104  
   105  func toCamelCase(str string) string {
   106  	exceptions := map[string]string{
   107  		"ip":  "IP",
   108  		"sql": "SQL",
   109  		"vm":  "VM",
   110  		"os":  "OS",
   111  		"id":  "ID",
   112  		"tls": "TLS",
   113  	}
   114  	parts := strings.Split(str, "_")
   115  	replaced := make([]string, len(parts))
   116  	for i, s := range parts {
   117  		conv, ok := exceptions[s]
   118  		if ok {
   119  			replaced[i] = conv
   120  		} else {
   121  			replaced[i] = s
   122  		}
   123  	}
   124  	str = strings.Join(replaced, "_")
   125  
   126  	return heading.ReplaceAllStringFunc(str, func(s string) string {
   127  		return strings.ToUpper(strings.Replace(s, "_", "", -1))
   128  	})
   129  }