Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add support for pre_condition with functions #36

Merged
merged 1 commit into from

3 participants

@bodepd
Collaborator

This commit adds support for using the pre_condition
hook to specify the source code that should be used to
compile a catalog that can be introspected by functions for
testing purposes.

This allows users to test functions that need access to
catalog contents.

This allows the following snippet to test a function that
needs access to the catalog generated by pre_condition:

describe 'defined_with_params' do
#describe 'when resource is passed as a string' do
let :pre_condition do
'user { "dan": }'
end
it { should run.with_params('User[dan]', {}).and_return('true') }
end

@bodepd bodepd Add support for pre_condition with functions
This commit adds support for using the pre_condition
hook to specify the source code that should be used to
compile a catalog that can be introspected by functions for
testing purposes.

This allows users to test functions that need access to
catalog contents.

This allows the following snippet to test a function that
needs access to the catalog generated by pre_condition:

  describe 'defined_with_params' do
    #describe 'when resource is passed as a string' do
    let :pre_condition do
      'user { "dan": }'
    end
    it { should run.with_params('User[dan]', {}).and_return('true') }
  end
41a2fc8
@rodjek rodjek merged commit e3495af into rodjek:master
@jeffmccune jeffmccune commented on the diff
lib/rspec-puppet/example/function_example_group.rb
((7 lines not shown))
+ if self.respond_to? :pre_condition
+ Puppet[:code] = pre_condition
+ nodename = self.respond_to?(:node) ? node : Puppet[:certname]
+ facts_val = {
+ 'hostname' => nodename.split('.').first,
+ 'fqdn' => nodename,
+ 'domain' => nodename.split('.').last,
+ }
+ facts_val.merge!(munge_facts(facts)) if self.respond_to?(:facts)
+ # we need to get a compiler, b/c we can attach that to a scope
+ @compiler = build_compiler(nodename, facts_val)
+ else
+ @compiler = nil
+ end
+
+ scope = Puppet::Parser::Scope.new(:compiler => @compiler)
@jeffmccune Collaborator

Today, rspec-puppet should not reach directly into Puppet to obtain a scope instance. Instead, it should use the puppetlabs_spec_helper to obtain a scope instance in Puppet version-agnostic manner. As a concrete example, this line:

scope = Puppet::Parser::Scope.new(:compiler => @compiler)

should be:

scope = PuppetlabsSpec::PuppetInternals.scope

This is important because if we change the behavior of the scope object again we will also change PuppetlabsSpec::PuppetInternals.scope to work correctly. rspec-puppet will then "just work" instead of breaking again.

It's very likely that the method signature of the scope object will change as we inject more dependencies through the initializer rather than relying on global process state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jeffmccune jeffmccune commented on the diff
lib/rspec-puppet/example/function_example_group.rb
((23 lines not shown))
scope.method "function_#{function_name}".to_sym
end
+
+ def compiler
+ @compiler
+ end
+ # get a compiler with an attached compiled catalog
+ def build_compiler(node_name, fact_values)
+ compiler = Puppet::Parser::Compiler.new(Puppet::Node.new(node_name, :parameters => fact_values))
+ compiler.compile
+ compiler
+ end
@jeffmccune Collaborator

The same logic applies here. rspec-puppet should not reach deep into Puppet to build a compiler instance. Instead, it should use puppetlabs_spec_helper to obtain a compiler instance in a Puppet version agnostic way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@bodepd
Collaborator

@rodjek Hi Tim, it is probably worth reading through Jeff's comments here. It has implications beyond the single pull request referenced here. It looks like rspec-puppet puppet is going through a few unsupported APIs and the recommended approach is to add an extra dependency on the puppetlabs spec helper gem and refactor calls that call puppet directly to instead make calls through the supported APIs made available by this gem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 2, 2012
  1. @bodepd

    Add support for pre_condition with functions

    bodepd authored
    This commit adds support for using the pre_condition
    hook to specify the source code that should be used to
    compile a catalog that can be introspected by functions for
    testing purposes.
    
    This allows users to test functions that need access to
    catalog contents.
    
    This allows the following snippet to test a function that
    needs access to the catalog generated by pre_condition:
    
      describe 'defined_with_params' do
        #describe 'when resource is passed as a string' do
        let :pre_condition do
          'user { "dan": }'
        end
        it { should run.with_params('User[dan]', {}).and_return('true') }
      end
This page is out of date. Refresh to see the latest.
Showing with 28 additions and 1 deletion.
  1. +28 −1 lib/rspec-puppet/example/function_example_group.rb
View
29 lib/rspec-puppet/example/function_example_group.rb
@@ -9,9 +9,36 @@ def subject
Puppet[:libdir] = Dir["#{Puppet[:modulepath]}/*/lib"].entries.join(File::PATH_SEPARATOR)
Puppet::Parser::Functions.autoloader.loadall
- scope = Puppet::Parser::Scope.new
+ # if we specify a pre_condition, we should ensure that we compile that code
+ # into a catalog that is accessible from the scope where the function is called
+ if self.respond_to? :pre_condition
+ Puppet[:code] = pre_condition
+ nodename = self.respond_to?(:node) ? node : Puppet[:certname]
+ facts_val = {
+ 'hostname' => nodename.split('.').first,
+ 'fqdn' => nodename,
+ 'domain' => nodename.split('.').last,
+ }
+ facts_val.merge!(munge_facts(facts)) if self.respond_to?(:facts)
+ # we need to get a compiler, b/c we can attach that to a scope
+ @compiler = build_compiler(nodename, facts_val)
+ else
+ @compiler = nil
+ end
+
+ scope = Puppet::Parser::Scope.new(:compiler => @compiler)
@jeffmccune Collaborator

Today, rspec-puppet should not reach directly into Puppet to obtain a scope instance. Instead, it should use the puppetlabs_spec_helper to obtain a scope instance in Puppet version-agnostic manner. As a concrete example, this line:

scope = Puppet::Parser::Scope.new(:compiler => @compiler)

should be:

scope = PuppetlabsSpec::PuppetInternals.scope

This is important because if we change the behavior of the scope object again we will also change PuppetlabsSpec::PuppetInternals.scope to work correctly. rspec-puppet will then "just work" instead of breaking again.

It's very likely that the method signature of the scope object will change as we inject more dependencies through the initializer rather than relying on global process state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
scope.method "function_#{function_name}".to_sym
end
+
+ def compiler
+ @compiler
+ end
+ # get a compiler with an attached compiled catalog
+ def build_compiler(node_name, fact_values)
+ compiler = Puppet::Parser::Compiler.new(Puppet::Node.new(node_name, :parameters => fact_values))
+ compiler.compile
+ compiler
+ end
@jeffmccune Collaborator

The same logic applies here. rspec-puppet should not reach deep into Puppet to build a compiler instance. Instead, it should use puppetlabs_spec_helper to obtain a compiler instance in a Puppet version agnostic way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
end
end
Something went wrong with that request. Please try again.