config 包

config 包利用 github.com/spf13/cobragithub.com/spf13/viper 实现了 Nirvana Command 和配置读取,为 Nirvana 服务启动提供了命令行支持。

NirvanaCommand 接口如下:

  1. // NirvanaCommand is a nirvana command.
  2. type NirvanaCommand interface {
  3. // EnablePlugin enables plugins.
  4. EnablePlugin(plugins ...Plugin) NirvanaCommand
  5. // AddOption will fill up options from flags/ENV/config after executing.
  6. // A non-empty prefix is recommended. It's used to divide option namespaces.
  7. AddOption(prefix string, options ...CustomOption) NirvanaCommand
  8. // Add adds a field by key.
  9. // If you don't have any struct to describe an option, you can use the method to
  10. // add a single field into nirvana command.
  11. // `pointer` must be a pointer to golang basic data type (e.g. *int, *string).
  12. // `key` must a config key. It's like 'nirvana.ip' and 'myconfig.name.firstName'.
  13. // The key will be converted to flag and env (e.g. --nirvana-ip and NIRVANA_IP).
  14. // If you want a short flag for the field, you can only set a one-char string.
  15. // `desc` describes the field.
  16. Add(pointer interface{}, key string, shortFlag string, desc string) NirvanaCommand
  17. // Execute runs nirvana server.
  18. Execute(descriptors ...definition.Descriptor) error
  19. // ExecuteWithConfig runs nirvana server from a custom config.
  20. ExecuteWithConfig(cfg *nirvana.Config) error
  21. // Command returns a command for command.
  22. Command(cfg *nirvana.Config) *cobra.Command
  23. // SetHook sets nirvana command hook.
  24. SetHook(hook NirvanaCommandHook)
  25. // Hook returns nirvana command hook.
  26. Hook() NirvanaCommandHook
  27. }

NirvanaCommand 扩展了 nirvana 包的插件能力:

  1. // CustomOption must be a pointer to struct.
  2. //
  3. // Here is an example:
  4. // type Option struct {
  5. // FirstName string `desc:"Desc for First Name"`
  6. // Age uint16 `desc:"Desc for Age"`
  7. // }
  8. // The struct has two fields (with prefix example):
  9. // Field Flag ENV Key (In config file)
  10. // FirstName --example-first-name EXAMPLE_FIRST_NAME example.firstName
  11. // Age --example-age EXAMPLE_AGE example.age
  12. // When you execute command with `--help`, you can see the help doc of flags and
  13. // descriptions (From field tag `desc`).
  14. //
  15. // The priority is:
  16. // Flag > ENV > Key > The value you set in option
  17. type CustomOption interface{}
  18. // Plugin is for plugins to collect configurations
  19. type Plugin interface {
  20. // Name returns plugin name.
  21. Name() string
  22. // Configure configures nirvana config via current options.
  23. Configure(cfg *nirvana.Config) error
  24. }

Nirvana Command 要求每个插件提供一个 Option,并且实现 Plugin 接口。用户在 Comamnd 中传递 Option 来启用插件,并且将插件 Option 中的公开字段根据一定的规则(规则参考上面的注释)从 flag,环境变量,配置文件中读取。这样可以方便用户通过外部选项来改变运行时的行为。

由于 Nirvana Config 服务配置的特殊性,config 包提供了一个 Option 来表达这些配置:

  1. // Option contains basic configurations of nirvana.
  2. type Option struct {
  3. // IP is the IP to listen.
  4. IP string `desc:"Nirvana server listening IP"`
  5. // Port is the port to listen.
  6. Port uint16 `desc:"Nirvana server listening Port"`
  7. // Key is private key for HTTPS.
  8. Key string `desc:"TLS private key (PEM format) for HTTPS"`
  9. // Cert is certificate for HTTPS.
  10. Cert string `desc:"TLS certificate (PEM format) for HTTPS"`
  11. }

除了插件 Option 以外,config 包会从以下文件列表中读取配置文件:

  1. 目录:
  2. ./
  3. ./config/
  4. {ExecutableFilePath}/
  5. {ExecutableFilePath}/config/
  6. /etc/nirvana/
  7. 配置文件名:
  8. nirvana.yaml
  9. nirvana.toml
  10. nirvana.json

如果读取到配置文件,那么除了使用 Option 接收配置以外,还可以通过一些帮助方法获取配置:

  1. // IsSet checks to see if the key has been set in any of the data locations.
  2. // IsSet is case-insensitive for a key
  3. func IsSet(key string) bool
  4. // Set sets the value for the key in the override regiser.
  5. // Set is case-insensitive for a key.
  6. // Will be used instead of values obtained via
  7. // flags, config file, ENV, default, or key/value store.
  8. func Set(key string, value interface{})
  9. // Get can retrieve any value given the key to use.
  10. // Get is case-insensitive for a key.
  11. // Get has the behavior of returning the value associated with the first
  12. // place from where it is set. Viper will check in the following order:
  13. // override, flag, env, config file, key/value store, default
  14. //
  15. // Get returns an interface. For a specific value use one of the Get____ methods.
  16. func Get(key string) interface{}
  17. // GetBool returns the value associated with the key as a bool.
  18. func GetBool(key string) bool
  19. // GetDuration returns the value associated with the key as a time.Duration.
  20. func GetDuration(key string) time.Duration
  21. // GetFloat32 returns the value associated with the key as a float32.
  22. func GetFloat32(key string) float32
  23. // GetFloat64 returns the value associated with the key as a float64.
  24. func GetFloat64(key string) float64
  25. // GetInt returns the value associated with the key as a int.
  26. func GetInt(key string) int
  27. // GetInt8 returns the value associated with the key as a int.
  28. func GetInt8(key string) int8
  29. // GetInt16 returns the value associated with the key as a int.
  30. func GetInt16(key string) int16
  31. // GetInt32 returns the value associated with the key as a int32.
  32. func GetInt32(key string) int32
  33. // GetInt64 returns the value associated with the key as a int64.
  34. func GetInt64(key string) int64
  35. // GetString returns the value associated with the key as a string.
  36. func GetString(key string) string
  37. // GetStringSlice returns the value associated with the key as a []string.
  38. func GetStringSlice(key string) []string
  39. // GetUint returns the value associated with the key as a uint.
  40. func GetUint(key string) uint
  41. // GetUint8 returns the value associated with the key as a uint.
  42. func GetUint8(key string) uint8
  43. // GetUint16 returns the value associated with the key as a uint.
  44. func GetUint16(key string) uint16
  45. // GetUint32 returns the value associated with the key as a uint32.
  46. func GetUint32(key string) uint32
  47. // GetUint64 returns the value associated with the key as a uint64.
  48. func GetUint64(key string) uint64

注:如果在 nirvana 包中对 Config 进行了扩展,涉及到字段的改变,也需要在这个包中修改 Option 和相应的功能。