Modernise postgresql LWRPs
authorTom Hughes <tom@compton.nu>
Thu, 23 Nov 2017 18:36:37 +0000 (18:36 +0000)
committerTom Hughes <tom@compton.nu>
Thu, 23 Nov 2017 19:14:02 +0000 (19:14 +0000)
15 files changed:
cookbooks/postgresql/libraries/postgresql.rb
cookbooks/postgresql/providers/database.rb [deleted file]
cookbooks/postgresql/providers/execute.rb [deleted file]
cookbooks/postgresql/providers/extension.rb [deleted file]
cookbooks/postgresql/providers/munin.rb [deleted file]
cookbooks/postgresql/providers/table.rb [deleted file]
cookbooks/postgresql/providers/tablespace.rb [deleted file]
cookbooks/postgresql/providers/user.rb [deleted file]
cookbooks/postgresql/resources/database.rb
cookbooks/postgresql/resources/execute.rb
cookbooks/postgresql/resources/extension.rb
cookbooks/postgresql/resources/munin.rb
cookbooks/postgresql/resources/table.rb
cookbooks/postgresql/resources/tablespace.rb
cookbooks/postgresql/resources/user.rb

index 70d3813..feaa508 100644 (file)
@@ -1,6 +1,6 @@
 require "chef/mixin/shell_out"
 
-class Chef
+module OpenStreetMap
   class PostgreSQL
     include Chef::Mixin::ShellOut
 
diff --git a/cookbooks/postgresql/providers/database.rb b/cookbooks/postgresql/providers/database.rb
deleted file mode 100644 (file)
index 1a8402b..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# Cookbook Name:: postgresql
-# Provider:: postgresql_database
-#
-# Copyright 2012, OpenStreetMap Foundation
-#
-# 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.
-#
-
-use_inline_resources
-
-def load_current_resource
-  @pg = Chef::PostgreSQL.new(new_resource.cluster)
-
-  @current_resource = Chef::Resource::PostgresqlDatabase.new(new_resource.name)
-  @current_resource.database(new_resource.database)
-  @current_resource.cluster(new_resource.cluster)
-  if (pg_database = @pg.databases[@current_resource.database])
-    @current_resource.owner(pg_database[:owner])
-    @current_resource.encoding(pg_database[:encoding])
-    @current_resource.encoding(pg_database[:collate])
-    @current_resource.encoding(pg_database[:ctype])
-  end
-  @current_resource
-end
-
-action :create do
-  if !@pg.databases.include?(new_resource.database)
-    converge_by "create database #{new_resource.database}" do
-      @pg.execute(:command => "CREATE DATABASE \"#{new_resource.database}\" OWNER \"#{new_resource.owner}\" TEMPLATE template0 ENCODING '#{new_resource.encoding}' LC_COLLATE '#{new_resource.collation}' LC_CTYPE '#{new_resource.ctype}'")
-    end
-  elsif new_resource.owner != @current_resource.owner
-    converge_by "alter database #{new_resource.database}" do
-      @pg.execute(:command => "ALTER DATABASE \"#{new_resource.database}\" OWNER TO \"#{new_resource.owner}\"")
-    end
-  end
-end
-
-action :drop do
-  if @pg.databases.include?(new_resource.database)
-    converge_by "drop database #{new_resource.database}" do
-      @pg.execute(:command => "DROP DATABASE \"#{new_resource.database}\"")
-    end
-  end
-end
diff --git a/cookbooks/postgresql/providers/execute.rb b/cookbooks/postgresql/providers/execute.rb
deleted file mode 100644 (file)
index c50cb27..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Cookbook Name:: postgresql
-# Provider:: postgresql_execute
-#
-# Copyright 2012, OpenStreetMap Foundation
-#
-# 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.
-#
-
-use_inline_resources
-
-def load_current_resource
-  @pg = Chef::PostgreSQL.new(new_resource.cluster)
-
-  @current_resource = Chef::Resource::PostgresqlExecute.new(new_resource.name)
-  @current_resource.cluster(new_resource.cluster)
-  @current_resource.database(new_resource.database)
-  @current_resource
-end
-
-action :nothing do
-end
-
-action :run do
-  options = { :database => new_resource.database, :user => new_resource.user, :group => new_resource.group }
-
-  converge_by "execute #{new_resource.command}" do
-    if ::File.exist?(new_resource.command)
-      @pg.execute(options.merge(:file => new_resource.command))
-    else
-      @pg.execute(options.merge(:command => new_resource.command))
-    end
-  end
-end
diff --git a/cookbooks/postgresql/providers/extension.rb b/cookbooks/postgresql/providers/extension.rb
deleted file mode 100644 (file)
index 8758069..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# Cookbook Name:: postgresql
-# Provider:: postgresql_extension
-#
-# Copyright 2012, OpenStreetMap Foundation
-#
-# 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.
-#
-
-use_inline_resources
-
-def load_current_resource
-  @pg = Chef::PostgreSQL.new(new_resource.cluster)
-
-  @current_resource = Chef::Resource::PostgresqlExtension.new(new_resource.name)
-  @current_resource.extension(new_resource.extension)
-  @current_resource.cluster(new_resource.cluster)
-  @current_resource.database(new_resource.database)
-  @current_resource
-end
-
-action :create do
-  unless @pg.extensions(new_resource.database).include?(new_resource.extension)
-    converge_by "create extension #{new_resource.extension}" do
-      @pg.execute(:command => "CREATE EXTENSION #{new_resource.extension}", :database => new_resource.database)
-    end
-  end
-end
-
-action :drop do
-  if @pg.extensions(new_resource.database).include?(new_resource.extension)
-    converge_by "drop extension #{new_resource.extension}" do
-      @pg.execute(:command => "DROP EXTENSION #{new_resource.extension}", :database => new_resource.database)
-    end
-  end
-end
diff --git a/cookbooks/postgresql/providers/munin.rb b/cookbooks/postgresql/providers/munin.rb
deleted file mode 100644 (file)
index efa0a8b..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# Cookbook Name:: postgresql
-# Provider:: postgresql_munin
-#
-# Copyright 2015, OpenStreetMap Foundation
-#
-# 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.
-#
-
-def whyrun_supported?
-  true
-end
-
-use_inline_resources
-
-action :create do
-  cluster = node[:postgresql][:clusters] && node[:postgresql][:clusters][new_resource.cluster]
-  database = new_resource.database
-
-  if cluster
-    %w[cache connections locks querylength scans size transactions tuples].each do |plugin|
-      munin_plugin "postgres_#{plugin}_#{database}:#{suffix}" do
-        target "postgres_#{plugin}_"
-        conf "munin.erb"
-        conf_cookbook "postgresql"
-        conf_variables :port => cluster[:port]
-        restart_munin false
-      end
-    end
-  else
-    Chef::Log.info "Postgres cluster #{new_resource.cluster} not found"
-  end
-end
-
-action :delete do
-  database = new_resource.database
-
-  %w[cache connections locks querylength scans size transactions tuples].each do |plugin|
-    munin_plugin "postgres_#{plugin}_#{database}:#{suffix}" do
-      action :delete
-      restart_munin false
-    end
-  end
-end
-
-def suffix
-  new_resource.cluster.tr("/", ":")
-end
diff --git a/cookbooks/postgresql/providers/table.rb b/cookbooks/postgresql/providers/table.rb
deleted file mode 100644 (file)
index 495bf8b..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#
-# Cookbook Name:: postgresql
-# Provider:: postgresql_table
-#
-# Copyright 2013, OpenStreetMap Foundation
-#
-# 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.
-#
-
-use_inline_resources
-
-def load_current_resource
-  @pg = Chef::PostgreSQL.new(new_resource.cluster)
-  @tables = @pg.tables(new_resource.database)
-  @name = "#{new_resource.schema}.#{new_resource.name}"
-
-  @current_resource = Chef::Resource::PostgresqlTable.new(new_resource.name)
-  @current_resource.cluster(new_resource.cluster)
-  @current_resource.database(new_resource.database)
-  @current_resource.schema(new_resource.schema)
-  if (pg_table = @tables[@name])
-    @current_resource.owner(pg_table[:owner])
-    @current_resource.permissions(pg_table[:permissions])
-  end
-  @current_resource
-end
-
-action :create do
-  if @tables.include?(@name)
-    if new_resource.owner != @current_resource.owner
-      converge_by("set owner for #{new_resource} to #{new_resource.owner}") do
-        Chef::Log.info("Setting owner for #{new_resource} to #{new_resource.owner}")
-        @pg.execute(:command => "ALTER TABLE #{@name} OWNER TO \"#{new_resource.owner}\"", :database => new_resource.database)
-      end
-    end
-
-    @current_resource.permissions.each_key do |user|
-      next if new_resource.permissions[user]
-
-      converge_by("revoke all for #{user} on #{new_resource}") do
-        Chef::Log.info("Revoking all for #{user} on #{new_resource}")
-        @pg.execute(:command => "REVOKE ALL ON #{@name} FROM \"#{user}\"", :database => new_resource.database)
-      end
-    end
-
-    new_resource.permissions.each do |user, new_privileges|
-      current_privileges = @current_resource.permissions[user] || {}
-      new_privileges = Array(new_privileges)
-
-      if new_privileges.include?(:all)
-        new_privileges |= Chef::PostgreSQL::TABLE_PRIVILEGES
-      end
-
-      Chef::PostgreSQL::TABLE_PRIVILEGES.each do |privilege|
-        if new_privileges.include?(privilege)
-          unless current_privileges.include?(privilege)
-            converge_by("grant #{privilege} for #{user} on #{new_resource}") do
-              Chef::Log.info("Granting #{privilege} for #{user} on #{new_resource}")
-              @pg.execute(:command => "GRANT #{privilege.to_s.upcase} ON #{@name} TO \"#{user}\"", :database => new_resource.database)
-            end
-          end
-        elsif current_privileges.include?(privilege)
-          converge_by("revoke #{privilege} for #{user} on #{new_resource}") do
-            Chef::Log.info("Revoking #{privilege} for #{user} on #{new_resource}")
-            @pg.execute(:command => "REVOKE #{privilege.to_s.upcase} ON #{@name} FROM \"#{user}\"", :database => new_resource.database)
-          end
-        end
-      end
-    end
-  end
-end
-
-action :drop do
-  if @tables.include?(@name)
-    converge_by("drop #{new_resource}") do
-      Chef::Log.info("Dropping #{new_resource}")
-      @pg.execute(:command => "DROP TABLE #{@name}", :database => new_resource.database)
-    end
-  end
-end
diff --git a/cookbooks/postgresql/providers/tablespace.rb b/cookbooks/postgresql/providers/tablespace.rb
deleted file mode 100644 (file)
index 22ff396..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Cookbook Name:: postgresql
-# Provider:: postgresql_tablespace
-#
-# Copyright 2016, OpenStreetMap Foundation
-#
-# 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.
-#
-
-use_inline_resources
-
-def load_current_resource
-  @pg = Chef::PostgreSQL.new(new_resource.cluster)
-
-  @current_resource = Chef::Resource::PostgresqlTablespace.new(new_resource.name)
-  @current_resource.tablespace(new_resource.tablespace)
-  @current_resource.location(new_resource.location)
-  @current_resource
-end
-
-action :create do
-  unless @pg.tablespaces.include?(new_resource.tablespace)
-    converge_by "create tablespace #{new_resource.tablespace}" do
-      @pg.execute(:command => "CREATE TABLESPACE #{new_resource.tablespace} LOCATION '#{new_resource.location}'")
-    end
-  end
-end
-
-action :drop do
-  if @pg.tablespaces.include?(new_resource.tablespace)
-    converge_by "drop tablespace #{new_resource.tablespace}" do
-      @pg.execute(:command => "DROP TABLESPACE #{new_resource.tablespace}")
-    end
-  end
-end
diff --git a/cookbooks/postgresql/providers/user.rb b/cookbooks/postgresql/providers/user.rb
deleted file mode 100644 (file)
index 22d01a4..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#
-# Cookbook Name:: postgresql
-# Provider:: postgresql_user
-#
-# Copyright 2012, OpenStreetMap Foundation
-#
-# 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.
-#
-
-require "shellwords"
-
-use_inline_resources
-
-def load_current_resource
-  @pg = Chef::PostgreSQL.new(new_resource.cluster)
-
-  @current_resource = Chef::Resource::PostgresqlUser.new(new_resource.name)
-  @current_resource.user(new_resource.user)
-  @current_resource.cluster(new_resource.cluster)
-  if (pg_user = @pg.users[@current_resource.user])
-    @current_resource.superuser(pg_user[:superuser])
-    @current_resource.createdb(pg_user[:createdb])
-    @current_resource.createrole(pg_user[:createrole])
-    @current_resource.replication(pg_user[:replication])
-  end
-  @current_resource
-end
-
-action :create do
-  password = new_resource.password ? "ENCRYPTED PASSWORD '#{new_resource.password.shellescape}'" : ""
-  superuser = new_resource.superuser ? "SUPERUSER" : "NOSUPERUSER"
-  createdb = new_resource.createdb ? "CREATEDB" : "NOCREATEDB"
-  createrole = new_resource.createrole ? "CREATEROLE" : "NOCREATEROLE"
-  replication = new_resource.replication ? "REPLICATION" : "NOREPLICATION"
-
-  if !@pg.users.include?(new_resource.user)
-    converge_by "create role #{new_resource.user}" do
-      @pg.execute(:command => "CREATE ROLE \"#{new_resource.user}\" LOGIN #{password} #{superuser} #{createdb} #{createrole}")
-    end
-  else
-    if new_resource.superuser != @current_resource.superuser
-      converge_by "alter role #{new_resource.user}" do
-        @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{superuser}")
-      end
-    end
-
-    unless new_resource.superuser
-      if new_resource.createdb != @current_resource.createdb
-        converge_by "alter role #{new_resource.user}" do
-          @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{createdb}")
-        end
-      end
-
-      if new_resource.createrole != @current_resource.createrole
-        converge_by "alter role #{new_resource.user}" do
-          @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{createrole}")
-        end
-      end
-
-      if new_resource.replication != @current_resource.replication
-        converge_by "alter role #{new_resource.user}" do
-          @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{replication}")
-        end
-      end
-    end
-  end
-end
-
-action :drop do
-  if @pg.users.include?(new_resource.user)
-    converge_by "drop role #{new_resource.user}" do
-      @pg.execute(:command => "DROP ROLE \"#{new_resource.user}\"")
-    end
-  end
-end
index 1e8f397..5e35b39 100644 (file)
 
 default_action :create
 
-actions :create, :drop
+property :database, :kind_of => String, :name_attribute => true
+property :cluster, :kind_of => String, :required => true
+property :owner, :kind_of => String, :required => true
+property :encoding, :kind_of => String, :default => "UTF8"
+property :collation, :kind_of => String, :default => "en_GB.UTF8"
+property :ctype, :kind_of => String, :default => "en_GB.UTF8"
 
-attribute :database, :kind_of => String, :name_attribute => true
-attribute :cluster, :kind_of => String, :required => true
-attribute :owner, :kind_of => String, :required => true
-attribute :encoding, :kind_of => String, :default => "UTF8"
-attribute :collation, :kind_of => String, :default => "en_GB.UTF8"
-attribute :ctype, :kind_of => String, :default => "en_GB.UTF8"
+action :create do
+  if !cluster.databases.include?(new_resource.database)
+    converge_by "create database #{new_resource.database}" do
+      cluster.execute(:command => "CREATE DATABASE \"#{new_resource.database}\" OWNER \"#{new_resource.owner}\" TEMPLATE template0 ENCODING '#{new_resource.encoding}' LC_COLLATE '#{new_resource.collation}' LC_CTYPE '#{new_resource.ctype}'")
+    end
+  elsif new_resource.owner != cluster.databases[new_resource.database][:owner]
+    converge_by "alter database #{new_resource.database}" do
+      cluster.execute(:command => "ALTER DATABASE \"#{new_resource.database}\" OWNER TO \"#{new_resource.owner}\"")
+    end
+  end
+end
+
+action :drop do
+  if cluster.databases.include?(new_resource.database)
+    converge_by "drop database #{new_resource.database}" do
+      cluster.execute(:command => "DROP DATABASE \"#{new_resource.database}\"")
+    end
+  end
+end
+
+action_class do
+  def cluster
+    @cluster ||= OpenStreetMap::PostgreSQL.new(new_resource.cluster)
+  end
+end
index f01e219..6295955 100644 (file)
 
 default_action :run
 
-actions :nothing, :run
+property :command, :kind_of => String, :name_attribute => true
+property :cluster, :kind_of => String, :required => true
+property :database, :kind_of => String, :required => true
+property :user, :default => "postgres"
+property :group, :default => "postgres"
 
-attribute :command, :kind_of => String, :name_attribute => true
-attribute :cluster, :kind_of => String, :required => true
-attribute :database, :kind_of => String, :required => true
-attribute :user, :default => "postgres"
-attribute :group, :default => "postgres"
+action :nothing do
+end
+
+action :run do
+  options = { :database => new_resource.database, :user => new_resource.user, :group => new_resource.group }
+
+  converge_by "execute #{new_resource.command}" do
+    if ::File.exist?(new_resource.command)
+      cluster.execute(options.merge(:file => new_resource.command))
+    else
+      cluster.execute(options.merge(:command => new_resource.command))
+    end
+  end
+end
+
+action_class do
+  def cluster
+    @cluster ||= OpenStreetMap::PostgreSQL.new(new_resource.cluster)
+  end
+end
index a136342..3be1a72 100644 (file)
 
 default_action :create
 
-actions :create, :drop
+property :extension, :kind_of => String, :name_attribute => true
+property :cluster, :kind_of => String, :required => true
+property :database, :kind_of => String, :required => true
 
-attribute :extension, :kind_of => String, :name_attribute => true
-attribute :cluster, :kind_of => String, :required => true
-attribute :database, :kind_of => String, :required => true
+action :create do
+  unless cluster.extensions(new_resource.database).include?(new_resource.extension)
+    converge_by "create extension #{new_resource.extension}" do
+      cluster.execute(:command => "CREATE EXTENSION #{new_resource.extension}", :database => new_resource.database)
+    end
+  end
+end
+
+action :drop do
+  if cluster.extensions(new_resource.database).include?(new_resource.extension)
+    converge_by "drop extension #{new_resource.extension}" do
+      cluster.execute(:command => "DROP EXTENSION #{new_resource.extension}", :database => new_resource.database)
+    end
+  end
+end
+
+action_class do
+  def cluster
+    @cluster ||= OpenStreetMap::PostgreSQL.new(new_resource.cluster)
+  end
+end
index aa4f8c8..78bbacb 100644 (file)
 # limitations under the License.
 #
 
-actions :create, :delete
 default_action :create
 
-attribute :name, :kind_of => String, :name_attribute => true
-attribute :cluster, :kind_of => String, :required => true
-attribute :database, :kind_of => String, :required => true
+property :munin, :kind_of => String, :name_attribute => true
+property :cluster, :kind_of => String, :required => true
+property :database, :kind_of => String, :required => true
+
+action :create do
+  cluster = node[:postgresql][:clusters] && node[:postgresql][:clusters][new_resource.cluster]
+  database = new_resource.database
+
+  if cluster
+    %w[cache connections locks querylength scans size transactions tuples].each do |plugin|
+      munin_plugin "postgres_#{plugin}_#{database}:#{suffix}" do
+        target "postgres_#{plugin}_"
+        conf "munin.erb"
+        conf_cookbook "postgresql"
+        conf_variables :port => cluster[:port]
+        restart_munin false
+      end
+    end
+  else
+    Chef::Log.info "Postgres cluster #{new_resource.cluster} not found"
+  end
+end
+
+action :delete do
+  database = new_resource.database
+
+  %w[cache connections locks querylength scans size transactions tuples].each do |plugin|
+    munin_plugin "postgres_#{plugin}_#{database}:#{suffix}" do
+      action :delete
+      restart_munin false
+    end
+  end
+end
+
+action_class do
+  def suffix
+    new_resource.cluster.tr("/", ":")
+  end
+end
 
 def after_created
   notifies :restart, "service[munin-node]"
index 9bf1fe1..d8dde97 100644 (file)
 # limitations under the License.
 #
 
-actions :create, :drop
 default_action :create
 
-attribute :table, :kind_of => String, :name_attribute => true
-attribute :cluster, :kind_of => String, :required => true
-attribute :database, :kind_of => String, :required => true
-attribute :schema, :kind_of => String, :default => "public"
-attribute :owner, :kind_of => String, :required => true
-attribute :permissions, :kind_of => Hash, :default => {}
+property :table, :kind_of => String, :name_attribute => true
+property :cluster, :kind_of => String, :required => true
+property :database, :kind_of => String, :required => true
+property :schema, :kind_of => String, :default => "public"
+property :owner, :kind_of => String, :required => true
+property :permissions, :kind_of => Hash, :default => {}
+
+action :create do
+  if tables.include?(qualified_name)
+    if new_resource.owner != tables[qualified_name][:owner]
+      converge_by("set owner for #{new_resource} to #{new_resource.owner}") do
+        Chef::Log.info("Setting owner for #{new_resource} to #{new_resource.owner}")
+        cluster.execute(:command => "ALTER TABLE #{qualified_name} OWNER TO \"#{new_resource.owner}\"", :database => new_resource.database)
+      end
+    end
+
+    tables[qualified_name][:permissions].each_key do |user|
+      next if new_resource.permissions[user]
+
+      converge_by("revoke all for #{user} on #{new_resource}") do
+        Chef::Log.info("Revoking all for #{user} on #{new_resource}")
+        cluster.execute(:command => "REVOKE ALL ON #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
+      end
+    end
+
+    new_resource.permissions.each do |user, new_privileges|
+      current_privileges = tables[qualified_name][:permissions][user] || {}
+      new_privileges = Array(new_privileges)
+
+      if new_privileges.include?(:all)
+        new_privileges |= OpenStreetMap::PostgreSQL::TABLE_PRIVILEGES
+      end
+
+      OpenStreetMap::PostgreSQL::TABLE_PRIVILEGES.each do |privilege|
+        if new_privileges.include?(privilege)
+          unless current_privileges.include?(privilege)
+            converge_by("grant #{privilege} for #{user} on #{new_resource}") do
+              Chef::Log.info("Granting #{privilege} for #{user} on #{new_resource}")
+              cluster.execute(:command => "GRANT #{privilege.to_s.upcase} ON #{qualified_name} TO \"#{user}\"", :database => new_resource.database)
+            end
+          end
+        elsif current_privileges.include?(privilege)
+          converge_by("revoke #{privilege} for #{user} on #{new_resource}") do
+            Chef::Log.info("Revoking #{privilege} for #{user} on #{new_resource}")
+            cluster.execute(:command => "REVOKE #{privilege.to_s.upcase} ON #{qualified_name} FROM \"#{user}\"", :database => new_resource.database)
+          end
+        end
+      end
+    end
+  end
+end
+
+action :drop do
+  if tables.include?(qualified_name)
+    converge_by("drop #{new_resource}") do
+      Chef::Log.info("Dropping #{new_resource}")
+      cluster.execute(:command => "DROP TABLE #{qualified_name}", :database => new_resource.database)
+    end
+  end
+end
+
+action_class do
+  def cluster
+    @cluster ||= OpenStreetMap::PostgreSQL.new(new_resource.cluster)
+  end
+
+  def tables
+    @tables ||= cluster.tables(new_resource.database)
+  end
+
+  def qualified_name
+    "#{new_resource.schema}.#{new_resource.name}"
+  end
+end
index 93bb021..c0e9f5a 100644 (file)
 
 default_action :create
 
-actions :create, :drop
+property :tablespace, :kind_of => String, :name_attribute => true
+property :cluster, :kind_of => String, :required => true
+property :location, :kind_of => String, :required => true
 
-attribute :tablespace, :kind_of => String, :name_attribute => true
-attribute :cluster, :kind_of => String, :required => true
-attribute :location, :kind_of => String, :required => true
+action :create do
+  unless cluster.tablespaces.include?(new_resource.tablespace)
+    converge_by "create tablespace #{new_resource.tablespace}" do
+      cluster.execute(:command => "CREATE TABLESPACE #{new_resource.tablespace} LOCATION '#{new_resource.location}'")
+    end
+  end
+end
+
+action :drop do
+  if cluster.tablespaces.include?(new_resource.tablespace)
+    converge_by "drop tablespace #{new_resource.tablespace}" do
+      cluster.execute(:command => "DROP TABLESPACE #{new_resource.tablespace}")
+    end
+  end
+end
+
+action_class do
+  def cluster
+    @cluster ||= OpenStreetMap::PostgreSQL.new(new_resource.cluster)
+  end
+end
index 5cbb94d..6aac6f2 100644 (file)
 # limitations under the License.
 #
 
+require "shellwords"
+
 default_action :create
 
-actions :create, :drop
+property :user, :kind_of => String, :name_attribute => true
+property :cluster, :kind_of => String, :required => true
+property :password, :kind_of => String
+property :superuser, :default => false
+property :createdb, :default => false
+property :createrole, :default => false
+property :replication, :default => false
+
+action :create do
+  password = new_resource.password ? "ENCRYPTED PASSWORD '#{new_resource.password.shellescape}'" : ""
+  superuser = new_resource.superuser ? "SUPERUSER" : "NOSUPERUSER"
+  createdb = new_resource.createdb ? "CREATEDB" : "NOCREATEDB"
+  createrole = new_resource.createrole ? "CREATEROLE" : "NOCREATEROLE"
+  replication = new_resource.replication ? "REPLICATION" : "NOREPLICATION"
+
+  if !cluster.users.include?(new_resource.user)
+    converge_by "create role #{new_resource.user}" do
+      cluster.execute(:command => "CREATE ROLE \"#{new_resource.user}\" LOGIN #{password} #{superuser} #{createdb} #{createrole}")
+    end
+  else
+    current_user = cluster.users[new_resource.user]
+
+    if new_resource.superuser != current_user[:superuser]
+      converge_by "alter role #{new_resource.user}" do
+        cluster.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{superuser}")
+      end
+    end
+
+    unless new_resource.superuser
+      if new_resource.createdb != current_user[:createdb]
+        converge_by "alter role #{new_resource.user}" do
+          cluster.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{createdb}")
+        end
+      end
+
+      if new_resource.createrole != current_user[:createrole]
+        converge_by "alter role #{new_resource.user}" do
+          cluster.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{createrole}")
+        end
+      end
+
+      if new_resource.replication != current_user[:replication]
+        converge_by "alter role #{new_resource.user}" do
+          cluster.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{replication}")
+        end
+      end
+    end
+  end
+end
+
+action :drop do
+  if cluster.users.include?(new_resource.user)
+    converge_by "drop role #{new_resource.user}" do
+      cluster.execute(:command => "DROP ROLE \"#{new_resource.user}\"")
+    end
+  end
+end
 
-attribute :user, :kind_of => String, :name_attribute => true
-attribute :cluster, :kind_of => String, :required => true
-attribute :password, :kind_of => String
-attribute :superuser, :default => false
-attribute :createdb, :default => false
-attribute :createrole, :default => false
-attribute :replication, :default => false
+action_class do
+  def cluster
+    @cluster ||= OpenStreetMap::PostgreSQL.new(new_resource.cluster)
+  end
+end