# == Define: elasticsearch::instance
#
# This define allows you to create or remove an elasticsearch instance
#
# === Parameters
#
# [*ensure*]
# String. Controls if the managed resources shall be <tt>present</tt> or
# <tt>absent</tt>. If set to <tt>absent</tt>:
# * The managed software packages are being uninstalled.
# * Any traces of the packages will be purged as good as possible. This may
# include existing configuration files. The exact behavior is provider
# dependent. Q.v.:
# * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
# * {Puppet's package provider source code}[http://j.mp/wtVCaL]
# * System modifications (if any) will be reverted as good as possible
# (e.g. removal of created users, services, changed log settings, ...).
# * This is thus destructive and should be used with care.
# Defaults to <tt>present</tt>.
#
# [*status*]
# String to define the status of the service. Possible values:
# * <tt>enabled</tt>: Service is running and will be started at boot time.
# * <tt>disabled</tt>: Service is stopped and will not be started at boot
# time.
# * <tt>running</tt>: Service is running but will not be started at boot time.
# You can use this to start a service on the first Puppet run instead of
# the system startup.
# * <tt>unmanaged</tt>: 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.
# Defaults to <tt>enabled</tt>. The singular form ("service") is used for the
# sake of convenience. Of course, the defined status affects all services if
# more than one is managed (see <tt>service.pp</tt> to check if this is the
# case).
#
# [*config*]
# Elasticsearch configuration hash
#
# [*configdir*]
# Path to directory containing the elasticsearch configuration.
# Use this setting if your packages deviate from the norm (/etc/elasticsearch)
#
# [*datadir*]
# Allows you to set the data directory of Elasticsearch
#
# [*logging_file*]
# Instead of a hash you can supply a puppet:// file source for the logging.yml file
#
# [*logging_config*]
# Hash representation of information you want in the logging.yml file
#
# [*logging_template*]
# Use a custom logging template - just supply the reative path ie ${module}/elasticsearch/logging.yml.erb
#
# [*logging_level*]
# Default logging level for Elasticsearch.
# Defaults to: INFO
#
# [*init_defaults*]
# Defaults file content in hash representation
#
# [*init_defaults_file*]
# Defaults file as puppet resource
#
# [*service_flags*]
# Service flags used for the OpenBSD service configuration, defaults to undef.
#
# [*init_template*]
# Service file as a template
#
# [*logdir*]
# Log directory for this instance.
#
# [*ssl*]
# Whether to manage TLS certificates for Shield. Requires the ca_certificate,
# certificate, private_key and keystore_password parameters to be set.
# Value type is boolean
# Default value: false
#
# [*ca_certificate*]
# Path to the trusted CA certificate to add to this node's java keystore.
# Value type is string
# Default value: undef
#
# [*certificate*]
# Path to the certificate for this node signed by the CA listed in
# ca_certificate.
# Value type is string
# Default value: undef
#
# [*private_key*]
# Path to the key associated with this node's certificate.
# Value type is string
# Default value: undef
#
# [*keystore_password*]
# Password to encrypt this node's Java keystore.
# Value type is string
# Default value: undef
#
# [*keystore_path*]
# Custom path to the java keystore file. This parameter is optional.
# Value type is string
# Default value: undef
#
# [*system_key*]
# Source for the Shield system key. Valid values are any that are
# supported for the file resource `source` parameter.
# Value type is string
# Default value: undef
#
# [*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.
# Value type is string
# Default value: dailyRollingFile
#
# [*daily_rolling_date_pattern*]
# File pattern for the file appender log when file_rolling_type is 'dailyRollingFile'
# Value type is string
# Default value: "'.'yyyy-MM-dd"
#
# [*rolling_file_max_backup_index*]
# Max number of logs to store whern file_rolling_type is 'rollingFile'
# Value type is integer
# Default value: 1
#
# [*rolling_file_max_file_size*]
# Max log file size when file_rolling_type is 'rollingFile'
# Value type is string
# Default value: 10MB
#
# === Authors
#
# * Tyler Langlois <mailto:tyler@elastic.co>
# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
#
define elasticsearch::instance(
$ensure = $elasticsearch::ensure,
$status = $elasticsearch::status,
$config = undef,
$configdir = undef,
$datadir = undef,
$logdir = undef,
$logging_file = undef,
$logging_config = undef,
$logging_template = undef,
$logging_level = $elasticsearch::default_logging_level,
$service_flags = undef,
$init_defaults = undef,
$init_defaults_file = undef,
$init_template = $elasticsearch::init_template,
$ssl = false,
$ca_certificate = undef,
$certificate = undef,
$private_key = undef,
$keystore_password = undef,
$keystore_path = undef,
$system_key = $elasticsearch::system_key,
$file_rolling_type = $elasticsearch::file_rolling_type,
$daily_rolling_date_pattern = $elasticsearch::daily_rolling_date_pattern,
$rolling_file_max_backup_index = $elasticsearch::rolling_file_max_backup_index,
$rolling_file_max_file_size = $elasticsearch::rolling_file_max_file_size,
) {
require elasticsearch::params
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")
}
$notify_service = $elasticsearch::restart_config_change ? {
true => Elasticsearch::Service[$name],
false => undef,
}
# Instance config directory
if ($configdir == undef) {
$instance_configdir = "${elasticsearch::configdir}/${name}"
} else {
$instance_configdir = $configdir
}
if ($ensure == 'present') {
# Configuration hash
if ($config == undef) {
$instance_config = {}
} else {
validate_hash($config)
$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 (is_array($elasticsearch::datadir)) {
$instance_datadir = array_suffix($elasticsearch::datadir, "/${name}")
} else {
$instance_datadir = "${elasticsearch::datadir}/${name}"
}
} else {
$instance_datadir = $datadir
}
# Logging file or hash
if ($logging_file != undef) {
$logging_source = $logging_file
$logging_content = undef
} elsif ($elasticsearch::logging_file != undef) {
$logging_source = $elasticsearch::logging_file
$logging_content = undef
} else {
if(is_hash($elasticsearch::logging_config)) {
$main_logging_config = deep_implode($elasticsearch::logging_config)
} else {
$main_logging_config = { }
}
if(is_hash($logging_config)) {
$instance_logging_config = deep_implode($logging_config)
} else {
$instance_logging_config = { }
}
$logging_hash = merge($elasticsearch::params::logging_defaults, $main_logging_config, $instance_logging_config)
if ($logging_template != undef ) {
$logging_content = template($logging_template)
} elsif ($elasticsearch::logging_template != undef) {
$logging_content = template($elasticsearch::logging_template)
} else {
$logging_content = template("${module_name}/etc/elasticsearch/logging.yml.erb")
}
$logging_source = undef
}
if ($elasticsearch::x_config != undef) {
$main_config = deep_implode($elasticsearch::x_config)
} else {
$main_config = { }
}
$instance_datadir_config = { 'path.data' => $instance_datadir }
if(is_array($instance_datadir)) {
$dirs = join($instance_datadir, ' ')
} else {
$dirs = $instance_datadir
}
# Manage instance log directory
if ($logdir == undef) {
$instance_logdir = "${elasticsearch::logdir}/${name}"
} else {
$instance_logdir = $logdir
}
$instance_logdir_config = { 'path.logs' => $instance_logdir }
validate_bool($ssl)
if $ssl {
validate_absolute_path($ca_certificate, $certificate, $private_key)
validate_string($keystore_password)
if ($keystore_path == undef) {
$_keystore_path = "${instance_configdir}/shield/${name}.ks"
} else {
validate_absolute_path($keystore_path)
$_keystore_path = $keystore_path
}
$tls_config = {
'shield.ssl.keystore.path' => $_keystore_path,
'shield.ssl.keystore.password' => $keystore_password,
'shield.transport.ssl' => true,
'shield.http.ssl' => true,
}
# Trust CA Certificate
java_ks { "elasticsearch_instance_${name}_keystore_ca":
ensure => 'latest',
certificate => $ca_certificate,
target => $_keystore_path,
password => $keystore_password,
trustcacerts => true,
}
# Load node certificate and private key
java_ks { "elasticsearch_instance_${name}_keystore_node":
ensure => 'latest',
certificate => $certificate,
private_key => $private_key,
target => $_keystore_path,
password => $keystore_password,
}
} else { $tls_config = {} }
if $system_key != undef {
validate_string($system_key)
}
exec { "mkdir_logdir_elasticsearch_${name}":
command => "mkdir -p ${instance_logdir}",
creates => $instance_logdir,
require => Class['elasticsearch::package'],
before => File[$instance_logdir],
}
file { $instance_logdir:
ensure => 'directory',
owner => $elasticsearch::elasticsearch_user,
group => undef,
mode => '0644',
require => Class['elasticsearch::package'],
before => Elasticsearch::Service[$name],
}
exec { "mkdir_datadir_elasticsearch_${name}":
command => "mkdir -p ${dirs}",
creates => $instance_datadir,
require => Class['elasticsearch::package'],
before => Elasticsearch::Service[$name],
}
file { $instance_datadir:
ensure => 'directory',
owner => $elasticsearch::elasticsearch_user,
group => undef,
mode => '0644',
require => [ Exec["mkdir_datadir_elasticsearch_${name}"], Class['elasticsearch::package'] ],
before => Elasticsearch::Service[$name],
}
exec { "mkdir_configdir_elasticsearch_${name}":
command => "mkdir -p ${instance_configdir}",
creates => $elasticsearch::configdir,
require => Class['elasticsearch::package'],
before => Elasticsearch::Service[$name],
}
file { $instance_configdir:
ensure => 'directory',
mode => '0644',
purge => $elasticsearch::purge_configdir,
force => $elasticsearch::purge_configdir,
require => [ Exec["mkdir_configdir_elasticsearch_${name}"], Class['elasticsearch::package'] ],
before => Elasticsearch::Service[$name],
}
file { "${instance_configdir}/logging.yml":
ensure => file,
content => $logging_content,
source => $logging_source,
mode => '0644',
notify => $notify_service,
require => Class['elasticsearch::package'],
before => Elasticsearch::Service[$name],
}
file { "${instance_configdir}/scripts":
ensure => 'link',
target => "${elasticsearch::params::homedir}/scripts",
}
file { "${instance_configdir}/shield":
ensure => 'directory',
mode => '0644',
source => "${elasticsearch::params::homedir}/shield",
recurse => 'remote',
owner => 'root',
group => '0',
before => Elasticsearch::Service[$name],
}
if $system_key != undef {
file { "${instance_configdir}/shield/system_key":
ensure => 'file',
source => $system_key,
mode => '0400',
before => Elasticsearch::Service[$name],
require => File["${instance_configdir}/shield"],
}
}
# build up new config
$instance_conf = merge($main_config, $instance_node_name, $instance_config, $instance_datadir_config, $instance_logdir_config, $tls_config)
# defaults file content
# ensure user did not provide both init_defaults and init_defaults_file
if (($init_defaults != undef) and ($init_defaults_file != undef)) {
fail ('Only one of $init_defaults and $init_defaults_file should be defined')
}
if (is_hash($elasticsearch::init_defaults)) {
$global_init_defaults = $elasticsearch::init_defaults
} else {
$global_init_defaults = { }
}
$instance_init_defaults_main = {
'CONF_DIR' => $instance_configdir,
'CONF_FILE' => "${instance_configdir}/elasticsearch.yml",
'LOG_DIR' => $instance_logdir,
'ES_HOME' => '/usr/share/elasticsearch',
}
if (is_hash($init_defaults)) {
$instance_init_defaults = $init_defaults
} else {
$instance_init_defaults = { }
}
$init_defaults_new = merge(
$global_init_defaults,
$instance_init_defaults_main,
$instance_init_defaults
)
$user = $elasticsearch::elasticsearch_user
$group = $elasticsearch::elasticsearch_group
datacat_fragment { "main_config_${name}":
target => "${instance_configdir}/elasticsearch.yml",
data => $instance_conf,
}
datacat { "${instance_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,
}
$require_service = Class['elasticsearch::package']
$before_service = undef
} else {
file { $instance_configdir:
ensure => 'absent',
recurse => true,
force => true,
}
$require_service = undef
$before_service = File[$instance_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,
}
}