diff --git a/manifests/config.pp b/manifests/config.pp index 2fe00d5..cf8e3f6 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -1,260 +1,296 @@ # This class exists to coordinate all configuration related actions, # functionality and logical units in a central place. # # It is not intended to be used directly by external resources like node # definitions or other modules. # # @example importing this class into other classes to use its functionality: # class { 'elasticsearch::config': } # # @author Richard Pijnenburg # @author Tyler Langlois # @author Gavin Williams # class elasticsearch::config { #### Configuration Exec { path => [ '/bin', '/usr/bin', '/usr/local/bin' ], cwd => '/', } if ( $elasticsearch::ensure == 'present' ) { file { $elasticsearch::homedir: ensure => 'directory', group => $elasticsearch::elasticsearch_group, owner => $elasticsearch::elasticsearch_user; $elasticsearch::configdir: ensure => 'directory', group => $elasticsearch::elasticsearch_group, owner => 'root', mode => '2750'; $elasticsearch::datadir: ensure => 'directory', group => $elasticsearch::elasticsearch_group, owner => $elasticsearch::elasticsearch_user; $elasticsearch::logdir: ensure => 'directory', group => $elasticsearch::elasticsearch_group, owner => $elasticsearch::elasticsearch_user, mode => '0750'; $elasticsearch::_plugindir: ensure => 'directory', group => $elasticsearch::elasticsearch_group, owner => $elasticsearch::elasticsearch_user, mode => 'o+Xr'; "${elasticsearch::homedir}/lib": ensure => 'directory', group => '0', owner => 'root', recurse => true; } if $elasticsearch::pid_dir { file { $elasticsearch::pid_dir: ensure => 'directory', group => undef, owner => $elasticsearch::elasticsearch_user, recurse => true, } if ($elasticsearch::service_provider == 'systemd') { $group = $elasticsearch::elasticsearch_group $user = $elasticsearch::elasticsearch_user $pid_dir = $elasticsearch::pid_dir file { '/usr/lib/tmpfiles.d/elasticsearch.conf': ensure => 'file', content => template("${module_name}/usr/lib/tmpfiles.d/elasticsearch.conf.erb"), group => '0', owner => 'root', } } } if $elasticsearch::defaults_location { augeas { "${elasticsearch::defaults_location}/elasticsearch": incl => "${elasticsearch::defaults_location}/elasticsearch", lens => 'Shellvars.lns', changes => [ 'rm CONF_FILE', 'rm CONF_DIR', 'rm ES_PATH_CONF', ], } file { "${elasticsearch::defaults_location}/elasticsearch": ensure => 'file', group => $elasticsearch::elasticsearch_group, owner => $elasticsearch::elasticsearch_user, mode => '0640'; } } if $::elasticsearch::security_plugin != undef and ($::elasticsearch::security_plugin in ['shield', 'x-pack']) { file { "${::elasticsearch::configdir}/${::elasticsearch::security_plugin}" : ensure => 'directory', owner => 'root', group => $elasticsearch::elasticsearch_group, mode => '0750', } } # Define logging config file for the in-use security plugin if $::elasticsearch::security_logging_content != undef or $::elasticsearch::security_logging_source != undef { if $::elasticsearch::security_plugin == undef or ! ($::elasticsearch::security_plugin in ['shield', 'x-pack']) { fail("\"${::elasticsearch::security_plugin}\" is not a valid security_plugin parameter value") } $_security_logging_file = $::elasticsearch::security_plugin ? { 'shield' => 'logging.yml', default => 'log4j2.properties' } file { "/etc/elasticsearch/${::elasticsearch::security_plugin}/${_security_logging_file}" : content => $::elasticsearch::security_logging_content, source => $::elasticsearch::security_logging_source, } } + $init_defaults = merge( + { + 'MAX_OPEN_FILES' => '65535', + }, + $::elasticsearch::init_defaults + ) + + # Setup init defaults + if ($::elasticsearch::ensure == 'present') { + # Defaults file, either from file source or from hash to augeas commands + if ($::elasticsearch::init_defaults_file != undef) { + file { "${::elasticsearch::defaults_location}/elasticsearch": + ensure => $::elasticsearch::ensure, + source => $::elasticsearch::init_defaults_file, + owner => 'root', + group => '0', + mode => '0644', + before => Service['elasticsearch'], + notify => $::elasticsearch::_notify_service + } + } else { + augeas { 'init_defaults': + incl => "${::elasticsearch::defaults_location}/elasticsearch", + lens => 'Shellvars.lns', + changes => template("${module_name}/etc/sysconfig/defaults.erb"), + before => Service['elasticsearch'], + notify => $::elasticsearch::_notify_service + } + } + } else { # absent + file { "${elasticsearch::defaults_location}/elasticsearch": + ensure => 'absent', + subscribe => Service['elasticsearch'], + } + } + # Generate config file $_config = deep_implode($elasticsearch::config) # Generate SSL config if $elasticsearch::ssl { if ($elasticsearch::keystore_password == undef) { fail('keystore_password required') } if ($elasticsearch::keystore_path == undef) { $_keystore_path = "${elasticsearch::configdir}/${elasticsearch::security_plugin}/${name}.ks" } else { $_keystore_path = $elasticsearch::keystore_path } if $elasticsearch::security_plugin == 'shield' { $_tls_config = { 'shield.transport.ssl' => true, 'shield.http.ssl' => true, 'shield.ssl.keystore.path' => $_keystore_path, 'shield.ssl.keystore.password' => $elasticsearch::keystore_password, } } elsif $elasticsearch::security_plugin == 'x-pack' { $_tls_config = { 'xpack.security.transport.ssl.enabled' => true, 'xpack.security.http.ssl.enabled' => true, 'xpack.ssl.keystore.path' => $_keystore_path, 'xpack.ssl.keystore.password' => $elasticsearch::keystore_password, } } # Trust CA Certificate java_ks { 'elasticsearch_ca': ensure => 'latest', certificate => $elasticsearch::ca_certificate, target => $_keystore_path, password => $elasticsearch::keystore_password, trustcacerts => true, } # Load node certificate and private key java_ks { 'elasticsearch_node': ensure => 'latest', certificate => $elasticsearch::certificate, private_key => $elasticsearch::private_key, target => $_keystore_path, password => $elasticsearch::keystore_password, } } else { $_tls_config = {} } # Logging file or hash if ($::elasticsearch::logging_file != undef) { $_log4j_content = undef } else { if ($::elasticsearch::logging_template != undef ) { $_log4j_content = template($::elasticsearch::logging_template) } else { $_log4j_content = template("${module_name}/etc/elasticsearch/log4j2.properties.erb") } $_logging_source = undef } file { "${::elasticsearch::configdir}/log4j2.properties": ensure => file, content => $_log4j_content, source => $_logging_source, mode => '0644', notify => $::elasticsearch::_notify_service, require => Class['elasticsearch::package'], before => Class['elasticsearch::service'], } # Generate Elasticsearch config $_es_config = merge( $::elasticsearch::config, { 'path.data' => $::elasticsearch::datadir }, { 'path.logs' => $::elasticsearch::logdir }, $_tls_config ) datacat_fragment { 'main_config': target => "${::elasticsearch::configdir}/elasticsearch.yml", data => $_es_config, } datacat { "${::elasticsearch::configdir}/elasticsearch.yml": template => "${module_name}/etc/elasticsearch/elasticsearch.yml.erb", notify => $::elasticsearch::_notify_service, require => Class['elasticsearch::package'], owner => $::elasticsearch::elasticsearch_user, group => $::elasticsearch::elasticsearch_group, mode => '0440', } # Configure JVM options file { "${::elasticsearch::configdir}/jvm.options": content => template("${module_name}/etc/elasticsearch/jvm.options.erb"), group => $::elasticsearch::elasticsearch_group, notify => $::elasticsearch::_notify_service, owner => $::elasticsearch::elasticsearch_user, } if $::elasticsearch::system_key != undef { file { "${::elasticsearch::configdir}/${::elasticsearch::security_plugin}/system_key": ensure => 'file', source => $::elasticsearch::system_key, mode => '0400', require => File["${::elasticsearch::configdir}/${::elasticsearch::security_plugin}"], } } # Add secrets to keystore if $::elasticsearch::secrets != undef { elasticsearch_keystore { 'elasticsearch_secrets': configdir => $::elasticsearch::configdir, purge => $::elasticsearch::purge_secrets, settings => $::elasticsearch::secrets, notify => $::elaticsearch::_notify_service, } } } elsif ( $elasticsearch::ensure == 'absent' ) { file { $elasticsearch::_plugindir: ensure => 'absent', force => true, backup => false, } file { "${elasticsearch::configdir}/jvm.options": ensure => 'absent', } } } diff --git a/manifests/instance.pp.ignore b/manifests/instance.pp.ignore new file mode 100644 index 0000000..8cf3206 --- /dev/null +++ b/manifests/instance.pp.ignore @@ -0,0 +1,281 @@ +# This define allows you to create or remove an elasticsearch instance +# +# @param ensure +# Controls if the managed resources shall be `present` or `absent`. +# If set to `absent`, the managed software packages will be uninstalled, and +# any traces of the packages will be purged as well as possible, possibly +# including existing configuration files. +# System modifications (if any) will be reverted as well as possible (e.g. +# removal of created users, services, changed log settings, and so on). +# This is a destructive parameter and should be used with care. +# + +# @param config +# Elasticsearch configuration hash. +# +# @param configdir +# Path to directory containing the elasticsearch configuration. +# Use this setting if your packages deviate from the norm (/etc/elasticsearch). +# +# @param configdir_recurselimit +# Dictates how deeply the file copy recursion logic should descend when +# copying files from the `elasticsearch::configdir` to instance `configdir`s. +# +# @param daily_rolling_date_pattern +# File pattern for the file appender log when file_rolling_type is `dailyRollingFile` +# +# @param datadir +# Allows you to set the data directory of Elasticsearch +# +# @param datadir_instance_directories +# Control whether individual directories for instances will be created within +# each instance's data directory. +# + +# @param file_rolling_type +# Configuration for the file appender rotation. It can be `dailyRollingFile` +# or `rollingFile`. The first rotates by name, and the second one by size. +# +# @param init_defaults +# Defaults file content in hash representation. +# +# @param init_defaults_file +# Defaults file as puppet resource. +# +# @param init_template +# Service file as a template +# +# @param jvm_options +# Array of options to set in jvm_options. +# +# @param keystore_password +# Password to encrypt this node's Java keystore. +# +# @param keystore_path +# Custom path to the java keystore file. This parameter is optional. +# +# @param logdir +# Log directory for this instance. +# +# @param logging_config +# Hash representation of information you want in the logging.yml file. +# +# @param logging_file +# Instead of a hash you can supply a puppet:// file source for the logging.yml file +# +# @param logging_level +# Default logging level for Elasticsearch. +# +# @param logging_template +# Use a custom logging template - just supply the reative path, ie +# $module_name/elasticsearch/logging.yml.erb +# +# @param private_key +# Path to the key associated with this node's certificate. +# +# @param purge_secrets +# Whether or not keys present in the keystore will be removed if they are not +# present in the specified secrets hash. +# +# @param rolling_file_max_backup_index +# Max number of logs to store whern file_rolling_type is `rollingFile` +# +# @param rolling_file_max_file_size +# Max log file size when file_rolling_type is `rollingFile` +# +# @param secrets +# Optional configuration hash of key/value pairs to store in the instance's +# Elasticsearch keystore file. If unset, the keystore is left unmanaged. +# +# @param security_plugin +# Which security plugin will be used to manage users, roles, and +# certificates. Inherited from top-level Elasticsearch class. +# +# @param service_flags +# Service flags used for the OpenBSD service configuration, defaults to undef. +# +# @param status +# To define the status of the service. If set to `enabled`, the service will +# be run and will be started at boot time. If set to `disabled`, the service +# is stopped and will not be started at boot time. If set to `running`, the +# service will be run but will not be started at boot time. You may use this +# to start a service on the first Puppet run instead of the system startup. +# If set to `unmanaged`, the service will not be started at boot time and Puppet +# does not care whether the service is running or not. For example, this may +# be useful if a cluster management software is used to decide when to start +# the service plus assuring it is running on the desired node. +# +# @param system_key +# Source for the Shield system key. Valid values are any that are +# supported for the file resource `source` parameter. +# +# @author Richard Pijnenburg +# @author Tyler Langlois +# +define elasticsearch::instance ( + Enum['absent', 'present'] $ensure = $elasticsearch::ensure, + Stdlib::Absolutepath $configdir = "${elasticsearch::configdir}/${name}", + Integer $configdir_recurselimit = $elasticsearch::configdir_recurselimit, + String $daily_rolling_date_pattern = $elasticsearch::daily_rolling_date_pattern, + Optional[Elasticsearch::Multipath] $datadir = undef, + Boolean $datadir_instance_directories = $elasticsearch::datadir_instance_directories, + String $file_rolling_type = $elasticsearch::file_rolling_type, + Hash $init_defaults = {}, + Optional[Stdlib::Absolutepath] $init_defaults_file = undef, + String $init_template = $elasticsearch::init_template, + Array[String] $jvm_options = $elasticsearch::jvm_options, + Optional[String] $keystore_password = undef, + Optional[Stdlib::Absolutepath] $keystore_path = undef, + Stdlib::Absolutepath $logdir = "${elasticsearch::logdir}/${name}", + Hash $logging_config = {}, + Optional[String] $logging_file = undef, + String $logging_level = $elasticsearch::default_logging_level, + Optional[String] $logging_template = undef, + Optional[Stdlib::Absolutepath] $private_key = undef, + Boolean $purge_secrets = $elasticsearch::purge_secrets, + Integer $rolling_file_max_backup_index = $elasticsearch::rolling_file_max_backup_index, + String $rolling_file_max_file_size = $elasticsearch::rolling_file_max_file_size, + Optional[Hash] $secrets = undef, + Optional[Enum['shield', 'x-pack']] $security_plugin = $elasticsearch::security_plugin, + Optional[String] $service_flags = undef, + Elasticsearch::Status $status = $elasticsearch::status, + Optional[String] $system_key = $elasticsearch::system_key, +) { + + File { + owner => $elasticsearch::elasticsearch_user, + group => $elasticsearch::elasticsearch_group, + } + + Exec { + path => [ '/bin', '/usr/bin', '/usr/local/bin' ], + cwd => '/', + } + + # ensure + if ! ($ensure in [ 'present', 'absent' ]) { + fail("\"${ensure}\" is not a valid ensure parameter value") + } + + if ($ensure == 'present') { + + # Configuration hash + if ($config == undef) { + $instance_config = {} + } else { + $instance_config = deep_implode($config) + } + + if(has_key($instance_config, 'node.name')) { + $instance_node_name = {} + } else { + $instance_node_name = { 'node.name' => "${::hostname}-${name}" } + } + + # String or array for data dir(s) + if ($datadir == undef) { + if ($datadir_instance_directories) { + if $elasticsearch::datadir =~ Array { + $instance_datadir = array_suffix($elasticsearch::datadir, "/${name}") + } else { + $instance_datadir = "${elasticsearch::datadir}/${name}" + } + } else { + $instance_datadir = $elasticsearch::datadir + } + } else { + $instance_datadir = $datadir + } + + # build up new config + $instance_conf = merge( + $main_config, + $instance_node_name, + $instance_datadir_config, + { 'path.logs' => $logdir }, + $tls_config, + $instance_config + ) + + # defaults file content + # ensure user did not provide both init_defaults and init_defaults_file + if ((!empty($init_defaults)) and ($init_defaults_file != undef)) { + fail ('Only one of $init_defaults and $init_defaults_file should be defined') + } + + $init_defaults_new = merge( + { 'DATA_DIR' => $elasticsearch::_datadir_default }, + $elasticsearch::init_defaults, + { + 'CONF_DIR' => $configdir, + 'ES_HOME' => $elasticsearch::homedir, + 'ES_JVM_OPTIONS' => "${configdir}/jvm.options", + 'ES_PATH_CONF' => $configdir, + 'LOG_DIR' => $logdir, + }, + $init_defaults + ) + + datacat_fragment { "main_config_${name}": + target => "${configdir}/elasticsearch.yml", + data => $instance_conf, + } + + datacat { "${configdir}/elasticsearch.yml": + template => "${module_name}/etc/elasticsearch/elasticsearch.yml.erb", + notify => $notify_service, + require => Class['elasticsearch::package'], + owner => $elasticsearch::elasticsearch_user, + group => $elasticsearch::elasticsearch_group, + mode => '0440', + } + + if ($elasticsearch::secrets != undef or $secrets != undef) { + if ($elasticsearch::secrets != undef) { + $main_secrets = $elasticsearch::secrets + } else { + $main_secrets = {} + } + + if ($secrets != undef) { + $instance_secrets = $secrets + } else { + $instance_secrets = {} + } + + elasticsearch_keystore { $name : + configdir => $elasticsearch::configdir, + purge => $purge_secrets, + settings => merge($main_secrets, $instance_secrets), + notify => $notify_service, + } + } + + $require_service = Class['elasticsearch::package'] + $before_service = undef + + } else { + + file { $configdir: + ensure => 'absent', + recurse => true, + force => true, + } + + $require_service = undef + $before_service = File[$configdir] + + $init_defaults_new = {} + } + + elasticsearch::service { $name: + ensure => $ensure, + status => $status, + service_flags => $service_flags, + init_defaults => $init_defaults_new, + init_defaults_file => $init_defaults_file, + init_template => $init_template, + require => $require_service, + before => $before_service, + } +} diff --git a/manifests/service.pp b/manifests/service.pp index 29fe10f..7dab4f1 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -1,112 +1,112 @@ # This class exists to coordinate all service management related actions, # functionality and logical units in a central place. # # *Note*: "service" is the Puppet term and type for background processes # in general and is used in a platform-independent way. E.g. "service" means # "daemon" in relation to Unix-like systems. # # @param ensure # Controls if the managed resources shall be `present` or `absent`. # If set to `absent`, the managed software packages will be uninstalled, and # any traces of the packages will be purged as well as possible, possibly # including existing configuration files. # System modifications (if any) will be reverted as well as possible (e.g. # removal of created users, services, changed log settings, and so on). # This is a destructive parameter and should be used with care. # # @param init_defaults # Defaults file content in hash representation # # @param init_defaults_file # Defaults file as puppet resource # # @param init_template # Service file as a template # # @param service_flags # Flags to pass to the service. # # @param status # Defines the status of the service. If set to `enabled`, the service is # started and will be enabled at boot time. If set to `disabled`, the # service is stopped and will not be started at boot time. If set to `running`, # the service is started but will not be enabled at boot time. You may use # this to start a service on the first Puppet run instead of the system startup. # If set to `unmanaged`, the service will not be started at boot time and Puppet # does not care whether the service is running or not. For example, this may # be useful if a cluster management software is used to decide when to start # the service plus assuring it is running on the desired node. # # @author Richard Pijnenburg # @author Tyler Langlois # @author Gavin Williams # class elasticsearch::service { #### Service management if $::elasticsearch::ensure == 'present' { case $::elasticsearch::status { # make sure service is currently running, start it on boot 'enabled': { $_service_ensure = 'running' $_service_enable = true } # make sure service is currently stopped, do not start it on boot 'disabled': { $_service_ensure = 'stopped' $_service_enable = false } # make sure service is currently running, do not start it on boot 'running': { $_service_ensure = 'running' $_service_enable = false } # do not start service on boot, do not care whether currently running # or not 'unmanaged': { $_service_ensure = undef $_service_enable = false } default: { } } } else { # make sure the service is stopped and disabled (the removal itself will be # done by package.pp) $_service_ensure = 'stopped' $_service_enable = false } - # TODO: Flesh this out - $_service_require = undef + # # TODO: Flesh this out + # $_service_require = undef - case $::elasticsearch::service_provider { - 'init': { - include elasticsearch::service::init - $_service_provider = undef - } - 'openbsd': { - include elasticsearch::service::openbsd - $_service_provider = undef - } - 'openrc': { - include elasticsearch::service::openrc - $_service_provider = undef - } - 'systemd': { - # include elasticsearch::service::systemd - $_service_provider = 'systemd' - } - default: { - fail("Unknown service provider ${::elasticsearch::service_provider}") - } - } + # case $::elasticsearch::service_provider { + # 'init': { + + # $_service_provider = undef + # } + # 'openbsd': { + # # include elasticsearch::service::openbsd + # $_service_provider = undef + # } + # 'openrc': { + # # include elasticsearch::service::openrc + # $_service_provider = undef + # } + # 'systemd': { + # # include elasticsearch::service::systemd + # $_service_provider = 'systemd' + # } + # default: { + # fail("Unknown service provider ${::elasticsearch::service_provider}") + # } + # } service { $::elasticsearch::service_name: - ensure => $_service_ensure, - enable => $_service_enable, - provider => $_service_provider, - require => $_service_require, + ensure => $_service_ensure, + enable => $_service_enable, + # provider => $_service_provider, + require => $_service_require, } } diff --git a/templates/etc/sysconfig/defaults.erb b/templates/etc/sysconfig/defaults.erb index 0f16a88..29cd20c 100644 --- a/templates/etc/sysconfig/defaults.erb +++ b/templates/etc/sysconfig/defaults.erb @@ -1,6 +1,6 @@ -<%- unless @new_init_defaults.key? 'CONF_FILE' -%> +<%- unless scope['elasticsearch::config::init_defaults'].key? 'CONF_FILE' -%> rm CONF_FILE <%- end -%> -<% @new_init_defaults.sort.map do |key, value| -%> +<% scope['elasticsearch::config::init_defaults'].sort.map do |key, value| -%> set <%= key %> '<%= value %>' <% end -%>