Issue #15106 has been updated by Charlie Sharpsteen.

Allright, it looks like there are two issues at play here.

The first issue is that non-existant files that are being watched by a 
LoadedFile class are perpetually marked as `changed?`. If the file didn't exist 
the last time LoadedFile performed a status check and still doesn't exist 
during the next check, then `changed?` should probably report false. Constantly 
reporting true when nothing actually changed causes Puppet to perform a bunch 
unnecessary re-parses and re-initializations---which leads us to the second 
issue.

When an ENV provides classes for an node, these end up as 
`unevaluated_resources` which are resolved during [the evaluate_generators 
step](https://github.com/puppetlabs/puppet/blob/3.2.0-rc2/lib/puppet/parser/compiler.rb#L103)
 of compilation.

During this step, the resources are resolved [by 
calling](https://github.com/puppetlabs/puppet/blob/3.2.0-rc2/lib/puppet/resource.rb#L234)
 `environment.known_resource_types`. Let's see what happens when an empty 
`site.pp` is present:

<pre>
[root@puppetmaster puppet]# puppet master --no-daemonize

From: /puppetlabs/puppet/lib/puppet/parser/compiler.rb @ line 102 
Puppet::Parser::Compiler#compile:

     91: def compile
     92:   # Set the client's parameters into the top scope.
     93:   Puppet::Util::Profiler.profile("Compile: Set node parameters") { 
set_node_parameters }
     94:
     95:   Puppet::Util::Profiler.profile("Compile: Created settings scope") { 
create_settings_scope }
     96:
     97:   Puppet::Util::Profiler.profile("Compile: Evaluated main") { 
evaluate_main }
     98:
     99:   Puppet::Util::Profiler.profile("Compile: Evaluated AST node") { 
evaluate_ast_node }
    100:
    101:   Puppet::Util::Profiler.profile("Compile: Evaluated node classes") { 
evaluate_node_classes }
 => 102:   require 'pry';binding.pry
    103:   Puppet::Util::Profiler.profile("Compile: Evaluated generators") { 
evaluate_generators }
    104:
    105:   Puppet::Util::Profiler.profile("Compile: Finished catalog") { finish 
}
    106:
    107:   fail_on_unevaluated
    108:
    109:   @catalog
    110: end

[1] pry(#<Puppet::Parser::Compiler>)> environment
=> #<Puppet::Node::Environment:0xb73cbc2c
 @attr_expirations=
  {:modules=>Wed May 08 16:41:46 -0700 2013,
   :modulepath=>Wed May 08 16:41:46 -0700 2013},
 @known_resource_types=
  TypeCollection{:nodes=>[], :hostclasses=>["", "apache", "settings"], 
:definitions=>[]},
 @mon_count=0,
 @mon_entering_queue=[],
 @mon_owner=nil,
 @mon_waiting_queue=[],
 @name=:fail,
 @value_cache=
  {:modules=>
    [#<Puppet::Module:0xb7399da8
      @author="puppetlabs",
      @dependencies=[],
      @environment=#<Puppet::Node::Environment:0xb73cbc2c ...>,
      @forge_name="puppetlabs/firewall",
      ...


[3] pry(#<Puppet::Parser::Compiler>)> environment.known_resource_types
=> TypeCollection{:nodes=>[], :hostclasses=>["", "apache", "settings"], 
:definitions=>[]}


[4] pry(#<Puppet::Parser::Compiler>)> 
environment.known_resource_types.hostclass('apache')
=> #<Puppet::Resource::Type:0xb6fd65a4
 @arguments=
  {"serveradmin"=>( Puppet::Parser::AST::String "root@localhost" nil ),
   "sendfile"=>( Puppet::Parser::AST::Boolean false nil ),
   "default_mods"=>( Puppet::Parser::AST::Boolean true nil ),
   "purge_vdir"=>( Puppet::Parser::AST::Boolean true nil ),
   "service_enable"=>( Puppet::Parser::AST::Boolean true nil )},
 @code=
  ( Puppet::Parser::AST::BlockExpression [include(apache::params), 
#<Puppet::Parser::AST::Resource:0xb6ff8064>, validate_bool($service_enable), 
#<Puppet::Parser::AST::Resource:0xb6ff20b0>, 
#<Puppet::Parser::AST::Resource:0xb6feb378>, 
#<Puppet::Parser::AST::IfStatement:0xb6fddf0c>, 
#<Puppet::Parser::AST::IfStatement:0xb6fd6fa4>] [( 
Puppet::Parser::AST::Function include(apache::params) [] ), ( 
Puppet::Parser::AST::Resource #<Puppet::Parser::AST::Resource:0xb6ff8064> [] ), 
( Puppet::Parser::AST::Function validate_bool($service_enable) [] ), ( 
Puppet::Parser::AST::Resource #<Puppet::Parser::AST::Resource:0xb6ff20b0> [] ), 
( Puppet::Parser::AST::Resource #<Puppet::Parser::AST::Resource:0xb6feb378> [] 
), ( Puppet::Parser::AST::IfStatement 
#<Puppet::Parser::AST::IfStatement:0xb6fddf0c> [] ), ( 
Puppet::Parser::AST::IfStatement #<Puppet::Parser::AST::IfStatement:0xb6fd6fa4> 
[] )] ),
 @doc=
  "Class: apache\n\nThis class installs Apache\n\nParameters:\n\nActions:\n  - 
Install Apache\n  - Manage Apache service\n\nRequires:\n\nSample Usage:\n\n",
 @file="/tmp/test/modules/apache/manifests/init.pp",
 @line=15,
 @module_name="apache",
 @name="apache",
 @namespace="apache",
 @resource_type_collection=
  TypeCollection{:nodes=>[], :hostclasses=>["", "apache", "settings"], 
:definitions=>[]},
 @type=:hostclass>
</pre>

All is good. The apache class exists in the environment, is accessible through 
the known_resource_types method and can be resolved by name into a hostclass. 
Let's see what happens when the site.pp file is missing:

<pre>
[1] pry(#<Puppet::Parser::Compiler>)> environment
=> #<Puppet::Node::Environment:0xb7419a94
 @attr_expirations=
  {:modules=>Wed May 08 16:50:52 -0700 2013,
   :modulepath=>Wed May 08 16:50:52 -0700 2013},
 @known_resource_types=
  TypeCollection{:nodes=>[], :hostclasses=>["apache", "", "settings"], 
:definitions=>[]},
 @mon_count=0,
 @mon_entering_queue=[],
 @mon_owner=nil,
 @mon_waiting_queue=[],
 @name=:fail,
 @value_cache=
  {:modules=>
    [#<Puppet::Module:0xb73b5e68
      @author="puppetlabs",
      @dependencies=[],
      @environment=#<Puppet::Node::Environment:0xb7419a94 ...>,
      @forge_name="puppetlabs/firewall",
      ...


[2] pry(#<Puppet::Parser::Compiler>)> environment.known_resource_types
=> TypeCollection{:nodes=>[], :hostclasses=>[""], :definitions=>[]}


[3] pry(#<Puppet::Parser::Compiler>)> 
environment.known_resource_types.hostclass('apache')
=> nil


[4] pry(#<Puppet::Parser::Compiler>)> environment
=> #<Puppet::Node::Environment:0xb7419a94
 @attr_expirations=
  {:modules=>Wed May 08 16:50:52 -0700 2013,
   :modulepath=>Wed May 08 16:50:52 -0700 2013},
 @known_resource_types=
  TypeCollection{:nodes=>[], :hostclasses=>[""], :definitions=>[]},
 @mon_count=0,
 @mon_entering_queue=[],
 @mon_owner=nil,
 @mon_waiting_queue=[],
 @name=:fail,
 @value_cache=
  {:modules=>
    [#<Puppet::Module:0xb73b5e68
      @author="puppetlabs",
      @dependencies=[],
      @environment=#<Puppet::Node::Environment:0xb7419a94 ...>,
      @forge_name="puppetlabs/firewall",
      ...
</pre>

At first, the apache class is present in the compiler's environment. But, the 
known_resource_types method fails to return it and therefore fails to resolve 
apache into a hostclass object. The real problem is that after 
known_resource_types is called, the types loaded into the compiler's 
environment are wiped clean---this is what is causing the compilation to fail.

I suspect the problem lies within the known_resource_types method. If we 
inspect the code, we can see that before returning the known types, the 
[environment first 
checks](https://github.com/puppetlabs/puppet/blob/3.2.0-rc2/lib/puppet/node/environment.rb#L84)
 to see if any watched files are out of date. If they are, it re-generates the 
list of known types [by parsing the site.pp 
file](https://github.com/puppetlabs/puppet/blob/3.2.0-rc2/lib/puppet/node/environment.rb#L225-L229).
 During this step, any information regarding classes and environments provided 
by the ENC appears lost.

I suspect this behavior may also be the cause of a few bugs that can be 
summarized as "I touch a random file and 10% of my currently running 
compilations fail".

----------------------------------------
Bug #15106: Missing site.pp can cause error 'Cannot find definition Class'
https://projects.puppetlabs.com/issues/15106#change-90714

* Author: Ken Barber
* Status: Investigating
* Priority: Normal
* Assignee: Charlie Sharpsteen
* 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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to