From c1db34ffb2e011d54a3c7159df86716648860c23 Mon Sep 17 00:00:00 2001 From: Christoph Maser Date: Sat, 4 Jan 2025 14:08:47 +0100 Subject: [PATCH] add ensure parameter to prometheus::daemon make it possible to also remove resources created by prometheus::daemon. This can then be passed through by all classes that use prometheus::daemon. --- REFERENCE.md | 20 +++++++- manifests/daemon.pp | 91 ++++++++++++++++++++++++++-------- manifests/scrape_job.pp | 5 +- spec/acceptance/daemon_spec.rb | 78 +++++++++++++++++++++++++++++ spec/defines/daemon_spec.rb | 4 +- spec/spec_helper_methods.rb | 10 ++++ 6 files changed, 183 insertions(+), 25 deletions(-) create mode 100644 spec/acceptance/daemon_spec.rb diff --git a/REFERENCE.md b/REFERENCE.md index 98d8d44ce..cb7e59b8c 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -15206,6 +15206,7 @@ The following parameters are available in the `prometheus::daemon` defined type: * [`init_style`](#-prometheus--daemon--init_style) * [`proxy_server`](#-prometheus--daemon--proxy_server) * [`proxy_type`](#-prometheus--daemon--proxy_type) +* [`ensure`](#-prometheus--daemon--ensure) * [`group`](#-prometheus--daemon--group) * [`manage_bin_link`](#-prometheus--daemon--manage_bin_link) * [`purge`](#-prometheus--daemon--purge) @@ -15233,7 +15234,7 @@ Complete URL corresponding to the where the release binary archive can be downlo ##### `notify_service` -Data type: `Any` +Data type: `Variant[Type[Exec],Type[Service],Undef]` The service to notify when something changes in this define @@ -15405,6 +15406,14 @@ Optional proxy server type (none|http|https|ftp) Default value: `undef` +##### `ensure` + +Data type: `Enum['present', 'absent']` + +Whether to install or remove the instance + +Default value: `'present'` + ##### `group` Data type: `String[1]` @@ -15515,6 +15524,7 @@ The following parameters are available in the `prometheus::scrape_job` defined t * [`targets`](#-prometheus--scrape_job--targets) * [`labels`](#-prometheus--scrape_job--labels) * [`collect_dir`](#-prometheus--scrape_job--collect_dir) +* [`ensure`](#-prometheus--scrape_job--ensure) ##### `job_name` @@ -15546,6 +15556,14 @@ NOTE: this is a prometheus setting and will be overridden during collection. Default value: `undef` +##### `ensure` + +Data type: `Enum['present', 'absent']` + +Whether the scrape job should be present or absent. + +Default value: `'present'` + ## Data types ### `Prometheus::GsUri` diff --git a/manifests/daemon.pp b/manifests/daemon.pp index 2944357a7..9a7863869 100644 --- a/manifests/daemon.pp +++ b/manifests/daemon.pp @@ -49,10 +49,12 @@ # Optional proxy server, with port number if needed. ie: https://example.com:8080 # @param proxy_type # Optional proxy server type (none|http|https|ftp) +# @param ensure +# Whether to install or remove the instance define prometheus::daemon ( String[1] $version, Prometheus::Uri $real_download_url, - $notify_service, + Variant[Type[Exec],Type[Service],Undef] $notify_service, String[1] $user, String[1] $group, Prometheus::Install $install_method = $prometheus::install_method, @@ -86,18 +88,22 @@ Stdlib::Absolutepath $usershell = $prometheus::usershell, Optional[String[1]] $proxy_server = undef, Optional[Enum['none', 'http', 'https', 'ftp']] $proxy_type = undef, + Enum['present', 'absent'] $ensure = 'present', ) { + $real_package_ensure = $ensure ? { 'absent' => 'absent', default => $package_ensure } + $real_service_ensure = $ensure ? { 'absent' => 'stopped', default => $service_ensure } + case $install_method { 'url': { if $download_extension == '' { file { "/opt/${name}-${version}.${os}-${arch}": - ensure => directory, + ensure => stdlib::ensure($ensure, 'directory'), owner => 'root', group => 0, # 0 instead of root because OS X uses "wheel". mode => '0755', } -> archive { "/opt/${name}-${version}.${os}-${arch}/${name}": - ensure => present, + ensure => $ensure, source => $real_download_url, checksum_verify => false, before => File["/opt/${name}-${version}.${os}-${arch}/${name}"], @@ -106,7 +112,7 @@ } } else { archive { "/tmp/${name}-${version}.${download_extension}": - ensure => present, + ensure => $ensure, extract => true, extract_path => $extract_path, source => $real_download_url, @@ -120,13 +126,14 @@ } } file { $archive_bin_path: - owner => 'root', - group => 0, # 0 instead of root because OS X uses "wheel". - mode => '0555', + ensure => stdlib::ensure($ensure, 'file'), + owner => 'root', + group => 0, # 0 instead of root because OS X uses "wheel". + mode => '0555', } if $manage_bin_link { file { "${bin_dir}/${bin_name}": - ensure => link, + ensure => stdlib::ensure($ensure, 'link'), notify => $notify_service, target => $archive_bin_path, require => File[$archive_bin_path], @@ -135,7 +142,7 @@ } 'package': { package { $package_name: - ensure => $package_ensure, + ensure => $real_package_ensure, notify => $notify_service, } if $manage_user { @@ -148,23 +155,28 @@ if $manage_user { # if we manage the service, we need to reload it if our user changes # important for cases where another group gets added - if $manage_service { + if $manage_service and $real_service_ensure == 'running' { User[$user] ~> $notify_service } ensure_resource('user', [$user], { - ensure => 'present', + ensure => $ensure, system => true, groups => $extra_groups, shell => $usershell, }) if $manage_group { - Group[$group] -> User[$user] + if $ensure == 'present' { + Group[$group] -> User[$user] + } else { + User[$user] -> Group[$group] + Service[$name] -> User[$user] + } } } if $manage_group { ensure_resource('group', [$group], { - ensure => 'present', + ensure => $ensure, system => true, }) } @@ -172,23 +184,31 @@ case $init_style { # lint:ignore:case_without_default 'upstart': { file { "/etc/init/${name}.conf": + ensure => stdlib::ensure($ensure, 'file'), mode => '0444', owner => 'root', group => 'root', content => template('prometheus/daemon.upstart.erb'), - notify => $notify_service, } file { "/etc/init.d/${name}": - ensure => link, + ensure => stdlib::ensure($ensure, 'file'), target => '/lib/init/upstart-job', owner => 'root', group => 'root', mode => '0755', } + if $notify_service !~ Undef { + if $ensure == 'present' { + File["/etc/init/${name}.conf"] ~> $notify_service + } else { + $notify_service -> File["/etc/init/${name}.conf"] + } + } } 'systemd': { include 'systemd' systemd::manage_unit { "${name}.service": + ensure => $ensure, unit_entry => { 'Description' => "Prometheus ${name}", 'Wants' => 'network-online.target', @@ -206,34 +226,61 @@ install_entry => { 'WantedBy' => 'multi-user.target', }, - notify => $notify_service, + } + if $notify_service !~ Undef { + if $ensure == 'present' { + Systemd::Manage_unit["${name}.service"] ~> $notify_service + } else { + $notify_service -> Systemd::Manage_unit["${name}.service"] + } } } 'sysv': { file { "/etc/init.d/${name}": + ensure => stdlib::ensure($ensure, 'file'), mode => '0555', owner => 'root', group => 'root', content => template('prometheus/daemon.sysv.erb'), - notify => $notify_service, + } + if $notify_service !~ Undef { + if $ensure == 'present' { + File["/etc/init.d/${name}"] ~> $notify_service + } else { + $notify_service -> File["/etc/init.d/${name}"] + } } } 'sles': { file { "/etc/init.d/${name}": + ensure => stdlib::ensure($ensure, 'file'), mode => '0555', owner => 'root', group => 'root', content => template('prometheus/daemon.sles.erb'), - notify => $notify_service, + } + if $notify_service !~ Undef { + if $ensure == 'present' { + File["/etc/init.d/${name}"] ~> $notify_service + } else { + $notify_service -> File["/etc/init.d/${name}"] + } } } 'launchd': { file { "/Library/LaunchDaemons/io.${name}.daemon.plist": + ensure => stdlib::ensure($ensure, 'file'), mode => '0644', owner => 'root', group => 'wheel', content => template('prometheus/daemon.launchd.erb'), - notify => $notify_service, + } + if $notify_service !~ Undef { + if $ensure == 'present' { + File["/Library/LaunchDaemons/io.${name}.daemon.plist"] ~> $notify_service + } else { + $notify_service -> File["/Library/LaunchDaemons/io.${name}.daemon.plist"] + } } } 'none': {} @@ -247,7 +294,7 @@ $env_vars_merged = $env_vars } - if $install_method == 'package' and $package_ensure in ['absent', 'purged'] { + if $install_method == 'package' and $real_package_ensure == 'absent' { # purge the environment file if the package is removed # # this is to make sure we can garbage-collect the files created by @@ -263,6 +310,7 @@ # those files to be present, even if empty, so it's critical that # the file not get removed file { "${env_file_path}/${name}": + ensure => stdlib::ensure($ensure, 'file'), mode => '0644', owner => 'root', group => '0', # Darwin uses wheel @@ -290,7 +338,7 @@ if $manage_service { service { $name: - ensure => $service_ensure, + ensure => $real_service_ensure, name => $init_selector, enable => $service_enable, provider => $real_provider, @@ -303,6 +351,7 @@ } @@prometheus::scrape_job { "${scrape_job_name}_${scrape_host}_${scrape_port}": + ensure => $ensure, job_name => $scrape_job_name, targets => ["${scrape_host}:${scrape_port}"], labels => $scrape_job_labels, diff --git a/manifests/scrape_job.pp b/manifests/scrape_job.pp index c1edf37ec..6448f22f3 100644 --- a/manifests/scrape_job.pp +++ b/manifests/scrape_job.pp @@ -13,11 +13,14 @@ # @param collect_dir # Directory used for collecting scrape definitions. # NOTE: this is a prometheus setting and will be overridden during collection. +# @param ensure +# Whether the scrape job should be present or absent. define prometheus::scrape_job ( String[1] $job_name, Array[String[1]] $targets, Hash[String[1], String[1]] $labels = {}, Stdlib::Absolutepath $collect_dir = undef, + Enum['present', 'absent'] $ensure = 'present', ) { $config = stdlib::to_yaml([ { @@ -26,7 +29,7 @@ }, ]) file { "${collect_dir}/${job_name}_${name}.yaml": - ensure => file, + ensure => stdlib::ensure($ensure, 'file'), owner => 'root', group => $prometheus::group, mode => $prometheus::config_mode, diff --git a/spec/acceptance/daemon_spec.rb b/spec/acceptance/daemon_spec.rb new file mode 100644 index 000000000..20e6ebcea --- /dev/null +++ b/spec/acceptance/daemon_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require 'spec_helper_acceptance' + +describe 'daemon' do + describe 'install node_exporter' do + it 'installs node_exporter with no errors' do + pp = " + include prometheus + $notify_service = Service[node_exporter] + prometheus::daemon { 'node_exporter': + version => '1.8.2', + real_download_url => 'https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz', + notify_service => $notify_service, + user => 'node-exporter', + group => 'node-exporter', + export_scrape_job => true, + scrape_host => 'localhost', + scrape_port => 9100, + } + " + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) + end + + describe service('node_exporter') do + it { is_expected.to be_running } + it { is_expected.to be_enabled } + end + + describe port(9100) do + it { is_expected.to be_listening.with('tcp6') } + end + end + + describe 'uninstall' do + it 'deletes node_exporter with no errors' do + pp = " + include prometheus + $notify_service = Service[node_exporter] + prometheus::daemon { 'node_exporter': + ensure => 'absent', + version => '1.8.2', + real_download_url => 'https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz', + notify_service => $notify_service, + user => 'node-exporter', + group => 'node-exporter', + export_scrape_job => true, + scrape_host => 'localhost', + scrape_port => 9100, + } + " + apply_manifest(pp, catch_failures: true) + end + + describe process('node_exporter') do + it { is_expected.not_to be_running } + end + + # rubocop:disable RSpec/RepeatedExampleGroupBody + describe user('node-exporter') do + it { is_expected.not_to exist } + end + + describe file('/usr/local/bin/node_exporter') do + it { is_expected.not_to exist } + end + + describe file('/etc/systemd/system/node_exporter.service') do + it { is_expected.not_to exist } + end + + describe file('/opt/node_exporter-1.8.2.linux-amd64/node_exporter') do + it { is_expected.not_to exist } + end + # rubocop:enable RSpec/RepeatedExampleGroupBody + end +end diff --git a/spec/defines/daemon_spec.rb b/spec/defines/daemon_spec.rb index ecc6aef3d..6561f9db8 100644 --- a/spec/defines/daemon_spec.rb +++ b/spec/defines/daemon_spec.rb @@ -21,7 +21,7 @@ { version: '1.2.3', real_download_url: 'https://github.com/prometheus/smurf_exporter/releases/v1.2.3/smurf_exporter-1.2.3.any.tar.gz', - notify_service: 'Service[smurf_exporter]', + notify_service: ResourceReference.new('Service[smurf_exporter]'), user: 'smurf_user', group: 'smurf_group', env_vars: { SOMEVAR: 42 }, @@ -169,7 +169,7 @@ { version: '1.2.3', real_download_url: 'https://github.com/prometheus/smurf_exporter/releases/v1.2.3/smurf_exporter-1.2.3.any.tar.gz', - notify_service: 'Service[smurf_exporter]', + notify_service: ResourceReference.new('Service[smurf_exporter]'), user: 'smurf_user', group: 'smurf_group', env_vars: { SOMEVAR: 42 }, diff --git a/spec/spec_helper_methods.rb b/spec/spec_helper_methods.rb index f58e0899d..a4964e7be 100644 --- a/spec/spec_helper_methods.rb +++ b/spec/spec_helper_methods.rb @@ -3,3 +3,13 @@ def os_specific_facts(facts) return { service_provider: 'systemd' } if %w[Archlinux Debian RedHat].include?(facts[:os]['family']) end + +class ResourceReference + def initialize(ref) + @ref = ref + end + + def inspect + @ref + end +end