github.com/teknogeek/dnscontrol@v0.2.8/providers/octodns/octoyaml/js.go (about) 1 package octoyaml 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" // required by otto 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(true) 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 // GetHelpers returns the filename of helpers.js, or the esc'ed version. 52 func GetHelpers(devMode bool) string { 53 d, err := ioutil.ReadFile("../pkg/js/helpers.js") 54 if err != nil { 55 panic(err) 56 } 57 return string(d) 58 } 59 60 func require(call otto.FunctionCall) otto.Value { 61 if len(call.ArgumentList) != 1 { 62 throw(call.Otto, "require takes exactly one argument") 63 } 64 file := call.Argument(0).String() 65 fmt.Printf("requiring: %s\n", file) 66 data, err := ioutil.ReadFile(file) 67 if err != nil { 68 throw(call.Otto, err.Error()) 69 } 70 _, err = call.Otto.Run(string(data)) 71 if err != nil { 72 throw(call.Otto, err.Error()) 73 } 74 return otto.TrueValue() 75 } 76 77 func throw(vm *otto.Otto, str string) { 78 panic(vm.MakeCustomError("Error", str)) 79 } 80 81 func reverse(call otto.FunctionCall) otto.Value { 82 if len(call.ArgumentList) != 1 { 83 throw(call.Otto, "REV takes exactly one argument") 84 } 85 dom := call.Argument(0).String() 86 rev, err := transform.ReverseDomainName(dom) 87 if err != nil { 88 throw(call.Otto, err.Error()) 89 } 90 v, _ := otto.ToValue(rev) 91 return v 92 }