control_common_bundlesequence_end .. a bug??
"'Nick Anderson' via help-cfengine" <[email protected]> Tue, 09 Sep 2025 12:27:24 -0500
| Newsgroups | gmane.comp.sysutils.cfengine.general |
|---|---|
| Message-ID | <[email protected]> |
--=-=-=
Content-Type: multipart/alternative; boundary="==-=-="
--==-=-=
Content-Type: text/plain; charset="UTF-8"
Response
========
Hi, thanks for bringing it up.
Indeed, I was able to reproduce the issue. And, I think you also
correctly spotted what is related to it.
<https://github.com/cfengine/masterfiles/blob/843a917db0e541d9a0c21a11e7886ddc30a2bec4/controls/def.cf#L285-L290>
,----
| "tbse" data => mergedata( "def.control_common_bundlesequence_end" );
| "bundlesequence_end" slist => getvalues( tbse );
|
| "tbse" data => mergedata( "def.control_common_bundlesequence_classification" );
| "bundlesequence_classification" slist => getvalues( tbse );
`----
Here a /temporary/ variable `tbse' is set twice, probably with the
thought that it would be fully re-defined. But when
`def.control_common_bundlesequence_classification' is not defined,
then `mergedata()' returns nothing.
For example here we see `j2m' doesn't get defined:
,----
| bundle agent main
| {
| vars:
| "j1" data => '["end_always"]';
|
| "j1m" data => mergedata( "j1" );
|
| "j2m" data => mergedata( "j2" );
|
|
| reports:
| "j1m: $(with)" with => storejson( "j1m" );
| "j2m: $(with)" with => storejson( "j2m" );
|
| }
`----
,----
| # cf-agent --no-lock --log-level info --show-evaluated-vars=main\\. --file ./example.cf
| R: j1m: [
| "end_always"
| ]
| R: j2m: $(with)
| Variable name Variable value Meta tags Comment
| default:main.j1 ["end_always"] source=promise
| default:main.j1m ["end_always"] source=promise
`----
To count the number of `end_always' in `bundlesequence':
,----
| cf-agent -KIf update.cf; cf-agent -Kv > out.log && grep "Using bundlesequence" out.log | awk '{print gsub("end_always", "&")}'
`----
Potential ways to address:
We could make the temporary variables uniquely named:
,----
| "tbse1" data => mergedata( "def.control_common_bundlesequence_end" );
| "bundlesequence_end" slist => getvalues( tbse1 );
| "tbse2" data => mergedata( "def.control_common_bundlesequence_classification" );
| "bundlesequence_classification" slist => getvalues( tbse2 );
`----
Define empty lists if control var not defined (as is the case when
defining from Augments), override with values of data from Augments.
We need to define an empty list or policy will error if it's not
defined.
,----
| "bundlesequence_end"
| slist => { },
| if => not( isvariable( "def.control_common_bundlesequence_end" ) );
| "bundlesequence_end" slist => getvalues( mergedata( "def.control_common_bundlesequence_end" ) );
|
| "bundlesequence_classification"
| slist => { },
| if => not( isvariable( "def.control_common_bundlesequence_classification" ) );
| "bundlesequence_classification" slist => getvalues( mergedata( "def.control_common_bundlesequence_classification" ) );
`----
Nested functions doesn't work
,----
| "bundlesequence_end" slist => getvalues( mergedata( "def.control_common_bundlesequence_end" ) );
| "bundlesequence_classification" slist => getvalues( mergedata( "def.control_common_bundlesequence_classification" ) );
`----
Because `getvalues()' on a variable that doesnt exist returns an
/empty slist/ but `getvalues()' on `mergedata()' that fails does not
return an empty list.
,----
| bundle agent main
| {
| vars:
| "l" slist => getvalues( "does_not_exist" );
| "j" slist => getvalues( mergedata( "does_not_exist" ) );
| }
`----
,----
| # cf-agent --no-lock --log-level info --show-evaluated-vars=main\\. --file ./example2.cf
| Variable name Variable value Meta tags Comment
| default:main.l source=promise
`----
I filed <https://northerntech.atlassian.net/browse/CFE-4588>
--
You received this message because you are subscribed to the Google Groups "help-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/help-cfengine/871poftu0t.fsf%40northern.tech.
--==-=-=
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<p>
Hi, thanks for bringing it up.
</p>
<p>
Indeed, I was able to reproduce the issue. And, I think you also correctly =
spotted what is related to it.
</p>
<p>
<a href=3D"https://github.com/cfengine/masterfiles/blob/843a917db0e541d9a0c=
21a11e7886ddc30a2bec4/controls/def.cf#L285-L290">https://github.com/cfengin=
e/masterfiles/blob/843a917db0e541d9a0c21a11e7886ddc30a2bec4/controls/def.cf=
#L285-L290</a>
</p>
<div class=3D"org-src-container">
<pre class=3D"src src-cfengine3"><span style=3D"color: #689d6a;">"tbse"</sp=
an> <span style=3D"color: #d79921;">data</span> =3D> mergedata<span styl=
e=3D"color: #689d6a;">(</span> <span style=3D"color: #689d6a;">"def.control=
_common_bundlesequence_end"</span> <span style=3D"color: #689d6a;">)</span>=
;
<span style=3D"color: #689d6a;">"bundlesequence_end"</span> <span style=3D"=
color: #d79921;">slist</span> =3D> getvalues<span style=3D"color: #689d6=
a;">(</span> tbse <span style=3D"color: #689d6a;">)</span>;
<span style=3D"color: #689d6a;">"tbse"</span> <span style=3D"color: #d79921=
;">data</span> =3D> mergedata<span style=3D"color: #689d6a;">(</span> <s=
pan style=3D"color: #689d6a;">"def.control_common_bundlesequence_classifica=
tion"</span> <span style=3D"color: #689d6a;">)</span>;
<span style=3D"color: #689d6a;">"bundlesequence_classification"</span> <spa=
n style=3D"color: #d79921;">slist</span> =3D> getvalues<span style=3D"co=
lor: #689d6a;">(</span> tbse <span style=3D"color: #689d6a;">)</span>;
</pre>
</div>
<p>
Here a <i>temporary</i> variable <code>tbse</code> is set twice, probably w=
ith the thought that it would be fully re-defined. But when <code>def.contr=
ol_common_bundlesequence_classification</code> is not defined, then <code>m=
ergedata()</code> returns nothing.
</p>
<p>
For example here we see <code>j2m</code> doesn't get defined:
</p>
<div class=3D"org-src-container">
<pre class=3D"src src-cfengine3"><span style=3D"color: #a89984; font-weight=
: bold;">bundle</span> <span style=3D"color: #458588; font-weight: bold;">a=
gent</span> <span style=3D"color: #458588;">main</span>
<span style=3D"color: #689d6a;">{</span>
<span style=3D"color: #a89984; font-weight: bold;">vars</span>:
<span style=3D"color: #689d6a;">"j1"</span> <span style=3D"color: #=
d79921;">data</span> =3D> <span style=3D"color: #689d6a;">'["end_always"=
]'</span>;
<span style=3D"color: #689d6a;">"j1m"</span> <span style=3D"color: =
#d79921;">data</span> =3D> mergedata<span style=3D"color: #d79921;">(</s=
pan> <span style=3D"color: #689d6a;">"j1"</span> <span style=3D"color: #d79=
921;">)</span>;
<span style=3D"color: #689d6a;">"j2m"</span> <span style=3D"color: =
#d79921;">data</span> =3D> mergedata<span style=3D"color: #d79921;">(</s=
pan> <span style=3D"color: #689d6a;">"j2"</span> <span style=3D"color: #d79=
921;">)</span>;
<span style=3D"color: #a89984; font-weight: bold;">reports</span>:
<span style=3D"color: #689d6a;">"j1m: $(with)"</span> with =3D> =
storejson<span style=3D"color: #d79921;">(</span> <span style=3D"color: #68=
9d6a;">"j1m"</span> <span style=3D"color: #d79921;">)</span>;
<span style=3D"color: #689d6a;">"j2m: $(with)"</span> with =3D> =
storejson<span style=3D"color: #d79921;">(</span> <span style=3D"color: #68=
9d6a;">"j2m"</span> <span style=3D"color: #d79921;">)</span>;
<span style=3D"color: #689d6a;">}</span>
</pre>
</div>
<pre class=3D"example">
# cf-agent --no-lock --log-level info --show-evaluated-vars=3Dmain\\. --fil=
e ./example.cf
R: j1m: [
"end_always"
]
R: j2m: $(with)
Variable name Variable value =
Meta tags Comment
default:main.j1 ["end_always"] =
source=3Dpromise
default:main.j1m ["end_always"] =
source=3Dpromise
</pre>
<p>
To count the number of <code>end_always</code> in <code>bundlesequence</cod=
e>:
</p>
<div class=3D"org-src-container">
<pre class=3D"src src-sh">cf-agent -KIf update.cf; cf-agent -Kv > out.lo=
g && grep <span style=3D"color: #689d6a;">"Using bundlesequence"</s=
pan> out.log | awk <span style=3D"color: #689d6a;">'{print gsub("end_always=
", "&")}'</span>
</pre>
</div>
<p>
Potential ways to address:
</p>
<p>
We could make the temporary variables uniquely named:
</p>
<pre class=3D"example" id=3D"org291e567">
"tbse1" data =3D> mergedata( "def.control_common_bundlesequence_end" );
"bundlesequence_end" slist =3D> getvalues( tbse1 );
"tbse2" data =3D> mergedata( "def.control_common_bundlesequence_classifi=
cation" );
"bundlesequence_classification" slist =3D> getvalues( tbse2 );
</pre>
<p>
Define empty lists if control var not defined (as is the case when defining=
from Augments), override with values of data from Augments.
</p>
<p>
We need to define an empty list or policy will error if it's not defined.
</p>
<pre class=3D"example" id=3D"orgea96e6f">
"bundlesequence_end"
slist =3D> { },
if =3D> not( isvariable( "def.control_common_bundlesequence_end" ) );
"bundlesequence_end" slist =3D> getvalues( mergedata( "def.control_commo=
n_bundlesequence_end" ) );
"bundlesequence_classification"
slist =3D> { },
if =3D> not( isvariable( "def.control_common_bundlesequence_classifica=
tion" ) );
"bundlesequence_classification" slist =3D> getvalues( mergedata( "def.co=
ntrol_common_bundlesequence_classification" ) );
</pre>
<p>
Nested functions doesn't work
</p>
<pre class=3D"example" id=3D"orgce9eb11">
"bundlesequence_end" slist =3D> getvalues( mergedata( "def.control_commo=
n_bundlesequence_end" ) );
"bundlesequence_classification" slist =3D> getvalues( mergedata( "def.co=
ntrol_common_bundlesequence_classification" ) );
</pre>
<p>
Because <code>getvalues()</code> on a variable that doesnt exist returns an=
<i>empty slist</i> but <code>getvalues()</code> on <code>mergedata()</code=
> that fails does not return an empty list.
</p>
<div class=3D"org-src-container">
<pre class=3D"src src-cfengine3"><span style=3D"color: #a89984; font-weight=
: bold;">bundle</span> <span style=3D"color: #458588; font-weight: bold;">a=
gent</span> <span style=3D"color: #458588;">main</span>
<span style=3D"color: #689d6a;">{</span>
<span style=3D"color: #a89984; font-weight: bold;">vars</span>:
<span style=3D"color: #689d6a;">"l"</span> <span style=3D"color: #d=
79921;">slist</span> =3D> getvalues<span style=3D"color: #d79921;">(</sp=
an> <span style=3D"color: #689d6a;">"does_not_exist"</span> <span style=3D=
"color: #d79921;">)</span>;
<span style=3D"color: #689d6a;">"j"</span> <span style=3D"color: #d=
79921;">slist</span> =3D> getvalues<span style=3D"color: #d79921;">(</sp=
an> mergedata<span style=3D"color: #458588;">(</span> <span style=3D"color:=
#689d6a;">"does_not_exist"</span> <span style=3D"color: #458588;">)</span>=
<span style=3D"color: #d79921;">)</span>;
<span style=3D"color: #689d6a;">}</span>
</pre>
</div>
<pre class=3D"example">
# cf-agent --no-lock --log-level info --show-evaluated-vars=3Dmain\\. --fil=
e ./example2.cf
Variable name Variable value =
Meta tags Comment
default:main.l =
source=3Dpromise
</pre>
<p>
I filed <a href=3D"https://northerntech.atlassian.net/browse/CFE-4588">htt=
ps://northerntech.atlassian.net/browse/CFE-4588</a>
</p>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;help-cfengine" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:[email protected]">help-=
[email protected]</a>.<br />
To view this discussion visit <a href=3D"https://groups.google.com/d/msgid/=
help-cfengine/871poftu0t.fsf%40northern.tech?utm_medium=3Demail&utm_source=
=3Dfooter">https://groups.google.com/d/msgid/help-cfengine/871poftu0t.fsf%4=
0northern.tech</a>.<br />
--==-=-=--
--=-=-=
Content-Type: text/plain; charset="UTF-8"
--
Nick Anderson | Doer of Things | (+1) 785-550-1767 | https://northern.tech
--
You received this message because you are subscribed to the Google Groups "help-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/help-cfengine/871poftu0t.fsf%40northern.tech.
--=-=-=--