# Chef Recipe inserting a line before last line in fie

**URL:** <https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380>\
**Category:** Chef Infra (archive)\
**Created:** [December 9, 2012, 6:37am UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380 "2012-12-09T06:37:04Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chucker42](https://avatars.discourse-cdn.com/v4/letter/c/9de053/32.png) [@Chucker42](https://discourse.chef.io/u/Chucker42)\
**Post date:** [December 9, 2012, 6:37am UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/1 "2012-12-09T06:37:04Z")

</div>

Hello,

I am new to Chef and Ruby and trying to figure out the proper way to add a line  
to /etc/security/access.conf prior to the last line that denies everything not  
already defined.

Not sure yet whether the best way is to use a Chef command of a Ruby Block.

I do not see a way in Chef to insert a new line searched for if the line does  
not already exist in the file prior to another line in the file.

I thought this would work:

file.replace\_line\_if\_no\_match but that adds it after the last line in the file.  
In security, all the entries in access.conf that allow access have to be prior  
to the line that denies everything not already allowed.

Basically, I want to see if “+:mongod:cron crond\n” already exists. If it  
does, do not do anything. However, if it does not exist, insert it prior to “-  
: ALL : ALL\n”.

What is the best way in a Chef Recipe to do this?

Thank you.

* * *

Charles Keagle  
[a-ckeagle@expedia.com](mailto:a-ckeagle@expedia.com)  
425-417-3434

---

<div class="post-metadata">

**Author:** ![AJ\_Christensen](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/aj_christensen/32/525_2.png) [@AJ\_Christensen](https://discourse.chef.io/u/AJ_Christensen)\
**Post date:** [December 9, 2012, 6:48am UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/2 "2012-12-09T06:48:01Z")

</div>

Template the whole file

Cheers,

AJ

On 9 December 2012 19:37, [chucker42@comcast.net](mailto:chucker42@comcast.net) wrote:

> Hello,
> 
> I am new to Chef and Ruby and trying to figure out the proper way to add a  
> line  
> to /etc/security/access.conf prior to the last line that denies everything  
> not  
> already defined.
> 
> Not sure yet whether the best way is to use a Chef command of a Ruby Block.
> 
> I do not see a way in Chef to insert a new line searched for if the line  
> does  
> not already exist in the file prior to another line in the file.
> 
> I thought this would work:
> 
> file.replace\_line\_if\_no\_match but that adds it after the last line in the  
> file.  
> In security, all the entries in access.conf that allow access have to be  
> prior  
> to the line that denies everything not already allowed.
> 
> Basically, I want to see if "+:mongod:cron crond\n" already exists. If it  
> does, do not do anything. However, if it does not exist, insert it prior  
> to "-  
> : ALL : ALL\n".
> 
> What is the best way in a Chef Recipe to do this?
> 
> Thank you.
> 
> * * *
> 
> Charles Keagle  
> [a-ckeagle@expedia.com](mailto:a-ckeagle@expedia.com)  
> 425-417-3434

---

<div class="post-metadata">

**Author:** ![Sean\_OMeara](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/sean_omeara/32/435_2.png) [@Sean\_OMeara](https://discourse.chef.io/u/Sean_OMeara)\
**Post date:** [December 9, 2012, 8:55am UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/3 "2012-12-09T08:55:56Z")

</div>

Hi Charles!

This comes up ALL THE TIME, so...

I whipped up a line cookbook on the community site that'll help you out.

add depends 'line' in a cookbook's metadata.rb, then in a recipe you can say:

append\_if\_no\_line "hello world" do  
file "/tmp/dangerfile"  
string "HI THERE I AM STRING"  
end

It's alpha code cut at 4am, so let me know how it works =)  
-s

On Sun, Dec 9, 2012 at 1:37 AM, [chucker42@comcast.net](mailto:chucker42@comcast.net) wrote:

> Hello,
> 
> I am new to Chef and Ruby and trying to figure out the proper way to add a line  
> to /etc/security/access.conf prior to the last line that denies everything not  
> already defined.
> 
> Not sure yet whether the best way is to use a Chef command of a Ruby Block.
> 
> I do not see a way in Chef to insert a new line searched for if the line does  
> not already exist in the file prior to another line in the file.
> 
> I thought this would work:
> 
> file.replace\_line\_if\_no\_match but that adds it after the last line in the file.  
> In security, all the entries in access.conf that allow access have to be prior  
> to the line that denies everything not already allowed.
> 
> Basically, I want to see if "+:mongod:cron crond\n" already exists. If it  
> does, do not do anything. However, if it does not exist, insert it prior to "-  
> : ALL : ALL\n".
> 
> What is the best way in a Chef Recipe to do this?
> 
> Thank you.
> 
> * * *
> 
> Charles Keagle  
> [a-ckeagle@expedia.com](mailto:a-ckeagle@expedia.com)  
> 425-417-3434

---

<div class="post-metadata">

**Author:** ![Chucker42](https://avatars.discourse-cdn.com/v4/letter/c/9de053/32.png) [@Chucker42](https://discourse.chef.io/u/Chucker42)\
**Post date:** [December 10, 2012, 2:06am UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/4 "2012-12-10T02:06:41Z")

</div>

Doesn't append add the new line to the end of the file? I need to add  
it before a line I define.

Maybe something like:  
prepend\_if\_no\_line "+:mongod:cron crond" do  
file "/etc/security/access.conf"  
string "-: ALL : ALL"  
end

Still looking at inserting a line before another line when necessary.

On 12/9/2012 12:55 AM, Sean OMeara wrote:

> Hi Charles!
> 
> This comes up ALL THE TIME, so...
> 
> I whipped up a line cookbook on the community site that'll help you out.
> 
> add depends 'line' in a cookbook's metadata.rb, then in a recipe you can say:
> 
> append\_if\_no\_line "hello world" do  
> file "/tmp/dangerfile"  
> string "HI THERE I AM STRING"  
> end
> 
> It's alpha code cut at 4am, so let me know how it works =)  
> -s
> 
> On Sun, Dec 9, 2012 at 1:37 AM, [chucker42@comcast.net](mailto:chucker42@comcast.net) wrote:
> 
> > Hello,
> > 
> > I am new to Chef and Ruby and trying to figure out the proper way to add a line  
> > to /etc/security/access.conf prior to the last line that denies everything not  
> > already defined.
> > 
> > Not sure yet whether the best way is to use a Chef command of a Ruby Block.
> > 
> > I do not see a way in Chef to insert a new line searched for if the line does  
> > not already exist in the file prior to another line in the file.
> > 
> > I thought this would work:
> > 
> > file.replace\_line\_if\_no\_match but that adds it after the last line in the file.  
> > In security, all the entries in access.conf that allow access have to be prior  
> > to the line that denies everything not already allowed.
> > 
> > Basically, I want to see if "+:mongod:cron crond\n" already exists. If it  
> > does, do not do anything. However, if it does not exist, insert it prior to "-  
> > : ALL : ALL\n".
> > 
> > What is the best way in a Chef Recipe to do this?
> > 
> > Thank you.
> > 
> > * * *
> > 
> > Charles Keagle  
> > [a-ckeagle@expedia.com](mailto:a-ckeagle@expedia.com)  
> > 425-417-3434

--  
Not All Who Wander Are Lost!

Charles Keagle  
[chucker42@comcast.net](mailto:chucker42@comcast.net)  
425-427-3434

---

<div class="post-metadata">

**Author:** ![Juanje\_Ojeda\_Croissi](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/juanje_ojeda_croissi/32/471_2.png) [@Juanje\_Ojeda\_Croissi](https://discourse.chef.io/u/Juanje_Ojeda_Croissi)\
**Post date:** [December 10, 2012, 4:14am UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/5 "2012-12-10T04:14:11Z")

</div>

As I had a similar problem time ago, i did create a similar cookbook  
(which is also at the community site and be installed from there):

> **[GitHub - juanje/cookbook-conf: Chef Cookbook to manage configuration files](https://github.com/juanje/cookbook-conf)**
>
> Chef Cookbook to manage configuration files. Contribute to juanje/cookbook-conf development by creating an account on GitHub.

There are some examples about how to use this LWRP. Maybe one of them  
fit your needs.  
I have one action that append a line just after specific line, but not  
to prepend, but I could add this action easily if is needed.

It's something to be used just if is really no way to use a template,  
it tries to be as much idempotence as it can.

On Mon, Dec 10, 2012 at 2:06 AM, charles Keagle [chucker42@comcast.net](mailto:chucker42@comcast.net) wrote:

> Doesn't append add the new line to the end of the file? I need to add it  
> before a line I define.
> 
> Maybe something like:  
> prepend\_if\_no\_line "+:mongod:cron crond" do  
> file "/etc/security/access.conf"  
> string "-: ALL : ALL"  
> end
> 
> Still looking at inserting a line before another line when necessary.
> 
> On 12/9/2012 12:55 AM, Sean OMeara wrote:
> 
> > Hi Charles!
> > 
> > This comes up ALL THE TIME, so...
> > 
> > I whipped up a line cookbook on the community site that'll help you out.
> > 
> > add depends 'line' in a cookbook's metadata.rb, then in a recipe you can  
> > say:
> > 
> > append\_if\_no\_line "hello world" do  
> > file "/tmp/dangerfile"  
> > string "HI THERE I AM STRING"  
> > end
> > 
> > It's alpha code cut at 4am, so let me know how it works =)  
> > -s
> > 
> > On Sun, Dec 9, 2012 at 1:37 AM, [chucker42@comcast.net](mailto:chucker42@comcast.net) wrote:
> > 
> > > Hello,
> > > 
> > > I am new to Chef and Ruby and trying to figure out the proper way to add  
> > > a line  
> > > to /etc/security/access.conf prior to the last line that denies  
> > > everything not  
> > > already defined.
> > > 
> > > Not sure yet whether the best way is to use a Chef command of a Ruby  
> > > Block.
> > > 
> > > I do not see a way in Chef to insert a new line searched for if the line  
> > > does  
> > > not already exist in the file prior to another line in the file.
> > > 
> > > I thought this would work:
> > > 
> > > file.replace\_line\_if\_no\_match but that adds it after the last line in the  
> > > file.  
> > > In security, all the entries in access.conf that allow access have to  
> > > be prior  
> > > to the line that denies everything not already allowed.
> > > 
> > > Basically, I want to see if "+:mongod:cron crond\n" already exists. If  
> > > it  
> > > does, do not do anything. However, if it does not exist, insert it prior  
> > > to "-  
> > > : ALL : ALL\n".
> > > 
> > > What is the best way in a Chef Recipe to do this?
> > > 
> > > Thank you.
> > > 
> > > * * *
> > > 
> > > Charles Keagle  
> > > [a-ckeagle@expedia.com](mailto:a-ckeagle@expedia.com)  
> > > 425-417-3434
> 
> --  
> Not All Who Wander Are Lost!
> 
> Charles Keagle  
> [chucker42@comcast.net](mailto:chucker42@comcast.net)  
> 425-427-3434

--  
Juanje

> **[Juanje Ojeda on about.me](https://about.me/juanje)**
>
> I am a personal trainer, public speaker, and teacher in Las Palmas de Gran Canaria, España. Read my articles.

---

<div class="post-metadata">

**Author:** ![kallistec](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/kallistec/32/23_2.png) [@kallistec](https://discourse.chef.io/u/kallistec)\
**Post date:** [December 10, 2012, 4:24am UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/6 "2012-12-10T04:24:50Z")

</div>

On Sunday, December 9, 2012 at 8:14 PM, Juanje Ojeda Croissier wrote:

> As I had a similar problem time ago, i did create a similar cookbook  
> (which is also at the community site and be installed from there):
> 
> [GitHub - juanje/cookbook-conf: Chef Cookbook to manage configuration files](https://github.com/juanje/cookbook-conf)
> 
> There are some examples about how to use this LWRP. Maybe one of them  
> fit your needs.  
> I have one action that append a line just after specific line, but not  
> to prepend, but I could add this action easily if is needed.
> 
> It's something to be used just if is really no way to use a template,  
> it tries to be as much idempotence as it can.

> On Mon, Dec 10, 2012 at 2:06 AM, charles Keagle \<[chucker42@comcast.net](mailto:chucker42@comcast.net) ([mailto:chucker42@comcast.net](mailto:chucker42@comcast.net))\> wrote:
> 
> > Doesn't append add the new line to the end of the file? I need to add it  
> > before a line I define.
> > 
> > Maybe something like:  
> > prepend\_if\_no\_line "+:mongod:cron crond" do  
> > file "/etc/security/access.conf"  
> > string "-: ALL : ALL"  
> > end
> > 
> > Still looking at inserting a line before another line when necessary.
> > 
> > On 12/9/2012 12:55 AM, Sean OMeara wrote:
> > 
> > > Hi Charles!
> > > 
> > > This comes up ALL THE TIME, so...
> > > 
> > > I whipped up a line cookbook on the community site that'll help you out.
> > > 
> > > add depends 'line' in a cookbook's metadata.rb, then in a recipe you can  
> > > say:
> > > 
> > > append\_if\_no\_line "hello world" do  
> > > file "/tmp/dangerfile"  
> > > string "HI THERE I AM STRING"  
> > > end
> > > 
> > > It's alpha code cut at 4am, so let me know how it works =)  
> > > -s
> > > 
> > > On Sun, Dec 9, 2012 at 1:37 AM, \<[chucker42@comcast.net](mailto:chucker42@comcast.net) ([mailto:chucker42@comcast.net](mailto:chucker42@comcast.net))\> wrote:
> > > 
> > > > Hello,
> > > > 
> > > > I am new to Chef and Ruby and trying to figure out the proper way to add  
> > > > a line  
> > > > to /etc/security/access.conf prior to the last line that denies  
> > > > everything not  
> > > > already defined.
> > > > 
> > > > Not sure yet whether the best way is to use a Chef command of a Ruby  
> > > > Block.
> > > > 
> > > > I do not see a way in Chef to insert a new line searched for if the line  
> > > > does  
> > > > not already exist in the file prior to another line in the file.
> > > > 
> > > > I thought this would work:
> > > > 
> > > > file.replace\_line\_if\_no\_match but that adds it after the last line in the  
> > > > file.  
> > > > In security, all the entries in access.conf that allow access have to  
> > > > be prior  
> > > > to the line that denies everything not already allowed.
> > > > 
> > > > Basically, I want to see if "+:mongod:cron crond\n" already exists. If  
> > > > it  
> > > > does, do not do anything. However, if it does not exist, insert it prior  
> > > > to "-  
> > > > : ALL : ALL\n".
> > > > 
> > > > What is the best way in a Chef Recipe to do this?
> > > > 
> > > > Thank you.

Just a quick friendly warning:

Only you can evaluate the tradeoffs of this approach vs. templating the whole file, but you should be aware of the risk. Namely, when you manage individual lines of a file like this, you create a situation where the exact file content isn't specified by a single resource, but rather by the history of the node's run\_list and cookbook versions over time.

For example, you may edit a file to stick a certain line in some place. Later, you need to change the line you inserted, so you change the recipe so it edits that line. Now when you bring up a new host, it doesn't add the line, so your new boxes are different than older ones. I'm sure you can imagine more variations on this type of issue.

That said, I've heard of use cases where other alternatives are so onerous that people find the risk acceptable. You should take a moment to make certain this is the situation you're in before proceeding with this approach.

--  
Daniel DeLeo

---

<div class="post-metadata">

**Author:** ![Arnold\_Krille](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/arnold_krille/32/285_2.png) [@Arnold\_Krille](https://discourse.chef.io/u/Arnold_Krille)\
**Post date:** [December 10, 2012, 8:44pm UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/7 "2012-12-10T20:44:52Z")

</div>

On Mon, 10 Dec 2012 04:14:11 +0000 Juanje Ojeda Croissier  
[juanje.ojeda@gmail.com](mailto:juanje.ojeda@gmail.com) wrote:

> As I had a similar problem time ago, i did create a similar cookbook  
> (which is also at the community site and be installed from there):
> 
> [GitHub - juanje/cookbook-conf: Chef Cookbook to manage configuration files](https://github.com/juanje/cookbook-conf)
> 
> There are some examples about how to use this LWRP. Maybe one of them  
> fit your needs.  
> I have one action that append a line just after specific line, but not  
> to prepend, but I could add this action easily if is needed.
> 
> It's something to be used just if is really no way to use a template,  
> it tries to be as much idempotence as it can.

Oh, this is nice! I did create something similar but much simpler for  
appending lines and just used some shell magic.

With your LWRP, what happens in :insert\_after\_match when the line to be  
inserted is already present? Or is this best catched with a not\_if  
-entry?

I think I will test your recipe the next days.

Have fun,

Arnold

---

<div class="post-metadata">

**Author:** ![Arnold\_Krille](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/arnold_krille/32/285_2.png) [@Arnold\_Krille](https://discourse.chef.io/u/Arnold_Krille)\
**Post date:** [December 10, 2012, 8:49pm UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/8 "2012-12-10T20:49:12Z")

</div>

On Sun, 9 Dec 2012 19:48:01 +1300 AJ Christensen [aj@junglist.gen.nz](mailto:aj@junglist.gen.nz)  
wrote:

> Template the whole file

Sometimes you can't do that:

- When adding the ssh-keys of your backup-system  
to /root/.ssh/authorized\_keys by chef but otherwise allow keys to be  
added by hand.
- When adding host-definitions to aforementioned backup-daemons config  
and be compatible with an existing installation gradually switching  
to chef-management.
- When adding stuff to files from several recipes.  
Most of these would be easier if more applications support conf.d/  
style directories, but we have to do with what we have...

Have fun,

Arnold

---

<div class="post-metadata">

**Author:** ![Juanje\_Ojeda\_Croissi](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/juanje_ojeda_croissi/32/471_2.png) [@Juanje\_Ojeda\_Croissi](https://discourse.chef.io/u/Juanje_Ojeda_Croissi)\
**Post date:** [December 11, 2012, 1:03am UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/9 "2012-12-11T01:03:00Z")

</div>

On Mon, Dec 10, 2012 at 8:44 PM, Arnold Krille [arnold@arnoldarts.de](mailto:arnold@arnoldarts.de) wrote:

> On Mon, 10 Dec 2012 04:14:11 +0000 Juanje Ojeda Croissier  
> [juanje.ojeda@gmail.com](mailto:juanje.ojeda@gmail.com) wrote:
> 
> > As I had a similar problem time ago, i did create a similar cookbook  
> > (which is also at the community site and be installed from there):
> > 
> > [GitHub - juanje/cookbook-conf: Chef Cookbook to manage configuration files](https://github.com/juanje/cookbook-conf)
> > 
> > There are some examples about how to use this LWRP. Maybe one of them  
> > fit your needs.  
> > I have one action that append a line just after specific line, but not  
> > to prepend, but I could add this action easily if is needed.
> > 
> > It's something to be used just if is really no way to use a template,  
> > it tries to be as much idempotence as it can.
> 
> Oh, this is nice! I did create something similar but much simpler for  
> appending lines and just used some shell magic.
> 
> With your LWRP, what happens in :insert\_after\_match when the line to be  
> inserted is already present? Or is this best catched with a not\_if  
> -entry?

Ouch, good point. It doesn't control that case :-/ But it should. I  
think I will review it. Long time since I did it.

This was reusing the Chef lib 'FileEdit', but this is a bit limited  
and maybe is worth to change it.

> <https://github.com/chef/chef/blob/main/lib/chef/util/file_edit.rb>

By now it's probably good idea to use the 'not\_if'.

> I think I will test your recipe the next days.

Tell me if you find anything else and I will change it.  
Thanks 🙂

--  
Juanje

> **[Juanje Ojeda on about.me](https://about.me/juanje)**
>
> I am a personal trainer, public speaker, and teacher in Las Palmas de Gran Canaria, España. Read my articles.

---

<div class="post-metadata">

**Author:** ![Jesse\_Campbell](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/jesse_campbell/32/251_2.png) [@Jesse\_Campbell](https://discourse.chef.io/u/Jesse_Campbell)\
**Post date:** [December 11, 2012, 1:56am UTC](https://discourse.chef.io/t/chef-recipe-inserting-a-line-before-last-line-in-fie/3380/10 "2012-12-11T01:56:30Z")

</div>

I did this by making a template with some relatively simple regex.  
I have since just templated the whole file, but this should still work.

Recipe:

lines[0]['text'] = "full line to insert"  
lines[0]['insertpoint'] = "file line to find in the file"

template "/etc/file\_to\_edit" do  
source "insertline.erb"  
mode 0600  
owner "root"  
group "root"  
variables(  
:oldfile =\> "/etc/file\_to\_edit",  
:insertlines =\> lines  
)  
end

Contents of insertline.erb:

\<% output = File.read(@oldfile) -%\>  
\<% @insertlines.each do |line| -%\>  
\<% unless (output.match(/^#{line['text']}$/i)) -%\>  
\<% output = output.sub(/^(#{line['insertpoint']})$/,"\1\n#{line['text']}") -%\>  
\<% end -%\>  
\<% end -%\>  
\<%= output -%\>

On Sun, Dec 9, 2012 at 1:37 AM, [chucker42@comcast.net](mailto:chucker42@comcast.net) wrote:

> Hello,
> 
> I am new to Chef and Ruby and trying to figure out the proper way to add a line  
> to /etc/security/access.conf prior to the last line that denies everything not  
> already defined.
> 
> Not sure yet whether the best way is to use a Chef command of a Ruby Block.
> 
> I do not see a way in Chef to insert a new line searched for if the line does  
> not already exist in the file prior to another line in the file.
> 
> I thought this would work:
> 
> file.replace\_line\_if\_no\_match but that adds it after the last line in the file.  
> In security, all the entries in access.conf that allow access have to be prior  
> to the line that denies everything not already allowed.
> 
> Basically, I want to see if "+:mongod:cron crond\n" already exists. If it  
> does, do not do anything. However, if it does not exist, insert it prior to "-  
> : ALL : ALL\n".
> 
> What is the best way in a Chef Recipe to do this?
> 
> Thank you.
> 
> * * *
> 
> Charles Keagle  
> [a-ckeagle@expedia.com](mailto:a-ckeagle@expedia.com)  
> 425-417-3434
