Skip to content

Instantly share code, notes, and snippets.

@pj
Created August 25, 2022 02:57
Show Gist options
  • Save pj/687745e85f4d5ed104b292cebd1cd426 to your computer and use it in GitHub Desktop.
Save pj/687745e85f4d5ed104b292cebd1cd426 to your computer and use it in GitHub Desktop.
Simple go program for generating terraform variables.tf files from cue definitions.
// Apply @generate_terraform_variables(filename="variables.tf") to a definition you want to output as a variables file.
package main
import (
"fmt"
"os"
"strings"
"text/template"
"cuelang.org/go/cue"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/load"
)
const VARIABLES_TEMPLATE = `
variable "{{ .Name }}" {
type = "{{ .Type }}"
{{- if .Default }}
default = {{ .Default }}
{{- end}}
}
`
type VariableDetails struct {
Type string
Default string
Name string
}
func getType(val cue.Value) (string, error) {
asdf := fmt.Sprintf("%v", val)
switch asdf {
case "string":
return "string", nil
case "int":
return "number", nil
case "float":
return "number", nil
case "bool":
return "boolean", nil
default:
return "", fmt.Errorf("Unknown type: %s", asdf)
}
}
func outputVariables(val cue.Value) error {
if val.Kind() == cue.StructKind {
iterator, err := val.Fields(cue.Definitions(true))
if err != nil {
return err
}
for iterator.Next() {
definition := iterator.Value()
att := definition.Attributes(cue.FieldAttr)
for _, x := range att {
if x.Name() == "generate_terraform_variables" {
var builder strings.Builder
builder.WriteString("// Generated by Cue\n")
template := template.New("generate_terraform_variables")
template.Parse(VARIABLES_TEMPLATE)
fieldIterator, err := definition.Fields(cue.Optional(true))
if err != nil {
return err
}
for fieldIterator.Next() {
field := fieldIterator.Value()
label, _ := field.Label()
kind, err := getType(field)
if err != nil {
return err
}
details := VariableDetails{
Name: label,
Type: kind,
}
template.Execute(&builder, details)
}
filename, found, err := x.Lookup(0, "filename")
if err != nil {
return err
}
if !found {
return fmt.Errorf("filename not found")
}
file, err := os.Create(filename)
if err != nil {
return err
}
file.WriteString(builder.String())
}
}
}
}
return nil
}
func main() {
c := cuecontext.New()
instances := load.Instances([]string{}, &load.Config{Module: "lazytest.io/config", Package: "config"})
for _, bi := range instances {
if bi.Err != nil {
fmt.Println("Error during load:", bi.Err)
continue
}
value := c.BuildInstance(bi)
if value.Err() != nil {
fmt.Println("Error during build:", value.Err())
continue
}
err := outputVariables(value)
if err != nil {
fmt.Printf("Error: %v", err)
os.Exit(1)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment