Aucune description http://j1x-huginn.herokuapp.com

sync.rb 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. require 'yaml'
  2. require 'pathname'
  3. # Edited by Andrew Cantino. Based on: https://gist.github.com/339471
  4. # Original info:
  5. #
  6. # Capistrano sync.rb task for syncing databases and directories between the
  7. # local development environment and different multi_stage environments. You
  8. # cannot sync directly between two multi_stage environments, always use your
  9. # local machine as loop way.
  10. #
  11. # This version pulls credentials for the remote database from
  12. # {shared_path}/config/database.yml on the remote server, thus eliminating
  13. # the requirement to have your production database credentials on your local
  14. # machine or in your repository.
  15. #
  16. # Author: Michael Kessler aka netzpirat
  17. # Gist: 111597
  18. #
  19. # Edits By: Evan Dorn, Logical Reality Design, March 2010
  20. # Gist: 339471
  21. #
  22. # Released under the MIT license.
  23. # Kindly sponsored by Screen Concept, www.screenconcept.ch
  24. namespace :sync do
  25. namespace :db do
  26. desc <<-DESC
  27. Syncs database from the selected environment to the local development environment.
  28. The database credentials will be read from your local config/database.yml file and a copy of the
  29. dump will be kept within the shared sync directory. The amount of backups that will be kept is
  30. declared in the sync_backups variable and defaults to 5.
  31. DESC
  32. task :down, :roles => :db, :only => {:primary => true} do
  33. run "mkdir -p #{shared_path}/sync"
  34. env = fetch :rails_env, 'production'
  35. filename = "database.#{env}.#{Time.now.strftime '%Y-%m-%d_%H:%M:%S'}.sql.bz2"
  36. on_rollback { delete "#{shared_path}/sync/#{filename}" }
  37. # Remote DB dump
  38. username, password, database, host = remote_database_config(env)
  39. hostcmd = host.nil? ? '' : "-h #{host}"
  40. puts "hostname: #{host}"
  41. puts "database: #{database}"
  42. opts = "-c --max_allowed_packet=128M --hex-blob --single-transaction --skip-extended-insert --quick"
  43. run "mysqldump #{opts} -u #{username} --password='#{password}' #{hostcmd} #{database} | bzip2 -9 > #{shared_path}/sync/#{filename}" do |channel, stream, data|
  44. puts data
  45. end
  46. purge_old_backups "database"
  47. # Download dump
  48. download "#{shared_path}/sync/#{filename}", filename
  49. # Local DB import
  50. username, password, database = database_config('development')
  51. system "bzip2 -d -c #{filename} | mysql --max_allowed_packet=128M -u #{username} --password='#{password}' #{database}"
  52. system "rake db:migrate"
  53. system "rake db:test:prepare"
  54. logger.important "sync database from '#{env}' to local has finished"
  55. end
  56. end
  57. namespace :fs do
  58. desc <<-DESC
  59. Sync declared remote directories to the local development environment. The synced directories must be declared
  60. as an array of Strings with the sync_directories variable. The path is relative to the rails root.
  61. DESC
  62. task :down, :roles => :web, :once => true do
  63. server, port = host_and_port
  64. Array(fetch(:sync_directories, [])).each do |syncdir|
  65. unless File.directory? "#{syncdir}"
  66. logger.info "create local '#{syncdir}' folder"
  67. Dir.mkdir "#{syncdir}"
  68. end
  69. logger.info "sync #{syncdir} from #{server}:#{port} to local"
  70. destination, base = Pathname.new(syncdir).split
  71. system "rsync --verbose --archive --compress --copy-links --delete --stats --rsh='ssh -p #{port}' #{user}@#{server}:#{current_path}/#{syncdir} #{destination.to_s}"
  72. end
  73. logger.important "sync filesystem from remote to local finished"
  74. end
  75. end
  76. #
  77. # Reads the database credentials from the local config/database.yml file
  78. # +db+ the name of the environment to get the credentials for
  79. # Returns username, password, database
  80. #
  81. def database_config(db)
  82. database = YAML::load_file('config/database.yml')
  83. return database["#{db}"]['username'], database["#{db}"]['password'], database["#{db}"]['database'], database["#{db}"]['host']
  84. end
  85. #
  86. # Reads the database credentials from the remote config/database.yml file
  87. # +db+ the name of the environment to get the credentials for
  88. # Returns username, password, database
  89. #
  90. def remote_database_config(db)
  91. remote_config = capture("cat #{current_path}/config/database.yml")
  92. database = YAML::load(remote_config)
  93. return database["#{db}"]['username'], database["#{db}"]['password'], database["#{db}"]['database'], database["#{db}"]['host']
  94. end
  95. #
  96. # Returns the actual host name to sync and port
  97. #
  98. def host_and_port
  99. return roles[:web].servers.first.host, ssh_options[:port] || roles[:web].servers.first.port || 22
  100. end
  101. #
  102. # Purge old backups within the shared sync directory
  103. #
  104. def purge_old_backups(base)
  105. count = fetch(:sync_backups, 5).to_i
  106. backup_files = capture("ls -xt #{shared_path}/sync/#{base}*").split.reverse
  107. if count >= backup_files.length
  108. logger.important "no old backups to clean up"
  109. else
  110. logger.info "keeping #{count} of #{backup_files.length} sync backups"
  111. delete_backups = (backup_files - backup_files.last(count)).join(" ")
  112. run "rm #{delete_backups}"
  113. end
  114. end
  115. end