1 require "chef/mixin/shell_out"
 
   2 require "rexml/document"
 
   6     include Chef::Mixin::ShellOut
 
   9       :select, :insert, :update, :delete, :create, :drop, :reload,
 
  10       :shutdown, :process, :file, :grant, :references, :index, :alter,
 
  11       :show_db, :super, :create_tmp_table, :lock_tables, :execute,
 
  12       :repl_slave, :repl_client, :create_view, :show_view, :create_routine,
 
  13       :alter_routine, :create_user, :event, :trigger, :create_tablespace
 
  16     DATABASE_PRIVILEGES = [
 
  17       :select, :insert, :update, :delete, :create, :drop, :grant,
 
  18       :references, :index, :alter, :create_tmp_table, :lock_tables,
 
  19       :create_view, :show_view, :create_routine, :alter_routine,
 
  20       :execute, :event, :trigger
 
  24       # Create argument array
 
  27       # Work out how to authenticate
 
  29         args.push("--username")
 
  30         args.push(options[:user])
 
  33           args.push("--password")
 
  34           args.push(options[:password])
 
  37         args.push("--defaults-file=/etc/mysql/debian.cnf")
 
  41       args.push("--xml") if options[:xml]
 
  43       # Add any SQL command to execute
 
  45         args.push("--execute")
 
  46         args.push(options[:command])
 
  49       # Add the database name
 
  50       args.push(options[:database] || "mysql")
 
  53       shell_out!("/usr/bin/mysql", *args, :user => "root", :group => "root")
 
  56     def query(sql, options = {})
 
  58       result = execute(options.merge(:command => sql, :xml => :true))
 
  61       document = REXML::Document.new(result.stdout)
 
  66       # Loop over the rows in the result set
 
  67       document.root.each_element("/resultset/row") do |row|
 
  71         # Loop over the fields, adding them to the record
 
  72         row.each_element("field") do |field|
 
  73           name = field.attributes["name"].downcase
 
  76           record[name.to_sym] = value
 
  79         # Add the record to the record list
 
  83       # Return the record list
 
  88       @users ||= query("SELECT * FROM user").each_with_object({}) do |user, users|
 
  89         name = "'#{user[:user]}'@'#{user[:host]}'"
 
  91         users[name] = USER_PRIVILEGES.each_with_object({}) do |privilege, privileges|
 
  92           privileges[privilege] = user["#{privilege}_priv".to_sym] == "Y"
 
  98       @databases ||= query("SHOW databases").each_with_object({}) do |database, databases|
 
  99         databases[database[:database]] = {
 
 104       query("SELECT * FROM db").each do |record|
 
 105         database = @databases[record[:db]]
 
 109         user = "'#{record[:user]}'@'#{record[:host]}'"
 
 111         database[:permissions][user] = DATABASE_PRIVILEGES.each_with_object([]) do |privilege, privileges|
 
 112           privileges << privilege if record["#{privilege}_priv".to_sym] == "Y"
 
 119     def canonicalise_user(user)
 
 120       local, host = user.split("@")
 
 122       host = "%" unless host
 
 124       local = "'#{local}'" unless local =~ /^'.*'$/
 
 125       host = "'#{host}'" unless host =~ /^'.*'$/
 
 130     def privilege_name(privilege)
 
 134       when :create_tmp_table
 
 135         "CREATE TEMPORARY TABLES"
 
 137         privilege.to_s.upcase.tr("_", " ")