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.


Reply via email to