]> git.openstreetmap.org Git - chef.git/blobdiff - cookbooks/postgresql/libraries/postgresql.rb
blogs: fix build in test
[chef.git] / cookbooks / postgresql / libraries / postgresql.rb
index 70d38135b7cbfa9c69cc32807f84325368b494d1..1a39da25a146bc6426ee9d694e1cc0f714da989c 100644 (file)
@@ -1,6 +1,6 @@
 require "chef/mixin/shell_out"
 
-class Chef
+module OpenStreetMap
   class PostgreSQL
     include Chef::Mixin::ShellOut
 
@@ -8,10 +8,18 @@ class Chef
       :select, :insert, :update, :delete, :truncate, :references, :trigger
     ].freeze
 
+    SEQUENCE_PRIVILEGES = [
+      :usage, :select, :update
+    ].freeze
+
     def initialize(cluster)
       @cluster = cluster
     end
 
+    def version
+      @cluster.split("/").first.to_f
+    end
+
     def execute(options)
       # Create argument array
       args = []
@@ -68,12 +76,13 @@ class Chef
     end
 
     def users
-      @users ||= query("SELECT * FROM pg_user").each_with_object({}) do |user, users|
+      @users ||= query("SELECT *, ARRAY(SELECT groname FROM pg_group WHERE usesysid = ANY(grolist)) AS roles FROM pg_user").each_with_object({}) do |user, users|
         users[user[:usename]] = {
           :superuser => user[:usesuper] == "t",
           :createdb => user[:usercreatedb] == "t",
           :createrole => user[:usecatupd] == "t",
-          :replication => user[:userepl] == "t"
+          :replication => user[:userepl] == "t",
+          :roles => parse_array(user[:roles] || "{}")
         }
       end
     end
@@ -108,7 +117,7 @@ class Chef
 
     def tables(database)
       @tables ||= {}
-      @tables[database] ||= query("SELECT n.nspname, c.relname, u.usename, c.relacl FROM pg_class AS c INNER JOIN pg_user AS u ON c.relowner = u.usesysid INNER JOIN pg_namespace AS n ON c.relnamespace = n.oid", :database => database).each_with_object({}) do |table, tables|
+      @tables[database] ||= query("SELECT n.nspname, c.relname, u.usename, c.relacl FROM pg_class AS c INNER JOIN pg_user AS u ON c.relowner = u.usesysid INNER JOIN pg_namespace AS n ON c.relnamespace = n.oid WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') AND c.relkind = 'r'", :database => database).each_with_object({}) do |table, tables|
         name = "#{table[:nspname]}.#{table[:relname]}"
 
         tables[name] = {
@@ -118,10 +127,26 @@ class Chef
       end
     end
 
+    def sequences(database)
+      @sequences ||= {}
+      @sequences[database] ||= query("SELECT n.nspname, c.relname, u.usename, c.relacl FROM pg_class AS c INNER JOIN pg_user AS u ON c.relowner = u.usesysid INNER JOIN pg_namespace AS n ON c.relnamespace = n.oid WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') AND c.relkind = 'S'", :database => database).each_with_object({}) do |sequence, sequences|
+        name = "#{sequence[:nspname]}.#{sequence[:relname]}"
+
+        sequences[name] = {
+          :owner => sequence[:usename],
+          :permissions => parse_acl(sequence[:relacl] || "{}")
+        }
+      end
+    end
+
     private
 
+    def parse_array(array)
+      array.sub(/^\{(.*)\}$/, "\\1").split(",")
+    end
+
     def parse_acl(acl)
-      acl.sub(/^\{(.*)\}$/, "\\1").split(",").each_with_object({}) do |entry, permissions|
+      parse_array(acl).each_with_object({}) do |entry, permissions|
         entry = entry.sub(/^"(.*)"$/) { Regexp.last_match[1].gsub(/\\"/, '"') }.sub(%r{/.*$}, "")
         user, privileges = entry.split("=")
 
@@ -129,8 +154,10 @@ class Chef
         user = "public" if user == ""
 
         permissions[user] = {
-          "a" => :insert, "r" => :select, "w" => :update, "d" => :delete,
-          "D" => :truncate, "x" => :references, "t" => :trigger
+          "r" => :select, "a" => :insert, "w" => :update, "d" => :delete,
+          "D" => :truncate, "x" => :references, "t" => :trigger,
+          "C" => :create, "c" => :connect, "T" => :temporary,
+          "X" => :execute, "U" => :usage, "s" => :set, "A" => :alter_system
         }.values_at(*privileges.chars).compact
       end
     end