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