pgbackups_s3 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/README.md +7 -0
- data/lib/generators/pgbackups_s3/install_generator.rb +14 -0
- data/lib/generators/templates/pgbackups_s3_initializer.rb +20 -0
- data/lib/pgbackups_s3/client.rb +118 -0
- data/lib/pgbackups_s3/configuration.rb +38 -0
- data/lib/pgbackups_s3.rb +11 -0
- data/lib/tasks/pgbackups_s3.rake +5 -0
- data/pgbackups_s3.gemspec +17 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cba68bca1c3791533eecdaa606272d069657efd8
|
4
|
+
data.tar.gz: b19a55e420cf7c5678de04050df90a700bdd93f2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 197d770f48b476fff20d5a1fa228922ea6959f8f40754d2894e52cc7e6ac691cc36d3d4682427c5b1e45165398004ed8a5abfa2a0a74583a1637e0f6af63be0e
|
7
|
+
data.tar.gz: 11eb69145134893beb213f603bd8017d824d94265374d5931ff4eb57a6de176efcdd743cd43e1dc5bbf52a04cef4c8c247349e5020b551f9c09d45bd09ff02d1
|
data/.gitignore
ADDED
data/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class PgbackupsS3
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../../templates', __FILE__)
|
5
|
+
desc "Creates PgbackupsS3 initialzier for your application"
|
6
|
+
|
7
|
+
def copy_initializer
|
8
|
+
template "pgbackups_s3_initializer.rb", "config/initializers/pgbackups_s3.rb"
|
9
|
+
|
10
|
+
puts "Your data is almost safe! Just fill out the 'config/initializers/pgbackups_s3.rb' and you'll be good to go"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
PgbackupsS3.configure do |config|
|
2
|
+
# Databases that you want data to be pulled from and restored to.
|
3
|
+
# Defaults to 'DATABASE_URL'
|
4
|
+
# Example of other is 'HEROKU_POSTGRESQL_GRAY_URL'
|
5
|
+
# config.capture_database = 'DATABASE_URL'
|
6
|
+
# config.restore_database = 'DATABASE_URL'
|
7
|
+
|
8
|
+
# Change this to the S3 bucket name you want the backups to go into
|
9
|
+
# Defaults to 'pgbackups_s3'
|
10
|
+
# config.bucket = 'YOUR_BUCKET_NAME'
|
11
|
+
|
12
|
+
# This specifies the directories the backups will go in within your bucket
|
13
|
+
# Ex. 'backups' will put all backups within your bucket in the backups folder
|
14
|
+
# config.directories = 'backups'
|
15
|
+
|
16
|
+
# Input your amazon credentials
|
17
|
+
# Required
|
18
|
+
config.access_key_id = 'YOUR_AWS_ACCESS_KEY'
|
19
|
+
config.secret_access_key = 'YOUR_AWS_SECRET_ACCESS_KEY'
|
20
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
class PgbackupsS3
|
2
|
+
include HTTParty
|
3
|
+
|
4
|
+
|
5
|
+
def self.backup
|
6
|
+
p = new
|
7
|
+
p.capture
|
8
|
+
p.get_latest_backup
|
9
|
+
p.download
|
10
|
+
p.send_to_s3
|
11
|
+
p.clean
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.list_backups(year=nil, month=nil, day=nil)
|
15
|
+
p = new
|
16
|
+
year ||= Date.today.year
|
17
|
+
month ||= Date.today.month
|
18
|
+
day ||= Date.today.day
|
19
|
+
p.list_backups(year, month, day)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.restore(key)
|
23
|
+
p = new
|
24
|
+
p.restore_from(key)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
uri = URI.parse(ENV['PGBACKUPS_URL'])
|
29
|
+
@host = "#{uri.scheme}://#{uri.host}"
|
30
|
+
@host += ":#{uri.port}" if uri.port
|
31
|
+
self.class.basic_auth uri.user, uri.password
|
32
|
+
@backup_url = ""
|
33
|
+
@tmp_file = "./tmp/#{DateTime.now.strftime('%k:%M:%S')}.dump"
|
34
|
+
@bucket = PgbackupsS3.configuration.bucket
|
35
|
+
@directories = PgbackupsS3.configuration.directories
|
36
|
+
@capture_database = PgbackupsS3.configuration.capture_database
|
37
|
+
@restore_database = PgbackupsS3.configuration.restore_database
|
38
|
+
File.new(@tmp_file, 'w+')
|
39
|
+
|
40
|
+
@s3 = AWS::S3.new(
|
41
|
+
access_key_id: PgbackupsS3.configuration.access_key_id,
|
42
|
+
secret_access_key: PgbackupsS3.configuration.secret_access_key
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_latest_backup
|
47
|
+
@backup_url = self.class.get("#{@host}/client/latest_backup")['public_url']
|
48
|
+
end
|
49
|
+
|
50
|
+
def capture
|
51
|
+
params = {:from_url => ENV[@capture_database], :from_name => ENV[@capture_database], :to_url => nil, :to_name => 'BACKUP', expire: true}
|
52
|
+
backup = self.class.post("#{@host}/client/transfers", query: params)
|
53
|
+
|
54
|
+
print "Wrangling up that postgres\n"
|
55
|
+
|
56
|
+
until backup["finished_at"]
|
57
|
+
print '.'
|
58
|
+
sleep 1
|
59
|
+
backup = self.class.get("#{@host}/client/transfers/#{backup['id']}")
|
60
|
+
end
|
61
|
+
|
62
|
+
print "\nYar we got it!\n"
|
63
|
+
end
|
64
|
+
|
65
|
+
def download
|
66
|
+
print "Downloading that postgres\n"
|
67
|
+
File.open(@tmp_file, "wb") do |output|
|
68
|
+
streamer = lambda do |chunk, remaining_bytes, total_bytes|
|
69
|
+
print '.'
|
70
|
+
output.write chunk
|
71
|
+
end
|
72
|
+
Excon.get(@backup_url, :response_block => streamer)
|
73
|
+
end
|
74
|
+
print "\nSaved as #{@tmp_file} on local server\n"
|
75
|
+
end
|
76
|
+
|
77
|
+
def send_to_s3
|
78
|
+
print "Shipping that sucka to S3\t"
|
79
|
+
key = File.basename(@tmp_file)
|
80
|
+
@s3.buckets[@bucket].objects["#{@directories}/#{Date.today.year}/6/#{Date.today.day}/#{key}"].write(:file => @tmp_file)
|
81
|
+
puts "Backup uploaded to #{@bucket} bucket."
|
82
|
+
end
|
83
|
+
|
84
|
+
def clean
|
85
|
+
print "Removing backup from local server\n"
|
86
|
+
File.delete(@tmp_file)
|
87
|
+
end
|
88
|
+
|
89
|
+
def list_backups(year, month, day)
|
90
|
+
prefix = "#{@directories}/#{year}/#{month}/#{day}"
|
91
|
+
keys = @s3.buckets[@bucket].objects.with_prefix(prefix).collect(&:key)
|
92
|
+
|
93
|
+
print "Backups for #{month}-#{day}-#{year} ----------------------- \n"
|
94
|
+
keys.each do |key|
|
95
|
+
print "-- #{key} \n"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def restore_from(key)
|
100
|
+
print "\n\nWARNING: This will overwrite the production database with restore: #{key}\n"
|
101
|
+
print "Type 'Give me my data!' to confirm \n"
|
102
|
+
|
103
|
+
input = gets.chomp
|
104
|
+
|
105
|
+
if input == 'Give me my data!'
|
106
|
+
object = @s3.buckets[@bucket].objects.with_prefix(key).first
|
107
|
+
object.acl = :public_read
|
108
|
+
params = {:to_url => ENV[@restore_database], :to_name => ENV[@restore_database], :from_url => object.public_url, :from_name => "EXTERNAL_BACKUP"}
|
109
|
+
backup = self.class.post("#{@host}/client/transfers", query: params)
|
110
|
+
sleep 20
|
111
|
+
object.acl = :private
|
112
|
+
|
113
|
+
print "Database restore is being run in the background. Check your apps logs for more info"
|
114
|
+
else
|
115
|
+
print "Not overwriting your data. Phew that was a close one!"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class PgbackupsS3
|
2
|
+
@@configuration = nil
|
3
|
+
|
4
|
+
def self.configure
|
5
|
+
@@configuration = Configuration.new
|
6
|
+
|
7
|
+
if block_given?
|
8
|
+
yield configuration
|
9
|
+
end
|
10
|
+
|
11
|
+
configuration
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.configuration
|
15
|
+
@@configuration || configure
|
16
|
+
end
|
17
|
+
|
18
|
+
class Configuration
|
19
|
+
attr_accessor :bucket, :directories, :access_key_id, :secret_access_key,
|
20
|
+
:capture_database, :restore_database
|
21
|
+
|
22
|
+
def bucket
|
23
|
+
@bucket ||= 'pgbackups_s3'
|
24
|
+
end
|
25
|
+
|
26
|
+
def directories
|
27
|
+
@directories ||= 'backups'
|
28
|
+
end
|
29
|
+
|
30
|
+
def capture_database
|
31
|
+
@capture_database ||= 'DATABASE_URL'
|
32
|
+
end
|
33
|
+
|
34
|
+
def restore_database
|
35
|
+
@restore_database ||= 'DATABASE_URL'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/pgbackups_s3.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'pgbackups_s3'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2014-07-25'
|
5
|
+
s.summary = %w{Send pgbackups to S3 using aws_sdk}
|
6
|
+
s.description = %w{Send pgbackups to S3 using aws_sdk. This gem also allows
|
7
|
+
you to restore from your backups on S3}
|
8
|
+
s.authors = ["Matt Leonard"]
|
9
|
+
s.email = 'mattleonardco@gmail.com'
|
10
|
+
s.files = `git ls-files`.split("\n")
|
11
|
+
s.require_paths = ["lib"]
|
12
|
+
s.homepage = 'http://mattl.co'
|
13
|
+
s.license = 'MIT'
|
14
|
+
|
15
|
+
s.add_runtime_dependency 'aws-sdk', '>= 1.0', '<= 1.49.0'
|
16
|
+
s.add_runtime_dependency 'httparty', '>= 0.3', '<= 0.13.1'
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pgbackups_s3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Leonard
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
- - "<="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.49.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.0'
|
30
|
+
- - "<="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.49.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: httparty
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.3'
|
40
|
+
- - "<="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.13.1
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.3'
|
50
|
+
- - "<="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.13.1
|
53
|
+
description: '["Send", "pgbackups", "to", "S3", "using", "aws_sdk.", "This", "gem",
|
54
|
+
"also", "allows", "you", "to", "restore", "from", "your", "backups", "on", "S3"]'
|
55
|
+
email: mattleonardco@gmail.com
|
56
|
+
executables: []
|
57
|
+
extensions: []
|
58
|
+
extra_rdoc_files: []
|
59
|
+
files:
|
60
|
+
- ".gitignore"
|
61
|
+
- README.md
|
62
|
+
- lib/generators/pgbackups_s3/install_generator.rb
|
63
|
+
- lib/generators/templates/pgbackups_s3_initializer.rb
|
64
|
+
- lib/pgbackups_s3.rb
|
65
|
+
- lib/pgbackups_s3/client.rb
|
66
|
+
- lib/pgbackups_s3/configuration.rb
|
67
|
+
- lib/tasks/pgbackups_s3.rake
|
68
|
+
- pgbackups_s3.gemspec
|
69
|
+
homepage: http://mattl.co
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
metadata: {}
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 2.2.2
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: '["Send", "pgbackups", "to", "S3", "using", "aws_sdk"]'
|
93
|
+
test_files: []
|