Skip to content

Commit 20a9490

Browse files
committed
Implement DSL based on goyacc
1 parent 68e8a6a commit 20a9490

File tree

8 files changed

+841
-113
lines changed

8 files changed

+841
-113
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
/confgenerator
33
/bin/
44
cover.out
5+
y.output

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ require (
118118
github.com/pion/transport/v2 v2.2.10 // indirect
119119
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
120120
github.com/prometheus/procfs v0.15.1 // indirect
121-
github.com/prometheus/prometheus v1.8.2-0.20201028100903-3245b3267b24 // indirect
121+
github.com/prometheus/prometheus v1.8.2-0.20201028100903-3245b3267b24
122122
github.com/rs/xid v1.6.0 // indirect
123123
github.com/russross/blackfriday/v2 v2.1.0 // indirect
124124
github.com/safchain/ethtool v0.3.1-0.20231027162144-83e5e0097c91 // indirect

pkg/dsl/dsl_test.go

Lines changed: 0 additions & 85 deletions
This file was deleted.

pkg/dsl/dsl.go renamed to pkg/dsl/eval.go

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,21 @@
11
package dsl
22

33
import (
4-
"github.com/netobserv/flowlogs-pipeline/pkg/api"
54
"github.com/netobserv/flowlogs-pipeline/pkg/config"
65
"github.com/netobserv/flowlogs-pipeline/pkg/utils/filters"
76
)
87

98
type Node struct {
10-
op string
11-
leaf *api.KeepEntryRule
9+
logicalOp string
1210
children []*Node
1311
predicate filters.Predicate
1412
}
1513

16-
func Parse(s string) Node {
17-
return Node{}
18-
}
19-
20-
func (n *Node) Preprocess() error {
21-
if n.leaf != nil {
22-
p, err := filters.FromKeepEntry(n.leaf)
23-
if err != nil {
24-
return err
25-
}
26-
n.predicate = p
27-
return nil
28-
}
29-
for _, child := range n.children {
30-
err := child.Preprocess()
31-
if err != nil {
32-
return err
33-
}
34-
}
35-
return nil
36-
}
37-
3814
func (n *Node) Apply(flow config.GenericMap) bool {
39-
if n.leaf != nil {
15+
if n.predicate != nil {
4016
return n.predicate(flow)
4117
}
42-
if n.op == "and" {
18+
if n.logicalOp == OperatorAnd {
4319
for _, child := range n.children {
4420
if !child.Apply(flow) {
4521
return false

pkg/dsl/eval_test.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package dsl
2+
3+
import (
4+
"testing"
5+
6+
"github.com/netobserv/flowlogs-pipeline/pkg/config"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestAndOrEqual(t *testing.T) {
11+
yyErrorVerbose = true
12+
n, err := Parse(`(srcnamespace="netobserv" OR (srcnamespace="ingress" AND dstnamespace="netobserv")) AND srckind!="service"`)
13+
assert.NoError(t, err)
14+
assert.NotNil(t, n)
15+
16+
result := n.Apply(config.GenericMap{
17+
"srcnamespace": "plop",
18+
"dstnamespace": "netobserv",
19+
"srckind": "pod",
20+
})
21+
assert.False(t, result)
22+
23+
result = n.Apply(config.GenericMap{
24+
"srcnamespace": "ingress",
25+
"dstnamespace": "netobserv",
26+
"srckind": "pod",
27+
})
28+
assert.True(t, result)
29+
30+
result = n.Apply(config.GenericMap{
31+
"srcnamespace": "ingress",
32+
"dstnamespace": "netobserv",
33+
"srckind": "service",
34+
})
35+
assert.False(t, result)
36+
}
37+
38+
func TestRegexp(t *testing.T) {
39+
yyErrorVerbose = true
40+
n, err := Parse(`srcnamespace=~"openshift.*" and dstnamespace!~"openshift.*"`)
41+
assert.NoError(t, err)
42+
assert.NotNil(t, n)
43+
44+
result := n.Apply(config.GenericMap{
45+
"srcnamespace": "openshift-ingress",
46+
"dstnamespace": "my-app",
47+
"srckind": "pod",
48+
})
49+
assert.True(t, result, "Should accept flows from OpenShift to App")
50+
51+
result = n.Apply(config.GenericMap{
52+
"srcnamespace": "my-app",
53+
"dstnamespace": "openshift-ingress",
54+
"srckind": "pod",
55+
})
56+
assert.False(t, result, "Should reject flows from App to OpenShift")
57+
58+
result = n.Apply(config.GenericMap{
59+
"srcnamespace": "my-app",
60+
"dstnamespace": "my-app",
61+
"srckind": "pod",
62+
})
63+
assert.False(t, result, "Should reject flows from App to App")
64+
65+
result = n.Apply(config.GenericMap{
66+
"srcnamespace": "openshift-operators",
67+
"dstnamespace": "openshift-ingress",
68+
"srckind": "pod",
69+
})
70+
assert.False(t, result, "Should reject flows from OpenShift to OpenShift")
71+
}
72+
73+
func TestWith(t *testing.T) {
74+
yyErrorVerbose = true
75+
n, err := Parse(`srcnamespace="foo" and with(rtt)`)
76+
assert.NoError(t, err)
77+
assert.NotNil(t, n)
78+
79+
result := n.Apply(config.GenericMap{
80+
"srcnamespace": "foo",
81+
"rtt": 4.5,
82+
})
83+
assert.True(t, result, "Should accept flows from foo with rtt")
84+
85+
result = n.Apply(config.GenericMap{
86+
"srcnamespace": "foo",
87+
})
88+
assert.False(t, result, "Should reject flows from foo without rtt")
89+
}
90+
91+
func TestWithout(t *testing.T) {
92+
yyErrorVerbose = true
93+
n, err := Parse(`srcnamespace="foo" or without(srcnamespace)`)
94+
assert.NoError(t, err)
95+
assert.NotNil(t, n)
96+
97+
result := n.Apply(config.GenericMap{
98+
"srcnamespace": "foo",
99+
})
100+
assert.True(t, result, "Should accept flows from foo")
101+
102+
result = n.Apply(config.GenericMap{})
103+
assert.True(t, result, "Should accept flows without srcnamespace")
104+
105+
result = n.Apply(config.GenericMap{
106+
"srcnamespace": "bar",
107+
})
108+
assert.False(t, result, "Should reject flows from bar")
109+
}

pkg/dsl/expr.y

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
%{
2+
package dsl
3+
%}
4+
5+
%union{
6+
expr Expression
7+
value string
8+
}
9+
10+
%type <expr> root
11+
%type <expr> expr
12+
13+
%token <value> VAR STRING NUMBER AND OR EQ NEQ REG NREG OPEN_PARENTHESIS CLOSE_PARENTHESIS WITH WITHOUT
14+
%left AND
15+
%left OR
16+
%%
17+
18+
root:
19+
expr {
20+
$$ = $1
21+
yylex.(*Lexer).result = $$
22+
}
23+
24+
expr:
25+
OPEN_PARENTHESIS expr CLOSE_PARENTHESIS { $$ = ParenthesisExpr{inner: $2} }
26+
| expr AND expr { $$ = LogicalExpr{left: $1, operator: "and", right: $3} }
27+
| expr OR expr { $$ = LogicalExpr{left: $1, operator: "or", right: $3} }
28+
| WITH OPEN_PARENTHESIS VAR CLOSE_PARENTHESIS { $$ = WithExpr{key: $3} }
29+
| WITHOUT OPEN_PARENTHESIS VAR CLOSE_PARENTHESIS { $$ = WithoutExpr{key: $3} }
30+
| VAR EQ STRING { $$ = ComparisonExpr{key: $1, operator: "=", value: $3} }
31+
| VAR NEQ STRING { $$ = ComparisonExpr{key: $1, operator: "!=", value: $3} }
32+
| VAR REG STRING { $$ = ComparisonExpr{key: $1, operator: "=~", value: $3} }
33+
| VAR NREG STRING { $$ = ComparisonExpr{key: $1, operator: "!~", value: $3} }
34+
%%

0 commit comments

Comments
 (0)