Overriding file resource with class inheritance

662 views
Skip to first unread message

Kyle Flavin

unread,
Jan 29, 2016, 11:05:24 PM1/29/16
to Puppet Users
I'm creating a module, and I want to override the file resource for puppet.conf which is defined within a module called "puppet".  The resource declaration looks like this:

# modules/puppet/manifests/init.pp
class puppet {
   
...
    file
{ '/etc/puppet/puppet.conf':
        content
=> template('puppet/puppet.conf.erb'),
   
}
   
...
}


I want to override this file resource to provide a customized puppet.conf, and I'm trying to do so using inheritance.  My module is laid out as follows:

# modules/foreman-proxy directory

├── manifests
  ├── init.pp
  └── puppet.pp
└── templates
   
└── puppet.conf.erb

# init.pp
class foreman-proxy inherits puppet {
    include foreman
-proxy::puppet
}

# puppet.pp
class foreman-proxy::puppet inherits puppet {
    file
{ '/etc/puppet/puppet.conf':
        content
=> template('foreman-proxy/puppet.conf.erb'),
   
}
}


When I run this on the client, I get the error:
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not find scope for foreman-proxy::puppet on node <myservername>
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

What am I doing incorrectly?  Is there a better approach?  I'm trying to avoid modifying the existing puppet module, because it's applied across many servers.

Garrett Honeycutt

unread,
Jan 29, 2016, 11:44:24 PM1/29/16
to puppet...@googlegroups.com
On 1/29/16 6:05 PM, Kyle Flavin wrote:
> I'm creating a module, and I want to override the file resource for
> puppet.conf which is defined within a module called "puppet". The
> resource declaration looks like this:
>
> |
> # modules/puppet/manifests/init.pp
> classpuppet {
> ...
> file {'/etc/puppet/puppet.conf':
> content =>template('puppet/puppet.conf.erb'),
> }
> ...
> }
> |
>
>
> I want to override this file resource to provide a customized
> puppet.conf, and I'm trying to do so using inheritance. My module is
> laid out as follows:
>
> |
> # modules/foreman-proxy directory
>
> ├──manifests
> │ ├──init.pp
> │ └──puppet.pp
> └──templates
> └──puppet.conf.erb
>
> # init.pp
> classforeman-proxy inherits puppet {
> include foreman-proxy::puppet
> }
>
> # puppet.pp
> classforeman-proxy::puppet inherits puppet {
> file {'/etc/puppet/puppet.conf':
> content =>template('foreman-proxy/puppet.conf.erb'),
> }
> }
>
> |
>
> When I run this on the client, I get the error:
> |
> Error:Couldnotretrieve catalog fromremote server:Error400on
> SERVER:Couldnotfind scope forforeman-proxy::puppet on node <myservername>
> Warning:Notusingcache on failed catalog
> Error:Couldnotretrieve catalog;skipping run
> |
>
> What am I doing incorrectly? Is there a better approach? I'm trying to
> avoid modifying the existing puppet module, because it's applied across
> many servers.
>

Hi Kyle,

I think you have a scoping issue, try using the double colons for the
puppet class, such as 'class foreman-proxy::puppet inherits ::puppet'.

You seem to be using inheritance correctly to override a resource,
though you are doing this between two modules. This pattern should be
avoided at all costs and will likely end in tears.

http://docs.puppetlabs.com/guides/style_guide.html#class-inheritance

Suggest that the puppet module manage the puppet.conf.

HTH,
-g

--
Garrett Honeycutt
@learnpuppet
Puppet Training with LearnPuppet.com
Mobile: +1.206.414.8658

Kyle Flavin

unread,
Jan 30, 2016, 12:27:31 AM1/30/16
to Puppet Users
On Friday, January 29, 2016 at 3:44:24 PM UTC-8, Garrett Honeycutt wrote:
Hi Kyle,

I think you have a scoping issue, try using the double colons for the
puppet class, such as 'class foreman-proxy::puppet inherits ::puppet'.

You seem to be using inheritance correctly to override a resource,
though you are doing this between two modules. This pattern should be
avoided at all costs and will likely end in tears.

http://docs.puppetlabs.com/guides/style_guide.html#class-inheritance

Suggest that the puppet module manage the puppet.conf.

I added the "::" and it allowed the client to run without an error, but I'm getting the modules/puppet/templates/puppet.conf.erb template brought down on the client, instead of modules/foreman-proxy/templates/puppet.conf.erb.  Is it possible to change that?

I'm looking into another solution as well.  The problem is, with the way our manifests were written, there doesn't seem to be an easy way to extend for edge cases like this without changing the original module.  The module is on thousands of servers, so I'm a little hesitant to change it.

Martin Alfke

unread,
Jan 30, 2016, 10:56:16 AM1/30/16
to puppet...@googlegroups.com
Hi Kyle,

On 30 Jan 2016, at 01:27, Kyle Flavin <kyle....@gmail.com> wrote:

> On Friday, January 29, 2016 at 3:44:24 PM UTC-8, Garrett Honeycutt wrote:
> Hi Kyle,
>
> I think you have a scoping issue, try using the double colons for the
> puppet class, such as 'class foreman-proxy::puppet inherits ::puppet'.
>
> You seem to be using inheritance correctly to override a resource,
> though you are doing this between two modules. This pattern should be
> avoided at all costs and will likely end in tears.
>
> http://docs.puppetlabs.com/guides/style_guide.html#class-inheritance
>
> Suggest that the puppet module manage the puppet.conf.
>
> I added the "::" and it allowed the client to run without an error, but I'm getting the modules/puppet/templates/puppet.conf.erb template brought down on the client, instead of modules/foreman-proxy/templates/puppet.conf.erb. Is it possible to change that?

First: inheritance should not be used whenever possible. Especially inheritance among modules.

Second: your inherited class should overwrite (not re-declare) the file resource:

class foreman-proxy::puppet inherits puppet {
File['/etc/puppet/puppet.conf’] {
content => template('foreman-proxy/puppet.conf.erb'),
}
}

Third: the best option would be to add a template parameter to the puppet class:

class puppet (
puppet_conf_template = ‘puppet/puppet.conf.erb’,
){
file { ‘/etc/puppet/puppet.conf’:
content => template($puppet_conf_template),
}
...
}

class foreman_proxy::puppet {
class { ‘::puppet’:
puppet_conf_template = ‘foreman_proxy/puppet.conf.erb’,
}
}

Fourth: a hyphen in class names is deprecated in Puppet 4. You should switch to underscore (like in my example).



>
> I'm looking into another solution as well. The problem is, with the way our manifests were written, there doesn't seem to be an easy way to extend for edge cases like this without changing the original module. The module is on thousands of servers, so I'm a little hesitant to change it.

Fifth: add rspec-puppet (and beaker) tests to your modules. This will allow testing behaviour prior doing changes.

Best,
Martin

>
> --
> You received this message because you are subscribed to the Google Groups "Puppet Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/4fd8baf6-398d-49d3-84b0-3fe7596886c3%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Kyle Flavin

unread,
Feb 1, 2016, 7:04:01 PM2/1/16
to Puppet Users
Thanks Martin, makes sense.  I'm modifying the code to avoid the cross-module inheritance.
Reply all
Reply to author
Forward
0 new messages