pgbackups-archive 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ *.gem
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@pgbackups-archive --create
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "fuubar", "~> 1.0.0"
7
+ gem "growl", "~> 1.0.3"
8
+ gem "guard-rspec", "~> 1.2.0"
9
+ gem "rspec", "~> 2.11.0"
10
+ end
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
@@ -0,0 +1,4 @@
1
+ guard "rspec", cli: "--color --format Fuubar", all_on_start: false, all_after_pass: false do
2
+ watch(%r{^spec/(.*)_spec\.rb$})
3
+ watch(%r{^lib/(.*)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ end
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,11 @@
1
+ if defined?(Rails)
2
+ module PgbackupsArchive
3
+ class Railtie < Rails::Railtie
4
+ railtie_name :pgbackups_archive
5
+
6
+ rake_tasks do
7
+ load "tasks/pgbackups_archive.rake"
8
+ end
9
+ end
10
+ end
11
+ 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,3 @@
1
+ module PgbackupsArchive
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,5 @@
1
+ module PgbackupsArchive
2
+ require "pgbackups-archive/heroku/client/pgbackups_archive"
3
+ require "pgbackups-archive/railtie"
4
+ require "pgbackups-archive/storage"
5
+ end
@@ -0,0 +1,9 @@
1
+ namespace :pgbackups do
2
+
3
+ task :archive do
4
+ archive = Heroku::Client::PgbackupsArchive.new(:pgbackups_url => ENV["PGBACKUPS_URL"])
5
+ archive.capture
6
+ archive.store
7
+ end
8
+
9
+ 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
@@ -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