diff --git a/Puppetfile b/Puppetfile index 7a03eda7e..03873332b 100644 --- a/Puppetfile +++ b/Puppetfile @@ -63,7 +63,7 @@ mod 'keystone', :git => 'https://github.com/stackforge/puppet-keystone.git' mod 'memcached', - :commit => '49dbf102fb6eee90297b2ed6a1fa463a8c5ccee7', + :commit => '5869cadc82553738610b305ce15842ab2a3a4313', :git => 'https://github.com/saz/puppet-memcached.git' mod 'module-data', diff --git a/memcached/.fixtures.yml b/memcached/.fixtures.yml index ff6d34112..21aa9ebf9 100644 --- a/memcached/.fixtures.yml +++ b/memcached/.fixtures.yml @@ -1,3 +1,10 @@ fixtures: + repositories: + 'firewall': + repo: 'git://github.com/puppetlabs/puppetlabs-firewall.git' + ref: '0.1.0' + 'stdlib': + repo: 'git://github.com/puppetlabs/puppetlabs-stdlib.git' + ref: '3.2.0' symlinks: - "memcached": "#{source_dir}" + memcached: "#{source_dir}" diff --git a/memcached/.gitattributes b/memcached/.gitattributes new file mode 100644 index 000000000..78640e123 --- /dev/null +++ b/memcached/.gitattributes @@ -0,0 +1,2 @@ +# Enforce Linux line-endings for template files on every operating system. +*.erb text eol=lf diff --git a/memcached/.gitignore b/memcached/.gitignore index 37e8aed56..6c68bc7fa 100644 --- a/memcached/.gitignore +++ b/memcached/.gitignore @@ -1,3 +1,3 @@ pkg/ *.swp -/metadata.json \ No newline at end of file +.forge-releng/ diff --git a/memcached/.travis.yml b/memcached/.travis.yml index 37e322a76..8e14c541f 100644 --- a/memcached/.travis.yml +++ b/memcached/.travis.yml @@ -1,17 +1,38 @@ -language: ruby -rvm: - - 1.8.7 -before_script: -after_script: -script: "rake spec" +--- branches: only: - master +language: ruby +bundler_args: --without development +script: 'bundle exec rake validate && bundle exec rake lint && SPEC_OPTS="--format documentation" bundle exec rake spec' +after_success: + - git clone -q git://github.com/puppetlabs/ghpublisher.git .forge-releng + - .forge-releng/publish +rvm: + - 1.8.7 + - 1.9.3 env: - - PUPPET_VERSION=2.7.13 - - PUPPET_VERSION=2.7.6 - - PUPPET_VERSION=2.6.9 - - PUPPET_VERSION=3.0.0 + matrix: + - PUPPET_GEM_VERSION="~> 2.7.0" + - PUPPET_GEM_VERSION="~> 3.0.0" + - PUPPET_GEM_VERSION="~> 3.1.0" + - PUPPET_GEM_VERSION="~> 3.2.0" + - PUPPET_GEM_VERSION="~> 3.3.0" + - PUPPET_GEM_VERSION="~> 3.4.0" + global: + - PUBLISHER_LOGIN=saz + - secure: |- + KHycFEf0ALVjITczYG0pcfk912muQkbJiGzKa5yyC8C9ppDW+dTYgDQu8AO1KXFHzds + NUASY2XNjrJNv27w7A2eMp88qU1ID1s8CWALph4fuxGcM/HoPw9q8sldJ9/sHGlY9Ye + DEeIvgt9qkwKtG/kb7dN7la42nv5fffWE95OU= +matrix: + include: + - rvm: 2.0.0 + env: PUPPET_GEM_VERSION="~> 3.2.0" + - rvm: 2.0.0 + env: PUPPET_GEM_VERSION="~> 3.3.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.6.0" notifications: email: false -gemfile: .gemfile +gemfile: Gemfile diff --git a/memcached/.gemfile b/memcached/Gemfile similarity index 52% rename from memcached/.gemfile rename to memcached/Gemfile index 9aad840c0..0a648da6d 100644 --- a/memcached/.gemfile +++ b/memcached/Gemfile @@ -1,5 +1,7 @@ -source :rubygems +source "https://rubygems.org" -puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 2.7'] +puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 3.3'] gem 'puppet', puppetversion gem 'puppetlabs_spec_helper', '>= 0.1.0' +gem 'puppet-lint', '>= 0.3.2' +gem 'facter', '>= 1.7.0', "< 1.8.0" diff --git a/memcached/LICENSE b/memcached/LICENSE index c46e2ee1d..7c6618932 100644 --- a/memcached/LICENSE +++ b/memcached/LICENSE @@ -1,4 +1,5 @@ Copyright 2011 Steffen Zieger + Copyright 2014 Garrett Honeycutt Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/memcached/Modulefile b/memcached/Modulefile deleted file mode 100644 index 3f339a9c6..000000000 --- a/memcached/Modulefile +++ /dev/null @@ -1,8 +0,0 @@ -name 'saz-memcached' -version '2.0.4' -source 'git://github.com/saz/puppet-memcached.git' -author 'saz' -license 'Apache License, Version 2.0' -summary 'UNKNOWN' -description 'Manage memcached via Puppet' -project_page 'https://github.com/saz/puppet-memcached' diff --git a/memcached/README.md b/memcached/README.md index 01bded1b5..7218b3e18 100644 --- a/memcached/README.md +++ b/memcached/README.md @@ -1,9 +1,10 @@ -# puppet-memcached - -[![Build Status](https://secure.travis-ci.org/saz/puppet-memcached.png)](http://travis-ci.org/saz/puppet-memcached) +# 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 + ## How to use ### Use roughly 90% of memory @@ -30,10 +31,22 @@ Manage memcached via Puppet ### 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) * $listen_ip = '0.0.0.0' * $tcp_port = 11211 * $udp_port = 11211 +* $manage_firewall = false * $user = '' (OS specific setting, see params.pp) * $max_connections = 8192 -* $lock_memory = false (WARNING: good if used intelligently, google for -k key) +* $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) +* $large_mem_pages = false (try to use large memory pages) diff --git a/memcached/Rakefile b/memcached/Rakefile index cd3d37995..06f1ab4fb 100644 --- a/memcached/Rakefile +++ b/memcached/Rakefile @@ -1 +1,19 @@ +require 'rubygems' require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' +PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.relative = true +PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] + +desc "Run puppet in noop mode and check for syntax errors." +task :validate do + Dir['manifests/**/*.pp'].each do |manifest| + sh "puppet parser validate --noop #{manifest}" + end + Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| + sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ + end + Dir['templates/**/*.erb'].each do |template| + sh "erb -P -x -T '-' #{template} | ruby -c" + end +end diff --git a/memcached/manifests/init.pp b/memcached/manifests/init.pp index 8d1ca1540..1d196c333 100644 --- a/memcached/manifests/init.pp +++ b/memcached/manifests/init.pp @@ -1,7 +1,14 @@ -class memcached( +# == Class: memcached +# +# Manage memcached +# +class memcached ( $package_ensure = 'present', $logfile = '/var/log/memcached.log', + $pidfile = '/var/run/memcached.pid', + $manage_firewall = false, $max_memory = false, + $item_size = false, $lock_memory = false, $listen_ip = '0.0.0.0', $tcp_port = 11211, @@ -9,26 +16,76 @@ $user = $::memcached::params::user, $max_connections = '8192', $verbosity = undef, - $unix_socket = undef + $unix_socket = undef, + $install_dev = false, + $processorcount = $::processorcount, + $service_restart = true, + $auto_removal = false, + $use_sasl = false, + $large_mem_pages = false, ) 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 + } else { + $service_ensure = 'running' + $service_enable = true + } + 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] + } + } + + 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 $service_restart { + $service_notify_real = Service[$memcached::params::service_name] + } else { + $service_notify_real = undef + } + 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, } service { $memcached::params::service_name: - ensure => running, - enable => true, + ensure => $service_ensure, + enable => $service_enable, hasrestart => true, - hasstatus => false, - subscribe => File[$memcached::params::config_file], + hasstatus => $memcached::params::service_hasstatus, } } diff --git a/memcached/manifests/params.pp b/memcached/manifests/params.pp index 9c1ca4710..20cb1ca51 100644 --- a/memcached/manifests/params.pp +++ b/memcached/manifests/params.pp @@ -1,21 +1,40 @@ +# == Class: memcached::params +# class memcached::params { case $::osfamily { 'Debian': { - $package_name = 'memcached' - $service_name = 'memcached' - $config_file = '/etc/memcached.conf' - $config_tmpl = "$module_name/memcached.conf.erb" - $user = 'nobody' + $package_name = 'memcached' + $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' } - 'RedHat': { - $package_name = 'memcached' - $service_name = 'memcached' - $config_file = '/etc/sysconfig/memcached' - $config_tmpl = "$module_name/memcached_sysconfig.erb" - $user = 'memcached' + /RedHat|Suse/: { + $package_name = 'memcached' + $service_name = 'memcached' + $service_hasstatus = true + $dev_package_name = 'libmemcached-devel' + $config_file = '/etc/sysconfig/memcached' + $config_tmpl = "${module_name}/memcached_sysconfig.erb" + $user = 'memcached' } default: { - fail("Unsupported platform: ${::osfamily}") + case $::operatingsystem { + 'Amazon': { + $package_name = 'memcached' + $service_name = 'memcached' + $service_hasstatus = true + $dev_package_name = 'libmemcached-devel' + $config_file = '/etc/sysconfig/memcached' + $config_tmpl = "${module_name}/memcached_sysconfig.erb" + $user = 'memcached' + } + default: { + fail("Unsupported platform: ${::osfamily}/${::operatingsystem}") + } + } } } } diff --git a/memcached/metadata.json b/memcached/metadata.json new file mode 100644 index 000000000..5ee9067f3 --- /dev/null +++ b/memcached/metadata.json @@ -0,0 +1,45 @@ +{ + "operatingsystem_support": [ + { + "operatingsystem": "RedHat" + }, + { + "operatingsystem": "CentOS" + }, + { + "operatingsystem": "OracleLinux" + }, + { + "operatingsystem": "Scientific" + }, + { + "operatingsystem": "Debian" + }, + { + "operatingsystem": "Ubuntu" + } + ], + "requirements": [ + { + "name": "pe", + "version_requirement": ">= 3.2.0 < 3.4.0" + }, + { + "name": "puppet", + "version_requirement": "3.x" + } + ], + "name": "saz-memcached", + "version": "2.6.0", + "author": "saz", + "summary": "UNKNOWN", + "license": "Apache License, Version 2.0", + "source": "git://github.com/saz/puppet-memcached.git", + "project_page": "https://github.com/saz/puppet-memcached", + "issues_url": "https://github.com/saz/puppet-memcached/issues", + "description": "Manage memcached via Puppet", + "dependencies": [ + {"name":"puppetlabs/stdlib","version_requirement":">= 3.2.0"}, + {"name":"puppetlabs/firewall","version_requirement":">= 0.1.0"} + ] +} diff --git a/memcached/spec/classes/memcached_spec.rb b/memcached/spec/classes/memcached_spec.rb index d39701d16..3357569f7 100644 --- a/memcached/spec/classes/memcached_spec.rb +++ b/memcached/spec/classes/memcached_spec.rb @@ -1,17 +1,67 @@ require 'spec_helper' describe 'memcached' do + describe 'with manage_firewall parameter' do + ['Debian','RedHat'].each do |osfam| + context "on osfamily #{osfam}" do + let(:facts) do + { :osfamily => osfam, + :memorysize => '1000 MB', + :processorcount => '1', + } + end + + ['true',true].each do |value| + context "set to #{value}" do + let(:params) { { :manage_firewall => value } } + + it { should contain_class('memcached') } + + it { should contain_firewall('100_tcp_11211_for_memcached') } + it { should contain_firewall('100_udp_11211_for_memcached') } + end + end + + ['false',false].each do |value| + context "set to #{value}" do + let(:params) { { :manage_firewall => value } } + + it { should contain_class('memcached') } + + it { should_not contain_firewall('100_tcp_11211_for_memcached') } + it { should_not contain_firewall('100_udp_11211_for_memcached') } + end + end + + context 'set to an invalid type (array)' do + let(:params) { { :manage_firewall => ['invalid','type'] } } + + it do + expect { + should contain_class('memcached') + }.to raise_error(Puppet::Error) + end + end + end + end + end + 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' + :max_connections => '8192', + :install_dev => false, + :processorcount => 1, + :use_sasl => false, + :large_mem_pages => false, } end @@ -20,13 +70,17 @@ :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' + :verbosity => 'vvv', + :processorcount => 3, + :use_sasl => true, + :large_mem_pages => true, }, { :package_ensure => 'present', @@ -38,7 +92,19 @@ :udp_port => '11213', :user => 'somebdy', :max_connections => '8193', - :verbosity => 'vvv' + :verbosity => 'vvv', + :install_dev => true, + :processorcount => 1 + }, + { + :pidfile => false, + }, + { + :pidfile => '/var/log/memcached.pid', + }, + { + :package_ensure => 'absent', + :install_dev => true } ].each do |param_set| describe "when #{param_set == {} ? "using default" : "specifying"} class parameters" do @@ -63,21 +129,39 @@ describe "on supported osfamily: #{osfamily}" do - it { should contain_class('memcached::params') } + it { should contain_class("memcached::params") } + + it { should contain_package("memcached").with_ensure(param_hash[:package_ensure]) } - it { should contain_package('memcached').with_ensure(param_hash[:package_ensure]) } + it { should_not contain_firewall('100_tcp_11211_for_memcached') } + it { should_not contain_firewall('100_udp_11211_for_memcached') } - it { should contain_file('/etc/memcached.conf').with( + it { + if param_hash[:install_dev] + should contain_package("libmemcached-dev").with_ensure(param_hash[:package_ensure]) + end + } + + it { should contain_file("/etc/memcached.conf").with( 'owner' => 'root', 'group' => 'root' )} - it { should contain_service('memcached').with( - 'ensure' => 'running', - 'enable' => true, - 'hasrestart' => true, - 'hasstatus' => false - )} + it { + if param_hash[:package_ensure] == 'absent' + should contain_service("memcached").with( + 'ensure' => 'stopped', + 'enable' => false + ) + else + should contain_service("memcached").with( + 'ensure' => 'running', + 'enable' => true, + 'hasrestart' => true, + 'hasstatus' => false + ) + end + } it 'should compile the template based on the class parameters' do content = param_value( @@ -93,7 +177,7 @@ "-U #{param_hash[:udp_port]}", "-u #{param_hash[:user]}", "-c #{param_hash[:max_connections]}", - "-t #{facts[:processorcount]}" + "-t #{param_hash[:processorcount]}" ] if(param_hash[:max_memory]) if(param_hash[:max_memory].end_with?('%')) @@ -107,9 +191,18 @@ 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 + if(param_hash[:use_sasl]) + expected_lines.push("-S") + end + if(param_hash[:large_mem_pages]) + expected_lines.push("-L") + end (content.split("\n") & expected_lines).should =~ expected_lines end end @@ -124,3 +217,5 @@ end end end + +# vim: expandtab shiftwidth=2 softtabstop=2 diff --git a/memcached/spec/spec_helper.rb b/memcached/spec/spec_helper.rb index 2c6f56649..dc7e9f4a0 100644 --- a/memcached/spec/spec_helper.rb +++ b/memcached/spec/spec_helper.rb @@ -1 +1,2 @@ +require 'rubygems' require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/memcached/templates/memcached.conf.erb b/memcached/templates/memcached.conf.erb index 03344d5da..1586d9426 100644 --- a/memcached/templates/memcached.conf.erb +++ b/memcached/templates/memcached.conf.erb @@ -3,45 +3,67 @@ # Run memcached as a daemon. -d +<% if @pidfile -%> # pidfile --P /var/run/memcached.pid +-P <%= @pidfile %> +<% end -%> # Log memcached's output -logfile <%= logfile -%> +logfile <%= @logfile -%> <% if @verbosity -%> # Verbosity --<%= verbosity %> +-<%= @verbosity %> <% end -%> # Use MB memory max to use for object storage. <% Puppet::Parser::Functions.function('memcached_max_memory') -%> --m <%= scope.function_memcached_max_memory([max_memory]) %> +-m <%= scope.function_memcached_max_memory([@max_memory]) %> <% if @lock_memory -%> # Lock down all paged memory. There is a limit on how much memory you may lock. -k <% end -%> +<% if @use_sasl -%> +# Start with SASL support +-S +<% end -%> + <% if @unix_socket -%> # UNIX socket path to listen on --s <%= unix_socket %> +-s <%= @unix_socket %> <% else -%> # IP to listen on --l <%= listen_ip %> +-l <%= @listen_ip %> # TCP port to listen on --p <%= tcp_port %> +-p <%= @tcp_port %> # UDP port to listen on --U <%= udp_port %> +-U <%= @udp_port %> <% end -%> # Run daemon as user --u <%= user %> +-u <%= @user %> + +<% if @large_mem_pages -%> +# Try to use large memory pages (if available) +-L +<% end -%> # Limit the number of simultaneous incoming connections. --c <%= max_connections %> +-c <%= @max_connections %> # Number of threads to use to process incoming requests. --t <%= processorcount %> +-t <%= @processorcount %> + +<% if @item_size -%> +# Override the default size of each slab page +-I <%= @item_size %> +<% end -%> + +<% if @auto_removal -%> +# Disable automatic removal of items from the cache when out of memory +-M +<% end -%> diff --git a/memcached/templates/memcached_sysconfig.erb b/memcached/templates/memcached_sysconfig.erb index 3c980309b..f9f38f90a 100644 --- a/memcached/templates/memcached_sysconfig.erb +++ b/memcached/templates/memcached_sysconfig.erb @@ -1,21 +1,52 @@ -PORT="<%= tcp_port %>" -USER="<%= user %>" -MAXCONN="<%= max_connections %>" -<% Puppet::Parser::Functions.function('memcached_max_memory') -%> -CACHESIZE="<%= scope.function_memcached_max_memory([max_memory]) %>" -OPTIONS="<% +<%- result = [] if @verbosity - result << '-' + verbosity + result << '-' + @verbosity.to_s end if @lock_memory result << '-k' end if @listen_ip - result << '-l ' + listen_ip + result << '-l ' + @listen_ip end if @udp_port - result << '-U ' + udp_port + result << '-U ' + @udp_port.to_s +end +if @item_size + result << '-I ' + @item_size.to_s end -result << '-t ' + processorcount --%><%= result.join(' ') -%>" +result << '-t ' + @processorcount +if @logfile + result << '>> ' + @logfile + ' 2>&1' +end +-%> +<%- if scope['osfamily'] != 'Suse' -%> +PORT="<%= @tcp_port %>" +USER="<%= @user %>" +MAXCONN="<%= @max_connections %>" +<% Puppet::Parser::Functions.function('memcached_max_memory') -%> +CACHESIZE="<%= scope.function_memcached_max_memory([@max_memory]) %>" +OPTIONS="<%= result.join(' ') %>" +<%- else -%> +MEMCACHED_PARAMS="<%= result.join(' ') %>" + +## Path: Network/WWW/Memcached +## Description: username memcached should run as +## Type: string +## Default: "memcached" +## Config: memcached +# +# username memcached should run as +# +MEMCACHED_USER="<%= @user %>" + +## Path: Network/WWW/Memcached +## Description: group memcached should be run as +## Type: string +## Default: "memcached" +## Config: memcached +# +# group memcached should be run as +# +MEMCACHED_GROUP="<%= @user %>" +<%- end -%>