Ask Your Question
0

future_parser breaks test.

asked 2015-07-08 08:22:19 -0500

Krist van Besien gravatar image

updated 2015-07-16 04:04:58 -0500

I have this line in my module manifest:

class pulp::plugin::crane (
  $debug                     = false,
  $data_dir                  = '/var/lib/pulp/published/docker/app/',
  $base_url                  = '/',
  $https_port                 = '8443',
  $endpoint                  = '',
  $data_dir_polling_interval = 60) {
  unless ($::operatingsystemmajrelease == 6){ fail('This can only be installed on el6')}

  package { 'python-crane': ensure => present }

  include httpd

  file { '/etc/crane.conf':
    ensure  => present,
    owner   => root,
    group   => root,
    mode    => '0644',
    notify  => Service['httpd'],
    content => template('pulp/crane/crane.conf.erb'),
    seltype => 'httpd_sys_content_t',
  }

  file { '/etc/httpd/conf.d/crane_vhost.conf':
    ensure  => present,
    owner   => root,
    group   => root,
    mode    => '0644',
    content => template('pulp/crane/crane_vhost.conf.erb'),
    notify  => Service['httpd'],
    seltype => 'httpd_config_t',
  }

  iptables::rule { $https_port: }

  selinux::seport { $https_port: setype => 'http_port_t' }
}

This works entirely as expected under puppet 3.7. When I try to apply this on a el7 host I get a usefull message telling me that I shouldn't...

To test this I have this in my spec test:

describe 'pulp::plugin::crane', :type => 'class' do
  let(:pre_condition) {"Exec{ path => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin' }" }
  let(:facts) do
    {
      :virtual          => 'vmware',
      :operatingsystem  => 'redhat',
      :operatingsystemrelease => '6.6',
      :operatingsystemmajrelease => '6',
      :osfamily         => 'RedHat',
      :is_virtual       => true,
      :concat_basedir   => '/var/lib/puppet/concat',
      :fqdn             => 'localserver.example.com',
      :concat_basedir   => '/var/lib/puppet/concat',
      :is_virtual       => true,
      :virtual          => 'kvm',
    }
  end
  describe 'Fail on wrong OS' do
    before do
      facts.merge!(
        :operatingsystemmajrelease => '7',
      )
    end
    it do
      expect {
        should compile
      }.to raise_error( /This can only be installed on el6/ )

    end
  end

end

My spec tests all run without error when run normally. Eg. "bundle exec rake" ends with all tests successfull However when I try this with future parser enabled I get a strange error:

export FUTURE_PARSER=yes

bundle exec rake

(...)


Puppet::Error:
       Evaluation Error: Error while evaluating a Function Call, This can only be installed on el6 at /vagrant/workspace/pulp/spec/fixtures/modules/pulp/manifests/plugin/crane.pp:11:47 on node localhost.pwlan.ch
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/parser/functions/fail.rb:3:in `block in <top (required)>'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/parser/functions.rb:164:in `block (2 levels) in newfunction'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/util/profiler/around_profiler.rb:58:in `profile'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/util/profiler.rb:51:in `profile'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/parser/functions.rb:157:in `block in newfunction'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/pops/evaluator/runtime3_support.rb:248:in `call_function'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/pops/evaluator/evaluator_impl.rb:814:in `call_function_with_block'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/pops/evaluator/evaluator_impl.rb:794:in `eval_CallNamedFunctionExpression'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/pops/visitor.rb:64:in `visit_this_1'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/pops/evaluator/evaluator_impl.rb:74:in `evaluate'
     # /home/vagrant/.gem/ruby/gems/puppet-3.7.5/lib/puppet/pops/evaluator/evaluator_impl.rb:947:in `block in eval_UnlessExpression ...
(more)
edit retag flag offensive close merge delete

Comments

Can you link to the code? There's not enough data here to diagnose it. My guess would be that you haven't defined the $::operatingsystemmajrelease fact in the test, so it's undefined and therefore not equal to 6.

domcleal gravatar imagedomcleal ( 2015-07-11 14:43:39 -0500 )edit

I can unfortunately not link to the code. The tests run fin when done normally. It's when I run the exact same tests with future parser enabled that an error is thrown.

Krist van Besien gravatar imageKrist van Besien ( 2015-07-15 08:18:12 -0500 )edit

Added code directly in the question.

Krist van Besien gravatar imageKrist van Besien ( 2015-07-15 08:25:18 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted
1

answered 2015-07-16 14:10:26 -0500

domcleal gravatar image

Under the future/4.x parser, variables have data types (e.g. string, integer), which were never really represented in the old/3.x parser which mostly handled only strings.

I suspect what's happening is that your test is passing in a string for the value of the fact:

:operatingsystemmajrelease => '6',

But because you use an unquoted 6 in the manifest, it's trying to compare to an integer:

unless ($::operatingsystemmajrelease == 6){ fail('This can only be installed on el6')}

If you were to quote the 6 here, it would probably match in the test. Try doing:

unless ($::operatingsystemmajrelease == '6'){ fail('This can only be installed on el6')}

You can see this behaviour with puppet apply --parser future -e 'notice("6" == 6)', which will output false. Changing quoting or the parser will cause it to output true.

The interesting question is, whether this would also work for real - i.e. are the values of $::operatingsystemmajrelease also a string when running Puppet outside of tests?

Puppet 3 would always keep the values of facts as strings, but could be changed with the stringify_facts (docs) to use their real data types. In Puppet 4, it always uses their real data types.

I think from checking the source, that Facter 2.x always provides operatingsystemmajrelease as a string. In this case, I'd suggest just quoting the '6'. I can't speak on Facter 3.x or whether it'll be changed in the future though. If it did become an integer and you wanted to keep compatibility then perhaps you could use a string to int conversion or vice versa.

edit flag offensive delete link more

Comments

Thank you. This makes a lot of sense now. But this also shows that the error message I received was a red herring. This could be done better I think.

Krist van Besien gravatar imageKrist van Besien ( 2015-07-17 02:17:17 -0500 )edit
0

answered 2015-07-15 23:09:59 -0500

It could be a bug. Do you know how to debug a problem like this using pry? Can you update your post with the full stack trace that you get when the test fails, and the exact version of Puppet you're using?

edit flag offensive delete link more

Comments

Pry really doesn't give me any help here. I can add pry() before the line, and then I see what the catalog is at that time. But I don't see how this helps me find out where the evaluaion error comes from .

Krist van Besien gravatar imageKrist van Besien ( 2015-07-16 03:58:47 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2015-07-08 08:22:19 -0500

Seen: 133 times

Last updated: Jul 16 '15