From f15a936006526dd915c8ff6fa3627fdac6333385 Mon Sep 17 00:00:00 2001 From: Simon Halvorsen Date: Thu, 16 Apr 2026 12:31:37 +0200 Subject: [PATCH 1/5] ENT-13828: Errors for invalid attributes for inbuilt promises Signed-off-by: Simon Halvorsen --- src/cfengine_cli/lint.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/cfengine_cli/lint.py b/src/cfengine_cli/lint.py index 50165dc..6089e89 100644 --- a/src/cfengine_cli/lint.py +++ b/src/cfengine_cli/lint.py @@ -634,6 +634,17 @@ def _lint_node( f"Error: '{name}' is not a defined body. Only bodies may be called with '{state.attribute_name}' {location}" ) return 1 + if node.type == "attribute_name" and state.promise_type and state.attribute_name: + promise_type_data = syntax_data.BUILTIN_PROMISE_TYPES.get( + state.promise_type, {} + ) + promise_type_attrs = promise_type_data.get("attributes", {}) + if state.attribute_name not in promise_type_attrs: + _highlight_range(node, lines) + print( + f"Error: Invalid attribute '{state.attribute_name}' for promise type '{state.promise_type}' {location}" + ) + return 1 return 0 From 420ccf28f14acb0947ba5c9e33a7c12e389f5525 Mon Sep 17 00:00:00 2001 From: Simon Halvorsen Date: Thu, 16 Apr 2026 12:50:08 +0200 Subject: [PATCH 2/5] ENT-13827: Check for valid attribute name inside promise blocks Signed-off-by: Simon Halvorsen --- src/cfengine_cli/lint.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/cfengine_cli/lint.py b/src/cfengine_cli/lint.py index 6089e89..71b9d15 100644 --- a/src/cfengine_cli/lint.py +++ b/src/cfengine_cli/lint.py @@ -645,6 +645,21 @@ def _lint_node( f"Error: Invalid attribute '{state.attribute_name}' for promise type '{state.promise_type}' {location}" ) return 1 + if ( + state.block_keyword == "promise" + and node.type == "attribute_name" + and state.attribute_name + not in ( + None, + "path", + "interpreter", + ) + ): + _highlight_range(node, lines) + print( + f"Error: Invalid attribute name '{state.attribute_name}' in '{state.block_name}' custom promise type definition {location}" + ) + return 1 return 0 From 16920ffeaa4dd962c7b80bae8fd67bc3ebe3a224 Mon Sep 17 00:00:00 2001 From: Simon Halvorsen Date: Thu, 16 Apr 2026 13:07:48 +0200 Subject: [PATCH 3/5] Added tests for checking valid attribute names in promise --- tests/lint/012_invalid_attributes.expected.txt | 12 ++++++++++++ tests/lint/012_invalid_attributes.x.cf | 13 +++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/lint/012_invalid_attributes.expected.txt create mode 100644 tests/lint/012_invalid_attributes.x.cf diff --git a/tests/lint/012_invalid_attributes.expected.txt b/tests/lint/012_invalid_attributes.expected.txt new file mode 100644 index 0000000..b54202f --- /dev/null +++ b/tests/lint/012_invalid_attributes.expected.txt @@ -0,0 +1,12 @@ + + path => "/var/cfengine/inputs/modules/promises/git.py"; + blah => "something"; + ^--^ +Error: Invalid attribute name 'blah' in 'git' custom promise type definition at tests/lint/012_invalid_attributes.x.cf:5:3 + + slist => {}, + bar => ""; + ^-^ +Error: Invalid attribute 'bar' for promise type 'vars' at tests/lint/012_invalid_attributes.x.cf:12:7 +FAIL: tests/lint/012_invalid_attributes.x.cf (2 errors) +Failure, 2 errors in total. diff --git a/tests/lint/012_invalid_attributes.x.cf b/tests/lint/012_invalid_attributes.x.cf new file mode 100644 index 0000000..90faa66 --- /dev/null +++ b/tests/lint/012_invalid_attributes.x.cf @@ -0,0 +1,13 @@ +promise agent git +{ + interpreter => "/usr/bin/python3"; + path => "/var/cfengine/inputs/modules/promises/git.py"; + blah => "something"; +} +bundle agent foo +{ + vars: + "error" + slist => {}, + bar => ""; +} From 2d5267dc5ed6220d46597538a865cd2983fae2ba Mon Sep 17 00:00:00 2001 From: Simon Halvorsen Date: Thu, 16 Apr 2026 14:48:08 +0200 Subject: [PATCH 4/5] ENT-13832: Error on invalid number of arguments for builtin functions Issue: Variadic is not consistent in use, some functions(readfile) require 1-N arguments, whilst others (getgroups/getusers) can take 0-N. Errormessage default to "expected 1-N, recieved X" as this is the most common I think. Signed-off-by: Simon Halvorsen --- src/cfengine_cli/lint.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/cfengine_cli/lint.py b/src/cfengine_cli/lint.py index 71b9d15..0355603 100644 --- a/src/cfengine_cli/lint.py +++ b/src/cfengine_cli/lint.py @@ -660,6 +660,21 @@ def _lint_node( f"Error: Invalid attribute name '{state.attribute_name}' in '{state.block_name}' custom promise type definition {location}" ) return 1 + if node.type == "call": + call, _, *args, _ = node.children # f ( a1 , a2 , a..N ) + call = _text(call) + args = list(filter(",".__ne__, iter(_text(x) for x in args))) + + if call in syntax_data.BUILTIN_FUNCTIONS: + variadic = syntax_data.BUILTIN_FUNCTIONS.get(call, {}).get("variadic", True) + params = syntax_data.BUILTIN_FUNCTIONS.get(call, {}).get("parameters", {}) + if not variadic and (len(params) != len(args)): + _highlight_range(node, lines) + print( + f"Error: Expected {len(params)} arguments, received {len(args)} {location}" + ) + return 1 + # TODO: Handle variadic functions with varying number of required arguments (0-N, 1-N, 2-N and so on) return 0 From 883a894915e72b54fb8dac46d7265fe185a58027 Mon Sep 17 00:00:00 2001 From: Simon Halvorsen Date: Thu, 16 Apr 2026 15:08:28 +0200 Subject: [PATCH 5/5] Added tests for invalid number of arguments in function calls --- tests/lint/013_function_call_arg_count.cf | 8 ++++++++ .../lint/013_function_call_arg_count.expected.txt | 12 ++++++++++++ tests/lint/013_function_call_arg_count.x.cf | 14 ++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 tests/lint/013_function_call_arg_count.cf create mode 100644 tests/lint/013_function_call_arg_count.expected.txt create mode 100644 tests/lint/013_function_call_arg_count.x.cf diff --git a/tests/lint/013_function_call_arg_count.cf b/tests/lint/013_function_call_arg_count.cf new file mode 100644 index 0000000..b6b7593 --- /dev/null +++ b/tests/lint/013_function_call_arg_count.cf @@ -0,0 +1,8 @@ +bundle agent main +{ +vars: + "string" + string => canonify("test"); +reports: + "Test => $(string)"; +} diff --git a/tests/lint/013_function_call_arg_count.expected.txt b/tests/lint/013_function_call_arg_count.expected.txt new file mode 100644 index 0000000..1fe0635 --- /dev/null +++ b/tests/lint/013_function_call_arg_count.expected.txt @@ -0,0 +1,12 @@ + + "string1" + string => canonify(); + ^--------^ +Error: Expected 1 arguments, received 0 at tests/lint/013_function_call_arg_count.x.cf:5:15 + + "string3" + string => canonify("test", "test"); + ^----------------------^ +Error: Expected 1 arguments, received 2 at tests/lint/013_function_call_arg_count.x.cf:9:15 +FAIL: tests/lint/013_function_call_arg_count.x.cf (2 errors) +Failure, 2 errors in total. diff --git a/tests/lint/013_function_call_arg_count.x.cf b/tests/lint/013_function_call_arg_count.x.cf new file mode 100644 index 0000000..ac4fb6d --- /dev/null +++ b/tests/lint/013_function_call_arg_count.x.cf @@ -0,0 +1,14 @@ +bundle agent main +{ +vars: + "string1" + string => canonify(); + "string2" + string => canonify("test"); + "string3" + string => canonify("test", "test"); +reports: + "Test1 => $(string1)"; + "Test2 => $(string2)"; + "Test3 => $(string3)"; +}