Skip to content

Commit

Permalink
Support .pgpass files for migra
Browse files Browse the repository at this point in the history
This eases the whole connection URI setup for developers who make use of the
.pgpass file.

Signed-off-by: Wesley Schwengle <wesley@opndev.io>
  • Loading branch information
waterkip committed Feb 5, 2023
1 parent da6671a commit c5c5c58
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
6 changes: 6 additions & 0 deletions docs/installing_and_connecting.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ The general form is as follows:
:::bash
connectiontype://username:password@databasehostname/databasename?extraparam1=a&extraparam2=b

If you have a .pgpass file in your $HOME dir, you can make use of that as well
as you don't need to enter the password in the connection string:

:::bash
postgresql://username@hostname/databasename

These can be left out if not necessary. For instance, if connecting locally, using your default system username and passwordless "trust" login, only a connection type and database name is required:

:::bash
Expand Down
51 changes: 50 additions & 1 deletion migra/command.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
from __future__ import print_function, unicode_literals

import argparse
import pgpasslib
import sys
import getpass

from contextlib import contextmanager
from sqlalchemy.engine.url import make_url
from sqlbag import S

from .migra import Migration
from .statements import UnsafeMigrationException
Expand Down Expand Up @@ -75,14 +80,58 @@ def parse_args(args):
return parser.parse_args(args)


def get_password_from_pgpass(host, port, database, username):
if not host:
host = "localhost"

if not port:
port = 5432

if not username:
username = getpass.getuser()

if not database:
database = username

try:
return pgpasslib.getpass(
host,
port,
database,
username,
)
except pgpasslib.FileNotFound:
return None

return None


def get_password_from_uri(uri):

uri = make_url(uri)

if not uri.password:
password = get_password_from_pgpass(
uri.host, uri.port, uri.database, uri.username
)
if password:
uri.set(password=password)

return uri


def run(args, out=None, err=None):
schema = args.schema
exclude_schema = args.exclude_schema
if not out:
out = sys.stdout # pragma: no cover
if not err:
err = sys.stderr # pragma: no cover
with arg_context(args.dburl_from) as ac0, arg_context(args.dburl_target) as ac1:

db_from = get_password_from_uri(args.dburl_from)
db_to = get_password_from_uri(args.dburl_target)

with arg_context(db_from) as ac0, arg_context(db_to) as ac1:
m = Migration(
ac0,
ac1,
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ six = "*"
# schemainspect = {path="../schemainspect", develop=true}
schemainspect = ">=3.1.1663480743"
psycopg2-binary = { version="*", optional = true }
pgpasslib = "*"

[tool.poetry.dev-dependencies]
sqlbag = "*"
Expand Down

0 comments on commit c5c5c58

Please sign in to comment.