diff --git a/README.md b/README.md
index faa24c1ae..de490c657 100644
--- a/README.md
+++ b/README.md
@@ -153,6 +153,7 @@ documentation for each plugin for configurable attributes.
* `memcached`(see [collectd::plugin::memcached](#class-collectdpluginmemcached)
below )
* `memory`(see [collectd::plugin::memory](#class-collectdpluginmemory) below )
+* `modbus` (see [collectd::plugin::modbus](#class-collectdpluginmodbus) below)
* `mongodb`(see [collectd::plugin::mongodb](#class-collectdpluginmongodb) below )
* `mysql` (see [collectd::plugin::mysql](#class-collectdpluginmysql) below)
* `netlink` (see [collectd::plugin::netlink](#class-collectdpluginnetlink) below)
@@ -1073,6 +1074,35 @@ class { 'collectd::plugin::memory':
}
```
+#### Class: `collectd::plugin::modbus`
+
+```puppet
+class {'collectd::plugin::modbus':
+ ensure => 'present',
+ data => {
+ current_phase_a => {
+ 'type' => 'gauge',
+ 'instance' => 'current phase A',
+ 'register_base' => 1234,
+ 'register_type' => 'Float',
+ }
+ },
+ hosts => {
+ meter123 => {
+ 'address' => '127.0.0.1',
+ 'port' => 502,
+ 'interval' => 10,
+ 'slaves' => {
+ 255 => {
+ 'instance' => 'power meter 255',
+ 'collect' => ['current_phase_a'],
+ }
+ },
+ }
+ },
+}
+```
+
#### Class: `collectd::plugin::mysql`
```puppet
diff --git a/REFERENCE.md b/REFERENCE.md
index 6f1127127..b5294fe53 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -60,6 +60,7 @@
* [`collectd::plugin::mcelog`](#collectd--plugin--mcelog): https://collectd.org/documentation/manpages/collectd.conf.5.shtml#plugin_mcelog
* [`collectd::plugin::memcached`](#collectd--plugin--memcached): https://collectd.org/wiki/index.php/Plugin:memcached
* [`collectd::plugin::memory`](#collectd--plugin--memory): https://collectd.org/wiki/index.php/Plugin:Memory
+* [`collectd::plugin::modbus`](#collectd--plugin--modbus): Install and configure the modbus plugin
* [`collectd::plugin::mongodb`](#collectd--plugin--mongodb): Class: collectd::plugin::mongodb
* [`collectd::plugin::mysql`](#collectd--plugin--mysql): MySQL plugin https://collectd.org/wiki/index.php/Plugin:MySQL
* [`collectd::plugin::netlink`](#collectd--plugin--netlink): https://collectd.org/wiki/index.php/Plugin:Netlink
@@ -188,6 +189,9 @@
* [`Collectd::LOGPARSER::Message`](#Collectd--LOGPARSER--Message): https://wiki.opnfv.org/display/fastpath/Logparser+plugin+HLD
* [`Collectd::MCELOG::Memory`](#Collectd--MCELOG--Memory): https://collectd.org/documentation/manpages/collectd.conf.5.shtml#plugin_mcelog
* [`Collectd::Manifests::Init`](#Collectd--Manifests--Init)
+* [`Collectd::Modbus::Data`](#Collectd--Modbus--Data): represents a modbus data entry
+* [`Collectd::Modbus::Host`](#Collectd--Modbus--Host): represents a modbus host entry
+* [`Collectd::Modbus::Slave`](#Collectd--Modbus--Slave): Represents a modbus host's slave entry
* [`Collectd::Network::SecurityLevel`](#Collectd--Network--SecurityLevel)
* [`Collectd::Redis::Node`](#Collectd--Redis--Node)
* [`Collectd::SNMP::AuthProtocol`](#Collectd--SNMP--AuthProtocol)
@@ -3591,6 +3595,54 @@ Data type: `Any`
Default value: `undef`
+### `collectd::plugin::modbus`
+
+Install and configure the modbus plugin
+
+* **See also**
+ * https://collectd.org/wiki/index.php/Plugin:Modbus
+
+#### Parameters
+
+The following parameters are available in the `collectd::plugin::modbus` class:
+
+* [`ensure`](#-collectd--plugin--modbus--ensure)
+* [`manage_package`](#-collectd--plugin--modbus--manage_package)
+* [`data`](#-collectd--plugin--modbus--data)
+* [`hosts`](#-collectd--plugin--modbus--hosts)
+
+##### `ensure`
+
+Data type: `Enum['present', 'absent']`
+
+Enable/Disable modbus support
+
+Default value: `'present'`
+
+##### `manage_package`
+
+Data type: `Optional[Boolean]`
+
+Install collectd-modbus package? Currently supports RedHat and Debian os family.
+
+Default value: `undef`
+
+##### `data`
+
+Data type: `Hash[String[1], Collectd::Modbus::Data]`
+
+modbus data entries
+
+Default value: `{}`
+
+##### `hosts`
+
+Data type: `Hash[String[1], Collectd::Modbus::Host]`
+
+modbus host entries
+
+Default value: `{}`
+
### `collectd::plugin::mongodb`
Class: collectd::plugin::mongodb
@@ -10312,6 +10364,65 @@ The Collectd::Manifests::Init data type.
Alias of `Pattern[/(^5.4|^5.5|^5.6|^5.7|^5.8|^master)/]`
+### `Collectd::Modbus::Data`
+
+https://github.com/collectd/collectd/blob/main/src/modbus.c
+
+Alias of
+
+```puppet
+Struct[{
+ Optional['instance'] => String,
+ NotUndef['type'] => String[1],
+ NotUndef['register_base'] => Integer[0],
+ NotUndef['register_type'] => Enum[
+ 'Int16',
+ 'Int32',
+ 'Int32LE',
+ 'Uint16',
+ 'Uint32',
+ 'Uint32LE',
+ 'Float',
+ 'FloatLE',
+ 'Uint64',
+ 'Int64',
+ 'Double',
+ ],
+ Optional['register_cmd'] => Enum['ReadHolding', 'ReadInput'],
+}]
+```
+
+### `Collectd::Modbus::Host`
+
+represents a modbus host entry
+
+Alias of
+
+```puppet
+Struct[{
+ NotUndef['address'] => String[1],
+ NotUndef['port'] => Stdlib::Port,
+ NotUndef['slaves'] => Hash[Integer, Collectd::Modbus::Slave],
+ Optional['interval'] => Integer[0]
+}]
+```
+
+### `Collectd::Modbus::Slave`
+
+Represents a modbus host's slave entry
+
+Alias of
+
+```puppet
+Struct[{
+ NotUndef['instance'] => String[1],
+ NotUndef['collect'] => Variant[
+ String[1],
+ Array[String[1], 1]
+ ]
+}]
+```
+
### `Collectd::Network::SecurityLevel`
The Collectd::Network::SecurityLevel data type.
diff --git a/manifests/plugin/modbus.pp b/manifests/plugin/modbus.pp
new file mode 100644
index 000000000..b76cd2338
--- /dev/null
+++ b/manifests/plugin/modbus.pp
@@ -0,0 +1,38 @@
+# @summary Install and configure the modbus plugin
+#
+# @see https://collectd.org/wiki/index.php/Plugin:Modbus
+#
+# @param ensure Enable/Disable modbus support
+# @param manage_package Install collectd-modbus package? Currently supports RedHat and Debian os family.
+# @param data modbus data entries
+# @param hosts modbus host entries
+class collectd::plugin::modbus (
+ Enum['present', 'absent'] $ensure = 'present',
+ Optional[Boolean] $manage_package = undef,
+ Hash[String[1], Collectd::Modbus::Data] $data = {},
+ Hash[String[1], Collectd::Modbus::Host] $hosts = {},
+) {
+ include collectd
+
+ $_manage_package = pick($manage_package, $collectd::manage_package)
+
+ $_package_name = $facts['os']['family'] ? {
+ 'RedHat' => 'collectd-modbus',
+ 'Debian' => 'libmodbus5',
+ default => undef,
+ }
+
+ if $_package_name and $_manage_package {
+ package { $_package_name:
+ ensure => $ensure,
+ }
+ }
+
+ collectd::plugin { 'modbus':
+ ensure => $ensure,
+ content => epp('collectd/plugin/modbus.conf', {
+ 'data' => $data,
+ 'hosts' => $hosts,
+ }),
+ }
+}
diff --git a/spec/classes/collectd_plugin_modbus_spec.rb b/spec/classes/collectd_plugin_modbus_spec.rb
new file mode 100644
index 000000000..35e014ef5
--- /dev/null
+++ b/spec/classes/collectd_plugin_modbus_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'collectd::plugin::modbus' do
+ on_supported_os(baseline_os_hash).each do |os, os_facts|
+ context "on #{os}" do
+ let :facts do
+ os_facts
+ end
+ let :pre_condition do
+ 'include collectd'
+ end
+
+ options = os_specific_options(os_facts)
+
+ context ':ensure => present and dataset for Current Phase A' do
+ let :params do
+ {
+ data: {
+ 'current_phase_a' => {
+ 'type' => 'gauge',
+ 'instance' => 'Current Phase A',
+ 'register_base' => 1234,
+ 'register_type' => 'Float',
+ }
+ },
+ hosts: {
+ 'power123' => {
+ 'address' => '127.0.0.1',
+ 'port' => 502,
+ 'interval' => 10,
+ 'slaves' => {
+ 255 => {
+ 'instance' => 'power meter 255',
+ 'collect' => ['current_phase_a'],
+ }
+ }
+ }
+ }
+ }
+ end
+
+ it "Will create #{options[:plugin_conf_dir]}/10-modbus.conf" do
+ is_expected.to contain_file('modbus.load').with(
+ ensure: 'present',
+ path: "#{options[:plugin_conf_dir]}/10-modbus.conf",
+ content: %r{Data "current_phase_a".+Instance "Current Phase A".+Host "power123".+Slave 255}m
+ )
+ end
+ end
+
+ context ':ensure => absent' do
+ let :params do
+ {
+ ensure: 'absent',
+ data: {
+ 'current_phase_a' => {
+ 'type' => 'gauge',
+ 'instance' => 'Current Phase A',
+ 'register_base' => 1234,
+ 'register_type' => 'Float',
+ }
+ },
+ hosts: {
+ 'power123' => {
+ 'address' => '127.0.0.1',
+ 'port' => 502,
+ 'interval' => 10,
+ 'slaves' => {
+ 255 => {
+ 'instance' => 'power meter 255',
+ 'collect' => ['current_phase_a'],
+ }
+ }
+ }
+ }
+ }
+ end
+
+ it "Will not create #{options[:plugin_conf_dir]}/10-modbus.conf" do
+ is_expected.to contain_file('modbus.load').with(
+ ensure: 'absent',
+ path: "#{options[:plugin_conf_dir]}/10-modbus.conf"
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/spec/type_aliases/collectd_modbus_data_spec.rb b/spec/type_aliases/collectd_modbus_data_spec.rb
new file mode 100644
index 000000000..86b5e9a17
--- /dev/null
+++ b/spec/type_aliases/collectd_modbus_data_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Collectd::Modbus::Data' do
+ it do
+ is_expected.to allow_values({
+ 'type' => 'foo',
+ 'register_base' => 123,
+ 'register_type' => 'Int32',
+ })
+ end
+
+ it do
+ is_expected.to allow_values({
+ 'type' => 'foo',
+ 'register_base' => 123,
+ 'register_type' => 'Int32',
+ 'register_cmd' => 'ReadInput',
+ })
+ end
+
+ it do
+ is_expected.to allow_values({
+ 'instance' => 'foobar',
+ 'type' => 'foo',
+ 'register_base' => 123,
+ 'register_type' => 'Int32',
+ })
+ end
+
+ it { is_expected.not_to allow_values(nil) }
+ it { is_expected.not_to allow_values({ 'type' => 'foo', 'register_base' => 123 }) }
+end
diff --git a/spec/type_aliases/collectd_modbus_host_spec.rb b/spec/type_aliases/collectd_modbus_host_spec.rb
new file mode 100644
index 000000000..99d9d5a4f
--- /dev/null
+++ b/spec/type_aliases/collectd_modbus_host_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Collectd::Modbus::Host' do
+ let(:slaves) do
+ {
+ 1 => { 'instance' => 'foo1', 'collect' => 'bar1' },
+ 2 => { 'instance' => 'foo2', 'collect' => %w[bar1 bar2] },
+ }
+ end
+
+ it { is_expected.to allow_values({ 'address' => '127.0.0.1', 'port' => 1234, 'slaves' => slaves }) }
+ it { is_expected.to allow_values({ 'address' => '127.0.0.1', 'port' => 1234, 'slaves' => slaves, 'interval' => 120 }) }
+
+ it { is_expected.not_to allow_values(nil) }
+ it { is_expected.not_to allow_values({ 'address' => '127.0.0.1', 'port' => '1234', 'slaves' => slaves, 'interval' => 120 }) }
+ it { is_expected.not_to allow_values({ 'port' => 1234, 'slaves' => slaves, 'interval' => 120 }) }
+end
diff --git a/spec/type_aliases/collectd_modbus_slave_spec.rb b/spec/type_aliases/collectd_modbus_slave_spec.rb
new file mode 100644
index 000000000..1e2fb3322
--- /dev/null
+++ b/spec/type_aliases/collectd_modbus_slave_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Collectd::Modbus::Slave' do
+ it { is_expected.to allow_values({ 'instance' => 'foo1', 'collect' => 'bar1' }) }
+ it { is_expected.to allow_values({ 'instance' => 'foo1', 'collect' => %w[bar1 bar2] }) }
+
+ it { is_expected.not_to allow_values(nil) }
+ it { is_expected.not_to allow_values({ 'collect' => ['bar1'] }) }
+ it { is_expected.not_to allow_values({ 'instance' => 'foo1' }) }
+ it { is_expected.not_to allow_values({ 'instance' => 'foo1', 'collect' => [] }) }
+end
diff --git a/templates/plugin/modbus.conf.epp b/templates/plugin/modbus.conf.epp
new file mode 100644
index 000000000..6f9671337
--- /dev/null
+++ b/templates/plugin/modbus.conf.epp
@@ -0,0 +1,52 @@
+<%- |
+ Hash[String[1], Collectd::Modbus::Host] $hosts = {},
+ Hash[String[1], Collectd::Modbus::Data] $data = {},
+| -%>
+<% if $data or $hosts { -%>
+
+<% $data.keys.sort.each |String $key| {
+ $val = $data[$key] -%>
+ ">
+ Type "<%= $val['type'] %>"
+<% if $val['instance'] { -%>
+ Instance "<%= $val['instance'] %>"
+<% } -%>
+<% if $val['register_base'] { -%>
+ RegisterBase <%= $val['register_base'] %>
+<% } -%>
+<% if $val['register_type'] { -%>
+ RegisterType <%= $val['register_type'] %>
+<% } -%>
+<% if $val['register_cmd'] { -%>
+ RegisterCmd <%= $val['register_cmd'] %>
+<% } -%>
+
+<% } -%>
+<% $hosts.keys.sort.each |String $key| {
+ $val = $hosts[$key] -%>
+ ">
+ Address "<%= $val['address'] %>"
+<% if $val['port'] { -%>
+ Port <%= $val['port'] %>
+<% } -%>
+<% if $val['interval'] { -%>
+ Interval <%= $val['interval'] %>
+<% } -%>
+<% if $val['slaves'] {
+ $val['slaves'].keys.sort.each |$slave_key| {
+ $slave_val = $val['slaves'][$slave_key]
+-%>
+ >
+<% if $slave_val['instance'] { -%>
+ Instance "<%= $slave_val['instance'] %>"
+<% } -%>
+<% $slave_val['collect'].sort.each |String $data_name| { -%>
+ Collect "<%= $data_name %>"
+<% } -%>
+
+<% } -%>
+<% } -%>
+
+<% } -%>
+
+<% } -%>
diff --git a/types/modbus/data.pp b/types/modbus/data.pp
new file mode 100644
index 000000000..d3bcc63b7
--- /dev/null
+++ b/types/modbus/data.pp
@@ -0,0 +1,22 @@
+# @summary represents a modbus data entry
+#
+# https://github.com/collectd/collectd/blob/main/src/modbus.c
+type Collectd::Modbus::Data = Struct[{
+ Optional['instance'] => String,
+ NotUndef['type'] => String[1],
+ NotUndef['register_base'] => Integer[0],
+ NotUndef['register_type'] => Enum[
+ 'Int16',
+ 'Int32',
+ 'Int32LE',
+ 'Uint16',
+ 'Uint32',
+ 'Uint32LE',
+ 'Float',
+ 'FloatLE',
+ 'Uint64',
+ 'Int64',
+ 'Double',
+ ],
+ Optional['register_cmd'] => Enum['ReadHolding', 'ReadInput'],
+}]
diff --git a/types/modbus/host.pp b/types/modbus/host.pp
new file mode 100644
index 000000000..b59eff92b
--- /dev/null
+++ b/types/modbus/host.pp
@@ -0,0 +1,7 @@
+# @summary represents a modbus host entry
+type Collectd::Modbus::Host = Struct[{
+ NotUndef['address'] => String[1],
+ NotUndef['port'] => Stdlib::Port,
+ NotUndef['slaves'] => Hash[Integer, Collectd::Modbus::Slave],
+ Optional['interval'] => Integer[0]
+}]
diff --git a/types/modbus/slave.pp b/types/modbus/slave.pp
new file mode 100644
index 000000000..7e31e6d5e
--- /dev/null
+++ b/types/modbus/slave.pp
@@ -0,0 +1,8 @@
+# @summary Represents a modbus host's slave entry
+type Collectd::Modbus::Slave = Struct[{
+ NotUndef['instance'] => String[1],
+ NotUndef['collect'] => Variant[
+ String[1],
+ Array[String[1], 1]
+ ]
+}]