Skip to content

Commit c37b50c

Browse files
committed
(MODULES-1394) replace validate_db_connection type with custom type
This replaces the defined type `validate_db_connection` with a new custom type called `postgresql_conn_validator`. It's functionality is nearly a copy of its predecessor with the exception of the `create_db_first` parameter which is taken care of with a collector in service.pp. The old type is still intact but all docs have been removed and a warning has been attached to it announcing its deprecation.
1 parent dcaed6c commit c37b50c

File tree

13 files changed

+520
-90
lines changed

13 files changed

+520
-90
lines changed

README.md

Lines changed: 63 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -283,16 +283,16 @@ Only the specified parameters are recognized in the template. The `recovery.conf
283283

284284
### Validate connectivity
285285

286-
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.
286+
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.
287287

288288
Example usage:
289289

290290
```puppet
291-
postgresql::validate_db_connection { 'validate my postgres connection':
292-
database_host => 'my.postgres.host',
293-
database_username => 'mydbuser',
294-
database_password => 'mydbpassword',
295-
database_name => 'mydbname',
291+
postgresql_conn_validator { 'validate my postgres connection':
292+
host => 'my.postgres.host',
293+
db_username => 'mydbuser',
294+
db_password => 'mydbpassword',
295+
db_name => 'mydbname',
296296
}->
297297
exec { 'rake db:migrate':
298298
cwd => '/opt/myrubyapp',
@@ -332,13 +332,13 @@ The postgresql module comes with many options for configuring the server. While
332332
* [postgresql::server::schema](#postgresqlserverschema)
333333
* [postgresql::server::table_grant](#postgresqlservertable_grant)
334334
* [postgresql::server::tablespace](#postgresqlservertablespace)
335-
* [postgresql::validate_db_connection](#postgresqlvalidate_db_connection)
336335

337336
**Types:**
338337

339338
* [postgresql_psql](#custom-resource-postgresql_psql)
340339
* [postgresql_replication_slot](#custom-resource-postgresql_replication_slot)
341340
* [postgresql_conf](#custom-resource-postgresql_conf)
341+
* [postgresql_conn_validator](#custom-resource-postgresql_conn_validator)
342342

343343
**Functions:**
344344

@@ -367,13 +367,6 @@ Sets the name of the PostgreSQL client package.
367367

368368
Default value: 'file'.
369369

370-
##### `validcon_script_path`
371-
372-
Specifies the path to validate the connection script.
373-
374-
375-
Default value: '/usr/local/bin/validate_postgresql_connection.sh'.
376-
377370
#### postgresql::lib::docs
378371

379372
Installs PostgreSQL bindings for Postgres-Docs. Set the following parameters if you have a custom version you would like to install.
@@ -1543,64 +1536,6 @@ Specifies the name of the tablespace.
15431536

15441537
Default value: the namevar.
15451538

1546-
#### postgresql::validate_db_connection
1547-
1548-
Validates client connection with a remote PostgreSQL database.
1549-
1550-
##### `connect_settings`
1551-
1552-
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.
1553-
1554-
##### `create_db_first`
1555-
1556-
Ensures that the database is created before running the test. This only works if your test is local.
1557-
1558-
Default value: `true`.
1559-
1560-
##### `database_host`
1561-
1562-
Sets the hostname of the database you wish to test.
1563-
1564-
Default value: `undef`, which generally uses the designated local Unix socket.
1565-
1566-
##### `database_name`
1567-
1568-
Specifies the name of the database you wish to test.
1569-
1570-
Default value: 'postgres'.
1571-
1572-
##### `database_port`
1573-
1574-
Defines the port to use when connecting.
1575-
1576-
Default value: `undef`, which generally defaults to port 5432 depending on your PostgreSQL packaging.
1577-
1578-
##### `database_password`
1579-
1580-
Specifies the password to connect with. Can be left blank, not recommended.
1581-
1582-
##### `database_username`
1583-
1584-
Specifies the username to connect with.
1585-
1586-
Default value: `undef`.
1587-
1588-
When using a Unix socket and ident auth, this is the user you are running as.
1589-
1590-
**If the host is remote you must provide a username.**
1591-
1592-
##### `run_as`
1593-
1594-
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.
1595-
1596-
##### `sleep`
1597-
1598-
Sets the number of seconds to sleep for before trying again after a failure.
1599-
1600-
##### `tries`
1601-
1602-
Sets the number of attempts after failure before giving up and failing the resource.
1603-
16041539
### Types
16051540

16061541
#### postgresql_psql
@@ -1703,6 +1638,62 @@ Specifies the name of the slot to create. Must be a valid replication slot name.
17031638

17041639
This is the namevar.
17051640

1641+
#### postgresql_conn_validator
1642+
1643+
Validate the connection to a local or remote PostgreSQL database using this type.
1644+
1645+
##### `connect_settings`
1646+
1647+
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.
1648+
1649+
Default value: {}
1650+
1651+
##### `db_name`
1652+
1653+
Specifies the name of the database you wish to test.
1654+
1655+
Default value: ''
1656+
1657+
##### `db_password`
1658+
1659+
Specifies the password to connect with. Can be left blank if `.pgpass` is being used, otherwise not recommended.
1660+
1661+
Default value: ''
1662+
1663+
##### `db_username`
1664+
1665+
Specifies the username to connect with.
1666+
1667+
Default value: ''
1668+
1669+
When using a Unix socket and ident auth, this is the user you are running as.
1670+
1671+
##### `host`
1672+
1673+
Sets the hostname of the database you wish to test.
1674+
1675+
Default value: '', which generally uses the designated local Unix socket.
1676+
1677+
**If the host is remote you must provide a username.**
1678+
1679+
##### `port`
1680+
1681+
Defines the port to use when connecting.
1682+
1683+
Default value: ''
1684+
1685+
##### `run_as`
1686+
1687+
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.
1688+
1689+
##### `sleep`
1690+
1691+
Sets the number of seconds to sleep for before trying again after a failure.
1692+
1693+
##### `tries`
1694+
1695+
Sets the number of attempts after failure before giving up and failing the resource.
1696+
17061697
### Functions
17071698

17081699
#### postgresql_password
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),"..","..",".."))
2+
require 'puppet/util/postgresql_validator'
3+
4+
# This file contains a provider for the resource type `postgresql_conn_validator`,
5+
# which validates the puppetdb connection by attempting an https connection.
6+
7+
Puppet::Type.type(:postgresql_conn_validator).provide(:ruby) do
8+
desc "A provider for the resource type `postgresql_conn_validator`,
9+
which validates the PostgreSQL connection by attempting a query
10+
to the target PostgreSQL server."
11+
12+
# Test to see if the resource exists, returns true if it does, false if it
13+
# does not.
14+
#
15+
# Here we simply monopolize the resource API, to execute a test to see if the
16+
# database is connectable. When we return a state of `false` it triggers the
17+
# create method where we can return an error message.
18+
#
19+
# @return [bool] did the test succeed?
20+
def exists?
21+
validator.attempt_connection(resource[:sleep], resource[:tries])
22+
end
23+
24+
# This method is called when the exists? method returns false.
25+
#
26+
# @return [void]
27+
def create
28+
# If `#create` is called, that means that `#exists?` returned false, which
29+
# means that the connection could not be established... so we need to
30+
# cause a failure here.
31+
raise Puppet::Error, "Unable to connect to PostgreSQL server! (#{resource[:host]}:#{resource[:port]})"
32+
end
33+
34+
# Returns the existing validator, if one exists otherwise creates a new object
35+
# from the class.
36+
#
37+
# @api private
38+
def validator
39+
@validator ||= Puppet::Util::PostgresqlValidator.new(resource)
40+
end
41+
42+
end
43+
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
Puppet::Type.newtype(:postgresql_conn_validator) do
2+
3+
@doc = "Verify that a connection can be successfully established between a node
4+
and the PostgreSQL server. Its primary use is as a precondition to
5+
prevent configuration changes from being applied if the PostgreSQL
6+
server cannot be reached, but it could potentially be used for other
7+
purposes such as monitoring."
8+
9+
ensurable do
10+
defaultvalues
11+
defaultto :present
12+
end
13+
14+
newparam(:name, :namevar => true) do
15+
desc 'An arbitrary name used as the identity of the resource.'
16+
end
17+
18+
newparam(:db_name) do
19+
desc "The name of the database you are trying to validate a connection with."
20+
end
21+
22+
newparam(:db_username) do
23+
desc "A user that has access to the target PostgreSQL database."
24+
end
25+
26+
newparam(:db_password) do
27+
desc "The password required to access the target PostgreSQL database."
28+
end
29+
30+
newparam(:host) do
31+
desc 'The DNS name or IP address of the server where PostgreSQL should be running.'
32+
end
33+
34+
newparam(:port) do
35+
desc 'The port that the PostgreSQL server should be listening on.'
36+
37+
validate do |value|
38+
if value
39+
value =~ /[0-9]+/
40+
end
41+
end
42+
end
43+
44+
newparam(:connect_settings) do
45+
desc 'Hash of environment variables for connection to a db.'
46+
47+
end
48+
49+
newparam(:sleep) do
50+
desc "The length of sleep time between connection tries."
51+
52+
validate do |value|
53+
Integer(value)
54+
end
55+
munge do |value|
56+
Integer(value)
57+
end
58+
59+
defaultto 2
60+
end
61+
62+
newparam(:tries) do
63+
desc "The number of tries to validate the connection to the target PostgreSQL database."
64+
65+
validate do |value|
66+
Integer(value)
67+
end
68+
munge do |value|
69+
Integer(value)
70+
end
71+
72+
defaultto 10
73+
end
74+
75+
newparam(:psql_path) do
76+
desc "Path to the psql command."
77+
end
78+
79+
newparam(:run_as) do
80+
desc "System user that will run the psql command."
81+
end
82+
end
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module Puppet
2+
module Util
3+
class PostgresqlValidator
4+
attr_reader :resource
5+
6+
def initialize(resource)
7+
@resource = resource
8+
end
9+
10+
def build_psql_cmd
11+
final_cmd = []
12+
13+
cmd_init = "#{@resource[:psql_path]} --tuples-only --quiet "
14+
15+
final_cmd.push cmd_init
16+
17+
cmd_parts = {
18+
:host => "-h #{@resource[:host]}",
19+
:port => "-p #{@resource[:port]}",
20+
:db_username => "-U #{@resource[:db_username]}",
21+
:db_name => "--dbname #{@resource[:db_name]}"
22+
}
23+
24+
cmd_parts[:db_password] = "-w " if @resource[:db_password]
25+
26+
cmd_parts.each do |k,v|
27+
final_cmd.push v if @resource[k]
28+
end
29+
30+
final_cmd.join ' '
31+
end
32+
33+
def parse_connect_settings
34+
c_settings = @resource[:connect_settings] || {}
35+
c_settings.merge! ({ 'PGPASSWORD' => @resource[:db_password] }) if @resource[:db_password]
36+
return c_settings.map { |k,v| "#{k}=#{v}" }
37+
end
38+
39+
def attempt_connection(sleep_length, tries)
40+
(0..tries-1).each do |try|
41+
Puppet.debug "PostgresqlValidator.attempt_connection: Attempting connection to #{@resource[:db_name]}"
42+
if execute_command =~ /1/
43+
Puppet.debug "PostgresqlValidator.attempt_connection: Connection to #{@resource[:db_name]} successful!"
44+
return true
45+
else
46+
Puppet.warning "PostgresqlValidator.attempt_connection: Sleeping for #{sleep_length} seconds"
47+
sleep sleep_length
48+
end
49+
end
50+
false
51+
end
52+
53+
private
54+
55+
def execute_command
56+
Execution.execute(build_validate_cmd, :uid => @resource[:run_as])
57+
end
58+
59+
def build_validate_cmd
60+
"/bin/echo 'SELECT 1' | #{parse_connect_settings.join(' ')} #{build_psql_cmd} "
61+
end
62+
end
63+
end
64+
end

manifests/server/db.pp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
privilege => $grant,
3939
db => $dbname,
4040
role => $user,
41-
} -> Postgresql::Validate_db_connection<| database_name == $dbname |>
41+
} -> Postgresql_conn_validator<| db_name == $dbname |>
4242
}
4343

4444
if($tablespace != undef and defined(Postgresql::Server::Tablespace[$tablespace])) {

0 commit comments

Comments
 (0)