Chef Recipe inserting a line before last line in fie

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
425-417-3434

Template the whole file

Cheers,

AJ

On 9 December 2012 19:37, 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
425-417-3434

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 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
425-417-3434

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 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
425-417-3434

--
Not All Who Wander Are Lost!

Charles Keagle
chucker42@comcast.net
425-427-3434

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):

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 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 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
425-417-3434

--
Not All Who Wander Are Lost!

Charles Keagle
chucker42@comcast.net
425-427-3434

--
Juanje

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

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.

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

On Mon, 10 Dec 2012 04:14:11 +0000 Juanje Ojeda Croissier
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

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

On Sun, 9 Dec 2012 19:48:01 +1300 AJ Christensen 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

On Mon, Dec 10, 2012 at 8:44 PM, Arnold Krille arnold@arnoldarts.de wrote:

On Mon, 10 Dec 2012 04:14:11 +0000 Juanje Ojeda Croissier
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

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.

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 :slight_smile:

--
Juanje

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 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
425-417-3434