dnscontrol/pkg/js/js.go

89 lines
2 KiB
Go
Raw Normal View History

2016-08-23 08:31:50 +08:00
package js
import (
"encoding/json"
"fmt"
"io/ioutil"
2016-08-23 08:31:50 +08:00
"github.com/StackExchange/dnscontrol/models"
2017-04-15 03:53:02 +08:00
"github.com/StackExchange/dnscontrol/transform"
2016-08-23 08:31:50 +08:00
"github.com/robertkrimen/otto"
//load underscore js into vm by default
2017-04-15 03:53:02 +08:00
2016-08-23 08:31:50 +08:00
_ "github.com/robertkrimen/otto/underscore"
)
//ExecuteJavascript accepts a javascript string and runs it, returning the resulting dnsConfig.
func ExecuteJavascript(script string, devMode bool) (*models.DNSConfig, error) {
vm := otto.New()
vm.Set("require", require)
2017-04-15 03:53:02 +08:00
vm.Set("REVERSE", reverse)
2016-08-23 08:31:50 +08:00
helperJs := GetHelpers(devMode)
// run helper script to prime vm and initialize variables
if _, err := vm.Run(helperJs); err != nil {
2016-08-23 08:31:50 +08:00
return nil, err
}
// run user script
if _, err := vm.Run(script); err != nil {
return nil, err
}
// export conf as string and unmarshal
value, err := vm.Run(`JSON.stringify(conf)`)
if err != nil {
return nil, err
}
str, err := value.ToString()
if err != nil {
return nil, err
}
conf := &models.DNSConfig{}
if err = json.Unmarshal([]byte(str), conf); err != nil {
return nil, err
}
return conf, nil
}
func GetHelpers(devMode bool) string {
2017-01-14 03:25:17 +08:00
return _escFSMustString(devMode, "/helpers.js")
2016-08-23 08:31:50 +08:00
}
func require(call otto.FunctionCall) otto.Value {
2017-04-15 03:53:02 +08:00
if len(call.ArgumentList) != 1 {
throw(call.Otto, "require takes exactly one argument")
}
file := call.Argument(0).String()
fmt.Printf("requiring: %s\n", file)
data, err := ioutil.ReadFile(file)
if err != nil {
2017-04-15 03:53:02 +08:00
throw(call.Otto, err.Error())
}
_, err = call.Otto.Run(string(data))
if err != nil {
2017-04-15 03:53:02 +08:00
throw(call.Otto, err.Error())
}
return otto.TrueValue()
}
2017-04-15 03:53:02 +08:00
func throw(vm *otto.Otto, str string) {
panic(vm.MakeCustomError("Error", str))
}
func reverse(call otto.FunctionCall) otto.Value {
if len(call.ArgumentList) != 1 {
throw(call.Otto, "REVERSE takes exactly one argument")
}
dom := call.Argument(0).String()
rev, err := transform.ReverseDomainName(dom)
fmt.Println(dom, rev, err)
if err != nil {
throw(call.Otto, err.Error())
}
v, _ := otto.ToValue(rev)
return v
}