1

I developed my puppet module with ruby version 1.8.7 ran bundle install on the following gem file and rspec tests worked successfully (so did the puppet run):

source 'https://rubygems.org'

if puppetversion = ENV['PUPPET_GEM_VERSION']
  gem 'puppet', puppetversion, :require => false
else
  gem 'puppet', '3.7.5'
end

gem 'metadata-json-lint'
gem 'puppetlabs_spec_helper', '>= 0.1.0'
gem 'puppet-lint', '>= 1.0.0'
gem 'facter', '>= 1.7.0'
gem 'rspec-puppet-facts'

# rspec must be v2 for ruby 1.8.7
if RUBY_VERSION >= '1.8.7' and RUBY_VERSION < '1.9'
  gem 'rspec', '~> 2.0'
end

However when I did a bundle install on the same Gemfile on my CI server which has ruby 1.9.3 I encountered the following rspec failures:

See verbose errors here

The common erorr is:

Puppet::Error:
       Failed to parse template silex/var/config/settings.json.erb:
         Filepath: /var/tmp/silex/spec/fixtures/modules/silex/templates/var/config/settings.json.erb
         Line: 4
         Detail: undefined method `each_with_index' for "default":String

Template that uses the each_with_index method:

{
    "elasticsearch.settings": {
        "connections": [
        <% @elastic_hosts.each_with_index do |host,i| -%>
        {"host":"<%= host['ip'] %>", "port": <%= host['port'] %> }<%= ',' if i < (@elastic_hosts.size - 1) -%>
        <% end -%>
        ],
        "index": "<%= @elastic_index %>"
    }
    },
    "cache.lifetime": <%= @elastic_cache_lifetime %>,
    "environment": "dev",
    "trusted": [
        <% @trusted_hosts.each_with_index do |host,i| -%>
        {"host":"<%= host['host'] %>"}<%= ',' if i < (@trusted_hosts.size - 1) -%>
        <% end -%>
    ],
    "homepage.settings": {
      "hero.count": 20,
      "list.count": 20
    }
}

I'm failing to understand why this would fail with a different version of ruby? I've also tried ruby 2.1.1 with the same result. The results are only successful on the CI server with ruby 1.8.7 (same version I used for development of the module).

UPDATE 1

It appears that because elastic_hosts is a hash map and I had a string it was failing. I did fix this along with trusted_hosts (another hash map) which has resulted in most of the tests passing but the error persists.

See errors here

NOTE: The error is unchanged from the common error highlighted above.

I have also updated the template file above with the full contents.

My config spec file

If you look at my config spec file I am not specifying default as a string anywhere yet it tells me that it is the error..

FIX

As suspected my init spec class had defaults set and adding the hiera look ups for elastic_hosts and trusted_hosts fixed the issue.

UPDATE 2

This behaviour is reproducible between version 1.8.7 and version > 1.9.3. It seems to have something to with how hashes are treated.

kaizenCoder
  • 2,211
  • 6
  • 33
  • 64

1 Answers1

3

The answer is pretty simple: Because the the each method was removed from newer versions of Ruby. One reason was that the method was confusing in the context of UTF-8 strings: does each iterate over each char or each byte?

But there is each_char and you can combine that with with_index:

string.each_char.with_index do |char, i|
  # ...
end

Furthermore you call that method on @elastic_hosts what in the snippet clearly should be an array of hosts. But the error message tells us that the @elastic_hosts is the string default. So it makes sense that the method call with each_with_index fails, but it seems like the iteration itself does not make sense. I advise to check if @elastic_hosts is set correctly.

spickermann
  • 100,941
  • 9
  • 101
  • 131
  • `elastic_hosts` is actually a hash map. You are right about it being set to a string. I am working on getting the hiera lookup working. Will update the answer soon. – kaizenCoder Nov 15 '15 at 08:18