source_file.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package config
  2. import (
  3. "github.com/knadh/koanf/v2"
  4. log "github.com/sirupsen/logrus"
  5. )
  6. const sourceFileKey = "x-olivetin-source-file"
  7. // stampSourceOnMaps sets the OliveTin source-file marker on each map in a
  8. // koanf slice value (actions or entities). Always overwrites so user-provided
  9. // x-olivetin-source-file values cannot spoof the real config path.
  10. func stampSourceOnMaps(raw any, sourceFile string) any {
  11. if sourceFile == "" {
  12. return raw
  13. }
  14. items, ok := raw.([]any)
  15. if !ok {
  16. return raw
  17. }
  18. for _, item := range items {
  19. stampSourceOnMap(item, sourceFile)
  20. }
  21. return items
  22. }
  23. func stampSourceOnMap(item any, sourceFile string) {
  24. m, ok := item.(map[string]any)
  25. if !ok {
  26. return
  27. }
  28. m[sourceFileKey] = sourceFile
  29. }
  30. func stampLoadedConfigSources(k *koanf.Koanf, configPath string) {
  31. stampConfigKey(k, "actions", configPath)
  32. stampConfigKey(k, "entities", configPath)
  33. }
  34. func stampConfigKey(k *koanf.Koanf, key, configPath string) {
  35. if err := k.Set(key, stampSourceOnMaps(k.Get(key), configPath)); err != nil {
  36. log.WithFields(log.Fields{
  37. "key": key,
  38. "configPath": configPath,
  39. }).Errorf("Failed to persist source stamps: %v", err)
  40. }
  41. }
  42. // applyStampedSourceFiles copies stamped source paths from koanf maps onto
  43. // unmarshaled actions/entities. SourceFile uses koanf:"-" so YAML cannot set it.
  44. func applyStampedSourceFiles(k *koanf.Koanf, cfg *Config) {
  45. actionPaths := stampedSourcePaths(k.Get("actions"))
  46. for i, action := range cfg.Actions {
  47. if action != nil {
  48. action.SourceFile = sourcePathAt(actionPaths, i)
  49. }
  50. }
  51. entityPaths := stampedSourcePaths(k.Get("entities"))
  52. for i, entity := range cfg.Entities {
  53. if entity != nil {
  54. entity.SourceFile = sourcePathAt(entityPaths, i)
  55. }
  56. }
  57. }
  58. func sourcePathAt(paths []string, index int) string {
  59. if index >= len(paths) {
  60. return ""
  61. }
  62. return paths[index]
  63. }
  64. func stampedSourcePaths(raw any) []string {
  65. items, ok := raw.([]any)
  66. if !ok {
  67. return nil
  68. }
  69. paths := make([]string, len(items))
  70. for i, item := range items {
  71. paths[i] = stampedSourceFromMap(item)
  72. }
  73. return paths
  74. }
  75. func stampedSourceFromMap(item any) string {
  76. m, ok := item.(map[string]any)
  77. if !ok {
  78. return ""
  79. }
  80. path, _ := m[sourceFileKey].(string)
  81. return path
  82. }