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