Added modules
This commit is contained in:
parent
c53c931217
commit
59ec520742
646 changed files with 35182 additions and 0 deletions
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
31
modules/postgresql/lib/puppet/type/postgresql_conf.rb
Normal file
31
modules/postgresql/lib/puppet/type/postgresql_conf.rb
Normal 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
|
89
modules/postgresql/lib/puppet/type/postgresql_psql.rb
Normal file
89
modules/postgresql/lib/puppet/type/postgresql_psql.rb
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue