github.com/splunk/qbec@v0.15.2/vm/internal/natives/nativefuncs.go (about) 1 // Copyright 2017 The kubecfg authors 2 // 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package natives 17 18 // copied from original code at https://github.com/ksonnet/kubecfg/blob/master/utils/nativefuncs.go 19 // and modified for use. 20 21 import ( 22 "bytes" 23 "encoding/json" 24 "fmt" 25 "reflect" 26 "regexp" 27 28 "github.com/google/go-jsonnet" 29 "github.com/google/go-jsonnet/ast" 30 "github.com/pkg/errors" 31 "k8s.io/apimachinery/pkg/labels" 32 ) 33 34 // Register adds qbec's native jsonnet functions to the provided VM 35 func Register(vm *jsonnet.VM) { 36 // NB: libjsonnet native functions can only pass primitive 37 // types, so some functions json-encode the arg. These 38 // "*FromJson" functions will be replaced by regular native 39 // version when libjsonnet is able to support this. 40 41 vm.NativeFunction(&jsonnet.NativeFunction{ 42 Name: "parseJson", 43 Params: []ast.Identifier{"json"}, 44 Func: func(args []interface{}) (res interface{}, err error) { 45 str := args[0].(string) 46 data := []byte(str) 47 res, err = ParseJSON(bytes.NewReader(data)) 48 return 49 }, 50 }) 51 52 vm.NativeFunction(&jsonnet.NativeFunction{ 53 Name: "parseYaml", 54 Params: []ast.Identifier{"yaml"}, 55 Func: func(args []interface{}) (res interface{}, err error) { 56 data := []byte(args[0].(string)) 57 return ParseYAMLDocuments(bytes.NewReader(data)) 58 }, 59 }) 60 61 vm.NativeFunction(&jsonnet.NativeFunction{ 62 Name: "renderYaml", 63 Params: []ast.Identifier{"data"}, 64 Func: func(args []interface{}) (res interface{}, err error) { 65 var buf bytes.Buffer 66 err = RenderYAMLDocuments(args[0], &buf) 67 if err != nil { 68 return nil, err 69 } 70 return buf.String(), nil 71 }, 72 }) 73 74 vm.NativeFunction(&jsonnet.NativeFunction{ 75 Name: "escapeStringRegex", 76 Params: []ast.Identifier{"str"}, 77 Func: func(args []interface{}) (res interface{}, err error) { 78 return regexp.QuoteMeta(args[0].(string)), nil 79 }, 80 }) 81 82 vm.NativeFunction(&jsonnet.NativeFunction{ 83 Name: "regexMatch", 84 Params: []ast.Identifier{"regex", "string"}, 85 Func: func(args []interface{}) (res interface{}, err error) { 86 return regexp.MatchString(args[0].(string), args[1].(string)) 87 }, 88 }) 89 90 vm.NativeFunction(&jsonnet.NativeFunction{ 91 Name: "regexSubst", 92 Params: []ast.Identifier{"regex", "src", "repl"}, 93 Func: func(args []interface{}) (res interface{}, err error) { 94 regex := args[0].(string) 95 src := args[1].(string) 96 repl := args[2].(string) 97 98 r, err := regexp.Compile(regex) 99 if err != nil { 100 return "", err 101 } 102 return r.ReplaceAllString(src, repl), nil 103 }, 104 }) 105 106 vm.NativeFunction(&jsonnet.NativeFunction{ 107 Name: "expandHelmTemplate", 108 Params: []ast.Identifier{"chart", "values", "options"}, 109 Func: func(args []interface{}) (res interface{}, err error) { 110 chart := args[0].(string) 111 values := args[1].(map[string]interface{}) 112 options := args[2].(map[string]interface{}) 113 var h helmOptions 114 b, err := json.Marshal(options) 115 if err != nil { 116 return nil, errors.Wrap(err, "marshal options to JSON") 117 } 118 if err := json.Unmarshal(b, &h); err != nil { 119 return nil, errors.Wrap(err, "unmarshal options from JSON") 120 } 121 return expandHelmTemplate(chart, values, h) 122 }, 123 }) 124 125 vm.NativeFunction(&jsonnet.NativeFunction{ 126 Name: "labelsMatchSelector", 127 Params: []ast.Identifier{"labels", "selectorString"}, 128 Func: func(args []interface{}) (res interface{}, err error) { 129 lbls, ok := args[0].(map[string]interface{}) 130 if !ok { 131 return nil, fmt.Errorf("invalid labels type, %v, want a map", reflect.TypeOf(args[0])) 132 } 133 selStr, ok := args[1].(string) 134 if !ok { 135 return nil, fmt.Errorf("invalid selector of type %v, want a string", reflect.TypeOf(args[1])) 136 } 137 input := map[string]string{} 138 for k, v := range lbls { 139 val, ok := v.(string) 140 if !ok { 141 return nil, fmt.Errorf("invalid label map value, %v, want a string", reflect.TypeOf(v)) 142 } 143 input[k] = val 144 } 145 sel, err := labels.Parse(selStr) 146 if err != nil { 147 return false, fmt.Errorf("invalid label selector: '%s', %v", selStr, err) 148 } 149 return sel.Matches(labels.Set(input)), nil 150 }, 151 }) 152 }