istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/framework/components/echo/config/param/template.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package param 16 17 import ( 18 "text/template" 19 "text/template/parse" 20 21 "istio.io/istio/pkg/util/sets" 22 ) 23 24 // Template that has been parsed to search for template parameters. 25 type Template struct { 26 *template.Template 27 params sets.String 28 } 29 30 // Parse the given template to find the set of template parameters used. 31 func Parse(t *template.Template) *Template { 32 return &Template{ 33 Template: t, 34 params: getParams(t.Root), 35 } 36 } 37 38 // Params returns the set of parameters that were found in this template. 39 func (t Template) Params() sets.String { 40 return t.params.Copy() 41 } 42 43 // Contains returns true if the given parameter is used by this Template. 44 func (t Template) Contains(p string) bool { 45 return t.params.Contains(p) 46 } 47 48 // ContainsWellKnown returns true if the given well-known parameter is used by 49 // this Template. 50 func (t Template) ContainsWellKnown(p WellKnown) bool { 51 return t.Contains(p.String()) 52 } 53 54 // MissingParams checks the provided params against the parameters used in this Template. 55 // Returns the set of template parameters not defined in params. 56 func (t Template) MissingParams(params Params) sets.String { 57 out := sets.New[string]() 58 for needed := range t.params { 59 if !params.Contains(needed) { 60 out.Insert(needed) 61 } 62 } 63 return out 64 } 65 66 func getParams(n parse.Node) sets.String { 67 out := sets.New[string]() 68 switch n.Type() { 69 case parse.NodeField: 70 // Only look at the first identifier. For example, if the action 71 // is {{.To.Config.Service}}, this will return "To" as the parameter. 72 // That's all we need when looking for well-known params. 73 firstIdentifier := n.(*parse.FieldNode).Ident[0] 74 out.Insert(firstIdentifier) 75 case parse.NodeIf: 76 out.Merge(getParams(n.(*parse.IfNode).Pipe)) 77 case parse.NodeWith: 78 out.Merge(getParams(n.(*parse.WithNode).Pipe)) 79 case parse.NodeRange: 80 out.Merge(getParams(n.(*parse.RangeNode).Pipe)) 81 case parse.NodeAction: 82 out.Merge(getParams(n.(*parse.ActionNode).Pipe)) 83 case parse.NodeCommand: 84 for _, arg := range n.(*parse.CommandNode).Args { 85 out.Merge(getParams(arg)) 86 } 87 case parse.NodePipe: 88 for _, c := range n.(*parse.PipeNode).Cmds { 89 out.Merge(getParams(c)) 90 } 91 case parse.NodeList: 92 for _, next := range n.(*parse.ListNode).Nodes { 93 out.Merge(getParams(next)) 94 } 95 } 96 return out 97 }