Browse Source

Bring database, database_user, and database_grant into alignment with mysql module

Renamed a few files and made some tweaks to try to get
database_grant, database_user, and database types into
a state where they work very similarly to the ones in
the mysql module.  Also introduced a "postgresql_password"
function that can be used to generate an md5 password
hash for a postgres user.
Chris Price 12 years ago
parent
commit
45055d324c

+ 18 - 0
lib/puppet/parser/functions/postgresql_password.rb

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

+ 10 - 7
manifests/db.pp → manifests/database.pp

@@ -16,15 +16,18 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-define postgresql::db(
+# TODO: in order to match up more closely with the mysql module, this probably
+#  needs to be moved over to ruby, and add support for ensurable.
+
+define postgresql::database(
   $dbname = $title,
-  $version = '9.1',
-  $encoding = 'UTF8',
-  $options='' )
+  $charset = 'UTF8')
 {
-  # TODO: This should be found based on the operating system; currently hardcoded to Ubuntu's path choice
-  exec {"/usr/lib/postgresql/${version}/bin/createdb --encoding '$encoding' '$dbname'":
-    unless  => "/usr/lib/postgresql/${version}/bin/psql --command=\"SELECT datname FROM pg_database WHERE datname=\'$dbname\' \" --pset=tuples_only | grep -q $dbname",
+  require postgresql::params
+
+
+  exec {"${postgresql::params::createdb_path} --template=template0 --encoding '$charset' --locale=C '$dbname'":
+    unless  => "${postgresql::params::psql_path} --command=\"SELECT datname FROM pg_database WHERE datname=\'$dbname\' \" --pset=tuples_only | grep -q $dbname",
     user    => 'postgres',
   }
 }

+ 58 - 0
manifests/database_grant.pp

@@ -0,0 +1,58 @@
+# puppet-postgresql
+# For all details and documentation:
+# http://github.com/inkling/puppet-postgresql
+#
+# Copyright 2012- Inkling Systems, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# TODO: in mysql module, the grant resource name might look like this: 'user@host/dbname';
+#  I think that the API for the resource type should split these up, because it's
+#  easier / safer to recombine them for mysql than it is to parse them for other
+#  databases.  Also, in the mysql module, the hostname portion of that string
+#  affects the user's ability to connect from remote hosts.  In postgres this is
+#  managed via pg_hba.conf; not sure if we want to try to reconcile that difference
+#  in the modules or not.
+
+define postgresql::database_grant(
+    # TODO: mysql supports an array of privileges here.  We should do that if we
+    #  port this to ruby.
+    $privilege,
+    $db,
+    $role,
+    $psql_db = 'postgres',
+    $psql_user='postgres',
+) {
+
+  # TODO: FIXME: only works on databases, due to using has_database_privilege
+
+  # 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 privelege 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!)
+  $unless_privilege = $privilege ? {
+    'ALL'   => 'CREATE',
+    default => $privilege,
+  }
+
+  postgresql::psql {"GRANT $privilege ON database $db TO $role":
+    db      => $psql_db,
+    user    => $psql_user,
+    unless  => "SELECT 1 WHERE has_database_privilege('$role', '$db', '$unless_privilege')",
+  }
+}
+

+ 14 - 8
manifests/user.pp → manifests/database_user.pp

@@ -16,14 +16,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-define postgresql::user($username=$title, $password, $version='9.1', $db = 'postgres', $createdb=false, $superuser=false, $createrole=false) {
+define postgresql::database_user(
+    $username=$title,
+    $password_hash,
+    $db = 'postgres',
+    $createdb=false,
+    $superuser=false,
+    $createrole=false
+) {
   postgresql::role {$username:
-    db         => $db,
-    password   => $password,
-    version    => $version,
-    login      => true,
-    createdb   => $createdb,
-    superuser  => $superuser,
-    createrole => $createrole,
+    db              => $db,
+    password_hash   => $password_hash,
+    login           => true,
+    createdb        => $createdb,
+    superuser       => $superuser,
+    createrole      => $createrole,
   }
 }

+ 0 - 30
manifests/grant.pp

@@ -1,30 +0,0 @@
-# puppet-postgresql
-# For all details and documentation:
-# http://github.com/inkling/puppet-postgresql
-#
-# Copyright 2012- Inkling Systems, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-define postgresql::grant($perm, $on_object, $grantee, $db = 'postgres', $user='postgres', $version='9.1') {
-
-  # FIXME: only works on tables, due to using has_table_privilege
-
-  postgresql::psql {"GRANT $perm ON $on_object TO $grantee":
-    version => $version,
-    db      => $db,
-    user    => $user,
-    unless  => "SELECT 1 WHERE has_table_privilege('$grantee', '$on_object', '$perm')",
-  }
-}
-

+ 4 - 2
manifests/params.pp

@@ -11,8 +11,6 @@
 # Sample Usage:
 #
 class postgresql::params {
-
-
   $user                     = 'postgres'
   $group                    = 'postgres'
   $ip_mask_postgres_user    = '127.0.0.1/32'
@@ -37,6 +35,8 @@ class postgresql::params {
       $server_package_name      = 'postgresql-server'
       $needs_initdb             = true
       $initdb_path              = '/usr/bin/initdb'
+      $createdb_path            = '/usr/bin/createdb'
+      $psql_path                = '/usr/bin/psql'
       $datadir                  = '/var/lib/pgsql/data/'
       $pg_hba_conf_path         = '/var/lib/pgsql/data/pg_hba.conf'
       $postgresql_conf_path     = '/var/lib/pgsql/data/postgresql.conf'
@@ -50,6 +50,8 @@ class postgresql::params {
       $server_package_name      = 'postgresql'
       $needs_initdb             = false
       $initdb_path              = "/usr/lib/postgresql/${::postgres_default_version}/bin/initdb"
+      $createdb_path            = "/usr/lib/postgresql/${::postgres_default_version}/bin/createdb"
+      $psql_path                = "/usr/lib/postgresql/${::postgres_default_version}/bin/psql"
       $datadir                  = "/var/lib/postgresql/${::postgres_default_version}/main"
       $pg_hba_conf_path         = "/etc/postgresql/${::postgres_default_version}/main/pg_hba.conf"
       $postgresql_conf_path     = "/etc/postgresql/${::postgres_default_version}/main/postgresql.conf"

+ 10 - 6
manifests/psql.pp

@@ -16,19 +16,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-define postgresql::psql($command = $title, $unless, $db, $user = 'postgres', $version='9.1') {
+define postgresql::psql($command = $title, $unless, $db, $user = 'postgres') {
 
-  # FIXME: shellquote does not work, and this regex works for trivial things but not nested escaping.
+  require postgresql::params
+
+  # TODO: FIXME: shellquote does not work, and this regex works for trivial things but not nested escaping.
   # Need a lexer, preferably a ruby SQL parser to catch errors at catalog time
   # Possibly https://github.com/omghax/sql ?
 
-  $psql = "/usr/lib/postgresql/$version/bin/psql --no-password --tuples-only --quiet --dbname $db"
+  $psql = "${postgresql::params::psql_path} --no-password --tuples-only --quiet --dbname $db"
   $quoted_command = regsubst($command, '"', '\\"')
   $quoted_unless  = regsubst($unless,  '"', '\\"')
 
-  exec {"/bin/echo \"$quoted_command\" | $psql":
-    unless  => "/bin/echo \"$quoted_$unless\" | $psql | egrep -v -q '^$'",
-    user    => $user,
+  exec {"/bin/echo \"$quoted_command\" | $psql |egrep -v -q '^$'":
+    cwd         => '/tmp',
+    user        => $user,
+    returns     => 1,
+    unless      => "/bin/echo \"$quoted_$unless\" | $psql | egrep -v -q '^$'",
   }
 }
 

+ 11 - 4
manifests/role.pp

@@ -16,16 +16,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-define postgresql::role($username=$title, $password, $db='postgres', $version='9.1', $login=false, $createrole=false, $createdb=false, $superuser=false) {
+define postgresql::role(
+    $username=$title,
+    $password_hash,
+    $db='postgres',
+    $login=false,
+    $createrole=false,
+    $createdb=false,
+    $superuser=false
+) {
 
   $login_sql      = $login      ? { true => 'LOGIN'     , false => 'NOLOGIN' }
   $createrole_sql = $createrole ? { true => 'CREATEROLE', false => 'NOCREATEROLE' }
   $createdb_sql   = $createdb   ? { true => 'CREATEDB'  , false => 'NOCREATEDB' }
   $superuser_sql  = $superuser  ? { true => 'SUPERUSER' , false => 'NOSUPERUSER' }
 
-  # FIXME: Will not correct the superuser / createdb / createrole / login status of a role that already exists
-  postgresql::psql {"CREATE ROLE ${username} ENCRYPTED PASSWORD '${password}' $login_sql $createrole_sql $createdb_sql $superuser_sql":
-    version => $version,
+  # TODO: FIXME: Will not correct the superuser / createdb / createrole / login status of a role that already exists
+  postgresql::psql {"CREATE ROLE ${username} ENCRYPTED PASSWORD '${password_hash}' $login_sql $createrole_sql $createdb_sql $superuser_sql":
     db      => $db,
     user    => 'postgres',
     unless  => "SELECT rolname FROM pg_roles WHERE rolname='$username'",

+ 22 - 0
tests/postgresql_database.pp

@@ -0,0 +1,22 @@
+class { 'postgresql::server':
+    config_hash => {
+        'ip_mask_postgres_user' => '0.0.0.0/0',
+        'ip_mask_all_users' => '0.0.0.0/0',
+        'listen_addresses' => '*',
+        'manage_redhat_firewall' => true,
+        'postgres_password' => 'postgres',
+    },
+}
+
+postgresql::database{ ['test1', 'test2', 'test3']:
+  # TODO: ensure not yet supported
+  #ensure  => present,
+  charset => 'utf8',
+  require => Class['postgresql::server'],
+}
+postgresql::database{ 'test4':
+  # TODO: ensure not yet supported
+  #ensure  => present,
+  charset => 'latin1',
+  require => Class['postgresql::server'],
+}

+ 14 - 0
tests/postgresql_grant.pp

@@ -0,0 +1,14 @@
+# TODO: in mysql module, the grant resource name might look like this: 'user@host/dbname';
+#  I think that the API for the resource type should split these up, because it's
+#  easier / safer to recombine them for mysql than it is to parse them for other
+#  databases.  Also, in the mysql module, the hostname portion of that string
+#  affects the user's ability to connect from remote hosts.  In postgres this is
+#  managed via pg_hba.conf; not sure if we want to try to reconcile that difference
+#  in the modules or not.
+postgresql::database_grant{'test1':
+    # TODO: mysql supports an array of privileges here.  We should do that if we
+    #  port this to ruby.
+    privilege   => 'ALL',
+    db          => 'test1',
+    role        => 'dan',
+}

+ 28 - 0
tests/postgresql_user.pp

@@ -0,0 +1,28 @@
+class { 'postgresql::server':
+    config_hash => {
+        'ip_mask_postgres_user' => '0.0.0.0/0',
+        'ip_mask_all_users' => '0.0.0.0/0',
+        'listen_addresses' => '*',
+        'manage_redhat_firewall' => true,
+        'postgres_password' => 'postgres',
+    },
+}
+
+# TODO: in mysql module, the username includes, e.g., '@%' or '@localhost', which
+#  affects the user's ability to connect from remote hosts.  In postgres this is
+#  managed via pg_hba.conf; not sure if we want to try to reconcile that difference
+#  in the modules or not.
+postgresql::database_user{ 'redmine':
+  # TODO: ensure is not yet supported
+  #ensure        => present,
+  password_hash => postgresql_password('redmine', 'redmine'),
+  require       => Class['postgresql::server'],
+}
+
+postgresql::database_user{ 'dan':
+  # TODO: ensure is not yet supported
+  #ensure        => present,
+  password_hash => postgresql_password('dan', 'blah'),
+  require       => Class['postgresql::server'],
+}
+