1/* 2Copyright 2021 The terraform-docs Authors. 3Licensed under the MIT license (the "License"); you may not 4use this file except in compliance with the License. 5 6You may obtain a copy of the License at the LICENSE file in 7the root directory of this source tree. 8*/ 9 10package format 11 12import ( 13 _ "embed" //nolint 14 "fmt" 15 "reflect" 16 "strings" 17 gotemplate "text/template" 18 19 "github.com/terraform-docs/terraform-docs/internal/types" 20 "github.com/terraform-docs/terraform-docs/print" 21 "github.com/terraform-docs/terraform-docs/template" 22 "github.com/terraform-docs/terraform-docs/terraform" 23) 24 25//go:embed templates/tfvars_hcl.tmpl 26var tfvarsHCLTpl []byte 27 28// tfvarsHCL represents Terraform tfvars HCL format. 29type tfvarsHCL struct { 30 *generator 31 32 config *print.Config 33 template *template.Template 34} 35 36var padding []int 37 38// NewTfvarsHCL returns new instance of TfvarsHCL. 39func NewTfvarsHCL(config *print.Config) Type { 40 tt := template.New(config, &template.Item{ 41 Name: "tfvars", 42 Text: string(tfvarsHCLTpl), 43 }) 44 tt.CustomFunc(gotemplate.FuncMap{ 45 "align": func(s string, i int) string { 46 return fmt.Sprintf("%-*s", padding[i], s) 47 }, 48 "value": func(s string) string { 49 if s == "" || s == "null" { 50 return "\"\"" 51 } 52 return s 53 }, 54 "convertToComment": func(s types.String) string { 55 return "\n# " + strings.ReplaceAll(string(s), "\n", "\n# ") 56 }, 57 "showDescription": func() bool { 58 return config.Settings.Description 59 }, 60 }) 61 62 return &tfvarsHCL{ 63 generator: newGenerator(config, false), 64 config: config, 65 template: tt, 66 } 67} 68 69// Generate a Terraform module as Terraform tfvars HCL. 70func (h *tfvarsHCL) Generate(module *terraform.Module) error { 71 alignments(module.Inputs, h.config) 72 73 rendered, err := h.template.Render("tfvars", module) 74 if err != nil { 75 return err 76 } 77 78 h.generator.funcs(withContent(strings.TrimSuffix(sanitize(rendered), "\n"))) 79 80 return nil 81} 82 83func isMultilineFormat(input *terraform.Input) bool { 84 isList := input.Type == "list" || reflect.TypeOf(input.Default).Name() == "List" 85 isMap := input.Type == "map" || reflect.TypeOf(input.Default).Name() == "Map" 86 return (isList || isMap) && input.Default.Length() > 0 87} 88 89func alignments(inputs []*terraform.Input, config *print.Config) { 90 padding = make([]int, len(inputs)) 91 maxlen := 0 92 index := 0 93 for i, input := range inputs { 94 isDescribed := config.Settings.Description && input.Description.Length() > 0 95 l := len(input.Name) 96 if isMultilineFormat(input) || isDescribed { 97 for j := index; j < i; j++ { 98 padding[j] = maxlen 99 } 100 padding[i] = l 101 maxlen = 0 102 index = i + 1 103 } else if l > maxlen { 104 maxlen = l 105 } 106 } 107 for i := index; i < len(inputs); i++ { 108 padding[i] = maxlen 109 } 110} 111 112func init() { 113 register(map[string]initializerFn{ 114 "tfvars hcl": NewTfvarsHCL, 115 }) 116} 117