Class: Geordi::DBCleaner
- Inherits:
-
Object
- Object
- Geordi::DBCleaner
- Defined in:
- lib/geordi/db_cleaner.rb
Instance Method Summary collapse
- #clean_mysql ⇒ Object
- #clean_postgres ⇒ Object
- #edit_whitelist(dbtype) ⇒ Object
-
#initialize(extra_flags) ⇒ DBCleaner
constructor
A new instance of DBCleaner.
- #is_protected?(dbtype, database_name) ⇒ Boolean
- #is_whitelisted?(dbtype, database_name) ⇒ Boolean
- #list_all_dbs(dbtype) ⇒ Object
- #list_all_mysql_dbs ⇒ Object
- #list_all_postgres_dbs ⇒ Object
- #whitelist_fname(dbtype) ⇒ Object
Constructor Details
#initialize(extra_flags) ⇒ DBCleaner
Returns a new instance of DBCleaner.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/geordi/db_cleaner.rb', line 8 def initialize(extra_flags) puts 'Please enter your sudo password if asked, for db operations as system users' puts "We're going to run `sudo -u postgres psql` for PostgreSQL" puts ' and `sudo mysql` for MariaDB (which uses PAM auth)' `sudo true` Interaction.fail 'sudo access is required for database operations as database users' if $? != 0 @derivative_dbname = /_(test\d*|development|cucumber)$/ base_directory = ENV['XDG_CONFIG_HOME'] base_directory = Dir.home.to_s if base_directory.nil? @whitelist_directory = File.join(base_directory, '.config', 'geordi', 'whitelists') FileUtils.mkdir_p(@whitelist_directory) unless File.directory? @whitelist_directory @mysql_command = decide_mysql_command(extra_flags['mysql']) @postgres_command = decide_postgres_command(extra_flags['postgres']) end |
Instance Method Details
#clean_mysql ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/geordi/db_cleaner.rb', line 173 def clean_mysql Interaction.announce 'Checking for MySQL databases' database_list = list_all_dbs('mysql') # confirm_deletion includes option for whitelist editing deletable_dbs = confirm_deletion('mysql', database_list) return if deletable_dbs.nil? deletable_dbs.each do |db| if @mysql_command.include? '-p' puts "Please enter your MySQL/MariaDB account 'root' for: DROP DATABASE #{db}" else Interaction.note "Dropping MySQL/MariaDB database #{db}" end `#{@mysql_command} -e 'DROP DATABASE \`#{db}\`;'` end end |
#clean_postgres ⇒ Object
189 190 191 192 193 194 195 196 197 198 |
# File 'lib/geordi/db_cleaner.rb', line 189 def clean_postgres Interaction.announce 'Checking for Postgres databases' database_list = list_all_dbs('postgres') deletable_dbs = confirm_deletion('postgres', database_list) return if deletable_dbs.nil? deletable_dbs.each do |db| Interaction.note "Dropping PostgreSQL database `#{db}`." `#{@postgres_command} -c 'DROP DATABASE "#{db}";'` end end |
#edit_whitelist(dbtype) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/geordi/db_cleaner.rb', line 23 def edit_whitelist(dbtype) whitelist = whitelist_fname(dbtype) whitelisted_dbs = if File.exist? whitelist Geordi::Util.stripped_lines(File.read(whitelist))\ .delete_if { |l| l.start_with? '#' } else [] end all_dbs = list_all_dbs(dbtype) tmp = Tempfile.open("geordi_whitelist_#{dbtype}") tmp.write <<-HEREDOC # Put each whitelisted database on a new line. # System databases will never be deleted. # When you whitelist foo, foo_development and foo_test\\d* are whitelisted, too. # This works even if foo does not exist. Also, you will only see foo in this list. # # Syntax: keep foo # drop bar HEREDOC tmpfile_content = Array.new all_dbs.each do |db| next if is_whitelisted?(dbtype, db) next if is_protected?(dbtype, db) db.sub!(@derivative_dbname, '') tmpfile_content.push(['drop', db]) end warn_manual_whitelist = false whitelisted_dbs.each do |db_name| # Remove 'keep' word from whitelist entries. This is not normally required since geordi # does not save 'keep' or 'drop' to the whitelist file on disk but rather saves a list # of all whitelisted db names and just presents the keep/drop information while editing # the whitelist to supply users a list of databases they can whitelist by changing the # prefix to 'keep'. Everything prefixed 'drop' is not considered whitelisted and thus # not written to the whitelist file on disk. # # However, if users manually edit their whitelist files they might use the keep/drop # syntax they're familiar with. if db_name.start_with? 'keep ' db_name.gsub!(/keep /, '') db_name = db_name.split[1..-1].join(' ') warn_manual_whitelist = true end tmpfile_content.push(['keep', db_name]) unless db_name.empty? end if warn_manual_whitelist Interaction.warn <<-ERROR_MSG.gsub(/^\s*/, '') Your whitelist #{whitelist} seems to have been generated manually. In that case, make sure to use only one database name per line and omit the 'keep' prefix." Launching the editor. ERROR_MSG end tmpfile_content.sort_by! { |k| k[1] } tmpfile_content.uniq! tmpfile_content.each do |line| tmp.write("#{line[0]} #{line[1]}\n") end tmp.close texteditor = Geordi::Util.decide_texteditor system("#{texteditor} #{tmp.path}") File.open(tmp.path, 'r') do |wl_edited| whitelisted_dbs = [] whitelist_storage = File.open(whitelist, 'w') lines = Geordi::Util.stripped_lines(wl_edited.read) lines.each do |line| next if line.start_with?('#') unless line.split.length == 2 Interaction.fail "Invalid edit to whitelist file: \`#{line}\` - Syntax is: ^[keep|drop] dbname$" end unless %w[keep drop k d].include? line.split.first Interaction.fail "Invalid edit to whitelist file: \`#{line}\` - must start with either drop or keep." end db_status, db_name = line.split if db_status == 'keep' whitelisted_dbs.push db_name whitelist_storage.write(db_name << "\n") end end whitelist_storage.close end end |
#is_protected?(dbtype, database_name) ⇒ Boolean
238 239 240 241 242 243 244 |
# File 'lib/geordi/db_cleaner.rb', line 238 def is_protected?(dbtype, database_name) protected = { 'mysql' => %w[mysql information_schema performance_schema sys], 'postgres' => ['postgres'], } protected[dbtype].include? database_name end |
#is_whitelisted?(dbtype, database_name) ⇒ Boolean
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/geordi/db_cleaner.rb', line 246 def is_whitelisted?(dbtype, database_name) whitelist_content = if File.exist? whitelist_fname(dbtype) Geordi::Util.stripped_lines(File.open(whitelist_fname(dbtype), 'r').read) else [] end # Allow explicit whitelisting of derivative databases like projectname_test2 if whitelist_content.include? database_name true # whitelisting `projectname` also whitelists `projectname_test\d*`, `projectname_development` elsif whitelist_content.include? database_name.sub(@derivative_dbname, '') true else false end end |
#list_all_dbs(dbtype) ⇒ Object
154 155 156 157 158 159 160 |
# File 'lib/geordi/db_cleaner.rb', line 154 def list_all_dbs(dbtype) if dbtype == 'postgres' list_all_postgres_dbs else list_all_mysql_dbs end end |
#list_all_mysql_dbs ⇒ Object
166 167 168 169 170 171 |
# File 'lib/geordi/db_cleaner.rb', line 166 def list_all_mysql_dbs if @mysql_command.include? '-p' puts "Please enter your MySQL/MariaDB account 'root' for: list all databases" end `#{@mysql_command} -B -N -e 'show databases'`.split end |
#list_all_postgres_dbs ⇒ Object
162 163 164 |
# File 'lib/geordi/db_cleaner.rb', line 162 def list_all_postgres_dbs `#{@postgres_command} -t -A -c 'SELECT DATNAME FROM pg_database WHERE datistemplate = false'`.split end |
#whitelist_fname(dbtype) ⇒ Object
200 201 202 |
# File 'lib/geordi/db_cleaner.rb', line 200 def whitelist_fname(dbtype) File.join(@whitelist_directory, dbtype) << '.txt' end |