Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Ijaz Ahmad
ksonnet
Commits
25395ed0
Unverified
Commit
25395ed0
authored
May 08, 2018
by
Bryan Liles
Committed by
GitHub
May 08, 2018
Browse files
Merge pull request #521 from bryanl/reintroduce-native-funcs
Make native funcs available for components
parents
c904092f
0bfb8d40
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
290 additions
and
0 deletions
+290
-0
pkg/util/jsonnet/vm.go
pkg/util/jsonnet/vm.go
+90
-0
pkg/util/jsonnet/vm_test.go
pkg/util/jsonnet/vm_test.go
+200
-0
No files found.
pkg/util/jsonnet/vm.go
View file @
25395ed0
...
...
@@ -16,15 +16,21 @@
package
jsonnet
import
(
"bytes"
"encoding/json"
"fmt"
"io"
"path/filepath"
"regexp"
"strings"
"time"
"github.com/google/go-jsonnet"
"github.com/google/go-jsonnet/ast"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/afero"
"k8s.io/apimachinery/pkg/util/yaml"
)
type
makeVMFn
func
()
*
jsonnet
.
VM
...
...
@@ -111,6 +117,7 @@ func (vm *VM) EvaluateSnippet(name, snippet string) (string, error) {
jvm
:=
jsonnet
.
MakeVM
()
jvm
.
ErrorFormatter
.
SetMaxStackTraceSize
(
40
)
registerNativeFuncs
(
jvm
)
importer
,
err
:=
vm
.
createImporter
()
if
err
!=
nil
{
return
""
,
errors
.
Wrap
(
err
,
"create jsonnet importer"
)
...
...
@@ -197,3 +204,86 @@ func (vm *VM) readString(path string) (string, error) {
return
string
(
b
),
nil
}
func
registerNativeFuncs
(
vm
*
jsonnet
.
VM
)
{
// NOTE: jsonnet native functions can only pass primitive
// types, so some functions json-encode the arg. These
// "*FromJson" functions will be replaced by regular native
// version when jsonnet is able to support this.
vm
.
NativeFunction
(
&
jsonnet
.
NativeFunction
{
Name
:
"parseJson"
,
Params
:
ast
.
Identifiers
{
"json"
},
Func
:
parseJSON
,
})
vm
.
NativeFunction
(
&
jsonnet
.
NativeFunction
{
Name
:
"parseYaml"
,
Params
:
ast
.
Identifiers
{
"yaml"
},
Func
:
parseYAML
,
})
vm
.
NativeFunction
(
&
jsonnet
.
NativeFunction
{
Name
:
"escapeStringRegex"
,
Params
:
ast
.
Identifiers
{
"str"
},
Func
:
escapeStringRegex
,
})
vm
.
NativeFunction
(
&
jsonnet
.
NativeFunction
{
Name
:
"regexMatch"
,
Params
:
ast
.
Identifiers
{
"regex"
,
"string"
},
Func
:
regexMatch
,
})
vm
.
NativeFunction
(
&
jsonnet
.
NativeFunction
{
Name
:
"regexSubst"
,
Params
:
ast
.
Identifiers
{
"regex"
,
"src"
,
"repl"
},
Func
:
regexSubst
,
})
}
func
regexSubst
(
data
[]
interface
{})
(
interface
{},
error
)
{
regex
,
src
,
repl
:=
data
[
0
]
.
(
string
),
data
[
1
]
.
(
string
),
data
[
2
]
.
(
string
)
r
,
err
:=
regexp
.
Compile
(
regex
)
if
err
!=
nil
{
return
""
,
err
}
return
r
.
ReplaceAllString
(
src
,
repl
),
nil
}
func
regexMatch
(
s
[]
interface
{})
(
interface
{},
error
)
{
return
regexp
.
MatchString
(
s
[
0
]
.
(
string
),
s
[
1
]
.
(
string
))
}
func
escapeStringRegex
(
s
[]
interface
{})
(
interface
{},
error
)
{
return
regexp
.
QuoteMeta
(
s
[
0
]
.
(
string
)),
nil
}
func
parseYAML
(
dataString
[]
interface
{})
(
interface
{},
error
)
{
data
:=
[]
byte
(
dataString
[
0
]
.
(
string
))
ret
:=
[]
interface
{}{}
d
:=
yaml
.
NewYAMLToJSONDecoder
(
bytes
.
NewReader
(
data
))
for
{
var
doc
interface
{}
if
err
:=
d
.
Decode
(
&
doc
);
err
!=
nil
{
if
err
==
io
.
EOF
{
break
}
return
nil
,
err
}
ret
=
append
(
ret
,
doc
)
}
return
ret
,
nil
}
func
parseJSON
(
dataString
[]
interface
{})
(
res
interface
{},
err
error
)
{
data
:=
[]
byte
(
dataString
[
0
]
.
(
string
))
err
=
json
.
Unmarshal
(
data
,
&
res
)
return
}
pkg/util/jsonnet/vm_test.go
View file @
25395ed0
...
...
@@ -101,3 +101,203 @@ func TestVM_EvaluateSnippet_memory_importer(t *testing.T) {
require
.
Equal
(
t
,
"evaluated"
,
out
)
}
func
Test_regexSubst
(
t
*
testing
.
T
)
{
cases
:=
[]
struct
{
name
string
in
[]
interface
{}
expected
string
isErr
bool
}{
{
name
:
"valid regex"
,
in
:
[]
interface
{}{
"ee"
,
"tree"
,
"oll"
,
},
expected
:
"troll"
,
},
{
name
:
"invalid regex"
,
in
:
[]
interface
{}{
"["
,
"tree"
,
"oll"
,
},
isErr
:
true
,
},
}
for
_
,
tc
:=
range
cases
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
out
,
err
:=
regexSubst
(
tc
.
in
)
if
tc
.
isErr
{
require
.
Error
(
t
,
err
)
return
}
require
.
NoError
(
t
,
err
)
s
,
ok
:=
out
.
(
string
)
require
.
True
(
t
,
ok
)
require
.
Equal
(
t
,
tc
.
expected
,
s
)
})
}
}
func
Test_regexMatch
(
t
*
testing
.
T
)
{
in
:=
[]
interface
{}{
"ee"
,
"tree"
}
out
,
err
:=
regexMatch
(
in
)
require
.
NoError
(
t
,
err
)
tf
,
ok
:=
out
.
(
bool
)
require
.
True
(
t
,
ok
)
require
.
True
(
t
,
tf
)
}
func
Test_escapeStringRegex
(
t
*
testing
.
T
)
{
in
:=
[]
interface
{}{
"[foo]"
}
out
,
err
:=
escapeStringRegex
(
in
)
require
.
NoError
(
t
,
err
)
s
,
ok
:=
out
.
(
string
)
require
.
True
(
t
,
ok
)
require
.
Equal
(
t
,
`\[foo\]`
,
s
)
}
func
Test_parseYAML
(
t
*
testing
.
T
)
{
cases
:=
[]
struct
{
name
string
in
[]
interface
{}
expected
interface
{}
isErr
bool
}{
{
name
:
"valid yaml"
,
in
:
[]
interface
{}{
"---
\n
foo: bar"
},
expected
:
[]
interface
{}{
map
[
string
]
interface
{}{
"foo"
:
"bar"
,
},
},
},
}
for
_
,
tc
:=
range
cases
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
out
,
err
:=
parseYAML
(
tc
.
in
)
if
tc
.
isErr
{
require
.
Error
(
t
,
err
)
return
}
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
tc
.
expected
,
out
)
})
}
}
func
Test_parseJSON
(
t
*
testing
.
T
)
{
cases
:=
[]
struct
{
name
string
in
[]
interface
{}
expected
interface
{}
isErr
bool
}{
{
name
:
"valid JSON"
,
in
:
[]
interface
{}{
`{ "foo": "bar" }`
},
expected
:
map
[
string
]
interface
{}{
"foo"
:
"bar"
,
},
},
}
for
_
,
tc
:=
range
cases
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
out
,
err
:=
parseJSON
(
tc
.
in
)
if
tc
.
isErr
{
require
.
Error
(
t
,
err
)
return
}
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
tc
.
expected
,
out
)
})
}
}
func
TestParseJson
(
t
*
testing
.
T
)
{
vm
:=
NewVM
()
_
,
err
:=
vm
.
EvaluateSnippet
(
"failtest"
,
`std.native("parseJson")("barf{")`
)
require
.
Error
(
t
,
err
)
x
,
err
:=
vm
.
EvaluateSnippet
(
"test"
,
`std.native("parseJson")("null")`
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"null
\n
"
,
x
)
x
,
err
=
vm
.
EvaluateSnippet
(
"test"
,
`
local a = std.native("parseJson")('{"foo": 3, "bar": 4}');
a.foo + a.bar`
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"7
\n
"
,
x
)
}
func
TestParseYaml
(
t
*
testing
.
T
)
{
vm
:=
NewVM
()
_
,
err
:=
vm
.
EvaluateSnippet
(
"failtest"
,
`std.native("parseYaml")("[barf")`
)
require
.
Error
(
t
,
err
)
x
,
err
:=
vm
.
EvaluateSnippet
(
"test"
,
`std.native("parseYaml")("")`
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"[ ]
\n
"
,
x
)
x
,
err
=
vm
.
EvaluateSnippet
(
"test"
,
`
local a = std.native("parseYaml")("foo:\n- 3\n- 4\n")[0];
a.foo[0] + a.foo[1]`
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"7
\n
"
,
x
)
x
,
err
=
vm
.
EvaluateSnippet
(
"test"
,
`
local a = std.native("parseYaml")("---\nhello\n---\nworld");
a[0] + a[1]`
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"
\"
helloworld
\"\n
"
,
x
)
}
func
Test_regexMatch_fun
(
t
*
testing
.
T
)
{
vm
:=
NewVM
()
_
,
err
:=
vm
.
EvaluateSnippet
(
"failtest"
,
`std.native("regexMatch")("[f", "foo")`
)
require
.
Error
(
t
,
err
)
x
,
err
:=
vm
.
EvaluateSnippet
(
"test"
,
`std.native("regexMatch")("foo.*", "seafood")`
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"true
\n
"
,
x
)
x
,
err
=
vm
.
EvaluateSnippet
(
"test"
,
`std.native("regexMatch")("bar.*", "seafood")`
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"false
\n
"
,
x
)
}
func
TestRegexSubst
(
t
*
testing
.
T
)
{
vm
:=
NewVM
()
_
,
err
:=
vm
.
EvaluateSnippet
(
"failtest"
,
`std.native("regexSubst")("[f",s "foo", "bar")`
)
require
.
Error
(
t
,
err
)
x
,
err
:=
vm
.
EvaluateSnippet
(
"test"
,
`std.native("regexSubst")("a(x*)b", "-ab-axxb-", "T")`
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"
\"
-T-T-
\"\n
"
,
x
)
x
,
err
=
vm
.
EvaluateSnippet
(
"test"
,
`std.native("regexSubst")("a(x*)b", "-ab-axxb-", "${1}W")`
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"
\"
-W-xxW-
\"\n
"
,
x
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment