diff --git a/manifests/config.pp b/manifests/config.pp index 89ada497..69ac5038 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,12 @@ owner => $::redis::service_user, } - if $::redis::ulimit { - contain ::redis::ulimit + if $::redis::default_install { + redis::instance {'default':} } - 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..2c1d8d1b --- /dev/null +++ b/manifests/instance.pp @@ -0,0 +1,154 @@ +# 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 first The first parameter for this class +# @param second The second paramter for this class +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, + $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, + $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, +) { + + if $title == 'default' { + $redis_file_name_orig = $config_file_orig + $redis_file_name = $config_file + } else { + $redis_config_extension = ".${title}" + $instance_init_file = "/etc/init.d/${title}" + $redis_file_name_orig = "${config_file_orig}${redis_config_extension}" + $redis_file_name = "${config_file}${redis_config_extension}" + + file { $instance_init_file: + ensure => file, + mode => '0755', + content => template('redis/redis.init.erb'), + subscribe => Exec["cp -p ${redis_file_name_orig} ${redis_file_name}"], + } + + ~> service { $title: + ensure => $service_ensure, + hasrestart => $service_hasrestart, + hasstatus => $service_hasstatus, + } + } + + File { + owner => $config_owner, + group => $config_group, + mode => $config_file_mode, + } + + file {$redis_file_name_orig: + ensure => file, + } + + $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) } + } + + exec {"cp -p ${redis_file_name_orig} ${redis_file_name}": + path => '/usr/bin:/bin', + subscribe => File[$redis_file_name_orig], + refreshonly => true; + } + +} diff --git a/manifests/params.pp b/manifests/params.pp index 06ad2bc0..a4fd4a5e 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 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..e1a6381a --- /dev/null +++ b/spec/acceptance/redis_multi_instances_one_host_spec.rb @@ -0,0 +1,72 @@ +require 'spec_helper_acceptance' + +describe 'redis::instance', :if => (fact('operatingsystem') == 'Ubuntu') 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', + pid_file => '/var/run/redis/redis-server-redis1.pid', + } + + redis::instance {'redis2': + port => '8888', + pid_file => '/var/run/redis/redis-server-redis2.pid', + } + + 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..21f66152 --- /dev/null +++ b/spec/defines/instance_spec.rb @@ -0,0 +1,23 @@ +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 RedHat based systems" 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 + end +end diff --git a/templates/redis.init.erb b/templates/redis.init.erb new file mode 100644 index 00000000..64c98cda --- /dev/null +++ b/templates/redis.init.erb @@ -0,0 +1,95 @@ +#! /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 + +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/redis.service.erb b/templates/redis.service.erb new file mode 100644 index 00000000..e0e86734 --- /dev/null +++ b/templates/redis.service.erb @@ -0,0 +1,34 @@ +[Unit] +Description=Advanced key-value store - Instance <%= @name %> +After=network.target +Documentation=http://redis.io/documentation, man:redis-server(1) + +[Service] +Type=forking +ExecStart=/usr/bin/redis-server <%= @redis_config_file_path %> +PIDFile=/var/run/redis/<%= @name %>.pid +TimeoutStopSec=0 +Restart=always +User=redis +Group=redis + +RuntimeDirectory=redis + +PrivateTmp=yes +LimitNOFILE=65535 +PrivateDevices=yes +ProtectHome=yes +ReadOnlyDirectories=/ +ReadWriteDirectories=-/var/lib/redis +ReadWriteDirectories=-/var/log/redis +ReadWriteDirectories=-/var/run/redis +CapabilityBoundingSet=~CAP_SYS_PTRACE + +# redis-server writes its own config file when in cluster mode so we allow +# writing there (NB. ProtectSystem=true over ProtectSystem=full) +ProtectSystem=true +ReadWriteDirectories=-/etc/redis + +[Install] +WantedBy=multi-user.target +Alias=<%= @name %>.service