Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Poetry and friends #9

Merged
merged 15 commits into from
May 16, 2024
Merged
3 changes: 3 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if has nix; then
use flake
fi
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ dist/**
*.xlf
package.nls.*.json
l10n/
/.direnv/
47 changes: 26 additions & 21 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
FROM python:3.12.3-slim-bookworm

ARG CONFIG_PATH=pg-migration-tool/config.example.yaml

ENV TERM=xterm-256color

ENV COLORTERM=truecolor
FROM python:3.12-slim

RUN apt-get update && apt-get -y upgrade

RUN apt-get install -y libpq-dev gcc xterm postgresql-client postgresql-client-common

RUN pip install pipenv

RUN useradd -m pgmigrator
RUN apt-get install -y libpq-dev gcc xterm wget postgresql-client postgresql-client-common

# Don't run as root
RUN useradd -m pgmigrator && \
# Set the working directory in the container
mkdir -p /home/pgmigrator/pg-migration-tool && \
chown pgmigrator:pgmigrator /home/pgmigrator/pg-migration-tool && \
# Use wget instead of curl since curl is external package in alpine
# https://python-poetry.org/docs/#installation
wget -O get-poetry.py https://install.python-poetry.org && \
POETRY_HOME=/home/pgmigrator/.poetry python3 get-poetry.py && \
rm get-poetry.py

USER pgmigrator

WORKDIR /app

COPY Pipfile ./
# Add Poetry to PATH
ENV PATH="/home/pgmigrator/.poetry/bin:${PATH}"

COPY Pipfile.lock ./
# Install dependencies
COPY poetry.lock pyproject.toml README.md ./
RUN poetry install

COPY pg-migration-tool/main.py ./pg-migration-tool/
WORKDIR /home/pgmigrator

COPY pg-migration-tool/select.tcss ./pg-migration-tool/
COPY pg_migration_tool/__init__.py ./pg-migration-tool/
COPY pg_migration_tool/main.py ./pg-migration-tool/
COPY pg_migration_tool/select.tcss ./pg-migration-tool/

ARG CONFIG_PATH=pg_migration_tool/config.example.yaml
COPY $CONFIG_PATH ./pg-migration-tool/config.yaml

RUN pipenv install
ENV TERM=xterm-256color
ENV COLORTERM=truecolor

ENTRYPOINT ["pipenv", "run", "python"]
ENTRYPOINT ["poetry", "run", "python"]

CMD ["pg-migration-tool/main.py"]
17 changes: 0 additions & 17 deletions Pipfile

This file was deleted.

288 changes: 0 additions & 288 deletions Pipfile.lock

This file was deleted.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# pg-migration-tool
27 changes: 27 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; };

outputs = { self, nixpkgs, ... }@inputs:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
pythonPackage = pkgs.python312;
myPython = (pythonPackage.withPackages (ps: with ps; [ pip ]));
in {
devShells.${system}.default = pkgs.mkShell {
buildInputs = with pkgs; [
myPython
(poetry.override { python3 = pythonPackage; })
postgresql
];
};
};
}
Empty file added pg_migration_tool/__init__.py
Empty file.
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
common:
kms_key_id: alias/my-key
dumps_working_directory: /tmp

dbs:
my-service:
dvdrental:
source:
db_connection_host: localhost
db_database_name : my_service_database
db_username: service_user
db_password_encrypted: AQICAHikQNm16H8uYi...
db_database_name : dvdrental
db_username: postgres
target:
db_connection_host: localhost
db_database_name : postgres
db_database_name : dvdrental_copy
db_username: postgres
db_password: password
another-service:
source:
db_connection_host: localhost
Expand All @@ -33,4 +33,4 @@ dbs:
db_connection_host: localhost
db_database_name : postgres
db_username: postgres
db_password: password
db_password: password
17 changes: 11 additions & 6 deletions pg-migration-tool/main.py → pg_migration_tool/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ async def select_changed(self, event: Select.Changed) -> None:

def clean_old_dumps(self, db):
self.query_one(Log).clear()
os.system(f"rm -rf {db['source']['db_database_name']}")
dump_path = self.construct_path_to_dump(db)
os.system(f"rm -rf {dump_path}")

def display_db_config(self, db):

Expand Down Expand Up @@ -82,9 +83,6 @@ async def check_connection_for_db(self, db, label) -> bool:

db["db_password"] = db_password

if not db_password:
return False

self.query_one(label).set_class(False, 'invisible')
self.query_one(label).update(f"{label} Running connection test...")

Expand Down Expand Up @@ -119,11 +117,18 @@ async def decrypt_password(self, db, label) -> str:
except Exception as e:
self.query_one(label).update(f'{label} Failed to decrypt password with kms key \'{config["common"]["kms_key_id"]}\': {e}')
return None

def construct_path_to_dump(self, db) -> str:
path = config["common"]["dumps_working_directory"]
db_name = db["source"]["db_database_name"]
return f"{path}/{db_name}"


def generate_pg_dump_and_restore_cmd(self, event: Select.Changed)-> str:
db = config["dbs"][event.value]
pg_dump_cmd = f'PGPASSWORD="{db['source']['db_password']}" pg_dump -h {db['source']['db_connection_host']} -U {db['source']['db_username']} -d {db['source']['db_database_name']} --create --clean --encoding utf8 --format directory --jobs 16 -Z 0 -v --file={db['source']['db_database_name']}'
pg_restore_cmd = f'PGPASSWORD="{db['target']['db_password']}" pg_restore -h {db['target']['db_connection_host']} -U {db['target']['db_username']} -d {db['target']['db_database_name']} --clean -vv {db['source']['db_database_name']}'
dump_path = self.construct_path_to_dump(db)
pg_dump_cmd = f'PGPASSWORD="{db['source']['db_password']}" pg_dump -h {db['source']['db_connection_host']} -U {db['source']['db_username']} -d {db['source']['db_database_name']} --create --clean --encoding utf8 --format directory --jobs 16 -Z 0 -v --file={dump_path}'
pg_restore_cmd = f'PGPASSWORD="{db['target']['db_password']}" pg_restore -h {db['target']['db_connection_host']} -U {db['target']['db_username']} -d {db['target']['db_database_name']} --clean --if-exists --single-transaction --exit-on-error --format directory -vv {dump_path}'

cmd = " && /\n ".join([pg_dump_cmd, pg_restore_cmd])
self.query_one(Log).write_line("The following migration commands will be executed:\n" + cmd)
Expand Down
File renamed without changes.
Loading