Permalink
Browse files

Initial code

  • Loading branch information...
1 parent 2f6445f commit 455049dc1281905827f02cb766d320a3dc8d2ffb @xaviershay xaviershay committed Mar 7, 2009
Showing with 154 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +4 −0 Rakefile
  3. +1 −0 init.rb
  4. +85 −0 lib/db2s3.rb
  5. +24 −0 spec/db2s3_spec.rb
  6. +1 −0 spec/mysql_drop_schema.sql
  7. +4 −0 spec/mysql_schema.sql
  8. +7 −0 spec/s3_config.example.rb
  9. +14 −0 spec/spec_helper.rb
  10. +13 −0 tasks/tasks.rake
View
@@ -0,0 +1 @@
+spec/s3_config.rb
View
@@ -0,0 +1,4 @@
+desc "Create test database"
+task :create_test_db do
+ `mysqladmin -u root create db2s3_unittest`
+end
View
@@ -0,0 +1 @@
+require File.expand_path(File.dirname(__FILE__) + '/lib/db2s3')
View
@@ -0,0 +1,85 @@
+require 'aws/s3'
+
+class DB2S3
+ class Config
+ end
+
+ def initialize
+ end
+
+ def full_backup
+ dump_file = Tempfile.new("dump")
+
+ #cmd = "mysqldump --quick --single-transaction --create-options -u#{db_credentials[:user]} --flush-logs --master-data=2 --delete-master-logs"
+ cmd = "mysqldump --quick --single-transaction --create-options #{mysql_options}"
+ cmd += " | gzip > #{dump_file.path}"
+ run(cmd)
+
+ store.store("dump-#{db_credentials[:database]}.sql.gz", open(dump_file.path))
+ end
+
+ def restore
+ file = store.fetch("dump-#{db_credentials[:database]}.sql.gz")
+ run "gunzip -c #{file.path} | mysql #{mysql_options}"
+ end
+
+ def mysql_credentials
+ cmd = " -u#{db_credentials[:user]} "
+ cmd += " -p'#{db_credentials[:password]}'" unless db_credentials[:password].nil?
+ cmd += " #{db_credentials[:database]}"
+ end
+
+ private
+
+ def store
+ @store ||= S3Store.new
+ end
+
+ def run(command)
+ puts command
+ result = system(command)
+ raise("error, process exited with status #{$?.exitstatus}") unless result
+ end
+
+ def db_credentials
+ ActiveRecord::Base.connection.instance_eval { @config } # Dodgy!
+ end
+
+ class S3Store
+ def initialize
+ @connected = false
+ end
+
+ def ensure_connected
+ return if @connected
+ AWS::S3::Base.establish_connection!(DB2S3::Config::S3.slice(:access_key_id, :secret_access_key).merge(:use_ssl => true))
+ AWS::S3::Bucket.create(bucket)
+ @connected = true
+ end
+
+ def store(file_name, file)
+ ensure_connected
+ AWS::S3::S3Object.store(file_name, file, bucket)
+ end
+
+ def fetch(file_name)
+ ensure_connected
+ AWS::S3::S3Object.find(file_name, bucket)
+
+ file = Tempfile.new("dump")
+ open(file.path, 'w') do |f|
+ AWS::S3::S3Object.stream(file_name, bucket) do |chunk|
+ f.write chunk
+ end
+ end
+ file
+ end
+
+ private
+
+ def bucket
+ DB2S3::Config::S3[:bucket]
+ end
+ end
+
+end
View
@@ -0,0 +1,24 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+describe 'db2s3' do
+ def load_schema
+ `cat '#{File.dirname(__FILE__) + '/mysql_schema.sql'}' | mysql -u #{DBConfig[:user]} #{DBConfig[:database]}`
+ end
+
+ def drop_schema
+ `cat '#{File.dirname(__FILE__) + '/mysql_drop_schema.sql'}' | mysql -u #{DBConfig[:user]} #{DBConfig[:database]}`
+ end
+
+ class Person < ActiveRecord::Base
+ end
+
+ it 'can save and restore a backup to S3' do
+ db2s3 = DB2S3.new
+ load_schema
+ Person.create!(:name => "Baxter")
+ db2s3.full_backup
+ drop_schema
+ db2s3.restore
+ Person.find_by_name("Baxter").should_not be_nil
+ end
+end
@@ -0,0 +1 @@
+DROP TABLE IF EXISTS people;
View
@@ -0,0 +1,4 @@
+DROP TABLE IF EXISTS people;
+CREATE TABLE people (
+name VARCHAR(255) NULL
+);
@@ -0,0 +1,7 @@
+DB2S3::Config.instance_eval do
+ S3 = {
+ :access_key_id => 'yourkey',
+ :secret_access_key => 'yoursecretkey',
+ :bucket => 'db2s3_test'
+ }
+end
View
@@ -0,0 +1,14 @@
+require 'spec'
+require 'activerecord'
+require File.dirname(__FILE__) + '/../lib/db2s3'
+require File.dirname(__FILE__) + '/s3_config.rb'
+
+DBConfig = {
+ :adapter => "mysql",
+ :encoding => "utf8",
+ :database => 'db2s3_unittest',
+ :user => "root"
+}
+
+ActiveRecord::Base.configurations = { 'production' => DBConfig }
+ActiveRecord::Base.establish_connection(:production)
View
@@ -0,0 +1,13 @@
+namespace :db2s3 do
+ namespace :backup do
+ desc "Save a full back to S3"
+ task :full => :environment do
+ DB2S3.new.full_backup
+ end
+
+ desc "Restore the latest backup stored on S3"
+ task :restore => :environment do
+ DB2S3.new.restore
+ end
+ end
+end

0 comments on commit 455049d

Please sign in to comment.