backy_rb 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.drone.yml +13 -0
  3. data/.idea/.gitignore +8 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +23 -0
  6. data/CHANGELOG.md +5 -0
  7. data/Gemfile +16 -0
  8. data/Gemfile.lock +120 -0
  9. data/README.md +36 -0
  10. data/Rakefile +10 -0
  11. data/backy.gemspec +45 -0
  12. data/bucky.png +0 -0
  13. data/config/database.example.yml +15 -0
  14. data/dummy/psql/.gitattributes +7 -0
  15. data/dummy/psql/.gitignore +22 -0
  16. data/dummy/psql/.ruby-version +1 -0
  17. data/dummy/psql/Gemfile +34 -0
  18. data/dummy/psql/Gemfile.lock +207 -0
  19. data/dummy/psql/README.md +24 -0
  20. data/dummy/psql/Rakefile +6 -0
  21. data/dummy/psql/app/assets/config/manifest.js +2 -0
  22. data/dummy/psql/app/assets/images/.keep +0 -0
  23. data/dummy/psql/app/assets/stylesheets/application.css +15 -0
  24. data/dummy/psql/app/controllers/application_controller.rb +2 -0
  25. data/dummy/psql/app/controllers/concerns/.keep +0 -0
  26. data/dummy/psql/app/controllers/posts_controller.rb +59 -0
  27. data/dummy/psql/app/helpers/application_helper.rb +2 -0
  28. data/dummy/psql/app/helpers/posts_helper.rb +2 -0
  29. data/dummy/psql/app/models/application_record.rb +3 -0
  30. data/dummy/psql/app/models/concerns/.keep +0 -0
  31. data/dummy/psql/app/models/post.rb +2 -0
  32. data/dummy/psql/app/views/layouts/application.html.erb +15 -0
  33. data/dummy/psql/app/views/posts/_form.html.erb +27 -0
  34. data/dummy/psql/app/views/posts/_post.html.erb +12 -0
  35. data/dummy/psql/app/views/posts/edit.html.erb +10 -0
  36. data/dummy/psql/app/views/posts/index.html.erb +14 -0
  37. data/dummy/psql/app/views/posts/new.html.erb +9 -0
  38. data/dummy/psql/app/views/posts/show.html.erb +10 -0
  39. data/dummy/psql/bin/bundle +109 -0
  40. data/dummy/psql/bin/rails +4 -0
  41. data/dummy/psql/bin/rake +4 -0
  42. data/dummy/psql/bin/setup +33 -0
  43. data/dummy/psql/config/application.rb +43 -0
  44. data/dummy/psql/config/boot.rb +3 -0
  45. data/dummy/psql/config/credentials.yml.enc +1 -0
  46. data/dummy/psql/config/database.yml +87 -0
  47. data/dummy/psql/config/environment.rb +5 -0
  48. data/dummy/psql/config/environments/development.rb +62 -0
  49. data/dummy/psql/config/environments/production.rb +75 -0
  50. data/dummy/psql/config/environments/test.rb +50 -0
  51. data/dummy/psql/config/locales/en.yml +33 -0
  52. data/dummy/psql/config/master.key +1 -0
  53. data/dummy/psql/config/puma.rb +43 -0
  54. data/dummy/psql/config/routes.rb +7 -0
  55. data/dummy/psql/config.ru +6 -0
  56. data/dummy/psql/db/migrate/20230330203226_create_posts.rb +10 -0
  57. data/dummy/psql/db/schema.rb +23 -0
  58. data/dummy/psql/db/seeds.rb +8 -0
  59. data/dummy/psql/log/.keep +0 -0
  60. data/dummy/psql/public/404.html +67 -0
  61. data/dummy/psql/public/422.html +67 -0
  62. data/dummy/psql/public/500.html +66 -0
  63. data/dummy/psql/public/apple-touch-icon-precomposed.png +0 -0
  64. data/dummy/psql/public/apple-touch-icon.png +0 -0
  65. data/dummy/psql/public/favicon.ico +0 -0
  66. data/dummy/psql/public/robots.txt +1 -0
  67. data/dummy/psql/tmp/.keep +0 -0
  68. data/dummy/psql/tmp/pids/.keep +0 -0
  69. data/lib/backy/app_config.rb +11 -0
  70. data/lib/backy/cli.rb +0 -0
  71. data/lib/backy/configuration.rb +66 -0
  72. data/lib/backy/db.rb +29 -0
  73. data/lib/backy/list.rb +18 -0
  74. data/lib/backy/pg_dump.rb +39 -0
  75. data/lib/backy/pg_restore.rb +27 -0
  76. data/lib/backy/railtie.rb +19 -0
  77. data/lib/backy/s3.rb +27 -0
  78. data/lib/backy/s3_list.rb +31 -0
  79. data/lib/backy/s3_load.rb +41 -0
  80. data/lib/backy/s3_save.rb +33 -0
  81. data/lib/backy/version.rb +3 -0
  82. data/lib/backy.rb +30 -0
  83. data/lib/tasks/backy_tasks.rake +84 -0
  84. metadata +291 -0
@@ -0,0 +1,33 @@
1
+ # Files in the config/locales directory are used for internationalization
2
+ # and are automatically loaded by Rails. If you want to use locales other
3
+ # than English, add the necessary files in this directory.
4
+ #
5
+ # To use the locales, use `I18n.t`:
6
+ #
7
+ # I18n.t "hello"
8
+ #
9
+ # In views, this is aliased to just `t`:
10
+ #
11
+ # <%= t("hello") %>
12
+ #
13
+ # To use a different locale, set it with `I18n.locale`:
14
+ #
15
+ # I18n.locale = :es
16
+ #
17
+ # This would use the information in config/locales/es.yml.
18
+ #
19
+ # The following keys must be escaped otherwise they will not be retrieved by
20
+ # the default I18n backend:
21
+ #
22
+ # true, false, on, off, yes, no
23
+ #
24
+ # Instead, surround them with single quotes.
25
+ #
26
+ # en:
27
+ # "true": "foo"
28
+ #
29
+ # To learn more, please read the Rails Internationalization guide
30
+ # available at https://guides.rubyonrails.org/i18n.html.
31
+
32
+ en:
33
+ hello: "Hello world"
@@ -0,0 +1 @@
1
+ 15729cca85c03e01e7b263643b18dfd7
@@ -0,0 +1,43 @@
1
+ # Puma can serve each request in a thread from an internal thread pool.
2
+ # The `threads` method setting takes two numbers: a minimum and maximum.
3
+ # Any libraries that use thread pools should be configured to match
4
+ # the maximum value specified for Puma. Default is set to 5 threads for minimum
5
+ # and maximum; this matches the default thread size of Active Record.
6
+ #
7
+ max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
8
+ min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
9
+ threads min_threads_count, max_threads_count
10
+
11
+ # Specifies the `worker_timeout` threshold that Puma will use to wait before
12
+ # terminating a worker in development environments.
13
+ #
14
+ worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
15
+
16
+ # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
17
+ #
18
+ port ENV.fetch("PORT") { 3000 }
19
+
20
+ # Specifies the `environment` that Puma will run in.
21
+ #
22
+ environment ENV.fetch("RAILS_ENV") { "development" }
23
+
24
+ # Specifies the `pidfile` that Puma will use.
25
+ pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
26
+
27
+ # Specifies the number of `workers` to boot in clustered mode.
28
+ # Workers are forked web server processes. If using threads and workers together
29
+ # the concurrency of the application would be max `threads` * `workers`.
30
+ # Workers do not work on JRuby or Windows (both of which do not support
31
+ # processes).
32
+ #
33
+ # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
34
+
35
+ # Use the `preload_app!` method when specifying a `workers` number.
36
+ # This directive tells Puma to first boot the application and load code
37
+ # before forking the application. This takes advantage of Copy On Write
38
+ # process behavior so workers use less memory.
39
+ #
40
+ # preload_app!
41
+
42
+ # Allow puma to be restarted by `bin/rails restart` command.
43
+ plugin :tmp_restart
@@ -0,0 +1,7 @@
1
+ Rails.application.routes.draw do
2
+ resources :posts
3
+ # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
4
+
5
+ # Defines the root path route ("/")
6
+ root "posts#index"
7
+ end
@@ -0,0 +1,6 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require_relative "config/environment"
4
+
5
+ run Rails.application
6
+ Rails.application.load_server
@@ -0,0 +1,10 @@
1
+ class CreatePosts < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :posts do |t|
4
+ t.string :title
5
+ t.text :body
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema[7.0].define(version: 2023_03_30_203226) do
14
+ # These are extensions that must be enabled in order to support this database
15
+ enable_extension "plpgsql"
16
+
17
+ create_table "posts", force: :cascade do |t|
18
+ t.string "title"
19
+ t.text "body"
20
+ t.datetime "created_at", null: false
21
+ t.datetime "updated_at", null: false
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ require "faker"
2
+
3
+ 100.times do
4
+ Post.create(
5
+ title: Faker::Lorem.sentence,
6
+ body: Faker::Lorem.paragraph
7
+ )
8
+ end
File without changes
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ .rails-default-error-page {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ .rails-default-error-page div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ .rails-default-error-page div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ .rails-default-error-page h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ .rails-default-error-page div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body class="rails-default-error-page">
58
+ <!-- This file lives in public/404.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The page you were looking for doesn't exist.</h1>
62
+ <p>You may have mistyped the address or the page may have moved.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ .rails-default-error-page {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ .rails-default-error-page div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ .rails-default-error-page div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ .rails-default-error-page h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ .rails-default-error-page div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body class="rails-default-error-page">
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ .rails-default-error-page {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ .rails-default-error-page div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ .rails-default-error-page div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ .rails-default-error-page h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ .rails-default-error-page div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body class="rails-default-error-page">
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
File without changes
@@ -0,0 +1 @@
1
+ # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ require 'forwardable'
2
+
3
+ module Backy
4
+ module AppConfig
5
+ extend Forwardable
6
+
7
+ private
8
+
9
+ def_delegators "Backy.configuration", :app_name, :environment, :log_file
10
+ end
11
+ end
data/lib/backy/cli.rb ADDED
File without changes
@@ -0,0 +1,66 @@
1
+ module Backy
2
+ class Configuration
3
+ attr_writer(
4
+ :pg_host,
5
+ :pg_port,
6
+ :pg_database,
7
+ :pg_username,
8
+ :pg_password,
9
+ :s3_region,
10
+ :s3_access_key,
11
+ :s3_secret,
12
+ :s3_bucket,
13
+ :app_name,
14
+ :environment,
15
+ :log_file
16
+ )
17
+
18
+ def pg_host
19
+ @pg_host ||= ENV["PG_HOST"]
20
+ end
21
+
22
+ def pg_port
23
+ @pg_port ||= ENV["PG_PORT"]
24
+ end
25
+
26
+ def pg_database
27
+ @pg_database ||= ENV["PG_DATABASE"]
28
+ end
29
+
30
+ def pg_username
31
+ @pg_username ||= ENV["PG_USERNAME"]
32
+ end
33
+
34
+ def pg_password
35
+ @pg_password ||= ENV["PG_PASSWORD"]
36
+ end
37
+
38
+ def s3_region
39
+ @s3_region ||= ENV["S3_REGION"]
40
+ end
41
+
42
+ def s3_access_key
43
+ @s3_access_key ||= ENV["S3_ACCESS_KEY"]
44
+ end
45
+
46
+ def s3_secret
47
+ @s3_secret ||= ENV["S3_SECRET"]
48
+ end
49
+
50
+ def s3_bucket
51
+ @s3_bucket ||= ENV["S3_BUCKET"]
52
+ end
53
+
54
+ def app_name
55
+ @app_name ||= "backy"
56
+ end
57
+
58
+ def environment
59
+ @environment ||= "development"
60
+ end
61
+
62
+ def log_file
63
+ @log_file ||= "log/backy.log"
64
+ end
65
+ end
66
+ end
data/lib/backy/db.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'forwardable'
2
+
3
+ module Backy
4
+ module Db
5
+ extend Forwardable
6
+
7
+ private
8
+
9
+ def_delegator "Backy.configuration", :pg_host, :host
10
+ def_delegator "Backy.configuration", :pg_port, :port
11
+ def_delegator "Backy.configuration", :pg_database, :database
12
+ def_delegator "Backy.configuration", :pg_username, :username
13
+ def_delegator "Backy.configuration", :pg_password, :password
14
+
15
+ def pg_password_env
16
+ password.present? ? "PGPASSWORD='#{password}' " : ""
17
+ end
18
+
19
+ def pg_credentials
20
+ args_string = ""
21
+
22
+ args_string << " -U #{username}" if username.present?
23
+ args_string << " -h #{host}" if host.present?
24
+ args_string << " -p #{port}" if port.present?
25
+
26
+ args_string
27
+ end
28
+ end
29
+ end
data/lib/backy/list.rb ADDED
@@ -0,0 +1,18 @@
1
+ module Backy
2
+ class List
3
+ def call
4
+ locals = Set.new(Dir.glob(dump_wildcard))
5
+ remotes = Set.new(S3List.new.call)
6
+
7
+ (locals + remotes).sort.map do |dump_file|
8
+ OpenStruct.new(local?: dump_file.in?(locals), remote?: dump_file.in?(remotes), dump_file: dump_file)
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def dump_wildcard
15
+ PgDump::DUMP_DIR + "/*"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,39 @@
1
+ module Backy
2
+ class PgDump
3
+ include Db
4
+ include AppConfig
5
+
6
+ DUMP_DIR = "db/dump"
7
+ DUMP_CMD_OPTS = "--no-acl --no-owner --no-subscriptions --no-publications --exclude-table=awsdms_ddl_audit"
8
+
9
+ def call
10
+ FileUtils.mkdir_p(DUMP_DIR)
11
+
12
+ dump_file = "#{DUMP_DIR}/#{database}_#{whoami}@#{hostname}_#{Time.zone.now.strftime("%Y%m%d_%H%M%S")}.sql.gz"
13
+
14
+ cmd = "(#{pg_password_env}pg_dump #{pg_credentials} #{database} #{DUMP_CMD_OPTS} | gzip -9 > #{dump_file}) 2>&1 >> #{log_file}"
15
+
16
+ print "Saving to #{dump_file} ... "
17
+
18
+ if system(cmd)
19
+ puts "done"
20
+ else
21
+ puts "error. See #{log_file}"
22
+
23
+ return
24
+ end
25
+
26
+ dump_file
27
+ end
28
+
29
+ private
30
+
31
+ def hostname
32
+ @hostname ||= `hostname`.strip
33
+ end
34
+
35
+ def whoami
36
+ @whoami ||= `whoami`.strip
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ module Backy
2
+ class PgRestore
3
+ include Db
4
+ include AppConfig
5
+
6
+ def initialize(file_name:)
7
+ @file_name = file_name
8
+ end
9
+
10
+ def call
11
+ terminate_connection_sql = "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '#{database}' AND pid <> pg_backend_pid();"
12
+ cmd = "(#{pg_password_env}psql -c \"#{terminate_connection_sql};\" #{pg_credentials} #{database}; #{pg_password_env}dropdb #{pg_credentials} #{database}; #{pg_password_env}createdb #{pg_credentials} #{database}; gunzip -c #{file_name} | #{pg_password_env}psql #{pg_credentials} -q -d #{database}) 2>&1 >> #{log_file}"
13
+
14
+ print "Restoring #{database} from #{file_name} ... "
15
+
16
+ if system(cmd)
17
+ puts "done"
18
+ else
19
+ puts "error. See #{log_file}"
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :file_name
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ module Backy
2
+ class Railtie < Rails::Railtie
3
+ initializer "railtie.configure_rails_initialization" do
4
+ Backy.configure do |config|
5
+ config.pg_host = ActiveRecord::Base.connection_db_config.configuration_hash[:host]
6
+ config.pg_port = ActiveRecord::Base.connection_db_config.configuration_hash[:port]
7
+ config.pg_database = ActiveRecord::Base.connection_db_config.configuration_hash[:database]
8
+ config.pg_username = ActiveRecord::Base.connection_db_config.configuration_hash[:username]
9
+ config.pg_password = ActiveRecord::Base.connection_db_config.configuration_hash[:password]
10
+ config.app_name = Rails.application.class.name.split("::").first.underscore
11
+ config.environment = Rails.env
12
+ end
13
+ end
14
+
15
+ rake_tasks do
16
+ load "tasks/backy_tasks.rake"
17
+ end
18
+ end
19
+ end
data/lib/backy/s3.rb ADDED
@@ -0,0 +1,27 @@
1
+ require "aws-sdk-s3"
2
+ require 'forwardable'
3
+
4
+ module Backy
5
+ module S3
6
+ extend Forwardable
7
+
8
+ private
9
+
10
+ def_delegator "Backy.configuration", :s3_region, :region
11
+ def_delegator "Backy.configuration", :s3_secret, :secret
12
+ def_delegator "Backy.configuration", :s3_bucket, :bucket
13
+ def_delegator "Backy.configuration", :s3_access_key, :access_key
14
+
15
+ def s3
16
+ @s3 ||= Aws::S3::Client.new(region: region, credentials: s3_credentials)
17
+ end
18
+
19
+ def s3_configured?
20
+ [region, access_key, secret, bucket].all?(&:present?)
21
+ end
22
+
23
+ def s3_credentials
24
+ @credentials ||= Aws::Credentials.new(access_key, secret)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ module Backy
2
+ class S3List
3
+ include S3
4
+
5
+ DEFAULT_PREFIX = "db/dump/"
6
+
7
+ def initialize(prefix: nil)
8
+ @prefix = prefix || DEFAULT_PREFIX
9
+ end
10
+
11
+ def call
12
+ return [] unless s3_configured?
13
+
14
+ response = s3.list_objects(prefix: prefix, bucket: bucket)
15
+
16
+ result = response.contents.map(&:key)
17
+
18
+ while response.next_page?
19
+ response = response.next_page
20
+
21
+ result += response.contents.map(&:key)
22
+ end
23
+
24
+ result.sort
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :prefix
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ module Backy
2
+ class S3Load
3
+ include S3
4
+
5
+ def initialize(file_name:, key: nil)
6
+ @file_name = file_name
7
+ @key = key || file_name
8
+ end
9
+
10
+ def call
11
+ return file_name if File.exist?(file_name)
12
+
13
+ print "Loading #{key} from S3 ... "
14
+
15
+ Tempfile.create(file_name) do |tempfile|
16
+ response_target = tempfile.path
17
+
18
+ begin
19
+ s3.get_object(response_target: response_target, key: key, bucket: bucket)
20
+ FileUtils.mkdir_p(File.dirname(file_name))
21
+ FileUtils.mv(response_target, file_name)
22
+ rescue Aws::S3::Errors::NoSuchKey
23
+ puts "error. No such key #{key}"
24
+ ensure
25
+ if File.exist?(tempfile.path)
26
+ tempfile.close
27
+ File.delete(tempfile.path)
28
+ end
29
+ end
30
+ end
31
+
32
+ puts "done"
33
+
34
+ file_name
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :key, :file_name
40
+ end
41
+ end