As does 'tpl', so that nested calls to 'tpl' see the templates defined by their enclosing contexts.
(parent *template.Template, includedNames map[string]int, strict bool)
| 154 | // As does 'tpl', so that nested calls to 'tpl' see the templates |
| 155 | // defined by their enclosing contexts. |
| 156 | func tplFun(parent *template.Template, includedNames map[string]int, strict bool) func(string, any) (string, error) { |
| 157 | return func(tpl string, vals any) (string, error) { |
| 158 | tmpl, err := parent.Clone() |
| 159 | if err != nil { |
| 160 | return "", errors.Wrapf(err, "cannot clone template") |
| 161 | } |
| 162 | |
| 163 | // Re-inject the missingkey option, see text/template issue https://github.com/golang/go/issues/43022 |
| 164 | // We have to go by strict from our engine configuration, as the option fields are private in Template. |
| 165 | //nolint:godox // upstream Helm tracks a Go stdlib workaround; comment is intentional. |
| 166 | // TODO: Remove workaround (and the strict parameter) once we build only with golang versions with a fix. |
| 167 | if strict { |
| 168 | tmpl.Option("missingkey=error") |
| 169 | } else { |
| 170 | tmpl.Option("missingkey=zero") |
| 171 | } |
| 172 | |
| 173 | // Re-inject 'include' so that it can close over our clone of tmpl; |
| 174 | // this lets any 'define's inside tpl be 'include'd. |
| 175 | tmpl.Funcs(template.FuncMap{ |
| 176 | helmFuncInclude: includeFun(tmpl, includedNames), |
| 177 | helmFuncTpl: tplFun(tmpl, includedNames, strict), |
| 178 | }) |
| 179 | |
| 180 | // We need a .New template, as template text which is just blanks |
| 181 | // or comments after parsing out defines just addes new named |
| 182 | // template definitions without changing the main template. |
| 183 | // https://pkg.go.dev/text/template#Template.Parse |
| 184 | // Use the parent's name for lack of a better way to identify the tpl |
| 185 | // text string. (Maybe we could use a hash appended to the name?) |
| 186 | tmpl, err = tmpl.New(parent.Name()).Parse(tpl) |
| 187 | if err != nil { |
| 188 | return "", errors.Wrapf(err, "cannot parse template %q", tpl) |
| 189 | } |
| 190 | |
| 191 | var buf strings.Builder |
| 192 | |
| 193 | err = tmpl.Execute(&buf, vals) |
| 194 | if err != nil { |
| 195 | return "", errors.Wrapf(err, "error during tpl function execution for %q", tpl) |
| 196 | } |
| 197 | |
| 198 | // See comment in renderWithReferences explaining the <no value> hack. |
| 199 | return strings.ReplaceAll(buf.String(), "<no value>", ""), nil |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | // initFunMap creates the Engine's FuncMap and adds context-specific functions. |
| 204 | func (e Engine) initFunMap(tmpl *template.Template) { |
no test coverage detected