From e7979de252c28124b25df4a7451fb7be580a2a5b Mon Sep 17 00:00:00 2001 From: Dan Sajner Date: Wed, 26 Nov 2014 16:59:40 -0500 Subject: [PATCH] Updates to run multiple instances of memcached. --- README.md | 31 ++++++++- manifests/init.pp | 89 ++++++++++-------------- manifests/instance.pp | 120 +++++++++++++++++++++++++++++++++ manifests/package.pp | 21 ++++++ manifests/params.pp | 12 +--- spec/classes/memcached_spec.rb | 23 ++----- templates/memcached.init.erb | 91 +++++++++++++++++++++++++ 7 files changed, 304 insertions(+), 83 deletions(-) create mode 100644 manifests/instance.pp create mode 100644 manifests/package.pp create mode 100755 templates/memcached.init.erb diff --git a/README.md b/README.md index 7218b3e18..fcf02325a 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,38 @@ If you find this module useful, send some bitcoins to 1Na3YFUmdxKxJLiuRXQYJU2kiN } ``` +### Run multiple instances + +Instantiating the class gets you a default instance of memcached. This instance is fully configurable. +```ruby + class { 'memcached': } +``` +You can configure additional instances of memcached with hiera data. +```ruby +memcached::instance_configs: + 'memcached_11222': + tcp_port: 11222 + udp_port: 11222 + max_memory: '12%' +``` +If you choose to configure all instances via hiera data instantiate the class like this. +```ruby + class { 'memcached': + default_instance => false + } +``` +Or if you want to declare the instances in a manifest. +```ruby + memcached::instance { 'memcached_11222': + tcp_port => 11222, + udp_port => 11222, + max_memory => '12%', + } +``` + ### Other class parameters * $package_ensure = 'present' -* $logfile = '/var/log/memcached.log' -* $pidfile = '/var/run/memcached.pid' (Debian family only, set to false to disable pidfile) * $max_memory = false * $item_size = false * $lock_memory = false (WARNING: good if used intelligently, google for -k key) diff --git a/manifests/init.pp b/manifests/init.pp index 08350ed0c..81c228f4d 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -4,8 +4,6 @@ # class memcached ( $package_ensure = 'present', - $logfile = $::memcached::params::logfile, - $pidfile = '/var/run/memcached.pid', $manage_firewall = false, $max_memory = false, $item_size = false, @@ -24,18 +22,11 @@ $use_sasl = false, $use_registry = $::memcached::params::use_registry, $registry_key = 'HKLM\System\CurrentControlSet\services\memcached\ImagePath', - $large_mem_pages = false + $large_mem_pages = false, + $default_instance = true, + $instance_configs = hiera_hash('memcached::instance_configs', undef), ) inherits memcached::params { - # validate type and convert string to boolean if necessary - if is_string($manage_firewall) { - $manage_firewall_bool = str2bool($manage_firewall) - } else { - $manage_firewall_bool = $manage_firewall - } - validate_bool($manage_firewall_bool) - validate_bool($service_restart) - if $package_ensure == 'absent' { $service_ensure = 'stopped' $service_enable = false @@ -44,54 +35,45 @@ $service_enable = true } - package { $memcached::params::package_name: - ensure => $package_ensure, - provider => $memcached::params::package_provider + class { '::memcached::package': + package_ensure => $package_ensure, + install_dev => $install_dev, } - if $install_dev { - package { $memcached::params::dev_package_name: - ensure => $package_ensure, - require => Package[$memcached::params::package_name] - } + $default_configs = { + 'memcached' => { + manage_firewall => $manage_firewall, + max_memory => $max_memory, + item_size => $item_size, + lock_memory => $lock_memory, + listen_ip => $listen_ip, + tcp_port => $tcp_port, + udp_port => $udp_port, + max_connections => $max_connections, + verbosity => $verbosity, + unix_socket => $unix_socket, + processorcount => $processorcount, + use_sasl => $use_sasl, + large_mem_pages => $large_mem_pages, + service_ensure => $service_ensure, + service_enable => $service_enable, + }, } - if $manage_firewall_bool == true { - firewall { "100_tcp_${tcp_port}_for_memcached": - port => $tcp_port, - proto => 'tcp', - action => 'accept', - } - - firewall { "100_udp_${udp_port}_for_memcached": - port => $udp_port, - proto => 'udp', - action => 'accept', - } + if $default_instance and is_hash($instance_configs) { + validate_hash($instance_configs) + $final_configs = merge($default_configs, $instance_configs) } - - if $service_restart { - $service_notify_real = Service[$memcached::params::service_name] - } else { - $service_notify_real = undef + elsif $default_instance { + $final_configs = $default_configs } - - if ( $memcached::params::config_file ) { - file { $memcached::params::config_file: - owner => 'root', - group => 'root', - mode => '0644', - content => template($memcached::params::config_tmpl), - require => Package[$memcached::params::package_name], - notify => $service_notify_real, - } + elsif is_hash($instance_configs) { + validate_hash($instance_configs) + $final_configs = $instance_configs } - service { $memcached::params::service_name: - ensure => $service_ensure, - enable => $service_enable, - hasrestart => true, - hasstatus => $memcached::params::service_hasstatus, + if ! is_hash($final_configs) { + fail('No configuration provided to the Memcached class') } if $use_registry { @@ -102,4 +84,7 @@ notify => Service[$memcached::params::service_name] } } + + create_resources(memcached::instance, $final_configs) + } diff --git a/manifests/instance.pp b/manifests/instance.pp new file mode 100644 index 000000000..6e4edd889 --- /dev/null +++ b/manifests/instance.pp @@ -0,0 +1,120 @@ +# == Type: memcached::instance +# +# Manage memcached instances +# +define memcached::instance ( + $package_ensure = 'present', + $manage_firewall = false, + $max_memory = false, + $item_size = false, + $lock_memory = false, + $listen_ip = '0.0.0.0', + $tcp_port = 11211, + $udp_port = 11211, + $max_connections = '8192', + $verbosity = undef, + $unix_socket = undef, + $install_dev = false, + $processorcount = $::processorcount, + $service_restart = true, + $auto_removal = false, + $use_sasl = false, + $large_mem_pages = false, + $service_ensure = 'running', + $service_enable = true, +) { + + include ::memcached::params + + # This is needed only if instances are exclusively defined rather than using the base class + if ! defined(Class['::memcached::package']) { + class { '::memcached::package': + package_ensure => $package_ensure, + install_dev => $install_dev, + } + } + + $user = $memcached::params::user + $pidfile = "/var/run/memcached_${tcp_port}.pid" + + if $::osfamily != 'Windows' { + $logfile = "/var/log/memcached_${tcp_port}.log" + } + + # validate type and convert string to boolean if necessary + if is_string($manage_firewall) { + $manage_firewall_bool = str2bool($manage_firewall) + } else { + $manage_firewall_bool = $manage_firewall + } + validate_bool($manage_firewall_bool) + validate_bool($service_restart) + + if $manage_firewall_bool == true { + firewall { "100_tcp_${tcp_port}_for_memcached": + port => $tcp_port, + proto => 'tcp', + action => 'accept', + } + + firewall { "100_udp_${udp_port}_for_memcached": + port => $udp_port, + proto => 'udp', + action => 'accept', + } + } + + case $::osfamily { + 'Debian': { + $config_file = "/etc/memcached_${tcp_port}.conf" + $service_name = 'memcached' + # We don't manage the init script for Debian + } + 'Windows': { + $config_file = undef + $service_name = 'memcached' + } + default: { + $config_file = "/etc/sysconfig/memcached_${tcp_port}" + $service_name = "memcached_${tcp_port}" + $init_script = "/etc/init.d/memcached_${tcp_port}" + } + } + + if $service_restart { + $service_notify_real = Service[$service_name] + } else { + $service_notify_real = undef + } + + if $config_file { + file { $config_file: + owner => 'root', + group => 'root', + mode => '0644', + content => template($memcached::params::config_tmpl), + require => Package[$memcached::params::package_name], + notify => $service_notify_real, + } + } + + if $::osfamily != 'Debian' { + file { $init_script: + owner => 'root', + group => 'root', + mode => '0755', + content => template($memcached::params::init_tmpl), + require => Package[$memcached::params::package_name], + notify => $service_notify_real, + } + } + + ensure_resource('service', $service_name, { + ensure => $service_ensure, + enable => $service_enable, + hasrestart => true, + hasstatus => $memcached::params::service_hasstatus, + } + ) + +} diff --git a/manifests/package.pp b/manifests/package.pp new file mode 100644 index 000000000..eafde502e --- /dev/null +++ b/manifests/package.pp @@ -0,0 +1,21 @@ +# == Class: memcached::package +# +# Manage memcached installation +# +class memcached::package ( + $package_ensure = 'present', + $install_dev = false, +) inherits memcached::params { + + package { $memcached::params::package_name: + ensure => $package_ensure, + } + + if $install_dev { + package { $memcached::params::dev_package_name: + ensure => $package_ensure, + require => Package[$memcached::params::package_name] + } + } + +} diff --git a/manifests/params.pp b/manifests/params.pp index 1469a4b4d..abc90f079 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -5,31 +5,25 @@ 'Debian': { $package_name = 'memcached' $package_provider = undef - $service_name = 'memcached' $service_hasstatus = false $dev_package_name = 'libmemcached-dev' - $config_file = '/etc/memcached.conf' $config_tmpl = "${module_name}/memcached.conf.erb" $user = 'nobody' - $logfile = '/var/log/memcached.log' $use_registry = false } /RedHat|Suse/: { $package_name = 'memcached' $package_provider = undef - $service_name = 'memcached' $service_hasstatus = true $dev_package_name = 'libmemcached-devel' - $config_file = '/etc/sysconfig/memcached' $config_tmpl = "${module_name}/memcached_sysconfig.erb" + $init_tmpl = "${module_name}/memcached.init.erb" $user = 'memcached' - $logfile = '/var/log/memcached.log' $use_registry = false } /windows/: { $package_name = 'memcached' $package_provider = 'chocolatey' - $service_name = 'memcached' $service_hasstatus = true $dev_package_name = 'libmemcached-devel' $config_file = undef @@ -43,13 +37,11 @@ 'Amazon': { $package_name = 'memcached' $package_provider = undef - $service_name = 'memcached' $service_hasstatus = true $dev_package_name = 'libmemcached-devel' - $config_file = '/etc/sysconfig/memcached' $config_tmpl = "${module_name}/memcached_sysconfig.erb" + $init_tmpl = "${module_name}/memcached.init.erb" $user = 'memcached' - $logfile = '/var/log/memcached.log' $use_registry = false } default: { diff --git a/spec/classes/memcached_spec.rb b/spec/classes/memcached_spec.rb index 3357569f7..cf595e069 100644 --- a/spec/classes/memcached_spec.rb +++ b/spec/classes/memcached_spec.rb @@ -49,14 +49,12 @@ let :default_params do { :package_ensure => 'present', - :logfile => '/var/log/memcached.log', :max_memory => false, :item_size => false, :lock_memory => false, :listen_ip => '0.0.0.0', :tcp_port => '11211', :udp_port => '11211', - :user => 'nobody', :max_connections => '8192', :install_dev => false, :processorcount => 1, @@ -68,14 +66,12 @@ [ {}, { :package_ensure => 'latest', - :logfile => '/var/log/memcached.log', :max_memory => '2', :item_size => false, :lock_memory => true, :listen_ip => '127.0.0.1', :tcp_port => '11212', :udp_port => '11213', - :user => 'somebdy', :max_connections => '8193', :verbosity => 'vvv', :processorcount => 3, @@ -84,24 +80,16 @@ }, { :package_ensure => 'present', - :logfile => '/var/log/memcached.log', :max_memory => '20%', :lock_memory => false, :listen_ip => '127.0.0.1', :tcp_port => '11212', :udp_port => '11213', - :user => 'somebdy', :max_connections => '8193', :verbosity => 'vvv', :install_dev => true, :processorcount => 1 }, - { - :pidfile => false, - }, - { - :pidfile => '/var/log/memcached.pid', - }, { :package_ensure => 'absent', :install_dev => true @@ -142,7 +130,9 @@ end } - it { should contain_file("/etc/memcached.conf").with( + it { should contain_memcached__instance("memcached") } + + it { should contain_file("/etc/memcached_#{param_hash[:tcp_port]}.conf").with( 'owner' => 'root', 'group' => 'root' )} @@ -167,15 +157,13 @@ content = param_value( subject, 'file', - '/etc/memcached.conf', + "/etc/memcached_#{param_hash[:tcp_port]}.conf", 'content' ) expected_lines = [ - "logfile #{param_hash[:logfile]}", "-l #{param_hash[:listen_ip]}", "-p #{param_hash[:tcp_port]}", "-U #{param_hash[:udp_port]}", - "-u #{param_hash[:user]}", "-c #{param_hash[:max_connections]}", "-t #{param_hash[:processorcount]}" ] @@ -191,9 +179,6 @@ if(param_hash[:lock_memory]) expected_lines.push("-k") end - if(param_hash[:pidfile]) - expected_lines.push("-P #{param_hash[:pidfile]}") - end if(param_hash[:verbosity]) expected_lines.push("-vvv") end diff --git a/templates/memcached.init.erb b/templates/memcached.init.erb new file mode 100755 index 000000000..a63507074 --- /dev/null +++ b/templates/memcached.init.erb @@ -0,0 +1,91 @@ +#! /bin/sh +# +# chkconfig: - 55 45 +# description: The memcached daemon is a network memory cache service. +# processname: memcached +# config: /etc/sysconfig/memcached +# pidfile: /var/run/memcached/memcached.pid + +# Standard LSB functions +#. /lib/lsb/init-functions + +# Source function library. +. /etc/init.d/functions + +PORT=<%= @tcp_port %> +INSTANCE="memcached_${PORT}" +USER=memcached +MAXCONN=1024 +CACHESIZE=64 +OPTIONS="" + +if [ -f /etc/sysconfig/${INSTANCE} ];then +. /etc/sysconfig/${INSTANCE} +fi + +# Check that networking is up. +. /etc/sysconfig/network + +if [ "$NETWORKING" = "no" ] +then + exit 0 +fi + +RETVAL=0 +prog=${INSTANCE} +pidfile=${PIDFILE-/var/run/memcached/${INSTANCE}.pid} +lockfile=${LOCKFILE-/var/lock/subsys/${INSTANCE}} + +start () { + echo -n $"Starting $prog: " + # Ensure that /var/run/memcached has proper permissions + if [ "`stat -c %U /var/run/memcached`" != "$USER" ]; then + chown $USER /var/run/memcached + fi + + daemon --pidfile ${pidfile} memcached -d -p $PORT -u $USER -m $CACHESIZE -c $MAXCONN -P ${pidfile} $OPTIONS + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && touch ${lockfile} +} +stop () { + echo -n $"Stopping $prog: " + killproc -p ${pidfile} /usr/bin/memcached + RETVAL=$? + echo + if [ $RETVAL -eq 0 ] ; then + rm -f ${lockfile} ${pidfile} + fi +} + +restart () { + stop + start +} + + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status -p ${pidfile} memcached + RETVAL=$? + ;; + restart|reload|force-reload) + restart + ;; + condrestart|try-restart) + [ -f ${lockfile} ] && restart || : + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart|try-restart}" + RETVAL=2 + ;; +esac + +exit $RETVAL