Skip to content

Commit af4b3fa

Browse files
committed
Use ActiveRecord::Migrator multiple migrations paths support
[#44034071] ActiveRecord::Migrator has a class attribute, migrations_paths, specificially for storing a list of different directories that have migrations in them. ActiveRecord::Migrator.migrations_paths is used in rake db:load_config, which is a dependency of db:migrate, etc. that is passed to ActiveRecord::Migrator.migrate. Since migrate supports an array of directories, and not just a single directory, there is no need to merge all the migrations paths into one temporary directory as was previously done.
1 parent 2e4760c commit af4b3fa

File tree

2 files changed

+31
-48
lines changed

2 files changed

+31
-48
lines changed

lib/msf/core/db_manager.rb

Lines changed: 28 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,6 @@ def active
5656
# Flag to indicate database migration has completed
5757
attr_accessor :migrated
5858

59-
# Array of additional migration paths
60-
attr_accessor :migration_paths
61-
6259
# Flag to indicate that modules are cached
6360
attr_accessor :modules_cached
6461

@@ -69,7 +66,6 @@ def initialize(framework, opts = {})
6966

7067
self.framework = framework
7168
self.migrated = false
72-
self.migration_paths = []
7369
self.modules_cached = false
7470
self.modules_caching = false
7571

@@ -82,17 +78,17 @@ def initialize(framework, opts = {})
8278
end
8379

8480
initialize_database_support
85-
86-
# have to set migration paths after initialize_database_support as it loads
87-
# MetasploitDataModels.
88-
self.migration_paths << MetasploitDataModels.root.join('db', 'migrate').to_s
8981
end
9082

91-
#
92-
# Add additional migration paths
93-
#
94-
def add_migration_path(path)
95-
self.migration_paths.push(path)
83+
def initialize_metasploit_data_models
84+
# Provide access to ActiveRecord models shared w/ commercial versions
85+
require "metasploit_data_models"
86+
87+
metasploit_data_model_migrations_pathname = MetasploitDataModels.root.join(
88+
'db',
89+
'migrate'
90+
)
91+
ActiveRecord::Migrator.migrations_paths << metasploit_data_model_migrations_pathname.to_s
9692
end
9793

9894
#
@@ -105,8 +101,7 @@ def initialize_database_support
105101

106102
require "active_record"
107103

108-
# Provide access to ActiveRecord models shared w/ commercial versions
109-
require "metasploit_data_models"
104+
initialize_metasploit_data_models
110105

111106
# Patches issues with ActiveRecord
112107
require "msf/core/patches/active_record"
@@ -283,45 +278,31 @@ def disconnect
283278
end
284279
end
285280

281+
# Migrate database to latest schema version.
286282
#
287-
# Migrate database to latest schema version
283+
# @param verbose [Boolean] see ActiveRecord::Migration.verbose
284+
# @return [Array<ActiveRecord::Migration>] List of migrations that ran.
288285
#
286+
# @see ActiveRecord::Migrator.migrate
289287
def migrate(verbose=false)
288+
ran = []
289+
ActiveRecord::Migration.verbose = verbose
290290

291-
temp_dir = ::File.expand_path(::File.join( Msf::Config.config_directory, "schema", "#{Time.now.to_i}_#{$$}" ))
292-
::FileUtils.rm_rf(temp_dir)
293-
::FileUtils.mkdir_p(temp_dir)
294-
295-
self.migration_paths.each do |mpath|
296-
dir = Dir.new(mpath) rescue nil
297-
if not dir
298-
elog("Could not access migration path #{mpath}")
299-
next
300-
end
301-
302-
dir.entries.each do |ent|
303-
next unless ent =~ /^\d+.*\.rb$/
304-
::FileUtils.cp( ::File.join(mpath, ent), ::File.join(temp_dir, ent) )
291+
ActiveRecord::Base.connection_pool.with_connection do
292+
begin
293+
ran = ActiveRecord::Migrator.migrate(
294+
ActiveRecord::Migrator.migrations_paths
295+
)
296+
# ActiveRecord::Migrator#migrate rescues all errors and re-raises them as
297+
# StandardError
298+
rescue StandardError => error
299+
self.error = error
300+
elog("DB.migrate threw an exception: #{error}")
301+
dlog("Call stack:\n#{error.backtrace.join "\n"}")
305302
end
306303
end
307304

308-
success = true
309-
begin
310-
311-
::ActiveRecord::Base.connection_pool.with_connection {
312-
ActiveRecord::Migration.verbose = verbose
313-
ActiveRecord::Migrator.migrate(temp_dir, nil)
314-
}
315-
rescue ::Exception => e
316-
self.error = e
317-
elog("DB.migrate threw an exception: #{e}")
318-
dlog("Call stack:\n#{e.backtrace.join "\n"}")
319-
success = false
320-
end
321-
322-
::FileUtils.rm_rf(temp_dir)
323-
324-
return true
305+
return ran
325306
end
326307

327308
def workspace=(workspace)

lib/msf/ui/console/driver.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ def initialize(prompt = DefaultPrompt, prompt_char = DefaultPromptChar, opts = {
171171

172172
# Append any migration paths necessary to bring the database online
173173
if opts['DatabaseMigrationPaths']
174-
opts['DatabaseMigrationPaths'].each {|m| framework.db.add_migration_path(m) }
174+
opts['DatabaseMigrationPaths'].each do |migrations_path|
175+
ActiveRecord::Migrator.migrations_paths << migrations_path
176+
end
175177
end
176178

177179
# Look for our database configuration in the following places, in order:

0 commit comments

Comments
 (0)