diff --git a/README.md b/README.md index bdbd830..1a13c0e 100644 --- a/README.md +++ b/README.md @@ -1,142 +1,142 @@ # puppet-memcached [![Build Status](https://secure.travis-ci.org/saz/puppet-memcached.png)](http://travis-ci.org/saz/puppet-memcached) Manage memcached via Puppet ## Show some love If you find this module useful, send some bitcoins to 1Na3YFUmdxKxJLiuRXQYJU2kiNqA3KY2j9 ### Supported Puppet versions * Puppet >= 5 * Last version supporting Puppet 3: v3.0.2 ## How to use ``` Starting with version 3.0.0, memcached will be listening on 127.0.0.1 only. This should make setups more secure (e.g. if there are no firewall rules in place). To change this behavior, you need to set listen_ip to '0.0.0.0'. ``` ### Use roughly 90% of memory ```ruby class { 'memcached': } ``` ### Set a fixed memory limit in MB ```ruby class { 'memcached': max_memory => 2048 } ``` ### Use 12% of available memory ```ruby class { 'memcached': max_memory => '12%' } ``` ### Install multiple memcached instances the multiinstance support uses a systemd instance unit file. This will be placed at `/etc/systemd/system/memcached@.service`. It allows us to manage multiple instances via the same unit file. To start a simple instance, you only need to know the desired TCP port: ```puppet memcached::instance{'11222':} ``` that's it! It will bind to localhost and listen to TCP port 11222. You might want to tune the systemd limits, for example the number of file descriptors (LimitNOFILE) or the number of processes (LimitNPROC): ```puppet memcached::instance{'11222': limits => { 'LimitNOFILE' => 8192, 'LimitNPROC' => 16384, } } ``` All systemd limits are documented in the [systemd documentation](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Process%20Properties). Another usecase. Let's assume your name is Eric and you want to change the actual memcached parameters, for example to bind it to every interface: ```puppet memcached::instance{'11222': override_content => "[Service]\nEnvironment='LISTEN=-l 0.0.0.0'", } ``` Maybe Eric also wants to override the cache size (the unit is MB): ```puppet memcached::instance{'11222': override_content => "[Service]\nEnvironment=CACHESIZE=4096\n", } ``` last but not least, Eric might also want to override the maximum amount of connections (the default is 1024): ```puppet memcached::instance{'11222': override_content => "[Service]\nEnvironment=MAXCONN=4096\n", } ``` Now Eric wants to use all those three settings at the same time: ```puppet memcached::instance{'11222': override_content => "[Service]\nEnvironment=MAXCONN=4096\nEnvironment=CACHESIZE=4096\nEnvironment='LISTEN=-l 0.0.0.0'\n", } ``` Instead of passing a long string with multiple `\n`, Eric can also put the content in a file and provide that: ```puppet memcached::instance{'11222': override_source => "${module_name}/memcached_11222_override.conf\n", } ``` ### Other class parameters * $package_ensure = 'present' * $logfile = '/var/log/memcached.log' * $logstdout = false (Set this to true to disable logging to a file/syslog entirely, useful when memcached runs in containers) * $pidfile = '/var/run/memcached.pid' (Debian family only, set to false to disable pidfile) * $max_memory = false * $max_item_size = false * $min_item_size = false * $factor = false * $lock_memory = false (WARNING: good if used intelligently, google for -k key) * $listen_ip = '127.0.0.1' * $tcp_port = 11211 -* $udp_port = 11211 +* $udp_port = 0 * $manage_firewall = false * $user = '' (OS specific setting, see params.pp) * $max_connections = 8192 * $verbosity = undef * $unix_socket = undef * $install_dev = false (TRUE if 'libmemcached-dev' package should be installed) * $processorcount = $::processorcount * $service_restart = true (restart service after configuration changes, false to prevent restarts) * $use_sasl = false (start memcached with SASL support) * $use_tls = false (start memcached with TLS support) * $tls_cert_chain = undef * $tls_key = undef * $tls_ca_cert = undef * $tls_verify_mode = 1 (0: None, 1: Request, 2: Require, 3: Once) * $notls_listener_addr = '127.0.0.1' * $notls_listener_port = undef * $large_mem_pages = false (try to use large memory pages) diff --git a/manifests/init.pp b/manifests/init.pp index 0020bab..7bbf30b 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,146 +1,148 @@ # == Class: memcached # # Manage memcached # # == Parameters # [* syslog *] # Boolean. # If true will pipe output to /bin/logger, sends to syslog. # class memcached ( Enum['present', 'latest', 'absent'] $package_ensure = 'present', Boolean $service_manage = true, Optional[Stdlib::Absolutepath] $logfile = $memcached::params::logfile, Boolean $logstdout = false, Boolean $syslog = false, Optional[Stdlib::Absolutepath] $pidfile = '/var/run/memcached.pid', Boolean $manage_firewall = false, $max_memory = '95%', Optional[Variant[Integer, String]] $max_item_size = undef, Optional[Variant[Integer, String]] $min_item_size = undef, Optional[Variant[Integer, String]] $factor = undef, Boolean $lock_memory = false, Optional[Variant[Stdlib::Compat::Ip_address,Array[Stdlib::Compat::Ip_address]]] $listen_ip = '127.0.0.1', Integer $tcp_port = 11211, - Integer $udp_port = 11211, + Integer $udp_port = 0, String $user = $memcached::params::user, Integer $max_connections = 8192, Optional[String] $verbosity = undef, Optional[String] $unix_socket = undef, String $unix_socket_mask = '0755', Boolean $install_dev = false, Variant[String,Integer] $processorcount = $facts['processors']['count'], Boolean $service_restart = true, Boolean $auto_removal = false, Boolean $use_sasl = false, Boolean $use_tls = false, Optional[Stdlib::Absolutepath] $tls_cert_chain = undef, Optional[Stdlib::Absolutepath] $tls_key = undef, Optional[Stdlib::Absolutepath] $tls_ca_cert = undef, Optional[Integer] $tls_verify_mode = 1, Optional[Stdlib::IP::Address] $notls_listener_addr = '127.0.0.1', Optional[Stdlib::Port] $notls_listener_port = undef, Boolean $use_registry = $memcached::params::use_registry, String $registry_key = 'HKLM\System\CurrentControlSet\services\memcached\ImagePath', Boolean $large_mem_pages = false, Boolean $use_svcprop = $memcached::params::use_svcprop, String $svcprop_fmri = 'memcached:default', String $svcprop_key = 'memcached/options', Optional[Array[String]] $extended_opts = undef, String $config_tmpl = $memcached::params::config_tmpl, Boolean $disable_cachedump = false, ) inherits memcached::params { # Logging to syslog and file are mutually exclusive # Fail if both options are defined if $syslog and str2bool($logfile) { fail 'Define either syslog or logfile as logging destinations but not both.' } if $use_tls { if $tls_cert_chain == undef or $tls_key == undef { fail 'tls_cert_chain and tls_key should be set when use_tls is true.' } } if $package_ensure == 'absent' { $service_ensure = 'stopped' $service_enable = false } else { $service_ensure = 'running' $service_enable = true } # Handle if $listen_ip is not an array $real_listen_ip = [$listen_ip] package { $memcached::params::package_name: ensure => $package_ensure, provider => $memcached::params::package_provider, } if $install_dev { package { $memcached::params::dev_package_name: ensure => $package_ensure, require => Package[$memcached::params::package_name], } } if $manage_firewall { firewall { "100_tcp_${tcp_port}_for_memcached": dport => $tcp_port, proto => 'tcp', action => 'accept', } - firewall { "100_udp_${udp_port}_for_memcached": - dport => $udp_port, - proto => 'udp', - action => 'accept', + if $udp_port != 0 { + firewall { "100_udp_${udp_port}_for_memcached": + dport => $udp_port, + proto => 'udp', + action => 'accept', + } } } if $service_restart and $service_manage { $service_notify_real = Service[$memcached::params::service_name] } else { $service_notify_real = undef } if ( $memcached::params::config_file ) { file { $memcached::params::config_file: ensure => 'file', owner => 'root', group => 0, mode => '0644', content => template($config_tmpl), require => Package[$memcached::params::package_name], notify => $service_notify_real, } } if $service_manage { service { $memcached::params::service_name: ensure => $service_ensure, enable => $service_enable, hasrestart => true, hasstatus => $memcached::params::service_hasstatus, } } if $use_registry { registry_value { $registry_key: ensure => 'present', type => 'string', data => template($config_tmpl), notify => $service_notify_real, } } if $use_svcprop { svcprop { $svcprop_key: fmri => $svcprop_fmri, property => $svcprop_key, value => template($memcached::params::config_tmpl), notify => $service_notify_real, } } } diff --git a/spec/acceptance/init_spec.rb b/spec/acceptance/init_spec.rb index bb5cf77..899e82f 100644 --- a/spec/acceptance/init_spec.rb +++ b/spec/acceptance/init_spec.rb @@ -1,22 +1,22 @@ require 'spec_helper_acceptance' describe 'memcached' do context 'with all defaults' do let(:pp) do 'include memcached' end it 'works idempotently with no errors' do apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) end describe service('memcached') do it { is_expected.to be_enabled } it { is_expected.to be_running } end describe port(11_211) do it { is_expected.to be_listening.on('127.0.0.1').with('tcp') } - it { is_expected.to be_listening.on('127.0.0.1').with('udp') } + it { is_expected.not_to be_listening.on('127.0.0.1').with('udp') } end end end diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 87b61e7..b3b617b 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1,57 +1,71 @@ require 'spec_helper' describe 'memcached' do let :node do 'rspec.puppet.com' end on_supported_os.each do |os, facts| context "on #{os} " do let :facts do facts end context 'with all defaults' do it { is_expected.to compile.with_all_deps } it { is_expected.to contain_class('memcached::params') } it { is_expected.to contain_service('memcached').with_ensure('running').with_enable('true') } it { is_expected.to contain_package('memcached').with_ensure('present') } it { is_expected.not_to contain_firewall('100_tcp_11211_for_memcached') } it { is_expected.not_to contain_firewall('100_udp_11211_for_memcached') } context 'on RedHat', if: facts[:os]['family'] == 'RedHat' do it { is_expected.to contain_file('/etc/sysconfig/memcached').with_ensure('file') } end context 'on Debian', if: facts[:os]['family'] == 'Debian' do it { is_expected.to contain_file('/etc/memcached.conf').with_ensure('file') } end end describe 'with manage_firewall parameter' do - context 'with manage_firewall set to true' do + context 'with manage_firewall set to true and unset udp_port' do let(:params) { { manage_firewall: true } } it { is_expected.to contain_class('memcached') } + it { is_expected.to contain_firewall('100_tcp_11211_for_memcached') } + end + + context 'with manage_firewall set to true and udp_port set to 11211' do + let :params do + { + 'manage_firewall' => true, + 'udp_port' => 11_211 + } + end + + it { is_expected.to contain_class('memcached') } + it { is_expected.to contain_firewall('100_tcp_11211_for_memcached') } it { is_expected.to contain_firewall('100_udp_11211_for_memcached') } end end + describe 'when setting use_tls to true and unset tls_ca_cert' do let :params do { 'use_tls' => true, 'tls_cert_chain' => '/path/to/cert', 'tls_key' => '/path/to/key', 'tls_ca_cert' => '/path/to/cacert', 'tls_verify_mode' => 0 } end context 'on RedHat', if: facts[:os]['family'] == 'RedHat' do - it { is_expected.to contain_file('/etc/sysconfig/memcached').with_content("PORT=\"11211\"\nUSER=\"memcached\"\nMAXCONN=\"8192\"\nCACHESIZE=\"462\"\nOPTIONS=\"-l 127.0.0.1 -U 11211 -t 1 -Z -o ssl_chain_cert=/path/to/cert -o ssl_key=/path/to/key -o ssl_ca_cert=/path/to/cacert -o ssl_verify_mode=0 >> /var/log/memcached.log 2>&1\"\n") } + it { is_expected.to contain_file('/etc/sysconfig/memcached').with_content("PORT=\"11211\"\nUSER=\"memcached\"\nMAXCONN=\"8192\"\nCACHESIZE=\"462\"\nOPTIONS=\"-l 127.0.0.1 -U 0 -t 1 -Z -o ssl_chain_cert=/path/to/cert -o ssl_key=/path/to/key -o ssl_ca_cert=/path/to/cacert -o ssl_verify_mode=0 >> /var/log/memcached.log 2>&1\"\n") } end end end end end # vim: expandtab shiftwidth=2 softtabstop=2