[augeas-devel] Managing a file as a whole with puppet and augeas

Dominic Cleal dcleal at redhat.com
Fri Jun 26 15:00:20 UTC 2015


On 26/06/15 15:38, Mickaël Canévet wrote:
> Hello,
> 
> I'd like to be able to manage a file as a whole with puppet and augeas.
> The typical use case is to take a sample file, or a systemd service
> file, provided by a package as source and apply some augeas translations
> on it, then write to a destination file.
> 
> I could use:
> 
> file { '/etc/foo/foo.conf':
>   ensure => file,
>   source => 'file:///usr/share/doc/foo/example/foo.conf',
>   replace => false,
> }
> augeas { 'bar':
>   context => '/files/etc/foo/foo.conf',
>   changes => [ ... ],
> }
> 
> But I don't like it because:
> - If the sample file is updated (because of security reason for
> example), my configuration file will not be updated,
> - The configuration file is not managed as whole, and thus can be
> manually corrupted.

Do you remember this function?

https://github.com/camptocamp/puppet-augeas/blob/master/lib/puppet/parser/functions/augeas.rb

It was written with the same ideas in mind - that you'd have some stock
file, probably inside the module, copied from /usr/share/doc which would
be transformed on the master by Augeas and put into the catalog.  That
has the same disadvantage as the first, the file needs to be copied from
the master.

> I'd like to have either something like an Augeas_builder resource that
> takes the source and apply any augeas transformation on it:
> 
> file { '/etc/foo/foo.conf':
>   ensure => file,
> }
> augeas_builder { '/etc/foo/foo.conf':
>   source => 'file:///usr/share/doc/foo/example/foo.conf',
> }
> augeas { 'bar':
>   context => '/files/etc/foo/foo.conf',
>   changes => [ ... ],
> }
>
> Or even a new provider for File resource that would take the source and
> apply any augeas transformation on it and compares with the destination
> file:
> 
> file { '/etc/foo/foo.conf':
>   ensure => file,
>   source => 'file:///usr/share/doc/foo/example/foo.conf',
>   provider => 'augeas',
> }
> augeas { 'bar':
>   context => '/files/etc/foo/foo.conf',
>   changes => [ ... ],
> }

With some changes to the augeas provider to support loading extra files
(in the "incl" parameter?), you could perhaps do:

augeas { "foo.conf":
  incl    => ["/usr/share/doc/foo/example/foo.conf"],
  changes => [
    "rm /etc/foo.conf",
    "cp /files/usr/share/doc/foo/example/foo.conf /etc/foo.conf",
    "set ..."
  ],
}
(and have no source parameter on the file resource.)

> I see lots of advantages over concat:
> - You don't have to manage the whole file, just have to code the
> transformations you want to apply on the source file,
> - A run with --noop should show a diff of the whole file, not just the
> diff of a fragment and yield about failing dependencies.
> 
> I'd like to have your opinion on:
> - is is feasible?
> - would this be useful?

I think it's an interesting pattern, I found myself wanting something
very similar a few years ago when writing modules for multiple OSes.

> - how to do it properly?
> - how to deal with all augeas transformation? (Augeas resources, augeas
> providers...)

I think this is a good reason to allow use of the existing
types/providers and wrap them somehow, avoiding reimplementing them or
using aug_srun directly (as augeas() did), so as to provide flexibility.
 You could even use file_line then.

Not quite sure how you'd do it, some sort of intermediate resources that
copied the files around from one output to another's input using notifies?

The downside is that it's probably a lot less efficient than having a
single function that loads Augeas just the once and can do everything in
memory.

-- 
Dominic Cleal
Red Hat Engineering




More information about the augeas-devel mailing list