diff --git a/.fixtures.yml b/.fixtures.yml index 44121bb..5dbd5d0 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -1,10 +1,8 @@ fixtures: repositories: - apt: - repo: "https://github.com/puppetlabs/puppetlabs-apt.git" - branch: "1.8.x" + apt: "https://github.com/puppetlabs/puppetlabs-apt.git" stdlib: "https://github.com/puppetlabs/puppetlabs-stdlib.git" firewall: "https://github.com/puppetlabs/puppetlabs-firewall.git" concat: "https://github.com/puppetlabs/puppetlabs-concat.git" symlinks: postgresql: "#{source_dir}" diff --git a/.gitattributes b/.gitattributes index 900ea0c..02d4646 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,5 @@ #This file is generated by ModuleSync, do not edit. -*.rb eol=lf +*.rb eol=lf *.erb eol=lf -*.pp eol=lf -*.sh eol=lf +*.pp eol=lf +*.sh eol=lf diff --git a/CHANGELOG.md b/CHANGELOG.md index 4946eff..521ae97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,876 +1,898 @@ +## Supported Release 5.0.0 +### Summary +This **major** release drops support for Puppet 3 and PostgreSQL 8.x, adds Puppet 4 data types, and deprecates the validate_db_connection type. + +#### Added +- `locales/` directory, .pot file, and i18n `config.yaml` +- `update_password` parameter to toggle password management per role +- **Puppet 4** type validation +- `postgresql_conn_validator` type + +#### Changed +- Updated default postgis versions in postgresql::globals +- Updated puppetlabs-concat and puppetlabs-apt dependencies +- default `log_line_prefix` has been removed +- `listen_addresses` now defaults to 'localhost' and can be set independently of a class declaration + +#### Fixed +- Fixed deprecated apt::source parameters +- Fix for default SUSE parameters +- Remove deprecated force parameter on concat resources +- Replace Puppet.version.to_f version comparison from spec_helper.rb ([MODULES-4528](https://tickets.puppetlabs.com/browse/MODULES-4528)) + ## Supported Release 4.9.0 ### Summary This release adds several types and, among other bugs, fixes an issue with the yum URL. #### Features - Modifying ownership of databases and schemas now available (MODULES-3247) - Use `module_workdir` to specify a custom directory in which to execute psql commands - `grant_role` and `grant` types added! - Support for parallel unit testing (parallel_tests) - Override download/installation repo URL with `repo_baseurl` - Set your timezone with `timezone` - Grant privileges on LANGUAGEs - Added support for Debian Stretch and Ubuntu Yakkety Yak #### Bugfixes - Usernames and passwords are now converted to strings before password hash is created - Specify default database name if it is not the username - Update to yum repo - Schema name conflicts fix ## Supported Release 4.8.0 ### Summary This release primarily fixes an issue with `postgresql_conf` values of ipaddresses being considered floats and not getting quoted. #### Features - Add `default_connect_settings` parameter to `postgresql::server` - Running under strict variables is now supported - Add timestamps into logs by default #### Bugfixes - Obscure password in postgresql\_psql type - Fix ip address quoting in postgresql\_conf type - Fix handling of systemd service on Ubuntu - Mark log_min_duration_statement setting as requiring a service restart - Add fixes for Fedora 23, Fedora 24, FreeBSD, OpenBSD - Fix environment handling to avoid "Overriding environment setting" message - Work around PUP-6385, using empty arrays instead of undef when specifying resource relationships - README editorial pass - Reduce whitespace in templates - Update build/test infrastructure ## Supported Release 4.7.1 ### Summary This release contains some bugfixes and documentation updates. #### Bugfixes - (MODULES-3024) Quote database objects when creating databases. - Properly escape case where password ends with '$'. - Fixes password change when postgres is configure to non-standard port. - Unpins concat dependency to be able to use concat 2.x. - Workaround to fix installing on Amazon Linux. - Fixes proper defaulting of `$service_provider` parameter. - Fixes postgres server init script naming on Amazon Linux. - Fixes service reload parameter on Arch Linux. - Adds missing onlyif_function to sequence grant code. - Fixes to the markdown of the README. ## Supported Release 4.7.0 ### Summary A release with a considerable amount of new features, including remote db support and several platform support updates. Various bugfixes including several to address warnings and a sizable README update. #### Features - Remote DB support - Connection-settings allows a hash of options that can be used when connecting to a remote DB. - Debian 8 support. - Updated systemd-override to support fedora and CentOS paths. - Adds the ability to define the extension name separately from the title of the resource, which allows you to add the extension to more than one database. - Added parameter to disable automatic service restarts on config changes. - Ubuntu 15.10 compatibility. - OpenBSD version is now 9.4. - Added .gitattributes to maintain line endings for .sh and .rb files. - Adds default postgis version for 9.5. - Allows float postgresql_conf values. - Schedule apt update after install of repo. #### Bugfixes - Fixed systemd-override for RedHat systems with unmanaged Yum repos. - Removed inherits postgresql::params. - Multi-node tests are now not ran by default. - Change apt::pin to apt_postgresql_org to prevent error message. - Removed syntax error near UTF8. - Removal of extra blanks and backslashes in README. - Double quotes now used around database name to prevent syntax error. - Removes ruby 1.8.7 and puppet 2.7 from travis-ci jobs. - Fixed paths to work on Amazon Linux. - Fixed quotes around locale options. - Huge README update. - Update to use current msync configs. - Fixes postgresql::server acceptance test descriptions. ## Supported Release 4.6.1 ###Summary Small release for support of newer PE versions. This increments the version of PE in the metadata.json file. ## 2015-09-01 - Supported Release 4.6.0 ### Summary This release adds a proxy feature for yum, Postgis improvements, and decoupling pg_hba_rule from postgresql::server. #### Features - Support setting a proxy for yum operations - Allow for undefined PostGIS version - Decouple pg_hba_rule from postgresql::server #### Bugfixes - Fix postgis default package name on RedHat ## 2015-07-27 - Supported Release 4.5.0 ### Summary This release adds sequence grants, some postgresql 9.4 fixes, and `onlyif` to the psql resource. ### Features - Add `onlyif` parameter to `postgresql_psql` - Add unsupported compatibility with Ubuntu 15.04 - Add unsupported compatibility with SLES 11/12 and OpenSuSE 13.2 - Add `postgresql::server::grant::onlyif_exists` attribute - Add `postgresql::server::table_grant::onlyif_exists` attribute - Add granting permissions on sequences ### Bugfixes - Added docs for `postgresql::server::grant` - Fix `pg_hba_conf_defaults => false` to not disable ipv4/ipv6 acls - Fix 9.4 for `postgresql::server::pg_hba_rule` ## 2015-07-07 - Supported Release 4.4.2 ### Summary This release fixes a bug introduced in 4.4.0. #### Bugfixes - Fixes `withenv` execution under Puppet 2.7. (MODULES-2185) ## 2015-07-01 - Supported Release 4.4.1 ### Summary This release fixes RHEL 7 & Fedora with manage_package_repo switched on. #### Bugfixes - Ensure manage_package_repo variable is in scope for systemd-override file for RHEL7 ## 2015-06-30 - Supported Release 4.4.0 ### Summary This release has several new features, bugfixes, and test improvements. #### Features - Adds a resource to manage recovery.conf. - Adds a parameter that allows the specification of a validate connection script in `postgresql::client`. - Adds support for plpython package management. - Adds support for postgresql-docs management. - Adds ability to make `postgresql::server::schema` titles unique. (MODULES-2049) - Updates puppetlabs-apt module dependency to support version 2.1.0. #### Bugfixes - Fix `postgresql_psql` parameter ordering to work on OpenBSD with Future Parser - Fix setting postgres role password (MODULES-1869) - Fix execution command with puppet <3.4 (MODULES-1923) - Fix Puppet.newtype deprecation warning (MODULES-2007) - Fix systemd override for manage_repo package versions - Fix Copy snakeoil certificate and key instead of symlinking #### Test Improvements - Allows setting BEAKER and BEAKER_RSPEC versions via environment variables. - Enables Unit testing on Travis CI with Puppet 4. - Cleans up spec_helper_acceptance.rb to use new puppet_install_helper gem. ## 2015-03-24 - Supported Release 4.3.0 ### Summary This release fixes compatibility with Puppet 4 and removes opportunities for local users to view the postgresql password. It also adds a new custom resource to aid in managing replication. #### Features - Add `postgresql::server::logdir` parameter to manage the logdir - Add `environment` parameter to `postgresql_psql` - Add `postgresql_replication_slot` custom resource #### Bugfixes - Fix for Puppet 4 - Don't print postgresql\_psql password in command - Allow `postgresql::validate_db_connection` for more than one host+port+database combo - Fix service command on Debian 8 and up - Fix `postgresql::server::extension` to work with custom user/group/port - Fix `postgresql::server::initdb` to work with custom user/group/port - Fix changing template1 encoding - Fix default `postgresql::server::grant::object_name` value - Fix idempotency of granting all tables in schema with `puppet::server::grant` - Fix lint warnings - Fix apt key to use 40 character key and bump puppetlabs-apt to >= 1.8.0 < 2.0.0 ##2015-03-10 - Supported Release 4.2.0 ###Summary This release has several new features including support for server extensions, improved grant support, and a number of bugfixes. ####Features - Changes to support OpenBSD - Add `service_reload` parameter to `postgresql::server` - Add `comment` parameter to `postgresql::server::database` (MODULES-1153) - Add `postgresql::server::extension` defined type - Add postgresql versions for utopic and jessie - Update `postgresql::server::grant` to support 'GRANT SCHEMA' and 'ALL TABLES IN SCHEMA' ####Bugfixes - Lint cleanup - Remove outdated upgrade info from README - Use correct TCP port when checking password - Create role before database - Fix template1 encoding on Debian - Require server package before user permissions - Fix `service_status` default for FreeBSD to allow PostgreSQL to start the first run - Fix invalid US-ASCII byte sequence in `postgresql::server::grant` comments - Reverted to default behavior for Debian systems as `pg_config` should not be overwritten (MODULES-1485) ##2014-11-04 - Supported Release 4.1.0 ###Summary This release adds the ability to change the PGDATA directory, and also includes documentation and test updates, future parser support, and a few other new features. ####Features - Future parser support - Documentation updates - Test updates - Add a link from `/etc/sysconfig/pgsql/postgresql-${version}` to `/etc/sysconfig/pgsql/postgresql` to support init scripts from the postgresql.org repo - Add support for changing the PGDATA directory - Set default versions for Fedora 21 and FreeBSD ##2014-09-03 - Supported Release 4.0.0 ###Summary This release removes the uninstall ability from the module, removes the firewall management, overhauls all of the acceptance testing, as well as adds better support for SuSE and Fedora. ###Backwards Incompatible changes. - Uninstall code removal. - Firewall management for Postgres. - Set manage_pg_ident_conf to true. ####Uninstallation removal We rely heavily on the ability to uninstall and reinstall postgres throughout our testing code, testing features like "can I move from the distribution packages to the upstream packages through the module" and over time we've learnt that the uninstall code simply doesn't work a lot of the time. It leaves traces of postgres behind or fails to remove certain packages on Ubuntu, and generally causes bits to be left on your system that you didn't expect. When we then reinstall things fail because it's not a true clean slate, and this causes us enormous problems during test. We've spent weeks and months working on these tests and they simply don't hold up well across the full range of PE platforms. Due to all these problems we've decided to take a stance on uninstalling in general. We feel that in 2014 it's completely reasonable and normal to have a good provisioning pipeline combined with your configuration management and the "correct" way to uninstall a fully installed service like postgresql is to simply reprovision the server without it in the first place. As a general rule this is how I personally like to work and I think is a good practice. ####I'm not OK with this! We understand that there are environments and situations in which it's not easy to do that. What if you accidently deployed Postgres on 100,000 nodes? In the future we're going to take a look at building some example 'profiles' to be found under examples/ within this module that can uninstall postgres on popular platforms. These can be modified and used in your specific case to uninstall postgresql. They will be much more brute force and reliant on deleting entire directories and require you to do more work up front in specifying where things are installed but we think it'll prove to be a much cleaner mechanism for this kind of thing rather than trying to weave it into the main module logic itself. ####Features - Removal of uninstall. - Removal of firewall management. - Tests ported to rspec3. - Acceptance tests rewritten. - Add a defined type for creating database schemas. - Add a pg_ident_rule defined type. - Set manage_pg_ident_conf to true. - Manage pg_ident.conf by default. - Improve selinux support for tablespace. - Remove deprecation warnings. - Support changing PGDATA on RedHat. - Add SLES 11 support. ####Bugfixes - Link pg_config binary into /usr/bin. - Fix fedora support by using systemd. - Initdb should create xlogdir if set. - Use a regular expression to match the major OS version on Ubuntu. ##2014-07-31 - Supported Release 3.4.2 ###Summary This release fixes recent Fedora versions. ####Features ####Bugfixes - Fix Fedora. ##2014-07-15 - Supported Release 3.4.1 ###Summary This release merely updates metadata.json so the module can be uninstalled and upgraded via the puppet module command. ##2014-04-14 - Supported Release 3.4.0 ###Summary This feature rolls up several important features, the biggest being PostGIS handling and allowing `port` to be set on postgresql::server in order to change the port that Postgres listens on. We've added support for RHEL7 and Ubuntu 14.04, as well as allowing you to manage the service via `service_ensure` finally. ####Features - Added `perl_package_name` for installing bindings. - Added `service_ensure` for allowing control of services. - Added `postgis_version` and postgis class for installing postgis. - Added `port` for selecting the port Postgres runs on. - Add support for RHEL7 and Ubuntu 14.04. - Add `default_db` to postgresql::server::database. - Widen the selection of unquoted parameters in postgresql_conf{} - Require the service within postgresql::server::reload for RHEL7. - Add `inherit` to postgresql::server::role. ####Bugfixes ##2014-03-04 - Supported Release 3.3.3 ###Summary This is a supported release. This release removes a testing symlink that can cause trouble on systems where /var is on a seperate filesystem from the modulepath. ####Features ####Bugfixes ####Known Bugs * SLES is not supported. ##2014-03-04 - Supported Release 3.3.2 ###Summary This is a supported release. It fixes a problem with updating passwords on postgresql.org distributed versions of PostgreSQL. ####Bugfixes - Correct psql path when setting password on custom versions. - Documentation updates - Test updates ####Known Bugs * SLES is not supported. ##2014-02-12 - Version 3.3.1 ####Bugfix: - Allow dynamic rubygems host ##2014-01-28 - Version 3.3.0 ###Summary This release rolls up a bunch of bugfixes our users have found and fixed for us over the last few months. This improves things for 9.1 users, and makes this module usable on FreeBSD. This release is dedicated to 'bma', who's suffering with Puppet 3.4.1 issues thanks to Puppet::Util::SUIDManager.run_and_capture. ####Features - Add lc_ config entry settings - Can pass template at database creation. - Add FreeBSD support. - Add support for customer `xlogdir` parameter. - Switch tests from rspec-system to beaker. (This isn't really a feature) ####Bugfixes - Properly fix the deprecated Puppet::Util::SUIDManager.run_and_capture errors. - Fix NOREPLICATION option for Postgres 9.1 - Wrong parameter name: manage_pg_conf -> manage_pg_hba_conf - Add $postgresql::server::client_package_name, referred to by install.pp - Add missing service_provider/service_name descriptions in ::globals. - Fix several smaller typos/issues throughout. - Exec['postgresql_initdb'] needs to be done after $datadir exists - Prevent defined resources from floating in the catalog. - Fix granting all privileges on a table. - Add some missing privileges. - Remove deprecated and unused concat::fragment parameters. ##2013-11-05 - Version 3.2.0 ###Summary Add's support for Ubuntu 13.10 (and 14.04) as well as x, y, z. ####Features - Add versions for Ubuntu 13.10 and 14.04. - Use default_database in validate_db_connection instead of a hardcoded 'postgres' - Add globals/params layering for default_database. - Allow specification of default database name. ####Bugs - Fixes to the README. ##2013-10-25 - Version 3.1.0 ###Summary This is a minor feature and bug fix release. Firstly, the postgresql_psql type now includes a new parameter `search_path` which is equivalent to using `set search_path` which allows you to change the default schema search path. The default version of Fedora 17 has now been added, so that Fedora 17 users can enjoy the module. And finally we've extended the capabilities of the defined type postgresql::validate_db_connection so that now it can handle retrying and sleeping between retries. This feature has been monopolized to fix a bug we were seeing with startup race conditions, but it can also be used by remote systems to 'wait' for PostgreSQL to start before their Puppet run continues. ####Features - Defined $default_version for Fedora 17 (Bret Comnes) - add search_path attribute to postgresql_psql resource (Jeremy Kitchen) - (GH-198) Add wait and retry capability to validate_db_connection (Ken Barber) ####Bugs - enabling defined postgres user password without resetting on every puppet run (jonoterc) - periods are valid in configuration variables also (Jeremy Kitchen) - Add zero length string to join() function (Jarl Stefansson) - add require of install to reload class (cdenneen) - (GH-198) Fix race condition on postgresql startup (Ken Barber) - Remove concat::setup for include in preparation for the next concat release (Ken Barber) ##2013-10-14 - Version 3.0.0 Final release of 3.0, enjoy! ##2013-10-14 - Version 3.0.0-rc3 ###Summary Add a parameter to unmanage pg_hba.conf to fix a regression from 2.5, as well as allowing owner to be passed into x. ####Features - `manage_pg_hba_conf` parameter added to control pg_hba.conf management. - `owner` parameter added to server::db. ##2013-10-09 - Version 3.0.0-rc2 ###Summary A few bugfixes have been found since -rc1. ####Fixes - Special case for $datadir on Amazon - Fix documentation about username/password for the postgresql_hash function ##2013-10-01 - Version 3.0.0-rc1 ###Summary Version 3 was a major rewrite to fix some internal dependency issues, and to make the new Public API more clear. As a consequence a lot of things have changed for version 3 and older revisions that we will try to outline here. (NOTE: The format of this CHANGELOG differs to normal in an attempt to explain the scope of changes) * Server specific objects now moved under `postgresql::server::` namespace: To restructure server specific elements under the `postgresql::server::` namespaces the following objects were renamed as such: `postgresql::database` -> `postgresql::server::database` `postgresql::database_grant` -> `postgresql::server::database_grant` `postgresql::db` -> `postgresql::server::db` `postgresql::grant` -> `postgresql::server::grant` `postgresql::pg_hba_rule` -> `postgresql::server::pg_hba_rule` `postgresql::plperl` -> `postgresql::server::plperl` `postgresql::contrib` -> `postgresql::server::contrib` `postgresql::role` -> `postgresql::server::role` `postgresql::table_grant` -> `postgresql::server::table_grant` `postgresql::tablespace` -> `postgresql::server::tablespace` * New `postgresql::server::config_entry` resource for managing configuration: Previously we used the `file_line` resource to modify `postgresql.conf`. This new revision now adds a new resource named `postgresql::server::config_entry` for managing this file. For example: ```puppet postgresql::server::config_entry { 'check_function_bodies': value => 'off', } ``` If you were using `file_line` for this purpose, you should change to this new methodology. * `postgresql_puppet_extras.conf` has been removed: Now that we have a methodology for managing `postgresql.conf`, and due to concerns over the file management methodology using an `exec { 'touch ...': }` as a way to create an empty file the existing postgresql\_puppet\_extras.conf file is no longer managed by this module. If you wish to recreate this methodology yourself, use this pattern: ```puppet class { 'postgresql::server': } $extras = "/tmp/include.conf" file { $extras: content => 'max_connections = 123', notify => Class['postgresql::server::service'], }-> postgresql::server::config_entry { 'include': value => $extras, } ``` * All uses of the parameter `charset` changed to `encoding`: Since PostgreSQL uses the terminology `encoding` not `charset` the parameter has been made consisent across all classes and resources. * The `postgresql` base class is no longer how you set globals: The old global override pattern was less then optimal so it has been fixed, however we decided to demark this properly by specifying these overrides in the class `postgresql::global`. Consult the documentation for this class now to see what options are available. Also, some parameter elements have been moved between this and the `postgresql::server` class where it made sense. * `config_hash` parameter collapsed for the `postgresql::server` class: Because the `config_hash` was really passing data through to what was in effect an internal class (`postgresql::config`). And since we don't want this kind of internal exposure the parameters were collapsed up into the `postgresql::server` class directly. * Lots of changes to 'private' or 'undocumented' classes: If you were using these before, these have changed names. You should only use what is documented in this README.md, and if you don't have what you need you should raise a patch to add that feature to a public API. All internal classes now have a comment at the top indicating them as private to make sure the message is clear that they are not supported as Public API. * `pg_hba_conf_defaults` parameter included to turn off default pg\_hba rules: The defaults should be good enough for most cases (if not raise a bug) but if you simply need an escape hatch, this setting will turn off the defaults. If you want to do this, it may affect the rest of the module so make sure you replace the rules with something that continues operation. * `postgresql::database_user` has now been removed: Use `postgresql::server::role` instead. * `postgresql::psql` resource has now been removed: Use `postgresql_psql` instead. In the future we may recreate this as a wrapper to add extra capability, but it will not match the old behaviour. * `postgresql_default_version` fact has now been removed: It didn't make sense to have this logic in a fact any more, the logic has been moved into `postgresql::params`. * `ripienaar/concat` is no longer used, instead we use `puppetlabs/concat`: The older concat module is now deprecated and moved into the `puppetlabs/concat` namespace. Functionality is more or less identical, but you may need to intervene during the installing of this package - as both use the same `concat` namespace. --- ##2013-09-09 Release 2.5.0 ###Summary The focus of this release is primarily to capture the fixes done to the types and providers to make sure refreshonly works properly and to set the stage for the large scale refactoring work of 3.0.0. ####Features ####Bugfixes - Use boolean for refreshonly. - Fix postgresql::plperl documentation. - Add two missing parameters to config::beforeservice - Style fixes ##2013-08-01 Release 2.4.1 ###Summary This minor bugfix release solves an idempotency issue when using plain text passwords for the password_hash parameter for the postgresql::role defined type. Without this, users would continually see resource changes everytime your run Puppet. ####Bugfixes - Alter role call not idempotent with cleartext passwords (Ken Barber) ##2013-07-19 Release 2.4.0 ###Summary This updates adds the ability to change permissions on tables, create template databases from normal databases, manage PL-Perl's postgres package, and disable the management of `pg_hba.conf`. ####Features - Add `postgresql::table_grant` defined resource - Add `postgresql::plperl` class - Add `manage_pg_hba_conf` parameter to the `postgresql::config` class - Add `istemplate` parameter to the `postgresql::database` define ####Bugfixes - Update `postgresql::role` class to be able to update roles when modified instead of only on creation. - Update tests - Fix documentation of `postgresql::database_grant` ##2.3.0 This feature release includes the following changes: * Add a new parameter `owner` to the `database` type. This can be used to grant ownership of a new database to a specific user. (Bruno Harbulot) * Add support for operating systems other than Debian/RedHat, as long as the user supplies custom values for all of the required paths, package names, etc. (Chris Price) * Improved integration testing (Ken Barber) ##2.2.1 This release fixes a bug whereby one of our shell commands (psql) were not ran from a globally accessible directory. This was causing permission denied errors when the command attempted to change user without changing directory. Users of previous versions might have seen this error: Error: Error executing SQL; psql returned 256: 'could not change directory to "/root" This patch should correct that. #### Detail Changes * Set /tmp as default CWD for postgresql_psql ##2.2.0 This feature release introduces a number of new features and bug fixes. First of all it includes a new class named `postgresql::python` which provides you with a convenient way of install the python Postgresql client libraries. class { 'postgresql::python': } You are now able to use `postgresql::database_user` without having to specify a password_hash, useful for different authentication mechanisms that do not need passwords (ie. cert, local etc.). We've also provided a lot more advanced custom parameters now for greater control of your Postgresql installation. Consult the class documentation for PuppetDB in the README. This release in particular has largely been contributed by the community members below, a big thanks to one and all. #### Detailed Changes * Add support for psycopg installation (Flaper Fesp and Dan Prince) * Added default PostgreSQL version for Ubuntu 13.04 (Kamil Szymanski) * Add ability to create users without a password (Bruno Harbulot) * Three Puppet 2.6 fixes (Dominic Cleal) * Add explicit call to concat::setup when creating concat file (Dominic Cleal) * Fix readme typo (Jordi Boggiano) * Update postgres_default_version for Ubuntu (Kamil Szymanski) * Allow to set connection for noew role (Kamil Szymanski) * Fix pg_hba_rule for postgres local access (Kamil Szymanski) * Fix versions for travis-ci (Ken Barber) * Add replication support (Jordi Boggiano) * Cleaned up and added unit tests (Ken Barber) * Generalization to provide more flexability in postgresql configuration (Karel Brezina) * Create dependent directory for sudoers so tests work on Centos 5 (Ken Barber) * Allow SQL commands to be run against a specific DB (Carlos Villela) * Drop trailing comma to support Puppet 2.6 (Michael Arnold) ##2.1.1 This release provides a bug fix for RHEL 5 and Centos 5 systems, or specifically systems using PostgreSQL 8.1 or older. On those systems one would have received the error: Error: Could not start Service[postgresqld]: Execution of ‘/sbin/service postgresql start’ returned 1: And the postgresql log entry: FATAL: unrecognized configuration parameter "include" This bug is due to a new feature we had added in 2.1.0, whereby the `include` directive in `postgresql.conf` was not compatible. As a work-around we have added checks in our code to make sure systems running PostgreSQL 8.1 or older do not have this directive added. #### Detailed Changes 2013-01-21 - Ken Barber * Only install `include` directive and included file on PostgreSQL >= 8.2 * Add system tests for Centos 5 ##2.1.0 This release is primarily a feature release, introducing some new helpful constructs to the module. For starters, we've added the line `include 'postgresql_conf_extras.conf'` by default so extra parameters not managed by the module can be added by other tooling or by Puppet itself. This provides a useful escape-hatch for managing settings that are not currently managed by the module today. We've added a new defined resource for managing your tablespace, so you can now create new tablespaces using the syntax: postgresql::tablespace { 'dbspace': location => '/srv/dbspace', } We've added a locale parameter to the `postgresql` class, to provide a default. Also the parameter has been added to the `postgresql::database` and `postgresql::db` defined resources for changing the locale per database: postgresql::db { 'mydatabase': user => 'myuser', password => 'mypassword', encoding => 'UTF8', locale => 'en_NG', } There is a new class for installing the necessary packages to provide the PostgreSQL JDBC client jars: class { 'postgresql::java': } And we have a brand new defined resource for managing fine-grained rule sets within your pg_hba.conf access lists: postgresql::pg_hba { 'Open up postgresql for access from 200.1.2.0/24': type => 'host', database => 'app', user => 'app', address => '200.1.2.0/24', auth_method => 'md5', } Finally, we've also added Travis-CI support and unit tests to help us iterate faster with tests to reduce regression. The current URL for these tests is here: https://travis-ci.org/puppetlabs/puppet-postgresql. Instructions on how to run the unit tests available are provided in the README for the module. A big thanks to all those listed below who made this feature release possible :-). #### Detailed Changes 2013-01-18 - Simão Fontes & Flaper Fesp * Remove trailing commas from params.pp property definition for Puppet 2.6.0 compatibility 2013-01-18 - Lauren Rother * Updated README.md to conform with best practices template 2013-01-09 - Adrien Thebo * Update postgresql_default_version to 9.1 for Debian 7.0 2013-01-28 - Karel Brezina * Add support for tablespaces 2013-01-16 - Chris Price & Karel Brezina * Provide support for an 'include' config file 'postgresql_conf_extras.conf' that users can modify manually or outside of the module. 2013-01-31 - jv * Fix typo in README.pp for postgresql::db example 2013-02-03 - Ken Barber * Add unit tests and travis-ci support 2013-02-02 - Ken Barber * Add locale parameter support to the 'postgresql' class 2013-01-21 - Michael Arnold * Add a class for install the packages containing the PostgreSQL JDBC jar 2013-02-06 - fhrbek * Coding style fixes to reduce warnings in puppet-lint and Geppetto 2013-02-10 - Ken Barber * Provide new defined resource for managing pg_hba.conf 2013-02-11 - Ken Barber * Fix bug with reload of Postgresql on Redhat/Centos 2013-02-15 - Erik Dalén * Fix more style issues to reduce warnings in puppet-lint and Geppetto 2013-02-15 - Erik Dalén * Fix case whereby we were modifying a hash after creation ##2.0.1 Minor bugfix release. 2013-01-16 - Chris Price * Fix revoke command in database.pp to support postgres 8.1 (43ded42) 2013-01-15 - Jordi Boggiano * Add support for ubuntu 12.10 status (3504405) ##2.0.0 Many thanks to the following people who contributed patches to this release: * Adrien Thebo * Albert Koch * Andreas Ntaflos * Brett Porter * Chris Price * dharwood * Etienne Pelletier * Florin Broasca * Henrik * Hunter Haugen * Jari Bakken * Jordi Boggiano * Ken Barber * nzakaria * Richard Arends * Spenser Gilliland * stormcrow * William Van Hevelingen Notable features: * Add support for versions of postgres other than the system default version (which varies depending on OS distro). This includes optional support for automatically managing the package repo for the "official" postgres yum/apt repos. (Major thanks to Etienne Pelletier and Ken Barber for their tireless efforts and patience on this feature set!) For example usage see `tests/official-postgresql-repos.pp`. * Add some support for Debian Wheezy and Ubuntu Quantal * Add new `postgres_psql` type with a Ruby provider, to replace the old exec-based `psql` type. This gives us much more flexibility around executing SQL statements and controlling their logging / reports output. * Major refactor of the "spec" tests--which are actually more like acceptance tests. We now support testing against multiple OS distros via vagrant, and the framework is in place to allow us to very easily add more distros. Currently testing against Cent6 and Ubuntu 10.04. * Fixed a bug that was preventing multiple databases from being owned by the same user (9adcd182f820101f5e4891b9f2ff6278dfad495c - Etienne Pelletier ) * Add support for ACLs for finer-grained control of user/interface access (b8389d19ad78b4fb66024897097b4ed7db241930 - dharwood ) * Many other bug fixes and improvements! --- ##1.0.0 2012-09-17 - Version 0.3.0 released 2012-09-14 - Chris Price * Add a type for validating a postgres connection (ce4a049) 2012-08-25 - Jari Bakken * Remove trailing commas. (e6af5e5) 2012-08-16 - Version 0.2.0 released diff --git a/Gemfile b/Gemfile index 5d86325..46cb2ea 100644 --- a/Gemfile +++ b/Gemfile @@ -1,86 +1,75 @@ #This file is generated by ModuleSync, do not edit. source ENV['GEM_SOURCE'] || "https://rubygems.org" # Determines what type of gem is requested based on place_or_version. def gem_type(place_or_version) if place_or_version =~ /^git:/ :git elsif place_or_version =~ /^file:/ :file else :gem end end # Find a location or specific version for a gem. place_or_version can be a # version, which is most often used. It can also be git, which is specified as # `git://somewhere.git#branch`. You can also use a file source location, which # is specified as `file://some/location/on/disk`. def location_for(place_or_version, fake_version = nil) if place_or_version =~ /^(git[:@][^#]*)#(.*)/ [fake_version, { :git => $1, :branch => $2, :require => false }].compact elsif place_or_version =~ /^file:\/\/(.*)/ ['>= 0', { :path => File.expand_path($1), :require => false }] else [place_or_version, { :require => false }] end end # Used for gem conditionals supports_windows = false +ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments +minor_version = "#{ruby_version_segments[0]}.#{ruby_version_segments[1]}" group :development do - gem 'puppet-lint', :require => false - gem 'metadata-json-lint', :require => false, :platforms => 'ruby' - gem 'puppet_facts', :require => false - gem 'puppet-blacksmith', '>= 3.4.0', :require => false, :platforms => 'ruby' - gem 'puppetlabs_spec_helper', '>= 1.2.1', :require => false - gem 'rspec-puppet', '>= 2.3.2', :require => false - gem 'rspec-puppet-facts', :require => false, :platforms => 'ruby' - gem 'mocha', '< 1.2.0', :require => false - gem 'simplecov', :require => false, :platforms => 'ruby' - gem 'parallel_tests', '< 2.10.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem 'parallel_tests', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.0.0') - gem 'rubocop', '0.41.2', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem 'rubocop', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.0.0') - gem 'rubocop-rspec', '~> 1.6', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0') - gem 'pry', :require => false - gem 'json_pure', '<= 2.0.1', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem 'fast_gettext', '1.1.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') - gem 'fast_gettext', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') - gem 'rainbow', '< 2.2.0', :require => false + gem "puppet-module-posix-default-r#{minor_version}", :require => false, :platforms => "ruby" + gem "puppet-module-win-default-r#{minor_version}", :require => false, :platforms => ["mswin", "mingw", "x64_mingw"] + gem "puppet-module-posix-dev-r#{minor_version}", :require => false, :platforms => "ruby" + gem "puppet-module-win-dev-r#{minor_version}", :require => false, :platforms => ["mswin", "mingw", "x64_mingw"] + gem "json_pure", '<= 2.0.1', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') + gem "fast_gettext", '1.1.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') + gem "fast_gettext", :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') end group :system_tests do - gem 'beaker', *location_for(ENV['BEAKER_VERSION'] || '>= 3') - gem 'beaker-pe', :require => false - gem 'beaker-rspec', *location_for(ENV['BEAKER_RSPEC_VERSION']) - gem 'beaker-puppet_install_helper', :require => false - gem 'beaker-module_install_helper', :require => false - gem 'master_manipulator', :require => false - gem 'beaker-hostgenerator', *location_for(ENV['BEAKER_HOSTGENERATOR_VERSION']) - gem 'beaker-abs', *location_for(ENV['BEAKER_ABS_VERSION'] || '~> 0.1') + gem "puppet-module-posix-system-r#{minor_version}", :require => false, :platforms => "ruby" + gem "puppet-module-win-system-r#{minor_version}", :require => false, :platforms => ["mswin", "mingw", "x64_mingw"] + gem "beaker", *location_for(ENV['BEAKER_VERSION'] || '>= 3') + gem "beaker-pe", :require => false + gem "beaker-rspec", *location_for(ENV['BEAKER_RSPEC_VERSION']) + gem "beaker-hostgenerator", *location_for(ENV['BEAKER_HOSTGENERATOR_VERSION']) + gem "beaker-abs", *location_for(ENV['BEAKER_ABS_VERSION'] || '~> 0.1') end gem 'puppet', *location_for(ENV['PUPPET_GEM_VERSION']) # Only explicitly specify Facter/Hiera if a version has been specified. # Otherwise it can lead to strange bundler behavior. If you are seeing weird # gem resolution behavior, try setting `DEBUG_RESOLVER` environment variable # to `1` and then run bundle install. gem 'facter', *location_for(ENV['FACTER_GEM_VERSION']) if ENV['FACTER_GEM_VERSION'] gem 'hiera', *location_for(ENV['HIERA_GEM_VERSION']) if ENV['HIERA_GEM_VERSION'] # Evaluate Gemfile.local if it exists if File.exists? "#{__FILE__}.local" eval(File.read("#{__FILE__}.local"), binding) end # Evaluate ~/.gemfile if it exists if File.exists?(File.join(Dir.home, '.gemfile')) eval(File.read(File.join(Dir.home, '.gemfile')), binding) end # vim:ft=ruby diff --git a/README.md b/README.md index 1128623..de99b2c 100644 --- a/README.md +++ b/README.md @@ -1,1461 +1,1795 @@ # postgresql #### Table of Contents 1. [Module Description - What does the module do?](#module-description) 2. [Setup - The basics of getting started with postgresql module](#setup) * [What postgresql affects](#what-postgresql-affects) * [Getting started with postgresql](#getting-started-with-postgresql) 3. [Usage - Configuration options and additional functionality](#usage) * [Configure a server](#configure-a-server) * [Create a database](#create-a-database) * [Manage users, roles, and permissions](#manage-users-roles-and-permissions) * [Override defaults](#override-defaults) * [Create an access rule for pg_hba.conf](#create-an-access-rule-for-pg_hbaconf) * [Create user name maps for pg_ident.conf](#create-user-name-maps-for-pg_identconf) * [Validate connectivity](#validate-connectivity) 4. [Reference - An under-the-hood peek at what the module is doing and how](#reference) * [Classes](#classes) * [Defined Types](#defined-types) * [Types](#types) * [Functions](#functions) 5. [Limitations - OS compatibility, etc.](#limitations) 6. [Development - Guide for contributing to the module](#development) * [Contributors - List of module contributors](#contributors) 7. [Tests](#tests) 8. [Contributors - List of module contributors](#contributors) ## Module description The postgresql module allows you to manage PostgreSQL databases with Puppet. PostgreSQL is a high-performance, free, open-source relational database server. The postgresql module allows you to manage packages, services, databases, users, and common security settings in PostgreSQL. ## Setup ### What postgresql affects * Package, service, and configuration files for PostgreSQL * Listened-to ports * IP and mask (optional) ### Getting started with postgresql To configure a basic default PostgreSQL server, declare the `postgresql::server` class. ```puppet -class { 'postgresql::server': } +class { 'postgresql::server': +} ``` ## Usage ### Configure a server For default settings, declare the `postgresql::server` class as above. To customize PostgreSQL server settings, specify the [parameters](#postgresqlserver) you want to change: ```puppet class { 'postgresql::server': ip_mask_deny_postgres_user => '0.0.0.0/32', ip_mask_allow_all_users => '0.0.0.0/0', - listen_addresses => '*', ipv4acls => ['hostssl all johndoe 192.168.0.0/24 cert'], postgres_password => 'TPSrep0rt!', } ``` After configuration, test your settings from the command line: -``` +```shell psql -h localhost -U postgres psql -h my.postgres.server -U ``` If you get an error message from these commands, your permission settings restrict access from the location you're trying to connect from. Depending on whether you want to allow connections from that location, you might need to adjust your permissions. For more details about server configuration parameters, consult the [PostgreSQL Runtime Configuration documentation](http://www.postgresql.org/docs/current/static/runtime-config.html). ### Create a database You can set up a variety of PostgreSQL databases with the `postgresql::server::db` defined type. For instance, to set up a database for PuppetDB: ```puppet -class { 'postgresql::server': } +class { 'postgresql::server': +} postgresql::server::db { 'mydatabasename': user => 'mydatabaseuser', password => postgresql_password('mydatabaseuser', 'mypassword'), } ``` ### Manage users, roles, and permissions To manage users, roles, and permissions: ```puppet -class { 'postgresql::server': } +class { 'postgresql::server': +} postgresql::server::role { 'marmot': -password_hash => postgresql_password('marmot', 'mypasswd'), + password_hash => postgresql_password('marmot', 'mypasswd'), } postgresql::server::database_grant { 'test1': privilege => 'ALL', db => 'test1', role => 'marmot', } postgresql::server::table_grant { 'my_table of test2': privilege => 'ALL', table => 'my_table', db => 'test2', role => 'marmot', } ``` This example grants **all** privileges on the test1 database and on the `my_table` table of the test2 database to the specified user or group. After the values are added into the PuppetDB config file, this database would be ready for use. ### Override defaults The `postgresql::globals` class allows you to configure the main settings for this module globally, so that other classes and defined resources can use them. By itself, it does nothing. For example, to overwrite the default `locale` and `encoding` for all classes, use the following: ```puppet class { 'postgresql::globals': encoding => 'UTF-8', locale => 'en_US.UTF-8', -}-> +} + class { 'postgresql::server': } ``` To use a specific version of the PostgreSQL package: ```puppet class { 'postgresql::globals': manage_package_repo => true, version => '9.2', -}-> -class { 'postgresql::server': } +} + +class { 'postgresql::server': +} ``` ### Manage remote users, roles, and permissions Remote SQL objects are managed using the same Puppet resources as local SQL objects, along with a [`connect_settings`](#connect_settings) hash. This provides control over how Puppet connects to the remote Postgres instances and which version is used for generating SQL commands. The `connect_settings` hash can contain environment variables to control Postgres client connections, such as 'PGHOST', 'PGPORT', 'PGPASSWORD', and 'PGSSLKEY'. See the [PostgreSQL Environment Variables](http://www.postgresql.org/docs/9.4/static/libpq-envars.html) documentation for a complete list of variables. Additionally, you can specify the target database version with the special value of 'DBVERSION'. If the `connect_settings` hash is omitted or empty, then Puppet connects to the local PostgreSQL instance. You can provide a `connect_settings` hash for each of the Puppet resources, or you can set a default `connect_settings` hash in `postgresql::globals`. Configuring `connect_settings` per resource allows SQL objects to be created on multiple databases by multiple users. ```puppet $connection_settings_super2 = { - 'PGUSER' => "super2", - 'PGPASSWORD' => "foobar2", - 'PGHOST' => "127.0.0.1", - 'PGPORT' => "5432", - 'PGDATABASE' => "postgres", - } + 'PGUSER' => 'super2', + 'PGPASSWORD' => 'foobar2', + 'PGHOST' => '127.0.0.1', + 'PGPORT' => '5432', + 'PGDATABASE' => 'postgres', +} include postgresql::server # Connect with no special settings, i.e domain sockets, user postgres -postgresql::server::role{'super2': - password_hash => "foobar2", - superuser => true, +postgresql::server::role { 'super2': + password_hash => 'foobar2', + superuser => true, connect_settings => {}, - require => [ - Class['postgresql::globals'], - Class['postgresql::server::service'], - ], } # Now using this new user connect via TCP postgresql::server::database { 'db1': connect_settings => $connection_settings_super2, - -require => Postgresql::Server::Role['super2'], + require => Postgresql::Server::Role['super2'], } ``` ### Create an access rule for pg_hba.conf To create an access rule for `pg_hba.conf`: ```puppet postgresql::server::pg_hba_rule { 'allow application network to access app database': - description => "Open up PostgreSQL for access from 200.1.2.0/24", + description => 'Open up PostgreSQL for access from 200.1.2.0/24', type => 'host', database => 'app', user => 'app', address => '200.1.2.0/24', auth_method => 'md5', } ``` This would create a ruleset in `pg_hba.conf` similar to: ``` # Rule Name: allow application network to access app database # Description: Open up PostgreSQL for access from 200.1.2.0/24 # Order: 150 host app app 200.1.2.0/24 md5 ``` By default, `pg_hba_rule` requires that you include `postgresql::server`. However, you can override that behavior by setting target and postgresql_version when declaring your rule. That might look like the following: ```puppet postgresql::server::pg_hba_rule { 'allow application network to access app database': - description => "Open up postgresql for access from 200.1.2.0/24", + description => 'Open up postgresql for access from 200.1.2.0/24', type => 'host', database => 'app', user => 'app', address => '200.1.2.0/24', auth_method => 'md5', target => '/path/to/pg_hba.conf', postgresql_version => '9.4', } ``` ### Create user name maps for pg_ident.conf To create a user name map for the pg_ident.conf: ```puppet -postgresql::server::pg_ident_rule{ 'Map the SSL certificate of the backup server as a replication user': +postgresql::server::pg_ident_rule { 'Map the SSL certificate of the backup server as a replication user': map_name => 'sslrepli', system_username => 'repli1.example.com', database_username => 'replication', } ``` This would create a user name map in `pg_ident.conf` similar to: ``` #Rule Name: Map the SSL certificate of the backup server as a replication user #Description: none #Order: 150 sslrepli repli1.example.com replication ``` ### Create recovery configuration To create the recovery configuration file (`recovery.conf`): ```puppet -postgresql::server::recovery{ 'Create a recovery.conf file with the following defined parameters': - restore_command => 'cp /mnt/server/archivedir/%f %p', - archive_cleanup_command => undef, - recovery_end_command => undef, - recovery_target_name => 'daily backup 2015-01-26', - recovery_target_time => '2015-02-08 22:39:00 EST', - recovery_target_xid => undef, - recovery_target_inclusive => true, - recovery_target => 'immediate', - recovery_target_timeline => 'latest', - pause_at_recovery_target => true, - standby_mode => 'on', - primary_conninfo => 'host=localhost port=5432', - primary_slot_name => undef, - trigger_file => undef, - recovery_min_apply_delay => 0, +postgresql::server::recovery { 'Create a recovery.conf file with the following defined parameters': + restore_command => 'cp /mnt/server/archivedir/%f %p', + archive_cleanup_command => undef, + recovery_end_command => undef, + recovery_target_name => 'daily backup 2015-01-26', + recovery_target_time => '2015-02-08 22:39:00 EST', + recovery_target_xid => undef, + recovery_target_inclusive => true, + recovery_target => 'immediate', + recovery_target_timeline => 'latest', + pause_at_recovery_target => true, + standby_mode => 'on', + primary_conninfo => 'host=localhost port=5432', + primary_slot_name => undef, + trigger_file => undef, + recovery_min_apply_delay => 0, } ``` The above creates this `recovery.conf` config file: ``` restore_command = 'cp /mnt/server/archivedir/%f %p' recovery_target_name = 'daily backup 2015-01-26' recovery_target_time = '2015-02-08 22:39:00 EST' recovery_target_inclusive = true recovery_target = 'immediate' recovery_target_timeline = 'latest' pause_at_recovery_target = true standby_mode = 'on' primary_conninfo = 'host=localhost port=5432' recovery_min_apply_delay = 0 ``` Only the specified parameters are recognized in the template. The `recovery.conf` is only be created if at least one parameter is set **and** [manage_recovery_conf](#manage_recovery_conf) is set to true. ### Validate connectivity -To validate client connections to a remote PostgreSQL database before starting dependent tasks, use the `postgresql::validate_db_connection` resource. You can use this on any node where the PostgreSQL client software is installed. It is often chained to other tasks such as starting an application server or performing a database migration. +To validate client connections to a remote PostgreSQL database before starting dependent tasks, use the `postgresql_conn_validator` resource. You can use this on any node where the PostgreSQL client software is installed. It is often chained to other tasks such as starting an application server or performing a database migration. Example usage: ```puppet -postgresql::validate_db_connection { 'validate my postgres connection': - database_host => 'my.postgres.host', - database_username => 'mydbuser', - database_password => 'mydbpassword', - database_name => 'mydbname', +postgresql_conn_validator { 'validate my postgres connection': + host => 'my.postgres.host', + db_username => 'mydbuser', + db_password => 'mydbpassword', + db_name => 'mydbname', }-> exec { 'rake db:migrate': cwd => '/opt/myrubyapp', } ``` ## Reference The postgresql module comes with many options for configuring the server. While you are unlikely to use all of the settings below, they provide a decent amount of control over your security settings. **Classes:** * [postgresql::client](#postgresqlclient) * [postgresql::globals](#postgresqlglobals) * [postgresql::lib::devel](#postgresqllibdevel) * [postgresql::lib::java](#postgresqllibjava) * [postgresql::lib::perl](#postgresqllibperl) * [postgresql::lib::python](#postgresqllibpython) * [postgresql::server](#postgresqlserver) * [postgresql::server::plperl](#postgresqlserverplperl) * [postgresql::server::contrib](#postgresqlservercontrib) * [postgresql::server::postgis](#postgresqlserverpostgis) **Defined Types:** * [postgresql::server::config_entry](#postgresqlserverconfig_entry) * [postgresql::server::database](#postgresqlserverdatabase) * [postgresql::server::database_grant](#postgresqlserverdatabase_grant) * [postgresql::server::db](#postgresqlserverdb) * [postgresql::server::extension](#postgresqlserverextension) * [postgresql::server::grant](#postgresqlservergrant) * [postgresql::server::grant_role](#postgresqlservergrant_role) * [postgresql::server::pg_hba_rule](#postgresqlserverpg_hba_rule) * [postgresql::server::pg_ident_rule](#postgresqlserverpg_ident_rule) * [postgresql::server::recovery](#postgresqlserverrecovery) * [postgresql::server::role](#postgresqlserverrole) * [postgresql::server::schema](#postgresqlserverschema) * [postgresql::server::table_grant](#postgresqlservertable_grant) * [postgresql::server::tablespace](#postgresqlservertablespace) -* [postgresql::validate_db_connection](#postgresqlvalidate_db_connection) **Types:** * [postgresql_psql](#custom-resource-postgresql_psql) * [postgresql_replication_slot](#custom-resource-postgresql_replication_slot) * [postgresql_conf](#custom-resource-postgresql_conf) +* [postgresql_conn_validator](#custom-resource-postgresql_conn_validator) **Functions:** * [postgresql_password](#function-postgresql_password) * [postgresql_acls_to_resources_hash](#function-postgresql_acls_to_resources_hashacl_array-id-order_offset) ### Classes #### postgresql::client Installs PostgreSQL client software. Set the following parameters if you have a custom version you would like to install. >**Note:** Make sure to add any necessary yum or apt repositories if specifying a custom version. ##### `package_ensure` -Whether the PostgreSQL client package resource should be present. Valid values: 'present', 'absent'. Default: 'present'. +Whether the PostgreSQL client package resource should be present. -##### `package_name` +Valid values: 'present', 'absent'. + +Default value: 'present'. -Sets the name of the PostgreSQL client package. Default: 'file'. +##### `package_name` -##### `validcon_script_path` +Sets the name of the PostgreSQL client package. -Specifies the path to validate the connection script. Default: '/usr/local/bin/validate_postgresql_connection.sh'. +Default value: 'file'. #### postgresql::lib::docs Installs PostgreSQL bindings for Postgres-Docs. Set the following parameters if you have a custom version you would like to install. **Note:** Make sure to add any necessary yum or apt repositories if specifying a custom version. ##### `package_name` Specifies the name of the PostgreSQL docs package. ##### `package_ensure` -Whether the PostgreSQL docs package resource should be present. Valid values: 'present', 'absent'. Default: 'present'. +Whether the PostgreSQL docs package resource should be present. + +Valid values: 'present', 'absent'. + +Default value: 'present'. #### postgresql::globals **Note:** Most server-specific defaults should be overridden in the `postgresql::server` class. This class should be used only if you are using a non-standard OS, or if you are changing elements that can only be changed here, such as `version` or `manage_package_repo`. ##### `bindir` -Overrides the default PostgreSQL binaries directory for the target platform. Default: OS dependent. +Overrides the default PostgreSQL binaries directory for the target platform. + +Default value: OS dependent. ##### `client_package_name` -Overrides the default PostgreSQL client package name. Default: OS dependent. +Overrides the default PostgreSQL client package name. + +Default value: OS dependent. ##### `confdir` -Overrides the default PostgreSQL configuration directory for the target platform. Default: OS dependent. +Overrides the default PostgreSQL configuration directory for the target platform. + +Default value: OS dependent. ##### `contrib_package_name` -Overrides the default PostgreSQL contrib package name. Default: OS dependent. +Overrides the default PostgreSQL contrib package name. + +Default value: OS dependent. ##### `createdb_path` -**Deprecated.** Path to the `createdb` command. Default: "${bindir}/createdb". +**Deprecated.** Path to the `createdb` command. + +Default value: '${bindir}/createdb'. ##### `datadir` -Overrides the default PostgreSQL data directory for the target platform. Default: OS dependent. +Overrides the default PostgreSQL data directory for the target platform. + +Default value: OS dependent. **Note:** Changing the datadir after installation causes the server to come to a full stop before making the change. For Red Hat systems, the data directory must be labeled appropriately for SELinux. On Ubuntu, you must explicitly set `needs_initdb = true` to allow Puppet to initialize the database in the new datadir (`needs_initdb` defaults to true on other systems). **Warning:** If datadir is changed from the default, Puppet does not manage purging of the original data directory, which causes it to fail if the data directory is changed back to the original. ##### `default_database` -Specifies the name of the default database to connect with. On most systems, this is 'postgres'. +Specifies the name of the default database to connect with. + +Default value: 'postgres' (for most systems). ##### `devel_package_name` -Overrides the default PostgreSQL devel package name. Default: OS dependent. +Overrides the default PostgreSQL devel package name. + +Default value: OS dependent. ##### `docs_package_name` -Overrides the default PostgreSQL docs package name. If not specified, the module uses the default for your OS distro. +Optional. + +Overrides the default PostgreSQL docs package name. + +Default value: OS dependent. ##### `encoding` -Sets the default encoding for all databases created with this module. On certain operating systems, this is also used during the `template1` initialization, so it becomes a default outside of the module as well. Defaults to the operating system's default encoding. +Sets the default encoding for all databases created with this module. On certain operating systems, this is also used during the `template1` initialization, so it becomes a default outside of the module as well. + +Default value: Dependent on the operating system's default encoding. ##### `group` -Overrides the default postgres user group to be used for related files in the file system. Default: 'postgres'. +Overrides the default postgres user group to be used for related files in the file system. + +Default value: 'postgres'. ##### `initdb_path` Path to the `initdb` command. ##### `java_package_name` -Overrides the default PostgreSQL java package name. Default: OS dependent. +Overrides the default PostgreSQL java package name. + +Default value: OS dependent. ##### `locale` -Sets the default database locale for all databases created with this module. On certain operating systems, this is also used during the `template1` initialization, so it becomes a default outside of the module as well. Default: undef, which is effectively `C`. **On Debian, you'll need to ensure that the 'locales-all' package is installed for full functionality of PostgreSQL.** +Sets the default database locale for all databases created with this module. On certain operating systems, this is also used during the `template1` initialization, so it becomes a default outside of the module as well. + +Default value: `undef`, which is effectively 'C'. + +**On Debian, you'll need to ensure that the 'locales-all' package is installed for full functionality of PostgreSQL.** ##### `timezone` Sets the default timezone of the postgresql server. The postgresql built-in default is taking the systems timezone information. ##### `logdir` -Overrides the default PostgreSQL log directory. Default: initdb's default path. +Overrides the default PostgreSQL log directory. -##### `log_line_prefix` - -Set a prefix for the server logs. Default: `'%t '` +Default value: initdb's default path. ##### `manage_package_repo` -Sets up official PostgreSQL repositories on your host if set to true. Default: false. +Sets up official PostgreSQL repositories on your host if set to `true`. + +Default value: `false`. ##### `module_workdir` -Specifies working directory under which the psql command should be executed. May need to specify if /tmp is on volume mounted with noexec option. Default: /tmp +Specifies working directory under which the psql command should be executed. May need to specify if '/tmp' is on volume mounted with noexec option. + +Default value: '/tmp'. ##### `needs_initdb` -Explicitly calls the initdb operation after the server package is installed and before the PostgreSQL service is started. Default: OS dependent. +Explicitly calls the initdb operation after the server package is installed and before the PostgreSQL service is started. + +Default value: OS dependent. ##### `perl_package_name` -Overrides the default PostgreSQL Perl package name. Default: OS dependent. +Overrides the default PostgreSQL Perl package name. + +Default value: OS dependent. ##### `pg_hba_conf_defaults` -Disables the defaults supplied with the module for `pg_hba.conf` if set to false. This is useful if you want to override the defaults. Be sure that your changes align with the rest of the module, as some access is required to perform some operations, such as basic `psql` operations. Default: true. +Disables the defaults supplied with the module for `pg_hba.conf` if set to `false`. This is useful if you want to override the defaults. Be sure that your changes align with the rest of the module, as some access is required to perform some operations, such as basic `psql` operations. + +Default value: The globals value set in `postgresql::globals::manage_pg_hba_conf` which defaults to `true`. ##### `pg_hba_conf_path` -Specifies the path to your `pg_hba.conf` file. Default: '${confdir}/pg_hba.conf'. +Specifies the path to your `pg_hba.conf` file. + +Default value: '${confdir}/pg_hba.conf'. ##### `pg_ident_conf_path` -Specifies the path to your `pg_ident.conf` file. Default: "${confdir}/pg_ident.conf". +Specifies the path to your `pg_ident.conf` file. + +Default value: '${confdir}/pg_ident.conf'. ##### `plperl_package_name` -Overrides the default PostgreSQL PL/Perl package name. Default: OS dependent. +Overrides the default PostgreSQL PL/Perl package name. + +Default value: OS dependent. ##### `plpython_package_name` -Overrides the default PostgreSQL PL/Python package name. Default: OS dependent. +Overrides the default PostgreSQL PL/Python package name. + +Default value: OS dependent. ##### `postgis_version` -Defines the version of PostGIS to install, if you install PostGIS. Defaults to the lowest available with the version of PostgreSQL to be installed. +Defines the version of PostGIS to install, if you install PostGIS. + +Default value: The lowest available with the version of PostgreSQL to be installed. ##### `postgresql_conf_path` -Sets the path to your `postgresql.conf` file. Default: "${confdir}/postgresql.conf". +Sets the path to your `postgresql.conf` file. + +Default value: '${confdir}/postgresql.conf'. ##### `psql_path` Sets the path to the `psql` command. ##### `python_package_name` -Overrides the default PostgreSQL Python package name. Default: OS dependent. +Overrides the default PostgreSQL Python package name. + +Default value: OS dependent. ##### `recovery_conf_path` Path to your `recovery.conf` file. ##### `repo_proxy` -Sets the proxy option for the official PostgreSQL yum-repositories only. Debian is currently not supported. This is useful if your server is behind a corporate firewall and needs to use proxy servers for outside connectivity. +Sets the proxy option for the official PostgreSQL yum-repositories only. This is useful if your server is behind a corporate firewall and needs to use proxy servers for outside connectivity. + +Debian is currently not supported. ##### `repo_baseurl` -Sets the baseurl for the PostgreSQL repository. Useful if you host your own mirror of the repository. Defaults to the official PostgreSQL repository. +Sets the baseurl for the PostgreSQL repository. Useful if you host your own mirror of the repository. + +Default value: The official PostgreSQL repository. ##### `server_package_name` -Overrides the default PostgreSQL server package name. Default: OS dependent. +Overrides the default PostgreSQL server package name. + +Default value: OS dependent. ##### `service_name` -Overrides the default PostgreSQL service name. Default: OS dependent. +Overrides the default PostgreSQL service name. + +Default value: OS dependent. ##### `service_provider` -Overrides the default PostgreSQL service provider. Default: OS dependent. +Overrides the default PostgreSQL service provider. + +Default value: OS dependent. ##### `service_status` -Overrides the default status check command for your PostgreSQL service. Default: OS dependent. +Overrides the default status check command for your PostgreSQL service. + +Default value: OS dependent. ##### `user` -Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. Default: 'postgres'. +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. + +Default value: 'postgres'. ##### `version` -The version of PostgreSQL to install and manage. Default: OS system default. +The version of PostgreSQL to install and manage. + +Default value: OS system default. ##### `xlogdir` -Overrides the default PostgreSQL xlog directory. Default: initdb's default path. +Overrides the default PostgreSQL xlog directory. + +Default value: initdb's default path. ####postgresql::lib::devel Installs the packages containing the development libraries for PostgreSQL and symlinks `pg_config` into `/usr/bin` (if not in `/usr/bin` or `/usr/local/bin`). ##### `link_pg_config` -If the bin directory used by the PostgreSQL page is not `/usr/bin` or `/usr/local/bin`, symlinks `pg_config` from the package's bin dir into `usr/bin` (not applicable to Debian systems). Set to false to disable this behavior. Valid values: true, false. Default: true. +If the bin directory used by the PostgreSQL page is not `/usr/bin` or `/usr/local/bin`, symlinks `pg_config` from the package's bin dir into `usr/bin` (not applicable to Debian systems). Set to `false` to disable this behavior. + +Valid values: `true`, `false`. + +Default value: `true`. ##### `package_ensure` -Overrides the `ensure` parameter during package installation. Defaults to `present`. +Overrides the 'ensure' parameter during package installation. + +Default value: 'present'. ##### `package_name` -Overrides the default package name for the distribution you are installing to. Defaults to `postgresql-devel` or `postgresql-devel` depending on your distro. +Overrides the default package name for the distribution you are installing to. + +Default value: 'postgresql-devel' or 'postgresql-devel' depending on your distro. #### postgresql::lib::java Installs PostgreSQL bindings for Java (JDBC). Set the following parameters if you have a custom version you would like to install. **Note:** Make sure to add any necessary yum or apt repositories if specifying a custom version. ##### `package_ensure` -Specifies whether the package is present. Valid values: 'present', 'absent'. Default: 'present'. +Specifies whether the package is present. + +Valid values: 'present', 'absent'. + +Default value: 'present'. ##### `package_name` Specifies the name of the PostgreSQL java package. #### postgresql::lib::perl Installs the PostgreSQL Perl libraries. ##### `package_ensure` -Specifies whether the package is present. Valid values: 'present', 'absent'. Default: 'present'. +Specifies whether the package is present. + +Valid values: 'present', 'absent'. + +Default value: 'present'. ##### `package_name` Specifies the name of the PostgreSQL perl package to install. #### postgresql::server::plpython Installs the PL/Python procedural language for PostgreSQL. ##### `package_name` Specifies the name of the postgresql PL/Python package. ##### `package_ensure` -Specifies whether the package is present. Valid values: 'present', 'absent'. Default: 'present'. +Specifies whether the package is present. + +Valid values: 'present', 'absent'. + +Default value: 'present'. #### postgresql::lib::python Installs PostgreSQL Python libraries. ##### `package_ensure` -Specifies whether the package is present. Valid values: 'present', 'absent'. Default: 'present'. +Specifies whether the package is present. + +Valid values: 'present', 'absent'. + +Default value: 'present'. ##### `package_name` The name of the PostgreSQL Python package. #### postgresql::server ##### `createdb_path` -**Deprecated.** Specifies the path to the `createdb` command. Default: "${bindir}/createdb". +**Deprecated.** Specifies the path to the `createdb` command. + +Default value: '${bindir}/createdb'. ##### `default_database` -Specifies the name of the default database to connect with. On most systems this is "postgres". +Specifies the name of the default database to connect with. On most systems this is 'postgres'. ##### `default_connect_settings` Specifies a hash of environment variables used when connecting to a remote server. Becomes the default for other defined-types. i.e. `postgresql::server::role` ##### `encoding` -Sets the default encoding for all databases created with this module. On certain operating systems this is also used during the `template1` initialization, so it becomes a default outside of the module as well. Default: undef. +Sets the default encoding for all databases created with this module. On certain operating systems this is also used during the `template1` initialization, so it becomes a default outside of the module as well. + +Default value: `undef`. ##### `group` -Overrides the default postgres user group to be used for related files in the file system. Default: OS dependent default. +Overrides the default postgres user group to be used for related files in the file system. + +Default value: OS dependent default. ##### `initdb_path` -Specifies the path to the `initdb` command. Default: "${bindir}/initdb". +Specifies the path to the `initdb` command. + +Default value: '${bindir}/initdb'. ##### `ipv4acls` -Lists strings for access control for connection method, users, databases, IPv4 addresses; see [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html) on `pg_hba.conf` for information. +Lists strings for access control for connection method, users, databases, IPv4 addresses; + +see [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html) on `pg_hba.conf` for information. ##### `ipv6acls` -Lists strings for access control for connection method, users, databases, IPv6 addresses; see [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html) on `pg_hba.conf` for information. +Lists strings for access control for connection method, users, databases, IPv6 addresses. + +see [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html) on `pg_hba.conf` for information. ##### `ip_mask_allow_all_users` Overrides PostgreSQL defaults for remote connections. By default, PostgreSQL does not allow database user accounts to connect via TCP from remote machines. If you'd like to allow this, you can override this setting. -Set to `0.0.0.0/0` to allow database users to connect from any remote machine, or `192.168.0.0/16` to allow connections from any machine on your local 192.168 subnet. Default: `127.0.0.1/32`. +Set to '0.0.0.0/0' to allow database users to connect from any remote machine, or '192.168.0.0/1' to allow connections from any machine on your local '192.168' subnet. -##### `ip_mask_deny_postgres_user` +Default value: '127.0.0.1/32'. -Specifies the IP mask from which remote connections should be denied for the postgres superuser. Defaults to `0.0.0.0/0`, which denies any remote connection. +##### `ip_mask_deny_postgres_user` -##### `listen_addresses` +Specifies the IP mask from which remote connections should be denied for the postgres superuser. -Specifies the addresses the server accepts connections to. Valid values: - * 'localhost': Accept connections from local host only. - * '*': Accept connections from any remote machine. - * Specified comma-separated list of hostnames or IP addresses. +Default value: '0.0.0.0/0', which denies any remote connection. ##### `locale` -Sets the default database locale for all databases created with this module. On certain operating systems this is used during the `template1` initialization as well, so it becomes a default outside of the module. Default: undef, which is effectively `C`. **On Debian, you must ensure that the 'locales-all' package is installed for full functionality of PostgreSQL.** +Sets the default database locale for all databases created with this module. On certain operating systems this is used during the `template1` initialization as well, so it becomes a default outside of the module. -##### `log_line_prefix` +Default value: `undef`, which is effectively 'C'. -Set a prefix for the server logs. Default: `'%t '` +**On Debian, you must ensure that the 'locales-all' package is installed for full functionality of PostgreSQL.** ##### `manage_pg_hba_conf` -Whether to manage the pg_hba.conf. If set to true, Puppet overwrites this file. If set to false, Puppet does not modify the file. Valid values: true, false. Default +Whether to manage the `pg_hba.conf`. + +If set to `true`, Puppet overwrites this file. + +If set to `false`, Puppet does not modify the file. + +Valid values: `true`, `false`. + +Default value: `true` ##### `manage_pg_ident_conf` -Overwrites the pg_ident.conf file. If set to true, Puppet overwrites the file. If set to false, Puppet does not modify the file. Valid values: true, false. Default: true. +Overwrites the pg_ident.conf file. + +If set to `true`, Puppet overwrites the file. + +If set to `false`, Puppet does not modify the file. + +Valid values: `true`, `false`. + +Default value: `true`. ##### `manage_recovery_conf` -Specifies whether or not manage the recovery.conf. If set to true, Puppet overwrites this file. Valid values: true, false. Default: false. +Specifies whether or not manage the `recovery.conf`. + +If set to `true`, Puppet overwrites this file. + +Valid values: `true`, `false`. + +Default value: `false`. ##### `needs_initdb` -Explicitly calls the `initdb` operation after server package is installed, and before the PostgreSQL service is started. Default: OS dependent. +Explicitly calls the `initdb` operation after server package is installed, and before the PostgreSQL service is started. + +Default value: OS dependent. ##### `package_ensure` -Passes a value through to the `package` resource when creating the server instance. Default: undef. +Passes a value through to the `package` resource when creating the server instance. + +Default value: `undef`. ##### `package_name` -Specifies the name of the package to use for installing the server software. Default: OS dependent. +Specifies the name of the package to use for installing the server software. + +Default value: OS dependent. ##### `pg_hba_conf_defaults` -If false, disables the defaults supplied with the module for `pg_hba.conf`. This is useful if you disagree with the defaults and wish to override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform basic `psql` operations for example. +If `false`, disables the defaults supplied with the module for `pg_hba.conf`. This is useful if you disagree with the defaults and wish to override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform basic `psql` operations for example. ##### `pg_hba_conf_path` Specifies the path to your `pg_hba.conf` file. ##### `pg_ident_conf_path` -Specifies the path to your `pg_ident.conf` file. Default: "${confdir}/pg_ident.conf". +Specifies the path to your `pg_ident.conf` file. + +Default value: '${confdir}/pg_ident.conf'. ##### `plperl_package_name` -Sets the default package name for the PL/Perl extension. Default: OS dependent. +Sets the default package name for the PL/Perl extension. + +Default value: OS dependent. ##### `plpython_package_name` -Sets the default package name for the PL/Python extension. Default: OS dependent. +Sets the default package name for the PL/Python extension. + +Default value: OS dependent. ##### `port` -Specifies the port for the PostgreSQL server to listen on. **Note:** The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, changing the port causes the server to come to a full stop before being able to make the change. Default: `5432`, meaning the Postgres server listens on TCP port 5432. +Specifies the port for the PostgreSQL server to listen on. **Note:** The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, changing the port causes the server to come to a full stop before being able to make the change. + +Default value: 5432. Meaning the Postgres server listens on TCP port 5432. ##### `postgres_password` -Sets the password for the `postgres` user to your specified value. Default: undef, meaning the superuser account in the Postgres database is a user called `postgres` and this account does not have a password. +Sets the password for the postgres user to your specified value. By default, this setting uses the superuser account in the Postgres database, with a user called `postgres` and no password. + +Default value: `undef`. ##### `postgresql_conf_path` -Specifies the path to your `postgresql.conf` file. Default: "${confdir}/postgresql.conf". +Specifies the path to your `postgresql.conf` file. + +Default value: '${confdir}/postgresql.conf'. ##### `psql_path` -Specifies the path to the `psql` command. Default: OS dependent. +Specifies the path to the `psql` command. + +Default value: OS dependent. ##### `service_manage` -Defines whether or not Puppet should manage the service. Default: true. +Defines whether or not Puppet should manage the service. + +Default value: `true`. ##### `service_name` -Overrides the default PostgreSQL service name. Default: OS dependent. +Overrides the default PostgreSQL service name. + +Default value: OS dependent. ##### `service_provider` -Overrides the default PostgreSQL service provider. Default: undef. +Overrides the default PostgreSQL service provider. + +Default value: `undef`. ##### `service_reload` -Overrides the default reload command for your PostgreSQL service. Default: OS dependent. +Overrides the default reload command for your PostgreSQL service. + +Default value: OS dependent. ##### `service_restart_on_change` -Overrides the default behavior to restart your PostgreSQL service when a config entry has been changed that requires a service restart to become active. Default: true. +Overrides the default behavior to restart your PostgreSQL service when a config entry has been changed that requires a service restart to become active. + +Default value: `true`. ##### `service_status` -Overrides the default status check command for your PostgreSQL service. Default: OS dependent. +Overrides the default status check command for your PostgreSQL service. + +Default value: OS dependent. ##### `user` -Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. Default: 'postgres'. +Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +Default value: 'postgres'. #### postgresql::server::contrib Installs the PostgreSQL contrib package. ##### `package_ensure` Sets the ensure parameter passed on to PostgreSQL contrib package resource. ##### `package_name` The name of the PostgreSQL contrib package. #### postgresql::server::plperl Installs the PL/Perl procedural language for postgresql. ##### `package_ensure` The ensure parameter passed on to PostgreSQL PL/Perl package resource. ##### `package_name` The name of the PostgreSQL PL/Perl package. - #### postgresql::server::postgis Installs the PostgreSQL postgis packages. ### Defined Types #### postgresql::server::config_entry Modifies your `postgresql.conf` configuration file. Each resource maps to a line inside the file, for example: ```puppet postgresql::server::config_entry { 'check_function_bodies': value => 'off', } ``` ##### `ensure` -Removes an entry if set to 'absent'. Valid values: 'present', 'absent'. +Removes an entry if set to 'absent'. + +Valid values: 'present', 'absent'. + +Default value: 'present'. ##### `value` Defines the value for the setting. #### postgresql::server::db Creates a local database, user, and assigns necessary permissions. ##### `comment` Defines a comment to be stored about the database using the PostgreSQL COMMENT command. ##### `connect_settings` -Specifies a hash of environment variables used when connecting to a remote server. Default: Connects to the local Postgres instance. +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: Connects to the local Postgres instance. ##### `dbname` -Sets the name of the database to be created. Defaults to the namevar. +Sets the name of the database to be created. + +Default value: the namevar. ##### `encoding` -Overrides the character set during creation of the database. Defaults to the default defined during installation. +Overrides the character set during creation of the database. + +Default value: The default defined during installation. ##### `grant` -Specifies the permissions to grant during creation. Default: `ALL`. +Specifies the permissions to grant during creation. + +Default value: 'ALL'. ##### `istemplate` -Specifies that the database is a template, if set to true. Default: false. +Specifies that the database is a template, if set to `true`. + +Default value: `false`. ##### `locale` -Overrides the locale during creation of the database. Defaults to the default defined during installation. +Overrides the locale during creation of the database. + +Default value: The default defined during installation. ##### `owner` -Sets a user as the owner of the database. Default: $user variable set in `postgresql::server` or `postgresql::globals`. +Sets a user as the owner of the database. + +Default value: '$user' variable set in `postgresql::server` or `postgresql::globals`. ##### `password` **Required** Sets the password for the created user. ##### `tablespace` -Defines the name of the tablespace to allocate the created database to. Default: PostgreSQL default. +Defines the name of the tablespace to allocate the created database to. + +Default value: PostgreSQL default. ##### `template` -Specifies the name of the template database from which to build this database. Defaults to `template0`. +Specifies the name of the template database from which to build this database. + +Defaults value: `template0`. ##### `user` User to create and assign access to the database upon creation. Mandatory. #### postgresql::server::database Creates a database with no users and no permissions. ##### `dbname` -Sets the name of the database. Defaults to the namevar. +Sets the name of the database. + +Defaults value: The namevar. ##### `encoding` -Overrides the character set during creation of the database. Default: The default defined during installation. +Overrides the character set during creation of the database. + +Default value: The default defined during installation. ##### `istemplate` -Defines the database as a template if set to true. Default: false. +Defines the database as a template if set to `true`. + +Default value: `false`. ##### `locale` -Overrides the locale during creation of the database. The default defined during installation. +Overrides the locale during creation of the database. + +Default value: The default defined during installation. ##### `owner` -Sets name of the database owner. Default: The $user variable set in `postgresql::server` or `postgresql::globals`. +Sets name of the database owner. + +Default value: The '$user' variable set in `postgresql::server` or `postgresql::globals`. ##### `tablespace` -Sets tablespace for where to create this database. Default: The defaults defined during PostgreSQL installation. +Sets tablespace for where to create this database. + +Default value: The default defined during installation. ##### `template` -Specifies the name of the template database from which to build this database. Default: `template0`. +Specifies the name of the template database from which to build this database. + +Default value: 'template0'. #### postgresql::server::database_grant Manages grant-based access privileges for users, wrapping the `postgresql::server::database_grant` for database specific permissions. Consult the [PostgreSQL documentation for `grant`](http://www.postgresql.org/docs/current/static/sql-grant.html) for more information. #### `connect_settings` -Specifies a hash of environment variables used when connecting to a remote server. Default: Connects to the local Postgres instance. +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: Connects to the local Postgres instance. ##### `db` Specifies the database to which you are granting access. ##### `privilege` -Specifies comma-separated list of privileges to grant. Valid options: `ALL`, `CREATE`, `CONNECT`, `TEMPORARY`, `TEMP`. +Specifies comma-separated list of privileges to grant. + +Valid options: 'ALL', 'CREATE', 'CONNECT', 'TEMPORARY', 'TEMP'. ##### `psql_db` -Defines the database to execute the grant against. **This should not ordinarily be changed from the default**, which is `postgres`. +Defines the database to execute the grant against. + +**This should not ordinarily be changed from the default** + +Default value: 'postgres'. ##### `psql_user` -Specifies the OS user for running `psql`. Default: The default user for the module, usually `postgres`. +Specifies the OS user for running `psql`. + +Default value: The default user for the module, usually 'postgres'. ##### `role` Specifies the role or user whom you are granting access to. #### postgresql::server::extension Manages a PostgreSQL extension. ##### `database` Specifies the database on which to activate the extension. ##### `ensure` -Specifies whether to activate ('present') or deactivate (absent') the extension. +Specifies whether to activate or deactivate the extension. + +Valid options: 'present' or 'absent'. #### `extension` Specifies the extension to activate. If left blank, uses the name of the resource. ##### `package_name` Specifies a package to install prior to activating the extension. ##### `package_ensure` -Overrides default package deletion behavior. By default, the package specified with `package_name` is installed when the extension is activated and removed when the extension is deactivated. To override this behavior, set the `ensure` value for the package. +Overrides default package deletion behavior. + +By default, the package specified with `package_name` is installed when the extension is activated and removed when the extension is deactivated. To override this behavior, set the `ensure` value for the package. #### postgresql::server::grant Manages grant-based access privileges for roles. See [PostgreSQL documentation for `grant`](http://www.postgresql.org/docs/current/static/sql-grant.html) for more information. ##### `db` Specifies the database to which you are granting access. ##### `object_type` -Specifies the type of object to which you are granting privileges. Valid options: `DATABASE`, `SCHEMA`, `SEQUENCE`, `ALL SEQUENCES IN SCHEMA`, `TABLE` or `ALL TABLES IN SCHEMA`. +Specifies the type of object to which you are granting privileges. + +Valid options: 'DATABASE', 'SCHEMA', 'SEQUENCE', 'ALL SEQUENCES IN SCHEMA', 'TABLE' or 'ALL TABLES IN SCHEMA'. ##### `object_name` Specifies name of `object_type` to which to grant access. ##### `port` -Port to use when connecting. Default: undef, which generally defaults to port 5432 depending on your PostgreSQL packaging. +Port to use when connecting. + +Default value: `undef`, which generally defaults to port 5432 depending on your PostgreSQL packaging. ##### `privilege` -Specifies the privilege to grant. Valid options: `ALL`, `ALL PRIVILEGES` or `object_type` dependent string. +Specifies the privilege to grant. + +Valid options: 'ALL', 'ALL PRIVILEGES' or 'object_type' dependent string. ##### `psql_db` -Specifies the database to execute the grant against. _This should not ordinarily be changed from the default_, which is `postgres`. +Specifies the database to execute the grant against. + +**This should not ordinarily be changed from the default** + +Default value: 'postgres'. ##### `psql_user` -Sets the OS user to run `psql`. Default: the default user for the module, usually `postgres`. +Sets the OS user to run `psql`. + +Default value: the default user for the module, usually 'postgres'. ##### `role` Specifies the role or user whom you are granting access to. #### postgresql::server::grant_role Allows you to assign a role to a (group) role. See [PostgreSQL documentation for `Role Membership`](http://www.postgresql.org/docs/current/static/role-membership.html) for more information. ##### `group` Specifies the group role to which you are assigning a role. ##### `role` Specifies the role you want to assign to a group. If left blank, uses the name of the resource. ##### `ensure` -Specifies whether to grant ('present') or revoke ('absent') the membership. Default: 'present'. +Specifies whether to grant or revoke the membership. + +Valid options: 'present' or 'absent'. + +Default value: 'present'. ##### `port` -Port to use when connecting. Default: undef, which generally defaults to port 5432 depending on your PostgreSQL packaging. +Port to use when connecting. + +Default value: `undef`, which generally defaults to port 5432 depending on your PostgreSQL packaging. ##### `psql_db` -Specifies the database to execute the grant against. _This should not ordinarily be changed from the default_, which is `postgres`. +Specifies the database to execute the grant against. + +**This should not ordinarily be changed from the default** + +Default value: 'postgres'. ##### `psql_user` -Sets the OS user to run `psql`. Default: the default user for the module, usually `postgres`. +Sets the OS user to run `psql`. + +Default value: the default user for the module, usually `postgres`. ##### `connect_settings` -Specifies a hash of environment variables used when connecting to a remote server. Default: Connects to the local Postgres instance. +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: Connects to the local Postgres instance. #### postgresql::server::pg_hba_rule Allows you to create an access rule for `pg_hba.conf`. For more details see the [usage example](#create-an-access-rule-for-pghba.conf) and the [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html). ##### `address` Sets a CIDR based address for this rule matching when the type is not 'local'. ##### `auth_method` Provides the method that is used for authentication for the connection that this rule matches. Described further in the PostgreSQL `pg_hba.conf` documentation. ##### `auth_option` For certain `auth_method` settings there are extra options that can be passed. Consult the PostgreSQL `pg_hba.conf` documentation for further details. ##### `database` Sets a comma-separated list of databases that this rule matches. ##### `description` -Defines a longer description for this rule, if required. This description is placed in the comments above the rule in `pg_hba.conf`. Defaults: `none`. +Defines a longer description for this rule, if required. This description is placed in the comments above the rule in `pg_hba.conf`. + +Default value: 'none'. + Specifies a way to uniquely identify this resource, but functionally does nothing. + ##### `order` -Sets an order for placing the rule in `pg_hba.conf`. Default: `150`. +Sets an order for placing the rule in `pg_hba.conf`. + +Default value: 150. #### `postgresql_version` -Manages `pg_hba.conf` without managing the entire PostgreSQL instance. Default: the version set in `postgresql::server`. +Manages `pg_hba.conf` without managing the entire PostgreSQL instance. + +Default value: the version set in `postgresql::server`. ##### `target` -Provides the target for the rule, and is generally an internal only property. **Use with caution.** +Provides the target for the rule, and is generally an internal only property. + +**Use with caution.** ##### `type` -Sets the type of rule. Valid options: `local`, `host`, `hostssl` or `hostnossl`. +Sets the type of rule. + +Valid options: 'local', 'host', 'hostssl' or 'hostnossl'. ##### `user` Sets a comma-separated list of users that this rule matches. #### postgresql::server::pg_ident_rule Allows you to create user name maps for `pg_ident.conf`. For more details see the [usage example](#create-user-name-maps-for-pgidentconf) above and the [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/auth-username-maps.html). ##### `database_username` Specifies the user name of the database user. The `system_username` is mapped to this user name. ##### `description` -Sets a longer description for this rule if required. This description is placed in the comments above the rule in `pg_ident.conf`. Default: `none`. +Sets a longer description for this rule if required. This description is placed in the comments above the rule in `pg_ident.conf`. + +Default value: 'none'. ##### `map_name` Sets the name of the user map that is used to refer to this mapping in `pg_hba.conf`. ##### `order` -Defines an order for placing the mapping in `pg_ident.conf`. Default: 150. +Defines an order for placing the mapping in `pg_ident.conf`. + +Default value: 150. ##### `system_username` Specifies the operating system user name (the user name used to connect to the database). ##### `target` -Provides the target for the rule and is generally an internal only property. **Use with caution.** +Provides the target for the rule and is generally an internal only property. + +**Use with caution.** #### postgresql::server::recovery Allows you to create the content for `recovery.conf`. For more details see the [usage example](#create-recovery-configuration) and the [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/recovery-config.html). Every parameter value is a string set in the template except `recovery_target_inclusive`, `pause_at_recovery_target`, `standby_mode` and `recovery_min_apply_delay`. A detailed description of all listed parameters can be found in the [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/recovery-config.html). The parameters are grouped into these three sections: ##### [Archive Recovery Parameters](http://www.postgresql.org/docs/current/static/archive-recovery-settings.html) * `restore_command` * `archive_cleanup_command` * `recovery_end_command` ##### [Recovery Target Settings](http://www.postgresql.org/docs/current/static/recovery-target-settings.html) * `recovery_target_name` * `recovery_target_time` * `recovery_target_xid` * `recovery_target_inclusive` * `recovery_target` * `recovery_target_timeline` * `pause_at_recovery_target` ##### [Standby Server Settings](http://www.postgresql.org/docs/current/static/standby-settings.html) -* `standby_mode`: Can be specified with the string ('on'/'off'), or by using a Boolean value (true/false). +* `standby_mode`: Can be specified with the string ('on'/'off'), or by using a Boolean value (`true`/`false`). * `primary_conninfo` * `primary_slot_name` * `trigger_file` * `recovery_min_apply_delay` ##### `target` -Provides the target for the rule, and is generally an internal only property. **Use with caution.** +Provides the target for the rule, and is generally an internal only property. + +**Use with caution.** #### postgresql::server::role Creates a role or user in PostgreSQL. ##### `connection_limit` -Specifies how many concurrent connections the role can make. Default: `-1`, meaning no limit. +Specifies how many concurrent connections the role can make. + +Default value: '-1', meaning no limit. ##### `connect_settings` -Specifies a hash of environment variables used when connecting to a remote server. Default: Connects to the local Postgres instance. +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: Connects to the local Postgres instance. ##### `createdb` -Specifies whether to grant the ability to create new databases with this role. Default: false. +Specifies whether to grant the ability to create new databases with this role. + +Default value: `false`. ##### `createrole` -Specifies whether to grant the ability to create new roles with this role. Default: false. +Specifies whether to grant the ability to create new roles with this role. + +Default value: `false`. ##### `inherit` -Specifies whether to grant inherit capability for the new role. Default: true. +Specifies whether to grant inherit capability for the new role. + +Default value: `true`. ##### `login` -Specifies whether to grant login capability for the new role. Default: true. +Specifies whether to grant login capability for the new role. + +Default value: `true`. ##### `password_hash` Sets the hash to use during password creation. If the password is not already pre-encrypted in a format that PostgreSQL supports, use the `postgresql_password` function to provide an MD5 hash here, for example: +##### `update_password` +If set to true, updates the password on changes. Set this to false to not modify the role's password after creation. + ```puppet -postgresql::server::role { "myusername": -password_hash => postgresql_password('myusername', 'mypassword'), +postgresql::server::role { 'myusername': + password_hash => postgresql_password('myusername', 'mypassword'), } ``` ##### `replication` -Provides provides replication capabilities for this role if set to true. Default: false. +Provides provides replication capabilities for this role if set to `true`. + +Default value: `false`. ##### `superuser` -Specifies whether to grant super user capability for the new role. Default: false. +Specifies whether to grant super user capability for the new role. + +Default value: `false`. ##### `username` -Defines the username of the role to create. Defaults to the namevar. +Defines the username of the role to create. + +Default value: the namevar. #### postgresql::server::schema Creates a schema. ##### `connect_settings` -Specifies a hash of environment variables used when connecting to a remote server. Default: Connects to the local Postgres instance. +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: Connects to the local Postgres instance. ##### `db` -**Required**. Sets the name of the database in which to create this schema. +Required. + +Sets the name of the database in which to create this schema. ##### `owner` Sets the default owner of the schema. ##### `schema` -Sets the name of the schema. Defaults to the namevar. +Sets the name of the schema. + +Default value: the namevar. #### postgresql::server::table_grant Manages grant-based access privileges for users. Consult the PostgreSQL documentation for `grant` for more information. ##### `connect_settings` -Specifies a hash of environment variables used when connecting to a remote server. Default: Connects to the local Postgres instance. +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: Connects to the local Postgres instance. ##### `db` Specifies which database the table is in. ##### `privilege` -Specifies comma-separated list of privileges to grant. Valid options: `ALL`, `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, `REFERENCES`, `TRIGGER`. +Specifies comma-separated list of privileges to grant. Valid options: 'ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER'. ##### `psql_db` -Specifies the database to execute the grant against. This should not ordinarily be changed from the default, which is `postgres`. +Specifies the database to execute the grant against. + +This should not ordinarily be changed from the default. + +Default value: 'postgres'. ##### `psql_user` -Specifies the OS user for running `psql`. Defaults to the default user for the module, usually `postgres`. +Specifies the OS user for running `psql`. + +Default value: The default user for the module, usually 'postgres'. ##### `role` Specifies the role or user to whom you are granting access. ##### `table` Specifies the table to which you are granting access. - #### postgresql::server::tablespace Creates a tablespace. If necessary, also creates the location and assigns the same permissions as the PostgreSQL server. ##### `connect_settings` -Specifies a hash of environment variables used when connecting to a remote server. Default: Connects to the local Postgres instance. +Specifies a hash of environment variables used when connecting to a remote server. + +Default value: Connects to the local Postgres instance. ##### `location` Specifies the path to locate this tablespace. ##### `owner` Specifies the default owner of the tablespace. ##### `spcname` -Specifies the name of the tablespace. Defaults to the namevar. - -#### postgresql::validate_db_connection - -Validates client connection with a remote PostgreSQL database. - -##### `connect_settings` - -Specifies a hash of environment variables used when connecting to a remote server. This is an alternative to providing individual parameters (database_host, etc.). If provided, the individual parameters take precedence. - -##### `create_db_first` - -Ensures that the database is created before running the test. This only works if your test is local. Default: true. - -##### `database_host` - -Sets the hostname of the database you wish to test. Default: undef, which generally uses the designated local Unix socket. - -##### `database_name` - -Specifies the name of the database you wish to test. Default: 'postgres'. - -##### `database_port` - -Defines the port to use when connecting. Default: undef, which generally defaults to port 5432 depending on your PostgreSQL packaging. - -##### `database_password` - -Specifies the password to connect with. Can be left blank, not recommended. - -##### `database_username` - -Specifies the username to connect with. Default: undef. When using a Unix socket and ident auth, this is the user you are running as. **If the host is remote you must provide a username.** - -##### `run_as` - -Specifies the user to run the `psql` command as. This is important when trying to connect to a database locally using Unix sockets and `ident` authentication. Not needed for remote testing. +Specifies the name of the tablespace. -##### `sleep` - -Sets the number of seconds to sleep for before trying again after a failure. - -##### `tries` - -Sets the number of attempts after failure before giving up and failing the resource. +Default value: the namevar. ### Types #### postgresql_psql Enables Puppet to run psql statements. ##### `command` -**Required.** Specifies the SQL command to execute via psql. +Required. + +Specifies the SQL command to execute via psql. ##### `cwd` -Specifies the working directory under which the psql command should be executed. Default: '/tmp'. +Specifies the working directory under which the psql command should be executed. + +Default value: '/tmp'. ##### `db` Specifies the name of the database to execute the SQL command against. ##### `environment` Specifies any additional environment variables you want to set for a SQL command. Multiple environment variables should be specified as an array. ##### `name` -Sets an arbitrary tag for your own reference; the name of the message. This is the -namevar. +Sets an arbitrary tag for your own reference; the name of the message. This is the namevar. ##### `onlyif` Sets 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. ##### `port` Specifies the port of the database server to execute the SQL command against. ##### `psql_group` -Specifies the system user group account under which the psql command should be executed. Default: 'postgres'. +Specifies the system user group account under which the psql command should be executed. + +Default value: 'postgres'. ##### `psql_path` -Specifies the path to psql executable. Default: 'psql'. +Specifies the path to psql executable. + +Default value: 'psql'. ##### `psql_user` -Specifies the system user account under which the psql command should be executed. Default: 'postgres'. +Specifies the system user account under which the psql command should be executed. + +Default value: 'postgres'. ##### `refreshonly` -Specifies whether to execute the SQL only if there is a notify or subscribe event. Valid values: true, false. Default: false. +Specifies whether to execute the SQL only if there is a notify or subscribe event. + +Valid values: `true`, `false`. + +Default value: `false`. ##### `search_path` Defines the schema search path to use when executing the SQL command. ##### `unless` The inverse of `onlyif`. #### postgresql_conf Allows Puppet to manage `postgresql.conf` parameters. ##### `name` -Specifies the PostgreSQL parameter name to manage. This is the namevar. +Specifies the PostgreSQL parameter name to manage. + +This is the namevar. ##### `target` -Specifies the path to `postgresql.conf`. Default: '/etc/postgresql.conf'. +Specifies the path to `postgresql.conf`. + +Default value: '/etc/postgresql.conf'. ##### `value` Specifies the value to set for this parameter. #### postgresql_replication_slot Allows you to create and destroy replication slots to register warm standby replication on a PostgreSQL master server. ##### `name` -Specifies the name of the slot to create. Must be a valid replication slot name. This is the namevar. +Specifies the name of the slot to create. Must be a valid replication slot name. + +This is the namevar. + +#### postgresql_conn_validator + +Validate the connection to a local or remote PostgreSQL database using this type. + +##### `connect_settings` + +Specifies a hash of environment variables used when connecting to a remote server. This is an alternative to providing individual parameters (`host`, etc). If provided, the individual parameters take precedence. + +Default value: {} + +##### `db_name` + +Specifies the name of the database you wish to test. + +Default value: '' + +##### `db_password` + +Specifies the password to connect with. Can be left blank if `.pgpass` is being used, otherwise not recommended. + +Default value: '' + +##### `db_username` + +Specifies the username to connect with. + +Default value: '' + +When using a Unix socket and ident auth, this is the user you are running as. + +##### `command` + +This is the command run against the target database to verify connectivity. + +Default value: 'SELECT 1' + +##### `host` + +Sets the hostname of the database you wish to test. + +Default value: '', which generally uses the designated local Unix socket. + +**If the host is remote you must provide a username.** + +##### `port` + +Defines the port to use when connecting. + +Default value: '' + +##### `run_as` + +Specifies the user to run the `psql` command as. This is important when trying to connect to a database locally using Unix sockets and `ident` authentication. Not needed for remote testing. + +##### `sleep` + +Sets the number of seconds to sleep for before trying again after a failure. + +##### `tries` + +Sets the number of attempts after failure before giving up and failing the resource. ### Functions #### postgresql_password Generates a PostgreSQL encrypted password, use `postgresql_password`. Call it from the command line and then copy and paste the encrypted password into your manifest: -```puppet -puppet apply --execute 'notify { "test": message => postgresql_password("username", "password") }' +```shell +puppet apply --execute 'notify { 'test': message => postgresql_password('username', 'password') }' ``` Alternatively, you can call this from your production manifests, but the manifests will then contain a clear text version of your passwords. #### postgresql_acls_to_resources_hash(acl_array, id, order_offset) This internal function converts a list of `pg_hba.conf` based ACLs (passed in as an array of strings) to a format compatible with the `postgresql::pg_hba_rule` resource. **This function should only be used internally by the module**. ## Limitations Works with versions of PostgreSQL from 8.1 through 9.5. Currently, the postgresql module is tested on the following operating systems: * Debian 6.x, 7.x, 8.x. * CentOS 5.x, 6.x, and 7.x. * Ubuntu 10.04 and 12.04, 14.04. Other systems might be compatible, but are not being actively tested. ### Apt module support -While this module supports both 1.x and 2.x versions of the puppetlabs-apt module, it does not support puppetlabs-apt 2.0.0 or 2.0.1. +While this module supports both 1.x and 2.x versions of the 'puppetlabs-apt' module, it does not support 'puppetlabs-apt' 2.0.0 or 2.0.1. ### PostGIS support PostGIS is currently considered an unsupported feature, as it doesn't work on all platforms correctly. ### All versions of RHEL/CentOS If you have SELinux enabled you must add any custom ports you use to the `postgresql_port_t` context. You can do this as follows: -``` +```shell semanage port -a -t postgresql_port_t -p tcp $customport ``` ## Development Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve. We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. For more information, see our [module contribution guide](https://docs.puppetlabs.com/forge/contributing.html). ### Tests There are two types of tests distributed with this module. Unit tests with `rspec-puppet` and system tests using `rspec-system`. For unit testing, make sure you have: * rake * bundler Install the necessary gems: -``` +```shell bundle install --path=vendor ``` And then run the unit tests: -``` +```shell bundle exec rake spec ``` The unit tests are run in Travis-CI as well. If you want to see the results of your own tests, register the service hook through Travis-CI via the accounts section for your GitHub clone of this project. To run the system tests, make sure you also have: * Vagrant > 1.2.x * VirtualBox > 4.2.10 Then run the tests using: -``` +```shell bundle exec rspec spec/acceptance ``` To run the tests on different operating systems, see the sets available in `.nodeset.yml` and run the specific set with the following syntax: -``` +```shell RSPEC_SET=debian-607-x64 bundle exec rspec spec/acceptance ``` ### Contributors -View the full list of contributors on [https://github.com/puppetlabs/puppetlabs-postgresql/graphs/contributors](GitHub). +View the full list of contributors on [Github](https://github.com/puppetlabs/puppetlabs-postgresql/graphs/contributors). diff --git a/lib/puppet/provider/postgresql_conn_validator/ruby.rb b/lib/puppet/provider/postgresql_conn_validator/ruby.rb new file mode 100644 index 0000000..f31b8b9 --- /dev/null +++ b/lib/puppet/provider/postgresql_conn_validator/ruby.rb @@ -0,0 +1,43 @@ +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),"..","..","..")) +require 'puppet/util/postgresql_validator' + +# This file contains a provider for the resource type `postgresql_conn_validator`, +# which validates the puppetdb connection by attempting an https connection. + +Puppet::Type.type(:postgresql_conn_validator).provide(:ruby) do + desc "A provider for the resource type `postgresql_conn_validator`, + which validates the PostgreSQL connection by attempting a query + to the target PostgreSQL server." + + # Test to see if the resource exists, returns true if it does, false if it + # does not. + # + # Here we simply monopolize the resource API, to execute a test to see if the + # database is connectable. When we return a state of `false` it triggers the + # create method where we can return an error message. + # + # @return [bool] did the test succeed? + def exists? + validator.attempt_connection(resource[:sleep], resource[:tries]) + end + + # This method is called when the exists? method returns false. + # + # @return [void] + def create + # If `#create` is called, that means that `#exists?` returned false, which + # means that the connection could not be established... so we need to + # cause a failure here. + raise Puppet::Error, "Unable to connect to PostgreSQL server! (#{resource[:host]}:#{resource[:port]})" + end + + # Returns the existing validator, if one exists otherwise creates a new object + # from the class. + # + # @api private + def validator + @validator ||= Puppet::Util::PostgresqlValidator.new(resource) + end + +end + diff --git a/lib/puppet/type/postgresql_conn_validator.rb b/lib/puppet/type/postgresql_conn_validator.rb new file mode 100644 index 0000000..b9dc64e --- /dev/null +++ b/lib/puppet/type/postgresql_conn_validator.rb @@ -0,0 +1,88 @@ +Puppet::Type.newtype(:postgresql_conn_validator) do + + @doc = "Verify that a connection can be successfully established between a node + and the PostgreSQL server. Its primary use is as a precondition to + prevent configuration changes from being applied if the PostgreSQL + server cannot be reached, but it could potentially be used for other + purposes such as monitoring." + + ensurable do + defaultvalues + defaultto :present + end + + newparam(:name, :namevar => true) do + desc 'An arbitrary name used as the identity of the resource.' + end + + newparam(:db_name) do + desc "The name of the database you are trying to validate a connection with." + end + + newparam(:db_username) do + desc "A user that has access to the target PostgreSQL database." + end + + newparam(:db_password) do + desc "The password required to access the target PostgreSQL database." + end + + newparam(:host) do + desc 'The DNS name or IP address of the server where PostgreSQL should be running.' + end + + newparam(:port) do + desc 'The port that the PostgreSQL server should be listening on.' + + validate do |value| + Integer(value) + end + munge do |value| + Integer(value) + end + end + + newparam(:connect_settings) do + desc 'Hash of environment variables for connection to a db.' + end + + newparam(:sleep) do + desc "The length of sleep time between connection tries." + + validate do |value| + Integer(value) + end + munge do |value| + Integer(value) + end + + defaultto 2 + end + + newparam(:tries) do + desc "The number of tries to validate the connection to the target PostgreSQL database." + + validate do |value| + Integer(value) + end + munge do |value| + Integer(value) + end + + defaultto 10 + end + + newparam(:psql_path) do + desc "Path to the psql command." + end + + newparam(:run_as) do + desc "System user that will run the psql command." + end + + newparam(:command) do + desc "Command to run against target database." + + defaultto "SELECT 1" + end +end diff --git a/lib/puppet/util/postgresql_validator.rb b/lib/puppet/util/postgresql_validator.rb new file mode 100644 index 0000000..d737f12 --- /dev/null +++ b/lib/puppet/util/postgresql_validator.rb @@ -0,0 +1,65 @@ +module Puppet + module Util + class PostgresqlValidator + attr_reader :resource + + def initialize(resource) + @resource = resource + end + + def build_psql_cmd + final_cmd = [] + + cmd_init = "#{@resource[:psql_path]} --tuples-only --quiet --no-psqlrc" + + final_cmd.push cmd_init + + cmd_parts = { + :host => "--host #{@resource[:host]}", + :port => "--port #{@resource[:port]}", + :db_username => "--username #{@resource[:db_username]}", + :db_name => "--dbname #{@resource[:db_name]}", + :command => "--command '#{@resource[:command]}'" + } + + cmd_parts.each do |k,v| + final_cmd.push v if @resource[k] + end + + final_cmd.join ' ' + end + + def parse_connect_settings + c_settings = @resource[:connect_settings] || {} + c_settings.merge! ({ 'PGPASSWORD' => @resource[:db_password] }) if @resource[:db_password] + return c_settings.map { |k,v| "#{k}=#{v}" } + end + + def attempt_connection(sleep_length, tries) + (0..tries-1).each do |try| + Puppet.debug "PostgresqlValidator.attempt_connection: Attempting connection to #{@resource[:db_name]}" + Puppet.debug "PostgresqlValidator.attempt_connection: #{build_validate_cmd}" + result = execute_command + if result && result.length > 0 + Puppet.debug "PostgresqlValidator.attempt_connection: Connection to #{@resource[:db_name] || parse_connect_settings.select { |elem| elem.match /PGDATABASE/ }} successful!" + return true + else + Puppet.warning "PostgresqlValidator.attempt_connection: Sleeping for #{sleep_length} seconds" + sleep sleep_length + end + end + false + end + + private + + def execute_command + Execution.execute(build_validate_cmd, :uid => @resource[:run_as]) + end + + def build_validate_cmd + "#{parse_connect_settings.join(' ')} #{build_psql_cmd} " + end + end + end +end diff --git a/locales/config.yaml b/locales/config.yaml new file mode 100644 index 0000000..4d2b70b --- /dev/null +++ b/locales/config.yaml @@ -0,0 +1,25 @@ +--- +# This is the project-specific configuration file for setting up +# fast_gettext for your project. +gettext: + # This is used for the name of the .pot and .po files; they will be + # called .pot? + project_name: puppetlabs-postgresql + # This is used in comments in the .pot and .po files to indicate what + # project the files belong to and should bea little more desctiptive than + # + package_name: puppetlabs-postgresql + # The locale that the default messages in the .pot file are in + default_locale: en + # The email used for sending bug reports. + bugs_address: docs@puppet.com + # The holder of the copyright. + copyright_holder: Puppet, Inc. + # This determines which comments in code should be eligible for translation. + # Any comments that start with this string will be externalized. (Leave + # empty to include all.) + comments_tag: TRANSLATOR + # Patterns for +Dir.glob+ used to find all files that might contain + # translatable content, relative to the project root directory + source_files: + diff --git a/locales/puppetlabs-postgresql.pot b/locales/puppetlabs-postgresql.pot new file mode 100644 index 0000000..4d8c456 --- /dev/null +++ b/locales/puppetlabs-postgresql.pot @@ -0,0 +1,18 @@ +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-21 14:19+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Translate Toolkit 2.0.0\n" + +#. metadata.json +#: .summary +msgid "Offers support for basic management of PostgreSQL databases." +msgstr "" diff --git a/manifests/client.pp b/manifests/client.pp index b805749..7e6da1c 100644 --- a/manifests/client.pp +++ b/manifests/client.pp @@ -1,27 +1,25 @@ # Install client cli tool. See README.md for more details. class postgresql::client ( - $file_ensure = 'file', - $validcon_script_path = $postgresql::params::validcon_script_path, - $package_name = $postgresql::params::client_package_name, - $package_ensure = 'present' + Enum['file', 'absent'] $file_ensure = 'file', + Stdlib::Absolutepath $validcon_script_path = $postgresql::params::validcon_script_path, + String[1] $package_name = $postgresql::params::client_package_name, + String[1] $package_ensure = 'present' ) inherits postgresql::params { - validate_absolute_path($validcon_script_path) - validate_string($package_name) if $package_name != 'UNSET' { package { 'postgresql-client': ensure => $package_ensure, name => $package_name, tag => 'postgresql', } } file { $validcon_script_path: ensure => $file_ensure, source => 'puppet:///modules/postgresql/validate_postgresql_connection.sh', owner => 0, group => 0, mode => '0755', } } diff --git a/manifests/globals.pp b/manifests/globals.pp index b005c62..5fa248f 100644 --- a/manifests/globals.pp +++ b/manifests/globals.pp @@ -1,155 +1,156 @@ # Class for setting cross-class global overrides. See README.md for more # details. class postgresql::globals ( $client_package_name = undef, $server_package_name = undef, $contrib_package_name = undef, $devel_package_name = undef, $java_package_name = undef, $docs_package_name = undef, $perl_package_name = undef, $plperl_package_name = undef, $plpython_package_name = undef, $python_package_name = undef, $postgis_package_name = undef, $service_name = undef, $service_provider = undef, $service_status = undef, $default_database = undef, $validcon_script_path = undef, $initdb_path = undef, $createdb_path = undef, $psql_path = undef, $pg_hba_conf_path = undef, $pg_ident_conf_path = undef, $postgresql_conf_path = undef, $recovery_conf_path = undef, $default_connect_settings = {}, $pg_hba_conf_defaults = undef, $datadir = undef, $confdir = undef, $bindir = undef, $xlogdir = undef, $logdir = undef, $log_line_prefix = undef, $user = undef, $group = undef, $version = undef, $postgis_version = undef, $repo_proxy = undef, $repo_baseurl = undef, $needs_initdb = undef, $encoding = undef, $locale = undef, $timezone = undef, $manage_pg_hba_conf = undef, $manage_pg_ident_conf = undef, $manage_recovery_conf = undef, $manage_package_repo = undef, $module_workdir = undef, ) { # We are determining this here, because it is needed by the package repo # class. $default_version = $::osfamily ? { /^(RedHat|Linux)/ => $::operatingsystem ? { 'Fedora' => $::operatingsystemrelease ? { /^(24|25)$/ => '9.5', /^(22|23)$/ => '9.4', /^(21)$/ => '9.3', /^(18|19|20)$/ => '9.2', /^(17)$/ => '9.1', default => undef, }, 'Amazon' => '9.2', default => $::operatingsystemrelease ? { /^7\./ => '9.2', /^6\./ => '8.4', /^5\./ => '8.1', default => undef, }, }, 'Debian' => $::operatingsystem ? { 'Debian' => $::operatingsystemrelease ? { /^(squeeze|6\.)/ => '8.4', /^(wheezy|7\.)/ => '9.1', /^(jessie|8\.)/ => '9.4', /^(stretch|9\.)/ => '9.6', default => undef, }, 'Ubuntu' => $::operatingsystemrelease ? { /^(10.04|10.10|11.04)$/ => '8.4', /^(11.10|12.04|12.10|13.04|13.10)$/ => '9.1', /^(14.04)$/ => '9.3', /^(14.10|15.04|15.10)$/ => '9.4', /^(16.04|16.10)$/ => '9.5', default => undef, }, default => undef, }, 'Archlinux' => $::operatingsystem ? { /Archlinux/ => '9.2', default => '9.2', }, 'Gentoo' => '9.5', 'FreeBSD' => '93', 'OpenBSD' => $::operatingsystemrelease ? { /5\.6/ => '9.3', /5\.[7-9]/ => '9.4', /6\.[0-9]/ => '9.5', }, 'Suse' => $::operatingsystem ? { 'SLES' => $::operatingsystemrelease ? { /11\.[0-4]/ => '91', - default => '93', + /12\.0/ => '93', + default => '94', }, 'OpenSuSE' => $::operatingsystemrelease ? { - '13.2' => '93', + default => '94', }, default => undef, }, default => undef, } $globals_version = pick($version, $default_version, 'unknown') if($globals_version == 'unknown') { fail('No preferred version defined or automatically detected.') } $default_postgis_version = $globals_version ? { '8.1' => '1.3.6', - '8.4' => '1.5', - '9.0' => '1.5', - '9.1' => '1.5', - '91' => '1.5', - '9.2' => '2.0', - '9.3' => '2.1', - '93' => '2.1', - '9.4' => '2.1', - '9.5' => '2.2', + '8.4' => '2.0', + '9.0' => '2.1', + '9.1' => '2.1', + '91' => '2.1', + '9.2' => '2.3', + '9.3' => '2.3', + '93' => '2.3', + '9.4' => '2.3', + '9.5' => '2.3', '9.6' => '2.3', default => undef, } $globals_postgis_version = $postgis_version ? { undef => $default_postgis_version, default => $postgis_version, } # Setup of the repo only makes sense globally, so we are doing this here. if($manage_package_repo) { class { 'postgresql::repo': version => $globals_version, proxy => $repo_proxy, baseurl => $repo_baseurl, } } } diff --git a/manifests/lib/devel.pp b/manifests/lib/devel.pp index bbc5272..e6ff183 100644 --- a/manifests/lib/devel.pp +++ b/manifests/lib/devel.pp @@ -1,30 +1,28 @@ # 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', - $link_pg_config = $postgresql::params::link_pg_config + String $package_name = $postgresql::params::devel_package_name, + String[1] $package_ensure = 'present', + Boolean $link_pg_config = $postgresql::params::link_pg_config ) inherits postgresql::params { - validate_string($package_name) - if $::osfamily == 'Gentoo' { fail('osfamily Gentoo does not have a separate "devel" package, postgresql::lib::devel is not supported') } package { 'postgresql-devel': ensure => $package_ensure, name => $package_name, tag => 'postgresql', } if $link_pg_config { if ( $postgresql::params::bindir != '/usr/bin' and $postgresql::params::bindir != '/usr/local/bin') { file { '/usr/bin/pg_config': ensure => link, target => "${postgresql::params::bindir}/pg_config", } } } } diff --git a/manifests/lib/docs.pp b/manifests/lib/docs.pp index 55825d1..f3c31ff 100644 --- a/manifests/lib/docs.pp +++ b/manifests/lib/docs.pp @@ -1,16 +1,14 @@ # This class installs the postgresql-docs See README.md for more # details. class postgresql::lib::docs ( - $package_name = $postgresql::params::docs_package_name, - $package_ensure = 'present', + String $package_name = $postgresql::params::docs_package_name, + String[1] $package_ensure = 'present', ) inherits postgresql::params { - validate_string($package_name) - package { 'postgresql-docs': ensure => $package_ensure, name => $package_name, tag => 'postgresql', } } diff --git a/manifests/lib/java.pp b/manifests/lib/java.pp index 0a2d45f..dc131d5 100644 --- a/manifests/lib/java.pp +++ b/manifests/lib/java.pp @@ -1,16 +1,14 @@ # 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' + String $package_name = $postgresql::params::java_package_name, + String[1] $package_ensure = 'present' ) inherits postgresql::params { - validate_string($package_name) - package { 'postgresql-jdbc': ensure => $package_ensure, name => $package_name, tag => 'postgresql', } } diff --git a/manifests/lib/perl.pp b/manifests/lib/perl.pp index 6ed2853..67fd4a2 100644 --- a/manifests/lib/perl.pp +++ b/manifests/lib/perl.pp @@ -1,13 +1,13 @@ # This class installs the perl libs for postgresql. See README.md for more # details. class postgresql::lib::perl( - $package_name = $postgresql::params::perl_package_name, - $package_ensure = 'present' + String $package_name = $postgresql::params::perl_package_name, + String[1] $package_ensure = 'present' ) inherits postgresql::params { package { 'perl-DBD-Pg': ensure => $package_ensure, name => $package_name, } } diff --git a/manifests/lib/python.pp b/manifests/lib/python.pp index bfe0585..590727d 100644 --- a/manifests/lib/python.pp +++ b/manifests/lib/python.pp @@ -1,13 +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' + String[1] $package_name = $postgresql::params::python_package_name, + String[1] $package_ensure = 'present' ) inherits postgresql::params { package { 'python-psycopg2': ensure => $package_ensure, name => $package_name, } } diff --git a/manifests/params.pp b/manifests/params.pp index b07f8f2..cf3abe8 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -1,314 +1,319 @@ # PRIVATE CLASS: do not use directly class postgresql::params inherits postgresql::globals { $version = $postgresql::globals::globals_version $postgis_version = $postgresql::globals::globals_postgis_version - $listen_addresses = 'localhost' + $listen_addresses = undef $port = 5432 - $log_line_prefix = '%t ' + $log_line_prefix = undef $ip_mask_deny_postgres_user = '0.0.0.0/0' $ip_mask_allow_all_users = '127.0.0.1/32' $ipv4acls = [] $ipv6acls = [] $encoding = $postgresql::globals::encoding $locale = $postgresql::globals::locale $timezone = $postgresql::globals::timezone $service_ensure = 'running' $service_enable = true $service_manage = true $service_restart_on_change = true $service_provider = $postgresql::globals::service_provider $manage_pg_hba_conf = pick($manage_pg_hba_conf, true) $manage_pg_ident_conf = pick($manage_pg_ident_conf, true) $manage_recovery_conf = pick($manage_recovery_conf, false) $package_ensure = 'present' $module_workdir = pick($module_workdir,'/tmp') # Amazon Linux's OS Family is 'Linux', operating system 'Amazon'. case $::osfamily { 'RedHat', 'Linux': { $link_pg_config = true $user = pick($user, 'postgres') $group = pick($group, 'postgres') $needs_initdb = pick($needs_initdb, true) $version_parts = split($version, '[.]') $package_version = "${version_parts[0]}${version_parts[1]}" if $version == $postgresql::globals::default_version and $::operatingsystem != 'Amazon' { $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') $docs_package_name = pick($docs_package_name, 'postgresql-docs') $plperl_package_name = pick($plperl_package_name, 'postgresql-plperl') $plpython_package_name = pick($plpython_package_name, 'postgresql-plpython') $service_name = pick($service_name, 'postgresql') $bindir = pick($bindir, '/usr/bin') $datadir = $::operatingsystem ? { 'Amazon' => pick($datadir, "/var/lib/pgsql${package_version}/data"), default => pick($datadir, '/var/lib/pgsql/data'), } $confdir = pick($confdir, $datadir) } else { $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") $docs_package_name = pick($docs_package_name, "postgresql${package_version}-docs") $plperl_package_name = pick($plperl_package_name, "postgresql${package_version}-plperl") $plpython_package_name = pick($plpython_package_name, "postgresql${package_version}-plpython") $service_name = $::operatingsystem ? { 'Amazon' => pick($service_name, "postgresql${version_parts[0]}${version_parts[1]}"), default => pick($service_name, "postgresql-${version}"), } $bindir = $::operatingsystem ? { 'Amazon' => pick($bindir, '/usr/bin'), default => pick($bindir, "/usr/pgsql-${version}/bin"), } $datadir = $::operatingsystem ? { 'Amazon' => pick($datadir, "/var/lib/pgsql${package_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 $service_reload = "service ${service_name} reload" $perl_package_name = pick($perl_package_name, 'perl-DBD-Pg') $python_package_name = pick($python_package_name, 'python-psycopg2') if $postgresql::globals::postgis_package_name { $postgis_package_name = $postgresql::globals::postgis_package_name } elsif $::operatingsystemrelease =~ /^5\./ { $postgis_package_name = 'postgis' } elsif $postgis_version and versioncmp($postgis_version, '2') < 0 { $postgis_package_name = "postgis${package_version}" } else { $postgis_package_name = "postgis2_${package_version}" } } 'Archlinux': { $link_pg_config = true $needs_initdb = pick($needs_initdb, true) $user = pick($user, 'postgres') $group = pick($group, 'postgres') # 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') $plpython_package_name = pick($plpython_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 $service_reload = "systemctl reload ${service_name}" $python_package_name = pick($python_package_name, 'python-psycopg2') # Archlinux does not have a perl::DBD::Pg package $perl_package_name = pick($perl_package_name, 'undef') } 'Debian': { $link_pg_config = false $user = pick($user, 'postgres') $group = pick($group, 'postgres') if $postgresql::globals::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}") if $postgis_version and versioncmp($postgis_version, '2') < 0 { $postgis_package_name = pick($postgis_package_name, "postgresql-${version}-postgis") } else { $postgis_package_name = pick($postgis_package_name, "postgresql-${version}-postgis-${postgis_version}") } $devel_package_name = pick($devel_package_name, 'libpq-dev') $java_package_name = $::operatingsystem ? { 'Debian' => $::operatingsystemrelease ? { /^6/ => pick($java_package_name, 'libpg-java'), default => pick($java_package_name, 'libpostgresql-jdbc-java'), }, default => pick($java_package_name, 'libpostgresql-jdbc-java'), } $perl_package_name = pick($perl_package_name, 'libdbd-pg-perl') $plperl_package_name = pick($plperl_package_name, "postgresql-plperl-${version}") $plpython_package_name = pick($plpython_package_name, "postgresql-plpython-${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") if $::operatingsystem == 'Debian' and versioncmp($::operatingsystemrelease, '8.0') >= 0 { # Jessie uses systemd $service_status = pick($service_status, "/usr/sbin/service ${service_name}@*-main status") } elsif $::operatingsystem == 'Ubuntu' and versioncmp($::operatingsystemrelease, '15.04') >= 0 { # Ubuntu releases since vivid use systemd $service_status = pick($service_status, "/usr/sbin/service ${service_name} status") } else { $service_status = pick($service_status, "/etc/init.d/${service_name} status | /bin/egrep -q 'Running clusters: .+|online'") } $service_reload = "service ${service_name} reload" $psql_path = pick($psql_path, '/usr/bin/psql') } 'Gentoo': { $user = pick($user, 'postgres') $group = pick($group, 'postgres') $client_package_name = pick($client_package_name, 'UNSET') $server_package_name = pick($server_package_name, 'postgresql') $contrib_package_name = pick_default($contrib_package_name, undef) $devel_package_name = pick_default($devel_package_name, undef) $java_package_name = pick($java_package_name, 'jdbc-postgresql') $perl_package_name = pick($perl_package_name, 'DBD-Pg') $plperl_package_name = undef $python_package_name = pick($python_package_name, 'psycopg') $service_name = pick($service_name, "postgresql-${version}") $bindir = pick($bindir, "/usr/lib/postgresql-${version}/bin") $datadir = pick($datadir, "/var/lib/postgresql/${version}_data") $confdir = pick($confdir, "/etc/postgresql-${version}") $service_status = pick($service_status, "systemctl status ${service_name}") $service_reload = "systemctl reload ${service_name}" $psql_path = pick($psql_path, "${bindir}/psql") $needs_initdb = pick($needs_initdb, true) } 'FreeBSD': { case $version { '96': { $user = pick($user, 'postgres') $group = pick($group, 'postgres') $datadir = pick($datadir, "/var/db/postgres/data${version}") } default: { $user = pick($user, 'pgsql') $group = pick($group, 'pgsql') $datadir = pick($datadir, '/usr/local/pgsql/data') } } $link_pg_config = true $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') $perl_package_name = pick($plperl_package_name, 'databases/p5-DBD-Pg') $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') $confdir = pick($confdir, $datadir) $service_status = pick($service_status, "/usr/local/etc/rc.d/${service_name} onestatus") $service_reload = "service ${service_name} reload" $psql_path = pick($psql_path, "${bindir}/psql") $needs_initdb = pick($needs_initdb, true) } 'OpenBSD': { $user = pick($user, '_postgresql') $group = pick($group, '_postgresql') $client_package_name = pick($client_package_name, 'postgresql-client') $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-client') $java_package_name = pick($java_package_name, 'postgresql-jdbc') $perl_package_name = pick($perl_package_name, 'databases/p5-DBD-Pg') $plperl_package_name = undef $python_package_name = pick($python_package_name, 'py-psycopg2') $service_name = pick($service_name, 'postgresql') $bindir = pick($bindir, '/usr/local/bin') $datadir = pick($datadir, '/var/postgresql/data') $confdir = pick($confdir, $datadir) $service_status = pick($service_status, "/etc/rc.d/${service_name} check") $service_reload = "/etc/rc.d/${service_name} reload" $psql_path = pick($psql_path, "${bindir}/psql") $needs_initdb = pick($needs_initdb, true) } 'Suse': { $link_pg_config = true $user = pick($user, 'postgres') $group = pick($group, 'postgres') $client_package_name = pick($client_package_name, "postgresql${version}") $server_package_name = pick($server_package_name, "postgresql${version}-server") $contrib_package_name = pick($contrib_package_name, "postgresql${version}-contrib") $devel_package_name = pick($devel_package_name, "postgresql${version}-devel") $java_package_name = pick($java_package_name, "postgresql${version}-jdbc") $perl_package_name = pick($plperl_package_name, 'perl-DBD-Pg') $plperl_package_name = pick($plperl_package_name, "postgresql${version}-plperl") $python_package_name = pick($python_package_name, 'python-psycopg2') $service_name = pick($service_name, 'postgresql') $bindir = pick($bindir, "/usr/lib/postgresql${version}/bin") $datadir = pick($datadir, '/var/lib/pgsql/data') $confdir = pick($confdir, $datadir) - $service_status = pick($service_status, "/etc/init.d/${service_name} status") - $service_reload = "/etc/init.d/${service_name} reload" + if $::operatingsystem == 'SLES' and versioncmp($::operatingsystemrelease, '11.4') <= 0 { + $service_status = pick($service_status, "/etc/init.d/${service_name} status") + $service_reload = "/etc/init.d/${service_name} reload" + } else { + $service_status = pick($service_status, "systemctl status ${service_name}") + $service_reload = "systemctl reload ${service_name}" + } $psql_path = pick($psql_path, "${bindir}/psql") $needs_initdb = pick($needs_initdb, true) } default: { $link_pg_config = true $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") } } } $validcon_script_path = pick($validcon_script_path, '/usr/local/bin/validate_postgresql_connection.sh') $initdb_path = pick($initdb_path, "${bindir}/initdb") $pg_hba_conf_path = pick($pg_hba_conf_path, "${confdir}/pg_hba.conf") $pg_hba_conf_defaults = pick($pg_hba_conf_defaults, true) $pg_ident_conf_path = pick($pg_ident_conf_path, "${confdir}/pg_ident.conf") $postgresql_conf_path = pick($postgresql_conf_path, "${confdir}/postgresql.conf") $recovery_conf_path = pick($recovery_conf_path, "${datadir}/recovery.conf") $default_database = pick($default_database, 'postgres') } diff --git a/manifests/repo/apt_postgresql_org.pp b/manifests/repo/apt_postgresql_org.pp index 71f76d5..3e671f3 100644 --- a/manifests/repo/apt_postgresql_org.pp +++ b/manifests/repo/apt_postgresql_org.pp @@ -1,28 +1,32 @@ # PRIVATE CLASS: do not use directly class postgresql::repo::apt_postgresql_org inherits postgresql::repo { include ::apt # Here we have tried to replicate the instructions on the PostgreSQL site: # # http://www.postgresql.org/download/linux/debian/ # $default_baseurl = 'http://apt.postgresql.org/pub/repos/apt/' $_baseurl = pick($postgresql::repo::baseurl, $default_baseurl) apt::pin { 'apt_postgresql_org': originator => 'apt.postgresql.org', priority => 500, - }-> - apt::source { 'apt.postgresql.org': - location => $_baseurl, - release => "${::lsbdistcodename}-pgdg", - repos => "main ${postgresql::repo::version}", - key => 'B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8', - key_source => 'https://www.postgresql.org/media/keys/ACCC4CF8.asc', - include_src => false, + } + -> apt::source { 'apt.postgresql.org': + location => $_baseurl, + release => "${::lsbdistcodename}-pgdg", + repos => "main ${postgresql::repo::version}", + key => { + id => 'B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8', + source => 'https://www.postgresql.org/media/keys/ACCC4CF8.asc', + }, + include => { + src => false, + }, } Apt::Source['apt.postgresql.org']->Package<|tag == 'postgresql'|> Class['Apt::Update'] -> Package<|tag == 'postgresql'|> } diff --git a/manifests/server.pp b/manifests/server.pp index 2e90178..306410e 100644 --- a/manifests/server.pp +++ b/manifests/server.pp @@ -1,83 +1,83 @@ # This installs a PostgreSQL server. See README.md for more details. class postgresql::server ( $postgres_password = undef, $package_name = $postgresql::params::server_package_name, $package_ensure = $postgresql::params::package_ensure, $plperl_package_name = $postgresql::params::plperl_package_name, $plpython_package_name = $postgresql::params::plpython_package_name, $service_ensure = $postgresql::params::service_ensure, $service_enable = $postgresql::params::service_enable, $service_manage = $postgresql::params::service_manage, $service_name = $postgresql::params::service_name, $service_restart_on_change = $postgresql::params::service_restart_on_change, $service_provider = $postgresql::params::service_provider, $service_reload = $postgresql::params::service_reload, $service_status = $postgresql::params::service_status, $default_database = $postgresql::params::default_database, $default_connect_settings = $postgresql::globals::default_connect_settings, $listen_addresses = $postgresql::params::listen_addresses, $port = $postgresql::params::port, $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, $pg_ident_conf_path = $postgresql::params::pg_ident_conf_path, $postgresql_conf_path = $postgresql::params::postgresql_conf_path, $recovery_conf_path = $postgresql::params::recovery_conf_path, $datadir = $postgresql::params::datadir, $xlogdir = $postgresql::params::xlogdir, $logdir = $postgresql::params::logdir, $log_line_prefix = $postgresql::params::log_line_prefix, $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, $timezone = $postgresql::params::timezone, $manage_pg_hba_conf = $postgresql::params::manage_pg_hba_conf, $manage_pg_ident_conf = $postgresql::params::manage_pg_ident_conf, $manage_recovery_conf = $postgresql::params::manage_recovery_conf, $module_workdir = $postgresql::params::module_workdir, #Deprecated $version = undef, ) inherits postgresql::params { $pg = 'postgresql::server' if $version != undef { warning('Passing "version" to postgresql::server is deprecated; please use postgresql::globals instead.') $_version = $version } else { $_version = $postgresql::params::version } if $createdb_path != undef{ warning('Passing "createdb_path" to postgresql::server is deprecated, it can be removed safely for the same behaviour') } # 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": }-> - anchor { "${pg}::end": } + anchor { "${pg}::start": } + -> class { "${pg}::install": } + -> class { "${pg}::initdb": } + -> class { "${pg}::config": } + -> class { "${pg}::service": } + -> class { "${pg}::passwd": } + -> anchor { "${pg}::end": } } diff --git a/manifests/server/config.pp b/manifests/server/config.pp index 205dd22..616fc34 100644 --- a/manifests/server/config.pp +++ b/manifests/server/config.pp @@ -1,219 +1,221 @@ # PRIVATE CLASS: do not call directly class postgresql::server::config { $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 $port = $postgresql::server::port $ipv4acls = $postgresql::server::ipv4acls $ipv6acls = $postgresql::server::ipv6acls $pg_hba_conf_path = $postgresql::server::pg_hba_conf_path $pg_ident_conf_path = $postgresql::server::pg_ident_conf_path $postgresql_conf_path = $postgresql::server::postgresql_conf_path $recovery_conf_path = $postgresql::server::recovery_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 $manage_pg_ident_conf = $postgresql::server::manage_pg_ident_conf $manage_recovery_conf = $postgresql::server::manage_recovery_conf $datadir = $postgresql::server::datadir $logdir = $postgresql::server::logdir $service_name = $postgresql::server::service_name $log_line_prefix = $postgresql::server::log_line_prefix $timezone = $postgresql::server::timezone if ($manage_pg_hba_conf == true) { # Prepare the main pg_hba file concat { $pg_hba_conf_path: owner => $user, group => $group, mode => '0640', warn => true, + order => 'numeric', 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', + order => 1, } postgresql::server::pg_hba_rule { 'local access to database with same name': type => 'local', auth_method => 'ident', auth_option => $local_auth_option, - order => '002', + order => 2, } 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', + order => 3, } 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', + order => 4, } postgresql::server::pg_hba_rule { 'allow access to all users': type => 'host', address => $ip_mask_allow_all_users, auth_method => 'md5', - order => '100', + order => 100, } postgresql::server::pg_hba_rule { 'allow access to ipv6 localhost': type => 'host', address => '::1/128', auth_method => 'md5', - order => '101', + order => 101, } } # 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) # 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, + if $listen_addresses { + postgresql::server::config_entry { 'listen_addresses': + value => $listen_addresses, + } } + postgresql::server::config_entry { 'port': value => $port, } postgresql::server::config_entry { 'data_directory': value => $datadir, } if $timezone { postgresql::server::config_entry { 'timezone': value => $timezone, } } if $logdir { postgresql::server::config_entry { 'log_directory': value => $logdir, } } # Allow timestamps in log by default if $log_line_prefix { postgresql::server::config_entry {'log_line_prefix': value => $log_line_prefix, } } # RedHat-based systems hardcode some PG* variables in the init script, and need to be overriden # in /etc/sysconfig/pgsql/postgresql. Create a blank file so we can manage it with augeas later. if ($::osfamily == 'RedHat') and ($::operatingsystemrelease !~ /^7/) and ($::operatingsystem != 'Fedora') { file { '/etc/sysconfig/pgsql/postgresql': ensure => present, replace => false, } # The init script from the packages of the postgresql.org repository # sources an alternate sysconfig file. # I. e. /etc/sysconfig/pgsql/postgresql-9.3 for PostgreSQL 9.3 # Link to the sysconfig file set by this puppet module file { "/etc/sysconfig/pgsql/postgresql-${version}": ensure => link, target => '/etc/sysconfig/pgsql/postgresql', require => File[ '/etc/sysconfig/pgsql/postgresql' ], } } if ($manage_pg_ident_conf == true) { concat { $pg_ident_conf_path: owner => $user, group => $group, - force => true, # do not crash if there is no pg_ident_rules mode => '0640', warn => true, + order => 'numeric', notify => Class['postgresql::server::reload'], } } if ($manage_recovery_conf == true) { concat { $recovery_conf_path: owner => $user, group => $group, - force => true, # do not crash if there is no recovery conf file mode => '0640', warn => true, + order => 'numeric', notify => Class['postgresql::server::reload'], } } if $::osfamily == 'RedHat' { if $::operatingsystemrelease =~ /^7/ or $::operatingsystem == 'Fedora' { # Template uses: # - $::operatingsystem # - $service_name # - $port # - $datadir file { 'systemd-override': ensure => present, path => "/etc/systemd/system/${service_name}.service", owner => root, group => root, content => template('postgresql/systemd-override.erb'), notify => [ Exec['restart-systemd'], Class['postgresql::server::service'] ], before => Class['postgresql::server::reload'], } exec { 'restart-systemd': command => 'systemctl daemon-reload', refreshonly => true, path => '/bin:/usr/bin:/usr/local/bin' } } } elsif $::osfamily == 'Gentoo' { # Template uses: # - $::operatingsystem # - $service_name # - $port # - $datadir file { 'systemd-override': ensure => present, path => "/etc/systemd/system/${service_name}.service", owner => root, group => root, content => template('postgresql/systemd-override.erb'), notify => [ Exec['restart-systemd'], Class['postgresql::server::service'] ], before => Class['postgresql::server::reload'], } exec { 'restart-systemd': command => 'systemctl daemon-reload', refreshonly => true, path => '/bin:/usr/bin:/usr/local/bin' } } } diff --git a/manifests/server/config_entry.pp b/manifests/server/config_entry.pp index 7c34737..3e37f00 100644 --- a/manifests/server/config_entry.pp +++ b/manifests/server/config_entry.pp @@ -1,126 +1,173 @@ # 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, } + # Those are the variables that are marked as "(change requires restart)" + # on postgresql.conf. Items are ordered as on postgresql.conf. + # + # XXX: This resource supports setting other variables without knowing + # their names. Do not add them here. + $requires_restart_until = { + 'data_directory' => undef, + 'hba_file' => undef, + 'ident_file' => undef, + 'external_pid_file' => undef, + 'listen_addresses' => undef, + 'port' => undef, + 'max_connections' => undef, + 'superuser_reserved_connections' => undef, + 'unix_socket_directory' => '9.3', # Turned into "unix_socket_directories" + 'unix_socket_directories' => undef, + 'unix_socket_group' => undef, + 'unix_socket_permissions' => undef, + 'bonjour' => undef, + 'bonjour_name' => undef, + 'ssl' => '10', + 'ssl_ciphers' => '10', + 'ssl_prefer_server_ciphers' => '10', # New on 9.4 + 'ssl_ecdh_curve' => '10', # New on 9.4 + 'ssl_cert_file' => '10', # New on 9.2 + 'ssl_key_file' => '10', # New on 9.2 + 'ssl_ca_file' => '10', # New on 9.2 + 'ssl_crl_file' => '10', # New on 9.2 + 'shared_buffers' => undef, + 'huge_pages' => undef, # New on 9.4 + 'max_prepared_transactions' => undef, + 'max_files_per_process' => undef, + 'shared_preload_libraries' => undef, + 'max_worker_processes' => undef, # New on 9.4 + 'old_snapshot_threshold' => undef, # New on 9.6 + 'wal_level' => undef, + 'wal_log_hints' => undef, # New on 9.4 + 'wal_buffers' => undef, + 'archive_mode' => undef, + 'max_wal_senders' => undef, + 'max_replication_slots' => undef, # New on 9.4 + 'track_commit_timestamp' => undef, # New on 9.5 + 'hot_standby' => undef, + 'logging_collector' => undef, + 'cluster_name' => undef, # New on 9.5 + 'silent_mode' => '9.2', # Removed + 'track_activity_query_size' => undef, + 'autovacuum_max_workers' => undef, + 'autovacuum_freeze_max_age' => undef, + 'autovacuum_multixact_freeze_max_age' => undef, # New on 9.5 + 'max_locks_per_transaction' => undef, + 'max_pred_locks_per_transaction' => undef, + } + Exec { logoutput => 'on_failure', } - case $name { - /data_directory|timezone|hba_file|ident_file|include|listen_addresses|port|max_connections|superuser_reserved_connections|unix_socket_director(y|ies)|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/: { - if $postgresql::server::service_restart_on_change { - Postgresql_conf { - notify => Class['postgresql::server::service'], - before => Class['postgresql::server::reload'], - } - } else { - Postgresql_conf { - before => [ - Class['postgresql::server::service'], - Class['postgresql::server::reload'], - ], - } - } + if ! ($name in $requires_restart_until and ( + ! $requires_restart_until[$name] or + versioncmp($postgresql::server::_version, $requires_restart_until[$name]) < 0 + )) { + Postgresql_conf { + notify => Class['postgresql::server::reload'], } - - default: { - Postgresql_conf { - notify => Class['postgresql::server::reload'], - } + } elsif $postgresql::server::service_restart_on_change { + Postgresql_conf { + notify => Class['postgresql::server::service'], + } + } else { + Postgresql_conf { + before => Class['postgresql::server::service'], } } # We have to handle ports and the data directory in a weird and # special way. On early Debian and Ubuntu and RHEL we have to ensure # we stop the service completely. On RHEL 7 we either have to create # a systemd override for the port or update the sysconfig file, but this # is managed for us in postgresql::server::config. if $::operatingsystem == 'Debian' or $::operatingsystem == 'Ubuntu' { if $name == 'port' and ( $::operatingsystemrelease =~ /^6/ or $::operatingsystemrelease =~ /^10\.04/ ) { exec { "postgresql_stop_${name}": command => "service ${::postgresql::server::service_name} stop", onlyif => "service ${::postgresql::server::service_name} status", unless => "grep 'port = ${value}' ${::postgresql::server::postgresql_conf_path}", path => '/usr/sbin:/sbin:/bin:/usr/bin:/usr/local/bin', before => Postgresql_conf[$name], } } elsif $name == 'data_directory' { exec { "postgresql_stop_${name}": command => "service ${::postgresql::server::service_name} stop", onlyif => "service ${::postgresql::server::service_name} status", unless => "grep \"data_directory = '${value}'\" ${::postgresql::server::postgresql_conf_path}", path => '/usr/sbin:/sbin:/bin:/usr/bin:/usr/local/bin', before => Postgresql_conf[$name], } } } if $::osfamily == 'RedHat' { if ! ($::operatingsystemrelease =~ /^7/ or $::operatingsystem == 'Fedora') { if $name == 'port' { # We need to force postgresql to stop before updating the port # because puppet becomes confused and is unable to manage the # service appropriately. exec { "postgresql_stop_${name}": command => "service ${::postgresql::server::service_name} stop", onlyif => "service ${::postgresql::server::service_name} status", unless => "grep 'PGPORT=${value}' /etc/sysconfig/pgsql/postgresql", path => '/sbin:/bin:/usr/bin:/usr/local/bin', require => File['/etc/sysconfig/pgsql/postgresql'], - } -> - augeas { 'override PGPORT in /etc/sysconfig/pgsql/postgresql': + } + -> augeas { 'override PGPORT in /etc/sysconfig/pgsql/postgresql': lens => 'Shellvars.lns', incl => '/etc/sysconfig/pgsql/*', context => '/files/etc/sysconfig/pgsql/postgresql', changes => "set PGPORT ${value}", require => File['/etc/sysconfig/pgsql/postgresql'], notify => Class['postgresql::server::service'], before => Class['postgresql::server::reload'], } } elsif $name == 'data_directory' { # We need to force postgresql to stop before updating the data directory # otherwise init script breaks exec { "postgresql_${name}": command => "service ${::postgresql::server::service_name} stop", onlyif => "service ${::postgresql::server::service_name} status", unless => "grep 'PGDATA=${value}' /etc/sysconfig/pgsql/postgresql", path => '/sbin:/bin:/usr/bin:/usr/local/bin', require => File['/etc/sysconfig/pgsql/postgresql'], - } -> - augeas { 'override PGDATA in /etc/sysconfig/pgsql/postgresql': + } + -> augeas { 'override PGDATA in /etc/sysconfig/pgsql/postgresql': lens => 'Shellvars.lns', incl => '/etc/sysconfig/pgsql/*', context => '/files/etc/sysconfig/pgsql/postgresql', changes => "set PGDATA ${value}", require => File['/etc/sysconfig/pgsql/postgresql'], notify => Class['postgresql::server::service'], before => 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}'.") } } } diff --git a/manifests/server/contrib.pp b/manifests/server/contrib.pp index 4c6cdc1..7e3426b 100644 --- a/manifests/server/contrib.pp +++ b/manifests/server/contrib.pp @@ -1,23 +1,22 @@ # 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' + String $package_name = $postgresql::params::contrib_package_name, + String[1] $package_ensure = 'present' ) inherits postgresql::params { - validate_string($package_name) if $::osfamily == 'Gentoo' { fail('osfamily Gentoo does not have a separate "contrib" package, postgresql::server::contrib is not supported.') } package { 'postgresql-contrib': ensure => $package_ensure, name => $package_name, tag => 'postgresql', } - anchor { 'postgresql::server::contrib::start': }-> - Class['postgresql::server::install']-> - Package['postgresql-contrib']-> - Class['postgresql::server::service']-> + anchor { 'postgresql::server::contrib::start': } + -> Class['postgresql::server::install'] + -> Package['postgresql-contrib'] + -> Class['postgresql::server::service'] anchor { 'postgresql::server::contrib::end': } } diff --git a/manifests/server/database.pp b/manifests/server/database.pp index b03729c..057bc46 100644 --- a/manifests/server/database.pp +++ b/manifests/server/database.pp @@ -1,128 +1,128 @@ # Define for creating a database. See README.md for more details. define postgresql::server::database( $comment = undef, $dbname = $title, $owner = undef, $tablespace = undef, $template = 'template0', $encoding = $postgresql::server::encoding, $locale = $postgresql::server::locale, $istemplate = false, $connect_settings = $postgresql::server::default_connect_settings, ) { $createdb_path = $postgresql::server::createdb_path $user = $postgresql::server::user $group = $postgresql::server::group $psql_path = $postgresql::server::psql_path $default_db = $postgresql::server::default_database # If possible use the version of the remote database, otherwise # fallback to our local DB version if $connect_settings != undef and has_key( $connect_settings, 'DBVERSION') { $version = $connect_settings['DBVERSION'] } else { $version = $postgresql::server::_version } # If the connection settings do not contain a port, then use the local server port if $connect_settings != undef and has_key( $connect_settings, 'PGPORT') { $port = undef } else { $port = $postgresql::server::port } # Set the defaults for the postgresql_psql resource Postgresql_psql { db => $default_db, psql_user => $user, psql_group => $group, psql_path => $psql_path, port => $port, connect_settings => $connect_settings, } # 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 => "LC_COLLATE = '${locale}' LC_CTYPE = '${locale}'", } $public_revoke_privilege = 'CONNECT' } else { $locale_option = '' $public_revoke_privilege = 'ALL' } $template_option = $template ? { undef => '', default => "TEMPLATE = \"${template}\"", } $encoding_option = $encoding ? { undef => '', default => "ENCODING = '${encoding}'", } $tablespace_option = $tablespace ? { undef => '', default => "TABLESPACE = \"${tablespace}\"", } if $createdb_path != undef { warning('Passing "createdb_path" to postgresql::database is deprecated, it can be removed safely for the same behaviour') } postgresql_psql { "CREATE DATABASE \"${dbname}\"": command => "CREATE DATABASE \"${dbname}\" WITH ${template_option} ${encoding_option} ${locale_option} ${tablespace_option}", unless => "SELECT 1 FROM pg_database WHERE datname = '${dbname}'", require => Class['postgresql::server::service'] - }~> + } # 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": + ~> postgresql_psql { "REVOKE ${public_revoke_privilege} ON DATABASE \"${dbname}\" FROM public": refreshonly => true, } - Postgresql_psql["CREATE DATABASE \"${dbname}\""]-> - postgresql_psql { "UPDATE pg_database SET datistemplate = ${istemplate} WHERE datname = '${dbname}'": + Postgresql_psql["CREATE DATABASE \"${dbname}\""] + -> postgresql_psql { "UPDATE pg_database SET datistemplate = ${istemplate} WHERE datname = '${dbname}'": unless => "SELECT 1 FROM pg_database WHERE datname = '${dbname}' AND datistemplate = ${istemplate}", } if $comment { # The shobj_description function was only introduced with 8.2 $comment_information_function = $version ? { '8.1' => 'obj_description', default => 'shobj_description', } - Postgresql_psql["CREATE DATABASE \"${dbname}\""]-> - postgresql_psql { "COMMENT ON DATABASE \"${dbname}\" IS '${comment}'": + Postgresql_psql["CREATE DATABASE \"${dbname}\""] + -> postgresql_psql { "COMMENT ON DATABASE \"${dbname}\" IS '${comment}'": unless => "SELECT 1 FROM pg_catalog.pg_database d WHERE datname = '${dbname}' AND pg_catalog.${comment_information_function}(d.oid, 'pg_database') = '${comment}'", db => $dbname, } } if $owner { postgresql_psql { "ALTER DATABASE \"${dbname}\" OWNER TO \"${owner}\"": unless => "SELECT 1 FROM pg_database JOIN pg_roles rol ON datdba = rol.oid WHERE datname = '${dbname}' AND rolname = '${owner}'", require => Postgresql_psql["CREATE DATABASE \"${dbname}\""], } if defined(Postgresql::Server::Role[$owner]) { Postgresql::Server::Role[$owner]->Postgresql_psql["ALTER DATABASE \"${dbname}\" OWNER TO \"${owner}\""] } } if $tablespace { postgresql_psql { "ALTER DATABASE \"${dbname}\" SET ${tablespace_option}": unless => "SELECT 1 FROM pg_database JOIN pg_tablespace spc ON dattablespace = spc.oid WHERE datname = '${dbname}' AND spcname = '${tablespace}'", require => Postgresql_psql["CREATE DATABASE \"${dbname}\""], } if defined(Postgresql::Server::Tablespace[$tablespace]) { # The tablespace must be there, before we create the database. Postgresql::Server::Tablespace[$tablespace]->Postgresql_psql["CREATE DATABASE \"${dbname}\""] } } } diff --git a/manifests/server/db.pp b/manifests/server/db.pp index b4c1232..9b20928 100644 --- a/manifests/server/db.pp +++ b/manifests/server/db.pp @@ -1,47 +1,47 @@ # Define for conveniently creating a role, database and assigning the correct # permissions. See README.md for more details. define postgresql::server::db ( $user, $password, $comment = undef, $dbname = $title, $encoding = $postgresql::server::encoding, $locale = $postgresql::server::locale, $grant = 'ALL', $tablespace = undef, $template = 'template0', $istemplate = false, $owner = undef ) { if ! defined(Postgresql::Server::Database[$dbname]) { postgresql::server::database { $dbname: comment => $comment, 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, before => Postgresql::Server::Database[$dbname], } } if ! defined(Postgresql::Server::Database_grant["GRANT ${user} - ${grant} - ${dbname}"]) { postgresql::server::database_grant { "GRANT ${user} - ${grant} - ${dbname}": privilege => $grant, db => $dbname, role => $user, - } -> Postgresql::Validate_db_connection<| database_name == $dbname |> + } -> Postgresql_conn_validator<| db_name == $dbname |> } if($tablespace != undef and defined(Postgresql::Server::Tablespace[$tablespace])) { Postgresql::Server::Tablespace[$tablespace]->Postgresql::Server::Database[$name] } } diff --git a/manifests/server/extension.pp b/manifests/server/extension.pp index 1c9b684..6d28783 100644 --- a/manifests/server/extension.pp +++ b/manifests/server/extension.pp @@ -1,61 +1,61 @@ # Activate an extension on a postgresql database define postgresql::server::extension ( $database, - $extension = $name, - $ensure = 'present', - $package_name = undef, - $package_ensure = undef, + $extension = $name, + String[1] $ensure = 'present', + $package_name = undef, + $package_ensure = undef, $connect_settings = $postgresql::server::default_connect_settings, ) { - $user = $postgresql::server::user - $group = $postgresql::server::group - $psql_path = $postgresql::server::psql_path + $user = $postgresql::server::user + $group = $postgresql::server::group + $psql_path = $postgresql::server::psql_path case $ensure { 'present': { $command = "CREATE EXTENSION \"${extension}\"" $unless_comp = '=' $package_require = [] $package_before = Postgresql_psql["Add ${extension} extension to ${database}"] } 'absent': { $command = "DROP EXTENSION \"${extension}\"" $unless_comp = '!=' $package_require = Postgresql_psql["Add ${extension} extension to ${database}"] $package_before = [] } default: { fail("Unknown value for ensure '${ensure}'.") } } postgresql_psql {"Add ${extension} extension to ${database}": psql_user => $user, psql_group => $group, psql_path => $psql_path, connect_settings => $connect_settings, db => $database, command => $command, unless => "SELECT t.count FROM (SELECT count(extname) FROM pg_extension WHERE extname = '${extension}') as t WHERE t.count ${unless_comp} 1", require => Postgresql::Server::Database[$database], } if $package_name { $_package_ensure = $package_ensure ? { undef => $ensure, default => $package_ensure, } ensure_packages($package_name, { ensure => $_package_ensure, tag => 'postgresql', require => $package_require, before => $package_before, }) } } diff --git a/manifests/server/grant.pp b/manifests/server/grant.pp index 2836f17..f030019 100644 --- a/manifests/server/grant.pp +++ b/manifests/server/grant.pp @@ -1,294 +1,294 @@ # 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 = undef, - $psql_db = $postgresql::server::default_database, - $psql_user = $postgresql::server::user, - $port = $postgresql::server::port, - $onlyif_exists = false, - $connect_settings = $postgresql::server::default_connect_settings, + String $role, + String $db, + Optional[String] $privilege = undef, + String $object_type = 'database', + Optional[String[1]] $object_name = undef, + String $psql_db = $postgresql::server::default_database, + String $psql_user = $postgresql::server::user, + Integer $port = $postgresql::server::port, + Boolean $onlyif_exists = false, + Hash $connect_settings = $postgresql::server::default_connect_settings, ) { + $group = $postgresql::server::group $psql_path = $postgresql::server::psql_path if ! $object_name { $_object_name = $db } else { $_object_name = $object_name } - validate_bool($onlyif_exists) # # Port, order of precedence: $port parameter, $connect_settings[PGPORT], $postgresql::server::port # if $port != undef { $port_override = $port } elsif $connect_settings != undef and has_key( $connect_settings, 'PGPORT') { $port_override = undef } else { $port_override = $postgresql::server::port } ## Munge the input values $_object_type = upcase($object_type) $_privilege = upcase($privilege) ## Validate that the object type is known validate_re($_object_type,[ #'^COLUMN$', '^DATABASE$', #'^FOREIGN SERVER$', #'^FOREIGN DATA WRAPPER$', #'^FUNCTION$', #'^PROCEDURAL LANGUAGE$', '^SCHEMA$', '^SEQUENCE$', '^ALL SEQUENCES IN SCHEMA$', '^TABLE$', '^ALL TABLES IN SCHEMA$', '^LANGUAGE$', #'^TABLESPACE$', #'^VIEW$', ] ) # You can use ALL TABLES IN SCHEMA by passing schema_name to object_name # You can use ALL SEQUENCES IN SCHEMA by passing schema_name to object_name ## 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', 'ALL PRIVILEGES' => 'CREATE', default => $_privilege, } validate_re($unless_privilege, [ '^$', '^CREATE$','^CONNECT$','^TEMPORARY$','^TEMP$', '^ALL$','^ALL PRIVILEGES$' ]) $unless_function = 'has_database_privilege' $on_db = $psql_db $onlyif_function = undef } 'SCHEMA': { $unless_privilege = $_privilege ? { 'ALL' => 'CREATE', 'ALL PRIVILEGES' => 'CREATE', default => $_privilege, } validate_re($_privilege, [ '^$', '^CREATE$', '^USAGE$', '^ALL$', '^ALL PRIVILEGES$' ]) $unless_function = 'has_schema_privilege' $on_db = $db $onlyif_function = undef } 'SEQUENCE': { $unless_privilege = $_privilege ? { 'ALL' => 'USAGE', default => $_privilege, } validate_re($unless_privilege, [ '^$', '^USAGE$', '^SELECT$', '^UPDATE$', '^ALL$', '^ALL PRIVILEGES$' ]) $unless_function = 'has_sequence_privilege' $on_db = $db $onlyif_function = undef } 'ALL SEQUENCES IN SCHEMA': { validate_re($_privilege, [ '^$', '^USAGE$', '^SELECT$', '^UPDATE$', '^ALL$', '^ALL PRIVILEGES$' ]) $unless_function = 'custom' $on_db = $db $onlyif_function = undef $schema = $object_name $custom_privilege = $_privilege ? { 'ALL' => 'USAGE', 'ALL PRIVILEGES' => 'USAGE', default => $_privilege, } # This checks if there is a difference between the sequences in the # specified schema and the sequences for which the role has the specified # privilege. It uses the EXCEPT clause which computes the set of rows # that are in the result of the first SELECT statement but not in the # result of the second one. It then counts the number of rows from this # operation. If this number is zero then the role has the specified # privilege for all sequences in the schema and the whole query returns a # single row, which satisfies the `unless` parameter of Postgresql_psql. # If this number is not zero then there is at least one sequence for which # the role does not have the specified privilege, making it necessary to # execute the GRANT statement. $custom_unless = "SELECT 1 FROM ( SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema='${schema}' EXCEPT DISTINCT SELECT object_name as sequence_name FROM ( SELECT object_schema, object_name, grantee, CASE privs_split WHEN 'r' THEN 'SELECT' WHEN 'w' THEN 'UPDATE' WHEN 'U' THEN 'USAGE' END AS privilege_type FROM ( SELECT DISTINCT object_schema, object_name, (regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[1] AS grantee, regexp_split_to_table((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[2],E'\\s*') AS privs_split FROM ( SELECT n.nspname as object_schema, c.relname as object_name, regexp_split_to_table(array_to_string(c.relacl,','),',') AS privs FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind = 'S' AND n.nspname NOT IN ( 'pg_catalog', 'information_schema' ) ) P1 ) P2 ) P3 WHERE grantee='${role}' AND object_schema='${schema}' AND privilege_type='${custom_privilege}' ) P HAVING count(P.sequence_name) = 0" } 'TABLE': { $unless_privilege = $_privilege ? { 'ALL' => 'INSERT', default => $_privilege, } validate_re($unless_privilege,[ '^$', '^SELECT$','^INSERT$','^UPDATE$','^DELETE$', '^TRUNCATE$','^REFERENCES$','^TRIGGER$','^ALL$','^ALL PRIVILEGES$' ]) $unless_function = 'has_table_privilege' $on_db = $db $onlyif_function = $onlyif_exists ? { true => 'table_exists', default => undef, } } 'ALL TABLES IN SCHEMA': { validate_re($_privilege, [ '^$', '^SELECT$','^INSERT$','^UPDATE$','^DELETE$', '^TRUNCATE$','^REFERENCES$','^TRIGGER$','^ALL$','^ALL PRIVILEGES$' ]) $unless_function = 'custom' $on_db = $db $onlyif_function = undef $schema = $object_name # Again there seems to be no easy way in plain SQL to check if ALL # PRIVILEGES are granted on a table. By convention we use INSERT # here to represent ALL PRIVILEGES (truly terrible). $custom_privilege = $_privilege ? { 'ALL' => 'INSERT', 'ALL PRIVILEGES' => 'INSERT', default => $_privilege, } # This checks if there is a difference between the tables in the # specified schema and the tables for which the role has the specified # privilege. It uses the EXCEPT clause which computes the set of rows # that are in the result of the first SELECT statement but not in the # result of the second one. It then counts the number of rows from this # operation. If this number is zero then the role has the specified # privilege for all tables in the schema and the whole query returns a # single row, which satisfies the `unless` parameter of Postgresql_psql. # If this number is not zero then there is at least one table for which # the role does not have the specified privilege, making it necessary to # execute the GRANT statement. $custom_unless = "SELECT 1 FROM ( SELECT table_name FROM information_schema.tables WHERE table_schema='${schema}' EXCEPT DISTINCT SELECT table_name FROM information_schema.role_table_grants WHERE grantee='${role}' AND table_schema='${schema}' AND privilege_type='${custom_privilege}' ) P HAVING count(P.table_name) = 0" } 'LANGUAGE': { $unless_privilege = $_privilege ? { 'ALL' => 'USAGE', 'ALL PRIVILEGES' => 'USAGE', default => $_privilege, } validate_re($unless_privilege, [ '^$','^CREATE$','^USAGE$','^ALL$','^ALL PRIVILEGES$' ]) $unless_function = 'has_language_privilege' $on_db = $db $onlyif_function = $onlyif_exists ? { true => 'language_exists', default => undef, } } default: { fail("Missing privilege validation for object type ${_object_type}") } } # This is used to give grant to "schemaname"."tablename" # If you need such grant, use: # postgresql::grant { 'table:foo': # role => 'joe', # ... # object_type => 'TABLE', # object_name => [$schema, $table], # } if is_array($_object_name) { $_togrant_object = join($_object_name, '"."') # Never put double quotes into has_*_privilege function $_granted_object = join($_object_name, '.') } else { $_granted_object = $_object_name $_togrant_object = $_object_name } $_unless = $unless_function ? { false => undef, 'custom' => $custom_unless, default => "SELECT 1 WHERE ${unless_function}('${role}', '${_granted_object}', '${unless_privilege}')", } $_onlyif = $onlyif_function ? { 'table_exists' => "SELECT true FROM pg_tables WHERE tablename = '${_togrant_object}'", 'language_exists' => "SELECT true from pg_language WHERE lanname = '${_togrant_object}'", default => undef, } $grant_cmd = "GRANT ${_privilege} ON ${_object_type} \"${_togrant_object}\" TO \"${role}\"" postgresql_psql { "grant:${name}": command => $grant_cmd, db => $on_db, port => $port_override, connect_settings => $connect_settings, psql_user => $psql_user, psql_group => $group, psql_path => $psql_path, unless => $_unless, onlyif => $_onlyif, require => Class['postgresql::server'] } if($role != undef and defined(Postgresql::Server::Role[$role])) { Postgresql::Server::Role[$role]->Postgresql_psql["grant:${name}"] } if($db != undef and defined(Postgresql::Server::Database[$db])) { Postgresql::Server::Database[$db]->Postgresql_psql["grant:${name}"] } } diff --git a/manifests/server/grant_role.pp b/manifests/server/grant_role.pp index 04729d4..601fd69 100644 --- a/manifests/server/grant_role.pp +++ b/manifests/server/grant_role.pp @@ -1,51 +1,43 @@ # Define for granting membership to a role. See README.md for more information define postgresql::server::grant_role ( - $group, - $role = $name, - $ensure = 'present', - $psql_db = $postgresql::server::default_database, - $psql_user = $postgresql::server::user, - $port = $postgresql::server::port, - $connect_settings = $postgresql::server::default_connect_settings, + String[1] $group, + String[1] $role = $name, + Enum['present', 'absent'] $ensure = 'present', + $psql_db = $postgresql::server::default_database, + $psql_user = $postgresql::server::user, + $port = $postgresql::server::port, + $connect_settings = $postgresql::server::default_connect_settings, ) { - validate_string($group) - validate_string($role) - if empty($group) { - fail('$group must be set') - } - if empty($role) { - fail('$role must be set') - } case $ensure { 'present': { $command = "GRANT \"${group}\" TO \"${role}\"" $unless_comp = '=' } 'absent': { $command = "REVOKE \"${group}\" FROM \"${role}\"" $unless_comp = '!=' } default: { fail("Unknown value for ensure '${ensure}'.") } } postgresql_psql { "grant_role:${name}": command => $command, unless => "SELECT 1 WHERE EXISTS (SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = '${group}' AND r_role.rolname = '${role}') ${unless_comp} true", db => $psql_db, psql_user => $psql_user, port => $port, connect_settings => $connect_settings, } if ! $connect_settings or empty($connect_settings) { Class['postgresql::server']->Postgresql_psql["grant_role:${name}"] } if defined(Postgresql::Server::Role[$role]) { Postgresql::Server::Role[$role]->Postgresql_psql["grant_role:${name}"] } if defined(Postgresql::Server::Role[$group]) { Postgresql::Server::Role[$group]->Postgresql_psql["grant_role:${name}"] } } diff --git a/manifests/server/pg_hba_rule.pp b/manifests/server/pg_hba_rule.pp index 0eecdc5..97a7aaa 100644 --- a/manifests/server/pg_hba_rule.pp +++ b/manifests/server/pg_hba_rule.pp @@ -1,64 +1,60 @@ # 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', + Enum['local', 'host', 'hostssl', 'hostnossl'] $type, + String $database, + String $user, + String $auth_method, + Optional[String] $address = undef, + String $description = 'none', + Optional[String] $auth_option = undef, + Integer $order = 150, # Needed for testing primarily, support for multiple files is not really # working. - $target = $postgresql::server::pg_hba_conf_path, - $postgresql_version = $postgresql::server::_version + Stdlib::Absolutepath $target = $postgresql::server::pg_hba_conf_path, + String $postgresql_version = $postgresql::server::_version ) { #Allow users to manage pg_hba.conf even if they are not managing the whole PostgreSQL instance if !defined( 'postgresql::server' ) { $manage_pg_hba_conf = true } else { $manage_pg_hba_conf = $postgresql::server::manage_pg_hba_conf } if $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, hostnossl") if($type =~ /^host/ and $address == undef) { fail('You must specify an address property when type is host based') } $allowed_auth_methods = $postgresql_version ? { '9.6' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam', 'bsd'], '9.5' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.4' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.3' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.2' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.1' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], '9.0' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'radius', 'cert', 'pam'], '8.4' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'cert', 'pam'], '8.3' => ['trust', 'reject', 'md5', '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', 'bsd'] } - $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, ', ')],'')) + assert_type(Enum[$allowed_auth_methods], $auth_method) # Create a rule fragment $fragname = "pg_hba_rule_${name}" concat::fragment { $fragname: target => $target, content => template('postgresql/pg_hba_rule.conf'), order => $order, } } } diff --git a/manifests/server/plperl.pp b/manifests/server/plperl.pp index 6ad5cf9..53145da 100644 --- a/manifests/server/plperl.pp +++ b/manifests/server/plperl.pp @@ -1,19 +1,19 @@ # 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', } - anchor { 'postgresql::server::plperl::start': }-> - Class['postgresql::server::install']-> - Package['postgresql-plperl']-> - Class['postgresql::server::service']-> + anchor { 'postgresql::server::plperl::start': } + -> Class['postgresql::server::install'] + -> Package['postgresql-plperl'] + -> Class['postgresql::server::service'] anchor { 'postgresql::server::plperl::end': } } diff --git a/manifests/server/plpython.pp b/manifests/server/plpython.pp index 962dbad..892a95c 100644 --- a/manifests/server/plpython.pp +++ b/manifests/server/plpython.pp @@ -1,19 +1,19 @@ # This class installs the PL/Python procedural language for postgresql. See # README.md for more details. class postgresql::server::plpython( $package_ensure = 'present', $package_name = $postgresql::server::plpython_package_name, ) { package { 'postgresql-plpython': ensure => $package_ensure, name => $package_name, tag => 'postgresql', } - anchor { 'postgresql::server::plpython::start': }-> - Class['postgresql::server::install']-> - Package['postgresql-plpython']-> - Class['postgresql::server::service']-> - anchor { 'postgresql::server::plpython::end': } + anchor { 'postgresql::server::plpython::start': } + -> Class['postgresql::server::install'] + -> Package['postgresql-plpython'] + -> Class['postgresql::server::service'] + -> anchor { 'postgresql::server::plpython::end': } } diff --git a/manifests/server/postgis.pp b/manifests/server/postgis.pp index ac4c641..a4e4321 100644 --- a/manifests/server/postgis.pp +++ b/manifests/server/postgis.pp @@ -1,24 +1,23 @@ # Install the postgis postgresql packaging. See README.md for more details. class postgresql::server::postgis ( - $package_name = $postgresql::params::postgis_package_name, - $package_ensure = 'present' + String $package_name = $postgresql::params::postgis_package_name, + String[1] $package_ensure = 'present' ) inherits postgresql::params { - validate_string($package_name) package { 'postgresql-postgis': ensure => $package_ensure, name => $package_name, tag => 'postgresql', } - anchor { 'postgresql::server::postgis::start': }-> - Class['postgresql::server::install']-> - Package['postgresql-postgis']-> - Class['postgresql::server::service']-> - anchor { 'postgresql::server::postgis::end': } + anchor { 'postgresql::server::postgis::start': } + -> Class['postgresql::server::install'] + -> Package['postgresql-postgis'] + -> Class['postgresql::server::service'] + -> anchor { 'postgresql::server::postgis::end': } if $postgresql::globals::manage_package_repo { - Class['postgresql::repo'] -> - Package['postgresql-postgis'] + Class['postgresql::repo'] + -> Package['postgresql-postgis'] } } diff --git a/manifests/server/role.pp b/manifests/server/role.pp index c4a8f10..a0bc7ef 100644 --- a/manifests/server/role.pp +++ b/manifests/server/role.pp @@ -1,124 +1,125 @@ # Define for creating a database role. See README.md for more information define postgresql::server::role( + $update_password = true, $password_hash = false, $createdb = false, $createrole = false, $db = $postgresql::server::default_database, $port = undef, $login = true, $inherit = true, $superuser = false, $replication = false, $connection_limit = '-1', $username = $title, $connect_settings = $postgresql::server::default_connect_settings, ) { $psql_user = $postgresql::server::user $psql_group = $postgresql::server::group $psql_path = $postgresql::server::psql_path $module_workdir = $postgresql::server::module_workdir # # Port, order of precedence: $port parameter, $connect_settings[PGPORT], $postgresql::server::port # if $port != undef { $port_override = $port } elsif $connect_settings != undef and has_key( $connect_settings, 'PGPORT') { $port_override = undef } else { $port_override = $postgresql::server::port } # If possible use the version of the remote database, otherwise # fallback to our local DB version if $connect_settings != undef and has_key( $connect_settings, 'DBVERSION') { $version = $connect_settings['DBVERSION'] } else { $version = $postgresql::server::_version } $login_sql = $login ? { true => 'LOGIN', default => 'NOLOGIN' } $inherit_sql = $inherit ? { true => 'INHERIT', default => 'NOINHERIT' } $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) { $environment = "NEWPGPASSWD=${password_hash}" $password_sql = "ENCRYPTED PASSWORD '\$NEWPGPASSWD'" } else { $password_sql = '' $environment = [] } Postgresql_psql { db => $db, port => $port_override, psql_user => $psql_user, psql_group => $psql_group, psql_path => $psql_path, connect_settings => $connect_settings, cwd => $module_workdir, require => [ Postgresql_psql["CREATE ROLE ${username} ENCRYPTED PASSWORD ****"], Class['postgresql::server'], ], } postgresql_psql { "CREATE ROLE ${username} ENCRYPTED PASSWORD ****": command => "CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}", unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}'", environment => $environment, require => Class['Postgresql::Server'], } postgresql_psql {"ALTER ROLE \"${username}\" ${superuser_sql}": unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolsuper = ${superuser}", } postgresql_psql {"ALTER ROLE \"${username}\" ${createdb_sql}": unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolcreatedb = ${createdb}", } postgresql_psql {"ALTER ROLE \"${username}\" ${createrole_sql}": unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolcreaterole = ${createrole}", } postgresql_psql {"ALTER ROLE \"${username}\" ${login_sql}": unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolcanlogin = ${login}", } postgresql_psql {"ALTER ROLE \"${username}\" ${inherit_sql}": unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolinherit = ${inherit}", } if(versioncmp($version, '9.1') >= 0) { if $replication_sql == '' { postgresql_psql {"ALTER ROLE \"${username}\" NOREPLICATION": unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolreplication = ${replication}", } } else { postgresql_psql {"ALTER ROLE \"${username}\" ${replication_sql}": unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolreplication = ${replication}", } } } postgresql_psql {"ALTER ROLE \"${username}\" CONNECTION LIMIT ${connection_limit}": unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}' AND rolconnlimit = ${connection_limit}", } - if $password_hash { + if $password_hash and $update_password { 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} ENCRYPTED PASSWORD ****": command => "ALTER ROLE \"${username}\" ${password_sql}", unless => "SELECT 1 FROM pg_shadow WHERE usename = '${username}' AND passwd = '${pwd_hash_sql}'", environment => $environment, } } } diff --git a/manifests/server/service.pp b/manifests/server/service.pp index de06818..2a4f500 100644 --- a/manifests/server/service.pp +++ b/manifests/server/service.pp @@ -1,46 +1,48 @@ # PRIVATE CLASS: do not call directly class postgresql::server::service { $service_ensure = $postgresql::server::service_ensure $service_enable = $postgresql::server::service_enable $service_manage = $postgresql::server::service_manage $service_name = $postgresql::server::service_name $service_provider = $postgresql::server::service_provider $service_status = $postgresql::server::service_status $user = $postgresql::server::user $port = $postgresql::server::port $default_database = $postgresql::server::default_database + $psql_path = $postgresql::params::psql_path anchor { 'postgresql::server::service::begin': } if $service_manage { service { 'postgresqld': ensure => $service_ensure, enable => $service_enable, name => $service_name, provider => $service_provider, hasstatus => true, status => $service_status, } if $service_ensure == 'running' { # 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, - database_port => $port, - sleep => 1, - tries => 60, - create_db_first => false, - require => Service['postgresqld'], - before => Anchor['postgresql::server::service::end'] + postgresql_conn_validator{ 'validate_service_is_running': + run_as => $user, + db_name => $default_database, + port => $port, + sleep => 1, + tries => 60, + psql_path => $psql_path, + require => Service['postgresqld'], + before => Anchor['postgresql::server::service::end'] } + Postgresql::Server::Database <| title == $default_database |> -> Postgresql_conn_validator['validate_service_is_running'] } } anchor { 'postgresql::server::service::end': } } diff --git a/manifests/validate_db_connection.pp b/manifests/validate_db_connection.pp index 9c17419..10e5ecc 100644 --- a/manifests/validate_db_connection.pp +++ b/manifests/validate_db_connection.pp @@ -1,92 +1,94 @@ # 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, $connect_settings = undef, $run_as = undef, $sleep = 2, $tries = 10, $create_db_first = true ) { include postgresql::client include postgresql::params + warning('postgresql::validate_db_connection is deprecated, please use postgresql_conn_validator.') + $psql_path = $postgresql::params::psql_path $module_workdir = $postgresql::params::module_workdir $validcon_script_path = $postgresql::client::validcon_script_path $cmd_init = "${psql_path} --tuples-only --quiet " $cmd_host = $database_host ? { undef => '', default => "-h ${database_host} ", } $cmd_user = $database_username ? { undef => '', default => "-U ${database_username} ", } $cmd_port = $database_port ? { undef => '', default => "-p ${database_port} ", } $cmd_dbname = $database_name ? { undef => "--dbname ${postgresql::params::default_database} ", default => "--dbname ${database_name} ", } $pass_env = $database_password ? { undef => undef, default => "PGPASSWORD=${database_password}", } $cmd = join([$cmd_init, $cmd_host, $cmd_user, $cmd_port, $cmd_dbname], ' ') $validate_cmd = "${validcon_script_path} ${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) # Combine $database_password and $connect_settings into an array of environment # variables, ensure $database_password is last, allowing it to override a password # from the $connect_settings hash if $connect_settings != undef { if $pass_env != undef { $env = concat(join_keys_to_values( $connect_settings, '='), $pass_env) } else { $env = join_keys_to_values( $connect_settings, '=') } } else { $env = $pass_env } $exec_name = "validate postgres connection for ${database_username}@${database_host}:${database_port}/${database_name}" exec { $exec_name: command => "echo 'Unable to connect to defined database using: ${cmd}' && false", unless => $validate_cmd, cwd => $module_workdir, environment => $env, logoutput => 'on_failure', user => $run_as, path => '/bin:/usr/bin:/usr/local/bin', timeout => $timeout, require => Class['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] } } diff --git a/metadata.json b/metadata.json index a3e2c69..e2f5cdc 100644 --- a/metadata.json +++ b/metadata.json @@ -1,73 +1,73 @@ { "name": "puppetlabs-postgresql", - "version": "4.9.0", + "version": "5.0.0", "author": "Inkling/Puppet Labs", "summary": "Offers support for basic management of PostgreSQL databases.", "license": "Apache-2.0", "source": "git://github.com/puppetlabs/puppetlabs-postgresql.git", "project_page": "https://github.com/puppetlabs/puppetlabs-postgresql", "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":"4.x"}, - {"name":"puppetlabs/apt","version_requirement":">=1.8.0 <3.0.0"}, - {"name":"puppetlabs/concat","version_requirement":">= 1.1.0 <3.0.0"} + {"name":"puppetlabs/stdlib","version_requirement":">= 4.13.1 < 5.0.0"}, + {"name":"puppetlabs/apt","version_requirement":">= 2.0.0 < 5.0.0"}, + {"name":"puppetlabs/concat","version_requirement":">= 1.1.0 < 5.0.0"} ], "data_provider": null, "operatingsystem_support": [ { "operatingsystem": "RedHat", "operatingsystemrelease": [ "5", "6", "7" ] }, { "operatingsystem": "CentOS", "operatingsystemrelease": [ "5", "6", "7" ] }, { "operatingsystem": "OracleLinux", "operatingsystemrelease": [ "5", "6", "7" ] }, { "operatingsystem": "Scientific", "operatingsystemrelease": [ "5", "6", "7" ] }, { "operatingsystem": "Debian", "operatingsystemrelease": [ "6", "7", "8" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ "10.04", "12.04", "14.04", "16.04" ] } ], "requirements": [ { "name": "puppet", - "version_requirement": ">= 3.0.0 < 5.0.0" + "version_requirement": ">= 4.7.0 < 5.0.0" } ] } diff --git a/spec/acceptance/db_spec.rb b/spec/acceptance/db_spec.rb index 449c4b0..0285c3f 100644 --- a/spec/acceptance/db_spec.rb +++ b/spec/acceptance/db_spec.rb @@ -1,54 +1,54 @@ require 'spec_helper_acceptance' describe 'postgresql::server::db', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do it 'creates a database' do begin tmpdir = default.tmpdir('postgresql') pp = <<-EOS class { 'postgresql::server': postgres_password => 'space password', } postgresql::server::tablespace { 'postgresql-test-db': location => '#{tmpdir}', } -> postgresql::server::db { 'postgresql-test-db': comment => 'testcomment', user => 'test-user', password => 'test1', tablespace => 'postgresql-test-db', } EOS apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_changes => true) # Verify that the postgres password works - shell("echo 'localhost:*:*:postgres:space password' > /root/.pgpass") + shell("echo 'localhost:*:*:postgres:\'space password\'' > /root/.pgpass") shell("chmod 600 /root/.pgpass") shell("psql -U postgres -h localhost --command='\\l'") psql('--command="select datname from pg_database" "postgresql-test-db"') do |r| expect(r.stdout).to match(/postgresql-test-db/) expect(r.stderr).to eq('') end psql('--command="SELECT 1 FROM pg_roles WHERE rolname=\'test-user\'"') do |r| expect(r.stdout).to match(/\(1 row\)/) end result = shell('psql --version') version = result.stdout.match(%r{\s(\d\.\d)})[1] if version > "8.1" comment_information_function = "shobj_description" else comment_information_function = "obj_description" end psql("--dbname postgresql-test-db --command=\"SELECT pg_catalog.#{comment_information_function}(d.oid, 'pg_database') FROM pg_catalog.pg_database d WHERE datname = 'postgresql-test-db' AND pg_catalog.#{comment_information_function}(d.oid, 'pg_database') = 'testcomment'\"") do |r| expect(r.stdout).to match(/\(1 row\)/) end ensure psql('--command=\'drop database "postgresql-test-db" postgres\'') psql('--command="DROP USER test"') end end end diff --git a/spec/acceptance/postgresql_conn_validator_spec.rb b/spec/acceptance/postgresql_conn_validator_spec.rb new file mode 100644 index 0000000..20d8422 --- /dev/null +++ b/spec/acceptance/postgresql_conn_validator_spec.rb @@ -0,0 +1,76 @@ +require 'spec_helper_acceptance' + +describe 'postgresql_conn_validator', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do + + let(:install_pp) { <<-EOS + class { 'postgresql::server': + postgres_password => 'space password', + }-> + postgresql::server::role { 'testuser': + password_hash => postgresql_password('testuser','test1'), + }-> + postgresql::server::database { 'testdb': + owner => 'testuser', + require => Postgresql::Server::Role['testuser'] + }-> + postgresql::server::database_grant { 'allow connect for testuser': + privilege => 'ALL', + db => 'testdb', + role => 'testuser', + } + + EOS + + } + + context 'local connection' do + it 'validates successfully with defaults' do + pp = <<-EOS + #{install_pp}-> + postgresql_conn_validator { 'validate this': + db_name => 'testdb', + db_username => 'testuser', + db_password => 'test1', + host => 'localhost', + psql_path => '/usr/bin/psql', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + it 'works with connect settings hash' do + pp = <<-EOS + #{install_pp}-> + postgresql_conn_validator { 'validate this': + connect_settings => { + 'PGDATABASE' => 'testdb', + 'PGPORT' => '5432', + 'PGUSER' => 'testuser', + 'PGPASSWORD' => 'test1', + 'PGHOST' => 'localhost' + }, + psql_path => '/usr/bin/psql' + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + end + + it 'fails gracefully' do + pp = <<-EOS + #{install_pp}-> + postgresql_conn_validator { 'validate this': + psql_path => '/usr/bin/psql', + tries => 3 + } + EOS + + result = apply_manifest(pp) + expect(result.stderr).to match /Unable to connect to PostgreSQL server/ + end + end +end diff --git a/spec/acceptance/server/grant_role_spec.rb b/spec/acceptance/server/grant_role_spec.rb index e802a41..552c2f5 100644 --- a/spec/acceptance/server/grant_role_spec.rb +++ b/spec/acceptance/server/grant_role_spec.rb @@ -1,230 +1,259 @@ require 'spec_helper_acceptance' describe 'postgresql::server::grant_role:', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do - db = 'grant_role_test' - user = 'psql_grant_role_tester' - group = 'test_group' - password = 'psql_grant_role_pw' + let(:db) { 'grant_role_test' } + let(:user) { 'psql_grant_role_tester' } + let(:group) { 'test_group' } + let(:password) { 'psql_grant_role_pw' } + let(:version) do + if fact('osfamily') == 'RedHat' and fact('operatingsystemrelease') =~ /5/ + '8.1' + end + end it 'should grant a role to a user' do begin pp = <<-EOS.unindent $db = #{db} $user = #{user} $group = #{group} $password = #{password} + $version = '#{version}' class { 'postgresql::server': } # Since we are not testing pg_hba or any of that, make a local user for ident auth user { $user: ensure => present, } postgresql::server::role { $user: password_hash => postgresql_password($user, $password), } postgresql::server::database { $db: owner => $user, require => Postgresql::Server::Role[$user], } + # Lets setup the base rules + $local_auth_option = $version ? { + '8.1' => 'sameuser', + default => undef, + } + # Create a rule for the user postgresql::server::pg_hba_rule { "allow ${user}": type => 'local', database => $db, user => $user, auth_method => 'ident', + auth_option => $local_auth_option, order => 1, } # Create a role to grant to the user postgresql::server::role { $group: db => $db, login => false, require => Postgresql::Server::Database[$db], } # Grant the role to the user postgresql::server::grant_role { "grant_role ${group} to ${user}": role => $user, group => $group, } EOS apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_changes => true) ## Check that the role was granted to the user psql('--command="SELECT 1 WHERE pg_has_role(\'psql_grant_role_tester\', \'test_group\', \'MEMBER\') = true" grant_role_test', 'psql_grant_role_tester') do |r| expect(r.stdout).to match(/\(1 row\)/) expect(r.stderr).to eq('') end end end it 'should grant a role to a superuser' do begin pp = <<-EOS.unindent $db = "#{db}" $user = "#{user}" $group = "#{group}" $password = #{password} + $version = '#{version}' class { 'postgresql::server': } # Since we are not testing pg_hba or any of that, make a local user for ident auth user { $user: ensure => present, } postgresql::server::role { $user: password_hash => postgresql_password($user, $password), superuser => true, } postgresql::server::database { $db: owner => $user, require => Postgresql::Server::Role[$user], } + # Lets setup the base rules + $local_auth_option = $version ? { + '8.1' => 'sameuser', + default => undef, + } + # Create a rule for the user postgresql::server::pg_hba_rule { "allow ${user}": type => 'local', database => $db, user => $user, auth_method => 'ident', + auth_option => $local_auth_option, order => 1, } # Create a role to grant to the user postgresql::server::role { $group: db => $db, login => false, require => Postgresql::Server::Database[$db], } # Grant the role to the user postgresql::server::grant_role { "grant_role ${group} to ${user}": role => $user, group => $group, } EOS apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_changes => true) ## Check that the role was granted to the user psql('--command="SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = \'test_group\' AND r_role.rolname = \'psql_grant_role_tester\'" grant_role_test', 'psql_grant_role_tester') do |r| expect(r.stdout).to match(/\(1 row\)/) expect(r.stderr).to eq('') end end end it 'should revoke a role from a user' do begin pp = <<-EOS $db = "#{db}" $user = "#{user}" $group = "#{group}" $password = #{password} + $version = '#{version}' class { 'postgresql::server': } # Since we are not testing pg_hba or any of that, make a local user for ident auth user { $user: ensure => present, } postgresql::server::role { $user: password_hash => postgresql_password($user, $password), } postgresql::server::database { $db: owner => $user, require => Postgresql::Server::Role[$user], } + # Lets setup the base rules + $local_auth_option = $version ? { + '8.1' => 'sameuser', + default => undef, + } + # Create a rule for the user postgresql::server::pg_hba_rule { "allow ${user}": type => 'local', database => $db, user => $user, auth_method => 'ident', + auth_option => $local_auth_option, order => 1, } # Create a role to grant to the user postgresql::server::role { $group: db => $db, login => false, require => Postgresql::Server::Database[$db], } # Grant the role to the user postgresql::server::grant_role { "grant_role ${group} to ${user}": role => $user, group => $group, } postgresql::server::grant_role {"revoke ${group} from ${user}": ensure => absent, role => $user, group => $group, } EOS apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :expect_changes => true) psql('--command="SELECT 1 WHERE pg_has_role(\'psql_grant_role_tester\', \'test_group\', \'MEMBER\') = true" grant_role_test', 'psql_grant_role_tester') do |r| expect(r.stdout).to match(/\(0 rows\)/) expect(r.stderr).to eq('') end end end it 'should not grant permission to a nonexistent user' do begin pp = <<-EOS $db = "#{db}" $user = "#{user}" $group = "#{group}" $password = #{password} class { 'postgresql::server': } # Since we are not testing pg_hba or any of that, make a local user for ident auth user { $user: ensure => absent, } postgresql::server::database { $db: } # Create a role to grant to the nonexistent user postgresql::server::role { $group: db => $db, login => false, require => Postgresql::Server::Database[$db], } # Grant the role to the nonexistent user postgresql::server::grant_role { "grant_role ${group} to ${user}": role => $user group => $group, } EOS apply_manifest(pp, :expect_failures => true) psql('--command="SELECT 1 WHERE pg_has_role(\'psql_grant_role_tester\', \'test_group\', \'MEMBER\') = true" grant_role_test', 'psql_grant_role_tester') do |r| expect(r.stdout).to match(/\(0 rows\)/) expect(r.stderr).to eq('') end end end end diff --git a/spec/acceptance/server/schema_spec.rb b/spec/acceptance/server/schema_spec.rb index 065ec63..43b2c8a 100644 --- a/spec/acceptance/server/schema_spec.rb +++ b/spec/acceptance/server/schema_spec.rb @@ -1,56 +1,71 @@ require 'spec_helper_acceptance' describe 'postgresql::server::schema:', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do + + let(:version) do + if fact('osfamily') == 'RedHat' and fact('operatingsystemrelease') =~ /5/ + '8.1' + end + end + it 'should create a schema for a user' do begin pp = <<-EOS.unindent $db = 'schema_test' $user = 'psql_schema_tester' $password = 'psql_schema_pw' + $version = '#{version}' class { 'postgresql::server': } # Since we are not testing pg_hba or any of that, make a local user for ident auth user { $user: ensure => present, } postgresql::server::role { $user: password_hash => postgresql_password($user, $password), } postgresql::server::database { $db: owner => $user, require => Postgresql::Server::Role[$user], } + # Lets setup the base rules + $local_auth_option = $version ? { + '8.1' => 'sameuser', + default => undef, + } + # Create a rule for the user postgresql::server::pg_hba_rule { "allow ${user}": type => 'local', database => $db, user => $user, auth_method => 'ident', + auth_option => $local_auth_option, order => 1, } postgresql::server::schema { $user: db => $db, owner => $user, require => Postgresql::Server::Database[$db], } EOS apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_changes => true) ## Check that the user can create a table in the database psql('--command="create table psql_schema_tester.foo (foo int)" schema_test', 'psql_schema_tester') do |r| expect(r.stdout).to match(/CREATE TABLE/) expect(r.stderr).to eq('') end ensure psql('--command="drop table psql_schema_tester.foo" schema_test', 'psql_schema_tester') end end end diff --git a/spec/unit/classes/globals_spec.rb b/spec/unit/classes/globals_spec.rb index ea3ff9d..d4bceda 100644 --- a/spec/unit/classes/globals_spec.rb +++ b/spec/unit/classes/globals_spec.rb @@ -1,87 +1,94 @@ require 'spec_helper' describe 'postgresql::globals', type: :class do context 'on a debian 6' do let (:facts) do { + :os => { + :family => 'Debian', + :name => 'Debian', + :release => { + :full => '6.0' + } + }, :osfamily => 'Debian', :operatingsystem => 'Debian', :operatingsystemrelease => '6.0', :lsbdistid => 'Debian', :lsbdistcodename => 'squeeze' } end describe 'with no parameters' do it 'should work' do is_expected.to contain_class('postgresql::globals') end end describe 'manage_package_repo => true' do let(:params) do { manage_package_repo: true } end it 'should pull in class postgresql::repo' do is_expected.to contain_class('postgresql::repo') end end end context 'on redhat family systems' do let (:facts) do { osfamily: 'RedHat', operatingsystem: 'RedHat', operatingsystemrelease: '7.1' } end describe 'with no parameters' do it 'should work' do is_expected.to contain_class('postgresql::globals') end end describe 'manage_package_repo on RHEL => true' do let(:params) do { manage_package_repo: true, repo_proxy: 'http://proxy-server:8080' } end it 'should pull in class postgresql::repo' do is_expected.to contain_class('postgresql::repo') end it do should contain_yumrepo('yum.postgresql.org').with( 'enabled' => '1', 'proxy' => 'http://proxy-server:8080' ) end end describe 'repo_baseurl on RHEL => mirror.localrepo.com' do let(:params) do { manage_package_repo: true, repo_baseurl: 'http://mirror.localrepo.com' } end it 'should pull in class postgresql::repo' do is_expected.to contain_class('postgresql::repo') end it do should contain_yumrepo('yum.postgresql.org').with( 'enabled' => '1', 'baseurl' => 'http://mirror.localrepo.com' ) end end end end diff --git a/spec/unit/classes/repo_spec.rb b/spec/unit/classes/repo_spec.rb index a9be84e..edfeda3 100644 --- a/spec/unit/classes/repo_spec.rb +++ b/spec/unit/classes/repo_spec.rb @@ -1,19 +1,26 @@ require 'spec_helper' describe 'postgresql::repo', :type => :class do let :facts do { + :os => { + :name => 'Debian', + :family => 'Debian', + :release => { + :full => '6.0' + } + }, :osfamily => 'Debian', :operatingsystem => 'Debian', :operatingsystemrelease => '6.0', :lsbdistid => 'Debian', :lsbdistcodename => 'squeeze', } end describe 'with no parameters' do it 'should instantiate apt_postgresql_org class' do is_expected.to contain_class('postgresql::repo::apt_postgresql_org') end end end diff --git a/spec/unit/classes/server_spec.rb b/spec/unit/classes/server_spec.rb index 852b7e4..c78e60e 100644 --- a/spec/unit/classes/server_spec.rb +++ b/spec/unit/classes/server_spec.rb @@ -1,160 +1,167 @@ require 'spec_helper' describe 'postgresql::server', :type => :class do let :facts do { + :os => { + :family => 'Debian', + :name => 'Debian', + :release => { + :full => '6.0' + } + }, :osfamily => 'Debian', :operatingsystem => 'Debian', :lsbdistid => 'Debian', :lsbdistcodename => 'jessie', :operatingsystemrelease => '8.0', :concat_basedir => tmpfilename('server'), :kernel => 'Linux', :id => 'root', :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', } end describe 'with no parameters' do it { is_expected.to contain_class("postgresql::params") } it { is_expected.to contain_class("postgresql::server") } it { is_expected.to contain_exec('postgresql_reload').with({ 'command' => 'service postgresql reload', }) } it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') + is_expected.to contain_postgresql_conn_validator('validate_service_is_running') end end describe 'service_ensure => running' do let(:params) do { :service_ensure => 'running', :postgres_password => 'new-p@s$word-to-set' } end it { is_expected.to contain_class("postgresql::params") } it { is_expected.to contain_class("postgresql::server") } it { is_expected.to contain_class("postgresql::server::passwd") } it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') + is_expected.to contain_postgresql_conn_validator('validate_service_is_running') end it 'should set postgres password' do is_expected.to contain_exec('set_postgres_postgrespw').with({ 'command' => '/usr/bin/psql -c "ALTER ROLE \"postgres\" PASSWORD ${NEWPASSWD_ESCAPED}"', 'user' => 'postgres', 'environment' => [ "PGPASSWORD=new-p@s$word-to-set", "PGPORT=5432", "NEWPASSWD_ESCAPED=$$new-p@s$word-to-set$$" ], 'unless' => "/usr/bin/psql -h localhost -p 5432 -c 'select 1' > /dev/null", }) end end describe 'service_ensure => stopped' do let(:params) {{ :service_ensure => 'stopped' }} it { is_expected.to contain_class("postgresql::params") } it { is_expected.to contain_class("postgresql::server") } it 'shouldnt validate connection' do - is_expected.not_to contain_postgresql__validate_db_connection('validate_service_is_running') + is_expected.not_to contain_postgresql_conn_validator('validate_service_is_running') end end describe 'service_restart_on_change => false' do let(:params) {{ :service_restart_on_change => false }} it { is_expected.to contain_class("postgresql::params") } it { is_expected.to contain_class("postgresql::server") } it { is_expected.to_not contain_Postgresql_conf('data_directory').that_notifies('Class[postgresql::server::service]') } it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') + is_expected.to contain_postgresql_conn_validator('validate_service_is_running') end end describe 'service_restart_on_change => true' do let(:params) {{ :service_restart_on_change => true }} it { is_expected.to contain_class("postgresql::params") } it { is_expected.to contain_class("postgresql::server") } it { is_expected.to contain_Postgresql_conf('data_directory').that_notifies('Class[postgresql::server::service]') } it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') + is_expected.to contain_postgresql_conn_validator('validate_service_is_running') end end describe 'service_reload => /bin/true' do let(:params) {{ :service_reload => '/bin/true' }} it { is_expected.to contain_class("postgresql::params") } it { is_expected.to contain_class("postgresql::server") } it { is_expected.to contain_exec('postgresql_reload').with({ 'command' => '/bin/true', }) } it 'should validate connection' do - is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') + is_expected.to contain_postgresql_conn_validator('validate_service_is_running') end end describe 'service_manage => true' do let(:params) {{ :service_manage => true }} it { is_expected.to contain_service('postgresqld') } end describe 'service_manage => false' do let(:params) {{ :service_manage => false }} it { is_expected.not_to contain_service('postgresqld') } it 'shouldnt validate connection' do - is_expected.not_to contain_postgresql__validate_db_connection('validate_service_is_running') + is_expected.not_to contain_postgresql_conn_validator('validate_service_is_running') end end describe 'package_ensure => absent' do let(:params) do { :package_ensure => 'absent', } end it 'should remove the package' do is_expected.to contain_package('postgresql-server').with({ :ensure => 'purged', }) end it 'should still enable the service' do is_expected.to contain_service('postgresqld').with({ :ensure => 'running', }) end end describe 'needs_initdb => true' do let(:params) do { :needs_initdb => true, } end it 'should contain proper initdb exec' do is_expected.to contain_exec('postgresql_initdb') end end describe 'postgresql_version' do let(:pre_condition) do <<-EOS class { 'postgresql::globals': manage_package_repo => true, version => '99.5', before => Class['postgresql::server'], } EOS end it 'contains the correct package version' do is_expected.to contain_class('postgresql::repo').with_version('99.5') end end end diff --git a/spec/unit/defines/server/grant_role_spec.rb b/spec/unit/defines/server/grant_role_spec.rb index d93b1e4..12a41e2 100644 --- a/spec/unit/defines/server/grant_role_spec.rb +++ b/spec/unit/defines/server/grant_role_spec.rb @@ -1,161 +1,105 @@ require 'spec_helper' describe 'postgresql::server::grant_role', :type => :define do let :pre_condition do "class { 'postgresql::server': }" end let :facts do {:osfamily => 'Debian', :operatingsystem => 'Debian', :operatingsystemrelease => '6.0', :kernel => 'Linux', :concat_basedir => tmpfilename('postgis'), :id => 'root', :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', } end let (:title) { 'test' } let (:params) { { :group => 'my_group', :role => 'my_role', } } context "with mandatory arguments only" do it { is_expected.to contain_postgresql_psql("grant_role:#{title}").with({ :command => "GRANT \"#{params[:group]}\" TO \"#{params[:role]}\"", :unless => "SELECT 1 WHERE EXISTS (SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = '#{params[:group]}' AND r_role.rolname = '#{params[:role]}') = true", }).that_requires('Class[postgresql::server]') } end - context "validation" do - context "group invalid type" do - let (:params) { { - :group => ['a', 'b'], - :role => 'r', - } } - - it { - expect { catalogue }.to raise_error(Puppet::Error, /is not a string/) - } - end - - context "role invalid type" do - let (:params) { { - :group => 'g', - :role => true, - } } - - it { - expect { catalogue }.to raise_error(Puppet::Error, /is not a string/) - } - end - - context "group empty" do - let (:params) { { - :group => '', - :role => 'r', - } } - - it { - expect { catalogue }.to raise_error(/\$group must be set/) - } - end - - context "role empty" do - let (:params) { { - :group => 'g', - :role => '', - } } - - it { - expect { catalogue }.to raise_error(/\$role must be set/) - } - end - end - context "with db arguments" do let (:params) { super().merge({ :psql_db => 'postgres', :psql_user => 'postgres', :port => '5432', }) } it { is_expected.to contain_postgresql_psql("grant_role:#{title}").with({ :command => "GRANT \"#{params[:group]}\" TO \"#{params[:role]}\"", :unless => "SELECT 1 WHERE EXISTS (SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = '#{params[:group]}' AND r_role.rolname = '#{params[:role]}') = true", :db => params[:psql_db], :psql_user => params[:psql_user], :port => params[:port], }).that_requires('Class[postgresql::server]') } end context "with ensure => absent" do let (:params) { super().merge({ :ensure => 'absent', }) } it { is_expected.to contain_postgresql_psql("grant_role:#{title}").with({ :command => "REVOKE \"#{params[:group]}\" FROM \"#{params[:role]}\"", :unless => "SELECT 1 WHERE EXISTS (SELECT 1 FROM pg_roles AS r_role JOIN pg_auth_members AS am ON r_role.oid = am.member JOIN pg_roles AS r_group ON r_group.oid = am.roleid WHERE r_group.rolname = '#{params[:group]}' AND r_role.rolname = '#{params[:role]}') != true", }).that_requires('Class[postgresql::server]') } end - context "with ensure => invalid" do - let (:params) { super().merge({ - :ensure => 'invalid', - }) } - - it { - expect { catalogue }.to raise_error(Puppet::Error, /Unknown value for ensure/) - } - end - context "with user defined" do let :pre_condition do "class { 'postgresql::server': } postgresql::server::role { '#{params[:role]}': }" end it { is_expected.to contain_postgresql_psql("grant_role:#{title}").that_requires("Postgresql::Server::Role[#{params[:role]}]") } it { is_expected.not_to contain_postgresql_psql("grant_role:#{title}").that_requires("Postgresql::Server::Role[#{params[:group]}]") } end context "with group defined" do let :pre_condition do "class { 'postgresql::server': } postgresql::server::role { '#{params[:group]}': }" end it { is_expected.to contain_postgresql_psql("grant_role:#{title}").that_requires("Postgresql::Server::Role[#{params[:group]}]") } it { is_expected.not_to contain_postgresql_psql("grant_role:#{title}").that_requires("Postgresql::Server::Role[#{params[:role]}]") } end context "with connect_settings" do let (:params) { super().merge({ :connect_settings => { 'PGHOST' => 'postgres-db-server' }, }) } it { is_expected.to contain_postgresql_psql("grant_role:#{title}").with_connect_settings( { 'PGHOST' => 'postgres-db-server' } ) } it { is_expected.not_to contain_postgresql_psql("grant_role:#{title}").that_requires('Class[postgresql::server]') } end end diff --git a/spec/unit/defines/server/grant_spec.rb b/spec/unit/defines/server/grant_spec.rb index fe79636..79d569d 100644 --- a/spec/unit/defines/server/grant_spec.rb +++ b/spec/unit/defines/server/grant_spec.rb @@ -1,155 +1,155 @@ require 'spec_helper' describe 'postgresql::server::grant', :type => :define do let :facts do { :osfamily => 'Debian', :operatingsystem => 'Debian', :operatingsystemrelease => '6.0', :kernel => 'Linux', :concat_basedir => tmpfilename('contrib'), :id => 'root', :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', } end let :title do 'test' end context 'plain' do let :params do { :db => 'test', :role => 'test', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__grant('test') } end context 'sequence' do let :params do { :db => 'test', :role => 'test', :privilege => 'usage', :object_type => 'sequence', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql_psql('grant:test').with( { 'command' => /GRANT USAGE ON SEQUENCE "test" TO\s* "test"/m, 'unless' => /SELECT 1 WHERE has_sequence_privilege\('test',\s* 'test', 'USAGE'\)/m, } ) } end context 'all sequences' do let :params do { :db => 'test', :role => 'test', :privilege => 'usage', :object_type => 'all sequences in schema', :object_name => 'public', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql_psql('grant:test').with( { 'command' => /GRANT USAGE ON ALL SEQUENCES IN SCHEMA "public" TO\s* "test"/m, 'unless' => /SELECT 1 FROM \(\s*SELECT sequence_name\s* FROM information_schema\.sequences\s* WHERE sequence_schema='public'\s* EXCEPT DISTINCT\s* SELECT object_name as sequence_name\s* FROM .* WHERE .*grantee='test'\s* AND object_schema='public'\s* AND privilege_type='USAGE'\s*\) P\s* HAVING count\(P\.sequence_name\) = 0/m, } ) } end context "with specific db connection settings - default port" do let :params do { :db => 'test', :role => 'test', :connect_settings => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', }, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql_psql("grant:test").with_connect_settings( { 'PGHOST' => 'postgres-db-server','DBVERSION' => '9.1' } ).with_port( 5432 ) } end context "with specific db connection settings - including port" do let :params do { :db => 'test', :role => 'test', :connect_settings => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234', }, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql_psql("grant:test").with_connect_settings( { 'PGHOST' => 'postgres-db-server','DBVERSION' => '9.1','PGPORT' => '1234' } ) } end context "with specific db connection settings - port overriden by explicit parameter" do let :params do { :db => 'test', :role => 'test', :connect_settings => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234', }, - :port => '5678', + :port => 5678, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql_psql("grant:test").with_connect_settings( { 'PGHOST' => 'postgres-db-server','DBVERSION' => '9.1','PGPORT' => '1234' } ).with_port( '5678' ) } end context 'invalid objectype' do let :params do { :db => 'test', :role => 'test', :privilege => 'usage', :object_type => 'invalid', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.and_raise_error(/"INVALID" does not match/) } end end diff --git a/spec/unit/defines/server/pg_hba_rule_spec.rb b/spec/unit/defines/server/pg_hba_rule_spec.rb index f36d27d..f657589 100644 --- a/spec/unit/defines/server/pg_hba_rule_spec.rb +++ b/spec/unit/defines/server/pg_hba_rule_spec.rb @@ -1,198 +1,126 @@ require 'spec_helper' describe 'postgresql::server::pg_hba_rule', :type => :define do let :facts do { :osfamily => 'Debian', :operatingsystem => 'Debian', :operatingsystemrelease => '6.0', :kernel => 'Linux', :concat_basedir => tmpfilename('pg_hba'), :id => 'root', :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', } end let :title do 'test' end let :target do tmpfilename('pg_hba_rule') end context 'test template 1' do let :pre_condition do <<-EOS class { 'postgresql::server': } EOS end let :params do { :type => 'host', :database => 'all', :user => 'all', :address => '1.1.1.1/24', :auth_method => 'md5', :target => target, } end it do is_expected.to contain_concat__fragment('pg_hba_rule_test').with({ :content => /host\s+all\s+all\s+1\.1\.1\.1\/24\s+md5/ }) end end context 'test template 2' do let :pre_condition do <<-EOS class { 'postgresql::server': } EOS end let :params do { :type => 'local', :database => 'all', :user => 'all', :auth_method => 'ident', :target => target, } end it do is_expected.to contain_concat__fragment('pg_hba_rule_test').with({ :content => /local\s+all\s+all\s+ident/ }) end end context 'test template 3' do let :pre_condition do <<-EOS class { 'postgresql::server': } EOS end let :params do { :type => 'host', :database => 'all', :user => 'all', :address => '0.0.0.0/0', :auth_method => 'ldap', :auth_option => 'foo=bar', :target => target, } end it do is_expected.to contain_concat__fragment('pg_hba_rule_test').with({ :content => /host\s+all\s+all\s+0\.0\.0\.0\/0\s+ldap\s+foo=bar/ }) end end context 'validation' do - context 'validate type test 1' do - let :pre_condition do - <<-EOS - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'invalid', - :database => 'all', - :user => 'all', - :address => '0.0.0.0/0', - :auth_method => 'ldap', - :target => target, - } - end - it 'should fail parsing when type is not valid' do - expect { catalogue }.to raise_error(Puppet::Error, - /The type you specified \[invalid\] must be one of/) - end - end - - context 'validate auth_method' do - let :pre_condition do - <<-EOS - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'local', - :database => 'all', - :user => 'all', - :address => '0.0.0.0/0', - :auth_method => 'invalid', - :target => target, - } - end - - it 'should fail parsing when auth_method is not valid' do - expect { catalogue }.to raise_error(Puppet::Error, - /The auth_method you specified \[invalid\] must be one of/) - end - end - - context 'validate unsupported auth_method' do - let :pre_condition do - <<-EOS - class { 'postgresql::globals': - version => '9.0', - } - class { 'postgresql::server': } - EOS - end - - let :params do - { - :type => 'local', - :database => 'all', - :user => 'all', - :address => '0.0.0.0/0', - :auth_method => 'peer', - :target => target, - } - end - - it 'should fail parsing when auth_method is not valid' do - expect { catalogue }.to raise_error(Puppet::Error, - /The auth_method you specified \[peer\] must be one of: trust, reject, md5, password, gss, sspi, krb5, ident, ldap, radius, cert, pam/) - end - end - context 'validate supported auth_method' do let :pre_condition do <<-EOS class { 'postgresql::globals': version => '9.2', } class { 'postgresql::server': } EOS end let :params do { :type => 'local', :database => 'all', :user => 'all', :address => '0.0.0.0/0', :auth_method => 'peer', :target => target, } end it do - is_expected.to contain_concat__fragment('pg_hba_rule_test').with({ - :content => /local\s+all\s+all\s+0\.0\.0\.0\/0\s+peer/ - }) + is_expected.to contain_concat__fragment('pg_hba_rule_test').with( + { + :content => /local\s+all\s+all\s+0\.0\.0\.0\/0\s+peer/ + } + ) end end end end diff --git a/spec/unit/defines/server/role_spec.rb b/spec/unit/defines/server/role_spec.rb index 5c608cf..1b061d0 100644 --- a/spec/unit/defines/server/role_spec.rb +++ b/spec/unit/defines/server/role_spec.rb @@ -1,135 +1,152 @@ require 'spec_helper' describe 'postgresql::server::role', :type => :define do let :facts do { :osfamily => 'Debian', :operatingsystem => 'Debian', :operatingsystemrelease => '6.0', :kernel => 'Linux', :concat_basedir => tmpfilename('contrib'), :id => 'root', :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', } end let :title do 'test' end let :params do { :password_hash => 'new-pa$s', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__role('test') } it 'should have create role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****').with({ 'command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", 'environment' => "NEWPGPASSWD=new-pa$s", 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", 'port' => "5432", }) end it 'should have alter role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****').with({ 'command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", 'environment' => "NEWPGPASSWD=new-pa$s", 'unless' => "SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa'", 'port' => "5432", }) end context "with specific db connection settings - default port" do let :params do { :password_hash => 'new-pa$s', :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGUSER' => 'login-user', - 'PGPASSWORD' => 'login-pass' }, + 'DBVERSION' => '9.1', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' }, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__role('test') } it 'should have create role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****').with({ 'command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", 'environment' => "NEWPGPASSWD=new-pa$s", 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", 'port' => "5432", 'connect_settings' => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }, }) end it 'should have alter role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****').with({ 'command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", 'environment' => "NEWPGPASSWD=new-pa$s", 'unless' => "SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa'", 'port' => "5432", 'connect_settings' => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }, }) end end context "with specific db connection settings - including port" do let :params do { :password_hash => 'new-pa$s', :connect_settings => { 'PGHOST' => 'postgres-db-server', - 'DBVERSION' => '9.1', - 'PGPORT' => '1234', - 'PGUSER' => 'login-user', - 'PGPASSWORD' => 'login-pass' }, + 'DBVERSION' => '9.1', + 'PGPORT' => '1234', + 'PGUSER' => 'login-user', + 'PGPASSWORD' => 'login-pass' }, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__role('test') } it 'should have create role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****').with({ 'command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", 'environment' => "NEWPGPASSWD=new-pa$s", 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", 'connect_settings' => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }, }) end it 'should have alter role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****').with({ 'command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", 'environment' => "NEWPGPASSWD=new-pa$s", 'unless' => "SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa'", 'connect_settings' => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }, }) end end + context 'with update_password set to false' do + let :params do + { + :password_hash => 'new-pa$s', + :update_password => false, + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it 'should not have alter role for "test" user with password as **** if update_password is false' do + is_expected.not_to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') + end + end + end diff --git a/spec/unit/puppet/provider/postgresql_conn_validator/ruby_spec.rb b/spec/unit/puppet/provider/postgresql_conn_validator/ruby_spec.rb new file mode 100644 index 0000000..3d678ea --- /dev/null +++ b/spec/unit/puppet/provider/postgresql_conn_validator/ruby_spec.rb @@ -0,0 +1,66 @@ +require 'spec_helper' + +describe Puppet::Type.type(:postgresql_conn_validator).provider(:ruby) do + + let(:resource) { Puppet::Type.type(:postgresql_conn_validator).new({ + :name => "testname" + }.merge attributes) } + let(:provider) { resource.provider } + + let(:attributes) do + { + :psql_path => '/usr/bin/psql', + :host => 'db.test.com', + :port => 4444, + :db_username => 'testuser', + :db_password => 'testpass' + } + end + + describe '#build_psql_cmd' do + it 'contains expected commandline options' do + expect(provider.validator.build_psql_cmd).to match /\/usr\/bin\/psql.*--host.*--port.*--username.*/ + end + end + + describe '#parse_connect_settings' do + it 'returns array if password is present' do + expect(provider.validator.parse_connect_settings).to eq(['PGPASSWORD=testpass']) + end + + it 'returns an empty array if password is nil' do + attributes.delete(:db_password) + expect(provider.validator.parse_connect_settings).to eq([]) + end + + let(:connect_settings) do + { + :connect_settings => { + :PGPASSWORD => 'testpass', + :PGHOST => 'db.test.com', + :PGPORT => '1234' + } + } + end + it 'returns an array of settings' do + attributes.delete(:db_password) + attributes.merge! connect_settings + expect(provider.validator.parse_connect_settings).to eq(['PGPASSWORD=testpass','PGHOST=db.test.com','PGPORT=1234']) + end + end + + describe '#attempt_connection' do + let(:sleep_length) {1} + let(:tries) {3} + let(:exec) { + provider.validator.stub(:execute_command).and_return(true) + } + + it 'tries the correct number of times' do + expect(provider.validator).to receive(:execute_command).exactly(3).times + + provider.validator.attempt_connection(sleep_length,tries) + + end + end +end diff --git a/spec/unit/puppet/type/postgresql_conn_validator.rb b/spec/unit/puppet/type/postgresql_conn_validator.rb new file mode 100644 index 0000000..ef3a1ed --- /dev/null +++ b/spec/unit/puppet/type/postgresql_conn_validator.rb @@ -0,0 +1,42 @@ +#! /usr/bin/env ruby +require 'spec_helper' + +describe Puppet::Type.type(:postgresql_conn_validator) do + before do + @provider_class = described_class.provide(:simple) { mk_resource_methods } + @provider_class.stub(:suitable?).and_return true + described_class.stub(:defaultprovider).and_return @provider_class + end + + describe "when validating attributes" do + [:name, :db_name, :db_username, :command, :host, :port, :connect_settings, :sleep, :tries, :psql_path].each do |param| + it "should have a #{param} parameter" do + expect(described_class.attrtype(param)).to eq(:param) + end + end + end + + describe "when validating values" do + describe "tries and sleep" do + [:tries, :sleep, :port].each do |param| + it "#{param} should be able to cast value as integer" do + expect { described_class.new(:name => 'test', param => '1') }.to_not raise_error + expect { described_class.new(:name => 'test', param => 1) }.to_not raise_error + end + it "#{param} should not accept non-numeric string" do + expect { described_class.new(:name => 'test', param => 'test') }.to raise_error Puppet::ResourceError + end + end + end + describe "connect_settings" do + it "should accept a hash" do + expect { described_class.new(:name => 'test', :connect_settings => { "PGPASSWORD" => "test1" }) }.to_not raise_error + end + end + describe "port" do + it "does not accept a word" do + expect { described_class.new(:name => 'test', :port => 'test')}.to raise_error Puppet::Error + end + end + end +end