diff --git a/.github/workflows/cfengine_cli.yml b/.github/workflows/cfengine_cli.yml new file mode 100644 index 0000000000..1dab88dfb3 --- /dev/null +++ b/.github/workflows/cfengine_cli.yml @@ -0,0 +1,23 @@ +name: Lint policy and check formatting with CFEngine CLI +on: + workflow_call: +permissions: + contents: read +jobs: + lint: + runs-on: ubuntu-24.04 + steps: + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.14" + - name: Checkout masterfiles + uses: actions/checkout@v7 + - name: Install CFEngine CLI + run: pipx install cfengine + - name: Run cfengine lint + run: | + cfengine lint --strict no ./ + - name: Run cfengine format --check + run: | + cfengine format --check diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3510615faf..36bcf11f06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,10 @@ on: branches: [ master, 3.27.x, 3.24.x ] jobs: + cfengine_cli: + uses: ./.github/workflows/cfengine_cli.yml unit_tests: + needs: cfengine_cli uses: ./.github/workflows/unit_tests.yml shellcheck_tests: uses: ./.github/workflows/shellcheck.yml diff --git a/tests/acceptance/01_vars/02_functions/staging/datatype.cf b/tests/acceptance/01_vars/02_functions/staging/datatype.cf deleted file mode 100644 index a4ea6b269c..0000000000 --- a/tests/acceptance/01_vars/02_functions/staging/datatype.cf +++ /dev/null @@ -1,264 +0,0 @@ -####################################################### -# -# Test datatype() -# -####################################################### -body common control -{ - inputs => { "../../default.sub.cf" }; - bundlesequence => { default("$(this.promise_filename)") }; - version => "1.0"; -} - -####################################################### -bundle agent init -{ - vars: - "results" - string => 'jsonstring = { - "person": { - "first": "miyamoto", - "last": "musashi" - }, - "birth": null, - "death": 16450613, - "go rin no sho": { - "1": "ground", - "2": "water", - "3": "fire", - "4": "wind", - "5": "void" - }, - "dokkōdō": [ - "accept everything just the way it is.", - "do not seek pleasure for its own sake.", - "do not, under any circumstances, depend on a partial feeling.", - "think lightly of yourself and deeply of the world.", - "be detached from desire your whole life.", - "do not regret what you have done.", - "never be jealous.", - "never let yourself be saddened by a separation.", - "resentment and complaint are appropriate neither for oneself nor others.", - "do not let yourself be guided by the feeling of lust or love.", - "In all things, have no preferences.", - "be indifferent to where you live.", - "do not pursue the taste of good food.", - "do not hold on to possessions you no longer need.", - "do not act following customary beliefs.", - "do not collect weapons or practice with weapons beyond what is useful.", - "do not fear death.", - "do not seek to possess either goods or fiefs for your old age.", - "respect buddha and the gods without counting on their help.", - "you may abandon your own body but you must preserve your honor.", - "never stray from the way." - ], - "styles": [ - "two heavens as one", - "two swords as one" - ], - "decidable": false, - "dituri was here": 3.1416 -}'; - - "results2" - string => '--------------------- -toplevel:key = person -toplevel:key = birth -toplevel:key = death -toplevel:key = go rin no sho -toplevel:key = dokkōdō -toplevel:key = styles -toplevel:key = decidable -toplevel:key = dituri was here -toplevel[person]:type = json_object -toplevel[birth]:type = json_null -toplevel[death]:type = json_integer -toplevel[go rin no sho]:type = json_object -toplevel[dokkōdō]:type = json_array -toplevel[styles]:type = json_array -toplevel[decidable]:type = json_bool -toplevel[dituri was here]:type = json_real ------------------------------------------- -toplevel[person]:key= first -toplevel[go rin no sho]:key= 1 -toplevel[dokkōdō]:key= 0 -toplevel[styles]:key= 0 -toplevel[person]:key= last -toplevel[go rin no sho]:key= 2 -toplevel[go rin no sho]:key= 3 -toplevel[go rin no sho]:key= 4 -toplevel[go rin no sho]:key= 5 -toplevel[dokkōdō]:key= 1 -toplevel[dokkōdō]:key= 2 -toplevel[dokkōdō]:key= 3 -toplevel[dokkōdō]:key= 4 -toplevel[dokkōdō]:key= 5 -toplevel[dokkōdō]:key= 6 -toplevel[dokkōdō]:key= 7 -toplevel[dokkōdō]:key= 8 -toplevel[dokkōdō]:key= 9 -toplevel[dokkōdō]:key= 10 -toplevel[dokkōdō]:key= 11 -toplevel[dokkōdō]:key= 12 -toplevel[dokkōdō]:key= 13 -toplevel[dokkōdō]:key= 14 -toplevel[dokkōdō]:key= 15 -toplevel[dokkōdō]:key= 16 -toplevel[dokkōdō]:key= 17 -toplevel[dokkōdō]:key= 18 -toplevel[dokkōdō]:key= 19 -toplevel[dokkōdō]:key= 20 -toplevel[styles]:key= 1'; - - "results3" - string => 'toplevel[person][first]:type = json_string -toplevel[go rin no sho][1]:type = json_string -toplevel[dokkōdō][0]:type = json_string -toplevel[styles][0]:type = json_string -toplevel[person][last]:type = json_string -toplevel[go rin no sho][2]:type = json_string -toplevel[go rin no sho][3]:type = json_string -toplevel[go rin no sho][4]:type = json_string -toplevel[go rin no sho][5]:type = json_string -toplevel[dokkōdō][1]:type = json_string -toplevel[dokkōdō][2]:type = json_string -toplevel[dokkōdō][3]:type = json_string -toplevel[dokkōdō][4]:type = json_string -toplevel[dokkōdō][5]:type = json_string -toplevel[dokkōdō][6]:type = json_string -toplevel[dokkōdō][7]:type = json_string -toplevel[dokkōdō][8]:type = json_string -toplevel[dokkōdō][9]:type = json_string -toplevel[dokkōdō][10]:type = json_string -toplevel[dokkōdō][11]:type = json_string -toplevel[dokkōdō][12]:type = json_string -toplevel[dokkōdō][13]:type = json_string -toplevel[dokkōdō][14]:type = json_string -toplevel[dokkōdō][15]:type = json_string -toplevel[dokkōdō][16]:type = json_string -toplevel[dokkōdō][17]:type = json_string -toplevel[dokkōdō][18]:type = json_string -toplevel[dokkōdō][19]:type = json_string -toplevel[dokkōdō][20]:type = json_string -toplevel[styles][1]:type = json_string -ok: datatype(datastr) failed properly'; - - files: - "$(G.testfile).expected" - create => "true", - edit_defaults => init_empty, - edit_line => init_insert; -} - -body edit_defaults init_empty -{ - empty_file_before_editing => "true"; - edit_backup => "false"; -} - -bundle edit_line init_insert -{ - insert_lines: - "$(init.results)"; - "$(init.results2)"; - "$(init.results3)"; -} - -####################################################### -bundle common test_common -{ - vars: - "datastr" string => storejson("data"); - - "data" - data => parsejson( - ' -{ - "person": { "first": "miyamoto", "last": "musashi" }, - "birth": null, - "death": 16450613, - "go rin no sho": { "1": "ground", "2": "water", "3": "fire", "4": "wind", "5": "void" }, - "dokkōdō": [ - "accept everything just the way it is.", - "do not seek pleasure for its own sake.", - "do not, under any circumstances, depend on a partial feeling.", - "think lightly of yourself and deeply of the world.", - "be detached from desire your whole life.", - "do not regret what you have done.", - "never be jealous.", - "never let yourself be saddened by a separation.", - "resentment and complaint are appropriate neither for oneself nor others.", - "do not let yourself be guided by the feeling of lust or love.", - "In all things, have no preferences.", - "be indifferent to where you live.", - "do not pursue the taste of good food.", - "do not hold on to possessions you no longer need.", - "do not act following customary beliefs.", - "do not collect weapons or practice with weapons beyond what is useful.", - "do not fear death.", - "do not seek to possess either goods or fiefs for your old age.", - "respect buddha and the gods without counting on their help.", - "you may abandon your own body but you must preserve your honor.", - "never stray from the way." - ], - "styles": ["two heavens as one","two swords as one"], - "decidable": false - "dituri was here": 3.14159265 -} -' - ); - - "typenames" slist => { "person", "go rin no sho", "dokkōdō", "styles" }; - "keys[top]" slist => getindices("data"); - "types[top][$(keys[top])]" string => datatype("data[$(keys[top])]"); - "keys[$(typenames)]" slist => getindices("data[$(typenames)]"); - - "types[$(typenames)][$(keys[$(typenames)])]" - string => datatype("data[$(typenames)][$(keys[$(typenames)])]"); - - "bad_type_test" string => datatype("datastr"); - - classes: - "ok_invalid_test_failed" not => isvariable("bad_type_test"); -} - -bundle agent test -{ - files: - "$(G.testfile).actual" - create => "true", - edit_line => test_insert; -} - -bundle edit_line test_insert -{ - insert_lines: - cfengine:: - "jsonstring = $(test_common.datastr)"; - "---------------------"; - "toplevel:key = $(test_common.keys[top])"; - "toplevel[$(test_common.keys[top])]:type = $(test_common.types[top][$(test_common.keys[top])])"; - "------------------------------------------"; - "toplevel[$(test_common.typenames)]:key= $(test_common.keys[$(test_common.typenames)])"; - "toplevel[$(test_common.typenames)][$(test_common.keys[$(test_common.typenames)])]:type = $(test_common.types[$(test_common.typenames)][$(test_common.keys[$(test_common.typenames)])])"; - - ok_invalid_test_failed:: - "------------------------------------------"; - "ok: datatype(datastr) failed properly"; - - !ok_invalid_test_failed:: - "------------------------------------------"; - "NOT_OK: datatype(datastr) was supposed to fail"; -} - -####################################################### -bundle agent check -{ - methods: - "any" - usebundle => dcs_check_diff( - "$(G.testfile).actual", - "$(G.testfile).expected", - "$(this.promise_filename)" - ); -} diff --git a/tests/acceptance/01_vars/02_functions/staging/execresult_large.cf b/tests/acceptance/01_vars/02_functions/staging/execresult_large.cf index e3c5c56c1b..55b68ae051 100644 --- a/tests/acceptance/01_vars/02_functions/staging/execresult_large.cf +++ b/tests/acceptance/01_vars/02_functions/staging/execresult_large.cf @@ -31,7 +31,7 @@ bundle agent check "$(G.perl) -e 'my $x = qw/x/ x $(testlengths); print $x;'", "useshell" ); - "length_$(testlengths)" int => strlen("$(result_$(testlengths))"); + "length_$(testlengths)" int => string_length("$(result_$(testlengths))"); classes: "ok_$(testlengths)" diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_dontread_comment_duplicate_lastline3.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_dontread_comment_duplicate_lastline3.cf index f2ac8963b2..0e0e7b896b 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_dontread_comment_duplicate_lastline3.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_dontread_comment_duplicate_lastline3.cf @@ -48,7 +48,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", 1000); + "teststr" string => readfile("$(G.testfile)", 1000); "cnt" int => parsestringarrayidx( diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_change_comment_parsing2.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_change_comment_parsing2.cf index e617dd9335..c5f38e2bba 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_change_comment_parsing2.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_change_comment_parsing2.cf @@ -48,7 +48,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", "", ":"1000); + "teststr" string => readfile("$(G.testfile)"); "cnt" int => parsestringarrayidx("ary", "$(teststr)", "", ":", 10, 1000); "num" int => "9"; } diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_duplicates_trailing_newlines.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_duplicates_trailing_newlines.cf index 6e8edbf807..950f1c702c 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_duplicates_trailing_newlines.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_duplicates_trailing_newlines.cf @@ -68,42 +68,39 @@ bundle agent check classes: "ok" and => { + strcmp("$(test.num)", "$(test.cnt)"), + strcmp("$(test.ary[0][0])", "0"), + strcmp("$(test.ary[0][1])", "1"), + strcmp("$(test.ary[0][2])", "2"), + strcmp("$(test.ary[1][0])", "1"), + strcmp("$(test.ary[1][1])", "2"), + strcmp("$(test.ary[1][2])", "3"), + strcmp("$(test.ary[here is][0])", "here is"), + strcmp("$(test.ary[here is][1])", "a line"), + strcmp("$(test.ary[here is][2])", " with spaces "), + strcmp("$(test.ary[here is][3])", " in it"), + strcmp("$(test.ary[blank][0])", "blank"), + strcmp("$(test.ary[blank][1])", "fields"), + strcmp("$(test.ary[blank][2])", ""), + strcmp("$(test.ary[blank][3])", ""), + strcmp("$(test.ary[blank][4])", "in here"), + strcmp("$(test.ary[blank][5])", ""), + strcmp("$(test.ary[blank][6])", ""), + strcmp("$(test.ary[][0])", ""), + strcmp("$(test.ary[][1])", "leading blank field"), strcmp( - "$(test.num)", - "$(test.cnt)", - strcmp("$(test.ary[0][0])", "0"), - strcmp("$(test.ary[0][1])", "1"), - strcmp("$(test.ary[0][2])", "2"), - strcmp("$(test.ary[1][0])", "1"), - strcmp("$(test.ary[1][1])", "2"), - strcmp("$(test.ary[1][2])", "3"), - strcmp("$(test.ary[here is][0])", "here is"), - strcmp("$(test.ary[here is][1])", "a line"), - strcmp("$(test.ary[here is][2])", " with spaces "), - strcmp("$(test.ary[here is][3])", " in it"), - strcmp("$(test.ary[blank][0])", "blank"), - strcmp("$(test.ary[blank][1])", "fields"), - strcmp("$(test.ary[blank][2])", ""), - strcmp("$(test.ary[blank][3])", ""), - strcmp("$(test.ary[blank][4])", "in here"), - strcmp("$(test.ary[blank][5])", ""), - strcmp("$(test.ary[blank][6])", ""), - strcmp("$(test.ary[][0])", ""), - strcmp("$(test.ary[][1])", "leading blank field"), - strcmp( - "$(test.ary[# A duplicate follows][0])", "# A duplicate follows" - ), - strcmp( - "$(test.ary[# A duplicate follows][1])", - "this line is not always a comment" - ), - strcmp("$(test.ary[this][0])", "this"), - strcmp("$(test.ary[this][1])", "also"), - strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), - strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), - strcmp("$(test.ary[last][0])", "last"), - strcmp("$(test.ary[last][1])", "one") - , + "$(test.ary[# A duplicate follows][0])", "# A duplicate follows" + ), + strcmp( + "$(test.ary[# A duplicate follows][1])", + "this line is not always a comment" + ), + strcmp("$(test.ary[this][0])", "this"), + strcmp("$(test.ary[this][1])", "also"), + strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), + strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), + strcmp("$(test.ary[last][0])", "last"), + strcmp("$(test.ary[last][1])", "one"), }; reports: diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_duplicates_trailing_newlines2.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_duplicates_trailing_newlines2.cf index 0936f2cdcd..b0eaa9b9d3 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_duplicates_trailing_newlines2.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_duplicates_trailing_newlines2.cf @@ -51,7 +51,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", 1000); + "teststr" string => readfile("$(G.testfile)", 1000); "cnt" int => parsestringarrayidx( diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_real_comments3.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_real_comments3.cf index 196f151fc1..23112a5ac0 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_real_comments3.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_real_comments3.cf @@ -48,7 +48,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", "^#.*", ":"1000); + "teststr" string => readfile("$(G.testfile)"); "cnt" int => parsestringarrayidx("ary", "$(teststr)", "^#.*", ":", 10, 1000); diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_real_comments_noemptyfields4.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_real_comments_noemptyfields4.cf index 75a71e1ccc..62baef2e4d 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_real_comments_noemptyfields4.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarray_weird_indices_real_comments_noemptyfields4.cf @@ -48,7 +48,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", "^#.*", ":+"1000); + "teststr" string => readfile("$(G.testfile)"); "cnt" int => parsestringarrayidx("ary", "$(teststr)", "^#.*", ":+", 10, 1000); diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_change_separator_to_s.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_change_separator_to_s.cf index b426f4b0ac..01f1c9a8cf 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_change_separator_to_s.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_change_separator_to_s.cf @@ -48,7 +48,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", "^#.*", 1000); + "teststr" string => readfile("$(G.testfile)"); "cnt" int => parsestringarrayidx("ary", "$(teststr)", "^#.*", "s+", 10, 1000); diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_duplicate_key.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_duplicate_key.cf index ea69f69e27..6aa8390f74 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_duplicate_key.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_duplicate_key.cf @@ -43,7 +43,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", 1000); + "teststr" string => readfile("$(G.testfile)", 1000); "cnt" int => parsestringarrayidx( diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_nonparsed_comment.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_nonparsed_comment.cf index f13af81d87..0d2efd4db7 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_nonparsed_comment.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_nonparsed_comment.cf @@ -50,7 +50,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", 1000); + "teststr" string => readfile("$(G.testfile)", 1000); "cnt" int => parsestringarrayidx( diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_weird_indices_duplicate.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_weird_indices_duplicate.cf index 689cf2dfd7..64d4d3b3ab 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_weird_indices_duplicate.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_weird_indices_duplicate.cf @@ -48,7 +48,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", 1000); + "teststr" string => readfile("$(G.testfile)", 1000); "cnt" int => parsestringarrayidx( diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_weird_indices_real_comments_noemptyfields.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_weird_indices_real_comments_noemptyfields.cf index c622349459..d664a44bc8 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_weird_indices_real_comments_noemptyfields.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_weird_indices_real_comments_noemptyfields.cf @@ -48,7 +48,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", "^#.*", ":+"14); + "teststr" string => readfile("$(G.testfile)"); "cnt" int => parsestringarrayidx("ary", "$(teststr)", "^#.*", ":+", 10, 14); "num" int => "3"; } diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayinx_simple.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayinx_simple.cf index e674001f90..8713cbd6a9 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayinx_simple.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayinx_simple.cf @@ -42,7 +42,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", 1000); + "teststr" string => readfile("$(G.testfile)", 1000); "cnt" int => parsestringarrayidx( diff --git a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayinx_singleton_nootherfields.cf b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayinx_singleton_nootherfields.cf index 4c6023cd33..f558022b86 100644 --- a/tests/acceptance/01_vars/02_functions/staging/parsestringarrayinx_singleton_nootherfields.cf +++ b/tests/acceptance/01_vars/02_functions/staging/parsestringarrayinx_singleton_nootherfields.cf @@ -42,7 +42,7 @@ body delete init_delete bundle agent test { vars: - "teststr" str => readfile("$(G.testfile)", 1000); + "teststr" string => readfile("$(G.testfile)", 1000); "cnt" int => parsestringarrayidx(