heroku_super_backup 0.0.1.rc

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ .DS_Store
2
+ .rvmrc
3
+ *.gem
4
+ .bundle
5
+ Gemfile.lock
6
+ pkg/*
7
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in heroku_cloud_backup.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Jack Chu
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # Heroku Cloud Backup
2
+
3
+ The `heroku_cloud_backup` gem adds a rake task to your project that will take backups stored with Heroku's [PGBackup addon](http://devcenter.heroku.com/articles/pgbackups) and upload them to the cloud.
4
+
5
+ ## Installation
6
+
7
+ It's recommended that you use this gem in conjunction with the [heroku_backup_task](https://github.com/joemsak/heroku_backup_task) gem. heroku_backup_task adds a rake tasks that will create a fresh database capture and expire the oldest backup if you're at your capture limit.
8
+
9
+ First, you need to enable the Heroku PGBackups addon:
10
+
11
+ heroku addons:add pgbackups:basic
12
+
13
+ If you want this to run daily, you'll need to enable the Heroku cron addon:
14
+
15
+ heroku addons:add cron:daily
16
+
17
+ For Rails 3 and later, add this to your Gemfile:
18
+
19
+ gem 'heroku_backup_task'
20
+ gem 'heroku_cloud_backup'
21
+
22
+ For Rails 2.1 and later, add this to your in your environment.rb:
23
+
24
+ config.gem 'heroku_backup_task'
25
+ config.gem 'heroku_cloud_backup'
26
+
27
+ In your Rakefile:
28
+
29
+ require "heroku_backup_task"
30
+ require "heroku_cloud_backup"
31
+ task :cron do
32
+ HerokuBackupTask.execute
33
+ HerokuCloudBackup.execute
34
+ end
35
+
36
+ ## Usage
37
+
38
+ The first thing you'll want to do is configure the addon.
39
+
40
+ HCB_PROVIDER (aws, rackspace, google) - Add which provider you're using. **Required**
41
+
42
+ heroku config:add HCB_PROVIDER='aws' # or 'google' or 'rackspace'
43
+
44
+ HCB_BUCKET (alphanumberic characters, dashes, period, underscore are allowed, between 3 and 255 characters long) - Select a bucket name to upload to. This the bucket or root directory that your files will be stored in. If the bucket doesn't exist, it will be created. **Required**
45
+
46
+ heroku config:add HCB_BUCKET='mywebsite'
47
+
48
+ HCB_PREFIX (Defaults to "db") - The direction prefix for where the backups are stored. This is so you can store your backups within a specific sub directory within the bucket. heroku_cloud_backup will also append the ENV var of the database to the path, so you can backup multiple databases, by their ENV names. **Optional**
49
+
50
+ heroku config:add HCB_PREFIX='backups/pg'
51
+
52
+ HCB_MAX (Defaults to no limit) - The number of backups to store before the script will prune out older backups. A value of 10 will allow you to store 10 of the most recent backups. Newer backups will replace older ones. **Optional**
53
+
54
+ heroku config:add HCB_MAX=10
55
+
56
+ Depending on which provider you specify, you'll need to provide different login credentials.
57
+
58
+ For Amazon:
59
+
60
+ heroku config:add HCB_KEY1="aws_access_key_id"
61
+ heroku config:add HCB_KEY2="aws_secret_access_key"
62
+
63
+ For Rackspace:
64
+
65
+ heroku config:add HCB_KEY1="rackspace_username"
66
+ heroku config:add HCB_KEY2="rackspace_api_key"
67
+
68
+ For Google Storage:
69
+
70
+ heroku config:add HCB_KEY1="google_storage_secret_access_key"
71
+ heroku config:add HCB_KEY2="google_storage_access_key_id"
72
+
73
+ You can run this manually like this:
74
+
75
+ heroku rake heroku_backup
76
+ heroku rake heroku:cloud_backup
77
+
78
+ ## Restoring a backup
79
+
80
+ I would recommend you create a temporarily public url from your cloud storage. I do this with Cyberduck. It has a neat feature where you can right click on a file and it'll generate temporarily accessible urls to that file, with the auth params for it. So once you have that url you can store like this:
81
+
82
+ heroku pgbackups:restore 'http://my-bucket-name.s3.amazonaws.com/db/DATABASE_URL/2011-06-09-014500.dump?authparameters'
83
+
84
+ ## Note on Patches/Pull Requests
85
+
86
+ * Fork the project.
87
+ * Make your feature addition or bug fix.
88
+ * Add tests for it. This is important so I don't break it in a
89
+ future version unintentionally.
90
+ * Commit, do not mess with rakefile, version, or history.
91
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
92
+ * Send me a pull request. Bonus points for topic branches.
93
+
94
+ ### Copyright
95
+
96
+ Copyright (c) 2011 Jack Chu. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "heroku_super_backup/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "heroku_super_backup"
7
+ s.version = HerokuSuperBackup::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["RedGuava", "William Basmayor"]
10
+ s.email = ["info@redguava.com.au"]
11
+ s.homepage = "https://github.com/redguava/heroku_cloud_backup"
12
+ s.summary = %q{Backup pg dumps to the cloud. Forked from the heroku_cloud_backup}
13
+ s.description = %q{PG backups into the cloud with fog}
14
+
15
+ s.rubyforge_project = "heroku_super_backup"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.add_runtime_dependency('fog', '>= 0.7.2')
22
+ s.add_runtime_dependency('heroku', '>= 2.1.4')
23
+ end
@@ -0,0 +1,11 @@
1
+ module HerokuSuperBackup
2
+ module Errors
3
+ class Error < StandardError; end
4
+ class NotFound < HerokuSuperBackup::Errors::Error; end
5
+ class InvalidProvider < HerokuSuperBackup::Errors::Error; end
6
+ class ConnectionError < HerokuSuperBackup::Errors::Error; end
7
+ class UploadError < HerokuSuperBackup::Errors::Error; end
8
+ class NoBackups < HerokuSuperBackup::Errors::Error; end
9
+ class Forbidden < HerokuSuperBackup::Errors::Error; end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ CLOUD_CREDENTIALS = [{:provider => 'aws',
2
+ :bucket_name => 'your-bucket-name',
3
+ :backup_path => 'db',
4
+ :key1 => 'your-key-1',
5
+ :key2 => 'your-key-2'
6
+ }
7
+ ]
@@ -0,0 +1,12 @@
1
+ require 'heroku_super_backup'
2
+
3
+ module HerokuSuperBackup
4
+ if defined? Rails::Railtie
5
+ require 'rails'
6
+ class Railtie < Rails::Railtie
7
+ rake_tasks do
8
+ require "heroku_super_backup/tasks"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ require 'heroku_super_backup'
2
+
3
+ namespace :heroku do
4
+ desc "Transfer PostgreSQL database backups from Heroku to the cloud"
5
+ task :cloud_backup => :environment do
6
+ HerokuSuperBackup.execute
7
+ end
8
+
9
+ desc "Create the initializer heroku_super_backup"
10
+ task :create_initializer do
11
+ HerokuSuperBackup.create_initializer
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module HerokuSuperBackup
2
+ VERSION = "0.0.1.rc"
3
+ end
@@ -0,0 +1,134 @@
1
+ require 'fog'
2
+ require 'open-uri'
3
+ require "heroku"
4
+ require "pgbackups/client"
5
+ require 'heroku_super_backup/errors'
6
+ require 'heroku_super_backup/railtie'
7
+ require 'heroku_super_backup/version'
8
+
9
+ module HerokuSuperBackup
10
+ class << self
11
+
12
+ def log(message)
13
+ puts "[#{Time.now}] #{message}"
14
+ end
15
+
16
+ def backups_url
17
+ ENV["PGBACKUPS_URL"]
18
+ end
19
+
20
+ def client
21
+ @client ||= PGBackups::Client.new(ENV["PGBACKUPS_URL"])
22
+ end
23
+
24
+ def databases
25
+ if db = #ENV["HEROKU_BACKUP_DATABASES"]
26
+ db.split(",").map(&:strip)
27
+ else
28
+ ["DATABASE_URL"]
29
+ end
30
+ end
31
+
32
+ def backup_name(to_url)
33
+ # translate s3://bucket/email/foo/bar.dump => foo/bar
34
+ parts = to_url.split('/')
35
+ parts.slice(4..-1).join('/').gsub(/\.dump$/, '')
36
+ end
37
+
38
+ def execute
39
+ log "heroku:backup started"
40
+ begin
41
+ CLOUD_CREDENTIALS.each do |credential|
42
+
43
+ @bucket_name = credential[:bucket_name] || raise(HerokuSuperBackup::Errors::NotFound.new("Please provide a 'bucket_name' on the CLOUD_CREDENTIALS variable."))
44
+ @backup_path = credential[:backup_path] || "db"
45
+ @provider = credential[:provider] || raise(HerokuSuperBackup::Errors::NotFound.new("Please provide a 'provider' on the CLOUD_CREDENTIALS variable."))
46
+ @key1 = credential[:key1] || raise(HerokuSuperBackup::Errors::NotFound.new("Please provide a 'HCB_KEY1' on the CLOUD_CREDENTIALS variable."))
47
+ @key2 = credential[:key2] || raise(HerokuSuperBackup::Errors::NotFound.new("Please provide a 'HCB_KEY2' CLOUD_CREDENTIALS variable."))
48
+
49
+ b = client.get_backups.last
50
+ raise HerokuSuperBackup::Errors::NoBackups.new("You don't have any pgbackups. Please run heroku pgbackups:capture first.") unless b
51
+
52
+ begin
53
+ case @provider
54
+ when 'aws'
55
+ @connection = Fog::Storage.new(
56
+ :provider => 'AWS',
57
+ :aws_access_key_id => @key1,
58
+ :aws_secret_access_key => @key2
59
+ )
60
+ when 'rackspace'
61
+ @connection = Fog::Storage.new(
62
+ :provider => 'Rackspace',
63
+ :rackspace_username => @key1,
64
+ :rackspace_api_key => @key2
65
+ )
66
+ when 'google'
67
+ @connection = Fog::Storage.new(
68
+ :provider => 'Google',
69
+ :google_storage_secret_access_key => @key1,
70
+ :google_storage_access_key_id => @key2
71
+ )
72
+ else
73
+ raise HerokuSuperBackup::Errors::InvalidProvider.new("Your provider was invalid. Valid values are 'aws', 'rackspace', or 'google'")
74
+ end
75
+ rescue
76
+ raise HerokuSuperBackup::Errors::ConnectionError.new("There was an error connecting to your provider.")
77
+ end
78
+
79
+ begin
80
+ directory = @connection.directories.get(@bucket_name)
81
+ rescue Excon::Errors::Forbidden
82
+ raise HerokuSuperBackup::Errors::Forbidden.new("You do not have access to this bucket name. It's possible this bucket name is already owned by another user. Please check your credentials (access keys) or select a different bucket name.")
83
+ end
84
+
85
+ if !directory
86
+ directory = @connection.directories.create(:key => @bucket_name)
87
+ end
88
+
89
+ public_url = b["public_url"]
90
+ created_at = DateTime.parse b["created_at"]
91
+ db_name = b["from_name"]
92
+ name = "#{created_at.strftime('%Y-%m-%d-%H%M%S')}.dump"
93
+ begin
94
+ log "creating #{@backup_path}/#{b["from_name"]}/#{name}"
95
+ directory.files.create(:key => "#{@backup_path}/#{b["from_name"]}/#{name}", :body => open(public_url))
96
+ rescue Exception => e
97
+ raise HerokuSuperBackup::Errors::UploadError.new(e.message)
98
+ end
99
+
100
+ prune(@connection, @bucket_name, @backup_path)
101
+
102
+ log "heroku:backup complete"
103
+ end
104
+ rescue Exception => e
105
+ raise HerokuSuperBackup::Errors::NotFound.new(e.message)
106
+ end
107
+ end
108
+
109
+ def create_initializer
110
+ FileUtils.copy(File.join(File.dirname(File.expand_path(__FILE__)), "heroku_super_backup", "heroku_super_backup.sample.rb"), "#{Rails.root}/config/initializers/heroku_super_backup.rb")
111
+ end
112
+
113
+ private
114
+
115
+ def prune(connection, bucket_name, backup_path)
116
+ number_of_files = ENV['HCB_MAX']
117
+ if number_of_files && number_of_files.to_i > 0
118
+ directory = connection.directories.get(bucket_name)
119
+ files = directory.files.all(:prefix => backup_path)
120
+ file_count = 0
121
+ files.reverse.each do |file|
122
+ if file.key =~ Regexp.new("/#{backup_path}\/\d{4}-\d{2}-\d{2}-\d{6}\.sql\.gz$/i")
123
+ file_count += 1
124
+ else
125
+ next
126
+ end
127
+ if file_count > number_of_files
128
+ file.destroy
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heroku_super_backup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.rc
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - RedGuava
9
+ - William Basmayor
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-02-10 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: fog
17
+ requirement: &70238977778720 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.7.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70238977778720
26
+ - !ruby/object:Gem::Dependency
27
+ name: heroku
28
+ requirement: &70238977778220 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.1.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *70238977778220
37
+ description: PG backups into the cloud with fog
38
+ email:
39
+ - info@redguava.com.au
40
+ executables: []
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - .gitignore
45
+ - Gemfile
46
+ - LICENSE
47
+ - README.md
48
+ - Rakefile
49
+ - heroku_super_backup.gemspec
50
+ - lib/heroku_super_backup.rb
51
+ - lib/heroku_super_backup/errors.rb
52
+ - lib/heroku_super_backup/heroku_super_backup.sample.rb
53
+ - lib/heroku_super_backup/railtie.rb
54
+ - lib/heroku_super_backup/tasks.rb
55
+ - lib/heroku_super_backup/version.rb
56
+ homepage: https://github.com/redguava/heroku_cloud_backup
57
+ licenses: []
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>'
72
+ - !ruby/object:Gem::Version
73
+ version: 1.3.1
74
+ requirements: []
75
+ rubyforge_project: heroku_super_backup
76
+ rubygems_version: 1.8.10
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Backup pg dumps to the cloud. Forked from the heroku_cloud_backup
80
+ test_files: []