github.com/pmoroney/dnscontrol@v0.2.4-0.20171024134423-fad98f73f44a/pkg/js/js.go (about) 1 package js 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 8 "github.com/StackExchange/dnscontrol/models" 9 "github.com/StackExchange/dnscontrol/pkg/transform" 10 11 "github.com/robertkrimen/otto" 12 //load underscore js into vm by default 13 14 _ "github.com/robertkrimen/otto/underscore" 15 ) 16 17 //ExecuteJavascript accepts a javascript string and runs it, returning the resulting dnsConfig. 18 func ExecuteJavascript(script string, devMode bool) (*models.DNSConfig, error) { 19 vm := otto.New() 20 21 vm.Set("require", require) 22 vm.Set("REV", reverse) 23 24 helperJs := GetHelpers(devMode) 25 // run helper script to prime vm and initialize variables 26 if _, err := vm.Run(helperJs); err != nil { 27 return nil, err 28 } 29 30 // run user script 31 if _, err := vm.Run(script); err != nil { 32 return nil, err 33 } 34 35 // export conf as string and unmarshal 36 value, err := vm.Run(`JSON.stringify(conf)`) 37 if err != nil { 38 return nil, err 39 } 40 str, err := value.ToString() 41 if err != nil { 42 return nil, err 43 } 44 conf := &models.DNSConfig{} 45 if err = json.Unmarshal([]byte(str), conf); err != nil { 46 return nil, err 47 } 48 return conf, nil 49 } 50 51 func GetHelpers(devMode bool) string { 52 return _escFSMustString(devMode, "/helpers.js") 53 } 54 55 func require(call otto.FunctionCall) otto.Value { 56 if len(call.ArgumentList) != 1 { 57 throw(call.Otto, "require takes exactly one argument") 58 } 59 file := call.Argument(0).String() 60 fmt.Printf("requiring: %s\n", file) 61 data, err := ioutil.ReadFile(file) 62 if err != nil { 63 throw(call.Otto, err.Error()) 64 } 65 _, err = call.Otto.Run(string(data)) 66 if err != nil { 67 throw(call.Otto, err.Error()) 68 } 69 return otto.TrueValue() 70 } 71 72 func throw(vm *otto.Otto, str string) { 73 panic(vm.MakeCustomError("Error", str)) 74 } 75 76 func reverse(call otto.FunctionCall) otto.Value { 77 if len(call.ArgumentList) != 1 { 78 throw(call.Otto, "REV takes exactly one argument") 79 } 80 dom := call.Argument(0).String() 81 rev, err := transform.ReverseDomainName(dom) 82 if err != nil { 83 throw(call.Otto, err.Error()) 84 } 85 v, _ := otto.ToValue(rev) 86 return v 87 }