Is it possible to conditionally replace a file ?

3,195 views
Skip to first unread message

Dan White

unread,
Nov 28, 2011, 9:22:51 AM11/28/11
to Pupper Users Mailing List
As far as I can tell, the "replace" parameter is all or nothing.

What I am looking for is something like the exec/onlyif parameter that I can use to conditionally replace a file.

Any thoughts ?

“Sometimes I think the surest sign that intelligent life exists elsewhere in the universe is that none of it has tried to contact us.”
Bill Waterson (Calvin & Hobbes)

Bruce Richardson

unread,
Nov 28, 2011, 9:53:52 AM11/28/11
to puppet...@googlegroups.com
On Mon, Nov 28, 2011 at 02:22:51PM +0000, Dan White wrote:
> As far as I can tell, the "replace" parameter is all or nothing.
>
> What I am looking for is something like the exec/onlyif parameter that I can use to conditionally replace a file.
>
> Any thoughts ?

There is more than one way to do this. What kind of conditions woud you
be testing for?

--
Bruce

A problem shared brings the consolation that someone else is now
feeling as miserable as you.

Dan White

unread,
Nov 28, 2011, 10:01:14 AM11/28/11
to puppet...@googlegroups.com

Thanks for responding. Nice tag line.

OK, more details:

In my users class, I want to be able to push out custom dot-files when the user account is first created.
Unfortunately, if one sets user:managehome => true, the dotfiles are created by default and the custom file is not pushed out unless you set file:replace => yes.

The downside of this is that the dot-files would then have to be managed from the puppet-master, which, in this case, I would prefer to avoid. I want to push the custom dot-files out the first time only.

My though was to place a flag line in the file to search for ("Created by Puppet") and then replace the file if I do not find my flag line.

Does that clarify ?

Bruce Richardson

unread,
Nov 28, 2011, 10:37:08 AM11/28/11
to puppet...@googlegroups.com
On Mon, Nov 28, 2011 at 03:01:14PM +0000, Dan White wrote:
>
> Thanks for responding. Nice tag line.
>
> OK, more details:
>
> In my users class, I want to be able to push out custom dot-files when the user account is first created.
> Unfortunately, if one sets user:managehome => true, the dotfiles are
> created by default and the custom file is not pushed out unless you
> set file:replace => yes.

You realise that this is being done by Unix (Linux?), not Puppet? If
you use puppet to replace the system's default dotfiles (on Linux,
they'll be in /etc/skel) *before* creating any users, you'll get
precisely what you want. Just set up the users so that they depend on
the file resources which place the right files in /etc/skel and this
will guarantee the files are in there before the users are created
(assuming they didn't exist already). The Unix user creation tools
will copy the /etc/skel files into the right place when Puppet invokes
them.

This only fails if you need different dotfiles (differing by content
and/or name) for different users. If you don't, simple win

--
Bruce

Hierophant: someone who remembers, when you are on the way down,
everything you did to them on the way up.

Dan White

unread,
Nov 28, 2011, 11:00:48 AM11/28/11
to puppet...@googlegroups.com
----- Bruce Richardson <itsb...@workshy.org> wrote:

Thanks for responding.
I agree, globally customizing the defaults is one way to go, but I am shooting for the second option.

Stefan Schulte

unread,
Nov 28, 2011, 1:18:40 PM11/28/11
to puppet...@googlegroups.com
On Mon, Nov 28, 2011 at 04:00:48PM +0000, Dan White wrote:
> ----- Bruce Richardson <itsb...@workshy.org> wrote:
> > You realise that this is being done by Unix (Linux?), not Puppet? If
> > you use puppet to replace the system's default dotfiles (on Linux,
> > they'll be in /etc/skel) *before* creating any users, you'll get
> > precisely what you want. Just set up the users so that they depend on
> > the file resources which place the right files in /etc/skel and this
> > will guarantee the files are in there before the users are created
> > (assuming they didn't exist already). The Unix user creation tools
> > will copy the /etc/skel files into the right place when Puppet invokes
> > them.
> >
> > This only fails if you need different dotfiles (differing by content
> > and/or name) for different users. If you don't, simple win
> >
> > --
> > Bruce
> >
> > Hierophant: someone who remembers, when you are on the way down,
> > everything you did to them on the way up.
> >
>
> Thanks for responding.
> I agree, globally customizing the defaults is one way to go, but I am shooting for the second option.
>

If you do not want the gobal defaults copied why are you using
managehome => true?

If you really have to go this awkward path you can create a conditional
exec resoure that removes the dotfiles if they are equal to the skel files
so puppet will copy the correct files again. (fileresources with replace
=> false)

A second solution is to create a custom fact that tells you if puppet
should manage the dotfiles and wrap your fileresources in an if-clause
(fileresources with replace => true)

-Stefan

Martin Alfke

unread,
Nov 29, 2011, 7:07:04 AM11/29/11
to puppet...@googlegroups.com

On 28.11.2011, at 19:18, Stefan Schulte wrote:
>> [...]

>> Thanks for responding.
>> I agree, globally customizing the defaults is one way to go, but I am shooting for the second option.
>>
>
> If you do not want the gobal defaults copied why are you using
> managehome => true?
>
> If you really have to go this awkward path you can create a conditional
> exec resoure that removes the dotfiles if they are equal to the skel files
> so puppet will copy the correct files again. (fileresources with replace
> => false)
>
> A second solution is to create a custom fact that tells you if puppet
> should manage the dotfiles and wrap your fileresources in an if-clause
> (fileresources with replace => true)
>
> -Stefan

We have another usecase for conditional file replacement:

if a developer would like to forbid any puppet changes on a certain file he creates a flagfile $name.nopuppet
instead of normal file resource we use a parameterized define:

define configfile ($source) {
exec { "check_${name}":
command => '/usr/bin/true',
unless => "/usr/bin/test -e ${name}.nopuppet",
}
file { "$name":
source => $source,
requires => Exec["check_${name}"],
}
}

we then use this define on certain files.
e.g.

configfile { "/etc/apache2/apache2.conf": source => "puppet:///modules/apache2/apache2.conf" }


Daniel Pittman

unread,
Nov 29, 2011, 1:55:53 PM11/29/11
to puppet...@googlegroups.com
On Tue, Nov 29, 2011 at 04:07, Martin Alfke <tux...@gmail.com> wrote:
> On 28.11.2011, at 19:18, Stefan Schulte wrote:
>>> [...]
>
>>> Thanks for responding.
>>> I agree, globally customizing the defaults is one way to go, but I am shooting for the second option.
>>>
>>
>> If you do not want the gobal defaults copied why are you using
>> managehome => true?
>>
>> If you really have to go this awkward path you can create a conditional
>> exec resoure that removes the dotfiles if they are equal to the skel files
>> so puppet will copy the correct files again. (fileresources with replace
>> => false)
>>
>> A second solution is to create a custom fact that tells you if puppet
>> should manage the dotfiles and wrap your fileresources in an if-clause
>> (fileresources with replace => true)
>>
>> -Stefan
>
> We have another usecase for conditional file replacement:
>
> if a developer would like to forbid any puppet changes on a certain file he creates a flagfile $name.nopuppet
> instead of normal file resource we use a parameterized define:

This path is going to cause you nothing but pain. Instead of allowing
conditional opt-out based on the machine, you should rather prefer to
have the central authority own that - if the developer needs their
machine to have a custom HTTP setup, don't try and manage it on that
machine. Record that fact in your central configuration system.

If you really need that control to be allowed on a per-user or
per-machine basis, invest in an ENC and provide an interface to that
which allows the developers to exclude their machine from this
management.

Daniel
--
⎋ Puppet Labs Developer – http://puppetlabs.com
♲ Made with 100 percent post-consumer electrons

Thomas Bellman

unread,
Jan 4, 2012, 10:50:09 AM1/4/12
to puppet...@googlegroups.com, Dan White
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 2011-11-28 16:01, Dan White wrote:

> In my users class, I want to be able to push out custom dot-files when
> the user account is first created.
> Unfortunately, if one sets user:managehome => true, the dotfiles are
> created by default and the custom file is not pushed out unless you set
> file:replace => yes.
>
> The downside of this is that the dot-files would then have to be managed
> from the puppet-master, which, in this case, I would prefer to avoid. I
> want to push the custom dot-files out the first time only.

(Late answer, I know, but anyway.)

So, make useradd(8) not copy out those files you want to manage. Assuming
you want to give your users a specific .emacs file, something like this:

class no_skel_dot_emacs
{
file {
'/etc/skel/.emacs':
ensure => absent,
# We want this to happen *after* the /etc/skel/.emacs file
# is installed by the Emacs package...
require => Package['emacs-common'];
}
}

define myuser($uid, $gecos)
{
include no_skel_dot_emacs

user {
$name:
ensure => present, uid => $uid, $comment => $gecos,
managehome => true,
require => Class[no_skel_dot_emacs];
}
file {
"/home/${name}/.emacs":
ensure => file, replace => no,
content => template('.../dot-emacs.erb'),
owner => $name, group => $name, mode => 0644;
}
}

If /etc/skel/.emacs doesn't exist when useradd is run, it won't be copied
out to the user's home directory, and you won't have a conflict.


/Bellman
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk8EdTEACgkQDGpP8Cv3aqLCJQCfVwdX2zSzhaIxschELYv7xzY8
MpsAoIIbhO60x+AuZdats8cFIKlOdR8S
=5COp
-----END PGP SIGNATURE-----

Juan José Presa Rodal

unread,
Jan 25, 2012, 6:44:03 AM1/25/12
to puppet...@googlegroups.com
Hi, I would like to achieve a conditional file replacement but lightly different. I deploy recusively a directory with a lot of config files. This is my resource:

file {"/foo":
    ensure  => directory,
    recurse => remote,
    source  => "puppet:///modules/module_name/configs/${hostname}/foo",
    ignore  => ["no_replace1.cfg","no_replace2.cfg"],
  }

I need to ignore these two files because they will not be puppet managed but initializated by puppet.


Daniel Pittman

unread,
Jan 26, 2012, 1:05:58 PM1/26/12
to puppet...@googlegroups.com
2012/1/25 Juan José Presa Rodal <jua...@gmail.com>:

A recursive file resource is "less specific" than a file resource
managing an individual file.

If you install those two configuration files with `file {
".../no_replace1.cfg": ensure => present, ... }`, Puppet will put them
in place if they are missing, but otherwise ignore their content. It
will also prevent the recurse from overwriting them.

--
Daniel Pittman

Juan José Presa Rodal

unread,
Jan 26, 2012, 1:12:26 PM1/26/12
to puppet...@googlegroups.com
Ok, I understand. But i have not control about these individual "noreplace" files because are $hostname dependent.

In different hostnames, have different specific source locations.

So that was the reason for I need something similar to ignore parameter. (Or a workaround)

Thanks!
Reply all
Reply to author
Forward
0 new messages