# Modify a portion of a file if it fits a certain format, fail if not

I have to update an application file i dont own, meaning it could get changed in an upgrade.

What I would like to do is run a check that it first fits the format I expect. If it doesnt, that likely means the file underwent major changes and I need to review what happened and not update the file. If it does match the pattern, then make sure my value is as expected.

Here is the snippet Im working with (ERB file)

<os>
<type arch='<%= arch %>'><%= os_type %></type>
<% boot_order.each do |dev| -%>
<boot dev='<%= dev %>'/>
<% end -%>
</os>


Basically, if everything in the OS tag looks good, I then want to make sure my value is there, making the final form look like this

<os>
<type arch='<%= arch %>'><%= os_type %></type>
<% boot_order.each do |dev| -%>
<boot dev='<%= dev %>'/>
<% end -%>
<bios useserial='yes' rebootTimeout='5000'/>
</os>


I have a regex that will match to verify that the OS block is there as expected (with or without my edit)

^\s*<os>\n?\s*<type arch='<%= arch %>'><%= os_type %></type>\n?\s*<% boot_order.each do \|dev\| -%>\n?\s*<boot dev='<%= dev %>'/>\n?\s*<% end -%>\n?(.+\n)?\s*</os>


From reading it sounds like maybe I can use the line/match attributes to get this done. If the match is true (valid format, value may or may not be there) and then have it inject my value (replacing the whole block, every time its run.) I suspect this will work ok, but its probably horrible in the sense that it would update the file on every run.

The other thought I had was to use the -> (still pretty new so might be way off base)

file { is it there? } -> file_line { valid format? } -> file_line {valid value?}

edit retag close merge delete

Sort by » oldest newest most voted

For complex file editing, I strongly encourage you to use augeas. It can check for objects in a certain format (though I think it doesn't check the full ordering) and can make specific changes to parameters in objects. It's quite complicated, but can do quite complicated stuff too. In this case, you would write an augeas resource for 'type', 'boot' and 'bios' objects, which are children of 'os' object.

As for your last suggestion - file -> file_line -> file_line - I understand you want to do some checking in each step. But, from Puppet's logic perspective, I think the result is the opposite of what you expect: if any test fails, Puppet will change the file to make the test pass; and, if the test passes, it doesn't apply the next resource(s). Because that's how resources work - you write the right state, and Puppet enforces it.

more

Im not sure this can be done. In speaking with the Augaes folks, they think im out of my mind. I took a look at the xml.aug to modify it, and because the <% %> tag can be at any point, its going to be hard/impossible to trap

( 2018-05-31 12:45:52 -0600 )edit

## Stats

Seen: 94 times

Last updated: May 30