plugin.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package logger // import "github.com/docker/docker/daemon/logger"
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "path/filepath"
  7. "github.com/docker/docker/api/types/plugins/logdriver"
  8. "github.com/docker/docker/errdefs"
  9. getter "github.com/docker/docker/pkg/plugingetter"
  10. "github.com/docker/docker/pkg/plugins"
  11. "github.com/docker/docker/pkg/stringid"
  12. "github.com/pkg/errors"
  13. )
  14. var pluginGetter getter.PluginGetter
  15. const extName = "LogDriver"
  16. // logPlugin defines the available functions that logging plugins must implement.
  17. type logPlugin interface {
  18. StartLogging(streamPath string, info Info) (err error)
  19. StopLogging(streamPath string) (err error)
  20. Capabilities() (cap Capability, err error)
  21. ReadLogs(info Info, config ReadConfig) (stream io.ReadCloser, err error)
  22. }
  23. // RegisterPluginGetter sets the plugingetter
  24. func RegisterPluginGetter(plugingetter getter.PluginGetter) {
  25. pluginGetter = plugingetter
  26. }
  27. // getPlugin returns a logging driver by its name.
  28. // If the driver is empty, it looks for the local driver.
  29. func getPlugin(name string, mode int) (Creator, error) {
  30. p, err := pluginGetter.Get(name, extName, mode)
  31. if err != nil {
  32. return nil, fmt.Errorf("error looking up logging plugin %s: %v", name, err)
  33. }
  34. client, err := makePluginClient(p)
  35. if err != nil {
  36. return nil, err
  37. }
  38. return makePluginCreator(name, client, p.ScopedPath), nil
  39. }
  40. func makePluginClient(p getter.CompatPlugin) (logPlugin, error) {
  41. if pc, ok := p.(getter.PluginWithV1Client); ok {
  42. return &logPluginProxy{pc.Client()}, nil
  43. }
  44. pa, ok := p.(getter.PluginAddr)
  45. if !ok {
  46. return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", p))
  47. }
  48. if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
  49. return nil, errors.Errorf("plugin protocol not supported: %s", p)
  50. }
  51. addr := pa.Addr()
  52. c, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout())
  53. if err != nil {
  54. return nil, errors.Wrap(err, "error making plugin client")
  55. }
  56. return &logPluginProxy{c}, nil
  57. }
  58. func makePluginCreator(name string, l logPlugin, scopePath func(s string) string) Creator {
  59. return func(logCtx Info) (logger Logger, err error) {
  60. defer func() {
  61. if err != nil {
  62. pluginGetter.Get(name, extName, getter.Release)
  63. }
  64. }()
  65. unscopedPath := filepath.Join("/", "run", "docker", "logging")
  66. logRoot := scopePath(unscopedPath)
  67. if err := os.MkdirAll(logRoot, 0o700); err != nil {
  68. return nil, err
  69. }
  70. id := stringid.GenerateRandomID()
  71. a := &pluginAdapter{
  72. driverName: name,
  73. id: id,
  74. plugin: l,
  75. fifoPath: filepath.Join(logRoot, id),
  76. logInfo: logCtx,
  77. }
  78. cap, err := a.plugin.Capabilities()
  79. if err == nil {
  80. a.capabilities = cap
  81. }
  82. stream, err := openPluginStream(a)
  83. if err != nil {
  84. return nil, err
  85. }
  86. a.stream = stream
  87. a.enc = logdriver.NewLogEntryEncoder(a.stream)
  88. if err := l.StartLogging(filepath.Join(unscopedPath, id), logCtx); err != nil {
  89. return nil, errors.Wrapf(err, "error creating logger")
  90. }
  91. if cap.ReadLogs {
  92. return &pluginAdapterWithRead{a}, nil
  93. }
  94. return a, nil
  95. }
  96. }