Skip to content

Commit 6cf9737

Browse files
authored
feat: add script processor using Tengo (#428)
- Implement a new 'script' processor with 'tengo' as the only supported script engine. - Add internal packages for translating asset proto value into map[string]interface{} and for updating asset proto value with the given map.
1 parent 6495614 commit 6cf9737

File tree

17 files changed

+1331
-8
lines changed

17 files changed

+1331
-8
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ meteor-plugin-*
3232

3333
# build
3434
/dist
35+
36+
.playground

docs/docs/reference/processors.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,18 @@ processors:
2828

2929
This processor will append Asset's Labels with value from given config.
3030

31-
[More details](https://github.com/odpf/meteor/blob/main/plugins/processors/labels/README.md)
31+
[More details][labels-readme]
32+
33+
## Script
34+
35+
Script processor uses the user specified script to transform each asset emitted
36+
from the extractor. Currently, [Tengo][tengo] is the only supported script
37+
engine.
38+
39+
[More details][script-readme]
40+
41+
[labels-readme]: https://github.com/odpf/meteor/blob/main/plugins/processors/labels/README.md
42+
43+
[script-readme]: https://github.com/odpf/meteor/blob/main/plugins/processors/script/README.md
44+
45+
[tengo]: https://github.com/d5/tengo

go.mod

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ require (
1616
github.com/benbjohnson/clock v1.3.0 // indirect
1717
github.com/blastrain/vitess-sqlparser v0.0.0-20201030050434-a139afbb1aba
1818
github.com/cenkalti/backoff/v4 v4.1.2
19+
github.com/d5/tengo/v2 v2.13.0
1920
github.com/denisenkom/go-mssqldb v0.10.0
2021
github.com/dnaeon/go-vcr/v2 v2.0.1
2122
github.com/elastic/go-elasticsearch v0.0.0
@@ -31,7 +32,9 @@ require (
3132
github.com/go-playground/validator/v10 v10.10.0
3233
github.com/go-sql-driver/mysql v1.6.0
3334
github.com/gocql/gocql v0.0.0-20210817081954-bc256bbb90de
35+
github.com/google/go-cmp v0.5.8
3436
github.com/google/go-github/v37 v37.0.0
37+
github.com/gopherjs/gopherjs v0.0.0-20210503212227-fb464eba2686 // indirect
3538
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
3639
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
3740
github.com/lib/pq v1.10.4
@@ -50,6 +53,7 @@ require (
5053
github.com/prestodb/presto-go-client v0.0.0-20211201125635-ad28cec17d6c
5154
github.com/schollz/progressbar/v3 v3.8.5
5255
github.com/segmentio/kafka-go v0.4.17
56+
github.com/sergi/go-diff v1.1.0 // indirect
5357
github.com/sijms/go-ora/v2 v2.2.22
5458
github.com/snowflakedb/gosnowflake v1.6.7
5559
github.com/spf13/cast v1.5.0 // indirect
@@ -74,8 +78,3 @@ require (
7478
gopkg.in/ini.v1 v1.66.6 // indirect
7579
gopkg.in/yaml.v3 v3.0.1
7680
)
77-
78-
require (
79-
github.com/gopherjs/gopherjs v0.0.0-20210503212227-fb464eba2686 // indirect
80-
github.com/sergi/go-diff v1.1.0 // indirect
81-
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1S
501501
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
502502
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
503503
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
504+
github.com/d5/tengo/v2 v2.13.0 h1:4pZ5mR4vjOejpp+PMeIMpjZdObK7iwWoLTpVyhT+0Jk=
505+
github.com/d5/tengo/v2 v2.13.0/go.mod h1:XRGjEs5I9jYIKTxly6HCF8oiiilk5E/RYXOZ5b0DZC8=
504506
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
505507
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
506508
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package tengoutil
2+
3+
import (
4+
"github.com/d5/tengo/v2"
5+
"github.com/d5/tengo/v2/stdlib"
6+
)
7+
8+
const (
9+
maxAllocs = 5000
10+
maxConsts = 500
11+
)
12+
13+
func NewSecureScript(input []byte) *tengo.Script {
14+
s := tengo.NewScript(input)
15+
16+
s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...))
17+
s.SetMaxAllocs(maxAllocs)
18+
s.SetMaxConstObjects(maxConsts)
19+
20+
return s
21+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//go:build plugins
2+
// +build plugins
3+
4+
package tengoutil
5+
6+
import (
7+
"testing"
8+
9+
"github.com/MakeNowJust/heredoc"
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestNewSecureScript(t *testing.T) {
14+
t.Run("Allows import of builtin modules", func(t *testing.T) {
15+
s := NewSecureScript(([]byte)(heredoc.Doc(`
16+
math := import("math")
17+
os := import("os")
18+
text := import("text")
19+
times := import("times")
20+
rand := import("rand")
21+
fmt := import("fmt")
22+
json := import("json")
23+
base64 := import("base64")
24+
hex := import("hex")
25+
enum := import("enum")
26+
`)))
27+
_, err := s.Compile()
28+
assert.NoError(t, err)
29+
})
30+
31+
t.Run("File import disallowed", func(t *testing.T) {
32+
s := NewSecureScript(([]byte)(`sum := import("./testdata/sum")`))
33+
_, err := s.Compile()
34+
assert.ErrorContains(t, err, "Compile Error: module './testdata/sum' not found")
35+
})
36+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package structmap
2+
3+
import (
4+
"fmt"
5+
6+
v1beta2 "github.com/odpf/meteor/models/odpf/assets/v1beta2"
7+
"google.golang.org/protobuf/reflect/protoregistry"
8+
"google.golang.org/protobuf/types/known/anypb"
9+
)
10+
11+
type AssetWrapper struct {
12+
A *v1beta2.Asset
13+
}
14+
15+
func (w AssetWrapper) AsMap() (map[string]interface{}, error) {
16+
v, err := AsMap(w.A)
17+
if err != nil {
18+
return nil, fmt.Errorf("structmap: asset as map: %w", err)
19+
}
20+
21+
m, ok := v.(map[string]interface{})
22+
if !ok {
23+
return nil, fmt.Errorf("structmap: asset as map: unexpected type for asset map: %T", v)
24+
}
25+
26+
return m, err
27+
}
28+
29+
func (w *AssetWrapper) OverwriteWith(m map[string]interface{}) error {
30+
dataMap, ok := m["data"].(map[string]interface{})
31+
if !ok {
32+
return fmt.Errorf("structmap: overwrite asset: unexpected type for asset data: %T", m["data"])
33+
}
34+
35+
mt, err := protoregistry.GlobalTypes.FindMessageByName(w.A.Data.MessageName())
36+
if err != nil {
37+
return fmt.Errorf("structmap: overwrite asset: resolve type by full name %s: %w", w.A.Data.MessageName(), err)
38+
}
39+
40+
msg := mt.New().Interface()
41+
delete(dataMap, "@type")
42+
if err := AsStruct(m["data"], &msg); err != nil {
43+
return fmt.Errorf("structmap: overwrite asset: decode asset data: %w", err)
44+
}
45+
46+
delete(m, "data")
47+
if err := AsStruct(m, w.A); err != nil {
48+
return fmt.Errorf("structmap: overwrite asset: decode asset: %w", err)
49+
}
50+
51+
data, err := anypb.New(msg)
52+
if err != nil {
53+
return fmt.Errorf("structmap: overwrite asset: marshal data as any: %w", err)
54+
}
55+
56+
w.A.Data = data
57+
58+
return nil
59+
}

0 commit comments

Comments
 (0)