390 lines
15 KiB
Ruby
390 lines
15 KiB
Ruby
action :run do
|
|
configure
|
|
new_resource.updated_by_last_action(true)
|
|
end
|
|
|
|
def configure
|
|
base_piddir = new_resource.base_piddir
|
|
|
|
if !new_resource.version
|
|
redis_output = Mixlib::ShellOut.new("#{node['redisio']['bin_path']}/redis-server -v")
|
|
redis_output.run_command
|
|
redis_output.error!
|
|
current_version = redis_output.stdout.gsub(/.*v=((\d+\.){2}\d+).*/, '\1').chomp
|
|
else
|
|
current_version = new_resource.version
|
|
end
|
|
version_hash = RedisioHelper.version_to_hash(current_version)
|
|
|
|
# Setup a configuration file and init script for each configuration provided
|
|
new_resource.servers.each do |current_instance|
|
|
# Retrieve the default settings hash and the current server setups settings hash.
|
|
current_instance_hash = current_instance.to_hash
|
|
current_defaults_hash = new_resource.default_settings.to_hash
|
|
|
|
# Merge the configuration defaults with the provided array of configurations provided
|
|
current = current_defaults_hash.merge(current_instance_hash)
|
|
|
|
# Merge in the default maxmemory
|
|
node_memory_kb = node['memory']['total']
|
|
# On BSD platforms Ohai reports total memory as a Fixnum
|
|
|
|
node_memory_kb = node_memory_kb.sub('kB', '').to_i if node_memory_kb.is_a?(String)
|
|
|
|
# Here we determine what the logfile is. It has these possible states
|
|
#
|
|
# Redis 2.6 and lower can be
|
|
# stdout
|
|
# A path
|
|
# nil
|
|
# Redis 2.8 and higher can be
|
|
# empty string, which means stdout)
|
|
# A path
|
|
# nil
|
|
|
|
if current['logfile'].nil?
|
|
log_file = nil
|
|
log_directory = nil
|
|
elsif current['logfile'] == 'stdout' || current['logfile'].empty?
|
|
log_directory = nil
|
|
log_file = current['logfile']
|
|
else
|
|
log_directory = ::File.dirname(current['logfile'])
|
|
log_file = ::File.basename(current['logfile'])
|
|
if current['syslogenabled'] == 'yes'
|
|
Chef::Log.warn("log file is set to #{current['logfile']} but syslogenabled is also set to 'yes'")
|
|
end
|
|
end
|
|
|
|
maxmemory = current['maxmemory'].to_s
|
|
if !maxmemory.empty? && maxmemory.include?('%')
|
|
# Just assume this is sensible like "95%" or "95 %"
|
|
percent_factor = current['maxmemory'].to_f / 100.0
|
|
# Ohai reports memory in KB as it looks in /proc/meminfo
|
|
maxmemory = (node_memory_kb * 1024 * percent_factor / new_resource.servers.length).round.to_s
|
|
end
|
|
|
|
descriptors = if current['ulimit'] == 0
|
|
current['maxclients'] + 32
|
|
elsif current['ulimit'] > current['maxclients']
|
|
current['ulimit']
|
|
else
|
|
current['maxclients']
|
|
end
|
|
|
|
recipe_eval do
|
|
server_name = current['name'] || current['port']
|
|
piddir = "#{base_piddir}/#{server_name}"
|
|
aof_file = current['appendfilename'] || "#{current['datadir']}/appendonly-#{server_name}.aof"
|
|
rdb_file = current['dbfilename'] || "#{current['datadir']}/dump-#{server_name}.rdb"
|
|
|
|
# Create the owner of the redis data directory
|
|
user current['user'] do
|
|
comment 'Redis service account'
|
|
manage_home true
|
|
home current['homedir']
|
|
shell current['shell']
|
|
system current['systemuser']
|
|
uid current['uid'] unless current['uid'].nil?
|
|
end
|
|
|
|
# Create the redis configuration directory
|
|
directory current['configdir'] do
|
|
owner 'root'
|
|
group platform_family?('freebsd') ? 'wheel' : 'root'
|
|
mode '0755'
|
|
recursive true
|
|
action :create
|
|
end
|
|
# Create the instance data directory
|
|
directory current['datadir'] do
|
|
owner current['user']
|
|
group current['group']
|
|
mode '0775'
|
|
recursive true
|
|
action :create
|
|
end
|
|
# Create the pid file directory
|
|
directory piddir do
|
|
owner current['user']
|
|
group current['group']
|
|
mode '0755'
|
|
recursive true
|
|
action :create
|
|
end
|
|
# Create the log directory if syslog is not being used
|
|
if log_directory
|
|
directory log_directory do
|
|
owner current['user']
|
|
group current['group']
|
|
mode '0755'
|
|
recursive true
|
|
action :create
|
|
end
|
|
end
|
|
# Configure SELinux if it is enabled
|
|
extend Chef::Util::Selinux
|
|
|
|
if selinux_enabled?
|
|
selinux_policy_install 'install'
|
|
|
|
selinux_policy_fcontext "#{current['configdir']}(/.*)?" do
|
|
secontext 'redis_conf_t'
|
|
end
|
|
selinux_policy_fcontext "#{current['datadir']}(/.*)?" do
|
|
secontext 'redis_var_lib_t'
|
|
end
|
|
selinux_policy_fcontext "#{piddir}(/.*)?" do
|
|
secontext 'redis_var_run_t'
|
|
end
|
|
if log_directory
|
|
selinux_policy_fcontext "#{log_directory}(/.*)?" do
|
|
secontext 'redis_log_t'
|
|
end
|
|
end
|
|
end
|
|
# Create the log file if syslog is not being used
|
|
if log_file
|
|
file current['logfile'] do
|
|
owner current['user']
|
|
group current['group']
|
|
mode '0644'
|
|
backup false
|
|
action :touch
|
|
# in version 2.8 or higher the empty string is used instead of stdout
|
|
only_if { !log_file.empty? && log_file != 'stdout' }
|
|
end
|
|
end
|
|
# Set proper permissions on the AOF or RDB files
|
|
file aof_file do
|
|
owner current['user']
|
|
group current['group']
|
|
mode '0644'
|
|
only_if { current['backuptype'] == 'aof' || current['backuptype'] == 'both' }
|
|
only_if { ::File.exist?(aof_file) }
|
|
end
|
|
file rdb_file do
|
|
owner current['user']
|
|
group current['group']
|
|
mode '0644'
|
|
only_if { current['backuptype'] == 'rdb' || current['backuptype'] == 'both' }
|
|
only_if { ::File.exist?(rdb_file) }
|
|
end
|
|
|
|
# Setup the redis users descriptor limits
|
|
# Pending response on https://github.com/brianbianco/redisio/commit/4ee9aad3b53029cc3b6c6cf741f5126755e712cd#diff-8ae42a59a6f4e8dc5b4e6dd2d6a34eab
|
|
# TODO: ulimit cookbook v0.1.2 doesn't work with freeBSD
|
|
if current['ulimit'] && !platform_family?('freebsd')
|
|
user_ulimit current['user'] do
|
|
filehandle_limit descriptors
|
|
end
|
|
end
|
|
|
|
computed_save = current['save']
|
|
if current['save'] && current['save'].respond_to?(:each_line)
|
|
computed_save = current['save'].each_line
|
|
Chef::Log.warn("#{server_name}: given a save argument as a string, instead of an array.")
|
|
Chef::Log.warn("#{server_name}: This will be deprecated in future versions of the redisio cookbook.")
|
|
end
|
|
|
|
# Load password for use with requirepass from data bag if needed
|
|
if current['data_bag_name'] && current['data_bag_item'] && current['data_bag_key']
|
|
bag = data_bag_item(current['data_bag_name'], current['data_bag_item'])
|
|
current['requirepass'] = bag[current['data_bag_key']]
|
|
current['masterauth'] = bag[current['data_bag_key']]
|
|
end
|
|
|
|
# Lay down the configuration files for the current instance
|
|
template "#{current['configdir']}/#{server_name}.conf" do
|
|
source node['redisio']['redis_config']['template_source']
|
|
cookbook node['redisio']['redis_config']['template_cookbook']
|
|
owner current['user']
|
|
group current['group']
|
|
mode current['permissions']
|
|
action :create
|
|
variables(
|
|
version: version_hash,
|
|
piddir: piddir,
|
|
name: server_name,
|
|
job_control: node['redisio']['job_control'],
|
|
port: current['port'],
|
|
tcpbacklog: current['tcpbacklog'],
|
|
address: current['address'],
|
|
databases: current['databases'],
|
|
backuptype: current['backuptype'],
|
|
datadir: current['datadir'],
|
|
unixsocket: current['unixsocket'],
|
|
unixsocketperm: current['unixsocketperm'],
|
|
timeout: current['timeout'],
|
|
keepalive: current['keepalive'],
|
|
loglevel: current['loglevel'],
|
|
logfile: current['logfile'],
|
|
syslogenabled: current['syslogenabled'],
|
|
syslogfacility: current['syslogfacility'],
|
|
save: computed_save,
|
|
stopwritesonbgsaveerror: current['stopwritesonbgsaveerror'],
|
|
rdbcompression: current['rdbcompression'],
|
|
rdbchecksum: current['rdbchecksum'],
|
|
dbfilename: current['dbfilename'],
|
|
slaveof: current['slaveof'],
|
|
protected_mode: current['protected_mode'],
|
|
masterauth: current['masterauth'],
|
|
slaveservestaledata: current['slaveservestaledata'],
|
|
slavereadonly: current['slavereadonly'],
|
|
replpingslaveperiod: current['replpingslaveperiod'],
|
|
repltimeout: current['repltimeout'],
|
|
repldisabletcpnodelay: current['repldisabletcpnodelay'],
|
|
replbacklogsize: current['replbacklogsize'],
|
|
replbacklogttl: current['replbacklogttl'],
|
|
slavepriority: current['slavepriority'],
|
|
requirepass: current['requirepass'],
|
|
rename_commands: current['rename_commands'],
|
|
maxclients: current['maxclients'],
|
|
maxmemory: maxmemory,
|
|
maxmemorypolicy: current['maxmemorypolicy'],
|
|
maxmemorysamples: current['maxmemorysamples'],
|
|
appendfilename: current['appendfilename'],
|
|
appendfsync: current['appendfsync'],
|
|
noappendfsynconrewrite: current['noappendfsynconrewrite'],
|
|
aofrewritepercentage: current['aofrewritepercentage'],
|
|
aofrewriteminsize: current['aofrewriteminsize'],
|
|
aofloadtruncated: current['aofloadtruncated'],
|
|
luatimelimit: current['luatimelimit'],
|
|
slowloglogslowerthan: current['slowloglogslowerthan'],
|
|
slowlogmaxlen: current['slowlogmaxlen'],
|
|
notifykeyspaceevents: current['notifykeyspaceevents'],
|
|
hashmaxziplistentries: current['hashmaxziplistentries'],
|
|
hashmaxziplistvalue: current['hashmaxziplistvalue'],
|
|
listmaxziplistentries: current['listmaxziplistentries'],
|
|
listmaxziplistvalue: current['listmaxziplistvalue'],
|
|
setmaxintsetentries: current['setmaxintsetentries'],
|
|
zsetmaxziplistentries: current['zsetmaxziplistentries'],
|
|
zsetmaxziplistvalue: current['zsetmaxziplistvalue'],
|
|
hllsparsemaxbytes: current['hllsparsemaxbytes'],
|
|
activerehasing: current['activerehasing'],
|
|
clientoutputbufferlimit: current['clientoutputbufferlimit'],
|
|
hz: current['hz'],
|
|
aofrewriteincrementalfsync: current['aofrewriteincrementalfsync'],
|
|
clusterenabled: current['clusterenabled'],
|
|
clusterconfigfile: current['clusterconfigfile'],
|
|
clusternodetimeout: current['clusternodetimeout'],
|
|
includes: current['includes'],
|
|
minslavestowrite: current['minslavestowrite'],
|
|
minslavesmaxlag: current['minslavesmaxlag'],
|
|
repldisklesssync: current['repldisklesssync'],
|
|
repldisklesssyncdelay: current['repldisklesssyncdelay']
|
|
)
|
|
not_if { ::File.exist?("#{current['configdir']}/#{server_name}.conf.breadcrumb") }
|
|
end
|
|
|
|
file "#{current['configdir']}/#{server_name}.conf.breadcrumb" do
|
|
content 'This file prevents the chef cookbook from overwritting the redis config more than once'
|
|
action :create_if_missing
|
|
only_if { current['breadcrumb'] == true }
|
|
end
|
|
|
|
# Setup init.d file
|
|
bin_path = if node['redisio']['install_dir']
|
|
::File.join(node['redisio']['install_dir'], 'bin')
|
|
else
|
|
node['redisio']['bin_path']
|
|
end
|
|
|
|
case node['redisio']['job_control']
|
|
when 'initd'
|
|
template "/etc/init.d/redis#{server_name}" do
|
|
source 'redis.init.erb'
|
|
cookbook 'redisio'
|
|
owner 'root'
|
|
group 'root'
|
|
mode '0755'
|
|
variables(
|
|
name: server_name,
|
|
bin_path: bin_path,
|
|
port: current['port'],
|
|
address: current['address'],
|
|
user: current['user'],
|
|
configdir: current['configdir'],
|
|
piddir: piddir,
|
|
requirepass: current['requirepass'],
|
|
shutdown_save: current['shutdown_save'],
|
|
platform: node['platform'],
|
|
unixsocket: current['unixsocket'],
|
|
ulimit: descriptors,
|
|
required_start: node['redisio']['init.d']['required_start'].join(' '),
|
|
required_stop: node['redisio']['init.d']['required_stop'].join(' ')
|
|
)
|
|
end
|
|
when 'upstart'
|
|
template "/etc/init/redis#{server_name}.conf" do
|
|
source 'redis.upstart.conf.erb'
|
|
cookbook 'redisio'
|
|
owner current['user']
|
|
group current['group']
|
|
mode '0644'
|
|
variables(
|
|
name: server_name,
|
|
bin_path: bin_path,
|
|
port: current['port'],
|
|
user: current['user'],
|
|
group: current['group'],
|
|
configdir: current['configdir'],
|
|
piddir: piddir
|
|
)
|
|
end
|
|
when 'rcinit'
|
|
template "/usr/local/etc/rc.d/redis#{server_name}" do
|
|
source 'redis.rcinit.erb'
|
|
cookbook 'redisio'
|
|
owner current['user']
|
|
group current['group']
|
|
mode '0755'
|
|
variables(
|
|
name: server_name,
|
|
bin_path: bin_path,
|
|
user: current['user'],
|
|
configdir: current['configdir'],
|
|
piddir: piddir
|
|
)
|
|
end
|
|
when 'systemd'
|
|
service_name = "redis@#{server_name}"
|
|
reload_name = "#{service_name} systemd reload"
|
|
|
|
file "/etc/tmpfiles.d/#{service_name}.conf" do
|
|
content "d #{piddir} 0755 #{current['user']} #{current['group']}\n"
|
|
owner 'root'
|
|
group 'root'
|
|
mode '0644'
|
|
end
|
|
|
|
execute reload_name do
|
|
command 'systemctl daemon-reload'
|
|
action :nothing
|
|
end
|
|
|
|
template "/lib/systemd/system/#{service_name}.service" do
|
|
source 'redis@.service.erb'
|
|
cookbook 'redisio'
|
|
owner 'root'
|
|
group 'root'
|
|
mode '0644'
|
|
variables(
|
|
bin_path: bin_path,
|
|
user: current['user'],
|
|
group: current['group'],
|
|
limit_nofile: descriptors
|
|
)
|
|
notifies :run, "execute[#{reload_name}]", :immediately
|
|
end
|
|
end
|
|
end
|
|
end
|
|
# servers each loop
|
|
end
|
|
|
|
def load_current_resource
|
|
@current_resource = Chef::Resource.resource_for_node(:redisio_configure, node).new(new_resource.name)
|
|
@current_resource
|
|
end
|