Skip to content

Commit

Permalink
Add verifier support for the special $ variable. (#1255)
Browse files Browse the repository at this point in the history
This includes a test case.
Also fix some typos found when reading related code.
  • Loading branch information
porridge committed Jan 9, 2020
1 parent b85bd6c commit 1f0be0b
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 10 deletions.
37 changes: 29 additions & 8 deletions pkg/kudoctl/packages/verifier/template/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func getNodeMap(ts packages.Templates) nodeMap {
continue
}

//nodeMap is a map of node types ("Implicits", "Params") to a set of that type (which is go is a map :))
// nodeMap is a map of node types ("Implicits", "Params") to a set of that type (which in go is a map :))
nodeMap := map[string]map[string]bool{}
walkNodes(tplate.Root, fname, nodeMap)

Expand Down Expand Up @@ -78,7 +78,7 @@ All other Node types are not supported at this time.

// walkNodes walks the nodes of a template providing an array of parameters
// this function makes heavy use and deep understanding of Go Templating. The details for
// different types of nodes and how they are parse is in `parse.Node`.
// different types of nodes and how they are parsed is in `parse.Node`.
func walkNodes(node parse.Node, fname string, nodeMap map[string]map[string]bool) {
switch node := node.(type) {
case *parse.ActionNode:
Expand Down Expand Up @@ -109,11 +109,12 @@ func walkNodes(node parse.Node, fname string, nodeMap map[string]map[string]bool

/*
Regarding template node parsing. The underlying field information of a node (for instances it's text) is packaged as
args to commands (please review more in parse.Nodes in the go core for more detail). The arg type we are interested in is FieldNodes
which in the template could be {{.Name}}, {{.Params.Name}} or {{.Params.Foo.Bar}}. It is at this point in processing (below switch case parse.FieldNode)
that we know must the type of field we are processing. The number of dot separated strings is the "Ident" of this field. If an "Ident" of 0 is possible
args to commands (please review more in parse.Nodes in the go core for more detail). The arg types we are interested in is FieldNodes
which in the template could be {{.Name}}, {{.Params.Name}} or {{.Params.Foo.Bar}} and VariableNodes, but only those where the variable
name is empty (i.e. {{$.Name}} or {{$.Params.Name}}. It is at this point in processing (below switch case parse.FieldNode)
that we know must be the type of field we are processing. The number of dot separated strings is the "Ident" of this field. If an "Ident" of 0 is possible
it isn't useful to KUDO. If there is 1, that is an implicit field and will be mapped as an implicit. If there are 2 it is something like
{{.Params.Foo}} or {{.Pipes.Foo}} and will be mapped with it's kind. Greater than 2 is not supported in KUDO.
{{.Params.Foo}} or {{.Pipes.Foo}} and will be mapped with its kind. Greater than 2 is not supported in KUDO.
*/

// walkPipes walks the pipes of specific block types which may contain params
Expand All @@ -126,17 +127,37 @@ func walkPipes(node *parse.PipeNode, nodeMap map[string]map[string]bool) {
if len(n.Ident) < 1 {
return
}
//implicits have .Name which has 1 Indent
// implicits have .Name which has 1 Ident
if len(n.Ident) == 1 {
addNodeSliceMap(nodeMap, "Implicits", trimNodeValue(arg.String()))
return
}
// others like .Params.Foo are deeper. We currently only support 1 deep.
// others like .Params.Foo are deeper. We currently only support 1 deep.
// .Params or similar is the key
addNodeSliceMap(nodeMap, n.Ident[0], n.Ident[1])
if len(n.Ident) > 2 {
clog.V(3).Printf("template node %v has more elements than is supported", arg.String())
}
case *parse.VariableNode:
// not evaluated
if len(n.Ident) < 2 {
return
}
if n.Ident[0] != "$" {
clog.V(3).Printf("template node %v refers to a user variable", arg.String())
return
}
// implicits have $.Name which has 2 Idents
if len(n.Ident) == 2 {
addNodeSliceMap(nodeMap, "Implicits", n.Ident[1])
return
}
// others like $.Params.Foo are deeper. We currently only support 1 deep.
// .Params or similar is the key
addNodeSliceMap(nodeMap, n.Ident[1], n.Ident[2])
if len(n.Ident) > 3 {
clog.V(3).Printf("template node %v has more elements than is supported", arg.String())
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/kudoctl/packages/verifier/template/verify_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ func paramsDefinedNotUsed(pf *packages.Files) verifier.Result {
tparams := make(map[string]bool)
nodes := getNodeMap(pf.Templates)

for _, nodes := range nodes {
for _, tparam := range nodes.parameters {
for _, node := range nodes {
for _, tparam := range node.parameters {
tparams[tparam] = true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func TestTemplateParametersVerifier(t *testing.T) {
params := []v1beta1.Parameter{
{Name: "Foo"},
{Name: "NotUsed"},
{Name: "UsedViaRoot"},
}
paramFile := packages.ParamsFile{Parameters: params}
templates := make(map[string]string)
Expand All @@ -21,6 +22,8 @@ func TestTemplateParametersVerifier(t *testing.T) {
{{.Params.Bar}}
{{.Bar}}
{{.Name}}
{{$.AppVersion}}
{{$.Params.UsedViaRoot}}
`
operator := packages.OperatorFile{}
pf := packages.Files{
Expand Down

0 comments on commit 1f0be0b

Please sign in to comment.