From 2e81e301aebbed12804ce1d130cdb0a8e5904a20 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Mon, 14 Apr 2025 10:56:20 -0700 Subject: [PATCH] bake: fix variadic_params inconsistency for user functions There was inconsistency between variables used for function definitions in HCL and JSON format. Updated JSON to match HCL, fixed documentation and removed the unused code from userfunc pkg (based on HCL upstream) to avoid confusion. Theoretically we could add some temporary backwards compatibility for the JSON format but I think it is unlikely that someone uses JSON format for this and also defined variadic parameters. Signed-off-by: Tonis Tiigi --- bake/hclparser/hclparser.go | 2 +- util/userfunc/README.md | 2 +- util/userfunc/decode.go | 79 ------------------------------------- util/userfunc/public.go | 24 +---------- 4 files changed, 3 insertions(+), 104 deletions(-) delete mode 100644 util/userfunc/decode.go diff --git a/bake/hclparser/hclparser.go b/bake/hclparser/hclparser.go index 6aa5eada..1628e7c0 100644 --- a/bake/hclparser/hclparser.go +++ b/bake/hclparser/hclparser.go @@ -42,7 +42,7 @@ type variableValidation struct { type functionDef struct { Name string `json:"-" hcl:"name,label"` Params *hcl.Attribute `json:"params,omitempty" hcl:"params"` - Variadic *hcl.Attribute `json:"variadic_param,omitempty" hcl:"variadic_params"` + Variadic *hcl.Attribute `json:"variadic_params,omitempty" hcl:"variadic_params"` Result *hcl.Attribute `json:"result,omitempty" hcl:"result"` } diff --git a/util/userfunc/README.md b/util/userfunc/README.md index b0c726d2..6c6bfdcb 100644 --- a/util/userfunc/README.md +++ b/util/userfunc/README.md @@ -13,7 +13,7 @@ function "add" { function "list" { params = [] - variadic_param = items + variadic_params = items result = items } ``` diff --git a/util/userfunc/decode.go b/util/userfunc/decode.go deleted file mode 100644 index 6ca2b6be..00000000 --- a/util/userfunc/decode.go +++ /dev/null @@ -1,79 +0,0 @@ -package userfunc - -import ( - "github.com/hashicorp/hcl/v2" - "github.com/zclconf/go-cty/cty/function" -) - -var funcBodySchema = &hcl.BodySchema{ - Attributes: []hcl.AttributeSchema{ - { - Name: "params", - Required: true, - }, - { - Name: "variadic_param", - Required: false, - }, - { - Name: "result", - Required: true, - }, - }, -} - -func decodeUserFunctions(body hcl.Body, blockType string, contextFunc ContextFunc) (funcs map[string]function.Function, remain hcl.Body, diags hcl.Diagnostics) { - schema := &hcl.BodySchema{ - Blocks: []hcl.BlockHeaderSchema{ - { - Type: blockType, - LabelNames: []string{"name"}, - }, - }, - } - - content, remain, diags := body.PartialContent(schema) - if diags.HasErrors() { - return nil, remain, diags - } - - // first call to getBaseCtx will populate context, and then the same - // context will be used for all subsequent calls. It's assumed that - // all functions in a given body should see an identical context. - var baseCtx *hcl.EvalContext - getBaseCtx := func() *hcl.EvalContext { - if baseCtx == nil { - if contextFunc != nil { - baseCtx = contextFunc() - } - } - // baseCtx might still be nil here, and that's okay - return baseCtx - } - - funcs = make(map[string]function.Function) - - for _, block := range content.Blocks { - name := block.Labels[0] - funcContent, funcDiags := block.Body.Content(funcBodySchema) - diags = append(diags, funcDiags...) - if funcDiags.HasErrors() { - continue - } - - paramsExpr := funcContent.Attributes["params"].Expr - resultExpr := funcContent.Attributes["result"].Expr - var varParamExpr hcl.Expression - if funcContent.Attributes["variadic_param"] != nil { - varParamExpr = funcContent.Attributes["variadic_param"].Expr - } - f, funcDiags := NewFunction(paramsExpr, varParamExpr, resultExpr, getBaseCtx) - if funcDiags.HasErrors() { - diags = append(diags, funcDiags...) - continue - } - funcs[name] = f - } - - return funcs, remain, diags -} diff --git a/util/userfunc/public.go b/util/userfunc/public.go index 2a5c394b..9e0a0303 100644 --- a/util/userfunc/public.go +++ b/util/userfunc/public.go @@ -20,28 +20,6 @@ import ( // structure a function declaration is found, etc. type ContextFunc func() *hcl.EvalContext -// DecodeUserFunctions looks for blocks of the given type in the given body -// and, for each one found, interprets it as a custom function definition. -// -// On success, the result is a mapping of function names to implementations, -// along with a new body that represents the remaining content of the given -// body which can be used for further processing. -// -// The result expression of each function is parsed during decoding but not -// evaluated until the function is called. -// -// If the given ContextFunc is non-nil, it will be called to obtain the -// context in which the function result expressions will be evaluated. If nil, -// or if it returns nil, the result expression will have access only to -// variables named after the declared parameters. A non-nil context turns -// the returned functions into closures, bound to the given context. -// -// If the returned diagnostics set has errors then the function map and -// remain body may be nil or incomplete. -func DecodeUserFunctions(body hcl.Body, blockType string, context ContextFunc) (funcs map[string]function.Function, remain hcl.Body, diags hcl.Diagnostics) { - return decodeUserFunctions(body, blockType, context) -} - // NewFunction creates a new function instance from preparsed HCL expressions. func NewFunction(paramsExpr, varParamExpr, resultExpr hcl.Expression, getBaseCtx func() *hcl.EvalContext) (function.Function, hcl.Diagnostics) { var params []string @@ -69,7 +47,7 @@ func NewFunction(paramsExpr, varParamExpr, resultExpr hcl.Expression, getBaseCtx if varParam == "" { return function.Function{}, hcl.Diagnostics{{ Severity: hcl.DiagError, - Summary: "Invalid variadic_param", + Summary: "Invalid variadic_params", Detail: "The variadic parameter name must be an identifier.", Subject: varParamExpr.Range().Ptr(), }}