config_loader.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. package cmd
  2. import (
  3. "fmt"
  4. "github.com/urfave/cli/v2"
  5. "github.com/urfave/cli/v2/altsrc"
  6. "gopkg.in/yaml.v2"
  7. "heckel.io/ntfy/util"
  8. "os"
  9. )
  10. // initConfigFileInputSourceFunc is like altsrc.InitInputSourceWithContext and altsrc.NewYamlSourceFromFlagFunc, but checks
  11. // if the config flag is exists and only loads it if it does. If the flag is set and the file exists, it fails.
  12. func initConfigFileInputSourceFunc(configFlag string, flags []cli.Flag) cli.BeforeFunc {
  13. return func(context *cli.Context) error {
  14. configFile := context.String(configFlag)
  15. if context.IsSet(configFlag) && !util.FileExists(configFile) {
  16. return fmt.Errorf("config file %s does not exist", configFile)
  17. } else if !context.IsSet(configFlag) && !util.FileExists(configFile) {
  18. return nil
  19. }
  20. inputSource, err := newYamlSourceFromFile(configFile, flags)
  21. if err != nil {
  22. return err
  23. }
  24. return altsrc.ApplyInputSourceValues(context, inputSource, flags)
  25. }
  26. }
  27. // newYamlSourceFromFile creates a new Yaml InputSourceContext from a filepath.
  28. //
  29. // This function also maps aliases, so a .yml file can contain short options, or options with underscores
  30. // instead of dashes. See https://github.com/binwiederhier/ntfy/issues/255.
  31. func newYamlSourceFromFile(file string, flags []cli.Flag) (altsrc.InputSourceContext, error) {
  32. var rawConfig map[interface{}]interface{}
  33. b, err := os.ReadFile(file)
  34. if err != nil {
  35. return nil, err
  36. }
  37. if err := yaml.Unmarshal(b, &rawConfig); err != nil {
  38. return nil, err
  39. }
  40. for _, f := range flags {
  41. flagName := f.Names()[0]
  42. for _, flagAlias := range f.Names()[1:] {
  43. if _, ok := rawConfig[flagAlias]; ok {
  44. rawConfig[flagName] = rawConfig[flagAlias]
  45. }
  46. }
  47. }
  48. return altsrc.NewMapInputSource(file, rawConfig), nil
  49. }