Foreman/Puppet module pdxcat/collectd. Syntax of hash

2k Views Asked by At

New to puppet and trying to get this module to work, but finding it quite frustrating.

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: can't convert String into Hash at /etc/puppet/modules/collectd/manifests/plugin/network.pp:28

The plugin I am struggling with is this one: https://forge.puppetlabs.com/pdxcat/collectd#class-collectdpluginnetwork

The value I am trying to set is servers under collectd::plugin::network I have tried:

('127.0.0.1': port => 25826,) and 
('hostname' '127.0.0.1' 'port' 25826) and '127.0.0.1': port => 25826,

and a myriad of other options.

Could somebody please let me know how to write a valid hash?

The manifest:

[root@foreman ~]# cat /etc/puppet/modules/collectd/manifests/plugin/network/server.pp
#
define collectd::plugin::network::server (
  $ensure        = 'present',
  $username      = undef,
  $password      = undef,
  $port          = undef,
  $securitylevel = undef,
  $interface     = undef,
) {
  include collectd::params
  include collectd::plugin::network

  $conf_dir = $collectd::params::plugin_conf_dir

  validate_string($name)

  file { "${conf_dir}/network-server-${name}.conf":
    ensure  => $ensure,
    mode    => '0640',
    owner   => 'root',
    group   => $collectd::params::root_group,
    content => template('collectd/plugin/network/server.conf.erb'),
    notify  => Service['collectd'],
  }
}
2

There are 2 best solutions below

1
On BEST ANSWER

When putting hash data into a Foreman smart class parameter (or smart variable), you need to do two things to get it passed to Puppet correctly:

  1. Set the data type on the parameter to Hash, JSON or YAML
  2. Use JSON or YAML to represent the data

The first will ensure that Puppet is given an actual hash of data, instead of a string that looks like a hash (which I think was probably the cause of the error you got), and the second allows Foreman to parse what you enter.

Navigate in Foreman to Configure > Puppet classes > collectd::plugin::network > Smart class parameters > servers, and set Type to JSON (or Hash, or YAML, if you prefer).

Next, change the value of the parameter (either the default or an override further down) to:

{"127.0.0.1":{"port":"25826"}}

This is JSON syntax, which if you compare it to Puppet's DSL, you'll note it uses colons instead of => for key/value separators, and uses double quotes only for strings. Beware that trailing commas aren't valid in JSON.

Pretty much you can copy the example parameter from the documentation or from the other answer, substituting the separators and quotes to convert it to JSON.

Equivalent YAML format would be:

---
  127.0.0.1: 
    port: "25826"

Foreman will accept either when in "Hash" or "Array" mode, and IIRC it will store/retrieve it in YAML format by default.

If Foreman gives an error when saving the parameter, it might be due to the format of the data you're entering. There are numerous validation and linting tools for both JSON and YAML, e.g. jsonlint.com or json_verify (part of the yajl package), so run the data through it first.

There's more information about complex data types in the Foreman manual in section 4.2.6 Smart Matchers.

If you still get an error from Puppet after this, please go to the host page in Foreman, click the YAML button and copy/paste the classes: section of the YAML output (which is what's passed to Puppet), being careful to preserve whitespace.

2
On

Could you please attach fragment of manifest that is not working ?

Here you can find the description of puppet types: https://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html, also about hashes.

According to documentation:

Hashes are written as key/value pairs surrounded by curly braces; a key is separated from its value by a => (arrow, fat comma, or hash rocket), and adjacent pairs are separated by commas. An optional trailing comma is allowed between the final value and the closing curly brace.

{ key1 => 'val1', key2 => 'val2' }

So definitely you have to change "(" brackets to "{". Also after key should be "=>" not ":" Something like this should be working:

servers => { '127.0.0.1' =>
  { 'port' => '25826', },
}