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,29 @@
# Install client cli tool. See README.md for more details.
class postgresql::client (
$package_name = $postgresql::params::client_package_name,
$package_ensure = 'present'
) inherits postgresql::params {
validate_string($package_name)
package { 'postgresql-client':
ensure => $package_ensure,
name => $package_name,
tag => 'postgresql',
}
$file_ensure = $package_ensure ? {
'present' => 'file',
true => 'file',
'absent' => 'absent',
false => 'absent',
default => 'file',
}
file { "/usr/local/bin/validate_postgresql_connection.sh":
ensure => $file_ensure,
source => "puppet:///modules/postgresql/validate_postgresql_connection.sh",
owner => 0,
group => 0,
mode => 0755,
}
}

View file

@ -0,0 +1,94 @@
# Class for setting cross-class global overrides. See README.md for more
# details.
class postgresql::globals (
$ensure = undef,
$client_package_name = undef,
$server_package_name = undef,
$contrib_package_name = undef,
$devel_package_name = undef,
$java_package_name = undef,
$plperl_package_name = undef,
$python_package_name = undef,
$service_name = undef,
$service_provider = undef,
$service_status = undef,
$default_database = undef,
$initdb_path = undef,
$createdb_path = undef,
$psql_path = undef,
$pg_hba_conf_path = undef,
$postgresql_conf_path = undef,
$pg_hba_conf_defaults = undef,
$datadir = undef,
$confdir = undef,
$bindir = undef,
$xlogdir = undef,
$user = undef,
$group = undef,
$version = undef,
$needs_initdb = undef,
$encoding = undef,
$locale = undef,
$manage_firewall = undef,
$manage_pg_hba_conf = undef,
$firewall_supported = undef,
$manage_package_repo = undef
) {
# We are determining this here, because it is needed by the package repo
# class.
$default_version = $::osfamily ? {
/^(RedHat|Linux)/ => $::operatingsystem ? {
'Fedora' => $::operatingsystemrelease ? {
/^(18|19|20)$/ => '9.2',
/^(17)$/ => '9.1',
default => undef,
},
'Amazon' => '9.2',
default => $::operatingsystemrelease ? {
/^6\./ => '8.4',
/^5\./ => '8.1',
default => undef,
},
},
'Debian' => $::operatingsystem ? {
'Debian' => $::operatingsystemrelease ? {
/^6\./ => '8.4',
/^(wheezy|7\.)/ => '9.1',
default => undef,
},
'Ubuntu' => $::operatingsystemrelease ? {
/^(14.04)$/ => '9.3',
/^(11.10|12.04|12.10|13.04|13.10)$/ => '9.1',
/^(10.04|10.10|11.04)$/ => '8.4',
default => undef,
},
default => undef,
},
'Archlinux' => $::operatingsystem ? {
/Archlinux/ => '9.2',
default => '9.2',
},
'FreeBSD' => '93',
default => undef,
}
$globals_version = pick($version, $default_version, 'unknown')
# Setup of the repo only makes sense globally, so we are doing this here.
if($manage_package_repo) {
class { 'postgresql::repo':
ensure => $ensure,
version => $globals_version
}
}
}

View file

@ -0,0 +1,15 @@
# This class installs postgresql development libraries. See README.md for more
# details.
class postgresql::lib::devel(
$package_name = $postgresql::params::devel_package_name,
$package_ensure = 'present'
) inherits postgresql::params {
validate_string($package_name)
package { 'postgresql-devel':
ensure => $package_ensure,
name => $package_name,
tag => 'postgresql',
}
}

View file

@ -0,0 +1,15 @@
# This class installs the postgresql jdbc connector. See README.md for more
# details.
class postgresql::lib::java (
$package_name = $postgresql::params::java_package_name,
$package_ensure = 'present'
) inherits postgresql::params {
validate_string($package_name)
package { 'postgresql-jdbc':
ensure => $package_ensure,
name => $package_name,
}
}

View file

@ -0,0 +1,13 @@
# This class installs the python libs for postgresql. See README.md for more
# details.
class postgresql::lib::python(
$package_name = $postgresql::params::python_package_name,
$package_ensure = 'present'
) inherits postgresql::params {
package { 'python-psycopg2':
ensure => $package_ensure,
name => $package_name,
}
}

View file

@ -0,0 +1,175 @@
# PRIVATE CLASS: do not use directly
class postgresql::params inherits postgresql::globals {
$ensure = true
$version = $globals_version
$listen_addresses = 'localhost'
$ip_mask_deny_postgres_user = '0.0.0.0/0'
$ip_mask_allow_all_users = '127.0.0.1/32'
$ipv4acls = []
$ipv6acls = []
$user = pick($user, 'postgres')
$group = pick($group, 'postgres')
$encoding = $encoding
$locale = $locale
$service_provider = $service_provider
$manage_firewall = $manage_firewall
$manage_pg_hba_conf = pick($manage_pg_hba_conf, true)
# Amazon Linux's OS Family is 'Linux', operating system 'Amazon'.
case $::osfamily {
'RedHat', 'Linux': {
$needs_initdb = pick($needs_initdb, true)
$firewall_supported = pick($firewall_supported, true)
if $version == $default_version {
$client_package_name = pick($client_package_name, 'postgresql')
$server_package_name = pick($server_package_name, 'postgresql-server')
$contrib_package_name = pick($contrib_package_name,'postgresql-contrib')
$devel_package_name = pick($devel_package_name, 'postgresql-devel')
$java_package_name = pick($java_package_name, 'postgresql-jdbc')
$plperl_package_name = pick($plperl_package_name, 'postgresql-plperl')
$service_name = pick($service_name, 'postgresql')
$bindir = pick($bindir, '/usr/bin')
$datadir = $::operatingsystem ? {
'Amazon' => pick($datadir, '/var/lib/pgsql9/data'),
default => pick($datadir, '/var/lib/pgsql/data'),
}
$confdir = pick($confdir, $datadir)
} else {
$version_parts = split($version, '[.]')
$package_version = "${version_parts[0]}${version_parts[1]}"
$client_package_name = pick($client_package_name, "postgresql${package_version}")
$server_package_name = pick($server_package_name, "postgresql${package_version}-server")
$contrib_package_name = pick($contrib_package_name,"postgresql${package_version}-contrib")
$devel_package_name = pick($devel_package_name, "postgresql${package_version}-devel")
$java_package_name = pick($java_package_name, "postgresql${package_version}-jdbc")
$plperl_package_name = pick($plperl_package_name, "postgresql${package_version}-plperl")
$service_name = pick($service_name, "postgresql-${version}")
$bindir = pick($bindir, "/usr/pgsql-${version}/bin")
$datadir = $::operatingsystem ? {
'Amazon' => pick($datadir, "/var/lib/pgsql9/${version}/data"),
default => pick($datadir, "/var/lib/pgsql/${version}/data"),
}
$confdir = pick($confdir, $datadir)
}
$psql_path = pick($psql_path, "${bindir}/psql")
$service_status = $service_status
$python_package_name = pick($python_package_name, 'python-psycopg2')
}
'Archlinux': {
# Based on the existing version of the firewall module, this is normally
# true for Archlinux, but archlinux users want more control.
# so they can set it themself
$firewall_supported = pick($firewall_supported, true)
$needs_initdb = pick($needs_initdb, true)
# Archlinux doesn't have a client-package but has a libs package which
# pulls in postgresql server
$client_package_name = pick($client_package_name, 'postgresql')
$server_package_name = pick($server_package_name, 'postgresql-libs')
$java_package_name = pick($java_package_name, 'postgresql-jdbc')
# Archlinux doesn't have develop packages
$devel_package_name = pick($devel_package_name, 'postgresql-devel')
# Archlinux does have postgresql-contrib but it isn't maintained
$contrib_package_name = pick($contrib_package_name,'undef')
# Archlinux postgresql package provides plperl
$plperl_package_name = pick($plperl_package_name, 'undef')
$service_name = pick($service_name, 'postgresql')
$bindir = pick($bindir, '/usr/bin')
$datadir = pick($datadir, '/var/lib/postgres/data')
$confdir = pick($confdir, $datadir)
$psql_path = pick($psql_path, "${bindir}/psql")
$service_status = $service_status
$python_package_name = pick($python_package_name, 'python-psycopg2')
}
'Debian': {
if $manage_package_repo == true {
$needs_initdb = pick($needs_initdb, true)
$service_name = pick($service_name, 'postgresql')
} else {
$needs_initdb = pick($needs_initdb, false)
$service_name = $::operatingsystem ? {
'Debian' => pick($service_name, 'postgresql'),
'Ubuntu' => $::lsbmajdistrelease ? {
'10' => pick($service_name, "postgresql-${version}"),
default => pick($service_name, 'postgresql'),
},
default => undef
}
}
$client_package_name = pick($client_package_name, "postgresql-client-${version}")
$server_package_name = pick($server_package_name, "postgresql-${version}")
$contrib_package_name = pick($contrib_package_name, "postgresql-contrib-${version}")
$devel_package_name = pick($devel_package_name, 'libpq-dev')
$java_package_name = pick($java_package_name, 'libpostgresql-jdbc-java')
$plperl_package_name = pick($plperl_package_name, "postgresql-plperl-${version}")
$python_package_name = pick($python_package_name, 'python-psycopg2')
$bindir = pick($bindir, "/usr/lib/postgresql/${version}/bin")
$datadir = pick($datadir, "/var/lib/postgresql/${version}/main")
$confdir = pick($confdir, "/etc/postgresql/${version}/main")
$service_status = pick($service_status, "/etc/init.d/${service_name} status | /bin/egrep -q 'Running clusters: .+|online'")
$psql_path = pick($psql_path, "/usr/bin/psql")
$firewall_supported = pick($firewall_supported, true)
}
'FreeBSD': {
$client_package_name = pick($client_package_name, "databases/postgresql${version}-client")
$server_package_name = pick($server_package_name, "databases/postgresql${version}-server")
$contrib_package_name = pick($contrib_package_name, "databases/postgresql${version}-contrib")
$devel_package_name = pick($devel_package_name, 'databases/postgresql-libpqxx3')
$java_package_name = pick($java_package_name, 'databases/postgresql-jdbc')
$plperl_package_name = pick($plperl_package_name, "databases/postgresql${version}-plperl")
$python_package_name = pick($python_package_name, 'databases/py-psycopg2')
$service_name = pick($service_name, 'postgresql')
$bindir = pick($bindir, '/usr/local/bin')
$datadir = pick($datadir, '/usr/local/pgsql/data')
$confdir = pick($confdir, '/usr/local/share/postgresql')
$service_status = pick($service_status, "/usr/local/etc/rc.d/${service_name} status")
$psql_path = pick($psql_path, "${bindir}/psql")
$firewall_supported = pick($firewall_supported, false)
$needs_initdb = pick($needs_initdb, true)
}
default: {
# Based on the existing version of the firewall module, this is normally
# false for other OS, but this allows an escape hatch to override it.
$firewall_supported = pick($firewall_supported, false)
$psql_path = pick($psql_path, "${bindir}/psql")
# Since we can't determine defaults on our own, we rely on users setting
# parameters with the postgresql::globals class. Here we are checking
# that the mandatory minimum is set for the module to operate.
$err_prefix = "Module ${module_name} does not provide defaults for osfamily: ${::osfamily} operatingsystem: ${::operatingsystem}; please specify a value for ${module_name}::globals::"
if ($needs_initdb == undef) { fail("${err_prefix}needs_initdb") }
if ($service_name == undef) { fail("${err_prefix}service_name") }
if ($client_package_name == undef) { fail("${err_prefix}client_package_name") }
if ($server_package_name == undef) { fail("${err_prefix}server_package_name") }
if ($bindir == undef) { fail("${err_prefix}bindir") }
if ($datadir == undef) { fail("${err_prefix}datadir") }
if ($confdir == undef) { fail("${err_prefix}confdir") }
}
}
$initdb_path = pick($initdb_path, "${bindir}/initdb")
$createdb_path = pick($createdb_path, "${bindir}/createdb")
$pg_hba_conf_path = pick($pg_hba_conf_path, "${confdir}/pg_hba.conf")
$pg_hba_conf_defaults = pick($pg_hba_conf_defaults, true)
$postgresql_conf_path = pick($postgresql_conf_path, "${confdir}/postgresql.conf")
$default_database = pick($default_database, 'postgres')
if($version == 'unknown') {
fail('No preferred version defined or automatically detected.')
}
}

View file

@ -0,0 +1,22 @@
# PRIVATE CLASS: do not use directly
class postgresql::repo (
$ensure = $postgresql::params::ensure,
$version = undef
) inherits postgresql::params {
case $::osfamily {
'RedHat', 'Linux': {
if $version == undef {
fail("The parameter 'version' for 'postgresql::repo' is undefined. You must always define it when osfamily == Redhat or Linux")
}
class { 'postgresql::repo::yum_postgresql_org': }
}
'Debian': {
class { 'postgresql::repo::apt_postgresql_org': }
}
default: {
fail("Unsupported managed repository for osfamily: ${::osfamily}, operatingsystem: ${::operatingsystem}, module ${module_name} currently only supports managing repos for osfamily RedHat and Debian")
}
}
}

View file

@ -0,0 +1,30 @@
# PRIVATE CLASS: do not use directly
class postgresql::repo::apt_postgresql_org inherits postgresql::repo {
if($ensure == 'present' or $ensure == true) {
# Here we have tried to replicate the instructions on the PostgreSQL site:
#
# http://www.postgresql.org/download/linux/debian/
#
apt::pin { 'apt.postgresql.org':
originator => 'apt.postgresql.org',
priority => 500,
}->
apt::source { 'apt.postgresql.org':
location => 'http://apt.postgresql.org/pub/repos/apt/',
release => "${::lsbdistcodename}-pgdg",
repos => "main ${version}",
key => 'ACCC4CF8',
key_source => 'http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc',
include_src => false,
}
Apt::Source['apt.postgresql.org']->Package<|tag == 'postgresql'|>
} else {
apt::source { 'apt.postgresql.org':
ensure => absent,
}
apt::pin { 'apt.postgresql.org':
ensure => absent,
}
}
}

View file

@ -0,0 +1,38 @@
# PRIVATE CLASS: do not use directly
class postgresql::repo::yum_postgresql_org inherits postgresql::repo {
$version_parts = split($version, '[.]')
$package_version = "${version_parts[0]}${version_parts[1]}"
$gpg_key_path = "/etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-${package_version}"
if ($ensure == 'present' or $ensure == true) {
file { $gpg_key_path:
source => 'puppet:///modules/postgresql/RPM-GPG-KEY-PGDG',
before => Yumrepo['yum.postgresql.org']
}
if($::operatingsystem == 'Fedora') {
$label1 = 'fedora'
$label2 = $label1
} else {
$label1 = 'redhat'
$label2 = 'rhel'
}
yumrepo { 'yum.postgresql.org':
descr => "PostgreSQL ${version} \$releasever - \$basearch",
baseurl => "http://yum.postgresql.org/${version}/${label1}/${label2}-\$releasever-\$basearch",
enabled => 1,
gpgcheck => 1,
gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-${package_version}",
}
Yumrepo['yum.postgresql.org'] -> Package<|tag == 'postgresql'|>
} else {
yumrepo { 'yum.postgresql.org':
enabled => absent,
}->
file { $gpg_key_path:
ensure => absent,
}
}
}

View file

@ -0,0 +1,73 @@
# This installs a PostgreSQL server. See README.md for more details.
class postgresql::server (
$ensure = $postgresql::params::ensure,
$version = $postgresql::params::version,
$postgres_password = undef,
$package_name = $postgresql::params::server_package_name,
$client_package_name = $postgresql::params::client_package_name,
$package_ensure = $ensure,
$plperl_package_name = $postgresql::params::plperl_package_name,
$service_name = $postgresql::params::service_name,
$service_provider = $postgresql::params::service_provider,
$service_status = $postgresql::params::service_status,
$default_database = $postgresql::params::default_database,
$listen_addresses = $postgresql::params::listen_addresses,
$ip_mask_deny_postgres_user = $postgresql::params::ip_mask_deny_postgres_user,
$ip_mask_allow_all_users = $postgresql::params::ip_mask_allow_all_users,
$ipv4acls = $postgresql::params::ipv4acls,
$ipv6acls = $postgresql::params::ipv6acls,
$initdb_path = $postgresql::params::initdb_path,
$createdb_path = $postgresql::params::createdb_path,
$psql_path = $postgresql::params::psql_path,
$pg_hba_conf_path = $postgresql::params::pg_hba_conf_path,
$postgresql_conf_path = $postgresql::params::postgresql_conf_path,
$datadir = $postgresql::params::datadir,
$xlogdir = $postgresql::params::xlogdir,
$pg_hba_conf_defaults = $postgresql::params::pg_hba_conf_defaults,
$user = $postgresql::params::user,
$group = $postgresql::params::group,
$needs_initdb = $postgresql::params::needs_initdb,
$encoding = $postgresql::params::encoding,
$locale = $postgresql::params::locale,
$manage_firewall = $postgresql::params::manage_firewall,
$manage_pg_hba_conf = $postgresql::params::manage_pg_hba_conf,
$firewall_supported = $postgresql::params::firewall_supported
) inherits postgresql::params {
$pg = 'postgresql::server'
if ($ensure == 'present' or $ensure == true) {
# Reload has its own ordering, specified by other defines
class { "${pg}::reload": require => Class["${pg}::install"] }
anchor { "${pg}::start": }->
class { "${pg}::install": }->
class { "${pg}::initdb": }->
class { "${pg}::config": }->
class { "${pg}::service": }->
class { "${pg}::passwd": }->
class { "${pg}::firewall": }->
anchor { "${pg}::end": }
} else {
anchor { "${pg}::start": }->
class { "${pg}::firewall": }->
class { "${pg}::passwd": }->
class { "${pg}::service": }->
class { "${pg}::install": }->
class { "${pg}::initdb": }->
class { "${pg}::config": }->
anchor { "${pg}::end": }
}
}

View file

@ -0,0 +1,108 @@
# PRIVATE CLASS: do not call directly
class postgresql::server::config {
$ensure = $postgresql::server::ensure
$ip_mask_deny_postgres_user = $postgresql::server::ip_mask_deny_postgres_user
$ip_mask_allow_all_users = $postgresql::server::ip_mask_allow_all_users
$listen_addresses = $postgresql::server::listen_addresses
$ipv4acls = $postgresql::server::ipv4acls
$ipv6acls = $postgresql::server::ipv6acls
$pg_hba_conf_path = $postgresql::server::pg_hba_conf_path
$postgresql_conf_path = $postgresql::server::postgresql_conf_path
$pg_hba_conf_defaults = $postgresql::server::pg_hba_conf_defaults
$user = $postgresql::server::user
$group = $postgresql::server::group
$version = $postgresql::server::version
$manage_pg_hba_conf = $postgresql::server::manage_pg_hba_conf
if ($ensure == 'present' or $ensure == true) {
if ($manage_pg_hba_conf == true) {
# Prepare the main pg_hba file
concat { $pg_hba_conf_path:
owner => 0,
group => $group,
mode => '0640',
warn => true,
notify => Class['postgresql::server::reload'],
}
if $pg_hba_conf_defaults {
Postgresql::Server::Pg_hba_rule {
database => 'all',
user => 'all',
}
# Lets setup the base rules
$local_auth_option = $version ? {
'8.1' => 'sameuser',
default => undef,
}
postgresql::server::pg_hba_rule { 'local access as postgres user':
type => 'local',
user => $user,
auth_method => 'ident',
auth_option => $local_auth_option,
order => '001',
}
postgresql::server::pg_hba_rule { 'local access to database with same name':
type => 'local',
auth_method => 'ident',
auth_option => $local_auth_option,
order => '002',
}
postgresql::server::pg_hba_rule { 'allow localhost TCP access to postgresql user':
type => 'host',
user => $user,
address => '127.0.0.1/32',
auth_method => 'md5',
order => '003',
}
postgresql::server::pg_hba_rule { 'deny access to postgresql user':
type => 'host',
user => $user,
address => $ip_mask_deny_postgres_user,
auth_method => 'reject',
order => '004',
}
# ipv4acls are passed as an array of rule strings, here we transform
# them into a resources hash, and pass the result to create_resources
$ipv4acl_resources = postgresql_acls_to_resources_hash($ipv4acls,
'ipv4acls', 10)
create_resources('postgresql::server::pg_hba_rule', $ipv4acl_resources)
postgresql::server::pg_hba_rule { 'allow access to all users':
type => 'host',
address => $ip_mask_allow_all_users,
auth_method => 'md5',
order => '100',
}
postgresql::server::pg_hba_rule { 'allow access to ipv6 localhost':
type => 'host',
address => '::1/128',
auth_method => 'md5',
order => '101',
}
# ipv6acls are passed as an array of rule strings, here we transform
# them into a resources hash, and pass the result to create_resources
$ipv6acl_resources = postgresql_acls_to_resources_hash($ipv6acls,
'ipv6acls', 102)
create_resources('postgresql::server::pg_hba_rule', $ipv6acl_resources)
}
}
# We must set a "listen_addresses" line in the postgresql.conf if we
# want to allow any connections from remote hosts.
postgresql::server::config_entry { 'listen_addresses':
value => $listen_addresses,
}
} else {
file { $pg_hba_conf_path:
ensure => absent,
}
file { $postgresql_conf_path:
ensure => absent,
}
}
}

View file

@ -0,0 +1,43 @@
# Manage a postgresql.conf entry. See README.md for more details.
define postgresql::server::config_entry (
$ensure = 'present',
$value = undef,
$path = false
) {
$postgresql_conf_path = $postgresql::server::postgresql_conf_path
$target = $path ? {
false => $postgresql_conf_path,
default => $path,
}
case $name {
/data_directory|hba_file|ident_file|include|listen_addresses|port|max_connections|superuser_reserved_connections|unix_socket_directory|unix_socket_group|unix_socket_permissions|bonjour|bonjour_name|ssl|ssl_ciphers|shared_buffers|max_prepared_transactions|max_files_per_process|shared_preload_libraries|wal_level|wal_buffers|archive_mode|max_wal_senders|hot_standby|logging_collector|silent_mode|track_activity_query_size|autovacuum_max_workers|autovacuum_freeze_max_age|max_locks_per_transaction|max_pred_locks_per_transaction|restart_after_crash|lc_messages|lc_monetary|lc_numeric|lc_time/: {
Postgresql_conf {
notify => Class['postgresql::server::service'],
before => Class['postgresql::server::reload'],
}
}
default: {
Postgresql_conf {
notify => Class['postgresql::server::reload'],
}
}
}
case $ensure {
/present|absent/: {
postgresql_conf { $name:
ensure => $ensure,
target => $target,
value => $value,
require => Class['postgresql::server::initdb'],
}
}
default: {
fail("Unknown value for ensure '${ensure}'.")
}
}
}

View file

@ -0,0 +1,27 @@
# Install the contrib postgresql packaging. See README.md for more details.
class postgresql::server::contrib (
$package_name = $postgresql::params::contrib_package_name,
$package_ensure = 'present'
) inherits postgresql::params {
validate_string($package_name)
package { 'postgresql-contrib':
ensure => $package_ensure,
name => $package_name,
tag => 'postgresql',
}
if($package_ensure == 'present' or $package_ensure == true) {
anchor { 'postgresql::server::contrib::start': }->
Class['postgresql::server::install']->
Package['postgresql-contrib']->
Class['postgresql::server::service']->
anchor { 'postgresql::server::contrib::end': }
} else {
anchor { 'postgresql::server::contrib::start': }->
Class['postgresql::server::service']->
Package['postgresql-contrib']->
Class['postgresql::server::install']->
anchor { 'postgresql::server::contrib::end': }
}
}

View file

@ -0,0 +1,76 @@
# Define for creating a database. See README.md for more details.
define postgresql::server::database(
$dbname = $title,
$owner = $postgresql::server::user,
$tablespace = undef,
$template = 'template0',
$encoding = $postgresql::server::encoding,
$locale = $postgresql::server::locale,
$istemplate = false
) {
$createdb_path = $postgresql::server::createdb_path
$user = $postgresql::server::user
$group = $postgresql::server::group
$psql_path = $postgresql::server::psql_path
$version = $postgresql::server::version
# Set the defaults for the postgresql_psql resource
Postgresql_psql {
psql_user => $user,
psql_group => $group,
psql_path => $psql_path,
}
# Optionally set the locale switch. Older versions of createdb may not accept
# --locale, so if the parameter is undefined its safer not to pass it.
if ($version != '8.1') {
$locale_option = $locale ? {
undef => '',
default => "--locale=${locale} ",
}
$public_revoke_privilege = 'CONNECT'
} else {
$locale_option = ''
$public_revoke_privilege = 'ALL'
}
$encoding_option = $encoding ? {
undef => '',
default => "--encoding '${encoding}' ",
}
$tablespace_option = $tablespace ? {
undef => '',
default => "--tablespace='${tablespace}' ",
}
$createdb_command = "${createdb_path} --owner='${owner}' --template=${template} ${encoding_option}${locale_option}${tablespace_option} '${dbname}'"
postgresql_psql { "Check for existence of db '${dbname}'":
command => 'SELECT 1',
unless => "SELECT datname FROM pg_database WHERE datname='${dbname}'",
require => Class['postgresql::server::service']
}~>
exec { $createdb_command :
refreshonly => true,
user => $user,
logoutput => on_failure,
}~>
# This will prevent users from connecting to the database unless they've been
# granted privileges.
postgresql_psql {"REVOKE ${public_revoke_privilege} ON DATABASE \"${dbname}\" FROM public":
db => $user,
refreshonly => true,
}
Exec [ $createdb_command ]->
postgresql_psql {"UPDATE pg_database SET datistemplate = ${istemplate} WHERE datname = '${dbname}'":
unless => "SELECT datname FROM pg_database WHERE datname = '${dbname}' AND datistemplate = ${istemplate}",
}
# Build up dependencies on tablespace
if($tablespace != undef and defined(Postgresql::Server::Tablespace[$tablespace])) {
Postgresql::Server::Tablespace[$tablespace]->Exec[$createdb_command]
}
}

View file

@ -0,0 +1,18 @@
# Manage a database grant. See README.md for more details.
define postgresql::server::database_grant(
$privilege,
$db,
$role,
$psql_db = undef,
$psql_user = undef
) {
postgresql::server::grant { "database:${name}":
role => $role,
db => $db,
privilege => $privilege,
object_type => 'DATABASE',
object_name => $db,
psql_db => $psql_db,
psql_user => $psql_user,
}
}

View file

@ -0,0 +1,38 @@
# Define for conveniently creating a role, database and assigning the correct
# permissions. See README.md for more details.
define postgresql::server::db (
$user,
$password,
$encoding = $postgresql::server::encoding,
$locale = $postgresql::server::locale,
$grant = 'ALL',
$tablespace = undef,
$template = 'template0',
$istemplate = false,
$owner = undef
) {
postgresql::server::database { $name:
encoding => $encoding,
tablespace => $tablespace,
template => $template,
locale => $locale,
istemplate => $istemplate,
owner => $owner,
}
if ! defined(Postgresql::Server::Role[$user]) {
postgresql::server::role { $user:
password_hash => $password,
}
}
postgresql::server::database_grant { "GRANT ${user} - ${grant} - ${name}":
privilege => $grant,
db => $name,
role => $user,
}
if($tablespace != undef and defined(Postgresql::Server::Tablespace[$tablespace])) {
Postgresql::Server::Tablespace[$tablespace]->Postgresql::Server::Database[$name]
}
}

View file

@ -0,0 +1,21 @@
# PRIVATE CLASS: do not use directly
class postgresql::server::firewall {
$ensure = $postgresql::server::ensure
$manage_firewall = $postgresql::server::manage_firewall
$firewall_supported = $postgresql::server::firewall_supported
if ($manage_firewall and $firewall_supported) {
if ($ensure == 'present' or $ensure == true) {
# TODO: get rid of hard-coded port
firewall { '5432 accept - postgres':
port => '5432',
proto => 'tcp',
action => 'accept',
}
} else {
firewall { '5432 accept - postgres':
ensure => absent,
}
}
}
}

View file

@ -0,0 +1,85 @@
# Define for granting permissions to roles. See README.md for more details.
define postgresql::server::grant (
$role,
$db,
$privilege = undef,
$object_type = 'database',
$object_name = $db,
$psql_db = $postgresql::server::user,
$psql_user = $postgresql::server::user
) {
$group = $postgresql::server::group
$psql_path = $postgresql::server::psql_path
## Munge the input values
$_object_type = upcase($object_type)
$_privilege = upcase($privilege)
## Validate that the object type is known
validate_string($_object_type,
#'COLUMN',
'DATABASE',
#'FOREIGN SERVER',
#'FOREIGN DATA WRAPPER',
#'FUNCTION',
#'PROCEDURAL LANGUAGE',
#'SCHEMA',
#'SEQUENCE',
'TABLE',
#'TABLESPACE',
#'VIEW',
)
## Validate that the object type's privilege is acceptable
# TODO: this is a terrible hack; if they pass "ALL" as the desired privilege,
# we need a way to test for it--and has_database_privilege does not
# recognize 'ALL' as a valid privilege name. So we probably need to
# hard-code a mapping between 'ALL' and the list of actual privileges that
# it entails, and loop over them to check them. That sort of thing will
# probably need to wait until we port this over to ruby, so, for now, we're
# just going to assume that if they have "CREATE" privileges on a database,
# then they have "ALL". (I told you that it was terrible!)
case $_object_type {
'DATABASE': {
$unless_privilege = $_privilege ? {
'ALL' => 'CREATE',
default => $_privilege,
}
validate_string($unless_privilege,'CREATE','CONNECT','TEMPORARY','TEMP',
'ALL','ALL PRIVILEGES')
$unless_function = 'has_database_privilege'
$on_db = $psql_db
}
'TABLE': {
$unless_privilege = $_privilege ? {
'ALL' => 'INSERT',
default => $_privilege,
}
validate_string($unless_privilege,'SELECT','INSERT','UPDATE','DELETE',
'TRUNCATE','REFERENCES','TRIGGER','ALL','ALL PRIVILEGES')
$unless_function = 'has_table_privilege'
$on_db = $db
}
default: {
fail("Missing privilege validation for object type ${_object_type}")
}
}
$grant_cmd = "GRANT ${_privilege} ON ${_object_type} \"${object_name}\" TO \"${role}\""
postgresql_psql { $grant_cmd:
db => $on_db,
psql_user => $psql_user,
psql_group => $group,
psql_path => $psql_path,
unless => "SELECT 1 WHERE ${unless_function}('${role}', '${object_name}', '${unless_privilege}')",
require => Class['postgresql::server']
}
if($role != undef and defined(Postgresql::Server::Role[$role])) {
Postgresql::Server::Role[$role]->Postgresql_psql[$grant_cmd]
}
if($db != undef and defined(Postgresql::Server::Database[$db])) {
Postgresql::Server::Database[$db]->Postgresql_psql[$grant_cmd]
}
}

View file

@ -0,0 +1,76 @@
# PRIVATE CLASS: do not call directly
class postgresql::server::initdb {
$ensure = $postgresql::server::ensure
$needs_initdb = $postgresql::server::needs_initdb
$initdb_path = $postgresql::server::initdb_path
$datadir = $postgresql::server::datadir
$xlogdir = $postgresql::server::xlogdir
$encoding = $postgresql::server::encoding
$locale = $postgresql::server::locale
$group = $postgresql::server::group
$user = $postgresql::server::user
if($ensure == 'present' or $ensure == true) {
# Make sure the data directory exists, and has the correct permissions.
file { $datadir:
ensure => directory,
owner => $user,
group => $group,
mode => '0700',
}
if($xlogdir) {
# Make sure the xlog directory exists, and has the correct permissions.
file { $xlogdir:
ensure => directory,
owner => $user,
group => $group,
mode => '0700',
}
}
if($needs_initdb) {
# Build up the initdb command.
#
# We optionally add the locale switch if specified. Older versions of the
# initdb command don't accept this switch. So if the user didn't pass the
# parameter, lets not pass the switch at all.
$ic_base = "${initdb_path} --encoding '${encoding}' --pgdata '${datadir}'"
$ic_xlog = $xlogdir ? {
undef => $ic_base,
default => "${ic_base} --xlogdir '${xlogdir}'"
}
$initdb_command = $locale ? {
undef => $ic_xlog,
default => "${ic_xlog} --locale '${locale}'"
}
# This runs the initdb command, we use the existance of the PG_VERSION
# file to ensure we don't keep running this command.
exec { 'postgresql_initdb':
command => $initdb_command,
creates => "${datadir}/PG_VERSION",
user => $user,
group => $group,
logoutput => on_failure,
require => File[$datadir],
}
}
} else {
# Purge data directory if ensure => absent
file { $datadir:
ensure => absent,
recurse => true,
force => true,
}
if($xlogdir) {
# Make sure the xlog directory exists, and has the correct permissions.
file { $xlogdir:
ensure => absent,
recurse => true,
force => true,
}
}
}
}

View file

@ -0,0 +1,49 @@
# PRIVATE CLASS: do not call directly
class postgresql::server::install {
$package_ensure = $postgresql::server::package_ensure
$package_name = $postgresql::server::package_name
$client_package_name = $postgresql::server::client_package_name
# This is necessary to ensure that the extra client package that was
# installed automatically by the server package is removed and all
# of its dependencies are removed also. Without this later installation
# of the native Ubuntu packages will fail.
if($::operatingsystem == 'Ubuntu' and $package_ensure == 'absent') {
# This is an exec, because we want to invoke autoremove.
#
# An alternative would be to have a full list of packages, but that seemed
# more problematic to maintain, not to mention the conflict with the
# client class will create duplicate resources.
exec { 'apt-get-autoremove-postgresql-client-XX':
command => "apt-get autoremove --purge --yes ${client_package_name}",
onlyif => "dpkg -l ${client_package_name} | grep -e '^ii'",
logoutput => on_failure,
path => '/usr/bin:/bin:/usr/sbin/:/sbin',
}
# This will clean up anything we miss
exec { 'apt-get-autoremove-postgresql-client-brute':
command => "dpkg -P postgresql*",
onlyif => "dpkg -l postgresql* | grep -e '^ii'",
logoutput => on_failure,
path => '/usr/bin:/bin:/usr/sbin/:/sbin',
}
}
$_package_ensure = $package_ensure ? {
true => 'present',
false => 'purged',
'absent' => 'purged',
default => $package_ensure,
}
package { 'postgresql-server':
ensure => $_package_ensure,
name => $package_name,
# This is searched for to create relationships with the package repos, be
# careful about its removal
tag => 'postgresql',
}
}

View file

@ -0,0 +1,35 @@
# PRIVATE CLASS: do not call directly
class postgresql::server::passwd {
$ensure = $postgresql::server::ensure
$postgres_password = $postgresql::server::postgres_password
$user = $postgresql::server::user
$group = $postgresql::server::group
$psql_path = $postgresql::server::psql_path
if($ensure == 'present' or $ensure == true) {
if ($postgres_password != undef) {
# NOTE: this password-setting logic relies on the pg_hba.conf being
# configured to allow the postgres system user to connect via psql
# without specifying a password ('ident' or 'trust' security). This is
# the default for pg_hba.conf.
$escaped = postgresql_escape($postgres_password)
$env = "env PGPASSWORD='${postgres_password}'"
exec { 'set_postgres_postgrespw':
# This command works w/no password because we run it as postgres system
# user
command => "${psql_path} -c 'ALTER ROLE \"${user}\" PASSWORD ${escaped}'",
user => $user,
group => $group,
logoutput => true,
cwd => '/tmp',
# With this command we're passing -h to force TCP authentication, which
# does require a password. We specify the password via the PGPASSWORD
# environment variable. If the password is correct (current), this
# command will exit with an exit code of 0, which will prevent the main
# command from running.
unless => "${env} ${psql_path} -h localhost -c 'select 1' > /dev/null",
path => '/usr/bin:/usr/local/bin:/bin',
}
}
}
}

View file

@ -0,0 +1,52 @@
# This resource manages an individual rule that applies to the file defined in
# $target. See README.md for more details.
define postgresql::server::pg_hba_rule(
$type,
$database,
$user,
$auth_method,
$address = undef,
$description = 'none',
$auth_option = undef,
$order = '150',
# Needed for testing primarily, support for multiple files is not really
# working.
$target = $postgresql::server::pg_hba_conf_path
) {
if $postgresql::server::manage_pg_hba_conf == false {
fail('postgresql::server::manage_pg_hba_conf has been disabled, so this resource is now unused and redundant, either enable that option or remove this resource from your manifests')
} else {
validate_re($type, '^(local|host|hostssl|hostnossl)$',
"The type you specified [${type}] must be one of: local, host, hostssl, hostnosssl")
if($type =~ /^host/ and $address == undef) {
fail('You must specify an address property when type is host based')
}
$allowed_auth_methods = $postgresql::server::version ? {
'9.3' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'],
'9.2' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'],
'9.1' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'],
'9.0' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'radius', 'cert', 'pam'],
'8.4' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'cert', 'pam'],
'8.3' => ['trust', 'reject', 'md5', 'sha1', 'crypt', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'pam'],
'8.2' => ['trust', 'reject', 'md5', 'crypt', 'password', 'krb5', 'ident', 'ldap', 'pam'],
'8.1' => ['trust', 'reject', 'md5', 'crypt', 'password', 'krb5', 'ident', 'pam'],
default => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam', 'crypt']
}
$auth_method_regex = join(['^(', join($allowed_auth_methods, '|'), ')$'],'')
validate_re($auth_method, $auth_method_regex,
join(["The auth_method you specified [${auth_method}] must be one of: ", join($allowed_auth_methods, ', ')],''))
# Create a rule fragment
$fragname = "pg_hba_rule_${name}"
concat::fragment { $fragname:
target => $target,
content => template('postgresql/pg_hba_rule.conf'),
order => $order,
}
}
}

View file

@ -0,0 +1,27 @@
# This class installs the PL/Perl procedural language for postgresql. See
# README.md for more details.
class postgresql::server::plperl(
$package_ensure = 'present',
$package_name = $postgresql::server::plperl_package_name
) {
package { 'postgresql-plperl':
ensure => $package_ensure,
name => $package_name,
tag => 'postgresql',
}
if($package_ensure == 'present' or $package_ensure == true) {
anchor { 'postgresql::server::plperl::start': }->
Class['postgresql::server::install']->
Package['postgresql-plperl']->
Class['postgresql::server::service']->
anchor { 'postgresql::server::plperl::end': }
} else {
anchor { 'postgresql::server::plperl::start': }->
Class['postgresql::server::service']->
Package['postgresql-plperl']->
Class['postgresql::server::install']->
anchor { 'postgresql::server::plperl::end': }
}
}

View file

@ -0,0 +1,15 @@
# PRIVATE CLASS: do not use directly
class postgresql::server::reload {
$ensure = $postgresql::server::ensure
$service_name = $postgresql::server::service_name
$service_status = $postgresql::server::service_status
if($ensure == 'present' or $ensure == true) {
exec { 'postgresql_reload':
path => '/usr/bin:/usr/sbin:/bin:/sbin',
command => "service ${service_name} reload",
onlyif => $service_status,
refreshonly => true,
}
}
}

View file

@ -0,0 +1,85 @@
# Define for creating a database role. See README.md for more information
define postgresql::server::role(
$password_hash = false,
$createdb = false,
$createrole = false,
$db = $postgresql::server::user,
$login = true,
$superuser = false,
$replication = false,
$connection_limit = '-1',
$username = $title
) {
$psql_user = $postgresql::server::user
$psql_group = $postgresql::server::group
$psql_path = $postgresql::server::psql_path
$version = $postgresql::server::version
$login_sql = $login ? { true => 'LOGIN', default => 'NOLOGIN' }
$createrole_sql = $createrole ? { true => 'CREATEROLE', default => 'NOCREATEROLE' }
$createdb_sql = $createdb ? { true => 'CREATEDB', default => 'NOCREATEDB' }
$superuser_sql = $superuser ? { true => 'SUPERUSER', default => 'NOSUPERUSER' }
$replication_sql = $replication ? { true => 'REPLICATION', default => '' }
if ($password_hash != false) {
$password_sql = "ENCRYPTED PASSWORD '${password_hash}'"
} else {
$password_sql = ''
}
Postgresql_psql {
db => $db,
psql_user => $psql_user,
psql_group => $psql_group,
psql_path => $psql_path,
require => [ Postgresql_psql["CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}"], Class['postgresql::server'] ],
}
postgresql_psql {"CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}":
unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}'",
require => Class['Postgresql::Server'],
}
postgresql_psql {"ALTER ROLE \"${username}\" ${superuser_sql}":
unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolsuper=${superuser}",
}
postgresql_psql {"ALTER ROLE \"${username}\" ${createdb_sql}":
unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolcreatedb=${createdb}",
}
postgresql_psql {"ALTER ROLE \"${username}\" ${createrole_sql}":
unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolcreaterole=${createrole}",
}
postgresql_psql {"ALTER ROLE \"${username}\" ${login_sql}":
unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolcanlogin=${login}",
}
if(versioncmp($version, '9.1') >= 0) {
if $replication_sql == '' {
postgresql_psql {"ALTER ROLE \"${username}\" NOREPLICATION":
unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolreplication=${replication}",
}
} else {
postgresql_psql {"ALTER ROLE \"${username}\" ${replication_sql}":
unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolreplication=${replication}",
}
}
}
postgresql_psql {"ALTER ROLE \"${username}\" CONNECTION LIMIT ${connection_limit}":
unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}' and rolconnlimit=${connection_limit}",
}
if $password_hash {
if($password_hash =~ /^md5.+/) {
$pwd_hash_sql = $password_hash
} else {
$pwd_md5 = md5("${password_hash}${username}")
$pwd_hash_sql = "md5${pwd_md5}"
}
postgresql_psql {"ALTER ROLE \"${username}\" ${password_sql}":
unless => "SELECT usename FROM pg_shadow WHERE usename='${username}' and passwd='${pwd_hash_sql}'",
}
}
}

View file

@ -0,0 +1,45 @@
# PRIVATE CLASS: do not call directly
class postgresql::server::service {
$ensure = $postgresql::server::ensure
$service_name = $postgresql::server::service_name
$service_provider = $postgresql::server::service_provider
$service_status = $postgresql::server::service_status
$user = $postgresql::server::user
$default_database = $postgresql::server::default_database
$service_ensure = $ensure ? {
present => true,
absent => false,
default => $ensure
}
anchor { 'postgresql::server::service::begin': }
service { 'postgresqld':
ensure => $service_ensure,
name => $service_name,
enable => $service_ensure,
provider => $service_provider,
hasstatus => true,
status => $service_status,
}
if($service_ensure) {
# This blocks the class before continuing if chained correctly, making
# sure the service really is 'up' before continuing.
#
# Without it, we may continue doing more work before the database is
# prepared leading to a nasty race condition.
postgresql::validate_db_connection { 'validate_service_is_running':
run_as => $user,
database_name => $default_database,
sleep => 1,
tries => 60,
create_db_first => false,
require => Service['postgresqld'],
before => Anchor['postgresql::server::service::end']
}
}
anchor { 'postgresql::server::service::end': }
}

View file

@ -0,0 +1,20 @@
# This resource wraps the grant resource to manage table grants specifically.
# See README.md for more details.
define postgresql::server::table_grant(
$privilege,
$table,
$db,
$role,
$psql_db = undef,
$psql_user = undef
) {
postgresql::server::grant { "table:${name}":
role => $role,
db => $db,
privilege => $privilege,
object_type => 'TABLE',
object_name => $table,
psql_db => $psql_db,
psql_user => $psql_user,
}
}

View file

@ -0,0 +1,42 @@
# This module creates tablespace. See README.md for more details.
define postgresql::server::tablespace(
$location,
$owner = undef,
$spcname = $title
) {
$user = $postgresql::server::user
$group = $postgresql::server::group
$psql_path = $postgresql::server::psql_path
Postgresql_psql {
psql_user => $user,
psql_group => $group,
psql_path => $psql_path,
}
if ($owner == undef) {
$owner_section = ''
} else {
$owner_section = "OWNER \"${owner}\""
}
$create_tablespace_command = "CREATE TABLESPACE \"${spcname}\" ${owner_section} LOCATION '${location}'"
file { $location:
ensure => directory,
owner => $user,
group => $group,
mode => '0700',
}
$create_ts = "Create tablespace '${spcname}'"
postgresql_psql { "Create tablespace '${spcname}'":
command => $create_tablespace_command,
unless => "SELECT spcname FROM pg_tablespace WHERE spcname='${spcname}'",
require => [Class['postgresql::server'], File[$location]],
}
if($owner != undef and defined(Postgresql::Server::Role[$owner])) {
Postgresql::Server::Role[$owner]->Postgresql_psql[$create_ts]
}
}

View file

@ -0,0 +1,75 @@
# This type validates that a successful postgres connection can be established
# between the node on which this resource is run and a specified postgres
# instance (host/port/user/password/database name).
#
# See README.md for more details.
define postgresql::validate_db_connection(
$database_host = undef,
$database_name = undef,
$database_password = undef,
$database_username = undef,
$database_port = undef,
$run_as = undef,
$sleep = 2,
$tries = 10,
$create_db_first = true
) {
require postgresql::client
include postgresql::params
$psql_path = $postgresql::params::psql_path
$cmd_init = "${psql_path} --tuples-only --quiet "
$cmd_host = $database_host ? {
default => "-h ${database_host} ",
undef => "",
}
$cmd_user = $database_username ? {
default => "-U ${database_username} ",
undef => "",
}
$cmd_port = $database_port ? {
default => "-p ${database_port} ",
undef => "",
}
$cmd_dbname = $database_name ? {
default => "--dbname ${database_name} ",
undef => "--dbname ${postgresql::params::default_database} ",
}
$env = $database_password ? {
default => "PGPASSWORD=${database_password}",
undef => undef,
}
$cmd = join([$cmd_init, $cmd_host, $cmd_user, $cmd_port, $cmd_dbname])
$validate_cmd = "/usr/local/bin/validate_postgresql_connection.sh ${sleep} ${tries} '${cmd}'"
# This is more of a safety valve, we add a little extra to compensate for the
# time it takes to run each psql command.
$timeout = (($sleep + 2) * $tries)
$exec_name = "validate postgres connection for ${database_host}/${database_name}"
exec { $exec_name:
command => "echo 'Unable to connect to defined database using: ${cmd}' && false",
unless => $validate_cmd,
cwd => '/tmp',
environment => $env,
logoutput => 'on_failure',
user => $run_as,
path => '/bin',
timeout => $timeout,
require => Package['postgresql-client'],
}
# This is a little bit of puppet magic. What we want to do here is make
# sure that if the validation and the database instance creation are being
# applied on the same machine, then the database resource is applied *before*
# the validation resource. Otherwise, the validation is guaranteed to fail
# on the first run.
#
# We accomplish this by using Puppet's resource collection syntax to search
# for the Database resource in our current catalog; if it exists, the
# appropriate relationship is created here.
if($create_db_first) {
Postgresql::Server::Database<|title == $database_name|> -> Exec[$exec_name]
}
}