Class: CKnifePg

Inherits:
Thor
  • Object
show all
Defined in:
lib/cknife/cknife_pg.rb

Instance Method Summary collapse

Instance Method Details

#captureObject



139
140
141
142
143
144
145
146
147
# File 'lib/cknife/cknife_pg.rb', line 139

def capture
  file_name = "db" + Time.now.strftime("%Y%m%d%H%M%S") + ".dump"

  with_pg_pass_file do
    pg_pass_file_execute("pg_dump -Fc --no-owner #{connection_options} -f #{file_name} #{conf[:database]}") do
      say("Captured #{file_name}.")
    end
  end
end

#createdbObject



272
273
274
275
276
277
278
# File 'lib/cknife/cknife_pg.rb', line 272

def createdb
  with_pg_pass_file do
    pg_pass_file_execute("createdb #{connection_options} #{conf[:database]}") do
      say("Created #{conf[:database]} database.") if @session_ok
    end
  end
end

#dpassfileObject



315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/cknife/cknife_pg.rb', line 315

def dpassfile
  if !File.exists?(pg_pass_file)
    say("No .pgpass file to delete.")
    return
  end

  s = File.read(pg_pass_file)
  if s == pg_str
    File.unlink(pg_pass_file)
    say("Deleted .pgpass file.")
  else
    say("The .pgpass file's contents do not match what this tool would have generated. Assuming you are trying to delete a .pgpass file that this tool did not generate, please inspect the file to ensure it contains what you expect, and then delete it yourself.", :red)
  end
end

#dropdbObject



282
283
284
285
286
287
288
# File 'lib/cknife/cknife_pg.rb', line 282

def dropdb
  with_pg_pass_file do
    pg_pass_file_execute("dropdb #{connection_options} #{conf[:database]};") do
      say("Dropped #{conf[:database]} database.") if @session_ok
    end
  end
end

#fexec(file) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/cknife/cknife_pg.rb', line 257

def fexec(file)
  if !File.exists?(file)
    say("'#{file}' does not exist.")
    return
  end

  with_pg_pass_file do
    pg_pass_file_execute("#{psql_invocation} -f #{file}") do
      say("Ran #{file} SQL script.")
    end
  end
end

#passfileObject



300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/cknife/cknife_pg.rb', line 300

def passfile
  connect_msg = "Connect command: PGPASSFILE=.pgpass #{psql_easy}"
  if File.exists?(pg_pass_file)
    say("A .pgpass file is already present.")
    say(connect_msg)
    return
  end

  write_pg_pass_file
  say("Wrote #{pg_pass_file} to $CWD.")
  say(connect_msg)
  say("Remember to delete the .pgpass file when you are finished.")
end

#permsObject



292
293
294
295
296
297
# File 'lib/cknife/cknife_pg.rb', line 292

def perms
  with_pg_pass_file do
    output = pg_pass_file_execute("#{psql_easy}", "\\du")
    puts output if !options[:verbose]
  end
end

#psqlObject



333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/cknife/cknife_pg.rb', line 333

def psql
  if !File.exists?(pg_pass_file)
    if !options[:passfile]
      say("You must prepare a .pgpass file for this command, or use --passfile to have this tool create it for you. Alternatively, you can create a .pgpass file with the passfile command and delete it later with the dpassfile command.")
      return
    end

    write_pg_pass_file
  end

  dc(psql_easy) if options[:verbose]
  exec({'PGPASSFILE' => pg_pass_file}, psql_easy)
end

#restore(filename = nil) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/cknife/cknife_pg.rb', line 180

def restore(filename=nil)
  to_restore = filename if filename
  if to_restore.nil?
    files = Dir["db*.dump"]
    with_mtime = files.map { |f| [f, File.mtime(f)] }
    with_mtime.sort! { |a,b| a.last <=> b.last }
    files = with_mtime.map(&:first)
    to_restore = files.last
  end

  if to_restore.nil?
    say("No backups file to restore. No file given on the command line, and no files could be found in the $CWD.", :red)
    return
  else
    if !yes?("Restore #{to_restore}?", :green)
      return
    end
  end

  with_pg_pass_file do
    output = pg_pass_file_execute("dropdb #{connection_options} #{conf[:database]}")

    if !@session_ok
      if output.split("\n").any? { |s| s =~ /There are [0-9]+ other session\(s\) using the database./ }
        say
        say("Other sessions are blocking the database from being dropped.")
        say("You may want to terminate these sessions and try again. See the 'sessions' command.")
      end
    else
      say("Doing restore...")

      pg_pass_file_execute("createdb -T template0 #{connection_options} #{conf[:database]}")
      pg_pass_file_execute("pg_restore -n public --no-privileges --no-owner #{connection_options} -d #{conf[:database]} #{to_restore}") do
        say("Restored #{to_restore}")
      end
    end
  end
end

#schema(table = nil) ⇒ Object



221
222
223
224
225
226
227
228
229
230
# File 'lib/cknife/cknife_pg.rb', line 221

def schema(table=nil)
  table_string = table.nil? ? "" : "--table=#{table.strip}"
  with_pg_pass_file do
    output = pg_pass_file_execute("pg_dump #{connection_options} --no-owner --clean --if-exists --schema-only #{table_string} #{conf[:database]}")

    # This command is so verbose that we only print the output if
    # we didn't already do so in verbose mode.
    puts output if !options[:verbose]
  end
end

#sessionsObject



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/cknife/cknife_pg.rb', line 152

def sessions
  with_pg_pass_file do
    if !options[:kill]
      my_pid = pg_pass_file_execute(psql_invocation, "select pg_backend_pid();").split.first
      ids_output = pg_pass_file_execute(psql_invocation, "SELECT #{pid_col_name}, application_name FROM pg_stat_activity WHERE datname = '#{conf[:database]}' AND #{pid_col_name} != #{my_pid};")

      return if ids_output.nil?

      table = ids_output.split.map { |line| line.split("|") }
      print_table([["PID", "Application Name"]] + table, :indent => 2)
      say("To kill all active sessions connected to this database, you can use the --kill option with this command.")
    else
      sql = "SELECT pg_terminate_backend(pg_stat_activity.#{pid_col_name})
FROM pg_stat_activity
WHERE pg_stat_activity.datname = '#{conf[:database]}'
    AND pid <> pg_backend_pid();"

      with_pg_pass_file do
        pg_pass_file_execute(psql_invocation, sql) do
          say("Terminated all sessions.") if @session_ok
        end
      end
    end
  end
end

#tables(table = nil) ⇒ Object



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/cknife/cknife_pg.rb', line 234

def tables(table=nil)
  sql = "SELECT
  table_schema || '.' || table_name
FROM
  information_schema.tables
WHERE
  table_type = 'BASE TABLE'
AND
  table_schema NOT IN ('pg_catalog', 'information_schema');"

  with_pg_pass_file do
    output = pg_pass_file_execute(psql_invocation, sql)
    say ("removing public. prefixes.") if options[:verbose]
    tables = output.split.map do |ts|
      ts =~ /^public\.(.*)$/
      $1
    end
    print_in_columns(tables)
  end
end