uff_db_loader 1.3.0 → 2.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f807430f4dff47a2a9a98b6f360720a51a7f96c9af2554e0784383adaf0fe63
4
- data.tar.gz: dfaf6dad64eea0e267872426f1426534703e52257c8e29a6440c174a94a94f72
3
+ metadata.gz: 28a567bb65dcdcc545605a5b8b921abe6fb6b4b666d97928e659bf535a1675ed
4
+ data.tar.gz: 4deffc2f8bad009cd16d04f08280765be75042da0f6e6e97d488addd22a51065
5
5
  SHA512:
6
- metadata.gz: c1bed481bd67cc2d5dc3000b6d8b67d17ae0e3f7631302b717c436827862538ab679b52edea76777e8a6f2e1d103caca6c5b75796f64dcf457c7bec7e5a6b226
7
- data.tar.gz: 05defe18ffd2c6719180c26fcab48c85de42cba697834162c9ca81a15e8394760afe8e5daf60e287bc7611b2d257d3a58cbe98778ea2c119275a0a692673bbb3
6
+ metadata.gz: 22b2e2a27364e1afccda77edf18218c9c0862ee0ef389126e745848fceb08fb9fb73b042e07a71a9bddacc2818262d36c9ba109cadc5840c1c3b6175190ccfb5
7
+ data.tar.gz: d8ddddf06be94aa6d2799e7beaeff371c2897cbb7cf6e83855ed112325cc2796732c23082214aa9aa938be023f881e354d2607197dd01a9923777962068c555f
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## Installation
8
8
 
9
- Add this line to your application's Gemfile:
9
+ Add this line to your application's `Gemfile`:
10
10
 
11
11
  ```ruby
12
12
  gem 'uff_db_loader'
@@ -20,14 +20,16 @@ Or install it yourself as:
20
20
 
21
21
  $ gem install uff_db_loader
22
22
 
23
+ Run the installation script:
24
+
25
+ $ bin/rails uff_db_loader:install
26
+
23
27
  ## Configuration
24
28
 
25
29
  You can configure the gem by running the following during the initialization of the Rails app:
26
30
  ```ruby
27
- # frozen_string_literal: true
28
-
29
31
  UffDbLoader.configure do |config|
30
- config.environments = ['sandbox', 'production'] # default is "['staging', 'production']"
32
+ config.environments = ['staging', 'production']
31
33
  config.ssh_user = 'Francina'
32
34
  config.ssh_host = 'host.of.yoursite'
33
35
  config.db_name = 'twotter'
@@ -43,10 +45,13 @@ Make sure the app's database user has the superuser role. Otherwise the app will
43
45
 
44
46
  ## Usage
45
47
 
46
- `uff_db_loader` provides `rails uff_db_loader:dump` and `rails uff_db_loader:load` which will prompt for a configured environment.
47
- `dump` will only create and download a current database dump, while `load`, will do the same and restore the database content into a new database and gives instructions on how to use it in development.
48
-
48
+ `uff_db_loader` can be called like `bin/rails uff_db_loader:<task>` where `<task>` is one of the following:
49
49
 
50
+ - `dump`: Dumps a remote database from a selected environment and downloads it
51
+ - `restore`: Restores a downloaded dump into a local database
52
+ - `switch`: Selects a restored local database to use
53
+ - `load`: Dumps a remote database from a selected environment and downloads it then restores and selects the database
54
+ - `prune`: Delete all downloaded db dumps and removes all databases created by UffDbLoader
50
55
 
51
56
  ## Development
52
57
 
data/lib/configuration.rb CHANGED
@@ -8,7 +8,7 @@ module UffDbLoader
8
8
  attr_accessor :environments, :ssh_host, :ssh_user, :db_name, :db_system, :app_name, :dumps_directory, :database_config_file
9
9
 
10
10
  def initialize
11
- @environments = %w[staging production]
11
+ @environments = nil
12
12
  @ssh_host = nil
13
13
  @ssh_user = nil
14
14
  @db_name = nil
@@ -3,7 +3,21 @@
3
3
  require "tty-prompt"
4
4
 
5
5
  namespace :uff_db_loader do
6
- desc "Dumps a remote database to #{UffDbLoader.config.dumps_directory}"
6
+ desc "Set up UffDbLoader"
7
+ task install: :environment do
8
+ UffDbLoader.create_initializer
9
+
10
+ puts "👶 Created a Rails initializer file at #{UffDbLoader.initializer_path}."
11
+
12
+ if UffDbLoader.setup_dynamic_database_name_in_config
13
+ puts "🤖 Updated #{UffDbLoader.config.database_config_file}. Happy hacking, beep boop!"
14
+ else
15
+ puts "💩 Because YAML is a wonderful format, you need to adapt your config file by hand."
16
+ puts "🆗 Go to #{UffDbLoader.config.database_config_file} and change the development database value to: #{UffDbLoader.database_name_template("default_database_name")}"
17
+ end
18
+ end
19
+
20
+ desc "Dumps a remote database from a selected environment to #{UffDbLoader.config.dumps_directory}"
7
21
  task dump: :environment do
8
22
  prompt = TTY::Prompt.new
9
23
  environment = prompt.select("Which environment should we get the dump from?", UffDbLoader.config.environments)
@@ -11,8 +25,35 @@ namespace :uff_db_loader do
11
25
  UffDbLoader.dump_from(environment)
12
26
  end
13
27
 
14
- desc "Gets a dump from remote and loads it into the local database"
28
+ desc "Restores a downloaded dump into a local database"
29
+ task restore: :environment do
30
+ UffDbLoader.ensure_installation!
31
+
32
+ prompt = TTY::Prompt.new
33
+ existing_dumps = Dir.glob("#{UffDbLoader.config.dumps_directory}/#{UffDbLoader.config.app_name}*").map { |f| File.basename(f, ".*") }
34
+ database_name = prompt.select("Which dump should be restored?", existing_dumps)
35
+
36
+ UffDbLoader.load_dump_into_database(database_name)
37
+ end
38
+
39
+ desc "Selects a restored local database to use"
40
+ task switch: :environment do
41
+ UffDbLoader.ensure_installation!
42
+
43
+ prompt = TTY::Prompt.new
44
+ databases = UffDbLoader.databases
45
+ new_database = prompt.select("Which database do you want to switch to?", databases)
46
+
47
+ UffDbLoader.remember_database_name(new_database)
48
+ UffDbLoader.restart_rails_server
49
+
50
+ puts "♻️ Restarted rails server with new database."
51
+ end
52
+
53
+ desc "Dumps a remote database from a selected environment to #{UffDbLoader.config.dumps_directory}, then restores and selects the database"
15
54
  task load: :environment do
55
+ UffDbLoader.ensure_installation!
56
+
16
57
  prompt = TTY::Prompt.new
17
58
  environment = prompt.select("Which environment should we get the dump from?", UffDbLoader.config.environments)
18
59
  UffDbLoader.ensure_valid_environment!(environment)
@@ -21,27 +62,15 @@ namespace :uff_db_loader do
21
62
  puts "🤓 Reading from to #{result_file_path}"
22
63
 
23
64
  database_name = File.basename(result_file_path, ".*")
24
- UffDbLoader.create_database(database_name)
25
-
26
- puts "🗂 Created database #{database_name}"
27
-
28
- command_successful = system(UffDbLoader.restore_command(database_name, result_file_path))
29
- raise "Command did not run succesful: #{UffDbLoader.restore_command(database_name, result_file_path)}" unless command_successful
30
-
31
- puts "✅ Succesfully loaded #{result_file_path} into #{database_name}"
32
-
33
- if UffDbLoader.replace_database_name_in_config(database_name)
34
- system("bin/rails restart")
35
- puts "🤖 Updated #{UffDbLoader.config.database_config_file} and restarted the rails server. Happy hacking, beep boop!"
36
- else
37
- puts "💩 Because YAML is a wonderful format, you need to adapt your config file by hand."
38
- puts "🆗 Go to #{UffDbLoader.config.database_config_file} and change the development database value to: #{database_name}"
39
- puts "🧑🏾‍🏫 Don't forgot to restart the Rails server after changing the database config (`rails restart`)"
40
- end
65
+ UffDbLoader.load_dump_into_database(database_name)
41
66
  end
42
67
 
43
- desc "Delete all downloaded db dumps and emove all databases created by UffDbLoader"
68
+ desc "Delete all downloaded db dumps and removes all databases created by UffDbLoader"
44
69
  task prune: :environment do
70
+ # switch to default db so we can also drop the currently connected database
71
+ UffDbLoader.remember_database_name("")
72
+ ActiveRecord::Base.connection.reconnect!
73
+
45
74
  UffDbLoader.databases.each do |database_name|
46
75
  puts "Dropping #{database_name}"
47
76
  UffDbLoader.drop_database(database_name)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Check out our README: https://github.com/rmehner/uff_db_loader/blob/main/README.md
4
+
5
+ if defined?(UffDbLoader)
6
+ UffDbLoader.configure do |config|
7
+ config.ssh_user = 'SSH_USER'
8
+ config.ssh_host = 'HOST_OF_YOUR_SITE'
9
+ config.db_name = 'YOUR_DATABASE_NAME'
10
+ config.db_system = <%= used_database_system %> # Possible values are :postgresql and :mysql
11
+ config.environments = <%= environments %>
12
+
13
+ # Optional settings:
14
+ # config.app_name = 'my_app' # Defaults to the Rails app name
15
+ # config.dumps_directory = '/path/to/dumps' # Defaults to Rails.root.join('dumps')
16
+ # config.database_config_file = 'path/to/database.yml' # Defaults to Rails.root.join('config', 'database.yml')
17
+ end
18
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UffDbLoader
4
- VERSION = "1.3.0"
4
+ VERSION = "2.0.0"
5
5
  end
data/lib/uff_db_loader.rb CHANGED
@@ -6,91 +6,183 @@ require "configuration"
6
6
  module UffDbLoader
7
7
  require "railtie"
8
8
 
9
- def self.config
10
- @configuration ||= Configuration.new
11
- end
9
+ class << self
10
+ def config
11
+ @configuration ||= Configuration.new
12
+ end
12
13
 
13
- def self.reset
14
- @configuration = Configuration.new
15
- end
14
+ def reset
15
+ @configuration = Configuration.new
16
+ end
16
17
 
17
- def self.configure
18
- yield(config)
19
- end
18
+ def configure
19
+ yield(config)
20
+ end
20
21
 
21
- def self.dump_filename(environment)
22
- File.join(
23
- config.dumps_directory,
24
- Time.now.strftime("#{config.app_name}_#{environment}_%Y_%m_%d_%H_%M_%S.#{config.database_system.dump_extension}")
25
- )
26
- end
22
+ def restart_rails_server
23
+ system("bin/rails restart")
24
+ end
27
25
 
28
- def self.dump_from(environment)
29
- FileUtils.mkdir_p(config.dumps_directory)
26
+ def dump_from(environment)
27
+ FileUtils.mkdir_p(config.dumps_directory)
30
28
 
31
- puts "⬇️ Creating dump ..."
29
+ puts "⬇️ Creating dump ..."
32
30
 
33
- target = dump_filename(environment)
31
+ target = dump_file_path(Time.now.strftime("#{config.app_name}_#{environment}_%Y_%m_%d_%H_%M_%S)"))
34
32
 
35
- command_successful = system(dump_command(environment, target))
36
- raise "Command did not run succesful: #{dump_command(environment, target)}" unless command_successful
33
+ command_successful = system(dump_command(environment, target))
34
+ raise "Command did not run succesful: #{dump_command(environment, target)}" unless command_successful
37
35
 
38
- puts "✅ Succesfully dumped to #{target}"
36
+ puts "✅ Succesfully dumped to #{target}"
39
37
 
40
- target
41
- end
38
+ target
39
+ end
42
40
 
43
- def self.create_database(database_name)
44
- config.database_system.create_database(database_name)
45
- end
41
+ def ensure_valid_environment!(environment)
42
+ unless config.environments.include?(environment)
43
+ raise ForbiddenEnvironmentError, "Invalid environment: #{environment}."
44
+ end
45
+ end
46
46
 
47
- def self.dump_command(environment, target)
48
- config
49
- .database_system
50
- .dump_command_template
51
- .gsub("%environment%", environment)
52
- .gsub("%host%", config.ssh_host)
53
- .gsub("%user%", config.ssh_user)
54
- .gsub("%database%", config.database)
55
- .gsub("%target%", target)
56
- .gsub("%app_name%", config.app_name)
57
- end
47
+ def prune_dump_directory
48
+ FileUtils.rm_rf("#{config.dumps_directory}/.", secure: true)
49
+ end
58
50
 
59
- def self.ensure_valid_environment!(environment)
60
- unless config.environments.include?(environment)
61
- raise ForbiddenEnvironmentError, "Invalid environment: #{environment}."
51
+ def create_database(database_name)
52
+ config.database_system.create_database(database_name)
62
53
  end
63
- end
64
54
 
65
- def self.restore_command(database_name, result_file_path)
66
- config.database_system.restore_command(database_name, result_file_path)
67
- end
55
+ def drop_database(database_name)
56
+ config.database_system.drop_database(database_name)
57
+ end
68
58
 
69
- def self.prune_dump_directory
70
- FileUtils.rm_rf("#{config.dumps_directory}/.", secure: true)
71
- end
59
+ def databases
60
+ config.database_system.list_databases.select do |line|
61
+ line =~ /#{config.app_name}_(#{config.environments.join("|")})_(\d|_)+/
62
+ end
63
+ end
72
64
 
73
- def self.drop_database(database_name)
74
- config.database_system.drop_database(database_name)
75
- end
65
+ def setup_dynamic_database_name_in_config
66
+ old_database_name = Rails.configuration.database_configuration["development"]["database"]
67
+
68
+ return false if old_database_name.nil?
76
69
 
77
- def self.databases
78
- config.database_system.list_databases.select do |line|
79
- line =~ /#{config.app_name}_(#{config.environments.join("|")})_(\d|_)+/
70
+ old_config = File.read(UffDbLoader.config.database_config_file)
71
+ new_config = old_config.sub(old_database_name, database_name_template(old_database_name))
72
+ File.write(UffDbLoader.config.database_config_file, new_config)
80
73
  end
81
- end
82
74
 
83
- def self.replace_database_name_in_config(new_database_name)
84
- old_database_name = Rails.configuration.database_configuration["development"]["database"]
75
+ def current_database_name
76
+ File.read(database_name_file).strip.presence
77
+ rescue IOError, Errno::ENOENT => e
78
+ puts "Could not read #{database_name_file}. #{e.message} – Falling back to default database. 🥱"
79
+ end
85
80
 
86
- return false if old_database_name.nil?
81
+ def remember_database_name(database_name)
82
+ File.write(database_name_file, database_name)
83
+ end
87
84
 
88
- old_config = File.read(UffDbLoader.config.database_config_file)
89
- new_config = old_config.sub(old_database_name, new_database_name)
90
- File.write(UffDbLoader.config.database_config_file, new_config)
91
- end
85
+ def ensure_installation!
86
+ unless File.read(UffDbLoader.config.database_config_file).include?("UffDbLoader.current_database_name")
87
+ raise InstallationDidNotRunError, "Please run bin/rails uff_db_loader:install"
88
+ end
89
+ end
90
+
91
+ def load_dump_into_database(database_name)
92
+ UffDbLoader.drop_database(database_name)
93
+ UffDbLoader.create_database(database_name)
94
+
95
+ puts "🗂 Created database #{database_name}"
96
+
97
+ dump_file_path = dump_file_path(database_name)
92
98
 
93
- class ForbiddenEnvironmentError < StandardError; end
99
+ command_successful = system(restore_command(database_name, dump_file_path))
100
+ raise "Command did not run succesful: #{restore_command(database_name, dump_file_path)}" unless command_successful
94
101
 
95
- class UnknownDatabaseSystem < StandardError; end
102
+ puts "✅ Succesfully loaded #{dump_file_path} into #{database_name}"
103
+
104
+ remember_database_name(database_name)
105
+ restart_rails_server
106
+
107
+ puts "♻️ Restarted rails server with new database."
108
+ end
109
+
110
+ def initializer_path
111
+ File.join(__dir__, "uff_db_loader", "templates", "uff_db_loader_initializer.erb")
112
+ end
113
+
114
+ def create_initializer
115
+ template = ERB.new(File.read(initializer_path))
116
+
117
+ File.write(
118
+ Rails.root.join("config", "initializers", "uff_db_loader.rb"),
119
+ template.result_with_hash(
120
+ used_database_system: used_database_system,
121
+ environments: environments
122
+ )
123
+ )
124
+ end
125
+
126
+ private
127
+
128
+ def database_name_file
129
+ Rails.root.join("tmp", "uff_db_loader_database_name")
130
+ end
131
+
132
+ def dump_filename(environment)
133
+ File.join(
134
+ config.dumps_directory,
135
+ Time.now.strftime("#{config.app_name}_#{environment}_%Y_%m_%d_%H_%M_%S.#{config.database_system.dump_extension}")
136
+ )
137
+ end
138
+
139
+ def dump_command(environment, target)
140
+ config
141
+ .database_system
142
+ .dump_command_template
143
+ .gsub("%environment%", environment)
144
+ .gsub("%host%", config.ssh_host)
145
+ .gsub("%user%", config.ssh_user)
146
+ .gsub("%database%", config.database)
147
+ .gsub("%target%", target)
148
+ .gsub("%app_name%", config.app_name)
149
+ end
150
+
151
+ def restore_command(database_name, result_file_path)
152
+ config.database_system.restore_command(database_name, result_file_path)
153
+ end
154
+
155
+ def database_name_template(old_database_name)
156
+ "<%= defined?(UffDbLoader) && UffDbLoader.current_database_name || '#{old_database_name}' %>"
157
+ end
158
+
159
+ def dump_file_path(database_name)
160
+ File.join(
161
+ config.dumps_directory,
162
+ "#{database_name}.#{config.database_system.dump_extension}"
163
+ )
164
+ end
165
+
166
+ def used_database_system
167
+ case Rails.configuration.database_configuration["development"]["adapter"]
168
+ when "mysql", "mysql2", "trilogy"
169
+ ":mysql"
170
+ when "postgresql"
171
+ ":postgresql"
172
+ else
173
+ puts "🙃 Could not automatically determine your used database system. Please adapt in the initializer."
174
+ ":unknown"
175
+ end
176
+ end
177
+
178
+ def environments
179
+ ActiveRecord::Base.configurations.configurations.to_a.map(&:env_name) - ["test", "development"]
180
+ end
181
+
182
+ class ForbiddenEnvironmentError < StandardError; end
183
+
184
+ class UnknownDatabaseSystem < StandardError; end
185
+
186
+ class InstallationDidNotRunError < StandardError; end
187
+ end
96
188
  end
@@ -8,6 +8,7 @@ Gem::Specification.new do |spec|
8
8
 
9
9
  spec.summary = "Allows to dump, download and restore databases from docker servers."
10
10
  spec.description = "Allows to dump, download and restore databases from servers with a specific docker setup, that UFF uses commonly."
11
+ spec.post_install_message = "Please run `bin/rails uff_db_loader:install` to complete the installation."
11
12
  spec.homepage = "https://github.com/rmehner/uff_db_loader"
12
13
  spec.license = "MIT"
13
14
  spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uff_db_loader
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Hellwig
8
8
  - Fynn Heintz
9
9
  - Robin Mehner
10
- autorequire:
10
+ autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-08-25 00:00:00.000000000 Z
13
+ date: 2022-09-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: tty-prompt
@@ -79,8 +79,8 @@ files:
79
79
  - lib/uff_db_loader.rb
80
80
  - lib/uff_db_loader/mysql.rb
81
81
  - lib/uff_db_loader/postgresql.rb
82
- - lib/uff_db_loader/tasks/remote_database.rake
83
82
  - lib/uff_db_loader/tasks/uff_db_loader.rake
83
+ - lib/uff_db_loader/templates/uff_db_loader_initializer.erb
84
84
  - lib/uff_db_loader/version.rb
85
85
  - uff_db_loader.gemspec
86
86
  homepage: https://github.com/rmehner/uff_db_loader
@@ -88,10 +88,11 @@ licenses:
88
88
  - MIT
89
89
  metadata:
90
90
  bug_tracker_uri: https://github.com/rmehner/uff_db_loader/issues
91
- changelog_uri: https://github.com/rmehner/uff_db_loader/releases/tag/1.3.0
91
+ changelog_uri: https://github.com/rmehner/uff_db_loader/releases/tag/2.0.0
92
92
  homepage_uri: https://github.com/rmehner/uff_db_loader
93
- source_code_uri: https://github.com/rmehner/uff_db_loader/tree/1.3.0
94
- post_install_message:
93
+ source_code_uri: https://github.com/rmehner/uff_db_loader/tree/2.0.0
94
+ post_install_message: Please run `bin/rails uff_db_loader:install` to complete the
95
+ installation.
95
96
  rdoc_options: []
96
97
  require_paths:
97
98
  - lib
@@ -106,8 +107,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
107
  - !ruby/object:Gem::Version
107
108
  version: '0'
108
109
  requirements: []
109
- rubygems_version: 3.0.3
110
- signing_key:
110
+ rubygems_version: 3.3.8
111
+ signing_key:
111
112
  specification_version: 4
112
113
  summary: Allows to dump, download and restore databases from docker servers.
113
114
  test_files: []
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "tty-prompt"
4
-
5
- namespace :remote_database do
6
- desc "Dumps a remote database to #{UffDbLoader.config.dumps_directory}"
7
- task dump: :environment do
8
- puts "🧐 Please note this task is called 'uff_db_loader:dump' now."
9
- Rake::Task["uff_db_loader:dump"].invoke
10
- end
11
-
12
- desc "Gets a dump from remote and loads it into the local database"
13
- task load: :environment do
14
- puts "🧐 Please note this task is called 'uff_db_loader:load' now."
15
- Rake::Task["uff_db_loader:load"].invoke
16
- end
17
-
18
- desc "Delete all downloaded db dumps and emove all databases created by UffDbLoader"
19
- task prune: :environment do
20
- puts "🧐 Please note this task is called 'uff_db_loader:prune' now."
21
- Rake::Task["uff_db_loader:prune"].invoke
22
- end
23
- end