factory.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. package logger // import "github.com/docker/docker/daemon/logger"
  2. import (
  3. "fmt"
  4. "sort"
  5. "sync"
  6. containertypes "github.com/docker/docker/api/types/container"
  7. "github.com/docker/docker/pkg/plugingetter"
  8. units "github.com/docker/go-units"
  9. "github.com/pkg/errors"
  10. )
  11. // Creator builds a logging driver instance with given context.
  12. type Creator func(Info) (Logger, error)
  13. // LogOptValidator checks the options specific to the underlying
  14. // logging implementation.
  15. type LogOptValidator func(cfg map[string]string) error
  16. type logdriverFactory struct {
  17. registry map[string]Creator
  18. optValidator map[string]LogOptValidator
  19. m sync.Mutex
  20. }
  21. func (lf *logdriverFactory) list() []string {
  22. ls := make([]string, 0, len(lf.registry))
  23. lf.m.Lock()
  24. for name := range lf.registry {
  25. ls = append(ls, name)
  26. }
  27. lf.m.Unlock()
  28. sort.Strings(ls)
  29. return ls
  30. }
  31. // ListDrivers gets the list of registered log driver names
  32. func ListDrivers() []string {
  33. return factory.list()
  34. }
  35. func (lf *logdriverFactory) register(name string, c Creator) error {
  36. registered, err := lf.driverRegistered(name)
  37. if err != nil {
  38. return err
  39. }
  40. if registered {
  41. return fmt.Errorf("logger: log driver named '%s' is already registered", name)
  42. }
  43. lf.m.Lock()
  44. lf.registry[name] = c
  45. lf.m.Unlock()
  46. return nil
  47. }
  48. func (lf *logdriverFactory) driverRegistered(name string) (bool, error) {
  49. lf.m.Lock()
  50. _, ok := lf.registry[name]
  51. lf.m.Unlock()
  52. if !ok {
  53. if pluginGetter != nil { // this can be nil when the init functions are running
  54. l, err := getPlugin(name, plugingetter.Lookup)
  55. if err != nil {
  56. return false, err
  57. }
  58. if l != nil {
  59. return true, nil
  60. }
  61. }
  62. }
  63. return ok, nil
  64. }
  65. func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidator) error {
  66. lf.m.Lock()
  67. defer lf.m.Unlock()
  68. if _, ok := lf.optValidator[name]; ok {
  69. return fmt.Errorf("logger: log validator named '%s' is already registered", name)
  70. }
  71. lf.optValidator[name] = l
  72. return nil
  73. }
  74. func (lf *logdriverFactory) get(name string) (Creator, error) {
  75. lf.m.Lock()
  76. defer lf.m.Unlock()
  77. c, ok := lf.registry[name]
  78. if ok {
  79. return c, nil
  80. }
  81. c, err := getPlugin(name, plugingetter.Acquire)
  82. return c, errors.Wrapf(err, "logger: no log driver named '%s' is registered", name)
  83. }
  84. func (lf *logdriverFactory) getLogOptValidator(name string) LogOptValidator {
  85. lf.m.Lock()
  86. defer lf.m.Unlock()
  87. c := lf.optValidator[name]
  88. return c
  89. }
  90. var factory = &logdriverFactory{registry: make(map[string]Creator), optValidator: make(map[string]LogOptValidator)} // global factory instance
  91. // RegisterLogDriver registers the given logging driver builder with given logging
  92. // driver name.
  93. func RegisterLogDriver(name string, c Creator) error {
  94. return factory.register(name, c)
  95. }
  96. // RegisterLogOptValidator registers the logging option validator with
  97. // the given logging driver name.
  98. func RegisterLogOptValidator(name string, l LogOptValidator) error {
  99. return factory.registerLogOptValidator(name, l)
  100. }
  101. // GetLogDriver provides the logging driver builder for a logging driver name.
  102. func GetLogDriver(name string) (Creator, error) {
  103. return factory.get(name)
  104. }
  105. var builtInLogOpts = map[string]bool{
  106. "mode": true,
  107. "max-buffer-size": true,
  108. }
  109. // ValidateLogOpts checks the options for the given log driver. The
  110. // options supported are specific to the LogDriver implementation.
  111. func ValidateLogOpts(name string, cfg map[string]string) error {
  112. if name == "none" {
  113. return nil
  114. }
  115. switch containertypes.LogMode(cfg["mode"]) {
  116. case containertypes.LogModeBlocking, containertypes.LogModeNonBlock, containertypes.LogModeUnset:
  117. default:
  118. return fmt.Errorf("logger: logging mode not supported: %s", cfg["mode"])
  119. }
  120. if s, ok := cfg["max-buffer-size"]; ok {
  121. if containertypes.LogMode(cfg["mode"]) != containertypes.LogModeNonBlock {
  122. return fmt.Errorf("logger: max-buffer-size option is only supported with 'mode=%s'", containertypes.LogModeNonBlock)
  123. }
  124. if _, err := units.RAMInBytes(s); err != nil {
  125. return errors.Wrap(err, "error parsing option max-buffer-size")
  126. }
  127. }
  128. if err := validateExternal(cfg); err != nil {
  129. return err
  130. }
  131. registered, err := factory.driverRegistered(name)
  132. if err != nil {
  133. return err
  134. }
  135. if !registered {
  136. return fmt.Errorf("logger: no log driver named '%s' is registered", name)
  137. }
  138. filteredOpts := make(map[string]string, len(builtInLogOpts))
  139. for k, v := range cfg {
  140. if !builtInLogOpts[k] {
  141. filteredOpts[k] = v
  142. }
  143. }
  144. validator := factory.getLogOptValidator(name)
  145. if validator != nil {
  146. return validator(filteredOpts)
  147. }
  148. return nil
  149. }