Ask Your Question

How to generate file on local machine from dynamic source file?

asked 2015-09-17 19:49:58 -0600

Tim Landscheidt gravatar image

I want to create a file $target that is generated from file $source by replacing some texts with others ($replacements). File $source is managed by Puppet (3.4.3) and itself created dynamically from templates & Co.

File $target should be generated when it does not exist or when its source file $source was changed, or – best case – when there would be a change, but not on every Puppet run to keep the logs quiet.

I have tried:

define transform_file(
    $target = $title,
) {
    exec { "generate ${target}":
        command     => inline_template('<%= require "shellwords"; "/bin/sed #{@replacements.collect { |pattern, replacement| "-e #{Shellwords.escape("s/#{pattern}/#{replacement}/;")}" }.join(" ")} #{Shellwords.escape(@source)} > #{Shellwords.escape(@target)}" %>'),
        creates     => $target,
        refreshonly => true,
        subscribe   => File[$source, 'vmbuilder_version'],

but when a refresh is triggered, the command is not actually executed probably because $target already exists.

When I remove the creates attribute, the refresh triggers the command, but then it is not executed when $target does not exist.

If I add onlyif => "/usr/bin/test \\! -e ${target}" or unless => "/usr/bin/test -e ${target}" and keep refreshonly, it does not execute either when $target does not exist.

If I remove refreshonly and keep onlyif or unless, it does execute when $target does not exist, but does not execute when a refresh is triggered.

My general solution would be to put (only) unless => "diff $target <(sed … $source)" as the condition for exec and require => File[$source, …] to ensure that $source is created before exec is executed, but I cannot believe that Puppet does not have a more elegant solution for that :-).

Is there a better way to generate a file on the local machine that is the result of replacing texts in another Puppet-managed file?

edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted

answered 2015-09-17 22:31:11 -0600

Ancillas gravatar image

Is the original file machine generated? If not, you could just define all the text in Hiera, and then populate both files from the same data source.

If you are dealing with some ugly machine generated config file, then I'd skip the Puppet fanciness and just write an idempotent script that runs on every execution. You'll have a Puppet change in your logs, even if no change happens, but the implementation will be simple and easy to understand.

edit flag offensive delete link more


" File $source is managed by Puppet (3.4.3) and itself created dynamically from templates & Co.", so, no, that is not an option. And adding an `unless => "diff […]"` isn't that expensive, but makes live much easier when you don't have to think about why the exec was called again.

Tim Landscheidt gravatar imageTim Landscheidt ( 2015-09-18 09:03:11 -0600 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2015-09-17 19:49:58 -0600

Seen: 181 times

Last updated: Sep 17 '15