Issue #15106 has been updated by Adrien Thebo. Status changed from Investigating to Code Insufficient
This behavior can be triggered in a number of cases. In the general case this is the result of specifying classes via the ENC that cannot be reached/reparsed by parsing `Puppet[:manifest]` ## Summary Specifying classes with the ENC that can't be reached by parsing `Puppet[:manifest]` can cause catalog compilation to unexpectedly fail in very weird ways. ### Missing files are always treated as changed The implementation of [Puppet::Util::LoadedFile](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/util/loadedfile.rb#L50) treats missing files as always changed. This generally isn't a problem because files are generally only watched if they're present. However if we explicitly watch a file regardless of presence, this becomes an issue. ### `Puppet[:manifest]` is always parsed When an environment is initially loaded it will always try to load the [default manifest](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/node/environment.rb#L227). This file will be parsed regardless of the existence of the file on disk, which is triggered when an ENC is used. ### Every manifest that is parsed is also watched When the Environment tries to perform the initial import it tries to parse `Puppet[:manifest]`. When the parser is given a file to parse, it also [starts watching](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/parser/parser_support.rb#L92) that file. If we're forcibly adding a file to watch then this will trigger the behavior that a file has always changed. ### If any file is changed then a reparse may be triggered The TypeCollection keeps track of if a [reparse is required](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/resource/type_collection.rb#L134). If any watched files are [marked as changed](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/resource/type_collection.rb#L138) then it will indicate that a reparse is required. ### The `known_resource_types` is a singleton On first inspection the known_resource_types/TypeCollection looks like it's an instance variable of an environment, with an invocation like `environment.known_resource_types`. However there is only one TypeCollection instance present at [any given time](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/node/environment.rb#L84) that's stored in a thread local variable. Since Puppet can only run in a single thread, this makes it a global variable. ### `known_resource_types` is tied to a single environment This isn't a bug per se, but causes other issues. When a TypeCollection is instantiated it is created in a specific environment, so the Environment and TypeCollection are tightly coupled in that aspect. ### Changing the environment forces a reload of `known_resource_types` Since `known_resource_types` is a singleton but Environments are not, each environment has to be able to regenerate the known_resource_types. If two different environments called in succession, the second environment will [destroy the known_resource_types variable](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/node/environment.rb#L82) that was tied to the previous environment and generate a new `known_resource_types`. ### `Puppet::Parser::Catalog` creates resources without an environment The catalog stores resources in a hash that is keyed with either the title or uniqueness key of that resource. Given a type and a title for a resource, the only way to generate that information is to create a new resource and interrogate it. When the catalog creates this temporary resource it creates the resource without an [explicit environment](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/resource/catalog.rb#L376). ### Calling `Puppet::Resource#uniqueness_key` can invoke `known_resource_types` in the wrong environment When the catalog is searching for an existing resource in the resource table it has to call the `#uniqueness_key` method on the resource. This method invokes the [`#key_attributes` method](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/resource.rb#L255), which invokes [`#resource_type`](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/resource.rb#L259), which calls the [`#known_resource_types`](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/resource.rb#L232) method on the environment. If the resource environment doesn't match the current environment, this will regenerate the `known_resource_types` variable. ### The ENC can load classes that can't be reloaded by reparsing `Puppet[:manifest]` When the catalog is being compiled, classes that are explicitly passed by an ENC are parsed first. Each class is explicitly [loaded by name](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/parser/compiler.rb#L102). When the `known_resource_types` value is regenerated, it relies on the assumption that reloading `Puppet[:manifest]` is able to retrieve the definition of every class and defined type. Since classified in the ENC are [explicitly loaded by name](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/parser/compiler.rb#L129) these classes may not be reachable by walking the parse tree starting at `Puppet[:manifest]`. If there is no default manifest, then there is no way they can be reached. ### Multiple environments unmasks the behavior of `Puppet::Resource::Catalog#resource` If only a single environment is in use, then creating a Puppet::Resource in the catalog will get the correct environment by accident. However if two environments are in use and a catalog is compiled using the non-default one, the temporary resources in the `#resource` method will trigger the reload of the `known_resource_types`. ### Touching a file during catalog compilation can cause a reload of `known_resource_types`. If `Puppet[:manifest]` is missing the behavior around the reloading of `known_resource_types` can be reliably triggered, since that file is always considered changed. This can also be triggered by touching a file during catalog compilation. This will not happen immediately as files are only checked for change until `Puppet[:filetimeout]` seconds have elapsed after the last check. But if a file has been touched and is marked as changed, `known_resource_types` will be [dumped and reloaded](https://github.com/puppetlabs/puppet/blob/3.2.1/lib/puppet/node/environment.rb#L85). - - - ---------------------------------------- Bug #15106: Missing site.pp can cause error 'Cannot find definition Class' https://projects.puppetlabs.com/issues/15106#change-93117 * Author: Ken Barber * Status: Code Insufficient * Priority: Normal * Assignee: Adrien Thebo * Category: compiler * Target version: * Affected Puppet version: 2.7.12 * Keywords: customer * Branch: ---------------------------------------- In certain content scenarios, a missing site.pp can cause the error: err: Could not retrieve catalog from remote server: Error 400 on SERVER: Cannot find definition Class at /etc/puppetlabs/puppet/modules/mymodule/manifests/init.pp:3 on node foobar This can be remedied by touching the site.pp, but since site.pp is no longer mandatory this is causing issues for users who are specifically omitting. This is confirmed at a customer site using PE 2.5.0 running Puppet 2.7.12. This is specifically reproducible when the user is using environments, and apparently doesn't occur without environments. -- You have received this notification because you have either subscribed to it, or are involved in it. To change your notification preferences, please click here: http://projects.puppetlabs.com/my/account -- You received this message because you are subscribed to the Google Groups "Puppet Bugs" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/puppet-bugs. For more options, visit https://groups.google.com/groups/opt_out.
