heroku_cloud_backup 0.0.7 → 0.1.0

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.
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