Skip to content

Add all 16 *_by_lua_block and 9 *_by_lua directives to crossplane #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 40 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
f47eb14
WIP: Adds lua extension
ornj Apr 4, 2024
f1646e0
Adds wrapper for bufio.Scanner to track token line
ornj Apr 5, 2024
27cd56b
Pass lua-block-simple and lua-block-larger
xynicole Apr 17, 2024
ef6d6b7
WIP: Trying to fix consuming leading white space and args
ornj Apr 18, 2024
7c77289
fix "rewrite_by_lua_block"
xynicole Apr 25, 2024
69d8e51
fix if the lua token is the name of the upstream
xynicole May 6, 2024
6304b25
directive with quotes around
xynicole May 7, 2024
4f54070
add lua block simple tests for parser
xynicole May 8, 2024
26b31da
Add lua-block-larger testcase
xynicole May 8, 2024
3293b6c
Add lua-block-tricky testcase to parser_test
xynicole May 9, 2024
0e401f8
add lua validation in analyze
xynicole May 14, 2024
105372a
Fix analyze test
xynicole May 14, 2024
90f0b1f
Remove block mask from analyze
xynicole May 14, 2024
2c69e9a
Add lua block check for builder
xynicole May 14, 2024
e763d3e
fix lint errors
xynicole May 15, 2024
0acddd6
fix nosec G101 lint error
xynicole May 15, 2024
90236d9
Fix some linter error
xynicole May 20, 2024
0789aa6
Fix nextTokenIsDirective
xynicole May 22, 2024
6e54fc4
remove LexScanner
xynicole May 23, 2024
0ce75a1
Add doc strings
xynicole May 24, 2024
1d3e67d
Add ExternalBuild option
xynicole May 28, 2024
05d9e37
fix linter
xynicole May 28, 2024
c49fbd2
Fix build file
xynicole Jun 10, 2024
fbab1da
refinement and add more doc strings
xynicole Jun 10, 2024
44ab750
rename the interface
xynicole Jun 11, 2024
8e5edf6
Refactor idea to simplify interfaces
ornj Jun 11, 2024
3041f97
Refactor functional options for lex and build
ornj Jun 11, 2024
8eacf94
Adds missing docstring to lex fuction option
ornj Jun 11, 2024
fc21994
removes commented out field on Lua
ornj Jun 11, 2024
afb2858
Adds helper methods to Lua for registering
ornj Jun 11, 2024
bb0d1ab
Merge pull request #95 from ornj/ext-lua-sh
ornj Jun 11, 2024
8f9e835
resolcing linter complaints
ornj Jun 11, 2024
be0ac0a
Merge pull request #96 from nginxinc/ext-lua-lintfixes
ornj Jun 11, 2024
72b17bd
Pass directives to Lua Build
xynicole Jun 11, 2024
2ea1edb
Add more docstrings
xynicole Jun 11, 2024
54bd3b7
Fix docstrings
xynicole Jun 11, 2024
f6be787
Fix unmactched quotes
xynicole Jun 12, 2024
0f0bdd6
Add args check
xynicole Jun 12, 2024
6994fc9
Fix build return
xynicole Jun 12, 2024
6453d78
fix Magic number: 2
xynicole Jun 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -2588,54 +2588,129 @@ var LuaDirectives = map[string][]uint{
"lua_package_cpath": {
ngxHTTPMainConf | ngxConfTake1,
},
"init_by_lua": {
ngxHTTPMainConf | ngxConfTake1,
},
"init_by_lua_block": {
ngxHTTPMainConf | ngxConfTake1,
},
"init_by_lua_file": {
ngxHTTPMainConf | ngxConfTake1,
},
"init_worker_by_lua": {
ngxHTTPMainConf | ngxConfTake1,
},
"init_worker_by_lua_block": {
ngxHTTPMainConf | ngxConfTake1,
},
"init_worker_by_lua_file": {
ngxHTTPMainConf | ngxConfTake1,
},
"exit_worker_by_lua_block": {
ngxHTTPMainConf | ngxConfTake1,
},
"exit_worker_by_lua_file": {
ngxHTTPMainConf | ngxConfTake1,
},
"set_by_lua": {
ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConf2More,
},
"set_by_lua_block": {
ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake2,
},
"set_by_lua_file": {
ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConf2More,
},
"content_by_lua": {
ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"content_by_lua_block": {
ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"content_by_lua_file": {
ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"server_rewrite_by_lua_block": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
},
"server_rewrite_by_lua_file": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
},
"rewrite_by_lua": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"rewrite_by_lua_block": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"rewrite_by_lua_file": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"access_by_lua": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"access_by_lua_block": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"access_by_lua_file": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"header_filter_by_lua": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"header_filter_by_lua_block": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"header_filter_by_lua_file": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"body_filter_by_lua": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"body_filter_by_lua_block": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"body_filter_by_lua_file": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"log_by_lua": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"log_by_lua_block": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"log_by_lua_file": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1,
},
"balancer_by_lua_block": {
ngxHTTPUpsConf | ngxConfTake1,
},
"balancer_by_lua_file": {
ngxHTTPUpsConf | ngxConfTake1,
},
"lua_need_request_body": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfFlag,
},
"ssl_client_hello_by_lua_block": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
},
"ssl_client_hello_by_lua_file": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
},
"ssl_certificate_by_lua_block": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
},
"ssl_certificate_by_lua_file": {
ngxHTTPMainConf | ngxHTTPSrvConf | ngxConfTake1,
},
"ssl_session_fetch_by_lua_block": {
ngxHTTPMainConf | ngxConfTake1,
},
"ssl_session_fetch_by_lua_file": {
ngxHTTPMainConf | ngxConfTake1,
},
"ssl_session_store_by_lua_block": {
ngxHTTPMainConf | ngxConfTake1,
},
"ssl_session_store_by_lua_file": {
ngxHTTPMainConf | ngxConfTake1,
},
Expand Down
79 changes: 77 additions & 2 deletions analyze_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1984,13 +1984,13 @@ func TestAnalyze_lua(t *testing.T) {
blockCtx{"http", "location", "location if"},
false,
},
"content_by_lua_file nor ok": {
"content_by_lua_file not ok": {
&Directive{
Directive: "content_by_lua_file",
Args: []string{"foo/bar.lua"},
Line: 5,
},
blockCtx{"server"},
blockCtx{"http", "location"},
false,
},
"lua_shared_dict ok": {
Expand Down Expand Up @@ -2029,6 +2029,78 @@ func TestAnalyze_lua(t *testing.T) {
blockCtx{"http"},
true,
},
"set_by_lua ok": {
&Directive{
Directive: "set_by_lua",
Args: []string{"$res", "' return 32 + math.cos(32) '"},
Line: 5,
},
blockCtx{"http", "server"},
false,
},
"set_by_lua not ok no return value": {
&Directive{
Directive: "set_by_lua",
Args: []string{"' return 32 + math.cos(32) '"},
Line: 5,
},
blockCtx{"http", "server"},
true,
},
"set_by_lua_block ok": {
&Directive{
Directive: "set_by_lua_block",
Args: []string{"$res", "return tonumber(ngx.var.foo) + 1"},
Line: 5,
},
blockCtx{"http", "server"},
false,
},
"set_by_lua_block not ok no return value": {
&Directive{
Directive: "set_by_lua_block",
Args: []string{"return tonumber(ngx.var.foo) + 1"},
Line: 5,
},
blockCtx{"http", "server"},
true,
},
"content_by_lua ok": {
&Directive{
Directive: "content_by_lua",
Args: []string{"'ngx.say('I need no extra escaping here, for example: \r\nblah')'"},
Line: 5,
},
blockCtx{"http", "location"},
false,
},
"content_by_lua not ok stream": {
&Directive{
Directive: "content_by_lua",
Args: []string{"'ngx.say('I need no extra escaping here, for example: \r\nblah')'"},
Line: 5,
},
blockCtx{"stream"},
true,
},
"content_by_lua_block ok": {
&Directive{
Directive: "content_by_lua_block",
Args: []string{"ngx.say('I need no extra escaping here, for example: \r\nblah')"},
Line: 5,
},
blockCtx{"http", "location", "if"},
false,
},
"content_by_lua_block not ok extra argument": {
&Directive{
Directive: "content_by_lua_block",
Args: []string{"1", "ngx.say('I need no extra escaping here, for example: \r\nblah')"},
Line: 5,
},
blockCtx{"http", "location", "if"},
true,
},
}

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

if !tc.wantErr && err != nil {
Expand Down
61 changes: 57 additions & 4 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,46 @@ import (
)

type BuildOptions struct {
Indent int
Tabs bool
Header bool
Indent int
Tabs bool
Header bool
Builders []RegisterBuilder // handle specific directives
extBuilders map[string]Builder
}

// RegisterBuilder is an option that can be used to add a builder to build NGINX configuration for custom directives.
type RegisterBuilder interface {
applyBuildOptions(options *BuildOptions)
}

type registerBuilder struct {
b Builder
directives []string
}

func (rb registerBuilder) applyBuildOptions(o *BuildOptions) {
if o.extBuilders == nil {
o.extBuilders = make(map[string]Builder)
}

for _, s := range rb.directives {
o.extBuilders[s] = rb.b
}
}

// BuildWithBuilder registers a builder to build the NGINX configuration for the given directives.
func BuildWithBuilder(b Builder, directives ...string) RegisterBuilder { //nolint:ireturn
return registerBuilder{b: b, directives: directives}
}

// Builder is the interface implemented by types that can render a Directive
// as it appears in NGINX configuration files.
//
// Build writes the strings that represent the Directive and it's Block to the
// io.StringWriter returning any error encountered that caused the write to stop
// early. Build must not modify the Directive.
type Builder interface {
Build(stmt *Directive) string
}

const MaxIndent = 100
Expand Down Expand Up @@ -48,6 +85,10 @@ func BuildFiles(payload Payload, dir string, options *BuildOptions) error {
dir = cwd
}

for _, o := range options.Builders {
o.applyBuildOptions(options)
}

for _, config := range payload.Config {
path := config.File
if !filepath.IsAbs(path) {
Expand Down Expand Up @@ -96,6 +137,12 @@ func Build(w io.Writer, config Config, options *BuildOptions) error {
}
}

if options.extBuilders == nil { // might be set if using BuildFiles
for _, o := range options.Builders {
o.applyBuildOptions(options)
}
}

body := strings.Builder{}
buildBlock(&body, nil, config.Parsed, 0, 0, options)

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

func buildBlock(sb io.StringWriter, parent *Directive, block Directives, depth int, lastLine int, options *BuildOptions) {
for i, stmt := range block {
directive := Enquote(stmt.Directive)
// if the this statement is a comment on the same line as the preview, do not emit EOL for this stmt
if stmt.Line == lastLine && stmt.IsComment() {
_, _ = sb.WriteString(" #")
Expand All @@ -127,8 +175,11 @@ func buildBlock(sb io.StringWriter, parent *Directive, block Directives, depth i
if stmt.IsComment() {
_, _ = sb.WriteString("#")
_, _ = sb.WriteString(*stmt.Comment)
} else if options.extBuilders != nil {
if ext, ok := options.extBuilders[directive]; ok {
_, _ = sb.WriteString(ext.Build(stmt))
}
} else {
directive := Enquote(stmt.Directive)
_, _ = sb.WriteString(directive)

// special handling for if statements
Expand Down Expand Up @@ -159,9 +210,11 @@ func buildBlock(sb io.StringWriter, parent *Directive, block Directives, depth i
_, _ = sb.WriteString("}")
}
}

lastLine = stmt.Line
}
}

func margin(options *BuildOptions, depth int) string {
indent := depth * options.Indent
if indent < MaxIndent {
Expand Down
38 changes: 38 additions & 0 deletions build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,44 @@ var buildFixtures = []buildFixture{
},
expected: "#comment1\nuser root; #comment2 #comment3",
},
{
name: "lua block",
options: BuildOptions{Builders: []RegisterBuilder{lua.RegisterBuilder()}},
parsed: Directives{
{
Directive: "content_by_lua_block",
Line: 1,
Args: []string{"\n ngx.say(\"I need no extra escaping here, for example: \\r\\nblah\")\n "},
},
},

expected: "content_by_lua_block {\n ngx.say(\"I need no extra escaping here, for example: \\r\\nblah\")\n }",
},
{
name: "set_by_lua_block",
options: BuildOptions{Builders: []RegisterBuilder{lua.RegisterBuilder()}},
parsed: Directives{
{
Directive: "set_by_lua_block",
Line: 1,
Args: []string{"$res", " -- irregular lua block directive" +
"\n local a = 32" +
"\n local b = 56" +
"\n" +
"\n ngx.var.diff = a - b; -- write to $diff directly" +
"\n return a + b; -- return the $sum value normally" +
"\n "},
},
},

expected: "set_by_lua_block $res { -- irregular lua block directive" +
"\n local a = 32" +
"\n local b = 56" +
"\n" +
"\n ngx.var.diff = a - b; -- write to $diff directly" +
"\n return a + b; -- return the $sum value normally" +
"\n }",
},
}

func TestBuild(t *testing.T) {
Expand Down
Loading
Loading