From bf1b8223936b1217e2a5128bd537f532a58b6639 Mon Sep 17 00:00:00 2001 From: Javier Guerra Date: Wed, 21 Sep 2022 22:29:18 -0500 Subject: [PATCH 1/3] feat: add atc-router module to Lua --- go.mod | 6 +- go.sum | 13 ++- internal/vm/vm.go | 3 + internal/vm/vm_test.go | 41 +++++++ .../5.1/kong/db/schema/entities/routes.lua | 5 +- lualibs/go/atc-router/api.go | 106 ++++++++++++++++++ lualibs/go/atc-router/loader.go | 38 +++++++ patches/lua-tree.patch | 16 --- 8 files changed, 205 insertions(+), 23 deletions(-) create mode 100644 lualibs/go/atc-router/api.go create mode 100644 lualibs/go/atc-router/loader.go diff --git a/go.mod b/go.mod index 1bb3cdd..9abcb1e 100644 --- a/go.mod +++ b/go.mod @@ -3,16 +3,18 @@ module github.com/kong/goks go 1.19 require ( + github.com/gofrs/uuid v4.3.0+incompatible github.com/google/uuid v1.3.0 + github.com/kong/go-atc-router v0.0.0-20220928232922-8ca5a83e3675 github.com/layeh/gopher-json v0.0.0-20201124131017-552bb3c4c3bf github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.8.0 github.com/yuin/gluare v0.0.0-20170607022532-d7c94f1a80ed github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 ) require ( - github.com/davecgh/go-spew v1.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index bd3e373..bbf5b0f 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,28 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= +github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hbagdi/gopher-json v0.0.0-20220325165250-3030ea88774d h1:usQmJ+My7LkHpbJlTaZcdIZ6SjB14RL1K/yCTLQugwY= github.com/hbagdi/gopher-json v0.0.0-20220325165250-3030ea88774d/go.mod h1:UcFBID7OH3S2ZyMendQaeFLwqG9ViDd1n1ZkUSpHOfQ= github.com/hbagdi/gopher-lua v0.0.0-20211129210354-3e4a277fb892 h1:poeRFIafrco9L7eQC/lqfYq4npPWw0odfvRUOxHealk= github.com/hbagdi/gopher-lua v0.0.0-20211129210354-3e4a277fb892/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= +github.com/kong/go-atc-router v0.0.0-20220928232922-8ca5a83e3675 h1:CJ/J9EdninfXPPQGj4lP05o4SilJYbRhr1OFuC/6mPg= +github.com/kong/go-atc-router v0.0.0-20220928232922-8ca5a83e3675/go.mod h1:W4kR9hjkzehvSXgy3hzGfNXsnY7VA+BtKjvdVos6YuE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 h1:TToq11gyfNlrMFZiYujSekIsPd9AmsA2Bj/iv+s4JHE= github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/yuin/gluare v0.0.0-20170607022532-d7c94f1a80ed h1:I1vcLHWU9m30rA90rMrKPu0eD3NDA4FBlkB8WMaDyUw= github.com/yuin/gluare v0.0.0-20170607022532-d7c94f1a80ed/go.mod h1:9w6KSdZh23UWqOywWsRLUcJUrUNjRh4Ql3z9uVgnSP4= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/internal/vm/vm.go b/internal/vm/vm.go index 32aea26..9c7d2e3 100644 --- a/internal/vm/vm.go +++ b/internal/vm/vm.go @@ -10,6 +10,7 @@ import ( "github.com/kong/goks" "github.com/kong/goks/internal/fs" + atcrouter "github.com/kong/goks/lualibs/go/atc-router" "github.com/kong/goks/lualibs/go/ipmatcher" "github.com/kong/goks/lualibs/go/jsonschema" "github.com/kong/goks/lualibs/go/ngx" @@ -59,6 +60,8 @@ func New(opts Opts) (*VM, error) { l.PreloadModule("go.re2", gluare.Loader) l.PreloadModule("go.x509", x509.Loader) l.PreloadModule("go.jsonschema", jsonschema.Loader) + l.PreloadModule("resty.router.schema", atcrouter.SchemaLoader) + l.PreloadModule("resty.router.router", atcrouter.RouterLoader) ngx.LoadNgx(l) if err := setup(l); err != nil { diff --git a/internal/vm/vm_test.go b/internal/vm/vm_test.go index d37277c..ded749b 100644 --- a/internal/vm/vm_test.go +++ b/internal/vm/vm_test.go @@ -235,3 +235,44 @@ func TestJSONSchema(t *testing.T) { assert.Contains(t, err.Error(), "expected string") }) } + +func TestAtcRouter(t *testing.T) { + vm, err := New(Opts{}) + assert.NotNil(t, vm) + assert.NoError(t, err) + + assert.NoError(t, vm.Execute(bytes.NewBufferString(` + schema = require "resty.router.schema" + router = require "resty.router.router" + function val(atc) + local s = assert(schema.new()) + assert(s:add_field("http.host", "String")) + assert(s:add_field("net.port", "Int")) + local r = assert(router.new(s)) + return assert(r:add_matcher(0, "01e2b2ad-49be-434a-9c74-c49f8e8d52dd", atc)) + end + `), "test_atc-router")) + + t.Run("create schema object", func(t *testing.T) { + _, err := vm.CallByParams("schema.new") + assert.NoError(t, err) + }) + + t.Run("try to creeate router object", func(t *testing.T) { + _, err := vm.CallByParams("router.new") + assert.ErrorContains(t, err, "bad argument #1") + }) + + t.Run("test validation", func(t *testing.T) { + _, err := vm.CallByParams("val", `net.port == 80`) + assert.NoError(t, err) + + _, err = vm.CallByParams("val", `http.host == "80"`) + assert.NoError(t, err) + }) + + t.Run("fail validation", func(t *testing.T) { + _, err := vm.CallByParams("val", `net.port == "many"`) + assert.ErrorContains(t, err, "Type mismatch") + }) +} diff --git a/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua b/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua index da85443..db0696f 100644 --- a/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua +++ b/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua @@ -1,8 +1,9 @@ local typedefs = require("kong.db.schema.typedefs") +local atc = require("kong.router.atc") +local router = require("resty.router.router") local deprecation = require("kong.deprecation") --- ATC router is incompatible with goks -local kong_router_flavor = "traditional" +local kong_router_flavor = kong and kong.configuration and kong.configuration.router_flavor if kong_router_flavor == "expressions" then return { diff --git a/lualibs/go/atc-router/api.go b/lualibs/go/atc-router/api.go new file mode 100644 index 0000000..0322d20 --- /dev/null +++ b/lualibs/go/atc-router/api.go @@ -0,0 +1,106 @@ +package atcrouter + +import ( + "fmt" + + "github.com/gofrs/uuid" + router "github.com/kong/go-atc-router" + lua "github.com/yuin/gopher-lua" +) + +// lua: schema = new_schema() +func newSchema(l *lua.LState) int { + schemaUD := l.NewUserData() + schemaUD.Value = router.NewSchema() + schemaUD.Metatable = l.Get(lua.EnvironIndex) + + l.Push(schemaUD) + return 1 +} + +func raiseUDArgError(l *lua.LState, n int, expected string, got *lua.LUserData) { + l.ArgError(n, fmt.Sprintf("%v expected, got %T", expected, got.Value)) +} + +// lua: schema:add_field(fldname, type) +func schemaAddField(l *lua.LState) int { + const ( + schemaArgNum = 1 + fieldNameArgNum = 2 + fieldTypeArgNum = 3 + ) + + schemaUD := l.CheckUserData(schemaArgNum) + schema, ok := schemaUD.Value.(*router.Schema) + if !ok { + raiseUDArgError(l, schemaArgNum, "schema", schemaUD) + } + + fieldName := l.CheckString(fieldNameArgNum) + fieldTypeS := l.CheckString(fieldTypeArgNum) + fieldType, ok := map[string]router.FieldType{ + "String": router.String, + "IpCidr": router.IpCidr, + "IpAddr": router.IpAddr, + "Int": router.Int, + "Regex": router.Regex, + }[fieldTypeS] + if !ok { + l.RaiseError("Unknown type: %s", fieldTypeS) + } + + schema.AddField(fieldName, fieldType) + l.Push(lua.LTrue) + return 1 +} + +// lua: router = new_router(schema) +func newRouter(l *lua.LState) int { + schemaUD := l.CheckUserData(1) + schema, ok := schemaUD.Value.(*router.Schema) + if !ok { + raiseUDArgError(l, 1, "schema", schemaUD) + } + + routerUD := l.NewUserData() + routerUD.Value = router.NewRouter(schema) + routerUD.Metatable = l.Get(lua.EnvironIndex) + + l.Push(routerUD) + return 1 +} + +// lua: router:add_matcher(priority, uuid, atc) +func routerAddMatcher(l *lua.LState) int { + const ( + routerArgNum = 1 + priorityArgNum = 2 + uuidArgNum = 3 + atcArgNum = 4 + + failNumReturn = 2 + ) + + routerUD := l.CheckUserData(routerArgNum) + router, ok := routerUD.Value.(*router.Router) + if !ok { + raiseUDArgError(l, routerArgNum, "Router", routerUD) + } + priority := l.CheckInt(priorityArgNum) + idS := l.CheckString(uuidArgNum) + id, err := uuid.FromString(idS) + if err != nil { + l.ArgError(uuidArgNum, fmt.Sprintf("UUID expected, got %s", idS)) + } + atc := l.CheckString(atcArgNum) + + err = router.AddMatcher(priority, id, atc) + if err != nil { + l.Push(lua.LNil) + l.Push(lua.LString(err.Error())) + return failNumReturn + } + + l.Push(lua.LTrue) + return 1 +} diff --git a/lualibs/go/atc-router/loader.go b/lualibs/go/atc-router/loader.go new file mode 100644 index 0000000..b554723 --- /dev/null +++ b/lualibs/go/atc-router/loader.go @@ -0,0 +1,38 @@ +package atcrouter + +import lua "github.com/yuin/gopher-lua" + +func setCreator(l *lua.LState, t *lua.LTable, creatorName string) { + creator := l.GetField(t, creatorName) + if creator != lua.LNil { + submodMT := l.NewTable() + l.SetField(submodMT, "__index", t) + l.SetFEnv(creator, submodMT) + } +} + +func SchemaLoader(l *lua.LState) int { + t := l.NewTable() + l.SetFuncs(t, map[string]lua.LGFunction{ + "new": newSchema, + "add_field": schemaAddField, + }) + + setCreator(l, t, "new") + + l.Push(t) + return 1 +} + +func RouterLoader(l *lua.LState) int { + t := l.NewTable() + l.SetFuncs(t, map[string]lua.LGFunction{ + "new": newRouter, + "add_matcher": routerAddMatcher, + }) + + setCreator(l, t, "new") + + l.Push(t) + return 1 +} diff --git a/patches/lua-tree.patch b/patches/lua-tree.patch index eb93b27..f729dff 100644 --- a/patches/lua-tree.patch +++ b/patches/lua-tree.patch @@ -161,22 +161,6 @@ index a590f3f..f87343c 100644 { route = { type = "foreign", reference = "routes", default = null, on_delete = "cascade", }, }, { service = { type = "foreign", reference = "services", default = null, on_delete = "cascade", }, }, { consumer = { type = "foreign", reference = "consumers", default = null, on_delete = "cascade", }, }, -diff --git a/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua b/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua -index db0696f..da85443 100644 ---- a/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua -+++ b/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua -@@ -1,9 +1,8 @@ - local typedefs = require("kong.db.schema.typedefs") --local atc = require("kong.router.atc") --local router = require("resty.router.router") - local deprecation = require("kong.deprecation") - --local kong_router_flavor = kong and kong.configuration and kong.configuration.router_flavor -+-- ATC router is incompatible with goks -+local kong_router_flavor = "traditional" - - if kong_router_flavor == "expressions" then - return { diff --git a/lua-tree/share/lua/5.1/kong/db/schema/init.lua b/lua-tree/share/lua/5.1/kong/db/schema/init.lua index 489a666..1c660ed 100644 --- a/lua-tree/share/lua/5.1/kong/db/schema/init.lua From 5cdb995cb4b3a7642e783f97b43746ebd7c41f4a Mon Sep 17 00:00:00 2001 From: Javier Guerra Date: Fri, 30 Sep 2022 02:36:38 -0500 Subject: [PATCH 2/3] build library --- .github/workflows/test.yaml | 6 +++++- Makefile | 13 +++++++++++-- go.mod | 2 +- go.sum | 4 ++-- scripts/install-deps.sh | 6 ++++++ 5 files changed, 25 insertions(+), 6 deletions(-) create mode 100755 scripts/install-deps.sh diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d2018c1..dab7bb8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -7,7 +7,11 @@ jobs: - name: Setup go uses: actions/setup-go@v3 with: - go-version: '^1.18' + go-version: '^1.19' + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable - name: Checkout repository uses: actions/checkout@v3 - name: make install-tools diff --git a/Makefile b/Makefile index a5723d3..8043831 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ .DEFAULT_GOAL := all +LIBDIR=/usr/local/lib +DEPS=$(LIBDIR)/libatc_router.so .PHONY: gen-lua-tree gen-lua-tree: @@ -14,9 +16,16 @@ lint: all: lint test .PHONY: test -test: +test: $(DEPS) go test -race ./... .PHONY: install-tools install-tools: - ./scripts/install-tools.sh \ No newline at end of file + ./scripts/install-tools.sh + +# .PHONY: install-deps +# install-deps: $(DEPS) +# ./scripts/install-deps.sh + +$(DEPS): + ./scripts/install-deps.sh diff --git a/go.mod b/go.mod index 9abcb1e..8b065f9 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/gofrs/uuid v4.3.0+incompatible github.com/google/uuid v1.3.0 - github.com/kong/go-atc-router v0.0.0-20220928232922-8ca5a83e3675 + github.com/kong/go-atc-router v0.0.0-20220930151324-bea3d2372397 github.com/layeh/gopher-json v0.0.0-20201124131017-552bb3c4c3bf github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 github.com/stretchr/testify v1.8.0 diff --git a/go.sum b/go.sum index bbf5b0f..aef0dcd 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/hbagdi/gopher-json v0.0.0-20220325165250-3030ea88774d h1:usQmJ+My7LkH github.com/hbagdi/gopher-json v0.0.0-20220325165250-3030ea88774d/go.mod h1:UcFBID7OH3S2ZyMendQaeFLwqG9ViDd1n1ZkUSpHOfQ= github.com/hbagdi/gopher-lua v0.0.0-20211129210354-3e4a277fb892 h1:poeRFIafrco9L7eQC/lqfYq4npPWw0odfvRUOxHealk= github.com/hbagdi/gopher-lua v0.0.0-20211129210354-3e4a277fb892/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= -github.com/kong/go-atc-router v0.0.0-20220928232922-8ca5a83e3675 h1:CJ/J9EdninfXPPQGj4lP05o4SilJYbRhr1OFuC/6mPg= -github.com/kong/go-atc-router v0.0.0-20220928232922-8ca5a83e3675/go.mod h1:W4kR9hjkzehvSXgy3hzGfNXsnY7VA+BtKjvdVos6YuE= +github.com/kong/go-atc-router v0.0.0-20220930151324-bea3d2372397 h1:iTynvy5+dRzV/OiPKK/D+B6mbq/z2V4OhHcmgmBoLtk= +github.com/kong/go-atc-router v0.0.0-20220930151324-bea3d2372397/go.mod h1:W4kR9hjkzehvSXgy3hzGfNXsnY7VA+BtKjvdVos6YuE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 h1:TToq11gyfNlrMFZiYujSekIsPd9AmsA2Bj/iv+s4JHE= diff --git a/scripts/install-deps.sh b/scripts/install-deps.sh new file mode 100755 index 0000000..9fa0416 --- /dev/null +++ b/scripts/install-deps.sh @@ -0,0 +1,6 @@ +#!/bin/bash -e + +go mod tidy +go mod download + +. $(go list -m -f '{{.Dir}}' github.com/kong/go-atc-router)/build-deps.sh --build --install --rm From faaa6a714cdd8584375fa58bc7e5cd971c63ac60 Mon Sep 17 00:00:00 2001 From: Javier Guerra Date: Fri, 30 Sep 2022 10:23:36 -0500 Subject: [PATCH 3/3] cleaning diff --- .github/workflows/test.yaml | 6 +----- Makefile | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index dab7bb8..d2018c1 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -7,11 +7,7 @@ jobs: - name: Setup go uses: actions/setup-go@v3 with: - go-version: '^1.19' - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable + go-version: '^1.18' - name: Checkout repository uses: actions/checkout@v3 - name: make install-tools diff --git a/Makefile b/Makefile index 8043831..06c01ac 100644 --- a/Makefile +++ b/Makefile @@ -23,9 +23,5 @@ test: $(DEPS) install-tools: ./scripts/install-tools.sh -# .PHONY: install-deps -# install-deps: $(DEPS) -# ./scripts/install-deps.sh - $(DEPS): ./scripts/install-deps.sh