pgbackups-archive 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +89 -0
- data/Guardfile +4 -0
- data/README.md +57 -0
- data/Rakefile +1 -0
- data/lib/pgbackups-archive/heroku/client/pgbackups_archive.rb +38 -0
- data/lib/pgbackups-archive/railtie.rb +11 -0
- data/lib/pgbackups-archive/storage.rb +29 -0
- data/lib/pgbackups-archive/version.rb +3 -0
- data/lib/pgbackups-archive.rb +5 -0
- data/lib/tasks/pgbackups_archive.rake +9 -0
- data/pgbackups-archive.gemspec +23 -0
- data/spec/lib/pgbackups-archive/heroku/client/pgbackups_archive_spec.rb +26 -0
- data/spec/lib/pgbackups-archive/storage_spec.rb +28 -0
- data/spec/spec_helper.rb +1 -0
- metadata +115 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3@pgbackups-archive --create
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pgbackups-archive (0.0.1)
|
5
|
+
fog (>= 1.4.0)
|
6
|
+
heroku (>= 2.30.1)
|
7
|
+
rake (>= 0.9.2.2)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
addressable (2.3.2)
|
13
|
+
builder (3.0.0)
|
14
|
+
diff-lcs (1.1.3)
|
15
|
+
excon (0.15.5)
|
16
|
+
ffi (1.1.3)
|
17
|
+
fog (1.5.0)
|
18
|
+
builder
|
19
|
+
excon (~> 0.14)
|
20
|
+
formatador (~> 0.2.0)
|
21
|
+
mime-types
|
22
|
+
multi_json (~> 1.0)
|
23
|
+
net-scp (~> 1.0.4)
|
24
|
+
net-ssh (>= 2.1.3)
|
25
|
+
nokogiri (~> 1.5.0)
|
26
|
+
ruby-hmac
|
27
|
+
formatador (0.2.3)
|
28
|
+
fuubar (1.0.0)
|
29
|
+
rspec (~> 2.0)
|
30
|
+
rspec-instafail (~> 0.2.0)
|
31
|
+
ruby-progressbar (~> 0.0.10)
|
32
|
+
growl (1.0.3)
|
33
|
+
guard (1.2.3)
|
34
|
+
listen (>= 0.4.2)
|
35
|
+
thor (>= 0.14.6)
|
36
|
+
guard-rspec (1.2.1)
|
37
|
+
guard (>= 1.1)
|
38
|
+
heroku (2.30.1)
|
39
|
+
heroku-api (~> 0.3.1)
|
40
|
+
launchy (>= 0.3.2)
|
41
|
+
netrc (~> 0.7.5)
|
42
|
+
rest-client (~> 1.6.1)
|
43
|
+
rubyzip
|
44
|
+
heroku-api (0.3.2)
|
45
|
+
excon (~> 0.15.5)
|
46
|
+
launchy (2.1.1)
|
47
|
+
addressable (~> 2.3)
|
48
|
+
listen (0.4.7)
|
49
|
+
rb-fchange (~> 0.0.5)
|
50
|
+
rb-fsevent (~> 0.9.1)
|
51
|
+
rb-inotify (~> 0.8.8)
|
52
|
+
mime-types (1.19)
|
53
|
+
multi_json (1.3.6)
|
54
|
+
net-scp (1.0.4)
|
55
|
+
net-ssh (>= 1.99.1)
|
56
|
+
net-ssh (2.5.2)
|
57
|
+
netrc (0.7.5)
|
58
|
+
nokogiri (1.5.5)
|
59
|
+
rake (0.9.2.2)
|
60
|
+
rb-fchange (0.0.5)
|
61
|
+
ffi
|
62
|
+
rb-fsevent (0.9.1)
|
63
|
+
rb-inotify (0.8.8)
|
64
|
+
ffi (>= 0.5.0)
|
65
|
+
rest-client (1.6.7)
|
66
|
+
mime-types (>= 1.16)
|
67
|
+
rspec (2.11.0)
|
68
|
+
rspec-core (~> 2.11.0)
|
69
|
+
rspec-expectations (~> 2.11.0)
|
70
|
+
rspec-mocks (~> 2.11.0)
|
71
|
+
rspec-core (2.11.1)
|
72
|
+
rspec-expectations (2.11.2)
|
73
|
+
diff-lcs (~> 1.1.3)
|
74
|
+
rspec-instafail (0.2.4)
|
75
|
+
rspec-mocks (2.11.1)
|
76
|
+
ruby-hmac (0.4.0)
|
77
|
+
ruby-progressbar (0.0.10)
|
78
|
+
rubyzip (0.9.9)
|
79
|
+
thor (0.15.4)
|
80
|
+
|
81
|
+
PLATFORMS
|
82
|
+
ruby
|
83
|
+
|
84
|
+
DEPENDENCIES
|
85
|
+
fuubar (~> 1.0.0)
|
86
|
+
growl (~> 1.0.3)
|
87
|
+
guard-rspec (~> 1.2.0)
|
88
|
+
pgbackups-archive!
|
89
|
+
rspec (~> 2.11.0)
|
data/Guardfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# pgbackups-archive
|
2
|
+
|
3
|
+
A means of automating Heroku's pgbackups and archiving them to Amazon S3 via the `fog` gem.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
The `pgbackups:archive` rake task that this gem provides will capture a pgbackup, wait for it to complete, then store it within the Amazon S3 bucket you specify. This rake task can be scheduled via the Heroku Scheduler, thus producing automated, offsite, backups.
|
8
|
+
|
9
|
+
The rake task will use pgbackups' `--expire` flag to remove the oldest pgbackup Heroku is storing when there are no free slots remaining.
|
10
|
+
|
11
|
+
You can configure retention settings at the Amazon S3 bucket level from within the AWS Console if you like.
|
12
|
+
|
13
|
+
## Use
|
14
|
+
|
15
|
+
Add the gem to your Gemfile and bundle:
|
16
|
+
|
17
|
+
gem "pgbackups-archive"
|
18
|
+
bundle install
|
19
|
+
|
20
|
+
Install Heroku addons:
|
21
|
+
|
22
|
+
heroku addons:add pgbackups:plus
|
23
|
+
heroku addons:add scheduler:standard
|
24
|
+
|
25
|
+
Note: You can use paid-for versions of pgbackups if you'd like, however the dev and basic database offerings only support the free (plus) version.
|
26
|
+
|
27
|
+
Apply environment variables:
|
28
|
+
|
29
|
+
heroku config:add PGBACKUPS_AWS_ACCESS_KEY_ID="XXX"
|
30
|
+
heroku config:add PGBACKUPS_AWS_SECRET_ACCESS_KEY="YYY"
|
31
|
+
heroku config:add PGBACKUPS_BUCKET="myapp-backups"
|
32
|
+
heroku config:add PGBACKUPS_REGION="us-west-2"
|
33
|
+
|
34
|
+
Note: A good security measure would be to use a dedicated set of AWS credentials with a security policy only allowing access to the bucket you're specifying.
|
35
|
+
|
36
|
+
Add the rake task to scheduler:
|
37
|
+
|
38
|
+
heroku addons:open scheduler
|
39
|
+
|
40
|
+
Then specify `rake pgbackups:archive` as a task you would like to run at any of the available intervals.
|
41
|
+
|
42
|
+
## Disclaimer
|
43
|
+
|
44
|
+
I shouldn't have to say this, but I will. Your backups are your responsibility. Take charge of ensuring that they run, archive and can be restored periodically as expected. Don't rely on Heroku, this gem, or anything else out there to substitute for a regimented database backup and restore testing strategy.
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
|
48
|
+
1. [Fork it](https://github.com/kjohnston/pgbackups-archive/fork_select)
|
49
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
50
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
51
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
52
|
+
5. [Create a Pull Request](hhttps://github.com/kjohnston/pgbackups-archive/pull/new)
|
53
|
+
|
54
|
+
## License
|
55
|
+
|
56
|
+
* Freely distributable and licensed under the [MIT license](http://kjohnston.mit-license.org/license.html).
|
57
|
+
* Copyright (c) 2012 Kenny Johnston [![endorse](http://api.coderwall.com/kjohnston/endorsecount.png)](http://coderwall.com/kjohnston)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
load "tasks/pgbackups_archive.rake"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "heroku/client"
|
2
|
+
|
3
|
+
class Heroku::Client::PgbackupsArchive
|
4
|
+
|
5
|
+
attr_reader :client, :backup
|
6
|
+
|
7
|
+
def initialize(attrs={})
|
8
|
+
Heroku::Command.load
|
9
|
+
@client = Heroku::Client::Pgbackups.new attrs[:pgbackups_url]
|
10
|
+
@backup = nil
|
11
|
+
@environment = attrs[:env] || (defined?(Rails) ? Rails.env : nil)
|
12
|
+
end
|
13
|
+
|
14
|
+
def capture
|
15
|
+
@backup = @client.create_transfer ENV["DATABASE_URL"], ENV["DATABASE_URL"], nil, "BACKUP", :expire => true
|
16
|
+
|
17
|
+
until @backup["finished_at"]
|
18
|
+
print "."
|
19
|
+
sleep 1
|
20
|
+
@backup = @client.get_transfer @backup["id"]
|
21
|
+
end
|
22
|
+
|
23
|
+
@backup
|
24
|
+
end
|
25
|
+
|
26
|
+
def file
|
27
|
+
open @backup["public_url"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def key
|
31
|
+
["pgbackups", @environment, @backup["finished_at"].gsub(/\/|\:|\.|\s/, "-").concat(".dump")].join("/")
|
32
|
+
end
|
33
|
+
|
34
|
+
def store
|
35
|
+
PgbackupsArchive::Storage.new(key, file).store
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "fog"
|
2
|
+
require "open-uri"
|
3
|
+
|
4
|
+
class PgbackupsArchive::Storage
|
5
|
+
|
6
|
+
def initialize(key, file)
|
7
|
+
@key = key
|
8
|
+
@file = file
|
9
|
+
end
|
10
|
+
|
11
|
+
def connection
|
12
|
+
Fog::Storage.new({
|
13
|
+
provider: "AWS",
|
14
|
+
aws_access_key_id: ENV["PGBACKUPS_AWS_ACCESS_KEY_ID"],
|
15
|
+
aws_secret_access_key: ENV["PGBACKUPS_AWS_SECRET_ACCESS_KEY"],
|
16
|
+
region: ENV["PGBACKUPS_REGION"],
|
17
|
+
persistent: false
|
18
|
+
})
|
19
|
+
end
|
20
|
+
|
21
|
+
def bucket
|
22
|
+
connection.directories.get ENV["PGBACKUPS_BUCKET"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def store
|
26
|
+
bucket.files.create key: @key, body: @file, :public => false
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "pgbackups-archive/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "pgbackups-archive"
|
7
|
+
s.version = PgbackupsArchive::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Kenny Johnston"]
|
10
|
+
s.email = ["kjohnston.ca@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/kjohnston/pgbackups-archive"
|
12
|
+
s.summary = %q{A means of automating Heroku's pgbackups and archiving them to Amazon S3 via the fog gem.}
|
13
|
+
s.description = %q{A means of automating Heroku's pgbackups and archiving them to Amazon S3 via the fog gem.}
|
14
|
+
|
15
|
+
s.add_runtime_dependency "fog", ">= 1.4.0"
|
16
|
+
s.add_runtime_dependency "heroku", ">= 2.30.1"
|
17
|
+
s.add_runtime_dependency "rake", ">= 0.9.2.2"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "heroku/client"
|
3
|
+
|
4
|
+
describe Heroku::Client::PgbackupsArchive do
|
5
|
+
let(:archive) { Heroku::Client::PgbackupsArchive.new(:pgbackups_url => "https://ip:password@pgbackups.heroku.com/client") }
|
6
|
+
let(:backup) { { "finished_at" => "some timestamp" } }
|
7
|
+
|
8
|
+
it "should use a pgbackup client" do
|
9
|
+
archive.client.class.should eq Heroku::Client::Pgbackups
|
10
|
+
end
|
11
|
+
|
12
|
+
context "given a finished_at timestamp" do
|
13
|
+
before { archive.client.stub(:create_transfer).and_return(backup) }
|
14
|
+
|
15
|
+
it "should capture the backup" do
|
16
|
+
archive.capture.should eq backup
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should store the backup" do
|
20
|
+
archive.stub(:key).and_return("key")
|
21
|
+
archive.stub(:file).and_return("file")
|
22
|
+
archive.store.class.should eq Fog::Storage::AWS::File
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PgbackupsArchive::Storage do
|
4
|
+
let(:connection) { Fog::Storage.new(:provider => "AWS", :aws_access_key_id => "XXX", :aws_secret_access_key => "YYY") }
|
5
|
+
let(:bucket) { connection.directories.create(:key => "someapp-backups") }
|
6
|
+
let(:key) { "pgbackups/test/2012-08-02-12-00-00.dump" }
|
7
|
+
let(:file) { "test" }
|
8
|
+
let(:storage) { PgbackupsArchive::Storage.new(key, file) }
|
9
|
+
|
10
|
+
before do
|
11
|
+
Fog.mock!
|
12
|
+
storage.stub(:connection).and_return(connection)
|
13
|
+
storage.stub(:bucket).and_return(bucket)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should create a fog connection" do
|
17
|
+
storage.connection.class.should eq Fog::Storage::AWS::Mock
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should create a fog directory" do
|
21
|
+
storage.bucket.class.should eq Fog::Storage::AWS::Directory
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should create a fog file" do
|
25
|
+
storage.store.class.should eq Fog::Storage::AWS::File
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.dirname(__FILE__) + "/../lib/**/*.rb"].each { |f| require f }
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pgbackups-archive
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kenny Johnston
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: fog
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.4.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.4.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: heroku
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.30.1
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.30.1
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.2.2
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.9.2.2
|
62
|
+
description: A means of automating Heroku's pgbackups and archiving them to Amazon
|
63
|
+
S3 via the fog gem.
|
64
|
+
email:
|
65
|
+
- kjohnston.ca@gmail.com
|
66
|
+
executables: []
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- .gitignore
|
71
|
+
- .rvmrc
|
72
|
+
- Gemfile
|
73
|
+
- Gemfile.lock
|
74
|
+
- Guardfile
|
75
|
+
- README.md
|
76
|
+
- Rakefile
|
77
|
+
- lib/pgbackups-archive.rb
|
78
|
+
- lib/pgbackups-archive/heroku/client/pgbackups_archive.rb
|
79
|
+
- lib/pgbackups-archive/railtie.rb
|
80
|
+
- lib/pgbackups-archive/storage.rb
|
81
|
+
- lib/pgbackups-archive/version.rb
|
82
|
+
- lib/tasks/pgbackups_archive.rake
|
83
|
+
- pgbackups-archive.gemspec
|
84
|
+
- spec/lib/pgbackups-archive/heroku/client/pgbackups_archive_spec.rb
|
85
|
+
- spec/lib/pgbackups-archive/storage_spec.rb
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
homepage: http://github.com/kjohnston/pgbackups-archive
|
88
|
+
licenses: []
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.8.24
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: A means of automating Heroku's pgbackups and archiving them to Amazon S3
|
111
|
+
via the fog gem.
|
112
|
+
test_files:
|
113
|
+
- spec/lib/pgbackups-archive/heroku/client/pgbackups_archive_spec.rb
|
114
|
+
- spec/lib/pgbackups-archive/storage_spec.rb
|
115
|
+
- spec/spec_helper.rb
|