config_reloader_test.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package config
  2. import (
  3. "os"
  4. "testing"
  5. "github.com/knadh/koanf/parsers/yaml"
  6. "github.com/knadh/koanf/providers/rawbytes"
  7. "github.com/knadh/koanf/v2"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. var stringEnvConfigYaml = `
  11. PageTitle: ${{ INPUT }}
  12. `
  13. var stringEnvInterpolationConfigYaml = `
  14. PageTitle: Olivetin - ${{ INPUT }}
  15. `
  16. var boolEnvConfigYaml = `
  17. CheckForUpdates: ${{ INPUT }}
  18. `
  19. var numericEnvConfigYaml = `
  20. LogHistoryPageSize: ${{ INPUT }}
  21. `
  22. var argsSyntaxConfigYaml = `
  23. actions:
  24. - title: Ping host
  25. id: ping_host
  26. shell: ping {{ host }} -c ${{ INPUT }}
  27. icon: ping
  28. timeout: 100
  29. popupOnStart: execution-dialog-stdout-only
  30. arguments:
  31. - name: host
  32. title: Host
  33. type: ascii_identifier
  34. default: example.com
  35. description: The host that you want to ping
  36. `
  37. func pageTitleSelector(cfg *Config) any {
  38. return cfg.PageTitle
  39. }
  40. func checkForUpdatesSelector(cfg *Config) any {
  41. return cfg.CheckForUpdates
  42. }
  43. func logHistoryPageSizeSelector(cfg *Config) any {
  44. return cfg.LogHistoryPageSize
  45. }
  46. var envConfigTests = []struct {
  47. yaml string
  48. input string
  49. output any
  50. selector func(*Config) any
  51. }{
  52. // Test that it works for string type config fields, both standalone and as part of a larger string value.
  53. {stringEnvConfigYaml, "A Nice Title", "A Nice Title", pageTitleSelector},
  54. {stringEnvInterpolationConfigYaml, "A Nice Title", "Olivetin - A Nice Title", pageTitleSelector},
  55. // Test that unset variables turn into empty strings.
  56. {stringEnvConfigYaml, "", "", pageTitleSelector},
  57. // Test that it works for bool type config fields for intuitive bool->string conversions.
  58. {boolEnvConfigYaml, "FALSE", false, checkForUpdatesSelector},
  59. {boolEnvConfigYaml, "false", false, checkForUpdatesSelector},
  60. {boolEnvConfigYaml, "False", false, checkForUpdatesSelector},
  61. {boolEnvConfigYaml, "TRUE", true, checkForUpdatesSelector},
  62. {boolEnvConfigYaml, "true", true, checkForUpdatesSelector},
  63. {boolEnvConfigYaml, "True", true, checkForUpdatesSelector},
  64. {boolEnvConfigYaml, "0", false, checkForUpdatesSelector},
  65. {boolEnvConfigYaml, "1", true, checkForUpdatesSelector},
  66. // Test that unset variables turn into false bools.
  67. {boolEnvConfigYaml, "", false, checkForUpdatesSelector},
  68. // Test that it works for numeric type config fields.
  69. {numericEnvConfigYaml, "2048", int64(2048), logHistoryPageSizeSelector},
  70. // Test that unset variables turn into zero numbers.
  71. {numericEnvConfigYaml, "", int64(0), logHistoryPageSizeSelector},
  72. // Test that it doesn't interfere with similar arguments
  73. {argsSyntaxConfigYaml, "5", "ping {{ host }} -c 5", func(cfg *Config) any {
  74. if len(cfg.Actions) > 0 {
  75. return cfg.Actions[0].Shell
  76. }
  77. return ""
  78. }},
  79. }
  80. func TestEnvInConfig(t *testing.T) {
  81. t.Skip("Skipping test in 3k")
  82. for _, tt := range envConfigTests {
  83. cfg := DefaultConfig()
  84. setIfNotEmpty("INPUT", tt.input)
  85. processed := processYamlWithEnv(tt.yaml)
  86. k, err := loadKoanf(processed)
  87. if err != nil {
  88. t.Errorf("Error loading YAML: %v", err)
  89. continue
  90. }
  91. if err := k.UnmarshalWithConf("", cfg, koanf.UnmarshalConf{
  92. Tag: "koanf",
  93. }); err != nil {
  94. t.Errorf("Error unmarshalling config: %v", err)
  95. continue
  96. }
  97. field := tt.selector(cfg)
  98. assert.Equal(t, tt.output, field, "Unmarshaled config field doesn't match expected value: env=\"%s\"", tt.input)
  99. os.Unsetenv("INPUT")
  100. }
  101. }
  102. func setIfNotEmpty(key, val string) {
  103. if val != "" {
  104. os.Setenv(key, val)
  105. }
  106. }
  107. func processYamlWithEnv(content string) string {
  108. return envRegex.ReplaceAllStringFunc(content, func(match string) string {
  109. submatches := envRegex.FindStringSubmatch(match)
  110. key := submatches[1]
  111. val, _ := os.LookupEnv(key)
  112. return val
  113. })
  114. }
  115. func loadKoanf(processed string) (*koanf.Koanf, error) {
  116. k := koanf.New(".")
  117. if err := k.Load(rawbytes.Provider([]byte(processed)), yaml.Parser()); err != nil {
  118. return nil, err
  119. }
  120. return k, nil
  121. }