main.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // This program generates env config scripts from config.Config struct tags for
  2. // unix and windows platforms.
  3. // Usage: go run ./cmd/config_generator [platform] [filename] [value_tag]
  4. // Example: go run ./cmd/config_generator unix settings.basic.env basic
  5. package main
  6. import (
  7. "fmt"
  8. "io"
  9. "os"
  10. "reflect"
  11. "strings"
  12. "github.com/mk6i/open-oscar-server/config"
  13. "github.com/mitchellh/go-wordwrap"
  14. )
  15. var platformKeywords = map[string]struct {
  16. comment string
  17. assignment string
  18. }{
  19. "windows": {
  20. comment: "rem ",
  21. assignment: "set ",
  22. },
  23. "unix": {
  24. comment: "# ",
  25. assignment: "export ",
  26. },
  27. }
  28. func main() {
  29. args := os.Args[1:]
  30. if len(args) < 3 {
  31. fmt.Fprintln(os.Stderr, "usage: go run cmd/config_generator [platform] [filename] [value_tag]")
  32. os.Exit(1)
  33. }
  34. platform := args[0]
  35. filename := args[1]
  36. valueTag := args[2] // e.g., "basic", "ssl"
  37. keywords, ok := platformKeywords[platform]
  38. if !ok {
  39. fmt.Fprintf(os.Stderr, "unable to find platform `%s`\n", platform)
  40. os.Exit(1)
  41. }
  42. fmt.Println("writing to", filename)
  43. f, err := os.Create(filename)
  44. if err != nil {
  45. fmt.Fprintf(os.Stderr, "error creating file: %s\n", err.Error())
  46. os.Exit(1)
  47. }
  48. defer func() { _ = f.Close() }()
  49. configType := reflect.TypeOf(config.Config{})
  50. writeFields(f, configType, valueTag, keywords)
  51. }
  52. func writeFields(f *os.File, t reflect.Type, valueTag string, keywords struct {
  53. comment string
  54. assignment string
  55. }) {
  56. for i := 0; i < t.NumField(); i++ {
  57. field := t.Field(i)
  58. // Recurse into nested structs
  59. if field.Type.Kind() == reflect.Struct && field.Tag.Get("envconfig") == "" {
  60. writeFields(f, field.Type, valueTag, keywords)
  61. continue
  62. }
  63. // Check if field is optional and has empty value
  64. required := field.Tag.Get("required")
  65. val := field.Tag.Get(valueTag)
  66. // Skip optional fields with empty values
  67. if required == "false" && val == "" {
  68. continue
  69. }
  70. comment := field.Tag.Get("description")
  71. if err := writeComment(f, comment, 80, keywords.comment); err != nil {
  72. fmt.Fprintf(os.Stderr, "error writing to file: %s\n", err.Error())
  73. os.Exit(1)
  74. }
  75. varName := field.Tag.Get("envconfig")
  76. if err := writeAssignment(f, keywords.assignment, varName, val); err != nil {
  77. fmt.Fprintf(os.Stderr, "error writing to file: %s\n", err.Error())
  78. os.Exit(1)
  79. }
  80. }
  81. }
  82. func writeComment(w io.Writer, comment string, width uint, keyword string) error {
  83. // adjust wrapping threshold to accommodate comment keyword length
  84. width = width - uint(len(keyword))
  85. comment = wordwrap.WrapString(comment, width)
  86. // prepend lines with comment keyword
  87. comment = strings.ReplaceAll(comment, "\n", fmt.Sprintf("\n%s", keyword))
  88. _, err := fmt.Fprintf(w, "%s%s\n", keyword, comment)
  89. return err
  90. }
  91. func writeAssignment(w io.Writer, keyword string, varName string, val string) error {
  92. _, err := fmt.Fprintf(w, "%s%s=%s\n\n", keyword, varName, val)
  93. return err
  94. }