Class: KamalBackup::Databases::Postgres

Inherits:
Base
  • Object
show all
Defined in:
lib/kamal_backup/databases/postgres.rb

Constant Summary collapse

SOURCE_ENV_KEYS =
%w[
  PGHOST
  PGPORT
  PGUSER
  PGPASSWORD
  PGDATABASE
  PGSSLMODE
  PGSSLROOTCERT
  PGSSLCERT
  PGSSLKEY
  PGCONNECT_TIMEOUT
  PGSERVICE
  PGPASSFILE
].freeze

Instance Attribute Summary

Attributes inherited from Base

#config, #redactor

Instance Method Summary collapse

Methods inherited from Base

#backup, #backup_tags, build, #database_filename, #initialize

Constructor Details

This class inherits a constructor from KamalBackup::Databases::Base

Instance Method Details

#adapter_nameObject



24
25
26
# File 'lib/kamal_backup/databases/postgres.rb', line 24

def adapter_name
  'postgres'
end

#current_restore_commandObject



68
69
70
71
72
73
74
75
76
# File 'lib/kamal_backup/databases/postgres.rb', line 68

def current_restore_command
  connection = current_connection
  database = connection.fetch('PGDATABASE')

  argv = [postgres_binary('pg_restore', connection)] +
         %w[--clean --if-exists --no-owner --no-privileges --exit-on-error --dbname]
  argv << database
  CommandSpec.new(argv: argv, env: connection)
end

#current_target_identifierObject



87
88
89
# File 'lib/kamal_backup/databases/postgres.rb', line 87

def current_target_identifier
  value('DATABASE_URL') || value('PGDATABASE')
end

#dump_commandObject



32
33
34
35
36
# File 'lib/kamal_backup/databases/postgres.rb', line 32

def dump_command
  connection = current_connection
  argv = [postgres_binary('pg_dump', connection)] + %w[--format=custom --no-owner --no-privileges]
  CommandSpec.new(argv: argv, env: connection)
end

#dump_extensionObject



28
29
30
# File 'lib/kamal_backup/databases/postgres.rb', line 28

def dump_extension
  'pgdump'
end

#restore_to_current(restic, snapshot, filename) ⇒ Object

Replace the target's user schemas before restoring.

pg_restore --clean emits DROP TABLE for each object in the dump, but PostgreSQL refuses to drop a table another table still references, and the dump's ordering cannot account for constraints that only exist in the target. Restoring over a schema Rails already created — which is every restore onto a freshly deployed host, since Kamal runs db:prepare on boot — leaves the drops failing, the CREATEs failing as "already exists", the COPYs never running, and the foreign keys rejected because the tables they point at are still empty.

Dropping every non-system schema first sidesteps the ordering problem entirely and removes target-only custom schemas as well as public. Current and scratch restores both promise that the target represents the selected snapshot, so both paths reset their target schema.



53
54
55
56
57
58
# File 'lib/kamal_backup/databases/postgres.rb', line 53

def restore_to_current(restic, snapshot, filename)
  reset_schema(current_connection)
  result = super
  ensure_restore_reported_no_errors(result)
  result
end

#restore_to_scratch(restic, snapshot, filename, target:) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/kamal_backup/databases/postgres.rb', line 60

def restore_to_scratch(restic, snapshot, filename, target:)
  validate_scratch_restore_target(target)
  reset_schema(current_connection.merge('PGDATABASE' => target))
  result = restic.pipe_dump_to_command(snapshot, filename, scratch_restore_command(target))
  ensure_restore_reported_no_errors(result)
  result
end

#scratch_restore_command(target) ⇒ Object



78
79
80
81
82
83
84
85
# File 'lib/kamal_backup/databases/postgres.rb', line 78

def scratch_restore_command(target)
  connection = current_connection.merge('PGDATABASE' => target)

  argv = [postgres_binary('pg_restore', connection)] +
         %w[--clean --if-exists --no-owner --no-privileges --exit-on-error --dbname]
  argv << target
  CommandSpec.new(argv: argv, env: connection)
end

#scratch_target_identifier(target) ⇒ Object



91
92
93
# File 'lib/kamal_backup/databases/postgres.rb', line 91

def scratch_target_identifier(target)
  [current_connection['PGHOST'], target].compact.join('/')
end