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  }