heroku_cloud_backup 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-18mode # JRuby in 1.8 mode
7
+ - jruby-19mode # JRuby in 1.9 mode
8
+ - rbx-18mode
9
+ - rbx-19mode
10
+ - ree
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Jack Chu
1
+ Copyright (c) 2011-2012 Jack Chu
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Heroku Cloud Backup
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/kamui/heroku_cloud_backup.png)](http://travis-ci.org/kamui/heroku_cloud_backup)
4
+
3
5
  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
6
 
5
7
  ## Installation
@@ -93,4 +95,4 @@ I would recommend you create a temporarily public url from your cloud storage. I
93
95
 
94
96
  ### Copyright
95
97
 
96
- Copyright (c) 2011 Jack Chu. See LICENSE for details.
98
+ Copyright (c) 2011-2012 Jack Chu. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,2 +1,16 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'bundler'
2
4
  Bundler::GemHelper.install_tasks
5
+
6
+ require 'rake/testtask'
7
+ task :default => :test
8
+
9
+ desc "Run tests"
10
+ task :test do
11
+ Rake::TestTask.new do |t|
12
+ t.libs << 'lib' << 'spec'
13
+ t.pattern = 'spec/**/*_spec.rb'
14
+ t.verbose = true
15
+ end
16
+ end
@@ -1,4 +1,5 @@
1
- # -*- encoding: utf-8 -*-
1
+ # encoding: utf-8
2
+
2
3
  $:.push File.expand_path("../lib", __FILE__)
3
4
  require "heroku_cloud_backup/version"
4
5
 
@@ -8,7 +9,7 @@ Gem::Specification.new do |s|
8
9
  s.platform = Gem::Platform::RUBY
9
10
  s.authors = ["Jack Chu"]
10
11
  s.email = ["jack@jackchu.com"]
11
- s.homepage = "http://jackchu.com/automated-heroku-database-backups-to-s3"
12
+ s.homepage = "http://jackchu.com/blog/2011/06/10/automated-heroku-database-backups-to-amazon-s3/"
12
13
  s.summary = %q{Backup pg dumps to the cloud}
13
14
  s.description = %q{PG backups into the cloud with fog}
14
15
 
@@ -18,6 +19,9 @@ Gem::Specification.new do |s|
18
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
21
  s.require_paths = ["lib"]
21
- s.add_runtime_dependency('fog', '>= 0.7.2')
22
- s.add_runtime_dependency('heroku', '>= 2.1.4')
22
+
23
+ s.add_runtime_dependency 'fog', '>= 0.7.2'
24
+ s.add_runtime_dependency 'heroku', '>= 2.1.4'
25
+ s.add_development_dependency 'rake'
26
+ s.add_development_dependency 'minitest'
23
27
  end
@@ -1,8 +1,9 @@
1
+ # encoding: utf-8
2
+
1
3
  module HerokuCloudBackup
2
4
  module Errors
3
5
  class Error < StandardError; end
4
6
  class NotFound < HerokuCloudBackup::Errors::Error; end
5
- class InvalidProvider < HerokuCloudBackup::Errors::Error; end
6
7
  class ConnectionError < HerokuCloudBackup::Errors::Error; end
7
8
  class UploadError < HerokuCloudBackup::Errors::Error; end
8
9
  class NoBackups < HerokuCloudBackup::Errors::Error; end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'heroku_cloud_backup'
2
4
 
3
5
  module HerokuCloudBackup
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'heroku_cloud_backup'
2
4
 
3
5
  namespace :heroku do
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module HerokuCloudBackup
2
- VERSION = "0.0.7"
4
+ VERSION = "0.1.0"
3
5
  end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'fog'
2
4
  require 'open-uri'
3
5
  require "heroku"
@@ -8,80 +10,20 @@ require 'heroku_cloud_backup/version'
8
10
 
9
11
  module HerokuCloudBackup
10
12
  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
13
  def execute
39
14
  log "heroku:backup started"
40
15
 
41
- @bucket_name = ENV['HCB_BUCKET'] || raise(HerokuCloudBackup::Errors::NotFound.new("Please provide a 'HCB_BUCKET' config variable."))
42
- @backup_path = ENV['HCB_PREFIX'] || "db"
43
- @provider = ENV['HCB_PROVIDER'] || raise(HerokuCloudBackup::Errors::NotFound.new("Please provide a 'HCB_PROVIDER' config variable."))
44
- @key1 = ENV['HCB_KEY1'] || raise(HerokuCloudBackup::Errors::NotFound.new("Please provide a 'HCB_KEY1' config variable."))
45
- @key2 = ENV['HCB_KEY2'] || raise(HerokuCloudBackup::Errors::NotFound.new("Please provide a 'HCB_KEY2' config variable."))
46
-
47
16
  b = client.get_backups.last
48
- raise HerokuCloudBackup::Errors::NoBackups.new("You don't have any pgbackups. Please run heroku pgbackups:capture first.") unless b
17
+ raise HerokuCloudBackup::Errors::NoBackups.new("You don't have any pgbackups. Please run heroku pgbackups:capture first.") if b.empty?
49
18
 
50
19
  begin
51
- case @provider
52
- when 'aws'
53
- @connection = Fog::Storage.new(
54
- :provider => 'AWS',
55
- :aws_access_key_id => @key1,
56
- :aws_secret_access_key => @key2
57
- )
58
- when 'rackspace'
59
- @connection = Fog::Storage.new(
60
- :provider => 'Rackspace',
61
- :rackspace_username => @key1,
62
- :rackspace_api_key => @key2
63
- )
64
- when 'google'
65
- @connection = Fog::Storage.new(
66
- :provider => 'Google',
67
- :google_storage_secret_access_key => @key1,
68
- :google_storage_access_key_id => @key2
69
- )
70
- else
71
- raise HerokuCloudBackup::Errors::InvalidProvider.new("Your provider was invalid. Valid values are 'aws', 'rackspace', or 'google'")
72
- end
73
- rescue
74
- raise HerokuCloudBackup::Errors::ConnectionError.new("There was an error connecting to your provider.")
75
- end
76
-
77
- begin
78
- directory = @connection.directories.get(@bucket_name)
20
+ directory = connection.directories.get(bucket_name)
79
21
  rescue Excon::Errors::Forbidden
80
22
  raise HerokuCloudBackup::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.")
81
23
  end
82
24
 
83
25
  if !directory
84
- directory = @connection.directories.create(:key => @bucket_name)
26
+ directory = connection.directories.create(:key => bucket_name)
85
27
  end
86
28
 
87
29
  public_url = b["public_url"]
@@ -90,7 +32,7 @@ module HerokuCloudBackup
90
32
  name = "#{created_at.strftime('%Y-%m-%d-%H%M%S')}.dump"
91
33
  begin
92
34
  log "creating #{@backup_path}/#{b["from_name"]}/#{name}"
93
- directory.files.create(:key => "#{@backup_path}/#{b["from_name"]}/#{name}", :body => open(public_url))
35
+ directory.files.create(:key => "#{backup_path}/#{b["from_name"]}/#{name}", :body => open(public_url))
94
36
  rescue Exception => e
95
37
  raise HerokuCloudBackup::Errors::UploadError.new(e.message)
96
38
  end
@@ -100,16 +42,79 @@ module HerokuCloudBackup
100
42
  log "heroku:backup complete"
101
43
  end
102
44
 
45
+ def connection=(connection)
46
+ @connection = connection
47
+ end
48
+
49
+ def connection
50
+ return @connection if @connection
51
+ self.connection =
52
+ begin
53
+ case provider
54
+ when 'aws'
55
+ Fog::Storage.new(:provider => 'AWS',
56
+ :aws_access_key_id => key1,
57
+ :aws_secret_access_key => key2
58
+ )
59
+ when 'rackspace'
60
+ Fog::Storage.new(:provider => 'Rackspace',
61
+ :rackspace_username => key1,
62
+ :rackspace_api_key => key2
63
+ )
64
+ when 'google'
65
+ Fog::Storage.new(:provider => 'Google',
66
+ :google_storage_secret_access_key => key1,
67
+ :google_storage_access_key_id => key2
68
+ )
69
+ else
70
+ raise "Your provider was invalid. Valid values are 'aws', 'rackspace', or 'google'"
71
+ end
72
+ rescue => error
73
+ raise HerokuCloudBackup::Errors::ConnectionError.new("There was an error connecting to your provider. #{error}")
74
+ end
75
+ end
76
+
77
+ def client
78
+ @client ||= PGBackups::Client.new(backups_url)
79
+ end
80
+
103
81
  private
82
+ def backups_url
83
+ ENV["PGBACKUPS_URL"] || raise(HerokuCloudBackup::Errors::NotFound.new("'PGBACKUPS_URL' environment variable not found."))
84
+ end
85
+
86
+ def bucket_name
87
+ ENV['HCB_BUCKET'] || raise(HerokuCloudBackup::Errors::NotFound.new("Please provide a 'HCB_BUCKET' config variable."))
88
+ end
89
+
90
+ def backup_path
91
+ ENV['HCB_PREFIX'] || "db"
92
+ end
93
+
94
+ def provider
95
+ ENV['HCB_PROVIDER'] || raise(HerokuCloudBackup::Errors::NotFound.new("Please provide a 'HCB_PROVIDER' config variable."))
96
+ end
97
+
98
+ def key1
99
+ ENV['HCB_KEY1'] || raise(HerokuCloudBackup::Errors::NotFound.new("Please provide a 'HCB_KEY1' config variable."))
100
+ end
101
+
102
+ def key2
103
+ ENV['HCB_KEY2'] || raise(HerokuCloudBackup::Errors::NotFound.new("Please provide a 'HCB_KEY2' config variable."))
104
+ end
105
+
106
+ def log(message)
107
+ puts "[#{Time.now}] #{message}"
108
+ end
104
109
 
105
110
  def prune
106
111
  number_of_files = ENV['HCB_MAX']
107
112
  if number_of_files && number_of_files.to_i > 0
108
- directory = @connection.directories.get(@bucket_name)
109
- files = directory.files.all(:prefix => @backup_path)
113
+ directory = connection.directories.get(bucket_name)
114
+ files = directory.files.all(:prefix => backup_path)
110
115
  file_count = 0
111
116
  files.reverse.each do |file|
112
- if file.key =~ Regexp.new("/#{@backup_path}\/\d{4}-\d{2}-\d{2}-\d{6}\.sql\.gz$/i")
117
+ if file.key =~ Regexp.new("/#{backup_path}\/\d{4}-\d{2}-\d{2}-\d{6}\.sql\.gz$/i")
113
118
  file_count += 1
114
119
  else
115
120
  next
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ require 'minitest/autorun'
4
+ require "heroku_cloud_backup"
5
+
6
+ class MiniTest::Spec
7
+ class << self
8
+ alias :context :describe
9
+ end
10
+ end
11
+
12
+ describe HerokuCloudBackup do
13
+ before(:each) do
14
+ Fog.mock!
15
+ end
16
+
17
+ context ".client" do
18
+ it "should return an instance of PGBackups::Client" do
19
+ ENV['PGBACKUPS_URL'] = "http://example.com"
20
+ HerokuCloudBackup.client.must_be_instance_of PGBackups::Client
21
+ end
22
+ end
23
+
24
+ context ".connection" do
25
+ before(:each) do
26
+ ENV['HCB_KEY1'] = ENV['HCB_KEY2'] = 'testcredentials'
27
+ end
28
+
29
+ after(:each) do
30
+ HerokuCloudBackup.connection = nil
31
+ end
32
+
33
+ %w(aws rackspace google).each do |provider|
34
+ context "with HCB_PROVIDER=#{provider}" do
35
+ let(:connection) do
36
+ ENV['HCB_PROVIDER'] = provider
37
+ HerokuCloudBackup.connection
38
+ end
39
+
40
+ it "should return a valid storage object if provider is #{provider}" do
41
+ connection.wont_be_nil
42
+ end
43
+
44
+ it "should return a storage object matching the provider" do
45
+ connection.class.name.must_match(/^Fog::Storage::#{provider}::/i)
46
+ end
47
+ end
48
+ end
49
+
50
+ it "should raise HerokuCloudBackup::Errors::ConnectionError exception if provider is invalid" do
51
+ ENV['HCB_PROVIDER'] = "notsupported"
52
+ lambda { HerokuCloudBackup.connection }.must_raise HerokuCloudBackup::Errors::ConnectionError
53
+ end
54
+ end
55
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heroku_cloud_backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-19 00:00:00.000000000Z
12
+ date: 2012-02-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog
16
- requirement: &2153049140 !ruby/object:Gem::Requirement
16
+ requirement: &70160610629320 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.7.2
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2153049140
24
+ version_requirements: *70160610629320
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: heroku
27
- requirement: &2153048640 !ruby/object:Gem::Requirement
27
+ requirement: &70160610628780 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,29 @@ dependencies:
32
32
  version: 2.1.4
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2153048640
35
+ version_requirements: *70160610628780
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &70160610628380 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70160610628380
47
+ - !ruby/object:Gem::Dependency
48
+ name: minitest
49
+ requirement: &70160610627780 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70160610627780
36
58
  description: PG backups into the cloud with fog
37
59
  email:
38
60
  - jack@jackchu.com
@@ -41,6 +63,7 @@ extensions: []
41
63
  extra_rdoc_files: []
42
64
  files:
43
65
  - .gitignore
66
+ - .travis.yml
44
67
  - Gemfile
45
68
  - LICENSE
46
69
  - README.md
@@ -51,7 +74,8 @@ files:
51
74
  - lib/heroku_cloud_backup/railtie.rb
52
75
  - lib/heroku_cloud_backup/tasks.rb
53
76
  - lib/heroku_cloud_backup/version.rb
54
- homepage: http://jackchu.com/automated-heroku-database-backups-to-s3
77
+ - spec/heroku_cloud_backup_spec.rb
78
+ homepage: http://jackchu.com/blog/2011/06/10/automated-heroku-database-backups-to-amazon-s3/
55
79
  licenses: []
56
80
  post_install_message:
57
81
  rdoc_options: []
@@ -71,8 +95,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
95
  version: '0'
72
96
  requirements: []
73
97
  rubyforge_project: heroku_cloud_backup
74
- rubygems_version: 1.8.10
98
+ rubygems_version: 1.8.15
75
99
  signing_key:
76
100
  specification_version: 3
77
101
  summary: Backup pg dumps to the cloud
78
- test_files: []
102
+ test_files:
103
+ - spec/heroku_cloud_backup_spec.rb