Re: Re: Modify a YAML file

"'Lars Erik Wik' via help-cfengine" <[email protected]> Wed, 13 Aug 2025 00:23:18 -0700 (PDT)
Newsgroups gmane.comp.sysutils.cfengine.general
Message-ID <[email protected]>
------=_Part_632794_292615859.1755069798196
Content-Type: multipart/alternative; 
	boundary="----=_Part_632795_1087726372.1755069798196"

------=_Part_632795_1087726372.1755069798196
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

I believe replace_line_end should be usable more than once. Here is an=20
example doing so:

```cf3
body common control
{
  # Run bundles in this order
  bundlesequence =3D> { "init", "test", "check" };
  # Include files.cf from standard library
  inputs =3D> { "$(sys.libdir)/files.cf" };
}

bundle agent init
{
  # Create a file with original content
  files:
    "/tmp/somefile.yaml"
      content =3D> "ipaddr: 10.0.0.1
network: 10.0.0.0";
}

bundle agent test
{
  # Replace IP address of file
  files:
    "/tmp/somefile.yaml"
      edit_line =3D> replace_line_end("ipaddr:", "172.16.1.1");
    "/tmp/somefile.yaml"
      edit_line =3D> replace_line_end("network:", "172.16.1.0");
}

bundle agent check
{
  # Check if file has correct content after edit
  classes:
    "ok"
      expression =3D> strcmp(readfile("/tmp/somefile.yaml"), "ipaddr:=20
172.16.1.1
network: 172.16.1.0
"),
      if =3D> fileexists("/tmp/somefile.yaml");

  # Print message based on outcome
  reports:
    ok::
      "IP addr was replaced";
    !ok::
      "IP addr was not replaced";
}
```

And here is an example running that policy
```
$ sudo cf-agent -KIf ~/test.cf
    info: Updated file '/tmp/somefile.yaml' with content 'ipaddr: 10.0.0.1
network: 10.0.0.0'
    info: Set field sub-value '172.16.1.1' in '/tmp/somefile.yaml'
    info: fields_edit promise '\s*ipaddr:\s.*' repaired
    info: Edited file '/tmp/somefile.yaml'
    info: Set field sub-value '172.16.1.0' in '/tmp/somefile.yaml'
    info: fields_edit promise '\s*network:\s.*' repaired
    info: Edited file '/tmp/somefile.yaml'
R: IP addr was replaced
```

Hope this helps :)

Mustache templates that Craig mentioned is better if you want to control=20
the entire contents of the file. However, if you only need to configure=20
single lines in a file. E.g., make sure this line does (not) exist, or make=
=20
sure this field is configured to this value. Then edit_line is probably the=
=20
correct choice.
On Wednesday, August 13, 2025 at 3:29:20=E2=80=AFAM UTC+2 craig.c...@northe=
rn.tech=20
wrote:

> On Tue, Aug 12, 2025 at 05:04:16PM -0600, Jerome Verleyen wrote:
> > replace_line_end is usable just once. In
>
> I think you should use a mustache template with a files promise.
>
> Here is an example to get started. There is much more you can do dependin=
g=20
> on the data you provide and the nesting available.
>
>
> https://docs.cfengine.com/docs/3.24/examples-tutorials-render-files-with-=
mustache-templates.html#top
>
> -Craig
>

--=20
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 e=
mail to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/help-cfengi=
ne/6e053d95-c714-4bd9-b194-2714a18c9153n%40googlegroups.com.

------=_Part_632795_1087726372.1755069798196
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div>I believe=C2=A0replace_line_end should be usable more than once. Here =
is an example doing so:<br /><br /></div><div>```cf3</div><div>body common =
control<br />{<br />=C2=A0 # Run bundles in this order<br />=C2=A0 bundlese=
quence =3D&gt; { "init", "test", "check" };<br />=C2=A0 # Include files.cf =
from standard library<br />=C2=A0 inputs =3D&gt; { "$(sys.libdir)/files.cf"=
 };<br />}<br /><br />bundle agent init<br />{<br />=C2=A0 # Create a file =
with original content<br />=C2=A0 files:<br />=C2=A0 =C2=A0 "/tmp/somefile.=
yaml"<br />=C2=A0 =C2=A0 =C2=A0 content =3D&gt; "ipaddr: 10.0.0.1<br />netw=
ork: 10.0.0.0";<br />}<br /><br />bundle agent test<br />{<br />=C2=A0 # Re=
place IP address of file<br />=C2=A0 files:<br />=C2=A0 =C2=A0 "/tmp/somefi=
le.yaml"<br />=C2=A0 =C2=A0 =C2=A0 edit_line =3D&gt; replace_line_end("ipad=
dr:", "172.16.1.1");<br />=C2=A0 =C2=A0 "/tmp/somefile.yaml"<br />=C2=A0 =
=C2=A0 =C2=A0 edit_line =3D&gt; replace_line_end("network:", "172.16.1.0");=
<br />}<br /><br />bundle agent check<br />{<br />=C2=A0 # Check if file ha=
s correct content after edit<br />=C2=A0 classes:<br />=C2=A0 =C2=A0 "ok"<b=
r />=C2=A0 =C2=A0 =C2=A0 expression =3D&gt; strcmp(readfile("/tmp/somefile.=
yaml"), "ipaddr: 172.16.1.1<br />network: 172.16.1.0<br />"),<br />=C2=A0 =
=C2=A0 =C2=A0 if =3D&gt; fileexists("/tmp/somefile.yaml");<br /><br />=C2=
=A0 # Print message based on outcome<br />=C2=A0 reports:<br />=C2=A0 =C2=
=A0 ok::<br />=C2=A0 =C2=A0 =C2=A0 "IP addr was replaced";<br />=C2=A0 =C2=
=A0 !ok::<br />=C2=A0 =C2=A0 =C2=A0 "IP addr was not replaced";<br />}</div=
><div>```<br /><br />And here is an example running that policy</div>```<br=
 />$ sudo cf-agent -KIf ~/test.cf<br />=C2=A0 =C2=A0 info: Updated file '/t=
mp/somefile.yaml' with content 'ipaddr: 10.0.0.1<br />network: 10.0.0.0'<br=
 />=C2=A0 =C2=A0 info: Set field sub-value '172.16.1.1' in '/tmp/somefile.y=
aml'<br />=C2=A0 =C2=A0 info: fields_edit promise '\s*ipaddr:\s.*' repaired=
<br />=C2=A0 =C2=A0 info: Edited file '/tmp/somefile.yaml'<br />=C2=A0 =C2=
=A0 info: Set field sub-value '172.16.1.0' in '/tmp/somefile.yaml'<br />=C2=
=A0 =C2=A0 info: fields_edit promise '\s*network:\s.*' repaired<br />=C2=A0=
 =C2=A0 info: Edited file '/tmp/somefile.yaml'<br />R: IP addr was replaced=
<br />```<br /><br />Hope this helps :)<div><br /></div><div>Mustache templ=
ates that Craig mentioned is better if you want to control the entire conte=
nts of the file. However, if you only need to configure single lines in a f=
ile. E.g., make sure this line does (not) exist, or make sure this field is=
 configured to this value. Then edit_line is probably the correct choice.</=
div><div class=3D"gmail_quote"><div dir=3D"auto" class=3D"gmail_attr">On We=
dnesday, August 13, 2025 at 3:29:20=E2=80=AFAM UTC+2 [email protected]=
ch wrote:<br/></div><blockquote class=3D"gmail_quote" style=3D"margin: 0 0 =
0 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">On =
Tue, Aug 12, 2025 at 05:04:16PM -0600, Jerome Verleyen wrote:
<br>&gt; replace_line_end is usable just once. In
<br>
<br>I think you should use a mustache template with a files promise.
<br>
<br>Here is an example to get started. There is much more you can do depend=
ing on the data you provide and the nesting available.
<br>
<br><a href=3D"https://docs.cfengine.com/docs/3.24/examples-tutorials-rende=
r-files-with-mustache-templates.html#top" target=3D"_blank" rel=3D"nofollow=
" data-saferedirecturl=3D"https://www.google.com/url?hl=3Den&amp;q=3Dhttps:=
//docs.cfengine.com/docs/3.24/examples-tutorials-render-files-with-mustache=
-templates.html%23top&amp;source=3Dgmail&amp;ust=3D1755155573188000&amp;usg=
=3DAOvVaw0Wgp6wd_-1UwUb-UwHFHls">https://docs.cfengine.com/docs/3.24/exampl=
es-tutorials-render-files-with-mustache-templates.html#top</a>
<br>
<br>-Craig
<br></blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;help-cfengine&quot; 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/6e053d95-c714-4bd9-b194-2714a18c9153n%40googlegroups.com?utm_=
medium=3Demail&utm_source=3Dfooter">https://groups.google.com/d/msgid/help-=
cfengine/6e053d95-c714-4bd9-b194-2714a18c9153n%40googlegroups.com</a>.<br /=
>

------=_Part_632795_1087726372.1755069798196--

------=_Part_632794_292615859.1755069798196--