From 4dc081f97ff743d68c8bd1cb89dc5f600607471c Mon Sep 17 00:00:00 2001 From: Peter Souter Date: Fri, 7 Jul 2017 13:26:52 +0100 Subject: [PATCH] Adds defined type for mult-instancing (#200) * Move the config logic into a defined type * This will allow us to have multiple instances of redis on one machine * Example code: ``` # Install redis package class { '::redis': default_install => false, } redis::instance {'redis1': port => '7777', } redis::instance {'redis2': port => '8888', } ``` --- manifests/config.pp | 99 +----- manifests/init.pp | 2 + manifests/instance.pp | 297 ++++++++++++++++++ manifests/params.pp | 2 + .../redis_multi_instances_one_host_spec.rb | 71 +++++ spec/defines/instance_spec.rb | 56 ++++ spec/spec_helper.rb | 18 ++ templates/service_templates/redis.Debian.erb | 101 ++++++ templates/service_templates/redis.RedHat.erb | 104 ++++++ templates/service_templates/redis.service.erb | 14 + 10 files changed, 672 insertions(+), 92 deletions(-) create mode 100644 manifests/instance.pp create mode 100644 spec/acceptance/redis_multi_instances_one_host_spec.rb create mode 100644 spec/defines/instance_spec.rb create mode 100644 templates/service_templates/redis.Debian.erb create mode 100644 templates/service_templates/redis.RedHat.erb create mode 100644 templates/service_templates/redis.service.erb diff --git a/manifests/config.pp b/manifests/config.pp index 89ada497..4e1d21ac 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -3,70 +3,6 @@ # This class provides configuration for Redis. # class redis::config { - $activerehashing = $::redis::activerehashing - $aof_load_truncated = $::redis::aof_load_truncated - $aof_rewrite_incremental_fsync = $::redis::aof_rewrite_incremental_fsync - $appendfilename = $::redis::appendfilename - $appendfsync = $::redis::appendfsync - $appendonly = $::redis::appendonly - $auto_aof_rewrite_min_size = $::redis::auto_aof_rewrite_min_size - $auto_aof_rewrite_percentage = $::redis::auto_aof_rewrite_percentage - $bind = $::redis::bind - $cluster_config_file = $::redis::cluster_config_file - $cluster_enabled = $::redis::cluster_enabled - $cluster_node_timeout = $::redis::cluster_node_timeout - $daemonize = $::redis::daemonize - $databases = $::redis::databases - $dbfilename = $::redis::dbfilename - $extra_config_file = $::redis::extra_config_file - $hash_max_ziplist_entries = $::redis::hash_max_ziplist_entries - $hash_max_ziplist_value = $::redis::hash_max_ziplist_value - $hll_sparse_max_bytes = $::redis::hll_sparse_max_bytes - $hz = $::redis::hz - $latency_monitor_threshold = $::redis::latency_monitor_threshold - $list_max_ziplist_entries = $::redis::list_max_ziplist_entries - $list_max_ziplist_value = $::redis::list_max_ziplist_value - $log_file = $::redis::log_file - $log_level = $::redis::log_level - $masterauth = $::redis::masterauth - $maxclients = $::redis::maxclients - $maxmemory = $::redis::maxmemory - $maxmemory_policy = $::redis::maxmemory_policy - $maxmemory_samples = $::redis::maxmemory_samples - $min_slaves_max_lag = $::redis::min_slaves_max_lag - $min_slaves_to_write = $::redis::min_slaves_to_write - $minimum_version = $::redis::minimum_version - $no_appendfsync_on_rewrite = $::redis::no_appendfsync_on_rewrite - $notify_keyspace_events = $::redis::notify_keyspace_events - $pid_file = $::redis::pid_file - $port = $::redis::port - $rdbcompression = $::redis::rdbcompression - $repl_backlog_size = $::redis::repl_backlog_size - $repl_backlog_ttl = $::redis::repl_backlog_ttl - $repl_disable_tcp_nodelay = $::redis::repl_disable_tcp_nodelay - $repl_ping_slave_period = $::redis::repl_ping_slave_period - $repl_timeout = $::redis::repl_timeout - $requirepass = $::redis::requirepass - $save_db_to_disk = $::redis::save_db_to_disk - $save_db_to_disk_interval = $::redis::save_db_to_disk_interval - $set_max_intset_entries = $::redis::set_max_intset_entries - $slave_priority = $::redis::slave_priority - $slave_read_only = $::redis::slave_read_only - $slave_serve_stale_data = $::redis::slave_serve_stale_data - $slaveof = $::redis::slaveof - $slowlog_log_slower_than = $::redis::slowlog_log_slower_than - $slowlog_max_len = $::redis::slowlog_max_len - $stop_writes_on_bgsave_error = $::redis::stop_writes_on_bgsave_error - $syslog_enabled = $::redis::syslog_enabled - $syslog_facility = $::redis::syslog_facility - $tcp_backlog = $::redis::tcp_backlog - $tcp_keepalive = $::redis::tcp_keepalive - $timeout = $::redis::timeout - $unixsocket = $::redis::unixsocket - $unixsocketperm = $::redis::unixsocketperm - $workdir = $::redis::workdir - $zset_max_ziplist_entries = $::redis::zset_max_ziplist_entries - $zset_max_ziplist_value = $::redis::zset_max_ziplist_value File { owner => $::redis::config_owner, @@ -79,28 +15,6 @@ mode => $::redis::config_dir_mode, } - file {$::redis::config_file_orig: - ensure => file, - } - - $redis_version_real = pick(getvar_emptystring('redis_server_version'), $minimum_version) - - if ($redis_version_real and $::redis::conf_template == 'redis/redis.conf.erb') { - case $redis_version_real { - /^2.4./: { - File[$::redis::config_file_orig] { content => template('redis/redis.conf.2.4.10.erb') } - } - /^2.8./: { - File[$::redis::config_file_orig] { content => template('redis/redis.conf.2.8.erb') } - } - default: { - File[$::redis::config_file_orig] { content => template($::redis::conf_template) } - } - } - } else { - File[$::redis::config_file_orig] { content => template($::redis::conf_template) } - } - file {$::redis::log_dir: ensure => directory, group => $::redis::service_group, @@ -115,14 +29,15 @@ owner => $::redis::service_user, } - if $::redis::ulimit { - contain ::redis::ulimit + if $::redis::default_install { + redis::instance {'default': + pid_file => $::redis::pid_file, + manage_service_file => $::redis::manage_service_file, + } } - exec {"cp -p ${::redis::config_file_orig} ${::redis::config_file}": - path => '/usr/bin:/bin', - subscribe => File[$::redis::config_file_orig], - refreshonly => true; + if $::redis::ulimit { + contain ::redis::ulimit } # Adjust /etc/default/redis-server on Debian systems diff --git a/manifests/init.pp b/manifests/init.pp index 0d19023a..fed6a06e 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -27,6 +27,7 @@ # @param [String] config_owner Adjust filesystem owner for config files. # @param [String] conf_template Define which template to use. # @param [String] daemonize Have Redis run as a daemon. +# @param [String] default_install Configure a default install of redis # @param [String] databases Set the number of databases. # @param [String] dbfilename The filename where to dump the DB # @param [String] extra_config_file Description @@ -152,6 +153,7 @@ $config_owner = $::redis::params::config_owner, $daemonize = $::redis::params::daemonize, $databases = $::redis::params::databases, + $default_install = $::redis::params::default_install, $dbfilename = $::redis::params::dbfilename, $extra_config_file = $::redis::params::extra_config_file, $hash_max_ziplist_entries = $::redis::params::hash_max_ziplist_entries, diff --git a/manifests/instance.pp b/manifests/instance.pp new file mode 100644 index 00000000..68455bcd --- /dev/null +++ b/manifests/instance.pp @@ -0,0 +1,297 @@ +# redis::instance +# +# This is an defined type to allow the configuration of +# multiple redis instances on one machine without conflicts +# +# @summary Allows the configuration of multiple redis configurations on one machine +# +# @example +# redis::instance {'6380': +# port => '6380', +# } +# +# @param [String] activerehashing Enable/disable active rehashing. +# @param [String] aof_load_truncated Enable/disable loading truncated AOF file +# @param [String] aof_rewrite_incremental_fsync Enable/disable fsync for AOF file +# @param [String] appendfilename The name of the append only file +# @param [String] appendfsync Adjust fsync mode. Valid options: always, everysec, no. Default: everysec +# @param [String] appendonly Enable/disable appendonly mode. +# @param [String] auto_aof_rewrite_min_size Adjust minimum size for auto-aof-rewrite. +# @param [String] auto_aof_rewrite_percentage Adjust percentatge for auto-aof-rewrite. +# @param [String] bind Configure which IP address to listen on. +# @param [String] config_dir Directory containing the configuration files. +# @param [String] config_dir_mode Adjust mode for directory containing configuration files. +# @param [String] config_file_orig The location and name of a config file that provides the source +# @param [String] config_file Adjust main configuration file. +# @param [String] config_file_mode Adjust permissions for configuration files. +# @param [String] config_group Adjust filesystem group for config files. +# @param [String] config_owner Adjust filesystem owner for config files. +# @param [String] conf_template Define which template to use. +# @param [String] daemonize Have Redis run as a daemon. +# @param [String] databases Set the number of databases. +# @param [String] dbfilename The filename where to dump the DB +# @param [String] extra_config_file Description +# @param [String] hash_max_ziplist_entries Set max ziplist entries for hashes. +# @param [String] hash_max_ziplist_value Set max ziplist values for hashes. +# @param [String] hll_sparse_max_bytes HyperLogLog sparse representation bytes limit +# @param [String] hz Set redis background tasks frequency +# @param [String] latency_monitor_threshold Latency monitoring threshold in milliseconds +# @param [String] list_max_ziplist_entries Set max ziplist entries for lists. +# @param [String] list_max_ziplist_value Set max ziplist values for lists. +# @param [String] log_file Specify file where to write log entries. +# @param [String] log_level Specify the server verbosity level. +# @param [String] masterauth If the master is password protected (using the "requirepass" configuration +# @param [String] maxclients Set the max number of connected clients at the same time. +# @param [String] maxmemory Don't use more memory than the specified amount of bytes. +# @param [String] maxmemory_policy How Redis will select what to remove when maxmemory is reached. +# @param [String] maxmemory_samples Select as well the sample size to check. +# @param [String] min_slaves_max_lag The lag in seconds +# @param [String] min_slaves_to_write Minimum number of slaves to be in "online" state +# @param [String] no_appendfsync_on_rewrite If you have latency problems turn this to 'true'. Otherwise leave it as +# @param [String] notify_keyspace_events Which events to notify Pub/Sub clients about events happening +# @param [String] pid_file Where to store the pid. +# @param [String] port Configure which port to listen on. +# @param [String] rdbcompression Enable/disable compression of string objects using LZF when dumping. +# @param [String] repl_backlog_size The replication backlog size +# @param [String] repl_backlog_ttl The number of seconds to elapse before freeing backlog buffer +# @param [String] repl_disable_tcp_nodelay Enable/disable TCP_NODELAY on the slave socket after SYNC +# @param [String] repl_ping_slave_period Slaves send PINGs to server in a predefined interval. It's possible +# @param [String] repl_timeout Set the replication timeout for: +# @param [String] requirepass Require clients to issue AUTH before processing any +# other commands. +# @param [String] save_db_to_disk Set if save db to disk. +# @param [String] save_db_to_disk_interval save the dataset every N seconds if there are at least M changes in the dataset +# @param [String] service_enable Enable/disable daemon at boot. +# @param [String] service_ensure Specify if the server should be running. +# @param [String] service_hasrestart Does the init script support restart? +# @param [String] service_hasstatus Does the init script support status? +# @param [String] service_user Specify which user to run as. +# @param [String] set_max_intset_entries The following configuration setting sets the limit in the size of the +# set in order to use this special memory saving encoding. +# Default: 512 +# @param [String] slave_priority The priority number for slave promotion by Sentinel +# @param [String] slave_read_only You can configure a slave instance to accept writes or not. +# @param [String] slave_serve_stale_data When a slave loses its connection with the master, or when the replication +# is still in progress, the slave can act in two different ways: +# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will +# still reply to client requests, possibly with out of date data, or the +# data set may just be empty if this is the first synchronization. +# +# 2) if slave-serve-stale-data is set to 'no' the slave will reply with +# an error "SYNC with master in progress" to all the kind of commands +# but to INFO and SLAVEOF. +# +# Default: true +# +# @param [String] slaveof Use slaveof to make a Redis instance a copy of another Redis server. +# @param [String] slowlog_log_slower_than Tells Redis what is the execution time, in microseconds, to exceed +# in order for the command to get logged. +# Default: 10000 +# +# @param [String] slowlog_max_len Tells Redis what is the length to exceed in order for the command +# to get logged. +# Default: 1024 +# +# @param [String] stop_writes_on_bgsave_error If false then Redis will continue to work as usual even if there +# are problems with disk, permissions, and so forth. +# Default: true +# +# @param [String] syslog_enabled Enable/disable logging to the system logger. +# @param [String] syslog_facility Specify the syslog facility. +# Must be USER or between LOCAL0-LOCAL7. +# Default: undef +# +# @param [String] tcp_backlog Sets the TCP backlog +# @param [String] tcp_keepalive TCP keepalive. +# @param [String] timeout Close the connection after a client is idle for N seconds (0 to disable). +# @param [String] ulimit Limit the use of system-wide resources. +# @param [String] unixsocket Define unix socket path +# @param [String] unixsocketperm Define unix socket file permissions +# @param [String] workdir The DB will be written inside this directory, with the filename specified +# above using the 'dbfilename' configuration directive. +# Default: /var/lib/redis/ +# @param [String] zset_max_ziplist_entries Set max entries for sorted sets. +# @param [String] zset_max_ziplist_value Set max values for sorted sets. +# @param [String] cluster_enabled Enables redis 3.0 cluster functionality +# @param [String] cluster_config_file Config file for saving cluster nodes configuration. This file is never touched by humans. +# Only set if cluster_enabled is true +# Default: nodes.conf +# @param [String] cluster_node_timeout Node timeout +# Only set if cluster_enabled is true +# Default: 5000 +define redis::instance( + $activerehashing = $::redis::activerehashing, + $aof_load_truncated = $::redis::aof_load_truncated, + $aof_rewrite_incremental_fsync = $::redis::aof_rewrite_incremental_fsync, + $appendfilename = $::redis::appendfilename, + $appendfsync = $::redis::appendfsync, + $appendonly = $::redis::appendonly, + $auto_aof_rewrite_min_size = $::redis::auto_aof_rewrite_min_size, + $auto_aof_rewrite_percentage = $::redis::auto_aof_rewrite_percentage, + $bind = $::redis::bind, + $conf_template = $::redis::conf_template, + $config_dir = $::redis::config_dir, + $config_dir_mode = $::redis::config_dir_mode, + $config_file = $::redis::config_file, + $config_file_mode = $::redis::config_file_mode, + $config_file_orig = $::redis::config_file_orig, + $config_group = $::redis::config_group, + $config_owner = $::redis::config_owner, + $daemonize = $::redis::daemonize, + $databases = $::redis::databases, + $dbfilename = $::redis::dbfilename, + $extra_config_file = $::redis::extra_config_file, + $hash_max_ziplist_entries = $::redis::hash_max_ziplist_entries, + $hash_max_ziplist_value = $::redis::hash_max_ziplist_value, + $hll_sparse_max_bytes = $::redis::hll_sparse_max_bytes, + $hz = $::redis::hz, + $latency_monitor_threshold = $::redis::latency_monitor_threshold, + $list_max_ziplist_entries = $::redis::list_max_ziplist_entries, + $list_max_ziplist_value = $::redis::list_max_ziplist_value, + $log_file = $::redis::log_file, + $log_level = $::redis::log_level, + $minimum_version = $::redis::minimum_version, + $masterauth = $::redis::masterauth, + $maxclients = $::redis::maxclients, + $maxmemory = $::redis::maxmemory, + $maxmemory_policy = $::redis::maxmemory_policy, + $maxmemory_samples = $::redis::maxmemory_samples, + $min_slaves_max_lag = $::redis::min_slaves_max_lag, + $min_slaves_to_write = $::redis::min_slaves_to_write, + $no_appendfsync_on_rewrite = $::redis::no_appendfsync_on_rewrite, + $notify_keyspace_events = $::redis::notify_keyspace_events, + $managed_by_cluster_manager = $::redis::managed_by_cluster_manager, + $port = $::redis::port, + $rdbcompression = $::redis::rdbcompression, + $repl_backlog_size = $::redis::repl_backlog_size, + $repl_backlog_ttl = $::redis::repl_backlog_ttl, + $repl_disable_tcp_nodelay = $::redis::repl_disable_tcp_nodelay, + $repl_ping_slave_period = $::redis::repl_ping_slave_period, + $repl_timeout = $::redis::repl_timeout, + $requirepass = $::redis::requirepass, + $save_db_to_disk = $::redis::save_db_to_disk, + $save_db_to_disk_interval = $::redis::save_db_to_disk_interval, + $service_user = $::redis::service_user, + $set_max_intset_entries = $::redis::set_max_intset_entries, + $slave_priority = $::redis::slave_priority, + $slave_read_only = $::redis::slave_read_only, + $slave_serve_stale_data = $::redis::slave_serve_stale_data, + $slaveof = $::redis::slaveof, + $slowlog_log_slower_than = $::redis::slowlog_log_slower_than, + $slowlog_max_len = $::redis::slowlog_max_len, + $stop_writes_on_bgsave_error = $::redis::stop_writes_on_bgsave_error, + $syslog_enabled = $::redis::syslog_enabled, + $syslog_facility = $::redis::syslog_facility, + $tcp_backlog = $::redis::tcp_backlog, + $tcp_keepalive = $::redis::tcp_keepalive, + $timeout = $::redis::timeout, + $unixsocket = $::redis::unixsocket, + $unixsocketperm = $::redis::unixsocketperm, + $ulimit = $::redis::ulimit, + $zset_max_ziplist_entries = $::redis::zset_max_ziplist_entries, + $zset_max_ziplist_value = $::redis::zset_max_ziplist_value, + $cluster_enabled = $::redis::cluster_enabled, + $cluster_config_file = $::redis::cluster_config_file, + $cluster_node_timeout = $::redis::cluster_node_timeout, + $workdir = $::redis::workdir, + $service_ensure = $::redis::service_ensure, + $service_enable = $::redis::service_enable, + $service_hasrestart = $::redis::service_hasrestart, + $service_hasstatus = $::redis::service_hasstatus, + # Defaults for redis::instance + $manage_service_file = true, + $pid_file = "/var/run/redis/redis-server-${name}.pid", +) { + + if $title == 'default' { + $redis_file_name_orig = $config_file_orig + $redis_file_name = $config_file + } else { + $redis_config_extension = ".${title}" + $redis_file_name_orig = "${config_file_orig}${redis_config_extension}" + $redis_file_name = "${config_file}${redis_config_extension}" + } + + if $manage_service_file { + $service_provider_lookup = pick(getvar_emptystring('service_provider'), false) + + if $service_provider_lookup == 'systemd' { + + file { "/etc/systemd/system/${title}.service": + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => template('redis/service_templates/redis.service.erb'), + } + ~> Exec['systemd-reload-redis'] + + if $title != 'default' { + service { $title: + ensure => $service_ensure, + hasrestart => $service_hasrestart, + hasstatus => $service_hasstatus, + subscribe => [ + File["/etc/systemd/system/${title}.service"], + Exec["cp -p ${redis_file_name_orig} ${redis_file_name}"], + ], + } + } + + } else { + + file { "/etc/init.d/${title}": + ensure => file, + mode => '0755', + content => template("redis/service_templates/redis.${::osfamily}.erb"), + } + + if $title != 'default' { + service { $title: + ensure => $service_ensure, + hasrestart => $service_hasrestart, + hasstatus => $service_hasstatus, + subscribe => [ + File["/etc/init.d/${title}"], + Exec["cp -p ${redis_file_name_orig} ${redis_file_name}"], + ], + } + } + } + } + + File { + owner => $config_owner, + group => $config_group, + mode => $config_file_mode, + } + + file {$redis_file_name_orig: + ensure => file, + } + + exec {"cp -p ${redis_file_name_orig} ${redis_file_name}": + path => '/usr/bin:/bin', + subscribe => File[$redis_file_name_orig], + refreshonly => true, + } + + $redis_version_real = pick(getvar_emptystring('redis_server_version'), $minimum_version) + + if ($redis_version_real and $conf_template == 'redis/redis.conf.erb') { + case $redis_version_real { + /^2.4./: { + File[$redis_file_name_orig] { content => template('redis/redis.conf.2.4.10.erb') } + } + /^2.8./: { + File[$redis_file_name_orig] { content => template('redis/redis.conf.2.8.erb') } + } + default: { + File[$redis_file_name_orig] { content => template($conf_template) } + } + } + } else { + File[$redis_file_name_orig] { content => template($conf_template) } + } + +} diff --git a/manifests/params.pp b/manifests/params.pp index 06ad2bc0..2a852415 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -19,6 +19,7 @@ $auto_aof_rewrite_percentage = 100 $bind = '127.0.0.1' $conf_template = 'redis/redis.conf.erb' + $default_install = true $databases = 16 $dbfilename = 'dump.rdb' $extra_config_file = undef @@ -32,6 +33,7 @@ $log_dir = '/var/log/redis' $log_file = '/var/log/redis/redis.log' $log_level = 'notice' + $manage_service_file = false $maxclients = 10000 $maxmemory = undef $maxmemory_policy = undef diff --git a/spec/acceptance/redis_multi_instances_one_host_spec.rb b/spec/acceptance/redis_multi_instances_one_host_spec.rb new file mode 100644 index 00000000..4b870e57 --- /dev/null +++ b/spec/acceptance/redis_multi_instances_one_host_spec.rb @@ -0,0 +1,71 @@ +require 'spec_helper_acceptance' + +# Cant get this to work on Debian, add exception for now +describe 'redis::instance', :unless => (fact('operatingsystem') == 'Debian') do + case fact('osfamily') + when 'Debian' + config_path = '/etc/redis/redis.conf' + manage_repo = false + redis_name = 'redis-server' + else + redis_name = 'redis' + config_path = '/etc/redis.conf' + manage_repo = true + end + + it 'should run successfully' do + pp = <<-EOS + Exec { + path => [ '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', ] + } + + class { '::redis': + manage_repo => #{manage_repo}, + default_install => false, + } + + redis::instance {'redis1': + port => '7777', + } + + redis::instance {'redis2': + port => '8888', + } + + EOS + + # Apply twice to ensure no errors the second time. + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe package(redis_name) do + it { should be_installed } + end + + describe service('redis1') do + it { should be_running } + end + + describe service('redis2') do + it { should be_running } + end + + describe file("#{config_path}.redis1") do + its(:content) { should match /port 7777/ } + end + + describe file("#{config_path}.redis2") do + its(:content) { should match /port 8888/ } + end + + context 'redis should respond to ping command' do + describe command('redis-cli -h 127.0.0.1 -p 7777 ping') do + its(:stdout) { should match /PONG/ } + end + + describe command('redis-cli -h 127.0.0.1 -p 8888 ping') do + its(:stdout) { should match /PONG/ } + end + end +end diff --git a/spec/defines/instance_spec.rb b/spec/defines/instance_spec.rb new file mode 100644 index 00000000..2c87f4d9 --- /dev/null +++ b/spec/defines/instance_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' + +describe 'redis::instance', :type => :define do + let :pre_condition do + 'class { "redis": + default_install => false, + }' + end + let :title do + 'redis2' + end + describe 'os-dependent items' do + context "on Ubuntu systems" do + context '14.04' do + let(:facts) { + ubuntu_1404_facts + } + it { should contain_file('/etc/redis/redis.conf.puppet.redis2').with('content' => /^bind 127.0.0.1/) } + it { should contain_service('redis2').with_ensure('running') } + it { should contain_file('/etc/init.d/redis2').with_content(/DAEMON_ARGS=\/etc\/redis\/redis.conf.redis2/) } + it { should contain_file('/etc/init.d/redis2').with_content(/PIDFILE=\/var\/run\/redis\/redis-server-redis2.pid/) } + end + context '16.04' do + let(:facts) { + ubuntu_1604_facts.merge({ + :service_provider => 'systemd', + }) + } + it { should contain_file('/etc/redis/redis.conf.puppet.redis2').with('content' => /^bind 127.0.0.1/) } + it { should contain_service('redis2').with_ensure('running') } + it { should contain_file('/etc/systemd/system/redis2.service').with_content(/ExecStart=\/usr\/bin\/redis-server \/etc\/redis\/redis.conf.redis2/) } + end + end + context "on CentOS systems" do + context '6' do + let(:facts) { + centos_6_facts + } + it { should contain_file('/etc/redis.conf.puppet.redis2').with('content' => /^bind 127.0.0.1/) } + it { should contain_service('redis2').with_ensure('running') } + it { should contain_file('/etc/init.d/redis2').with_content(/REDIS_CONFIG="\/etc\/redis.conf.redis2"/) } + it { should contain_file('/etc/init.d/redis2').with_content(/pidfile="\/var\/run\/redis\/redis-server-redis2.pid"/) } + end + context '7' do + let(:facts) { + centos_7_facts.merge({ + :service_provider => 'systemd', + }) + } + it { should contain_file('/etc/redis.conf.puppet.redis2').with('content' => /^bind 127.0.0.1/) } + it { should contain_service('redis2').with_ensure('running') } + it { should contain_file('/etc/systemd/system/redis2.service').with_content(/ExecStart=\/usr\/bin\/redis-server \/etc\/redis.conf.redis2/) } + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index aef50bdf..2e1c7325 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -111,6 +111,15 @@ def centos_6_facts } end +def centos_7_facts + { + :operatingsystem => 'CentOS', + :osfamily => 'RedHat', + :operatingsystemmajrelease => '7', + :puppetversion => '4.5.2', + } +end + def ubuntu_1404_facts { :operatingsystem => 'Ubuntu', @@ -120,6 +129,15 @@ def ubuntu_1404_facts } end +def ubuntu_1604_facts + { + :operatingsystem => 'Ubuntu', + :osfamily => 'Debian', + :operatingsystemmajrelease => '16.04', + :puppetversion => '4.5.2' + } +end + def archlinux_facts { :operatingsystem => 'Archlinux', diff --git a/templates/service_templates/redis.Debian.erb b/templates/service_templates/redis.Debian.erb new file mode 100644 index 00000000..118abf3b --- /dev/null +++ b/templates/service_templates/redis.Debian.erb @@ -0,0 +1,101 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: redis-server +# Required-Start: $syslog $remote_fs +# Required-Stop: $syslog $remote_fs +# Should-Start: $local_fs +# Should-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: redis-server - Persistent key-value db +# Description: redis-server - Persistent key-value db +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/redis-server +DAEMON_ARGS=<%= @redis_file_name %> +NAME=redis-server-<%= @name %> +DESC=redis-server-<%= @name %> + +RUNDIR=/var/run/redis +PIDFILE=/var/run/redis/redis-server-<%= @name %>.pid + +test -x $DAEMON || exit 0 + +if [ -r /etc/default/$NAME ] +then + . /etc/default/$NAME +fi + +. /lib/lsb/init-functions + +set -e + +if [ "$(id -u)" != "0" ] +then + log_failure_msg "Must be run as root." + exit 1 +fi + +Run_parts () { + if [ -d /etc/redis/${NAME}.${1}.d ] + then + su redis -s /bin/sh -c "run-parts --exit-on-error /etc/redis/${NAME}.${1}.d" + fi +} + +case "$1" in + start) + echo -n "Starting $DESC: " + mkdir -p $RUNDIR + touch $PIDFILE + chown redis:redis $RUNDIR $PIDFILE + chmod 755 $RUNDIR + + if [ -n "$ULIMIT" ] + then + ulimit -n $ULIMIT + fi + + Run_parts pre-up + + if start-stop-daemon --start --quiet --oknodo --umask 007 --pidfile $PIDFILE --chuid redis:redis --exec $DAEMON -- $DAEMON_ARGS + then + Run_parts post-up + echo "$NAME." + else + echo "failed" + fi + ;; + stop) + echo -n "Stopping $DESC: " + + Run_parts pre-down + + if start-stop-daemon --stop --retry forever/TERM/1 --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON + then + Run_parts post-down + echo "$NAME." + else + echo "failed" + fi + rm -f $PIDFILE + sleep 1 + ;; + + restart|force-reload) + ${0} stop + ${0} start + ;; + + status) + status_of_proc -p ${PIDFILE} ${DAEMON} ${NAME} + ;; + + *) + echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/templates/service_templates/redis.RedHat.erb b/templates/service_templates/redis.RedHat.erb new file mode 100644 index 00000000..e061bda0 --- /dev/null +++ b/templates/service_templates/redis.RedHat.erb @@ -0,0 +1,104 @@ +#!/bin/sh +# +# redis init file for starting up the redis daemon +# +# chkconfig: - 20 80 +# description: Starts and stops the redis daemon. +# +### BEGIN INIT INFO +# Provides: redis-server-<%= @name %> +# Required-Start: $local_fs $remote_fs $network +# Required-Stop: $local_fs $remote_fs $network +# Short-Description: start and stop Redis server instance <%= @name %> +# Description: A persistent key-value database +### END INIT INFO + +# Source function library. +. /etc/rc.d/init.d/functions + +name="redis-server-<%= @name %>" +exec="/usr/sbin/redis-server" +pidfile="/var/run/redis/redis-server-<%= @name %>.pid" +REDIS_CONFIG="<%= @redis_file_name %>" + +[ -e /etc/sysconfig/redis ] && . /etc/sysconfig/redis + +lockfile=/var/lock/subsys/redis-<%= @name %> + +start() { + [ -f $REDIS_CONFIG ] || exit 6 + [ -x $exec ] || exit 5 + echo -n $"Starting $name: " + daemon --user ${REDIS_USER-redis} "$exec $REDIS_CONFIG" + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + echo -n $"Stopping $name: " + [ -x $shut ] && $shut + retval=$? + if [ -f $pidfile ] + then + # shutdown haven't work, try old way + killproc -p $pidfile $name + retval=$? + else + success "$name shutdown" + fi + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + false +} + +rh_status() { + status -p $pidfile $name +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart}" + exit 2 +esac +exit $? diff --git a/templates/service_templates/redis.service.erb b/templates/service_templates/redis.service.erb new file mode 100644 index 00000000..73acdc0e --- /dev/null +++ b/templates/service_templates/redis.service.erb @@ -0,0 +1,14 @@ +[Unit] +Description=Advanced key-value store +After=network.target + +[Service] +Type=forking +ExecStart=/usr/bin/redis-server <%= @redis_file_name %> +TimeoutStopSec=0 +Restart=always +User=redis +Group=redis + +[Install] +WantedBy=multi-user.target