I have a trivial puppet 2.7.18 installation as follows:
=== manifests/site.pp ===
node build-1 {
include mod1
include mod2
include mod3
}
=== modules/mod1/manifests/init.pp ===
import "*"
=== modules/mod1/manifests/mod1.pp ===
class mod1 {
file { "/tmp/mod1.file": ensure => present }
}
=== modules/mod2/manifests/init.pp ===
import "*"
=== modules/mod2/manifests/mod2.pp ===
class mod2 {
file { "/tmp/mod2.file": ensure => present }
}
=== modules/mod3/manifests/init.pp ===
import "*"
=== modules/mod3/manifests/mod3.pp ===
class mod3 {
file { "/tmp/mod3.file": ensure => present }
}
When I try to run puppet agent on the build-1 host, I get the following message:
: 0 build-1; sudo puppet agent --noop --test
err: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not find class mod1 for build-1 at /etc/puppet/manifests/site.pp:2 on node build-1
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
If I run it again, I get the same message, but for class mod2. Running it a third time gives me the message for class mod3. Finally, running it a fourth time works. But, if I do nothing more than touch one of the module files (e.g., mod1.pp), then I have to go through the whole thing again; running puppet agent until every module recompiles properly. This is obviously not sustainable.
Some other things I noticed:
- This seems similar to https://stackoverflow.com/questions/15289988/puppet-could-not-find-class-hiccups-often-once-after-manifest-module-change, except that one appears to be for version 3.0 and the bug ticket it refers to specifically says that it doesn't affect 2.7. In any case, switching to a passenger setup didn't help.
- If I change the module layout to just put the whole module definition into init.pp instead of importing the real module definition, I don't get the problem. But that's not going to scale well for complicated modules.
Best Answer
Is there any reason you can't have the definition of the main class in the
init.pp
file?My understanding of the class discovery is rudimentary, but the file
modules/mod1/mod1.pp
would be automatically checked for themod1::mod1
class, not themod1
class.As far as I'm aware, the
mod1
class should always be defined ininit.pp
, but that doesn't mean your entire module's config has to be in there - sub-classes are helpful!The module design that I believe is recommended these days is along these lines:
mod1/init.pp
:mod1/install.pp
:mod1/config.pp
:mod1/service.pp
:Edit: further, you shouldn't be using
import
inside of modules:http://docs.puppetlabs.com/puppet/2.7/reference/lang_import.html