Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hiera hash: telegraf inputs with no parameters #81

Closed
krostar opened this issue Sep 19, 2017 · 1 comment
Closed

Hiera hash: telegraf inputs with no parameters #81

krostar opened this issue Sep 19, 2017 · 1 comment

Comments

@krostar
Copy link

krostar commented Sep 19, 2017

Hi,
I'm using your module with the following configuration:

My configuration

# site/profile/manifests/monitoring.pp
class profile::monitoring (
  $inputs = lookup('profile::monitoring::inputs', Hash, 'hash'),
  $outputs = lookup('profile::monitoring::outputs', Hash, 'hash'),
  ) {

  class { '::telegraf':
    hostname => $::hostname,
    inputs   => $inputs,
    outputs  => $outputs,
  }

}
# data/global.yml
#...
profile::monitoring::inputs:
  cpu:
    percpu: false
    totalcpu: true
    collect_cpu_time: false
  disk:
  diskio:
  kernel:
  mem:
  processes:
  swap:
  system:
  nstat:
  puppetagent:

profile::monitoring::outputs:
  influxdb:
    urls:
      - http://influx.domain.tld
#...

Problem

When I execute the agent on the monitoring node, I have an undefined method 'sort' for :undef:Symbol error:

root@monitoring-dev-1:~# puppet agent -t
Info: Using configured environment 'dev'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Evaluation Error: Error while evaluating a Function Call, Failed to parse template telegraf/telegraf.conf.erb:
  Filepath: /etc/puppetlabs/code/environments/dev/modules/telegraf/templates/telegraf.conf.erb
  Line: 47
  Detail: undefined method `sort' for :undef:Symbol
 at /etc/puppetlabs/code/environments/dev/modules/telegraf/manifests/config.pp:12:18 on node monitoring-dev-1.local.tld
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

I'm pretty new to puppet but I think the problem is that an undefined value in a Hash is not nil in a template, even if the official latest documentation about template says otherwise

# case 1: this is gonna fail since the `cpu` value is undefined
profile::monitoring::inputs:
  cpu:

# case 2: this is gonna pass because the `cpu` value is defined
profile::monitoring::inputs:
  cpu:
    percpu: false
    totalcpu: true
    collect_cpu_time: false

# case 3: this is gonna pass because the `cpu` value is explicitly set to an empty hash
# https://stackoverflow.com/questions/33510094/syntax-for-empty-dictionary-in-yaml
profile::monitoring::inputs:
  cpu: {}

The error is in the modules/telegraf/templates/telegraf.conf.erb file line 47 (for inputs):

# modules/telegraf/templates/telegraf.conf.erb
#...
<% if @_inputs -%>
#
# INPUTS:
#
<%   @_inputs.sort.each do | input, options | -%>
[[inputs.<%= input %>]]
<%      unless options == nil -%> # option will not be nil in case 1
<%          options.sort.each do | option, value | -%> # gonna fail here since undefined does not have a sort function
  <%= option -%> = <% if value.is_a?(String) %>"<%= value %>"<% elsif value.is_a?(Array) %><%= value.inspect %><% else$
<%          end -%>
<%      end -%>
<%   end -%>
<% end -%>

Potential solutions

As mentioned above, if we explictly set a hash key to {} the options variable will not be nil or undefined and the template will not fail to find the sort function.

Another solution can be to explicitly check for undefined symbol in the erb template like this:

# modules/telegraf/templates/telegraf.conf.erb
#...
<% if @_inputs -%>
#
# INPUTS:
#
<%   @_inputs.sort.each do | input, options | -%>
[[inputs.<%= input %>]]
<%      unless options == nil or options == :undef -%> # explicitly check for nil or undefined values
<%          options.sort.each do | option, value | -%>
  <%= option -%> = <% if value.is_a?(String) %>"<%= value %>"<% elsif value.is_a?(Array) %><%= value.inspect %><% else$
<%          end -%>
<%      end -%>
<%   end -%>
<% end -%>

I personally choose the solution with explicit {} for empty values.
Hope I didnt miss something and this is gonna help,
Thanks for the module,
krostar

@yankcrime
Copy link
Member

This should be resolved via #80.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants