Re: Newbie questions
"'Nick Anderson' via help-cfengine" <[email protected]> Fri, 08 Aug 2025 17:54:50 -0500
| Newsgroups | gmane.comp.sysutils.cfengine.general |
|---|---|
| Message-ID | <[email protected]> |
--=-=-= Content-Type: multipart/alternative; boundary="==-=-=" --==-=-= Content-Type: text/plain; charset="UTF-8" IN_PROGRESS Respond to Jakub Wardyn <[email protected]>: Re: [help-cfengine] Newbie questions :email: ============================================================================================ Hi Jakub, Welcome to CFEngine. I will jump around a bit in my response. - Is there any "practical" guide for CFEngine which is reasonably recent, and can guide me through building small-scale stuff from the grounds up. I'd appreciate a link. I don't think there is a single guide that works for everyone. If I had to provide but a single link it would have to be <https://docs.cfengine.com>. Right now I have a couple of servers, on which I want to deploy some services (some in Docker, some as regular processes), I want a solution where I can describe that declaratively, and have a e.g. git repository with "current state of everything that's running on my servers", I also want to automate stuff like setting up backups, updating the system, etc. It's all Linux for now, and I expect the number of servers to grow in the future. This sounds like stuff that CFEngine can help you with. You might find `promise-type-docker-compose' useful or a source of inspirational (<https://build.cfengine.com/modules/promise-type-docker-compose/>). - And honestly, is CFEngine even the right tool for use cases like mine? I don't mind tinkering a bit and working in low-level stuff, but I hate fighting with the complexity of my tools. I want a simple low-level tool with which I build my own automation, not an "out-of-the-box" corporate solution for thousands of servers. So, you have some servers running Linux and you want a tool that can help you manage configuration files, processes and help you adjust and maintain the state of the running systems over time. You want something simple and low level to build your own system with and not an out of the box solution. I am bias, but I think CFEngine sounds like a natural fit. I think that CFEngine is simple, but I guess it's subjective. I am at least quite familiar with how it operates. If you find yourself "fighting" with CFEngine maybe take a step back and see if you can approach from a different perspective. I remember when starting with CFEngine that it changed the way I thought about things. - How to deal with the differences between paths in different distros? Should I just roll out CFEngine manually? I thought I can just install CFEngine in anyway, and then bootstrap and it will figure everything out from there, seems like that's not the case. I hope the "hub" can tell the agents where to look for the policies? Or is the files structure just coupled together everywhere? I think it's important to remember the agency of the agents, no one tells an agent anything. Perhaps imagine yourself as the agent rather than hollering at the hub in the sky ask where you should look for your policy think what in my environment can I clue in on to figure out where to get policy. Installing and bootstrapping to a hub and then figuring things out is totally possible. That's I think what most people do. By default the MPF doesn't really do much of anything. I am not sure what you mean by "is the file structure just coupled together everywhere". How to deal with the difference in paths between different distros? There are fundamental lower level answers to this but perhaps that leads well into your question if you need the MPF. - Do I need MPF? If I have a git repo do I just copy MPF into it? What does MPF do for me? The very reason that I wanted to learn CFEngine is the simplicity and transparency of what it does, MPF seems to contradict that. Categorically, I can tell you that you do not *need* the MPF. However, it does offer something to build off of and the policy is instrumented in the most common places so that you can tweak behavior without having to modify the vendored policy. Plus, there is often an assumption of use so if you are not using it it's good to highlight that fact. You can build a much leaner policy set, that covers just what you need. This goes back to dealing with differences in paths between repos and binaries. The MPF didn't always exist. In the early versions of 3.x up to maybe 3.5 there wasn't much to graft on to (<https://github.com/cfengine/core/tree/3.0.0/inputs>). So, the questions from that period of time led to the structure of the Masterfiles Policy Framework MPF forming. - Is there any "practical" guide for CFEngine which is reasonably recent, and can guide me through building small-scale stuff from the grounds up. I'd appreciate a link. I think the all time best way of learning CFEngine is live in person training. The best book is Diegos Learning CFEngine (<https://cf-learn.info/>). It's not current, but all the basics are in there and I recall when the book came out wishing I had that book when I started learning CFEngine. I referred to things in it for many years. Aleksey Tslalokhin published the content that he used for CFEngine training. You can use it as a self guided tutorial. <https://www.softcover.io/read/72be7d4f/cf3/_single-page> I think that modern practical guides focus on leveraging the newer higher level tools that are available (<https://docs.cfengine.com/docs/3.24/getting-started.html>). If you do choose to write your own policy, I will say that you might find `cf-locate' (<https://github.com/cfengine/core/tree/master/contrib/cf-locate>) useful. You could use it to lift out specific body and bundles from the standard library to keep your own policy set extremely minimal. The follow-up from [2025-08-04 Mon] : Got quick two questions: Can strings in CFEngine be split up into multiline without defining additional variables, and without adding unintended whitespaces? E.g. In C++ I'd do something like this: ``` const char* string = "This is my first line," " this is another line"; ``` Which evaluates to "This is my first line, this is another line" Yep, you can. ,---- | bundle agent __main__ | { | vars: | "s1" string => "Here | is | a | multiline string \ | where I \ | have escaped some \ | but not other newlines. | "; | | # Sometimes there is preference to use concat() | "s2" string => concat("Here we", | " bring some strings", | ' together and show', | ` various quoting of`, | ` strings which contain quoteing chars "'"'`, | " handy tricks indeed to avoid escapes" ); | | | reports: | "$(s1)"; | "$(s2)"; | } `---- ,---- | R: Here | is | a | multiline string where I have escaped some but not other newlines. | | R: Here we bring some strings together and show various quoting of strings which contain quoteing chars "'"' handy tricks indeed to avoid escapes `---- Can I build my own bundles/functions which return values? I've seen that bundles can modify variables and define class in the parent scope, but that seems quite horrible. I mean something like this: ``` vars: "my_value" string => do_http_request("some arguments here"); ``` where "do_http_request" is some wrapper around Curl that I can write on my own, can't use url_get, because the binary on Alpine is compiled without curl support, and I would rather not bother with that, and instead do what I would do in other languages: abstract the mundane task of calling curl into something less repetitive. Yes, it's possible to define your own bundles and bodies (it's quite expected that you will). I recommend reading through the language concepts section of the reference manual (<https://docs.cfengine.com/docs/3.24/reference-language-concepts.html>). You can even define your own promise types (<https://cfengine.com/blog/2020/introducing-cfengine-custom-promise-types/>) but there is not currently any ability to define custom /functions/. I think it's important to remember that bundles are not functions (<https://docs.cfengine.com/docs/3.24/reference-language-concepts-bundles.html>). Though you can use them in that way and they have the ability to return data into the calling bundle via /reports/ promises using `bundle_return_value_index' (<https://docs.cfengine.com/docs/3.26/reference-promise-types-reports.html#bundle_return_value_index>) and `useresult' (<https://docs.cfengine.com/docs/3.26/reference-promise-types-methods.html#useresult>) Here is an example: ,---- | bundle agent __main__ | { | methods: | "Call my bundle with params and define a variable with returned data" | usebundle => myBundle("KEY", "VALUE"), | useresult => "returned_from_myBundle"; | | "More ...." | usebundle => myBundle("CFEngine", "Awesome"), | useresult => "returned_from_myBundle"; | | "Calculator" | usebundle => add("5266", "42", "value"), | useresult => "sum"; | | reports: | "CFEngine version: $(sys.cf_version)"; | "$(with)" | with => storejson( returned_from_myBundle ); | | "Calculated $(sum[value])"; | } | bundle agent myBundle(key, value) | { | reports: | "$(value)" | bundle_return_value_index => "$(key)"; | } | bundle agent add(int1, int2, key) | { | reports: | "$(with)" | with => int( eval( "$(int1)+$(int2)", "math", "infix" ) ), | bundle_return_value_index => "$(key)"; | } `---- ,---- | R: CFEngine version: 3.27.0a.5553c81fe | R: { | "CFEngine": "Awesome", | "KEY": "VALUE" | } | R: Calculated 5308 `---- Modules are another thing to know about (<https://docs.cfengine.com/docs/3.26/reference-language-concepts-modules.html#top>). There are a lot of different kinds of modules in CFEngine. There are the traditional variables and classes modules which allow you to define variables and classes from external programs via a simple line based protocol. You can use modules in different ways but primarily via `usemodule()' (<https://docs.cfengine.com/docs/3.26/reference-functions-usemodule.html#top>) or via commands with `module => true' (<https://docs.cfengine.com/docs/3.26/reference-promise-types-commands.html#module>). Then there are package modules which are external programs that communicate with CFEngine to implement packages promises, promise modules which are for defining custom promise types and CFEngine Build Modules (<https://build.cfengine.com/>) which are collections of policy or other CFEngine related content. -- 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/87ikix8lvm.fsf%40northern.tech. --==-=-= Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <p> Hi Jakub, </p> <p> Welcome to CFEngine. I will jump around a bit in my response. </p> <blockquote style=3D"border-left: 2px solid gray; padding-left: 4px;"> <ul class=3D"org-ul"> <li>Is there any "practical" guide for CFEngine which is reasonably recent,= and can guide me through building small-scale stuff from the grounds up. I'd appreciate a link.</li> </ul> </blockquote> <p> I don't think there is a single guide that works for everyone. If I had to = provide but a single link it would have to be <a href=3D"https://docs.cfeng= ine.com">https://docs.cfengine.com</a>. </p> <blockquote style=3D"border-left: 2px solid gray; padding-left: 4px;"> <p> Right now I have a couple of servers, on which I want to deploy some servic= es (some in Docker, some as regular processes), I want a solution where I can describe that declaratively, and have a e.g. git repository with "current s= tate of everything that's running on my servers", I also want to automate stuff = like setting up backups, updating the system, etc. It's all Linux for now, and I expect the number of servers to grow in the future. </p> </blockquote> <p> This sounds like stuff that CFEngine can help you with. You might find <code>promise-type-docker-compose</code> useful or a source = of inspirational (<a href=3D"https://build.cfengine.com/modules/promise-typ= e-docker-compose/">https://build.cfengine.com/modules/promise-type-docker-c= ompose/</a>). </p> <blockquote style=3D"border-left: 2px solid gray; padding-left: 4px;"> <ul class=3D"org-ul"> <li>And honestly, is CFEngine even the right tool for use cases like mine? = I don't mind tinkering a bit and working in low-level stuff, but I hate fighting wi= th the complexity of my tools. I want a simple low-level tool with which I bui= ld my own automation, not an "out-of-the-box" corporate solution for thousands= of servers.</li> </ul> </blockquote> <p> So, you have some servers running Linux and you want a tool that can help y= ou manage configuration files, processes and help you adjust and maintain the = state of the running systems over time. You want something simple and low level t= o build your own system with and not an out of the box solution. </p> <p> I am bias, but I think CFEngine sounds like a natural fit. </p> <p> I think that CFEngine is simple, but I guess it's subjective. I am at least quite familiar with how it operates. If you find yourself "fighting" with CFEngine maybe take a step back and see if you can approach from a differen= t perspective. I remember when starting with CFEngine that it changed the way= I thought about things. </p> <blockquote style=3D"border-left: 2px solid gray; padding-left: 4px;"> <ul class=3D"org-ul"> <li>How to deal with the differences between paths in different distros? Sh= ould I just roll out CFEngine manually? I thought I can just install CFEngine in anyway, and then bootstrap and it will figure everything out from there, se= ems like that's not the case. I hope the "hub" can tell the agents where to loo= k for the policies? Or is the files structure just coupled together everywher= e?</li> </ul> </blockquote> <p> I think it's important to remember the agency of the agents, no one tells a= n agent anything. Perhaps imagine yourself as the agent rather than hollering= at the hub in the sky ask where you should look for your policy think what in = my environment can I clue in on to figure out where to get policy. </p> <p> Installing and bootstrapping to a hub and then figuring things out is total= ly possible. That's I think what most people do. By default the MPF doesn't re= ally do much of anything. </p> <p> I am not sure what you mean by "is the file structure just coupled together= everywhere". </p> <p> How to deal with the difference in paths between different distros? There a= re fundamental lower level answers to this but perhaps that leads well into yo= ur question if you need the MPF. </p> <blockquote style=3D"border-left: 2px solid gray; padding-left: 4px;"> <ul class=3D"org-ul"> <li>Do I need MPF? If I have a git repo do I just copy MPF into it? What do= es MPF do for me? The very reason that I wanted to learn CFEngine is the simplicit= y and transparency of what it does, MPF seems to contradict that.</li> </ul> </blockquote> <p> Categorically, I can tell you that you do not <b>need</b> the MPF. However,= it does offer something to build off of and the policy is instrumented in the most common places so that you can tweak behavior without having to modify the vendored policy. Plus, there is often an assumption of use so if you are no= t using it it's good to highlight that fact. You can build a much leaner poli= cy set, that covers just what you need. This goes back to dealing with differe= nces in paths between repos and binaries. </p> <p> The MPF didn't always exist. In the early versions of 3.x up to maybe 3.5 t= here wasn't much to graft on to (<a href=3D"https://github.com/cfengine/core/tre= e/3.0.0/inputs">https://github.com/cfengine/core/tree/3.0.0/inputs</a>). So= , the questions from that period of time led to the structure of the Masterfiles Policy Framework MPF forming. </p> <blockquote style=3D"border-left: 2px solid gray; padding-left: 4px;"> <ul class=3D"org-ul"> <li>Is there any "practical" guide for CFEngine which is reasonably recent,= and can guide me through building small-scale stuff from the grounds up. I'd appreciate a link.</li> </ul> </blockquote> <p> I think the all time best way of learning CFEngine is live in person traini= ng. </p> <p> The best book is Diegos Learning CFEngine (<a href=3D"https://cf-learn.info= /">https://cf-learn.info/</a>). It's not current, but all the basics are in= there and I recall when the book came out wishing I had that book when I s= tarted learning CFEngine. I referred to things in it for many years. </p> <p> Aleksey Tslalokhin published the content that he used for CFEngine training= . You can use it as a self guided tutorial. <a href=3D"https://www.softcove= r.io/read/72be7d4f/cf3/_single-page">https://www.softcover.io/read/72be7d4f= /cf3/_single-page</a> </p> <p> I think that modern practical guides focus on leveraging the newer higher l= evel tools that are available (<a href=3D"https://docs.cfengine.com/docs/3.24/ge= tting-started.html">https://docs.cfengine.com/docs/3.24/getting-started.htm= l</a>). </p> <p> If you do choose to write your own policy, I will say that you might find <= code>cf-locate</code> (<a href=3D"https://github.com/cfengine/core/tree/mas= ter/contrib/cf-locate">https://github.com/cfengine/core/tree/master/contrib= /cf-locate</a>) useful. You could use it to lift out specific body and bund= les from the standard library to keep your own policy set extremely minimal= . </p> <p> The follow-up from <span class=3D"timestamp-wrapper"><span class=3D"timesta= mp">[2025-08-04 Mon] </span></span> : </p> <blockquote style=3D"border-left: 2px solid gray; padding-left: 4px;"> <p> Got quick two questions: Can strings in CFEngine be split up into multiline without defining additio= nal variables, and without adding unintended whitespaces? E.g. In C++ I'd do something like this: ``` const char* string =3D "This is my first line," " this is another line"; ``` Which evaluates to "This is my first line, this is another line" </p> </blockquote> <p> Yep, you can. </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;">"s1"</span> <span style=3D"color: #d7= 9921;">string</span> =3D> <span style=3D"color: #689d6a;">"Here is a multiline string \ where I \ have escaped some \ but not other newlines. "</span>; <span style=3D"color: #7c6f64;"># Sometimes there is preference to us= e concat() </span> <span style=3D"color: #689d6a;">"s2"</span> <span style=3D"col= or: #d79921;">string</span> =3D> concat<span style=3D"color: #d79921;">(= </span><span style=3D"color: #689d6a;">"Here we"</span>, <span style=3D"color: #689d6a;">" bring some st= rings"</span>, <span style=3D"color: #689d6a;">' together and = show'</span>, ` various quoting of`, ` strings which contain quoteing chars <span st= yle=3D"color: #689d6a;">"'"'`, " handy tricks indeed to avoid escapes" ); reports: "$(s1)"; "$(s2)"; }</span> </pre> </div> <pre class=3D"example"> R: Here is a multiline string where I have escaped some but not other newlines. R: Here we bring some strings together and show various quoting of strings = which contain quoteing chars "'"' handy tricks indeed to avoid escapes </pre> <blockquote style=3D"border-left: 2px solid gray; padding-left: 4px;"> <p> Can I build my own bundles/functions which return values? I've seen that bu= ndles can modify variables and define class in the parent scope, but that seems quite horrible. I mean something = like this: ``` vars: "my_value" string =3D> do_http_request("some arguments here"); ``` where "do_http_request" is some wrapper around Curl that I can write on my = own, can't use url_get, because the binary on Alpine is compiled without curl su= pport, and I would rather not bother with that, and instead do what I would do in other languages: abstract the mundane tas= k of calling curl into something less repetitive. </p> </blockquote> <p> Yes, it's possible to define your own bundles and bodies (it's quite expect= ed that you will). </p> <p> I recommend reading through the language concepts section of the reference = manual (<a href=3D"https://docs.cfengine.com/docs/3.24/reference-language-c= oncepts.html">https://docs.cfengine.com/docs/3.24/reference-language-concep= ts.html</a>). You can even define your own promise types (<a href=3D"https:= //cfengine.com/blog/2020/introducing-cfengine-custom-promise-types/">https:= //cfengine.com/blog/2020/introducing-cfengine-custom-promise-types/</a>) bu= t there is not currently any ability to define custom <i>functions</i>. </p> <p> I think it's important to remember that bundles are not functions (<a href= =3D"https://docs.cfengine.com/docs/3.24/reference-language-concepts-bundles= .html">https://docs.cfengine.com/docs/3.24/reference-language-concepts-bund= les.html</a>). Though you can use them in that way and they have the abilit= y to return data into the calling bundle via <i>reports</i> promises using = <code>bundle_return_value_index</code> (<a href=3D"https://docs.cfengine.co= m/docs/3.26/reference-promise-types-reports.html#bundle_return_value_index"= >https://docs.cfengine.com/docs/3.26/reference-promise-types-reports.html#b= undle_return_value_index</a>) and <code>useresult</code> (<a href=3D"https:= //docs.cfengine.com/docs/3.26/reference-promise-types-methods.html#useresul= t">https://docs.cfengine.com/docs/3.26/reference-promise-types-methods.html= #useresult</a>) </p> <p> Here is an example: </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;">methods</span>: <span style=3D"color: #689d6a;">"Call my bundle with params and defin= e a variable with returned data"</span> usebundle =3D> myBundle<span style=3D"color: #d79921;">(</span><= span style=3D"color: #689d6a;">"KEY"</span>, <span style=3D"color: #689d6a;= ">"VALUE"</span><span style=3D"color: #d79921;">)</span>, useresult =3D> <span style=3D"color: #689d6a;">"returned_from_my= Bundle"</span>; <span style=3D"color: #689d6a;">"More ...."</span> usebundle =3D> myBundle<span style=3D"color: #d79921;">(</span><= span style=3D"color: #689d6a;">"CFEngine"</span>, <span style=3D"color: #68= 9d6a;">"Awesome"</span><span style=3D"color: #d79921;">)</span>, useresult =3D> <span style=3D"color: #689d6a;">"returned_from_my= Bundle"</span>; <span style=3D"color: #689d6a;">"Calculator"</span> usebundle =3D> add<span style=3D"color: #d79921;">(</span><span = style=3D"color: #689d6a;">"5266"</span>, <span style=3D"color: #689d6a;">"4= 2"</span>, <span style=3D"color: #689d6a;">"value"</span><span style=3D"col= or: #d79921;">)</span>, useresult =3D> <span style=3D"color: #689d6a;">"sum"</span>; <span style=3D"color: #a89984; font-weight: bold;">reports</span>: <span style=3D"color: #689d6a;">"CFEngine version: $(sys.cf_version)"= </span>; <span style=3D"color: #689d6a;">"$(with)"</span> with =3D> storejson<span style=3D"color: #d79921;">(</span> retu= rned_from_myBundle <span style=3D"color: #d79921;">)</span>; <span style=3D"color: #689d6a;">"Calculated $(sum[value])"</span>; <span style=3D"color: #689d6a;">}</span> <span style=3D"color: #a89984; font-weight: bold;">bundle</span> <span styl= e=3D"color: #458588; font-weight: bold;">agent</span> <span style=3D"color:= #458588;">myBundle</span><span style=3D"color: #689d6a;">(</span><span sty= le=3D"color: #458588;">key, value</span><span style=3D"color: #689d6a;">)</= span> <span style=3D"color: #689d6a;">{</span> <span style=3D"color: #a89984; font-weight: bold;">reports</span>: <span style=3D"color: #689d6a;">"$(value)"</span> bundle_return_value_index =3D> <span style=3D"color: #689d6a;">"= $(key)"</span>; <span style=3D"color: #689d6a;">}</span> <span style=3D"color: #a89984; font-weight: bold;">bundle</span> <span styl= e=3D"color: #458588; font-weight: bold;">agent</span> <span style=3D"color:= #458588;">add</span><span style=3D"color: #689d6a;">(</span><span style=3D= "color: #458588;">int1, int2, key</span><span style=3D"color: #689d6a;">)</= span> <span style=3D"color: #689d6a;">{</span> <span style=3D"color: #a89984; font-weight: bold;">reports</span>: <span style=3D"color: #689d6a;">"$(with)"</span> with =3D> <span style=3D"color: #d79921;">int</span><span style= =3D"color: #d79921;">(</span> eval<span style=3D"color: #458588;">(</span> = <span style=3D"color: #689d6a;">"$(int1)+$(int2)"</span>, <span style=3D"co= lor: #689d6a;">"math"</span>, <span style=3D"color: #689d6a;">"infix"</span= > <span style=3D"color: #458588;">)</span> <span style=3D"color: #d79921;">= )</span>, bundle_return_value_index =3D> <span style=3D"color: #689d6a;">"= $(key)"</span>; <span style=3D"color: #689d6a;">}</span> </pre> </div> <pre class=3D"example"> R: CFEngine version: 3.27.0a.5553c81fe R: { "CFEngine": "Awesome", "KEY": "VALUE" } R: Calculated 5308 </pre> <p> Modules are another thing to know about (<a href=3D"https://docs.cfengine.c= om/docs/3.26/reference-language-concepts-modules.html#top">https://docs.cfe= ngine.com/docs/3.26/reference-language-concepts-modules.html#top</a>). Ther= e are a lot of different kinds of modules in CFEngine. There are the tradit= ional variables and classes modules which allow you to define variables and= classes from external programs via a simple line based protocol. You can u= se modules in different ways but primarily via <code>usemodule()</code> (<a= href=3D"https://docs.cfengine.com/docs/3.26/reference-functions-usemodule.= html#top">https://docs.cfengine.com/docs/3.26/reference-functions-usemodule= .html#top</a>) or via commands with <code>module =3D> true</code> (<a hr= ef=3D"https://docs.cfengine.com/docs/3.26/reference-promise-types-commands.= html#module">https://docs.cfengine.com/docs/3.26/reference-promise-types-co= mmands.html#module</a>). Then there are package modules which are external = programs that communicate with CFEngine to implement packages promises, pro= mise modules which are for defining custom promise types and CFEngine Build= Modules (<a href=3D"https://build.cfengine.com/">https://build.cfengine.co= m/</a>) which are collections of policy or other CFEngine related content. </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/87ikix8lvm.fsf%40northern.tech?utm_medium=3Demail&utm_source= =3Dfooter">https://groups.google.com/d/msgid/help-cfengine/87ikix8lvm.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/87ikix8lvm.fsf%40northern.tech. --=-=-=--