Browse Source

(MODULES-3247) Enable schema and database ownership change

Currently postgresql::server::schema, postgresql::server::db and
postgresql::server::database allow creating new schemas and
databases if they don't already exist and assigning owners to
them. This patch enables changing the owner of a schema or database
that already exists if the change_ownership variable is set to true.
Nate Potter 7 years ago
parent
commit
82c6716d48

+ 15 - 3
README.md

@@ -792,7 +792,7 @@ Defines the value for the setting.
 
 #### postgresql::server::db
 
-Creates a local database, user, and assigns necessary permissions.
+Creates or modifies a local database, user, and assigns necessary permissions.
 
 ##### `comment`
 
@@ -842,9 +842,13 @@ Specifies the name of the template database from which to build this database. D
 
 User to create and assign access to the database upon creation. Mandatory.
 
+##### `change_ownership`
+
+Specifies whether to create a new database or change the owner of an existing one. Default: false.
+
 #### postgresql::server::database
 
-Creates a database with no users and no permissions.
+Creates or modifies a database with no users and no permissions.
 
 ##### `dbname`
 
@@ -874,6 +878,10 @@ Sets tablespace for where to create this database. Default: The defaults defined
 
 Specifies the name of the template database from which to build this database. Default: `template0`.
 
+##### `change_ownership`
+
+Specifies whether to create a new database or change the owner of an existing one. Default: false.
+
 #### 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.
@@ -1114,7 +1122,7 @@ Defines the username of the role to create. Defaults to the namevar.
 
 #### postgresql::server::schema
 
-Creates a schema.
+Creates or modifies a schema.
 
 ##### `connect_settings`
 
@@ -1132,6 +1140,10 @@ Sets the default owner of the schema.
 
 Sets the name of the schema. Defaults to the namevar.
 
+##### `change_ownership`
+
+Specifies whether to create a new schema or change the owner of an existing one. Default: false.
+
 #### postgresql::server::table_grant
 
 Manages grant-based access privileges for users. Consult the PostgreSQL documentation for `grant` for more information.

+ 71 - 56
manifests/server/database.pp

@@ -9,6 +9,7 @@ define postgresql::server::database(
   $locale           = $postgresql::server::locale,
   $istemplate       = false,
   $connect_settings = $postgresql::server::default_connect_settings,
+  $change_ownership = false,
 ) {
   $createdb_path = $postgresql::server::createdb_path
   $user          = $postgresql::server::user
@@ -40,73 +41,87 @@ define postgresql::server::database(
     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}'",
+  if $change_ownership {
+    # Change owner for existing database
+    if !$owner {
+      fail('Must specify an owner to change database ownership.')
+    }
+    postgresql_psql { "Change owner of db '${dbname}' to ${owner}":
+      command => "ALTER DATABASE \"${dbname}\" OWNER TO ${owner}",
+      onlyif  => "SELECT datname FROM pg_database WHERE datname='${dbname}'",
+      db      => $default_db,
+      require => Class['postgresql::server::service']
     }
-    $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}'",
-  }
+    # Create a new database
+    # 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'
+    }
 
-  $tablespace_option = $tablespace ? {
-    undef   => '',
-    default => "TABLESPACE=\"${tablespace}\"",
-  }
+    $template_option = $template ? {
+      undef   => '',
+      default => "TEMPLATE=\"${template}\"",
+    }
 
-  if $createdb_path != undef{
-    warning('Passing "createdb_path" to postgresql::database is deprecated, it can be removed safely for the same behaviour')
-  }
+    $encoding_option = $encoding ? {
+      undef   => '',
+      default => "ENCODING='${encoding}'",
+    }
 
-  postgresql_psql { "Create db '${dbname}'":
-    command => "CREATE DATABASE \"${dbname}\" WITH OWNER=\"${owner}\" ${template_option} ${encoding_option} ${locale_option} ${tablespace_option}",
-    unless  => "SELECT datname FROM pg_database WHERE datname='${dbname}'",
-    db      => $default_db,
-    require => Class['postgresql::server::service']
-  }~>
+    $tablespace_option = $tablespace ? {
+      undef   => '',
+      default => "TABLESPACE=\"${tablespace}\"",
+    }
 
-  # This will prevent users from connecting to the database unless they've been
-  #  granted privileges.
-  postgresql_psql {"REVOKE ${public_revoke_privilege} ON DATABASE \"${dbname}\" FROM public":
-    db          => $default_db,
-    refreshonly => true,
-  }
+    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 db '${dbname}'" ]->
-  postgresql_psql {"UPDATE pg_database SET datistemplate = ${istemplate} WHERE datname = '${dbname}'":
-    unless => "SELECT datname FROM pg_database WHERE datname = '${dbname}' AND datistemplate = ${istemplate}",
-    db     => $default_db,
-  }
+    postgresql_psql { "Create db '${dbname}'":
+      command => "CREATE DATABASE \"${dbname}\" WITH OWNER=\"${owner}\" ${template_option} ${encoding_option} ${locale_option} ${tablespace_option}",
+      unless  => "SELECT datname FROM pg_database WHERE datname='${dbname}'",
+      db      => $default_db,
+      require => Class['postgresql::server::service']
+    }~>
 
-  if $comment {
-    # The shobj_description function was only introduced with 8.2
-    $comment_information_function =  $version ? {
-      '8.1'   => 'obj_description',
-      default => 'shobj_description',
+    # This will prevent users from connecting to the database unless they've been
+    #  granted privileges.
+    postgresql_psql {"REVOKE ${public_revoke_privilege} ON DATABASE \"${dbname}\" FROM public":
+      db          => $default_db,
+      refreshonly => true,
     }
+
     Postgresql_psql[ "Create db '${dbname}'" ]->
-    postgresql_psql {"COMMENT ON DATABASE \"${dbname}\" IS '${comment}'":
-      unless => "SELECT pg_catalog.${comment_information_function}(d.oid, 'pg_database') as \"Description\" FROM pg_catalog.pg_database d WHERE datname = '${dbname}' AND pg_catalog.${comment_information_function}(d.oid, 'pg_database') = '${comment}'",
-      db     => $dbname,
+    postgresql_psql {"UPDATE pg_database SET datistemplate = ${istemplate} WHERE datname = '${dbname}'":
+      unless => "SELECT datname FROM pg_database WHERE datname = '${dbname}' AND datistemplate = ${istemplate}",
+      db     => $default_db,
     }
-  }
 
-  # Build up dependencies on tablespace
-  if($tablespace != undef and defined(Postgresql::Server::Tablespace[$tablespace])) {
-    Postgresql::Server::Tablespace[$tablespace]->Postgresql_psql[ "Create db '${dbname}'" ]
+    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 db '${dbname}'" ]->
+      postgresql_psql {"COMMENT ON DATABASE \"${dbname}\" IS '${comment}'":
+        unless => "SELECT pg_catalog.${comment_information_function}(d.oid, 'pg_database') as \"Description\" FROM pg_catalog.pg_database d WHERE datname = '${dbname}' AND pg_catalog.${comment_information_function}(d.oid, 'pg_database') = '${comment}'",
+        db     => $dbname,
+      }
+    }
+
+    # Build up dependencies on tablespace
+    if($tablespace != undef and defined(Postgresql::Server::Tablespace[$tablespace])) {
+      Postgresql::Server::Tablespace[$tablespace]->Postgresql_psql[ "Create db '${dbname}'" ]
+    }
   }
 }

+ 18 - 16
manifests/server/db.pp

@@ -3,26 +3,28 @@
 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
+  $comment          = undef,
+  $dbname           = $title,
+  $encoding         = $postgresql::server::encoding,
+  $locale           = $postgresql::server::locale,
+  $grant            = 'ALL',
+  $tablespace       = undef,
+  $template         = 'template0',
+  $istemplate       = false,
+  $owner            = undef,
+  $change_ownership = false,
 ) {
 
   if ! defined(Postgresql::Server::Database[$dbname]) {
     postgresql::server::database { $dbname:
-      comment    => $comment,
-      encoding   => $encoding,
-      tablespace => $tablespace,
-      template   => $template,
-      locale     => $locale,
-      istemplate => $istemplate,
-      owner      => $owner,
+      comment          => $comment,
+      encoding         => $encoding,
+      tablespace       => $tablespace,
+      template         => $template,
+      locale           => $locale,
+      istemplate       => $istemplate,
+      owner            => $owner,
+      change_ownership => $change_ownership,
     }
   }
 

+ 23 - 8
manifests/server/schema.pp

@@ -17,6 +17,7 @@ define postgresql::server::schema(
   $owner  = undef,
   $schema = $title,
   $connect_settings = $postgresql::server::default_connect_settings,
+  $change_ownership = false,
 ) {
   $user      = $postgresql::server::user
   $group     = $postgresql::server::group
@@ -39,19 +40,33 @@ define postgresql::server::schema(
     connect_settings => $connect_settings,
   }
 
-  $schema_title   = "Create Schema '${title}'"
+  $schema_exists = "SELECT nspname FROM pg_namespace WHERE nspname='${schema}'"
   $authorization = $owner? {
     undef   => '',
     default => "AUTHORIZATION \"${owner}\"",
   }
 
-  $schema_command = "CREATE SCHEMA \"${schema}\" ${authorization}"
-  $unless         = "SELECT nspname FROM pg_namespace WHERE nspname='${schema}'"
-
-  postgresql_psql { $schema_title:
-    command => $schema_command,
-    unless  => $unless,
-    require => Class['postgresql::server'],
+  if $change_ownership {
+    # Change owner for existing schema
+    if !$owner {
+      fail('Must specify an owner to change schema ownership.')
+    }
+    $schema_title   = "Change owner of schema '${schema}' to ${owner}"
+    $schema_command = "ALTER SCHEMA \"${schema}\" OWNER TO ${owner}"
+    postgresql_psql { $schema_title:
+      command => $schema_command,
+      onlyif  => $schema_exists,
+      require => Class['postgresql::server'],
+    }
+  } else {
+    # Create a new schema
+    $schema_title   = "Create Schema '${title}'"
+    $schema_command = "CREATE SCHEMA \"${schema}\" ${authorization}"
+    postgresql_psql { $schema_title:
+      command => $schema_command,
+      unless  => $schema_exists,
+      require => Class['postgresql::server'],
+    }
   }
 
   if($owner != undef and defined(Postgresql::Server::Role[$owner])) {

+ 7 - 0
spec/unit/defines/server/database_spec.rb

@@ -69,4 +69,11 @@ describe 'postgresql::server::database', :type => :define do
     it { is_expected.to contain_postgresql_psql("Create db 'test'").with_connect_settings( { 'PGHOST'    => 'postgres-db-server','DBVERSION' => '9.2','PGPORT'    => '1234' } ).with_port( nil ) }
 
   end
+
+  context "with change_ownership set to true" do
+    let (:params) {{ :change_ownership => true,
+                     :owner            => 'test_owner' }}
+
+    it { is_expected.to contain_postgresql_psql("Change owner of db 'test' to test_owner") }
+  end
 end

+ 12 - 0
spec/unit/defines/server/schema_spec.rb

@@ -29,4 +29,16 @@ describe 'postgresql::server::schema', :type => :define do
   end
 
   it { should contain_postgresql__server__schema('test') }
+
+  context "with change_ownership set to true" do
+    let :params do
+      {
+        :owner            => 'nate',
+        :db               => 'natedb',
+        :change_ownership => true,
+      }
+    end
+
+    it { is_expected.to contain_postgresql_psql("Change owner of schema 'test' to nate") }
+  end
 end