Added modules

This commit is contained in:
Ciaby 2014-07-11 13:30:23 -05:00
parent c53c931217
commit 59ec520742
646 changed files with 35182 additions and 0 deletions

View file

@ -0,0 +1,76 @@
module Puppet::Parser::Functions
newfunction(:postgresql_acls_to_resources_hash, :type => :rvalue, :doc => <<-EOS
This internal function translates the ipv(4|6)acls format into a resource
suitable for create_resources. It is not intended to be used outside of the
postgresql internal classes/defined resources.
This function accepts an array of strings that are pg_hba.conf rules. It
will return a hash that can be fed into create_resources to create multiple
individual pg_hba_rule resources.
The second parameter is an identifier that will be included in the namevar
to provide uniqueness. It must be a string.
The third parameter is an order offset, so you can start the order at an
arbitrary starting point.
EOS
) do |args|
func_name = "postgresql_acls_to_resources_hash()"
raise(Puppet::ParseError, "#{func_name}: Wrong number of arguments " +
"given (#{args.size} for 3)") if args.size != 3
acls = args[0]
raise(Puppet::ParseError, "#{func_name}: first argument must be an array") \
unless acls.instance_of? Array
id = args[1]
raise(Puppet::ParseError, "#{func_name}: second argument must be a string") \
unless id.instance_of? String
offset = args[2].to_i
raise(Puppet::ParseError, "#{func_name}: third argument must be a number") \
unless offset.instance_of? Fixnum
resources = {}
acls.each do |acl|
index = acls.index(acl)
parts = acl.split
raise(Puppet::ParseError, "#{func_name}: acl line #{index} does not " +
"have enough parts") unless parts.length >= 4
resource = {
'type' => parts[0],
'database' => parts[1],
'user' => parts[2],
'order' => format('%03d', offset + index),
}
if parts[0] == 'local' then
resource['auth_method'] = parts[3]
if parts.length > 4 then
resource['auth_option'] = parts.last(parts.length - 4).join(" ")
end
else
if parts[4] =~ /^\d/
resource['address'] = parts[3] + ' ' + parts[4]
resource['auth_method'] = parts[5]
if parts.length > 6 then
resource['auth_option'] = parts.last(parts.length - 6).join(" ")
end
else
resource['address'] = parts[3]
resource['auth_method'] = parts[4]
if parts.length > 5 then
resource['auth_option'] = parts.last(parts.length - 5).join(" ")
end
end
end
resources["postgresql class generated rule #{id} #{index}"] = resource
end
resources
end
end

View file

@ -0,0 +1,25 @@
require 'digest/md5'
module Puppet::Parser::Functions
newfunction(:postgresql_escape, :type => :rvalue, :doc => <<-EOS
Safely escapes a string using $$ using a random tag which should be consistent
EOS
) do |args|
raise(Puppet::ParseError, "postgresql_escape(): Wrong number of arguments " +
"given (#{args.size} for 1)") if args.size != 1
password = args[0]
if password !~ /\$\$/
retval = "$$#{password}$$"
else
escape = Digest::MD5.hexdigest(password)[0..5].gsub(/\d/,'')
until password !~ /#{escape}/
escape = Digest::MD5.hexdigest(escape)[0..5].gsub(/\d/,'')
end
retval = "$#{escape}$#{password}$#{escape}$"
end
retval
end
end

View file

@ -0,0 +1,18 @@
# hash a string as mysql's "PASSWORD()" function would do it
require 'digest/md5'
module Puppet::Parser::Functions
newfunction(:postgresql_password, :type => :rvalue, :doc => <<-EOS
Returns the postgresql password hash from the clear text username / password.
EOS
) do |args|
raise(Puppet::ParseError, "postgresql_password(): Wrong number of arguments " +
"given (#{args.size} for 2)") if args.size != 2
username = args[0]
password = args[1]
'md5' + Digest::MD5.hexdigest(password + username)
end
end

View file

@ -0,0 +1,37 @@
require 'puppet/provider/parsedfile'
Puppet::Type.type(:postgresql_conf).provide(
:parsed,
:parent => Puppet::Provider::ParsedFile,
:default_target => '/etc/postgresql.conf',
:filetype => :flat
) do
desc "Set key/values in postgresql.conf."
text_line :comment, :match => /^\s*#/
text_line :blank, :match => /^\s*$/
record_line :parsed,
:fields => %w{name value comment},
:optional => %w{comment},
:match => /^\s*([\w\.]+)\s*=?\s*(.*?)(?:\s*#\s*(.*))?\s*$/,
:to_line => proc { |h|
# simple string and numeric values don't need to be enclosed in quotes
dontneedquote = h[:value].match(/^(\w+|[0-9.-]+)$/)
dontneedequal = h[:name].match(/^(include|include_if_exists)$/i)
str = h[:name].downcase # normalize case
str += dontneedequal ? ' ' : ' = '
str += "'" unless dontneedquote && !dontneedequal
str += h[:value]
str += "'" unless dontneedquote && !dontneedequal
str += " # #{h[:comment]}" unless (h[:comment].nil? or h[:comment] == :absent)
str
},
:post_parse => proc { |h|
h[:name].downcase! # normalize case
h[:value].gsub!(/(^'|'$)/, '') # strip out quotes
}
end

View file

@ -0,0 +1,93 @@
Puppet::Type.type(:postgresql_psql).provide(:ruby) do
def command()
if ((! resource[:unless]) or (resource[:unless].empty?))
if (resource.refreshonly?)
# So, if there's no 'unless', and we're in "refreshonly" mode,
# we need to return the target command here. If we don't,
# then Puppet will generate an event indicating that this
# property has changed.
return resource[:command]
end
# if we're not in refreshonly mode, then we return nil,
# which will cause Puppet to sync this property. This
# is what we want if there is no 'unless' value specified.
return nil
end
if Puppet::PUPPETVERSION.to_f < 4
output, status = run_unless_sql_command(resource[:unless])
else
output = run_unless_sql_command(resource[:unless])
status = output.exitcode
end
if status != 0
puts status
self.fail("Error evaluating 'unless' clause: '#{output}'")
end
result_count = output.strip.to_i
if result_count > 0
# If the 'unless' query returned rows, then we don't want to execute
# the 'command'. Returning the target 'command' here will cause
# Puppet to treat this property as already being 'insync?', so it
# won't call the setter to run the 'command' later.
return resource[:command]
end
# Returning 'nil' here will cause Puppet to see this property
# as out-of-sync, so it will call the setter later.
nil
end
def command=(val)
output, status = run_sql_command(val)
if status != 0
self.fail("Error executing SQL; psql returned #{status}: '#{output}'")
end
end
def run_unless_sql_command(sql)
# for the 'unless' queries, we wrap the user's query in a 'SELECT COUNT',
# which makes it easier to parse and process the output.
run_sql_command('SELECT COUNT(*) FROM (' << sql << ') count')
end
def run_sql_command(sql)
if resource[:search_path]
sql = "set search_path to #{Array(resource[:search_path]).join(',')}; #{sql}"
end
command = [resource[:psql_path]]
command.push("-d", resource[:db]) if resource[:db]
command.push("-t", "-c", sql)
if resource[:cwd]
Dir.chdir resource[:cwd] do
run_command(command, resource[:psql_user], resource[:psql_group])
end
else
run_command(command, resource[:psql_user], resource[:psql_group])
end
end
def run_command(command, user, group)
if Puppet::PUPPETVERSION.to_f < 3.4
Puppet::Util::SUIDManager.run_and_capture(command, user, group)
else
output = Puppet::Util::Execution.execute(command, {
:uid => user,
:gid => group,
:failonfail => false,
:combine => true,
:override_locale => true,
:custom_environment => {}
})
[output, $CHILD_STATUS.dup]
end
end
end

View file

@ -0,0 +1,31 @@
module Puppet
newtype(:postgresql_conf) do
@doc = "This type allows puppet to manage postgresql.conf parameters."
ensurable
newparam(:name) do
desc "The postgresql parameter name to manage."
isnamevar
newvalues(/^[\w\.]+$/)
end
newproperty(:value) do
desc "The value to set for this parameter."
end
newproperty(:target) do
desc "The path to postgresql.conf"
defaultto {
if @resource.class.defaultprovider.ancestors.include?(Puppet::Provider::ParsedFile)
@resource.class.defaultprovider.default_target
else
nil
end
}
end
end
end

View file

@ -0,0 +1,89 @@
Puppet::Type.newtype(:postgresql_psql) do
newparam(:name) do
desc "An arbitrary tag for your own reference; the name of the message."
isnamevar
end
newproperty(:command) do
desc 'The SQL command to execute via psql.'
defaultto { @resource[:name] }
def sync(refreshing = false)
# We're overriding 'sync' here in order to do some magic
# in support of providing a 'refreshonly' parameter. This
# is kind of hacky because the logic for 'refreshonly' is
# spread between the type and the provider, but this is
# the least horrible way that I could determine to accomplish
# it.
#
# Note that our overridden version of 'sync' takes a parameter,
# 'refreshing', which the parent version doesn't take. This
# allows us to call the sync method directly from the 'refresh'
# method, and then inside of the body of 'sync' we can tell
# whether or not we're refreshing.
if (!@resource.refreshonly? || refreshing)
# If we're not in 'refreshonly' mode, or we're not currently
# refreshing, then we just call the parent method.
super()
else
# If we get here, it means we're in 'refreshonly' mode and
# we're not being called by the 'refresh' method, so we
# just no-op. We'll be called again by the 'refresh'
# method momentarily.
nil
end
end
end
newparam(:unless) do
desc "An optional SQL command to execute prior to the main :command; " +
"this is generally intended to be used for idempotency, to check " +
"for the existence of an object in the database to determine whether " +
"or not the main SQL command needs to be executed at all."
end
newparam(:db) do
desc "The name of the database to execute the SQL command against."
end
newparam(:search_path) do
desc "The schema search path to use when executing the SQL command"
end
newparam(:psql_path) do
desc "The path to psql executable."
defaultto("psql")
end
newparam(:psql_user) do
desc "The system user account under which the psql command should be executed."
defaultto("postgres")
end
newparam(:psql_group) do
desc "The system user group account under which the psql command should be executed."
defaultto("postgres")
end
newparam(:cwd, :parent => Puppet::Parameter::Path) do
desc "The working directory under which the psql command should be executed."
defaultto("/tmp")
end
newparam(:refreshonly, :boolean => true) do
desc "If 'true', then the SQL will only be executed via a notify/subscribe event."
defaultto(:false)
newvalues(:true, :false)
end
def refresh()
# All of the magic for this type is attached to the ':command' property, so
# we just need to sync it to accomplish a 'refresh'.
self.property(:command).sync(true)
end
end