Skip to content

Commit a44aa6b

Browse files
authored
Add *_by_lua_block and *_by_lua directives support to crossplane
1 parent 8b28fc1 commit a44aa6b

File tree

18 files changed

+1230
-73
lines changed

18 files changed

+1230
-73
lines changed

analyze.go

+75
Original file line numberDiff line numberDiff line change
@@ -2588,54 +2588,129 @@ var LuaDirectives = map[string][]uint{
25882588
"lua_package_cpath": {
25892589
ngxHTTPMainConf | ngxConfTake1,
25902590
},
2591+
"init_by_lua": {
2592+
ngxHTTPMainConf | ngxConfTake1,
2593+
},
2594+
"init_by_lua_block": {
2595+
ngxHTTPMainConf | ngxConfTake1,
2596+
},
25912597
"init_by_lua_file": {
25922598
ngxHTTPMainConf | ngxConfTake1,
25932599
},
2600+
"init_worker_by_lua": {
2601+
ngxHTTPMainConf | ngxConfTake1,
2602+
},
2603+
"init_worker_by_lua_block": {
2604+
ngxHTTPMainConf | ngxConfTake1,
2605+
},
25942606
"init_worker_by_lua_file": {
25952607
ngxHTTPMainConf | ngxConfTake1,
25962608
},
2609+
"exit_worker_by_lua_block": {
2610+
ngxHTTPMainConf | ngxConfTake1,
2611+
},
25972612
"exit_worker_by_lua_file": {
25982613
ngxHTTPMainConf | ngxConfTake1,
25992614
},
2615+
"set_by_lua": {
2616+
ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConf2More,
2617+
},
2618+
"set_by_lua_block": {
2619+
ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake2,
2620+
},
26002621
"set_by_lua_file": {
26012622
ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConf2More,
26022623
},
2624+
"content_by_lua": {
2625+
ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2626+
},
2627+
"content_by_lua_block": {
2628+
ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2629+
},
26032630
"content_by_lua_file": {
26042631
ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
26052632
},
2633+
"server_rewrite_by_lua_block": {
2634+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
2635+
},
26062636
"server_rewrite_by_lua_file": {
26072637
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
26082638
},
2639+
"rewrite_by_lua": {
2640+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2641+
},
2642+
"rewrite_by_lua_block": {
2643+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2644+
},
26092645
"rewrite_by_lua_file": {
26102646
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
26112647
},
2648+
"access_by_lua": {
2649+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2650+
},
2651+
"access_by_lua_block": {
2652+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2653+
},
26122654
"access_by_lua_file": {
26132655
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
26142656
},
2657+
"header_filter_by_lua": {
2658+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2659+
},
2660+
"header_filter_by_lua_block": {
2661+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2662+
},
26152663
"header_filter_by_lua_file": {
26162664
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
26172665
},
2666+
"body_filter_by_lua": {
2667+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2668+
},
2669+
"body_filter_by_lua_block": {
2670+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2671+
},
26182672
"body_filter_by_lua_file": {
26192673
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
26202674
},
2675+
"log_by_lua": {
2676+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2677+
},
2678+
"log_by_lua_block": {
2679+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
2680+
},
26212681
"log_by_lua_file": {
26222682
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
26232683
},
2684+
"balancer_by_lua_block": {
2685+
ngxHTTPUpsConf | ngxConfTake1,
2686+
},
26242687
"balancer_by_lua_file": {
26252688
ngxHTTPUpsConf | ngxConfTake1,
26262689
},
26272690
"lua_need_request_body": {
26282691
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfFlag,
26292692
},
2693+
"ssl_client_hello_by_lua_block": {
2694+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
2695+
},
26302696
"ssl_client_hello_by_lua_file": {
26312697
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
26322698
},
2699+
"ssl_certificate_by_lua_block": {
2700+
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
2701+
},
26332702
"ssl_certificate_by_lua_file": {
26342703
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
26352704
},
2705+
"ssl_session_fetch_by_lua_block": {
2706+
ngxHTTPMainConf | ngxConfTake1,
2707+
},
26362708
"ssl_session_fetch_by_lua_file": {
26372709
ngxHTTPMainConf | ngxConfTake1,
26382710
},
2711+
"ssl_session_store_by_lua_block": {
2712+
ngxHTTPMainConf | ngxConfTake1,
2713+
},
26392714
"ssl_session_store_by_lua_file": {
26402715
ngxHTTPMainConf | ngxConfTake1,
26412716
},

analyze_test.go

+77-2
Original file line numberDiff line numberDiff line change
@@ -1984,13 +1984,13 @@ func TestAnalyze_lua(t *testing.T) {
19841984
blockCtx{"http", "location", "location if"},
19851985
false,
19861986
},
1987-
"content_by_lua_file nor ok": {
1987+
"content_by_lua_file not ok": {
19881988
&Directive{
19891989
Directive: "content_by_lua_file",
19901990
Args: []string{"foo/bar.lua"},
19911991
Line: 5,
19921992
},
1993-
blockCtx{"server"},
1993+
blockCtx{"http", "location"},
19941994
false,
19951995
},
19961996
"lua_shared_dict ok": {
@@ -2029,6 +2029,78 @@ func TestAnalyze_lua(t *testing.T) {
20292029
blockCtx{"http"},
20302030
true,
20312031
},
2032+
"set_by_lua ok": {
2033+
&Directive{
2034+
Directive: "set_by_lua",
2035+
Args: []string{"$res", "' return 32 + math.cos(32) '"},
2036+
Line: 5,
2037+
},
2038+
blockCtx{"http", "server"},
2039+
false,
2040+
},
2041+
"set_by_lua not ok no return value": {
2042+
&Directive{
2043+
Directive: "set_by_lua",
2044+
Args: []string{"' return 32 + math.cos(32) '"},
2045+
Line: 5,
2046+
},
2047+
blockCtx{"http", "server"},
2048+
true,
2049+
},
2050+
"set_by_lua_block ok": {
2051+
&Directive{
2052+
Directive: "set_by_lua_block",
2053+
Args: []string{"$res", "return tonumber(ngx.var.foo) + 1"},
2054+
Line: 5,
2055+
},
2056+
blockCtx{"http", "server"},
2057+
false,
2058+
},
2059+
"set_by_lua_block not ok no return value": {
2060+
&Directive{
2061+
Directive: "set_by_lua_block",
2062+
Args: []string{"return tonumber(ngx.var.foo) + 1"},
2063+
Line: 5,
2064+
},
2065+
blockCtx{"http", "server"},
2066+
true,
2067+
},
2068+
"content_by_lua ok": {
2069+
&Directive{
2070+
Directive: "content_by_lua",
2071+
Args: []string{"'ngx.say('I need no extra escaping here, for example: \r\nblah')'"},
2072+
Line: 5,
2073+
},
2074+
blockCtx{"http", "location"},
2075+
false,
2076+
},
2077+
"content_by_lua not ok stream": {
2078+
&Directive{
2079+
Directive: "content_by_lua",
2080+
Args: []string{"'ngx.say('I need no extra escaping here, for example: \r\nblah')'"},
2081+
Line: 5,
2082+
},
2083+
blockCtx{"stream"},
2084+
true,
2085+
},
2086+
"content_by_lua_block ok": {
2087+
&Directive{
2088+
Directive: "content_by_lua_block",
2089+
Args: []string{"ngx.say('I need no extra escaping here, for example: \r\nblah')"},
2090+
Line: 5,
2091+
},
2092+
blockCtx{"http", "location", "if"},
2093+
false,
2094+
},
2095+
"content_by_lua_block not ok extra argument": {
2096+
&Directive{
2097+
Directive: "content_by_lua_block",
2098+
Args: []string{"1", "ngx.say('I need no extra escaping here, for example: \r\nblah')"},
2099+
Line: 5,
2100+
},
2101+
blockCtx{"http", "location", "if"},
2102+
true,
2103+
},
20322104
}
20332105

20342106
for name, tc := range testcases {
@@ -2037,6 +2109,9 @@ func TestAnalyze_lua(t *testing.T) {
20372109
t.Parallel()
20382110
err := analyze("nginx.conf", tc.stmt, ";", tc.ctx, &ParseOptions{
20392111
MatchFuncs: []MatchFunc{MatchLua},
2112+
LexOptions: LexOptions{
2113+
Lexers: []RegisterLexer{lua.RegisterLexer()},
2114+
},
20402115
})
20412116

20422117
if !tc.wantErr && err != nil {

build.go

+57-4
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,46 @@ import (
1818
)
1919

2020
type BuildOptions struct {
21-
Indent int
22-
Tabs bool
23-
Header bool
21+
Indent int
22+
Tabs bool
23+
Header bool
24+
Builders []RegisterBuilder // handle specific directives
25+
extBuilders map[string]Builder
26+
}
27+
28+
// RegisterBuilder is an option that can be used to add a builder to build NGINX configuration for custom directives.
29+
type RegisterBuilder interface {
30+
applyBuildOptions(options *BuildOptions)
31+
}
32+
33+
type registerBuilder struct {
34+
b Builder
35+
directives []string
36+
}
37+
38+
func (rb registerBuilder) applyBuildOptions(o *BuildOptions) {
39+
if o.extBuilders == nil {
40+
o.extBuilders = make(map[string]Builder)
41+
}
42+
43+
for _, s := range rb.directives {
44+
o.extBuilders[s] = rb.b
45+
}
46+
}
47+
48+
// BuildWithBuilder registers a builder to build the NGINX configuration for the given directives.
49+
func BuildWithBuilder(b Builder, directives ...string) RegisterBuilder { //nolint:ireturn
50+
return registerBuilder{b: b, directives: directives}
51+
}
52+
53+
// Builder is the interface implemented by types that can render a Directive
54+
// as it appears in NGINX configuration files.
55+
//
56+
// Build writes the strings that represent the Directive and it's Block to the
57+
// io.StringWriter returning any error encountered that caused the write to stop
58+
// early. Build must not modify the Directive.
59+
type Builder interface {
60+
Build(stmt *Directive) string
2461
}
2562

2663
const MaxIndent = 100
@@ -48,6 +85,10 @@ func BuildFiles(payload Payload, dir string, options *BuildOptions) error {
4885
dir = cwd
4986
}
5087

88+
for _, o := range options.Builders {
89+
o.applyBuildOptions(options)
90+
}
91+
5192
for _, config := range payload.Config {
5293
path := config.File
5394
if !filepath.IsAbs(path) {
@@ -96,6 +137,12 @@ func Build(w io.Writer, config Config, options *BuildOptions) error {
96137
}
97138
}
98139

140+
if options.extBuilders == nil { // might be set if using BuildFiles
141+
for _, o := range options.Builders {
142+
o.applyBuildOptions(options)
143+
}
144+
}
145+
99146
body := strings.Builder{}
100147
buildBlock(&body, nil, config.Parsed, 0, 0, options)
101148

@@ -110,6 +157,7 @@ func Build(w io.Writer, config Config, options *BuildOptions) error {
110157

111158
func buildBlock(sb io.StringWriter, parent *Directive, block Directives, depth int, lastLine int, options *BuildOptions) {
112159
for i, stmt := range block {
160+
directive := Enquote(stmt.Directive)
113161
// if the this statement is a comment on the same line as the preview, do not emit EOL for this stmt
114162
if stmt.Line == lastLine && stmt.IsComment() {
115163
_, _ = sb.WriteString(" #")
@@ -127,8 +175,11 @@ func buildBlock(sb io.StringWriter, parent *Directive, block Directives, depth i
127175
if stmt.IsComment() {
128176
_, _ = sb.WriteString("#")
129177
_, _ = sb.WriteString(*stmt.Comment)
178+
} else if options.extBuilders != nil {
179+
if ext, ok := options.extBuilders[directive]; ok {
180+
_, _ = sb.WriteString(ext.Build(stmt))
181+
}
130182
} else {
131-
directive := Enquote(stmt.Directive)
132183
_, _ = sb.WriteString(directive)
133184

134185
// special handling for if statements
@@ -159,9 +210,11 @@ func buildBlock(sb io.StringWriter, parent *Directive, block Directives, depth i
159210
_, _ = sb.WriteString("}")
160211
}
161212
}
213+
162214
lastLine = stmt.Line
163215
}
164216
}
217+
165218
func margin(options *BuildOptions, depth int) string {
166219
indent := depth * options.Indent
167220
if indent < MaxIndent {

build_test.go

+38
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,44 @@ var buildFixtures = []buildFixture{
258258
},
259259
expected: "#comment1\nuser root; #comment2 #comment3",
260260
},
261+
{
262+
name: "lua block",
263+
options: BuildOptions{Builders: []RegisterBuilder{lua.RegisterBuilder()}},
264+
parsed: Directives{
265+
{
266+
Directive: "content_by_lua_block",
267+
Line: 1,
268+
Args: []string{"\n ngx.say(\"I need no extra escaping here, for example: \\r\\nblah\")\n "},
269+
},
270+
},
271+
272+
expected: "content_by_lua_block {\n ngx.say(\"I need no extra escaping here, for example: \\r\\nblah\")\n }",
273+
},
274+
{
275+
name: "set_by_lua_block",
276+
options: BuildOptions{Builders: []RegisterBuilder{lua.RegisterBuilder()}},
277+
parsed: Directives{
278+
{
279+
Directive: "set_by_lua_block",
280+
Line: 1,
281+
Args: []string{"$res", " -- irregular lua block directive" +
282+
"\n local a = 32" +
283+
"\n local b = 56" +
284+
"\n" +
285+
"\n ngx.var.diff = a - b; -- write to $diff directly" +
286+
"\n return a + b; -- return the $sum value normally" +
287+
"\n "},
288+
},
289+
},
290+
291+
expected: "set_by_lua_block $res { -- irregular lua block directive" +
292+
"\n local a = 32" +
293+
"\n local b = 56" +
294+
"\n" +
295+
"\n ngx.var.diff = a - b; -- write to $diff directly" +
296+
"\n return a + b; -- return the $sum value normally" +
297+
"\n }",
298+
},
261299
}
262300

263301
func TestBuild(t *testing.T) {

0 commit comments

Comments
 (0)