X-Git-Url: https://git.openstreetmap.org./chef.git/blobdiff_plain/faf8ae12e85eabb050b0f5eceb2cb67ad1de5261..41b4f8ccdff661e5463961da893ef91866e9f74c:/cookbooks/mysql/libraries/mysql.rb diff --git a/cookbooks/mysql/libraries/mysql.rb b/cookbooks/mysql/libraries/mysql.rb index c0da28f33..ec9743c94 100644 --- a/cookbooks/mysql/libraries/mysql.rb +++ b/cookbooks/mysql/libraries/mysql.rb @@ -1,9 +1,9 @@ -require "chef/mixin/command" +require "chef/mixin/shell_out" require "rexml/document" -class Chef - class MySQL - include Chef::Mixin::Command +module OpenStreetMap + module MySQL + include Chef::Mixin::ShellOut USER_PRIVILEGES = [ :select, :insert, :update, :delete, :create, :drop, :reload, @@ -11,56 +11,54 @@ class Chef :show_db, :super, :create_tmp_table, :lock_tables, :execute, :repl_slave, :repl_client, :create_view, :show_view, :create_routine, :alter_routine, :create_user, :event, :trigger, :create_tablespace - ] + ].freeze DATABASE_PRIVILEGES = [ :select, :insert, :update, :delete, :create, :drop, :grant, :references, :index, :alter, :create_tmp_table, :lock_tables, :create_view, :show_view, :create_routine, :alter_routine, :execute, :event, :trigger - ] + ].freeze - def execute(options) + def mysql_execute(options) # Create argument array args = [] # Work out how to authenticate if options[:user] - args.push("--username=#{options[:user]}") - args.push("--password=#{options[:password]}") if options[:password] + args.push("--username") + args.push(options[:user]) + + if options[:password] + args.push("--password") + args.push(options[:password]) + end else args.push("--defaults-file=/etc/mysql/debian.cnf") end - # Build the other arguments - args.push("--execute=\"#{options[:command]}\"") if options[:command] - - # Get the database to use - database = options[:database] || "mysql" + # Set output format + args.push("--xml") if options[:xml] - # Build the command to run - command = "/usr/bin/mysql #{args.join(' ')} #{database}" + # Add any SQL command to execute + if options[:command] + args.push("--execute") + args.push(options[:command]) + end - # Escape backticks in the command - command.gsub!(/`/, "\\\\`") + # Add the database name + args.push(options[:database] || "mysql") # Run the command - run_command(:command => command, :user => "root", :group => "root") + shell_out!("/usr/bin/mysql", *args, :user => "root", :group => "root") end def query(sql, options = {}) - # Get the database to use - database = options[:database] || "mysql" - - # Construct the command string - command = "/usr/bin/mysql --defaults-file=/etc/mysql/debian.cnf --xml --execute='#{sql}' #{database}" - # Run the query - status, stdout, stderr = output_of_command(command, :user => "root", :group => "root") - handle_command_failures(status, "STDOUT: #{stdout}\nSTDERR: #{stderr}", :output_on_failure => true) + result = mysql_execute(options.merge(:command => sql, :xml => true)) # Parse the output - document = REXML::Document.new(stdout) + document = REXML::Document.new(result.stdout) # Create records = [] @@ -86,45 +84,44 @@ class Chef records end - def users - @users ||= query("SELECT * FROM user").inject({}) do |users,user| + def mysql_users + privilege_columns = USER_PRIVILEGES.collect { |privilege| "#{privilege}_priv" }.join(", ") + + @mysql_users ||= query("SELECT user, host, #{privilege_columns} FROM user").each_with_object({}) do |user, users| name = "'#{user[:user]}'@'#{user[:host]}'" - users[name] = USER_PRIVILEGES.inject({}) do |privileges,privilege| + users[name] = USER_PRIVILEGES.each_with_object({}) do |privilege, privileges| privileges[privilege] = user["#{privilege}_priv".to_sym] == "Y" - privileges end - - users end end - def databases - @databases ||= query("SHOW databases").inject({}) do |databases,database| + def mysql_databases + @mysql_databases ||= query("SHOW databases").each_with_object({}) do |database, databases| databases[database[:database]] = { :permissions => {} } - databases end query("SELECT * FROM db").each do |record| - if database = @databases[record[:db]] - user = "'#{record[:user]}'@'#{record[:host]}'" + database = @mysql_databases[record[:db]] + + next unless database + + user = "'#{record[:user]}'@'#{record[:host]}'" - database[:permissions][user] = DATABASE_PRIVILEGES.inject([]) do |privileges,privilege| - privileges << privilege if record["#{privilege}_priv".to_sym] == "Y" - privileges - end + database[:permissions][user] = DATABASE_PRIVILEGES.each_with_object([]) do |privilege, privileges| + privileges << privilege if record["#{privilege}_priv".to_sym] == "Y" end end - @databases + @mysql_databases end - def canonicalise_user(user) + def mysql_canonicalise_user(user) local, host = user.split("@") - host = "%" unless host + host ||= "%" local = "'#{local}'" unless local =~ /^'.*'$/ host = "'#{host}'" unless host =~ /^'.*'$/ @@ -132,10 +129,16 @@ class Chef "#{local}@#{host}" end - def privilege_name(privilege) + def mysql_privilege_name(privilege) case privilege when :grant "GRANT OPTION" + when :show_db + "SHOW DATABASES" + when :repl_slave + "REPLICATION SLAVE" + when :repl_client + "REPLICATION CLIENT" when :create_tmp_table "CREATE TEMPORARY TABLES" else