krakend-ce

Форк
0
/
plugin.go 
274 строки · 6.7 Кб
1
package krakend
2

3
import (
4
	"context"
5
	"fmt"
6
	"os"
7
	"path/filepath"
8
	"regexp"
9
	"strings"
10
	"time"
11

12
	cmd "github.com/krakendio/krakend-cobra/v2"
13
	"github.com/luraproject/lura/v2/logging"
14
	proxy "github.com/luraproject/lura/v2/proxy/plugin"
15
	client "github.com/luraproject/lura/v2/transport/http/client/plugin"
16
	server "github.com/luraproject/lura/v2/transport/http/server/plugin"
17
	"github.com/spf13/cobra"
18
)
19

20
// LoadPlugins loads and registers the plugins so they can be used if enabled at the configuration
21
func LoadPlugins(folder, pattern string, logger logging.Logger) {
22
	LoadPluginsWithContext(context.Background(), folder, pattern, logger)
23
}
24

25
func LoadPluginsWithContext(ctx context.Context, folder, pattern string, logger logging.Logger) {
26
	logger.Debug("[SERVICE: Plugin Loader] Starting loading process")
27

28
	n, err := client.LoadWithLogger(
29
		folder,
30
		pattern,
31
		client.RegisterClient,
32
		logger,
33
	)
34
	logPluginLoaderErrors(logger, "[SERVICE: Executor Plugin]", n, err)
35

36
	n, err = server.LoadWithLogger(
37
		folder,
38
		pattern,
39
		server.RegisterHandler,
40
		logger,
41
	)
42
	logPluginLoaderErrors(logger, "[SERVICE: Handler Plugin]", n, err)
43

44
	n, err = proxy.LoadWithLoggerAndContext(
45
		ctx,
46
		folder,
47
		pattern,
48
		proxy.RegisterModifier,
49
		logger,
50
	)
51
	logPluginLoaderErrors(logger, "[SERVICE: Modifier Plugin]", n, err)
52

53
	logger.Debug("[SERVICE: Plugin Loader] Loading process completed")
54
}
55

56
func logPluginLoaderErrors(logger logging.Logger, tag string, n int, err error) {
57
	if err != nil {
58
		if mErrs, ok := err.(pluginLoaderErr); ok {
59
			for _, err := range mErrs.Errs() {
60
				logger.Debug(tag, err.Error())
61
			}
62
		} else {
63
			logger.Debug(tag, err.Error())
64
		}
65
	}
66
	if n > 0 {
67
		logger.Info(tag, "Total plugins loaded:", n)
68
	}
69
}
70

71
type pluginLoader struct{}
72

73
func (pluginLoader) Load(folder, pattern string, logger logging.Logger) {
74
	LoadPlugins(folder, pattern, logger)
75
}
76

77
func (pluginLoader) LoadWithContext(ctx context.Context, folder, pattern string, logger logging.Logger) {
78
	LoadPluginsWithContext(ctx, folder, pattern, logger)
79
}
80

81
type pluginLoaderErr interface {
82
	Errs() []error
83
}
84

85
var (
86
	serverExpected   bool
87
	clientExpected   bool
88
	modifierExpected bool
89

90
	testPluginCmd = &cobra.Command{
91
		Use:     "test-plugin [flags] [artifacts]",
92
		Short:   "Tests that one or more plugins are loadable into KrakenD.",
93
		Run:     testPluginFunc,
94
		Example: "krakend test-plugin -scm ./plugins/my_plugin.so ./plugins/my_other_plugin.so",
95
	}
96

97
	serverExpectedFlag   cmd.FlagBuilder
98
	clientExpectedFlag   cmd.FlagBuilder
99
	modifierExpectedFlag cmd.FlagBuilder
100

101
	reLogErrorPlugins = regexp.MustCompile(`(?m)plugin \#\d+ \(.*\): (.*)`)
102
)
103

104
func init() {
105
	serverExpectedFlag = cmd.BoolFlagBuilder(&serverExpected, "server", "s", false, "The artifact should contain a Server Plugin.")
106
	clientExpectedFlag = cmd.BoolFlagBuilder(&clientExpected, "client", "c", false, "The artifact should contain a Client Plugin.")
107
	modifierExpectedFlag = cmd.BoolFlagBuilder(&modifierExpected, "modifier", "m", false, "The artifact should contain a Req/Resp Modifier Plugin.")
108
}
109

110
func NewTestPluginCmd() cmd.Command {
111
	return cmd.NewCommand(testPluginCmd, serverExpectedFlag, clientExpectedFlag, modifierExpectedFlag)
112
}
113

114
func testPluginFunc(ccmd *cobra.Command, args []string) {
115
	if len(args) == 0 {
116
		ccmd.Println("At least one plugin is required.")
117
		os.Exit(1)
118
	}
119
	if !serverExpected && !clientExpected && !modifierExpected {
120
		ccmd.Println("You must declare the expected type of the plugin.")
121
		os.Exit(1)
122
	}
123

124
	start := time.Now()
125

126
	ctx, cancel := context.WithCancel(context.Background())
127

128
	var failed int
129
	globalOK := true
130
	for _, pluginPath := range args {
131
		f, err := os.Open(pluginPath)
132
		if os.IsNotExist(err) {
133
			ccmd.Println(fmt.Sprintf("[KO] Unable to open the plugin %s.", pluginPath))
134
			failed++
135
			globalOK = false
136
			continue
137
		}
138
		f.Close()
139

140
		name := filepath.Base(pluginPath)
141
		folder := filepath.Dir(pluginPath)
142
		ok := true
143

144
		if serverExpected {
145
			ok = checkHandlerPlugin(ccmd, folder, name) && ok
146
		}
147

148
		if modifierExpected {
149
			ok = checkModifierPlugin(ctx, ccmd, folder, name) && ok
150
		}
151

152
		if clientExpected {
153
			ok = checkClientPlugin(ccmd, folder, name) && ok
154
		}
155

156
		if !ok {
157
			failed++
158
		}
159

160
		globalOK = globalOK && ok
161
	}
162

163
	cancel()
164

165
	if !globalOK {
166
		ccmd.Println(fmt.Sprintf("[KO] %d tested plugin(s) in %s.\n%d plugin(s) failed.", len(args), time.Since(start), failed))
167
		os.Exit(1)
168
	}
169

170
	ccmd.Println(fmt.Sprintf("[OK] %d tested plugin(s) in %s", len(args), time.Since(start)))
171
}
172

173
func checkClientPlugin(ccmd *cobra.Command, folder, name string) bool {
174
	_, err := client.LoadWithLogger(
175
		folder,
176
		name,
177
		client.RegisterClient,
178
		logging.NoOp,
179
	)
180
	if err == nil {
181
		ccmd.Println(fmt.Sprintf("[OK] CLIENT\t%s", name))
182
		return true
183
	}
184

185
	var msg string
186
	if mErrs, ok := err.(pluginLoaderErr); ok {
187
		for _, err := range mErrs.Errs() {
188
			msg += err.Error()
189
		}
190
	} else {
191
		msg = err.Error()
192
	}
193

194
	if strings.Contains(msg, "symbol ClientRegisterer not found") {
195
		ccmd.Println(fmt.Sprintf("[KO] CLIENT\t%s: The plugin does not contain a ClientRegisterer.", name))
196
		return false
197
	}
198

199
	for _, match := range reLogErrorPlugins.FindAllStringSubmatch(msg, -1) {
200
		msg = match[1]
201
	}
202

203
	ccmd.Println(fmt.Sprintf("[KO] CLIENT\t%s: %s", name, msg))
204
	return false
205
}
206

207
func checkHandlerPlugin(ccmd *cobra.Command, folder, name string) bool {
208
	_, err := server.LoadWithLogger(
209
		folder,
210
		name,
211
		server.RegisterHandler,
212
		logging.NoOp,
213
	)
214
	if err == nil {
215
		ccmd.Println(fmt.Sprintf("[OK] SERVER\t%s", name))
216
		return true
217
	}
218

219
	var msg string
220
	if mErrs, ok := err.(pluginLoaderErr); ok {
221
		for _, err := range mErrs.Errs() {
222
			msg += err.Error()
223
		}
224
	} else {
225
		msg = err.Error()
226
	}
227

228
	if strings.Contains(msg, "symbol HandlerRegisterer not found") {
229
		ccmd.Println(fmt.Sprintf("[KO] SERVER\t%s: The plugin does not contain a HandlerRegisterer.", name))
230
		return false
231
	}
232

233
	for _, match := range reLogErrorPlugins.FindAllStringSubmatch(msg, -1) {
234
		msg = match[1]
235
	}
236

237
	ccmd.Println(fmt.Sprintf("[KO] SERVER\t%s: %s", name, msg))
238
	return false
239
}
240

241
func checkModifierPlugin(ctx context.Context, ccmd *cobra.Command, folder, name string) bool {
242
	_, err := proxy.LoadWithLoggerAndContext(
243
		ctx,
244
		folder,
245
		name,
246
		proxy.RegisterModifier,
247
		logging.NoOp,
248
	)
249
	if err == nil {
250
		ccmd.Println(fmt.Sprintf("[OK] MODIFIER\t%s", name))
251
		return true
252
	}
253

254
	var msg string
255
	if mErrs, ok := err.(pluginLoaderErr); ok {
256
		for _, err := range mErrs.Errs() {
257
			msg += err.Error()
258
		}
259
	} else {
260
		msg = err.Error()
261
	}
262

263
	if strings.Contains(msg, "symbol ModifierRegisterer not found") {
264
		ccmd.Println(fmt.Sprintf("[KO] MODIFIER\t%s: The plugin does not contain a ModifierRegisterer.", name))
265
		return false
266
	}
267

268
	for _, match := range reLogErrorPlugins.FindAllStringSubmatch(msg, -1) {
269
		msg = match[1]
270
	}
271

272
	ccmd.Println(fmt.Sprintf("[KO] MODIFIER\t%s: %s", name, msg))
273
	return false
274
}
275

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.