From eb0c52d509103b4978f9e14e8909bd96efa9880b Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Mon, 12 Feb 2018 23:31:36 +1100 Subject: [PATCH 01/33] The beginning of what's about to happen. --- README.md | 122 +++++++++++++----- data/common.yaml | 7 + hiera.yaml | 22 ++++ .../provider/metricbeat_module/metricbeat.rb | 44 +++++++ lib/puppet/type/metricbeat_module.rb | 24 ++++ manifests/config.pp | 40 ++++++ manifests/init.pp | 45 +++++++ manifests/install.pp | 7 + manifests/package_install.pp | 9 ++ manifests/service.pp | 7 + manifests/service_install.pp | 13 ++ 11 files changed, 310 insertions(+), 30 deletions(-) create mode 100644 data/common.yaml create mode 100644 hiera.yaml create mode 100644 lib/puppet/provider/metricbeat_module/metricbeat.rb create mode 100644 lib/puppet/type/metricbeat_module.rb create mode 100644 manifests/config.pp create mode 100644 manifests/init.pp create mode 100644 manifests/install.pp create mode 100644 manifests/package_install.pp create mode 100644 manifests/service.pp create mode 100644 manifests/service_install.pp diff --git a/README.md b/README.md index a7e4f0a..a5eb544 100644 --- a/README.md +++ b/README.md @@ -15,57 +15,119 @@ ## Description -Start with a one- or two-sentence summary of what the module does and/or what problem it solves. This is your 30-second elevator pitch for your module. Consider including OS/Puppet version it works with. - -You can give more descriptive information in a second paragraph. This paragraph should answer the questions: "What does this module *do*?" and "Why would I use it?" If your module has a range of functionality (installation, configuration, management, etc.), this is the time to mention it. +A Puppet module for managing and configuring official Elastic beats. Works best with RPM/DEB installs of Beats packages but tries to handle custom installations. ## Setup -### What beats affects **OPTIONAL** +### What beats affects + +* Elastic stack repository files. +* Each Beats package. +* Each Beats configuration file. +* Each Beats service file. +* Metricbeat module configuration files. + +### Setup Requirements -If it's obvious what your module touches, you can skip this section. For example, folks can probably figure out that your mysql_instance module affects their MySQL instances. +* The [stdlib](https://forge.puppetlabs.com/puppetlabs/stdlib) Puppet library. -If there's more that they should know about, though, this is the place to mention: +#### Repository management -* Files, packages, services, or operations that the module will alter, impact, or execute. -* Dependencies that your module automatically installs. -* Warnings or other important notices. +When using the repository management, the following module dependencies are required: -### Setup Requirements **OPTIONAL** +* Debian/Ubuntu: [Puppetlabs/apt](http://forge.puppetlabs.com/puppetlabs/apt) +* OpenSuSE/SLES: [Darin/zypprepo](https://forge.puppetlabs.com/darin/zypprepo) -If your module requires anything extra before setting up (pluginsync enabled, another module, etc.), mention it here. - -If your most recent release breaks compatibility or requires particular steps for upgrading, you might want to include an additional "Upgrading" section here. +### Beginning with beats -### Beginning with beats +Include the `beats` class and pass a list of individual Beats to manage with `beats_manage`: -The very basic steps needed for a user to get the module up and running. This can include setup steps, if necessary, or it can be an example of the most basic use of the module. +```puppet +class { 'beats': + $beats_manage => ['metricbeat','auditbeat','heartbeat','packetbeat'] +} +``` ## Usage -This section is where you describe how to customize, configure, and do the fancy stuff with your module here. It's especially helpful if you include usage examples and code samples for doing things with your module. +### Main class -## Reference +There is very few parameters you should need to customise. The most useful would be `config_root` which allows you to control where this module expects the individual Beats configuration files to live: -Users need a complete list of your module's classes, types, defined types providers, facts, and functions, along with the parameters for each. You can provide this list either via Puppet Strings code comments or as a complete list in the README Reference section. +```puppet +class { 'beats': + beats_manage => ['metricbeat','auditbeat','heartbeat','packetbeat'], + config_root => '/opt/beats' +} +``` -* If you are using Puppet Strings code comments, this Reference section should include Strings information so that your users know how to access your documentation. +#### Beats custom configuration -* If you are not using Puppet Strings, include a list of all of your classes, defined types, and so on, along with their parameters. Each element in this listing should include: +This module recommends using [Hiera](https://puppet.com/docs/puppet/5.3/hiera_intro.html) for configuration data. You can either specify your complete Beats configuration in Hiera as YAML under `beats::::settings`: - * The data type, if applicable. - * A description of what the element does. - * Valid values, if the data type doesn't make it obvious. - * Default value, if any. +```yaml +beats::auditbeat::settings: + auditbeat.modules: + - module: auditd + audit_rules: | + -w /etc/group -p wa -k identity + -w /etc/passwd -p wa -k identity + -w /etc/gshadow -p wa -k identity + -w /etc/shadow -p wa -k identity + -w /etc/security/opasswd -p wa -k identity + -a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access + -a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access + -a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access + -a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access + - module: file_integrity + paths: + - /bin + - /usr/bin + - /sbin + - /usr/sbin + - /etc +``` -## Limitations +Or pass a Puppet URL that will be used as the source of configuration: -This is where you list OS compatibility, version compatibility, etc. If there are Known Issues, you might want to include them under their own heading here. +```yaml +beats::auditbeat::settings_file: 'puppet:///somefileshare/auditbeat.yml' +``` -## Development +#### Beats configuration + +### Beats specific usage + +#### Metricbeat modules + +This class can handle enabling/disabling Metricbeat modules for you. + +To enable a list of modules, ensure you manage Metricbeat with this class and then add the modules to `metricbeat_modules_enable`: -Since your module is awesome, other users will want to play with it. Let them know what the ground rules for contributing are. +```puppet +class { 'beats': + beats_manage => ['metricbeat'], + metricbeat_modules_enable => ['docker','kafka'] +} +``` -## Release Notes/Contributors/Etc. **Optional** +To disable some modules: + +```puppet +class { 'beats': + beats_manage => ['metricbeat'], + metricbeat_modules_disable => ['docker','kafka'] +} +``` + +## Reference + +TBD + +## Limitations + +TBD + +## Development -If you aren't using changelog, put your release notes here (though you should consider using changelog). You can also add any additional sections you feel are necessary or important to include here. Please use the `## ` header. +Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for instructions regarding development environments and testing. diff --git a/data/common.yaml b/data/common.yaml new file mode 100644 index 0000000..4c2fc90 --- /dev/null +++ b/data/common.yaml @@ -0,0 +1,7 @@ +beats::package_ensure: present +beats::package_manage: true +beats::service_enable: true +beats::service_ensure: running +beats::service_manage: true +beats::service_provider: ~ +beats::config_root: /etc diff --git a/hiera.yaml b/hiera.yaml new file mode 100644 index 0000000..6e2a6a1 --- /dev/null +++ b/hiera.yaml @@ -0,0 +1,22 @@ +--- +version: 5 + +defaults: + datadir: 'data' + data_hash: 'yaml_data' + +hierarchy: + - name: 'Full Version' + path: '%{facts.os.name}-%{facts.os.release.full}.yaml' + + - name: 'Major Version' + path: '%{facts.os.name}-%{facts.os.release.major}.yaml' + + - name: 'Distribution Name' + path: '%{facts.os.name}.yaml' + + - name: 'Operating System Family' + path: '%{facts.os.family}-family.yaml' + + - name: 'common' + path: 'common.yaml' diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb new file mode 100644 index 0000000..557f608 --- /dev/null +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -0,0 +1,44 @@ +Puppet::Type.type(:metricbeat_module).provide(:metricbeat) do + + commands :metricbeat => 'metricbeat' + + # Metricbeat module file. + # + # @return String + def module_file + File.join( + @resource[:module_dir], + "#{resource[:name]}.yml" + ) + end + + def exists? + if !File.exists?(module_file) + debug "Module file #{module_file} does not exist" + return false + else + debug "Module exists" + return true + end + end + + def create + retry_count = 3 + retry_times = 0 + begin + metricbeat(['modules','enable',resource[:name]]) + rescue Puppet::ExecutionFailure => e + retry_times += 1 + debug("Failed to enable module. Retrying... #{retry_times} of #{retry_count}") + sleep 2 + retry if retry_times < retry_count + raise "Failed to enable module. Received error: #{e.inspect}" + end + end + + # Remove this plugin from the host. + def destroy + metricbeat(['modules','disable',@resource[:name]]) + end + +end diff --git a/lib/puppet/type/metricbeat_module.rb b/lib/puppet/type/metricbeat_module.rb new file mode 100644 index 0000000..1ad70df --- /dev/null +++ b/lib/puppet/type/metricbeat_module.rb @@ -0,0 +1,24 @@ +Puppet::Type.newtype(:metricbeat_module) do + @doc = 'Manage Metricbeat modules' + + ensurable + + newparam(:name, :namevar => true) do + desc 'An arbitrary name used as the identity of the resource.' + end + + newparam(:settings) do + desc 'Any custom settings for this module.' + validate do |settings| + unless settings.to_yaml + raise ArgumentError , "%s can not be munged to YAML" % settings + end + end + end + + newparam(:module_dir) do + desc 'Path to the Metricbeat modules directory' + defaultto '/etc/metricbeat/modules.d' + end + +end diff --git a/manifests/config.pp b/manifests/config.pp new file mode 100644 index 0000000..3b045c1 --- /dev/null +++ b/manifests/config.pp @@ -0,0 +1,40 @@ +# @api private +# This class handles the configuration files for beats. Avoid modifying private classes. +class beats::config { + $beats::beats_manage.each |String $beat| { + if lookup("beats::${beat}::settings", Data, hash, {}) != {} { + file { "${beats::config_root}/${beat}/${beat}.yml": + ensure => file, + owner => 0, + group => 0, + mode => '0600', + content => inline_epp('<%= lookup("beats::${beat}::settings", {}).to_yaml %>'), + } + } + elsif lookup("beats::${beat}::settings_file", String, unique, '') != '' { + file { "${beats::config_root}/${beat}/${beat}.yml": + ensure => file, + owner => 0, + group => 0, + mode => '0600', + source => lookup("beats::${beat}::settings_file", String, unique), + } + } + if $beat == 'metricbeat' and lookup('metricbeat::modules_enable', Array[String], unique, []) != [] { + metricbeat::modules_enable.each |String $module| { + metricbeat_module { $module: + ensure => 'present' + } + } + } + if $beat == 'metricbeat' and lookup('metricbeat::modules_disable', Array[String], unique, []) != [] { + metricbeat_modules_disable.each |String $module| { + metricbeat_module { $module: + name => $module, + ensure => 'absent' + } + } + } + + } +} diff --git a/manifests/init.pp b/manifests/init.pp new file mode 100644 index 0000000..a8742cb --- /dev/null +++ b/manifests/init.pp @@ -0,0 +1,45 @@ +# beats +# +# @param beats_manage +# The names of Beats to manage with this module. +# +# @param package_ensure +# Whether to install Beats packages, and what version to install. Values: 'present', 'latest', or a specific version number. +# Default value: 'present'. +# +# @param package_manage +# Whether to manage the Beats packages. Default value: true. +# +# @param service_enable +# Whether to enable the Beats services at boot. Default value: true. +# +# @param service_ensure +# Whether the Beats services should be running. Default value: 'running'. +# +# @param service_manage +# Whether to manage the Beats services. Default value: true. +# +# @param service_provider +# Which service provider to use for Beats. Default value: 'undef'. +# +# @param config_root +# The root directory under which individual beats config directories are found. Default value: '/etc'. +# +class beats ( + Array[String] $beats_manage, + String $package_ensure, + Boolean $package_manage, + Boolean $service_enable, + Enum['running', 'stopped'] $service_ensure, + Boolean $service_manage, + Optional[String] $service_provider, + String $config_root + ) { + contain beats::install + contain beats::config + contain beats::service + + Class['::beats::install'] + -> Class['::beats::config'] + ~> Class['::beats::service'] +} diff --git a/manifests/install.pp b/manifests/install.pp new file mode 100644 index 0000000..43610e8 --- /dev/null +++ b/manifests/install.pp @@ -0,0 +1,7 @@ +# @api private +# This class handles beats packages. Avoid modifying private classes. +class beats::install { + if $beats::package_manage { + beats::package_install { $beats::beats_manage: } + } +} diff --git a/manifests/package_install.pp b/manifests/package_install.pp new file mode 100644 index 0000000..2aa1b6d --- /dev/null +++ b/manifests/package_install.pp @@ -0,0 +1,9 @@ +# @api private +# This defined type installs beats packages. Avoid modifying private defined types. +define beats::package_install ( + String[1] $package = $name + ) { + package { $package: + ensure => $beats::package_ensure + } +} diff --git a/manifests/service.pp b/manifests/service.pp new file mode 100644 index 0000000..1248a11 --- /dev/null +++ b/manifests/service.pp @@ -0,0 +1,7 @@ +# @api private +# This class handles the beats service. Avoid modifying private classes. +class beats::service { + if $beats::service_manage == true { + beats::service_install { $beats::beats_manage: } + } +} diff --git a/manifests/service_install.pp b/manifests/service_install.pp new file mode 100644 index 0000000..47c6a10 --- /dev/null +++ b/manifests/service_install.pp @@ -0,0 +1,13 @@ +# @api private +# This defined type installs beats services. Avoid modifying private defined types. +define beats::service_install ( + String[1] $service = $name +) { + service { $service: + ensure => $beats::service_ensure, + enable => $beats::service_enable, + provider => $beats::service_provider, + hasstatus => true, + hasrestart => true, + } +} From 9e01a1b3b9383c22d215fdc147eb0369b7493acd Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Tue, 13 Feb 2018 22:35:14 +1100 Subject: [PATCH 02/33] Metricbeat module handling worked out I think. Can enable/disable modules as needed. Custom settings for modules should also work. --- README.md | 20 ++--- .../provider/metricbeat_module/metricbeat.rb | 90 ++++++++++++------- manifests/config.pp | 26 +++--- manifests/init.pp | 3 +- 4 files changed, 77 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index a5eb544..0effe11 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,9 @@ class { 'beats': #### Beats custom configuration -This module recommends using [Hiera](https://puppet.com/docs/puppet/5.3/hiera_intro.html) for configuration data. You can either specify your complete Beats configuration in Hiera as YAML under `beats::::settings`: +This module recommends using [Hiera](https://puppet.com/docs/puppet/5.3/hiera_intro.html) for configuration data. You can either specify your complete Beats configuration in Hiera or as a Puppet URL under `beats::::settings`. + +Configure in Hiera: ```yaml beats::auditbeat::settings: @@ -91,7 +93,7 @@ beats::auditbeat::settings: Or pass a Puppet URL that will be used as the source of configuration: ```yaml -beats::auditbeat::settings_file: 'puppet:///somefileshare/auditbeat.yml' +beats::auditbeat::settings: 'puppet:///somefileshare/auditbeat.yml' ``` #### Beats configuration @@ -102,23 +104,17 @@ beats::auditbeat::settings_file: 'puppet:///somefileshare/auditbeat.yml' This class can handle enabling/disabling Metricbeat modules for you. -To enable a list of modules, ensure you manage Metricbeat with this class and then add the modules to `metricbeat_modules_enable`: +To enable/disable a list of modules, ensure you manage Metricbeat with this class and then manage the modules in `metricbeat_modules_manage`: ```puppet class { 'beats': beats_manage => ['metricbeat'], - metricbeat_modules_enable => ['docker','kafka'] + metricbeat_modules_manage => { 'present' => ['docker','kafka'], + 'absent' => ['redis'] } } ``` -To disable some modules: - -```puppet -class { 'beats': - beats_manage => ['metricbeat'], - metricbeat_modules_disable => ['docker','kafka'] -} -``` +If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::::settings`. ## Reference diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index 557f608..f680c54 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -1,44 +1,68 @@ +require 'yaml' + Puppet::Type.type(:metricbeat_module).provide(:metricbeat) do - commands :metricbeat => 'metricbeat' + commands :metricbeat => 'metricbeat' - # Metricbeat module file. - # - # @return String - def module_file - File.join( - @resource[:module_dir], - "#{resource[:name]}.yml" - ) - end + # Metricbeat module file. + # + # @return String + def module_file + File.join( + @resource[:module_dir], + "#{resource[:name]}.yml" + ) + end - def exists? - if !File.exists?(module_file) - debug "Module file #{module_file} does not exist" - return false - else - debug "Module exists" - return true - end + # Metricbeat module settings. + # + # @return String + def module_settings + if resource[:settings].empty? + return '' + else + return resource[:settings].to_yaml end + end - def create - retry_count = 3 - retry_times = 0 - begin - metricbeat(['modules','enable',resource[:name]]) - rescue Puppet::ExecutionFailure => e - retry_times += 1 - debug("Failed to enable module. Retrying... #{retry_times} of #{retry_count}") - sleep 2 - retry if retry_times < retry_count - raise "Failed to enable module. Received error: #{e.inspect}" - end + # Write module_settings contents to disk. + def writemodulefile + if module_settings + File.open(module_file, 'w') do |file| + file.write module_settings end + end + end - # Remove this plugin from the host. - def destroy - metricbeat(['modules','disable',@resource[:name]]) + def exists? + if !File.exists?(module_file) + debug "Module file #{module_file} does not exist" + writemodulefile + return false + else + debug "Module exists" + return true end + end + + def create + retry_count = 3 + retry_times = 0 + begin + metricbeat(['modules','enable',resource[:name]]) + writemodulefile + rescue Puppet::ExecutionFailure => e + retry_times += 1 + debug("Failed to enable module. Retrying... #{retry_times} of #{retry_count}") + sleep 2 + retry if retry_times < retry_count + raise "Failed to enable module. Received error: #{e.inspect}" + end + end + + # Remove this plugin from the host. + def destroy + metricbeat(['modules','disable',@resource[:name]]) + end end diff --git a/manifests/config.pp b/manifests/config.pp index 3b045c1..e8eea41 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -2,7 +2,7 @@ # This class handles the configuration files for beats. Avoid modifying private classes. class beats::config { $beats::beats_manage.each |String $beat| { - if lookup("beats::${beat}::settings", Data, hash, {}) != {} { + if lookup("beats::${beat}::settings", Data, 'hash', {}) != {} { file { "${beats::config_root}/${beat}/${beat}.yml": ensure => file, owner => 0, @@ -11,30 +11,24 @@ content => inline_epp('<%= lookup("beats::${beat}::settings", {}).to_yaml %>'), } } - elsif lookup("beats::${beat}::settings_file", String, unique, '') != '' { + elsif lookup("beats::${beat}::settings", String, unique, '') != '' { file { "${beats::config_root}/${beat}/${beat}.yml": ensure => file, owner => 0, group => 0, mode => '0600', - source => lookup("beats::${beat}::settings_file", String, unique), + source => lookup("beats::${beat}::settings", String, 'unique'), } } - if $beat == 'metricbeat' and lookup('metricbeat::modules_enable', Array[String], unique, []) != [] { - metricbeat::modules_enable.each |String $module| { - metricbeat_module { $module: - ensure => 'present' + if $beat == 'metricbeat' and lookup('beats::metricbeat_modules_manage', Hash, 'deep', {}) != {} { + lookup(beats::metricbeat_modules_manage).each | String $ensure, Array[String] $modules | { + $modules.each | String $m | { + metricbeat_module { $m: + ensure => $ensure, + settings => lookup("beats::metricbeat::${m}::settings", Hash, 'deep', {}) + } } } } - if $beat == 'metricbeat' and lookup('metricbeat::modules_disable', Array[String], unique, []) != [] { - metricbeat_modules_disable.each |String $module| { - metricbeat_module { $module: - name => $module, - ensure => 'absent' - } - } - } - } } diff --git a/manifests/init.pp b/manifests/init.pp index a8742cb..eeb0f2f 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -33,7 +33,8 @@ Enum['running', 'stopped'] $service_ensure, Boolean $service_manage, Optional[String] $service_provider, - String $config_root + String $config_root, + Hash $metricbeat_modules_manage ) { contain beats::install contain beats::config From eef0d906fed8d2e10a8ffe3ed86dde10b910ed59 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Tue, 13 Feb 2018 22:38:00 +1100 Subject: [PATCH 03/33] Fix README.md --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0effe11..4dc36ee 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,6 @@ Or pass a Puppet URL that will be used as the source of configuration: beats::auditbeat::settings: 'puppet:///somefileshare/auditbeat.yml' ``` -#### Beats configuration - ### Beats specific usage #### Metricbeat modules @@ -114,7 +112,14 @@ class { 'beats': } ``` -If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::::settings`. +If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::::settings`. For example: + +```yaml +beats::metricbeat::docker::settings: + metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] + hosts: ["unix:///var/run/docker.sock"] + period: 10s +``` ## Reference From a59b6acc8991c892c635704489d068233cdeee39 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Thu, 15 Feb 2018 22:37:57 +1100 Subject: [PATCH 04/33] Clean up defined types. Minor fix in metricbeat module provider. Add some rspec tests for class and defined types. --- data/common.yaml | 2 ++ .../provider/metricbeat_module/metricbeat.rb | 1 + manifests/init.pp | 5 ++++- manifests/install.pp | 4 +++- manifests/package_install.pp | 9 +++++---- manifests/service.pp | 6 +++++- manifests/service_install.pp | 11 +++++++---- spec/classes/beats_spec.rb | 8 ++++++++ spec/defines/define_package_install_spec.rb | 16 ++++++++++++++++ spec/defines/define_service_install_spec.rb | 15 +++++++++++++++ 10 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 spec/classes/beats_spec.rb create mode 100644 spec/defines/define_package_install_spec.rb create mode 100644 spec/defines/define_service_install_spec.rb diff --git a/data/common.yaml b/data/common.yaml index 4c2fc90..adde293 100644 --- a/data/common.yaml +++ b/data/common.yaml @@ -1,3 +1,4 @@ +beats::beats_manage: ['metricbeat'] beats::package_ensure: present beats::package_manage: true beats::service_enable: true @@ -5,3 +6,4 @@ beats::service_ensure: running beats::service_manage: true beats::service_provider: ~ beats::config_root: /etc +beats::metricbeat_modules_manage: {} diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index f680c54..ebbabd6 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -29,6 +29,7 @@ def module_settings def writemodulefile if module_settings File.open(module_file, 'w') do |file| + file.write "- module: #{resource[:name]}\n" file.write module_settings end end diff --git a/manifests/init.pp b/manifests/init.pp index eeb0f2f..1fc839d 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -25,6 +25,9 @@ # @param config_root # The root directory under which individual beats config directories are found. Default value: '/etc'. # +# @param metricbeat_modules_manage +# A list of Metricbeat modules to manage Default value: 'undef'. +# class beats ( Array[String] $beats_manage, String $package_ensure, @@ -34,7 +37,7 @@ Boolean $service_manage, Optional[String] $service_provider, String $config_root, - Hash $metricbeat_modules_manage + Optional[Hash] $metricbeat_modules_manage ) { contain beats::install contain beats::config diff --git a/manifests/install.pp b/manifests/install.pp index 43610e8..8884162 100644 --- a/manifests/install.pp +++ b/manifests/install.pp @@ -2,6 +2,8 @@ # This class handles beats packages. Avoid modifying private classes. class beats::install { if $beats::package_manage { - beats::package_install { $beats::beats_manage: } + beats::package_install { $beats::beats_manage: + ensure => $beats::package_ensure + } } } diff --git a/manifests/package_install.pp b/manifests/package_install.pp index 2aa1b6d..793559c 100644 --- a/manifests/package_install.pp +++ b/manifests/package_install.pp @@ -1,9 +1,10 @@ # @api private # This defined type installs beats packages. Avoid modifying private defined types. define beats::package_install ( - String[1] $package = $name + String $ensure, + String $package = $name ) { - package { $package: - ensure => $beats::package_ensure + package { $package: + ensure => $ensure + } } -} diff --git a/manifests/service.pp b/manifests/service.pp index 1248a11..ba1a8e9 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -2,6 +2,10 @@ # This class handles the beats service. Avoid modifying private classes. class beats::service { if $beats::service_manage == true { - beats::service_install { $beats::beats_manage: } + beats::service_install { $beats::beats_manage: + ensure => $beats::service_ensure, + enable => $beats::service_enable, + provider => $beats::service_provider + } } } diff --git a/manifests/service_install.pp b/manifests/service_install.pp index 47c6a10..bb4f153 100644 --- a/manifests/service_install.pp +++ b/manifests/service_install.pp @@ -1,12 +1,15 @@ # @api private # This defined type installs beats services. Avoid modifying private defined types. define beats::service_install ( - String[1] $service = $name + String $ensure, + Boolean $enable, + Optional[String] $provider, + String $service = $name ) { service { $service: - ensure => $beats::service_ensure, - enable => $beats::service_enable, - provider => $beats::service_provider, + ensure => $ensure, + enable => $enable, + provider => $provider, hasstatus => true, hasrestart => true, } diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb new file mode 100644 index 0000000..24bfba1 --- /dev/null +++ b/spec/classes/beats_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +describe 'beats' do + let(:params) { {'beats_manage' => ['metricbeat'], 'metricbeat_modules_manage' => { 'ensure' => ['docker']}} } + it { is_expected.to compile } + it { is_expected.to contain_package('metricbeat') } + it { is_expected.to contain_service('metricbeat') } +end diff --git a/spec/defines/define_package_install_spec.rb b/spec/defines/define_package_install_spec.rb new file mode 100644 index 0000000..b60ba62 --- /dev/null +++ b/spec/defines/define_package_install_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe 'beats::package_install' do + let(:title) { 'metricbeat' } + let(:params) { {'package' => 'metricbeat', 'ensure' => 'present' } } + + on_supported_os.each do |os, facts| + context "on #{os}" do + let(:facts) do + facts + end + it { is_expected.to compile } + it { is_expected.to contain_package('metricbeat') } + end + end +end diff --git a/spec/defines/define_service_install_spec.rb b/spec/defines/define_service_install_spec.rb new file mode 100644 index 0000000..a1665a1 --- /dev/null +++ b/spec/defines/define_service_install_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe 'beats::service_install' do + let(:title) { 'metricbeat' } + let(:params) { {'ensure' => 'running', 'enable' => true, 'provider' => :undef } } + on_supported_os.each do |os, facts| + context "on #{os}" do + let(:facts) do + facts + end + it { is_expected.to compile } + it { is_expected.to contain_service('metricbeat') } + end + end +end From 31bdd2a0f3618a1acdd74783741a9a6d8c66696e Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Thu, 15 Feb 2018 22:45:47 +1100 Subject: [PATCH 05/33] Better rspec tests. --- spec/classes/beats_spec.rb | 7 +++++-- spec/spec_helper.rb | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index 24bfba1..c2111cf 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -3,6 +3,9 @@ describe 'beats' do let(:params) { {'beats_manage' => ['metricbeat'], 'metricbeat_modules_manage' => { 'ensure' => ['docker']}} } it { is_expected.to compile } - it { is_expected.to contain_package('metricbeat') } - it { is_expected.to contain_service('metricbeat') } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_beats__package_install('metricbeat') } + it { is_expected.to contain_beats__service_install('metricbeat') } end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 15266c2..e39f6e7 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -20,4 +20,7 @@ RSpec.configure do |c| c.default_facts = default_facts + c.after(:suite) do + RSpec::Puppet::Coverage.report! + end end From 35a2011f95f6508a6cda82c4aacd7634e7d6a70c Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 10:59:33 +1100 Subject: [PATCH 06/33] Add tests for metricbeat_module type. Fix generation of module config files. --- data/common.yaml | 2 +- .../provider/metricbeat_module/metricbeat.rb | 3 +- lib/puppet/type/metricbeat_module.rb | 2 +- spec/classes/beats_spec.rb | 73 +++++++++++++++++-- spec/defines/metricbeat_module_spec.rb | 8 ++ 5 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 spec/defines/metricbeat_module_spec.rb diff --git a/data/common.yaml b/data/common.yaml index adde293..0b57b43 100644 --- a/data/common.yaml +++ b/data/common.yaml @@ -1,4 +1,4 @@ -beats::beats_manage: ['metricbeat'] +beats::beats_manage: ['auditbeat','heartbeat','metricbeat','packetbeat'] beats::package_ensure: present beats::package_manage: true beats::service_enable: true diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index ebbabd6..56fae68 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -21,7 +21,8 @@ def module_settings if resource[:settings].empty? return '' else - return resource[:settings].to_yaml + # magic to remove the '---' first line that to_yaml adds + return resource[:settings].to_yaml.lines[1..-1].join end end diff --git a/lib/puppet/type/metricbeat_module.rb b/lib/puppet/type/metricbeat_module.rb index 1ad70df..2f2212b 100644 --- a/lib/puppet/type/metricbeat_module.rb +++ b/lib/puppet/type/metricbeat_module.rb @@ -10,7 +10,7 @@ newparam(:settings) do desc 'Any custom settings for this module.' validate do |settings| - unless settings.to_yaml + if settings.is_Hash? and settings.to_yaml raise ArgumentError , "%s can not be munged to YAML" % settings end end diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index c2111cf..6dd1b4e 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -1,11 +1,70 @@ require 'spec_helper' describe 'beats' do - let(:params) { {'beats_manage' => ['metricbeat'], 'metricbeat_modules_manage' => { 'ensure' => ['docker']}} } - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_beats__package_install('metricbeat') } - it { is_expected.to contain_beats__service_install('metricbeat') } + + # defaults should result in all official beats installed + context 'defaults' do + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_beats__package_install('auditbeat') } + it { is_expected.to contain_beats__service_install('auditbeat') } + it { is_expected.to contain_beats__package_install('heartbeat') } + it { is_expected.to contain_beats__service_install('heartbeat') } + it { is_expected.to contain_beats__package_install('metricbeat') } + it { is_expected.to contain_beats__service_install('metricbeat') } + it { is_expected.to contain_beats__package_install('packetbeat') } + it { is_expected.to contain_beats__service_install('packetbeat') } + end + + # no package management + context 'defaults (no package mgmt)' do + let(:params) { {'package_manage' => false} } + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_beats__service_install('auditbeat') } + it { is_expected.to contain_beats__service_install('heartbeat') } + it { is_expected.to contain_beats__service_install('metricbeat') } + it { is_expected.to contain_beats__service_install('packetbeat') } + end + + # no service management + context 'defaults (no service mgmt)' do + let(:params) { {'service_manage' => false} } + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_beats__package_install('auditbeat') } + it { is_expected.to contain_beats__package_install('heartbeat') } + it { is_expected.to contain_beats__package_install('metricbeat') } + it { is_expected.to contain_beats__package_install('packetbeat') } + end + + # installing a specific beat (metricbeat) + context 'just metricbeat' do + let(:params) { {'beats_manage' => ['metricbeat']} } + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_beats__package_install('metricbeat') } + it { is_expected.to contain_beats__service_install('metricbeat') } + end + + # installing a specific beat with certain modules enabled/disabled + # context 'metricbeat with modules' do + # let(:params) { {'beats_manage' => ['metricbeat'], 'metricbeat_modules_manage' => { 'enable' => ['docker']}} } + # it { is_expected.to compile } + # it { is_expected.to contain_class('beats::install') } + # it { is_expected.to contain_class('beats::config') } + # it { is_expected.to contain_class('beats::service') } + # it { is_expected.to contain_beats__package_install('metricbeat') } + # it { is_expected.to contain_beats__service_install('metricbeat') } + # it { is_expected.to contain_metricbeat_module('docker') } + # end + end diff --git a/spec/defines/metricbeat_module_spec.rb b/spec/defines/metricbeat_module_spec.rb new file mode 100644 index 0000000..d92e236 --- /dev/null +++ b/spec/defines/metricbeat_module_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +describe 'metricbeat_module' do + let(:title) { 'docker' } + let(:name) { 'docker' } + it { is_expected.to compile } + it { is_expected.to contain_metricbeat_module('docker') } +end From ff68f95bc01780238f66d189e3eef78588ed10d9 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 11:02:38 +1100 Subject: [PATCH 07/33] Fix syntax error. --- lib/puppet/type/metricbeat_module.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet/type/metricbeat_module.rb b/lib/puppet/type/metricbeat_module.rb index 2f2212b..1da2a85 100644 --- a/lib/puppet/type/metricbeat_module.rb +++ b/lib/puppet/type/metricbeat_module.rb @@ -10,7 +10,7 @@ newparam(:settings) do desc 'Any custom settings for this module.' validate do |settings| - if settings.is_Hash? and settings.to_yaml + if settings.is_a?(Hash) and settings.to_yaml raise ArgumentError , "%s can not be munged to YAML" % settings end end From 93eacf20b548c5b5c755795bd60d2003abe8660d Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 11:05:03 +1100 Subject: [PATCH 08/33] Whoopsy wrong conditional. --- lib/puppet/type/metricbeat_module.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet/type/metricbeat_module.rb b/lib/puppet/type/metricbeat_module.rb index 1da2a85..a2b729c 100644 --- a/lib/puppet/type/metricbeat_module.rb +++ b/lib/puppet/type/metricbeat_module.rb @@ -10,7 +10,7 @@ newparam(:settings) do desc 'Any custom settings for this module.' validate do |settings| - if settings.is_a?(Hash) and settings.to_yaml + unless settings.is_a?(Hash) and settings.to_yaml raise ArgumentError , "%s can not be munged to YAML" % settings end end From 7965cf36e9b2e812130210cdfd03a95bb09b0672 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 11:13:33 +1100 Subject: [PATCH 09/33] More logging in metricbeat_module type --- lib/puppet/provider/metricbeat_module/metricbeat.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index 56fae68..2643cd4 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -21,16 +21,15 @@ def module_settings if resource[:settings].empty? return '' else - # magic to remove the '---' first line that to_yaml adds - return resource[:settings].to_yaml.lines[1..-1].join + return resource[:settings].to_yaml end end # Write module_settings contents to disk. def writemodulefile if module_settings + info("Writing settings for Metricbeat module #resource[:name]") File.open(module_file, 'w') do |file| - file.write "- module: #{resource[:name]}\n" file.write module_settings end end @@ -51,6 +50,7 @@ def create retry_count = 3 retry_times = 0 begin + info("Enabling Metricbeat module #resource[:name]") metricbeat(['modules','enable',resource[:name]]) writemodulefile rescue Puppet::ExecutionFailure => e @@ -64,6 +64,7 @@ def create # Remove this plugin from the host. def destroy + info("Disabling Metricbeat module #resource[:name]") metricbeat(['modules','disable',@resource[:name]]) end From 776c2cfa97674dc96ad937da929e4e2691252962 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 11:17:08 +1100 Subject: [PATCH 10/33] Fix Metricbeat module settings location --- manifests/config.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifests/config.pp b/manifests/config.pp index e8eea41..e8db85e 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -25,7 +25,7 @@ $modules.each | String $m | { metricbeat_module { $m: ensure => $ensure, - settings => lookup("beats::metricbeat::${m}::settings", Hash, 'deep', {}) + settings => lookup("beats::metricbeat::module::settings::${m}", Hash, 'deep', {}) } } } From b26d4ee1cbfaa9c4ec98e1b7cc4787ce5699fcca Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 12:07:16 +1100 Subject: [PATCH 11/33] Write out module file differently. --- .../provider/metricbeat_module/metricbeat.rb | 17 ++++++++++------- lib/puppet/type/metricbeat_module.rb | 6 ++++-- manifests/config.pp | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index 2643cd4..63c4b7e 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -19,25 +19,28 @@ def module_file # @return String def module_settings if resource[:settings].empty? - return '' + return false else - return resource[:settings].to_yaml + return resource[:settings] end end # Write module_settings contents to disk. def writemodulefile if module_settings - info("Writing settings for Metricbeat module #resource[:name]") + info("writing settings for Metricbeat module") File.open(module_file, 'w') do |file| - file.write module_settings + file.write "module: #{resource[:name]}" + module_settings.each do |key, value| + file.write "\t#{key}: #{value}" + end end end end def exists? if !File.exists?(module_file) - debug "Module file #{module_file} does not exist" + debug("Module file #{module_file} does not exist") writemodulefile return false else @@ -50,7 +53,7 @@ def create retry_count = 3 retry_times = 0 begin - info("Enabling Metricbeat module #resource[:name]") + info("Enabling Metricbeat module") metricbeat(['modules','enable',resource[:name]]) writemodulefile rescue Puppet::ExecutionFailure => e @@ -64,7 +67,7 @@ def create # Remove this plugin from the host. def destroy - info("Disabling Metricbeat module #resource[:name]") + info("Disabling Metricbeat module") metricbeat(['modules','disable',@resource[:name]]) end diff --git a/lib/puppet/type/metricbeat_module.rb b/lib/puppet/type/metricbeat_module.rb index a2b729c..35af20d 100644 --- a/lib/puppet/type/metricbeat_module.rb +++ b/lib/puppet/type/metricbeat_module.rb @@ -10,8 +10,10 @@ newparam(:settings) do desc 'Any custom settings for this module.' validate do |settings| - unless settings.is_a?(Hash) and settings.to_yaml - raise ArgumentError , "%s can not be munged to YAML" % settings + unless settings.empty? + unless settings.is_a?(Hash) and settings.to_yaml + raise ArgumentError , "%s can not be munged to YAML" % settings + end end end end diff --git a/manifests/config.pp b/manifests/config.pp index e8db85e..1821c90 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -25,7 +25,7 @@ $modules.each | String $m | { metricbeat_module { $m: ensure => $ensure, - settings => lookup("beats::metricbeat::module::settings::${m}", Hash, 'deep', {}) + settings => lookup("beats::metricbeat::module::settings.${m}", Hash, 'deep', {}) } } } From c175550878d459b2eef891bacc2fa13216a37382 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 12:12:21 +1100 Subject: [PATCH 12/33] Fix README.md. New line character can be important when writing files. --- README.md | 11 ++++++----- lib/puppet/provider/metricbeat_module/metricbeat.rb | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4dc36ee..5708e8f 100644 --- a/README.md +++ b/README.md @@ -112,13 +112,14 @@ class { 'beats': } ``` -If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::::settings`. For example: +If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::module::settings`. For example: ```yaml -beats::metricbeat::docker::settings: - metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] - hosts: ["unix:///var/run/docker.sock"] - period: 10s +beats::metricbeat::module::settings: + docker: + metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] + hosts: ["unix:///var/run/docker.sock"] + period: 10s ``` ## Reference diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index 63c4b7e..b5588e8 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -32,7 +32,7 @@ def writemodulefile File.open(module_file, 'w') do |file| file.write "module: #{resource[:name]}" module_settings.each do |key, value| - file.write "\t#{key}: #{value}" + file.write "\t#{key}: #{value}\n" end end end From 8fe64ab51230071bfd4f6a7ba68c4407bbae3350 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 12:15:17 +1100 Subject: [PATCH 13/33] Just can't get formatting right can I? --- lib/puppet/provider/metricbeat_module/metricbeat.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index b5588e8..ad25c70 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -30,9 +30,9 @@ def writemodulefile if module_settings info("writing settings for Metricbeat module") File.open(module_file, 'w') do |file| - file.write "module: #{resource[:name]}" + file.write "module: #{resource[:name]}\n" module_settings.each do |key, value| - file.write "\t#{key}: #{value}\n" + file.write " #{key}: #{value}\n" end end end From b709fe76594632e0d3276f34255c55410af60008 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 12:16:45 +1100 Subject: [PATCH 14/33] Missed a character. --- lib/puppet/provider/metricbeat_module/metricbeat.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index ad25c70..50ab960 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -30,7 +30,7 @@ def writemodulefile if module_settings info("writing settings for Metricbeat module") File.open(module_file, 'w') do |file| - file.write "module: #{resource[:name]}\n" + file.write "- module: #{resource[:name]}\n" module_settings.each do |key, value| file.write " #{key}: #{value}\n" end From ccd62e8a2c053e02e7e8fc881f6cd0acdb945510 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 17 Feb 2018 12:24:17 +1100 Subject: [PATCH 15/33] Fix where a Metricbeat module file is written. --- lib/puppet/provider/metricbeat_module/metricbeat.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index 50ab960..2ffe9e4 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -28,7 +28,7 @@ def module_settings # Write module_settings contents to disk. def writemodulefile if module_settings - info("writing settings for Metricbeat module") + info("Writing settings for Metricbeat module") File.open(module_file, 'w') do |file| file.write "- module: #{resource[:name]}\n" module_settings.each do |key, value| @@ -55,7 +55,6 @@ def create begin info("Enabling Metricbeat module") metricbeat(['modules','enable',resource[:name]]) - writemodulefile rescue Puppet::ExecutionFailure => e retry_times += 1 debug("Failed to enable module. Retrying... #{retry_times} of #{retry_count}") From 1a6e2c7c88bf43756fef5654d33ea738e05377cd Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 18 Feb 2018 00:09:35 +1100 Subject: [PATCH 16/33] Fix merging of Beats settings. --- manifests/config.pp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifests/config.pp b/manifests/config.pp index 1821c90..530cc9a 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -2,13 +2,13 @@ # This class handles the configuration files for beats. Avoid modifying private classes. class beats::config { $beats::beats_manage.each |String $beat| { - if lookup("beats::${beat}::settings", Data, 'hash', {}) != {} { + if lookup("beats::${beat}::settings", Hash, 'deep', {}) != {} { file { "${beats::config_root}/${beat}/${beat}.yml": ensure => file, owner => 0, group => 0, mode => '0600', - content => inline_epp('<%= lookup("beats::${beat}::settings", {}).to_yaml %>'), + content => inline_epp('<%= lookup("beats::${beat}::settings", Hash, \'deep\').to_yaml %>'), } } elsif lookup("beats::${beat}::settings", String, unique, '') != '' { From f5f5dacd4b5eab5feb17db8c64b866ffa0dabc8e Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 18 Feb 2018 18:23:45 +1100 Subject: [PATCH 17/33] Subscribe and notify as appropriate. --- manifests/config.pp | 15 ++++++++++++--- manifests/service_install.pp | 5 +++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/manifests/config.pp b/manifests/config.pp index 530cc9a..05c4a1b 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -23,9 +23,18 @@ if $beat == 'metricbeat' and lookup('beats::metricbeat_modules_manage', Hash, 'deep', {}) != {} { lookup(beats::metricbeat_modules_manage).each | String $ensure, Array[String] $modules | { $modules.each | String $m | { - metricbeat_module { $m: - ensure => $ensure, - settings => lookup("beats::metricbeat::module::settings.${m}", Hash, 'deep', {}) + if $beats::service_manage == true { + metricbeat_module { $m: + ensure => $ensure, + settings => lookup("beats::metricbeat::module::settings.${m}", Hash, 'deep', {}), + notify => Service['metricbeat'] + } + } + else { + metricbeat_module { $m: + ensure => $ensure, + settings => lookup("beats::metricbeat::module::settings.${m}", Hash, 'deep', {}), + } } } } diff --git a/manifests/service_install.pp b/manifests/service_install.pp index bb4f153..efea123 100644 --- a/manifests/service_install.pp +++ b/manifests/service_install.pp @@ -4,13 +4,14 @@ String $ensure, Boolean $enable, Optional[String] $provider, - String $service = $name + String $beat = $name ) { - service { $service: + service { $beat: ensure => $ensure, enable => $enable, provider => $provider, hasstatus => true, hasrestart => true, + subscribe => File["${beats::config_root}/${beat}/${beat}.yml"] } } From 10bfc7efb47e56b20de54bc3ad222edc2aae9ace Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 18 Feb 2018 22:52:19 +1100 Subject: [PATCH 18/33] Simplify module a little. --- manifests/config.pp | 4 +-- manifests/install.pp | 2 +- manifests/package_install.pp | 10 ------ manifests/service.pp | 24 +++++++++++--- manifests/service_install.pp | 17 ---------- spec/classes/beats_spec.rb | 36 ++++++++++----------- spec/defines/define_package_install_spec.rb | 16 --------- spec/defines/define_service_install_spec.rb | 15 --------- 8 files changed, 41 insertions(+), 83 deletions(-) delete mode 100644 manifests/package_install.pp delete mode 100644 manifests/service_install.pp delete mode 100644 spec/defines/define_package_install_spec.rb delete mode 100644 spec/defines/define_service_install_spec.rb diff --git a/manifests/config.pp b/manifests/config.pp index 05c4a1b..5b1e494 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -32,8 +32,8 @@ } else { metricbeat_module { $m: - ensure => $ensure, - settings => lookup("beats::metricbeat::module::settings.${m}", Hash, 'deep', {}), + ensure => $ensure, + settings => lookup("beats::metricbeat::module::settings.${m}", Hash, 'deep', {}), } } } diff --git a/manifests/install.pp b/manifests/install.pp index 8884162..14d20e2 100644 --- a/manifests/install.pp +++ b/manifests/install.pp @@ -2,7 +2,7 @@ # This class handles beats packages. Avoid modifying private classes. class beats::install { if $beats::package_manage { - beats::package_install { $beats::beats_manage: + package { $beats::beats_manage: ensure => $beats::package_ensure } } diff --git a/manifests/package_install.pp b/manifests/package_install.pp deleted file mode 100644 index 793559c..0000000 --- a/manifests/package_install.pp +++ /dev/null @@ -1,10 +0,0 @@ -# @api private -# This defined type installs beats packages. Avoid modifying private defined types. -define beats::package_install ( - String $ensure, - String $package = $name - ) { - package { $package: - ensure => $ensure - } - } diff --git a/manifests/service.pp b/manifests/service.pp index ba1a8e9..b3646a6 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -2,10 +2,26 @@ # This class handles the beats service. Avoid modifying private classes. class beats::service { if $beats::service_manage == true { - beats::service_install { $beats::beats_manage: - ensure => $beats::service_ensure, - enable => $beats::service_enable, - provider => $beats::service_provider + $beats::beats_manage.each |String $beat| { + if lookup("beats::${beat}::settings", Data, 'deep', false) { + service { $beat: + ensure => $beats::service_ensure, + enable => $beats::service_enable, + provider => $beats::service_provider, + hasstatus => true, + hasrestart => true, + subscribe => File["${beats::config_root}/${beat}/${beat}.yml"] + } + } + else { + service { $beat: + ensure => $beats::service_ensure, + enable => $beats::service_enable, + provider => $beats::service_provider, + hasstatus => true, + hasrestart => true, + } + } } } } diff --git a/manifests/service_install.pp b/manifests/service_install.pp deleted file mode 100644 index efea123..0000000 --- a/manifests/service_install.pp +++ /dev/null @@ -1,17 +0,0 @@ -# @api private -# This defined type installs beats services. Avoid modifying private defined types. -define beats::service_install ( - String $ensure, - Boolean $enable, - Optional[String] $provider, - String $beat = $name -) { - service { $beat: - ensure => $ensure, - enable => $enable, - provider => $provider, - hasstatus => true, - hasrestart => true, - subscribe => File["${beats::config_root}/${beat}/${beat}.yml"] - } -} diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index 6dd1b4e..ab5d65d 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -8,14 +8,14 @@ it { is_expected.to contain_class('beats::install') } it { is_expected.to contain_class('beats::config') } it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_beats__package_install('auditbeat') } - it { is_expected.to contain_beats__service_install('auditbeat') } - it { is_expected.to contain_beats__package_install('heartbeat') } - it { is_expected.to contain_beats__service_install('heartbeat') } - it { is_expected.to contain_beats__package_install('metricbeat') } - it { is_expected.to contain_beats__service_install('metricbeat') } - it { is_expected.to contain_beats__package_install('packetbeat') } - it { is_expected.to contain_beats__service_install('packetbeat') } + it { is_expected.to contain_package('auditbeat') } + it { is_expected.to contain_package('heartbeat') } + it { is_expected.to contain_package('metricbeat') } + it { is_expected.to contain_package('packetbeat') } + it { is_expected.to contain_service('auditbeat') } + it { is_expected.to contain_service('heartbeat') } + it { is_expected.to contain_service('metricbeat') } + it { is_expected.to contain_service('packetbeat') } end # no package management @@ -25,10 +25,10 @@ it { is_expected.to contain_class('beats::install') } it { is_expected.to contain_class('beats::config') } it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_beats__service_install('auditbeat') } - it { is_expected.to contain_beats__service_install('heartbeat') } - it { is_expected.to contain_beats__service_install('metricbeat') } - it { is_expected.to contain_beats__service_install('packetbeat') } + it { is_expected.to contain_service('auditbeat') } + it { is_expected.to contain_service('heartbeat') } + it { is_expected.to contain_service('metricbeat') } + it { is_expected.to contain_service('packetbeat') } end # no service management @@ -38,10 +38,10 @@ it { is_expected.to contain_class('beats::install') } it { is_expected.to contain_class('beats::config') } it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_beats__package_install('auditbeat') } - it { is_expected.to contain_beats__package_install('heartbeat') } - it { is_expected.to contain_beats__package_install('metricbeat') } - it { is_expected.to contain_beats__package_install('packetbeat') } + it { is_expected.to contain_package('auditbeat') } + it { is_expected.to contain_package('heartbeat') } + it { is_expected.to contain_package('metricbeat') } + it { is_expected.to contain_package('packetbeat') } end # installing a specific beat (metricbeat) @@ -51,8 +51,8 @@ it { is_expected.to contain_class('beats::install') } it { is_expected.to contain_class('beats::config') } it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_beats__package_install('metricbeat') } - it { is_expected.to contain_beats__service_install('metricbeat') } + it { is_expected.to contain_package('metricbeat') } + it { is_expected.to contain_service('metricbeat') } end # installing a specific beat with certain modules enabled/disabled diff --git a/spec/defines/define_package_install_spec.rb b/spec/defines/define_package_install_spec.rb deleted file mode 100644 index b60ba62..0000000 --- a/spec/defines/define_package_install_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'spec_helper' - -describe 'beats::package_install' do - let(:title) { 'metricbeat' } - let(:params) { {'package' => 'metricbeat', 'ensure' => 'present' } } - - on_supported_os.each do |os, facts| - context "on #{os}" do - let(:facts) do - facts - end - it { is_expected.to compile } - it { is_expected.to contain_package('metricbeat') } - end - end -end diff --git a/spec/defines/define_service_install_spec.rb b/spec/defines/define_service_install_spec.rb deleted file mode 100644 index a1665a1..0000000 --- a/spec/defines/define_service_install_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe 'beats::service_install' do - let(:title) { 'metricbeat' } - let(:params) { {'ensure' => 'running', 'enable' => true, 'provider' => :undef } } - on_supported_os.each do |os, facts| - context "on #{os}" do - let(:facts) do - facts - end - it { is_expected.to compile } - it { is_expected.to contain_service('metricbeat') } - end - end -end From 36bb5335aea1290d63366502b33da40fe8e4eb11 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 24 Feb 2018 16:55:51 +1100 Subject: [PATCH 19/33] Use elastic_stack module. --- manifests/init.pp | 8 +++++++- manifests/service.pp | 2 +- metadata.json | 4 ++++ spec/classes/beats_spec.rb | 10 ++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index 1fc839d..9f49148 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -28,6 +28,9 @@ # @param metricbeat_modules_manage # A list of Metricbeat modules to manage Default value: 'undef'. # +# @param [Boolean] manage_repo +# Enable repository management. Configure the official repositories. +# class beats ( Array[String] $beats_manage, String $package_ensure, @@ -37,12 +40,15 @@ Boolean $service_manage, Optional[String] $service_provider, String $config_root, + Boolean $manage_repo = true, Optional[Hash] $metricbeat_modules_manage ) { contain beats::install contain beats::config contain beats::service - + if ($manage_repo == true) { + include elastic_stack::repo + } Class['::beats::install'] -> Class['::beats::config'] ~> Class['::beats::service'] diff --git a/manifests/service.pp b/manifests/service.pp index b3646a6..28fbaed 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -3,7 +3,7 @@ class beats::service { if $beats::service_manage == true { $beats::beats_manage.each |String $beat| { - if lookup("beats::${beat}::settings", Data, 'deep', false) { + if lookup("beats::${beat}::settings", Data, 'deep', {}) != {} { service { $beat: ensure => $beats::service_ensure, enable => $beats::service_enable, diff --git a/metadata.json b/metadata.json index ab05ae6..89004a6 100644 --- a/metadata.json +++ b/metadata.json @@ -10,6 +10,10 @@ { "name": "puppetlabs-stdlib", "version_requirement": ">= 4.13.1 < 5.0.0" + }, + { + "name": "elastic/elastic_stack", + "version_requirement": ">=6.0.0 <7.0.0" } ], "operatingsystem_support": [ diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index ab5d65d..f0d0125 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -55,6 +55,16 @@ it { is_expected.to contain_service('metricbeat') } end + context 'auditbeat with a config file' do + let(:params) { {'beats_manage' => ['auditbeat']} } + let(:pre_condition) { '${beats::auditbeat::settings} = \'puppet:///some/path/to/auditbeat.yml\'' } + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_package('auditbeat') } + it { is_expected.to contain_service('auditbeat') } + end # installing a specific beat with certain modules enabled/disabled # context 'metricbeat with modules' do # let(:params) { {'beats_manage' => ['metricbeat'], 'metricbeat_modules_manage' => { 'enable' => ['docker']}} } From 49463affbb8ee52efed0bd03af851a8e25b699c9 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 24 Feb 2018 17:18:38 +1100 Subject: [PATCH 20/33] RSpec tests now has fixture to download module deps. Tests now run on all supported OSes. --- .fixtures.yml | 6 + spec/classes/beats_spec.rb | 146 +++++++++++++------------ spec/defines/metricbeat_module_spec.rb | 6 +- 3 files changed, 85 insertions(+), 73 deletions(-) create mode 100644 .fixtures.yml diff --git a/.fixtures.yml b/.fixtures.yml new file mode 100644 index 0000000..1f42440 --- /dev/null +++ b/.fixtures.yml @@ -0,0 +1,6 @@ +fixtures: + forge_modules: + apt: puppetlabs/apt + elastic_stack: elastic/elastic_stack + stdlib: puppetlabs/stdlib +zypprepo: darin/zypprepo diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index f0d0125..ba75cfb 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -1,80 +1,86 @@ require 'spec_helper' describe 'beats' do - # defaults should result in all official beats installed - context 'defaults' do - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_package('auditbeat') } - it { is_expected.to contain_package('heartbeat') } - it { is_expected.to contain_package('metricbeat') } - it { is_expected.to contain_package('packetbeat') } - it { is_expected.to contain_service('auditbeat') } - it { is_expected.to contain_service('heartbeat') } - it { is_expected.to contain_service('metricbeat') } - it { is_expected.to contain_service('packetbeat') } - end + let(:pre_condition) { %q( + include elastic_stack::repo + )} + on_supported_os.each do |os, facts| + let(:facts) do + facts + end + context "defaults on #{os}" do + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_package('auditbeat') } + it { is_expected.to contain_package('heartbeat') } + it { is_expected.to contain_package('metricbeat') } + it { is_expected.to contain_package('packetbeat') } + it { is_expected.to contain_service('auditbeat') } + it { is_expected.to contain_service('heartbeat') } + it { is_expected.to contain_service('metricbeat') } + it { is_expected.to contain_service('packetbeat') } + end - # no package management - context 'defaults (no package mgmt)' do - let(:params) { {'package_manage' => false} } - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_service('auditbeat') } - it { is_expected.to contain_service('heartbeat') } - it { is_expected.to contain_service('metricbeat') } - it { is_expected.to contain_service('packetbeat') } - end + # no package management + context "defaults (no package mgmt) on #{os}" do + let(:params) { {'package_manage' => false} } + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_service('auditbeat') } + it { is_expected.to contain_service('heartbeat') } + it { is_expected.to contain_service('metricbeat') } + it { is_expected.to contain_service('packetbeat') } + end - # no service management - context 'defaults (no service mgmt)' do - let(:params) { {'service_manage' => false} } - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_package('auditbeat') } - it { is_expected.to contain_package('heartbeat') } - it { is_expected.to contain_package('metricbeat') } - it { is_expected.to contain_package('packetbeat') } - end + # no service management + context "defaults (no service mgmt) on #{os}" do + let(:params) { {'service_manage' => false} } + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_package('auditbeat') } + it { is_expected.to contain_package('heartbeat') } + it { is_expected.to contain_package('metricbeat') } + it { is_expected.to contain_package('packetbeat') } + end - # installing a specific beat (metricbeat) - context 'just metricbeat' do - let(:params) { {'beats_manage' => ['metricbeat']} } - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_package('metricbeat') } - it { is_expected.to contain_service('metricbeat') } - end + # installing a specific beat (metricbeat) + context "just metricbeat on #{os}" do + let(:params) { {'beats_manage' => ['metricbeat']} } + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + it { is_expected.to contain_package('metricbeat') } + it { is_expected.to contain_service('metricbeat') } + end - context 'auditbeat with a config file' do - let(:params) { {'beats_manage' => ['auditbeat']} } - let(:pre_condition) { '${beats::auditbeat::settings} = \'puppet:///some/path/to/auditbeat.yml\'' } - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_package('auditbeat') } - it { is_expected.to contain_service('auditbeat') } + # context 'auditbeat with a config file' do + # let(:params) { {'beats_manage' => ['auditbeat']} } + # let(:pre_condition) { '${beats::auditbeat::settings} = \'puppet:///some/path/to/auditbeat.yml\'' } + # it { is_expected.to compile } + # it { is_expected.to contain_class('beats::install') } + # it { is_expected.to contain_class('beats::config') } + # it { is_expected.to contain_class('beats::service') } + # it { is_expected.to contain_package('auditbeat') } + # it { is_expected.to contain_service('auditbeat') } + # end + # installing a specific beat with certain modules enabled/disabled + # context 'metricbeat with modules' do + # let(:params) { {'beats_manage' => ['metricbeat'], 'metricbeat_modules_manage' => { 'enable' => ['docker']}} } + # it { is_expected.to compile } + # it { is_expected.to contain_class('beats::install') } + # it { is_expected.to contain_class('beats::config') } + # it { is_expected.to contain_class('beats::service') } + # it { is_expected.to contain_beats__package_install('metricbeat') } + # it { is_expected.to contain_beats__service_install('metricbeat') } + # it { is_expected.to contain_metricbeat_module('docker') } + # end end - # installing a specific beat with certain modules enabled/disabled - # context 'metricbeat with modules' do - # let(:params) { {'beats_manage' => ['metricbeat'], 'metricbeat_modules_manage' => { 'enable' => ['docker']}} } - # it { is_expected.to compile } - # it { is_expected.to contain_class('beats::install') } - # it { is_expected.to contain_class('beats::config') } - # it { is_expected.to contain_class('beats::service') } - # it { is_expected.to contain_beats__package_install('metricbeat') } - # it { is_expected.to contain_beats__service_install('metricbeat') } - # it { is_expected.to contain_metricbeat_module('docker') } - # end - end diff --git a/spec/defines/metricbeat_module_spec.rb b/spec/defines/metricbeat_module_spec.rb index d92e236..5e1259b 100644 --- a/spec/defines/metricbeat_module_spec.rb +++ b/spec/defines/metricbeat_module_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' describe 'metricbeat_module' do - let(:title) { 'docker' } - let(:name) { 'docker' } + let(:title) { 'apache' } + let(:name) { 'apache' } it { is_expected.to compile } - it { is_expected.to contain_metricbeat_module('docker') } + it { is_expected.to contain_metricbeat_module('apache') } end From 02f502819a2fd46c11bbba6f702647cdbc6b77cc Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 25 Feb 2018 10:40:16 +1100 Subject: [PATCH 21/33] More robust testing of different configuration conditions. --- manifests/config.pp | 14 +++- spec/classes/beats_spec.rb | 134 ++++++++++++++++++--------------- spec/fixtures/data/common.yaml | 1 + spec/fixtures/hiera/hiera.yaml | 7 ++ spec/spec_helper.rb | 1 + 5 files changed, 95 insertions(+), 62 deletions(-) create mode 100644 spec/fixtures/data/common.yaml create mode 100644 spec/fixtures/hiera/hiera.yaml diff --git a/manifests/config.pp b/manifests/config.pp index 5b1e494..04bba27 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -2,7 +2,8 @@ # This class handles the configuration files for beats. Avoid modifying private classes. class beats::config { $beats::beats_manage.each |String $beat| { - if lookup("beats::${beat}::settings", Hash, 'deep', {}) != {} { + case "beats::${beat}::settings" { + 'Hash': { file { "${beats::config_root}/${beat}/${beat}.yml": ensure => file, owner => 0, @@ -10,8 +11,8 @@ mode => '0600', content => inline_epp('<%= lookup("beats::${beat}::settings", Hash, \'deep\').to_yaml %>'), } - } - elsif lookup("beats::${beat}::settings", String, unique, '') != '' { + } + 'String': { file { "${beats::config_root}/${beat}/${beat}.yml": ensure => file, owner => 0, @@ -19,6 +20,13 @@ mode => '0600', source => lookup("beats::${beat}::settings", String, 'unique'), } + } + 'Undef': { + debug "no custom settings for ${beat}" + } + default: { + err "Got a value for beats::${beat}::settings that we didn't expect" + } } if $beat == 'metricbeat' and lookup('beats::metricbeat_modules_manage', Hash, 'deep', {}) != {} { lookup(beats::metricbeat_modules_manage).each | String $ensure, Array[String] $modules | { diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index ba75cfb..5fdfe99 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -9,78 +9,94 @@ let(:facts) do facts end - context "defaults on #{os}" do - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_package('auditbeat') } - it { is_expected.to contain_package('heartbeat') } - it { is_expected.to contain_package('metricbeat') } - it { is_expected.to contain_package('packetbeat') } - it { is_expected.to contain_service('auditbeat') } - it { is_expected.to contain_service('heartbeat') } - it { is_expected.to contain_service('metricbeat') } - it { is_expected.to contain_service('packetbeat') } + context "on #{os}" do + describe 'beats' do + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + end + describe 'beats::install' do + it { is_expected.to contain_package('auditbeat') } + it { is_expected.to contain_package('heartbeat') } + it { is_expected.to contain_package('metricbeat') } + it { is_expected.to contain_package('packetbeat') } + end + describe 'beats::service' do + it { is_expected.to contain_service('auditbeat') } + it { is_expected.to contain_service('heartbeat') } + it { is_expected.to contain_service('metricbeat') } + it { is_expected.to contain_service('packetbeat') } + end end # no package management - context "defaults (no package mgmt) on #{os}" do + context "no package mgmt on #{os}" do let(:params) { {'package_manage' => false} } - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_service('auditbeat') } - it { is_expected.to contain_service('heartbeat') } - it { is_expected.to contain_service('metricbeat') } - it { is_expected.to contain_service('packetbeat') } + describe 'beats' do + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + end + describe 'beats::install' do + it { is_expected.not_to contain_package('auditbeat') } + it { is_expected.not_to contain_package('heartbeat') } + it { is_expected.not_to contain_package('metricbeat') } + it { is_expected.not_to contain_package('packetbeat') } + end + describe 'beats::service' do + it { is_expected.to contain_service('auditbeat') } + it { is_expected.to contain_service('heartbeat') } + it { is_expected.to contain_service('metricbeat') } + it { is_expected.to contain_service('packetbeat') } + end end # no service management - context "defaults (no service mgmt) on #{os}" do + context "no service mgmt on #{os}" do let(:params) { {'service_manage' => false} } - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_package('auditbeat') } - it { is_expected.to contain_package('heartbeat') } - it { is_expected.to contain_package('metricbeat') } - it { is_expected.to contain_package('packetbeat') } + describe 'beats' do + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + end + describe 'beats::install' do + it { is_expected.to contain_package('auditbeat') } + it { is_expected.to contain_package('heartbeat') } + it { is_expected.to contain_package('metricbeat') } + it { is_expected.to contain_package('packetbeat') } + end + describe 'beats::service' do + it { is_expected.not_to contain_service('auditbeat') } + it { is_expected.not_to contain_service('heartbeat') } + it { is_expected.not_to contain_service('metricbeat') } + it { is_expected.not_to contain_service('packetbeat') } + end end # installing a specific beat (metricbeat) context "just metricbeat on #{os}" do let(:params) { {'beats_manage' => ['metricbeat']} } - it { is_expected.to compile } - it { is_expected.to contain_class('beats::install') } - it { is_expected.to contain_class('beats::config') } - it { is_expected.to contain_class('beats::service') } - it { is_expected.to contain_package('metricbeat') } - it { is_expected.to contain_service('metricbeat') } + describe 'beats' do + it { is_expected.to compile } + it { is_expected.to contain_class('beats::install') } + it { is_expected.to contain_class('beats::config') } + it { is_expected.to contain_class('beats::service') } + end + describe 'beats::install' do + it { is_expected.to contain_package('metricbeat') } + it { is_expected.not_to contain_package('auditbeat') } + it { is_expected.not_to contain_package('heartbeat') } + it { is_expected.not_to contain_package('packetbeat') } + end + describe 'beats::service' do + it { is_expected.to contain_service('metricbeat') } + it { is_expected.not_to contain_service('auditbeat') } + it { is_expected.not_to contain_service('heartbeat') } + it { is_expected.not_to contain_service('packetbeat') } + end end - - # context 'auditbeat with a config file' do - # let(:params) { {'beats_manage' => ['auditbeat']} } - # let(:pre_condition) { '${beats::auditbeat::settings} = \'puppet:///some/path/to/auditbeat.yml\'' } - # it { is_expected.to compile } - # it { is_expected.to contain_class('beats::install') } - # it { is_expected.to contain_class('beats::config') } - # it { is_expected.to contain_class('beats::service') } - # it { is_expected.to contain_package('auditbeat') } - # it { is_expected.to contain_service('auditbeat') } - # end - # installing a specific beat with certain modules enabled/disabled - # context 'metricbeat with modules' do - # let(:params) { {'beats_manage' => ['metricbeat'], 'metricbeat_modules_manage' => { 'enable' => ['docker']}} } - # it { is_expected.to compile } - # it { is_expected.to contain_class('beats::install') } - # it { is_expected.to contain_class('beats::config') } - # it { is_expected.to contain_class('beats::service') } - # it { is_expected.to contain_beats__package_install('metricbeat') } - # it { is_expected.to contain_beats__service_install('metricbeat') } - # it { is_expected.to contain_metricbeat_module('docker') } - # end end end diff --git a/spec/fixtures/data/common.yaml b/spec/fixtures/data/common.yaml new file mode 100644 index 0000000..23468e7 --- /dev/null +++ b/spec/fixtures/data/common.yaml @@ -0,0 +1 @@ +# beats::auditbeat::settings: puppet:///some/path/to/auditbeat.yml diff --git a/spec/fixtures/hiera/hiera.yaml b/spec/fixtures/hiera/hiera.yaml new file mode 100644 index 0000000..012268c --- /dev/null +++ b/spec/fixtures/hiera/hiera.yaml @@ -0,0 +1,7 @@ +--- +:backends: + - yaml +:yaml: + :datadir: spec/fixtures/data +:hierarchy: + - common diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e39f6e7..ce39e67 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -20,6 +20,7 @@ RSpec.configure do |c| c.default_facts = default_facts + c.hiera_config = 'spec/fixtures/hiera/hiera.yaml' c.after(:suite) do RSpec::Puppet::Coverage.report! end From d1ac9baf5a9adbaa59fda889096188cca11dd36d Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 25 Feb 2018 11:00:16 +1100 Subject: [PATCH 22/33] Handle Windows paths better. --- data/windows-family.yaml | 1 + manifests/config.pp | 14 ++++++++++++-- manifests/service.pp | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 data/windows-family.yaml diff --git a/data/windows-family.yaml b/data/windows-family.yaml new file mode 100644 index 0000000..95ef070 --- /dev/null +++ b/data/windows-family.yaml @@ -0,0 +1 @@ +beats::config_root: C:\Program Files diff --git a/manifests/config.pp b/manifests/config.pp index 04bba27..7db1140 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -2,10 +2,19 @@ # This class handles the configuration files for beats. Avoid modifying private classes. class beats::config { $beats::beats_manage.each |String $beat| { + case $facts['os']['family'] { + 'windows': { + $beat_config = "${beats::config_root}\${beat}\${beat}.yml" + } + default: { + $beat_config = "${beats::config_root}/${beat}/${beat}.yml" + } + } case "beats::${beat}::settings" { 'Hash': { - file { "${beats::config_root}/${beat}/${beat}.yml": + file { "${beat}_config": ensure => file, + path => $beat_config, owner => 0, group => 0, mode => '0600', @@ -13,8 +22,9 @@ } } 'String': { - file { "${beats::config_root}/${beat}/${beat}.yml": + file { "${beat}_config": ensure => file, + path => $beat_config, owner => 0, group => 0, mode => '0600', diff --git a/manifests/service.pp b/manifests/service.pp index 28fbaed..cfd3f8d 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -10,7 +10,7 @@ provider => $beats::service_provider, hasstatus => true, hasrestart => true, - subscribe => File["${beats::config_root}/${beat}/${beat}.yml"] + subscribe => File["${beat}_config"] } } else { From d298dcf5ecd51c24ed7459879492c01cff9eaf8b Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 25 Feb 2018 11:24:17 +1100 Subject: [PATCH 23/33] Clean up code for detecting if settings is Hash or String. --- manifests/config.pp | 44 ++++++++++++++++++++++---------------------- manifests/service.pp | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/manifests/config.pp b/manifests/config.pp index 7db1140..6e2760a 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -10,32 +10,32 @@ $beat_config = "${beats::config_root}/${beat}/${beat}.yml" } } - case "beats::${beat}::settings" { - 'Hash': { - file { "${beat}_config": - ensure => file, - path => $beat_config, - owner => 0, - group => 0, - mode => '0600', - content => inline_epp('<%= lookup("beats::${beat}::settings", Hash, \'deep\').to_yaml %>'), - } - } - 'String': { - file { "${beat}_config": - ensure => file, - path => $beat_config, - owner => 0, - group => 0, - mode => '0600', - source => lookup("beats::${beat}::settings", String, 'unique'), + case getvar("beats::${beat}::settings") { + Hash: { + file { "${beat}_config": + ensure => file, + path => $beat_config, + owner => 0, + group => 0, + mode => '0600', + content => inline_epp('<%= lookup("beats::${beat}::settings", Hash, \'deep\').to_yaml %>'), + } } + String: { + file { "${beat}_config": + ensure => file, + path => $beat_config, + owner => 0, + group => 0, + mode => '0600', + source => lookup("beats::${beat}::settings", String, 'unique'), + } } - 'Undef': { - debug "no custom settings for ${beat}" + Undef: { + debug "No custom settings for ${beat}, using defaults." } default: { - err "Got a value for beats::${beat}::settings that we didn't expect" + err "Got a data type for beats::${beat}::settings that we didn't expect. Want a Hash or String" } } if $beat == 'metricbeat' and lookup('beats::metricbeat_modules_manage', Hash, 'deep', {}) != {} { diff --git a/manifests/service.pp b/manifests/service.pp index cfd3f8d..67ef02d 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -3,7 +3,7 @@ class beats::service { if $beats::service_manage == true { $beats::beats_manage.each |String $beat| { - if lookup("beats::${beat}::settings", Data, 'deep', {}) != {} { + if getvar("beats::${beat}::settings") { service { $beat: ensure => $beats::service_ensure, enable => $beats::service_enable, From a763d5e2d4f43a2133cebd7257cbc99f9286f30b Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 25 Feb 2018 16:57:43 +1100 Subject: [PATCH 24/33] Fix resolving beats::${beat}::settings --- manifests/config.pp | 6 ++++-- spec/classes/beats_spec.rb | 1 + spec/fixtures/data/common.yaml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/manifests/config.pp b/manifests/config.pp index 6e2760a..5d540a1 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -10,7 +10,8 @@ $beat_config = "${beats::config_root}/${beat}/${beat}.yml" } } - case getvar("beats::${beat}::settings") { + if lookup("beats::${beat}::settings", Data, 'deep', undef) { + case lookup("beats::${beat}::settings") { Hash: { file { "${beat}_config": ensure => file, @@ -28,7 +29,7 @@ owner => 0, group => 0, mode => '0600', - source => lookup("beats::${beat}::settings", String, 'unique'), + source => lookup("beats::${beat}::settings", String), } } Undef: { @@ -38,6 +39,7 @@ err "Got a data type for beats::${beat}::settings that we didn't expect. Want a Hash or String" } } + } if $beat == 'metricbeat' and lookup('beats::metricbeat_modules_manage', Hash, 'deep', {}) != {} { lookup(beats::metricbeat_modules_manage).each | String $ensure, Array[String] $modules | { $modules.each | String $m | { diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index 5fdfe99..92d946b 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -21,6 +21,7 @@ it { is_expected.to contain_package('heartbeat') } it { is_expected.to contain_package('metricbeat') } it { is_expected.to contain_package('packetbeat') } + it { is_expected.to contain_file('auditbeat_config') } end describe 'beats::service' do it { is_expected.to contain_service('auditbeat') } diff --git a/spec/fixtures/data/common.yaml b/spec/fixtures/data/common.yaml index 23468e7..394025d 100644 --- a/spec/fixtures/data/common.yaml +++ b/spec/fixtures/data/common.yaml @@ -1 +1 @@ -# beats::auditbeat::settings: puppet:///some/path/to/auditbeat.yml +beats::auditbeat::settings: puppet:///some/path/to/auditbeat.yml From 2de53decb5f90f30f26fe2449b2af855cf361c06 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 4 Mar 2018 19:21:45 +1100 Subject: [PATCH 25/33] Handle custom Metricbeat module config outside of custom type. --- .../provider/metricbeat_module/metricbeat.rb | 25 ----------------- lib/puppet/type/metricbeat_module.rb | 11 -------- manifests/config.pp | 16 +++++------ manifests/init.pp | 4 +-- manifests/metricbeat/module.pp | 27 +++++++++++++++++++ spec/classes/beats_spec.rb | 1 + 6 files changed, 37 insertions(+), 47 deletions(-) create mode 100644 manifests/metricbeat/module.pp diff --git a/lib/puppet/provider/metricbeat_module/metricbeat.rb b/lib/puppet/provider/metricbeat_module/metricbeat.rb index 2ffe9e4..971e648 100644 --- a/lib/puppet/provider/metricbeat_module/metricbeat.rb +++ b/lib/puppet/provider/metricbeat_module/metricbeat.rb @@ -14,34 +14,9 @@ def module_file ) end - # Metricbeat module settings. - # - # @return String - def module_settings - if resource[:settings].empty? - return false - else - return resource[:settings] - end - end - - # Write module_settings contents to disk. - def writemodulefile - if module_settings - info("Writing settings for Metricbeat module") - File.open(module_file, 'w') do |file| - file.write "- module: #{resource[:name]}\n" - module_settings.each do |key, value| - file.write " #{key}: #{value}\n" - end - end - end - end - def exists? if !File.exists?(module_file) debug("Module file #{module_file} does not exist") - writemodulefile return false else debug "Module exists" diff --git a/lib/puppet/type/metricbeat_module.rb b/lib/puppet/type/metricbeat_module.rb index 35af20d..81e62c9 100644 --- a/lib/puppet/type/metricbeat_module.rb +++ b/lib/puppet/type/metricbeat_module.rb @@ -7,17 +7,6 @@ desc 'An arbitrary name used as the identity of the resource.' end - newparam(:settings) do - desc 'Any custom settings for this module.' - validate do |settings| - unless settings.empty? - unless settings.is_a?(Hash) and settings.to_yaml - raise ArgumentError , "%s can not be munged to YAML" % settings - end - end - end - end - newparam(:module_dir) do desc 'Path to the Metricbeat modules directory' defaultto '/etc/metricbeat/modules.d' diff --git a/manifests/config.pp b/manifests/config.pp index 5d540a1..4a5254f 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -42,22 +42,20 @@ } if $beat == 'metricbeat' and lookup('beats::metricbeat_modules_manage', Hash, 'deep', {}) != {} { lookup(beats::metricbeat_modules_manage).each | String $ensure, Array[String] $modules | { - $modules.each | String $m | { if $beats::service_manage == true { - metricbeat_module { $m: - ensure => $ensure, - settings => lookup("beats::metricbeat::module::settings.${m}", Hash, 'deep', {}), - notify => Service['metricbeat'] + beats::metricbeat::module { $modules: + ensure => $ensure, + module_dir => "${beats::config_root}/metricbeat/modules.d", + notify => Service['metricbeat'] } } else { - metricbeat_module { $m: - ensure => $ensure, - settings => lookup("beats::metricbeat::module::settings.${m}", Hash, 'deep', {}), + beats::metricbeat::module { $modules: + ensure => $ensure, + module_dir => "${beats::config_root}/metricbeat/modules.d", } } } } } } -} diff --git a/manifests/init.pp b/manifests/init.pp index 9f49148..25d1233 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -47,9 +47,9 @@ contain beats::config contain beats::service if ($manage_repo == true) { - include elastic_stack::repo + include elastic_stack::repo } Class['::beats::install'] -> Class['::beats::config'] - ~> Class['::beats::service'] + -> Class['::beats::service'] } diff --git a/manifests/metricbeat/module.pp b/manifests/metricbeat/module.pp new file mode 100644 index 0000000..8a7591b --- /dev/null +++ b/manifests/metricbeat/module.pp @@ -0,0 +1,27 @@ +# @api private +# This defined type handles the enabling/disabling Metricbeat modules. Avoid modifying private defined types. +define beats::metricbeat::module ( + String $ensure = 'present', + Hash $settings = lookup("beats::metricbeat::module::settings.${name}", Hash, 'deep', {}), + String $module_dir +) +{ + if $settings != {} { + metricbeat_module { $name: + ensure => $ensure, + } + file { "metricbeat_${name}_config": + ensure => file, + path => "${module_dir}/${name}.yml", + owner => 0, + group => 0, + mode => '0600', + content => inline_epp('- <%= $name -%>:\n<%= $settings.to_yaml %>'), + } + } + else { + metricbeat_module { $name: + ensure => $ensure + } + } +} diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index 92d946b..1729e02 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -68,6 +68,7 @@ it { is_expected.to contain_package('heartbeat') } it { is_expected.to contain_package('metricbeat') } it { is_expected.to contain_package('packetbeat') } + it { is_expected.to contain_file('auditbeat_config') } end describe 'beats::service' do it { is_expected.not_to contain_service('auditbeat') } From 28b3b9979a5fe32fbf0db09e142fb9d917753d9d Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 4 Mar 2018 22:18:03 +1100 Subject: [PATCH 26/33] Clean up beats::metricbeat::module defined type. --- manifests/metricbeat/module.pp | 6 +++--- templates/metricbeat_module.yml.epp | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 templates/metricbeat_module.yml.epp diff --git a/manifests/metricbeat/module.pp b/manifests/metricbeat/module.pp index 8a7591b..a5f0d9d 100644 --- a/manifests/metricbeat/module.pp +++ b/manifests/metricbeat/module.pp @@ -2,11 +2,11 @@ # This defined type handles the enabling/disabling Metricbeat modules. Avoid modifying private defined types. define beats::metricbeat::module ( String $ensure = 'present', - Hash $settings = lookup("beats::metricbeat::module::settings.${name}", Hash, 'deep', {}), + Hash $settings = lookup("beats::metricbeat::module_settings.${name}", Data, 'deep', {}), String $module_dir ) { - if $settings != {} { + if ! $settings.empty { metricbeat_module { $name: ensure => $ensure, } @@ -16,7 +16,7 @@ owner => 0, group => 0, mode => '0600', - content => inline_epp('- <%= $name -%>:\n<%= $settings.to_yaml %>'), + content => epp('beats/metricbeat_module.yml.epp', { name => $name, settings => $settings }), } } else { diff --git a/templates/metricbeat_module.yml.epp b/templates/metricbeat_module.yml.epp new file mode 100644 index 0000000..87973e7 --- /dev/null +++ b/templates/metricbeat_module.yml.epp @@ -0,0 +1,4 @@ +- module: <%= $name %> +<% $settings.each |$k,$v| { -%> + <%= $k -%>: <%= $v %> +<% } -%> From 3fc3f05be282795f533661482fb02fe3826620a5 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Mon, 5 Mar 2018 23:08:24 +1100 Subject: [PATCH 27/33] Add tests for beats::metricbeat::module. --- manifests/config.pp | 4 +--- manifests/metricbeat/module.pp | 15 +++++++++---- manifests/service.pp | 2 +- spec/classes/beats_spec.rb | 19 ++++++++++++++-- spec/defines/beats_metricbeat_module_spec.rb | 17 +++++++++++++++ spec/fixtures/data/common.yaml | 23 ++++++++++++++++++++ 6 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 spec/defines/beats_metricbeat_module_spec.rb diff --git a/manifests/config.pp b/manifests/config.pp index 4a5254f..c2f1c36 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -4,7 +4,7 @@ $beats::beats_manage.each |String $beat| { case $facts['os']['family'] { 'windows': { - $beat_config = "${beats::config_root}\${beat}\${beat}.yml" + $beat_config = "${beats::config_root}\\${beat}\\${beat}.yml" } default: { $beat_config = "${beats::config_root}/${beat}/${beat}.yml" @@ -45,14 +45,12 @@ if $beats::service_manage == true { beats::metricbeat::module { $modules: ensure => $ensure, - module_dir => "${beats::config_root}/metricbeat/modules.d", notify => Service['metricbeat'] } } else { beats::metricbeat::module { $modules: ensure => $ensure, - module_dir => "${beats::config_root}/metricbeat/modules.d", } } } diff --git a/manifests/metricbeat/module.pp b/manifests/metricbeat/module.pp index a5f0d9d..3a5ef57 100644 --- a/manifests/metricbeat/module.pp +++ b/manifests/metricbeat/module.pp @@ -1,12 +1,19 @@ # @api private # This defined type handles the enabling/disabling Metricbeat modules. Avoid modifying private defined types. define beats::metricbeat::module ( - String $ensure = 'present', - Hash $settings = lookup("beats::metricbeat::module_settings.${name}", Data, 'deep', {}), - String $module_dir + String $ensure = 'present' ) { - if ! $settings.empty { + case $facts['os']['family'] { + 'windows': { + $module_dir = "${beats::config_root}\\metricbeat\\${name}.yml" + } + default: { + $module_dir = "${beats::config_root}/metricbeat/${name}.yml" + } + } + $settings = lookup("beats::metricbeat::module_settings.${name}", Data, 'deep', {}) + if $settings != {} { metricbeat_module { $name: ensure => $ensure, } diff --git a/manifests/service.pp b/manifests/service.pp index 67ef02d..013dff2 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -3,7 +3,7 @@ class beats::service { if $beats::service_manage == true { $beats::beats_manage.each |String $beat| { - if getvar("beats::${beat}::settings") { + if lookup("beats::${beat}::settings", Data, 'deep', undef) { service { $beat: ensure => $beats::service_ensure, enable => $beats::service_enable, diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index 1729e02..02d9534 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -21,10 +21,14 @@ it { is_expected.to contain_package('heartbeat') } it { is_expected.to contain_package('metricbeat') } it { is_expected.to contain_package('packetbeat') } + end + describe 'beats::config' do it { is_expected.to contain_file('auditbeat_config') } + it { is_expected.to contain_beats__metricbeat__module('docker').that_notifies('Service[metricbeat]') } end describe 'beats::service' do - it { is_expected.to contain_service('auditbeat') } + it { is_expected.to contain_file('auditbeat_config') } + it { is_expected.to contain_service('auditbeat').that_subscribes_to('File[auditbeat_config]') } it { is_expected.to contain_service('heartbeat') } it { is_expected.to contain_service('metricbeat') } it { is_expected.to contain_service('packetbeat') } @@ -46,8 +50,12 @@ it { is_expected.not_to contain_package('metricbeat') } it { is_expected.not_to contain_package('packetbeat') } end + describe 'beats::config' do + it { is_expected.to contain_file('auditbeat_config') } + it { is_expected.to contain_beats__metricbeat__module('docker').that_notifies('Service[metricbeat]') } + end describe 'beats::service' do - it { is_expected.to contain_service('auditbeat') } + it { is_expected.to contain_service('auditbeat').that_subscribes_to('File[auditbeat_config]') } it { is_expected.to contain_service('heartbeat') } it { is_expected.to contain_service('metricbeat') } it { is_expected.to contain_service('packetbeat') } @@ -68,7 +76,10 @@ it { is_expected.to contain_package('heartbeat') } it { is_expected.to contain_package('metricbeat') } it { is_expected.to contain_package('packetbeat') } + end + describe 'beats::config' do it { is_expected.to contain_file('auditbeat_config') } + it { is_expected.to contain_beats__metricbeat__module('docker') } end describe 'beats::service' do it { is_expected.not_to contain_service('auditbeat') } @@ -93,6 +104,10 @@ it { is_expected.not_to contain_package('heartbeat') } it { is_expected.not_to contain_package('packetbeat') } end + describe 'beats::config' do + it { is_expected.not_to contain_file('auditbeat_config') } + it { is_expected.to contain_beats__metricbeat__module('docker').that_notifies('Service[metricbeat]') } + end describe 'beats::service' do it { is_expected.to contain_service('metricbeat') } it { is_expected.not_to contain_service('auditbeat') } diff --git a/spec/defines/beats_metricbeat_module_spec.rb b/spec/defines/beats_metricbeat_module_spec.rb new file mode 100644 index 0000000..fb6326a --- /dev/null +++ b/spec/defines/beats_metricbeat_module_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe 'beats::metricbeat::module' do + let(:pre_condition) { 'include beats' } + let(:title) { 'redis' } + let(:params) { {'ensure' => 'present' } } + on_supported_os.each do |os, facts| + let(:facts) do + facts + end + context "on #{os}" do + it { is_expected.to compile } + it { is_expected.to contain_file('metricbeat_redis_config') } + it { is_expected.to contain_metricbeat_module('redis') } + end + end +end diff --git a/spec/fixtures/data/common.yaml b/spec/fixtures/data/common.yaml index 394025d..5e9d1b4 100644 --- a/spec/fixtures/data/common.yaml +++ b/spec/fixtures/data/common.yaml @@ -1 +1,24 @@ beats::auditbeat::settings: puppet:///some/path/to/auditbeat.yml +beats::metricbeat_modules_manage: + 'present': + - docker +beats::metricbeat::module_settings: + docker: + metricsets: + - cpu # CPU usage + - filesystem # File system usage for each mountpoint + - fsstat # File system summary metrics + - load # CPU load averages + - memory # Memory usage + - network # Network IO + - process # Per process metrics + - process_summary # Process summary + - uptime # System Uptime + - core # Per CPU core usage + - diskio # Disk IO + hosts: ["unix:///var/run/docker.sock"] + period: 10s + redis: + metricsets: ["info", "keyspace"] + period: 10s + hosts: ["127.0.0.1:6379"] From 8a3c79bb82079eab6389b824d9e82f6d82fd35c1 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Mon, 5 Mar 2018 23:22:30 +1100 Subject: [PATCH 28/33] Update metadata.json. --- README.md | 4 ++-- metadata.json | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5708e8f..a8b9f0d 100644 --- a/README.md +++ b/README.md @@ -112,10 +112,10 @@ class { 'beats': } ``` -If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::module::settings`. For example: +If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::module_settings`. For example: ```yaml -beats::metricbeat::module::settings: +beats::metricbeat::module_settings: docker: metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] hosts: ["unix:///var/run/docker.sock"] diff --git a/metadata.json b/metadata.json index 89004a6..e33f53f 100644 --- a/metadata.json +++ b/metadata.json @@ -1,7 +1,7 @@ { "name": "elastic-beats", "version": "0.1.0", - "author": "toby@jarpy.net", + "author": "joshua.rich@elastic.co", "summary": "Module for installing and configuring Elastic Beats.", "license": "Apache-2.0", "source": "https://github.com/elastic/puppet-beats", @@ -26,12 +26,21 @@ { "operatingsystem": "RedHat", "operatingsystemrelease": [ - "7.0" + "6", + "7" + ] + }, + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "6", + "7" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ + "14.04", "16.04" ] }, From 31f78a82f478a7f8079d79d330ced46474adab4d Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Mon, 5 Mar 2018 23:31:46 +1100 Subject: [PATCH 29/33] Wrong path structure in beats::metricbeat::module. --- manifests/metricbeat/module.pp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifests/metricbeat/module.pp b/manifests/metricbeat/module.pp index 3a5ef57..5db4893 100644 --- a/manifests/metricbeat/module.pp +++ b/manifests/metricbeat/module.pp @@ -6,10 +6,10 @@ { case $facts['os']['family'] { 'windows': { - $module_dir = "${beats::config_root}\\metricbeat\\${name}.yml" + $module_dir = "${beats::config_root}\\metricbeat\\modules.d\\${name}.yml" } default: { - $module_dir = "${beats::config_root}/metricbeat/${name}.yml" + $module_dir = "${beats::config_root}/metricbeat/modules.d/${name}.yml" } } $settings = lookup("beats::metricbeat::module_settings.${name}", Data, 'deep', {}) From c99ec2a5f53728e6a6a5f59e5a16585b76103e49 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Mon, 5 Mar 2018 23:34:26 +1100 Subject: [PATCH 30/33] :facepalm: still wrong path. Time for bed. --- manifests/metricbeat/module.pp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifests/metricbeat/module.pp b/manifests/metricbeat/module.pp index 5db4893..587ae00 100644 --- a/manifests/metricbeat/module.pp +++ b/manifests/metricbeat/module.pp @@ -6,10 +6,10 @@ { case $facts['os']['family'] { 'windows': { - $module_dir = "${beats::config_root}\\metricbeat\\modules.d\\${name}.yml" + $module_dir = "${beats::config_root}\\metricbeat\\modules.d" } default: { - $module_dir = "${beats::config_root}/metricbeat/modules.d/${name}.yml" + $module_dir = "${beats::config_root}/metricbeat/modules.d" } } $settings = lookup("beats::metricbeat::module_settings.${name}", Data, 'deep', {}) From d31b7f3ea5b1a8b29d499051b7502ce4d325aa7f Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sat, 10 Mar 2018 14:50:36 +1100 Subject: [PATCH 31/33] Create a beats::metricbeat::config class and defined type for managing extra config around Metricbeat. Code clean-up. --- README.md | 26 ++++++++---- data/common.yaml | 1 - manifests/config.pp | 65 +++++++++++------------------ manifests/init.pp | 6 +-- manifests/metricbeat/config.pp | 26 ++++++++++++ manifests/metricbeat/module.pp | 4 +- spec/classes/beats_spec.rb | 15 +++++-- spec/fixtures/data/common.yaml | 30 ++++--------- templates/beat.yml.epp | 4 ++ templates/metricbeat_module.yml.epp | 1 + 10 files changed, 95 insertions(+), 83 deletions(-) create mode 100644 manifests/metricbeat/config.pp create mode 100644 templates/beat.yml.epp diff --git a/README.md b/README.md index a8b9f0d..2b92559 100644 --- a/README.md +++ b/README.md @@ -102,24 +102,32 @@ beats::auditbeat::settings: 'puppet:///somefileshare/auditbeat.yml' This class can handle enabling/disabling Metricbeat modules for you. -To enable/disable a list of modules, ensure you manage Metricbeat with this class and then manage the modules in `metricbeat_modules_manage`: +To enable/disable a list of modules, ensure you manage Metricbeat with this class: ```puppet class { 'beats': beats_manage => ['metricbeat'], - metricbeat_modules_manage => { 'present' => ['docker','kafka'], - 'absent' => ['redis'] } } ``` -If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::module_settings`. For example: +And then configure the modules you want to enable/disable in Hiera: ```yaml -beats::metricbeat::module_settings: - docker: - metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] - hosts: ["unix:///var/run/docker.sock"] - period: 10s +beats::metricbeat::modules: + 'present': + - docker + - system + 'absent': + - kafka +``` + +If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::::settings`. For example: + +```yaml +beats::metricbeat::docker::settings: + metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] + hosts: ["unix:///var/run/docker.sock"] + period: 10s ``` ## Reference diff --git a/data/common.yaml b/data/common.yaml index 0b57b43..35bce90 100644 --- a/data/common.yaml +++ b/data/common.yaml @@ -6,4 +6,3 @@ beats::service_ensure: running beats::service_manage: true beats::service_provider: ~ beats::config_root: /etc -beats::metricbeat_modules_manage: {} diff --git a/manifests/config.pp b/manifests/config.pp index c2f1c36..140cfc2 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -10,50 +10,33 @@ $beat_config = "${beats::config_root}/${beat}/${beat}.yml" } } - if lookup("beats::${beat}::settings", Data, 'deep', undef) { - case lookup("beats::${beat}::settings") { - Hash: { - file { "${beat}_config": - ensure => file, - path => $beat_config, - owner => 0, - group => 0, - mode => '0600', - content => inline_epp('<%= lookup("beats::${beat}::settings", Hash, \'deep\').to_yaml %>'), - } - } - String: { - file { "${beat}_config": - ensure => file, - path => $beat_config, - owner => 0, - group => 0, - mode => '0600', - source => lookup("beats::${beat}::settings", String), - } - } - Undef: { - debug "No custom settings for ${beat}, using defaults." - } - default: { - err "Got a data type for beats::${beat}::settings that we didn't expect. Want a Hash or String" - } - } - } - if $beat == 'metricbeat' and lookup('beats::metricbeat_modules_manage', Hash, 'deep', {}) != {} { - lookup(beats::metricbeat_modules_manage).each | String $ensure, Array[String] $modules | { - if $beats::service_manage == true { - beats::metricbeat::module { $modules: - ensure => $ensure, - notify => Service['metricbeat'] - } + $settings = lookup("beats::${beat}::settings", Data, 'deep', undef) + if $settings { + case type($settings) { + String: { + file { "${beat}_config": + ensure => file, + path => $beat_config, + owner => 0, + group => 0, + mode => '0600', + source => $settings, } - else { - beats::metricbeat::module { $modules: - ensure => $ensure, - } + } + default: { + file { "${beat}_config": + ensure => file, + path => $beat_config, + owner => 0, + group => 0, + mode => '0600', + content => epp('beats/beat.yml.epp', { settings => $settings }), } } } } + if $beat == 'metricbeat' { + require beats::metricbeat::config + } } +} diff --git a/manifests/init.pp b/manifests/init.pp index 25d1233..e1a173d 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -25,9 +25,6 @@ # @param config_root # The root directory under which individual beats config directories are found. Default value: '/etc'. # -# @param metricbeat_modules_manage -# A list of Metricbeat modules to manage Default value: 'undef'. -# # @param [Boolean] manage_repo # Enable repository management. Configure the official repositories. # @@ -40,8 +37,7 @@ Boolean $service_manage, Optional[String] $service_provider, String $config_root, - Boolean $manage_repo = true, - Optional[Hash] $metricbeat_modules_manage + Boolean $manage_repo = true ) { contain beats::install contain beats::config diff --git a/manifests/metricbeat/config.pp b/manifests/metricbeat/config.pp new file mode 100644 index 0000000..83a689f --- /dev/null +++ b/manifests/metricbeat/config.pp @@ -0,0 +1,26 @@ +# beats::metricbeat::config +# +# @param modules_manage +# A list of Metricbeat modules to manage. Default value: 'undef'. +# +# @api private +# This class handles the configuration files for beats. Avoid modifying private classes. +class beats::metricbeat::config ( + Optional[Hash] $modules_manage = lookup('beats::metricbeat::modules', Hash, 'deep', undef) +){ + if $modules_manage { + $modules_manage.each | String $ensure, Array[String] $modules | { + if $beats::service_manage == true { + beats::metricbeat::module { $modules: + ensure => $ensure, + notify => Service['metricbeat'] + } + } + else { + beats::metricbeat::module { $modules: + ensure => $ensure, + } + } + } + } + } diff --git a/manifests/metricbeat/module.pp b/manifests/metricbeat/module.pp index 587ae00..1c65c31 100644 --- a/manifests/metricbeat/module.pp +++ b/manifests/metricbeat/module.pp @@ -12,8 +12,8 @@ $module_dir = "${beats::config_root}/metricbeat/modules.d" } } - $settings = lookup("beats::metricbeat::module_settings.${name}", Data, 'deep', {}) - if $settings != {} { + $settings = lookup("beats::metricbeat::${name}::settings", Data, 'deep', undef) + if $settings { metricbeat_module { $name: ensure => $ensure, } diff --git a/spec/classes/beats_spec.rb b/spec/classes/beats_spec.rb index 02d9534..4ece563 100644 --- a/spec/classes/beats_spec.rb +++ b/spec/classes/beats_spec.rb @@ -2,9 +2,7 @@ describe 'beats' do # defaults should result in all official beats installed - let(:pre_condition) { %q( - include elastic_stack::repo - )} + let(:pre_condition) { 'include elastic_stack::repo' } on_supported_os.each do |os, facts| let(:facts) do facts @@ -24,6 +22,9 @@ end describe 'beats::config' do it { is_expected.to contain_file('auditbeat_config') } + it { is_expected.to contain_class('beats::metricbeat::config')} + end + describe 'beats::metricbeat::config' do it { is_expected.to contain_beats__metricbeat__module('docker').that_notifies('Service[metricbeat]') } end describe 'beats::service' do @@ -52,6 +53,9 @@ end describe 'beats::config' do it { is_expected.to contain_file('auditbeat_config') } + it { is_expected.to contain_class('beats::metricbeat::config')} + end + describe 'beats::metricbeat::config' do it { is_expected.to contain_beats__metricbeat__module('docker').that_notifies('Service[metricbeat]') } end describe 'beats::service' do @@ -79,6 +83,9 @@ end describe 'beats::config' do it { is_expected.to contain_file('auditbeat_config') } + it { is_expected.to contain_class('beats::metricbeat::config')} + end + describe 'beats::metricbeat::config' do it { is_expected.to contain_beats__metricbeat__module('docker') } end describe 'beats::service' do @@ -106,7 +113,7 @@ end describe 'beats::config' do it { is_expected.not_to contain_file('auditbeat_config') } - it { is_expected.to contain_beats__metricbeat__module('docker').that_notifies('Service[metricbeat]') } + it { is_expected.to contain_class('beats::metricbeat::config')} end describe 'beats::service' do it { is_expected.to contain_service('metricbeat') } diff --git a/spec/fixtures/data/common.yaml b/spec/fixtures/data/common.yaml index 5e9d1b4..a75b555 100644 --- a/spec/fixtures/data/common.yaml +++ b/spec/fixtures/data/common.yaml @@ -1,24 +1,12 @@ beats::auditbeat::settings: puppet:///some/path/to/auditbeat.yml -beats::metricbeat_modules_manage: +beats::metricbeat::modules: 'present': - docker -beats::metricbeat::module_settings: - docker: - metricsets: - - cpu # CPU usage - - filesystem # File system usage for each mountpoint - - fsstat # File system summary metrics - - load # CPU load averages - - memory # Memory usage - - network # Network IO - - process # Per process metrics - - process_summary # Process summary - - uptime # System Uptime - - core # Per CPU core usage - - diskio # Disk IO - hosts: ["unix:///var/run/docker.sock"] - period: 10s - redis: - metricsets: ["info", "keyspace"] - period: 10s - hosts: ["127.0.0.1:6379"] +beats::metricbeat::docker::settings: + metricsets: ['cpu','filesystem'] + hosts: ["unix:///var/run/docker.sock"] + period: 10s +beats::metricbeat::redis::settings: + metricsets: ["info", "keyspace"] + period: 10s + hosts: ["127.0.0.1:6379"] diff --git a/templates/beat.yml.epp b/templates/beat.yml.epp new file mode 100644 index 0000000..b6fe425 --- /dev/null +++ b/templates/beat.yml.epp @@ -0,0 +1,4 @@ +# MANAGED BY PUPPET +<% $settings.each |$k,$v| { -%> + <%= $k -%>: <%= $v %> +<% } -%> diff --git a/templates/metricbeat_module.yml.epp b/templates/metricbeat_module.yml.epp index 87973e7..58eb561 100644 --- a/templates/metricbeat_module.yml.epp +++ b/templates/metricbeat_module.yml.epp @@ -1,3 +1,4 @@ +# MANAGED BY PUPPET - module: <%= $name %> <% $settings.each |$k,$v| { -%> <%= $k -%>: <%= $v %> From 42a2759fecda24a068a16ff4e3e68549cd16bcc8 Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Sun, 11 Mar 2018 00:02:21 +1100 Subject: [PATCH 32/33] Fix conversion of settings to yaml. --- templates/beat.yml.epp | 4 +--- templates/metricbeat_module.yml.epp | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/templates/beat.yml.epp b/templates/beat.yml.epp index b6fe425..4f94333 100644 --- a/templates/beat.yml.epp +++ b/templates/beat.yml.epp @@ -1,4 +1,2 @@ # MANAGED BY PUPPET -<% $settings.each |$k,$v| { -%> - <%= $k -%>: <%= $v %> -<% } -%> +<%= $settings.to_yaml %> diff --git a/templates/metricbeat_module.yml.epp b/templates/metricbeat_module.yml.epp index 58eb561..3fe6c19 100644 --- a/templates/metricbeat_module.yml.epp +++ b/templates/metricbeat_module.yml.epp @@ -1,5 +1,2 @@ # MANAGED BY PUPPET -- module: <%= $name %> -<% $settings.each |$k,$v| { -%> - <%= $k -%>: <%= $v %> -<% } -%> +<%= merge({ 'module' => $name},$settings).to_yaml %> From a52db20aee7be334f370eb44c67881edc15fa1cc Mon Sep 17 00:00:00 2001 From: Joshua Rich Date: Mon, 12 Mar 2018 08:29:25 +1100 Subject: [PATCH 33/33] Spec clean-up. Fix function to handle fetching specific Metricbeat modules settings. --- README.md | 17 ++++++++++------- functions/metricbeat/get_module_settings.pp | 18 ++++++++++++++++++ manifests/config.pp | 2 +- manifests/metricbeat/config.pp | 17 +++++++++++------ manifests/metricbeat/module.pp | 6 +++--- spec/defines/beats_metricbeat_module_spec.rb | 8 +++++++- spec/fixtures/data/common.yaml | 13 +++++-------- templates/metricbeat_module.yml.epp | 2 +- 8 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 functions/metricbeat/get_module_settings.pp diff --git a/README.md b/README.md index 2b92559..26cb72e 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ class { 'beats': #### Beats custom configuration -This module recommends using [Hiera](https://puppet.com/docs/puppet/5.3/hiera_intro.html) for configuration data. You can either specify your complete Beats configuration in Hiera or as a Puppet URL under `beats::::settings`. +This module recommends using Hiera for configuration data. You can either specify your complete Beats configuration in Hiera or as a Puppet URL under `beats::::settings`. Configure in Hiera: @@ -106,7 +106,7 @@ To enable/disable a list of modules, ensure you manage Metricbeat with this clas ```puppet class { 'beats': - beats_manage => ['metricbeat'], + beats_manage => ['metricbeat'], } ``` @@ -121,13 +121,16 @@ beats::metricbeat::modules: - kafka ``` -If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::::settings`. For example: +If you need to define custom settings for a particular module, add those in Hiera under `beats::metricbeat::modules::settings`. For example: ```yaml -beats::metricbeat::docker::settings: - metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] - hosts: ["unix:///var/run/docker.sock"] - period: 10s +beats::metricbeat::modules::settings: + - module: docker + metricsets: ["container", "cpu", "diskio", "healthcheck", "info", "memory", "network"] + hosts: ["unix:///var/run/docker.sock"] + period: 10s + - module: redis + period: 10s ``` ## Reference diff --git a/functions/metricbeat/get_module_settings.pp b/functions/metricbeat/get_module_settings.pp new file mode 100644 index 0000000..7a2f6cf --- /dev/null +++ b/functions/metricbeat/get_module_settings.pp @@ -0,0 +1,18 @@ +# beats::metricbeat::get_module_settings +# +# @api private +# This function fetches all of a specific Metricbeat module settings from +# the beats::metricbeat::modules::settings key in Hiera. +# Avoid modifying private classes. +# +# @param module +# A Metricbeat module to fetch settings for. +# +function beats::metricbeat::get_module_settings(String $module) >> Array[Hash] { + $module_settings = lookup("beats::metricbeat::modules::settings", Array[Hash], 'deep', undef) + $settings = $module_settings.filter |$v| { + $value = $v + $value =~ Hash and $value[module] == $module + } + $settings +} diff --git a/manifests/config.pp b/manifests/config.pp index 140cfc2..5e360ee 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -35,7 +35,7 @@ } } } - if $beat == 'metricbeat' { + if $beat == 'metricbeat' and lookup('beats::metricbeat::modules', Data, 'deep', undef) { require beats::metricbeat::config } } diff --git a/manifests/metricbeat/config.pp b/manifests/metricbeat/config.pp index 83a689f..d241234 100644 --- a/manifests/metricbeat/config.pp +++ b/manifests/metricbeat/config.pp @@ -6,21 +6,26 @@ # @api private # This class handles the configuration files for beats. Avoid modifying private classes. class beats::metricbeat::config ( - Optional[Hash] $modules_manage = lookup('beats::metricbeat::modules', Hash, 'deep', undef) + Hash $modules_manage = lookup('beats::metricbeat::modules', Hash, 'deep') ){ if $modules_manage { $modules_manage.each | String $ensure, Array[String] $modules | { + $modules.each | $m | { + $settings = beats::metricbeat::get_module_settings($m) if $beats::service_manage == true { - beats::metricbeat::module { $modules: - ensure => $ensure, - notify => Service['metricbeat'] + beats::metricbeat::module { $m: + ensure => $ensure, + settings => $settings, + notify => Service['metricbeat'] } } else { - beats::metricbeat::module { $modules: - ensure => $ensure, + beats::metricbeat::module { $m: + ensure => $ensure, + settings => $settings } } } } } +} diff --git a/manifests/metricbeat/module.pp b/manifests/metricbeat/module.pp index 1c65c31..fefcdb1 100644 --- a/manifests/metricbeat/module.pp +++ b/manifests/metricbeat/module.pp @@ -1,7 +1,8 @@ # @api private # This defined type handles the enabling/disabling Metricbeat modules. Avoid modifying private defined types. define beats::metricbeat::module ( - String $ensure = 'present' + String $ensure = 'present', + Array $settings = [] ) { case $facts['os']['family'] { @@ -12,8 +13,7 @@ $module_dir = "${beats::config_root}/metricbeat/modules.d" } } - $settings = lookup("beats::metricbeat::${name}::settings", Data, 'deep', undef) - if $settings { + if ! $settings.empty { metricbeat_module { $name: ensure => $ensure, } diff --git a/spec/defines/beats_metricbeat_module_spec.rb b/spec/defines/beats_metricbeat_module_spec.rb index fb6326a..85c3d39 100644 --- a/spec/defines/beats_metricbeat_module_spec.rb +++ b/spec/defines/beats_metricbeat_module_spec.rb @@ -8,7 +8,13 @@ let(:facts) do facts end - context "on #{os}" do + context "on #{os} (without custom settings)" do + it { is_expected.to compile } + it { is_expected.not_to contain_file('metricbeat_redis_config') } + it { is_expected.to contain_metricbeat_module('redis') } + end + context "on #{os} (with custom settings)" do + let(:params) { {'ensure' => 'present', 'settings' => [{'module' => 'redis', 'period' => '20s'}]} } it { is_expected.to compile } it { is_expected.to contain_file('metricbeat_redis_config') } it { is_expected.to contain_metricbeat_module('redis') } diff --git a/spec/fixtures/data/common.yaml b/spec/fixtures/data/common.yaml index a75b555..ba597b6 100644 --- a/spec/fixtures/data/common.yaml +++ b/spec/fixtures/data/common.yaml @@ -2,11 +2,8 @@ beats::auditbeat::settings: puppet:///some/path/to/auditbeat.yml beats::metricbeat::modules: 'present': - docker -beats::metricbeat::docker::settings: - metricsets: ['cpu','filesystem'] - hosts: ["unix:///var/run/docker.sock"] - period: 10s -beats::metricbeat::redis::settings: - metricsets: ["info", "keyspace"] - period: 10s - hosts: ["127.0.0.1:6379"] +beats::metricbeat::modules::settings: + - module: docker + metricsets: ['cpu','filesystem'] + hosts: ["unix:///var/run/docker.sock"] + period: 10s diff --git a/templates/metricbeat_module.yml.epp b/templates/metricbeat_module.yml.epp index 3fe6c19..4f94333 100644 --- a/templates/metricbeat_module.yml.epp +++ b/templates/metricbeat_module.yml.epp @@ -1,2 +1,2 @@ # MANAGED BY PUPPET -<%= merge({ 'module' => $name},$settings).to_yaml %> +<%= $settings.to_yaml %>