Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,6 @@ venv-python3.10

# Helm Chart
*.lock
example/helm-chart/my-example-chart/charts/
example/helm-chart/my-example-chart/charts/

.envrc
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.2.0
6.2.1-dev0
12 changes: 6 additions & 6 deletions docs/multi-database.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ databases:
main:
alembic_directory_path: /app/alembic/main
alembic_config_file_path: alembic.ini
dialect: postgresql
dialect: postgresql+psycopg
user: app_user
password: app_password
host: postgres-main
Expand All @@ -31,7 +31,7 @@ databases:
analytics:
alembic_directory_path: /app/alembic/analytics
alembic_config_file_path: alembic.ini
dialect: postgresql
dialect: postgresql+psycopg
user: analytics_user
password: analytics_password
host: postgres-analytics
Expand All @@ -49,7 +49,7 @@ databases:
- `alembic_config_file_path`: Alembic configuration file name

**Database connection components (all required):**
- `dialect`: Database dialect (e.g., postgresql, mysql, sqlite)
- `dialect`: Database dialect (e.g., postgresql+psycopg, mysql, sqlite)
- `user`: Database username
- `password`: Database password
- `host`: Database host
Expand Down Expand Up @@ -129,7 +129,7 @@ data:
main:
alembic_directory_path: /app/alembic/main
alembic_config_file_path: alembic.ini
dialect: postgresql
dialect: postgresql+psycopg
user: {{ .Values.database.main.user }}
password: {{ .Values.database.main.password }}
host: {{ .Values.database.main.host }}
Expand All @@ -140,7 +140,7 @@ data:
analytics:
alembic_directory_path: /app/alembic/analytics
alembic_config_file_path: alembic.ini
dialect: postgresql
dialect: postgresql+psycopg
user: {{ .Values.database.analytics.user }}
password: {{ .Values.database.analytics.password }}
host: {{ .Values.database.analytics.host }}
Expand All @@ -163,4 +163,4 @@ volumes:
- name: config
configMap:
name: chartreuse-config
```
```
4 changes: 2 additions & 2 deletions example/alembic/alembic.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[postgresql]
script_location = postgresl
sqlalchemy.url = postgresql://wiremind_owner@localhost:5432/wiremind
sqlalchemy.url = postgresql+psycopg://wiremind_owner@localhost:5432/wiremind
prepend_sys_path = ..
file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s

Expand Down Expand Up @@ -44,4 +44,4 @@ formatter = generic

[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
datefmt = %H:%M:%S
10 changes: 5 additions & 5 deletions example/multi-database-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ databases:
alembic_directory_path: /app/alembic/main
alembic_config_file_path: alembic.ini
# Database connection components (URL will be built automatically)
dialect: postgresql
dialect: postgresql+psycopg
user: app_user
password: app_password
host: postgres-main
Expand All @@ -22,7 +22,7 @@ databases:
analytics:
alembic_directory_path: /app/alembic/analytics
alembic_config_file_path: alembic.ini
dialect: postgresql
dialect: postgresql+psycopg
user: analytics_user
password: analytics_password
host: postgres-analytics
Expand All @@ -35,7 +35,7 @@ databases:
audit:
alembic_directory_path: /app/alembic/audit
alembic_config_file_path: alembic.ini
dialect: postgresql
dialect: postgresql+psycopg
user: audit_user
password: audit_password
host: postgres-audit
Expand All @@ -48,11 +48,11 @@ databases:
reports:
alembic_directory_path: /app/alembic/reports
alembic_config_file_path: alembic.ini
dialect: postgresql
dialect: postgresql+psycopg
user: "${REPORTS_DB_USER}"
password: "${REPORTS_DB_PASSWORD}"
host: postgres-reports
port: 5432
database: reports
allow_migration_for_empty_database: false
additional_parameters: ""
additional_parameters: ""
6 changes: 3 additions & 3 deletions example/simple-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ databases:
main:
alembic_directory_path: /app/alembic/main
alembic_config_file_path: alembic.ini
dialect: postgresql
dialect: postgresql+psycopg
user: myuser
password: mypassword
host: localhost
Expand All @@ -16,10 +16,10 @@ databases:
cache:
alembic_directory_path: /app/alembic/cache
alembic_config_file_path: alembic.ini
dialect: postgresql
dialect: postgresql+psycopg
user: cache_user
password: cache_pass
host: redis-db
port: 5432
database: cache_db
allow_migration_for_empty_database: false
allow_migration_for_empty_database: false
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ requires-python = ">=3.11.0"

dependencies = [
"alembic",
"psycopg2",
"psycopg[binary]",
"pydantic>=2.0.0",
"PyYAML",
"wiremind-kubernetes~=7.0",
Expand Down Expand Up @@ -76,4 +76,4 @@ known-first-party = ["chartreuse"]
log_level = "INFO"
# Deterministic ordering for tests; useful for pytest-xdist.
env = ["PYTHONHASHSEED=0"]
filterwarnings = ["ignore::pytest.PytestUnknownMarkWarning"]
filterwarnings = ["ignore::pytest.PytestUnknownMarkWarning"]
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ markupsafe==3.0.3
# via mako
oauthlib==3.3.1
# via requests-oauthlib
psycopg2==2.9.10
psycopg==3.3.2
# via chartreuse (pyproject.toml)
psycopg-binary==3.3.2
# via psycopg
pyasn1==0.6.1
# via
# pyasn1-modules
Expand Down
4 changes: 2 additions & 2 deletions scripts/validate_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ def validate_config(config_path: str) -> bool:
print(f" 📍 Built URL: {url}")

# Basic URL format validation
if not url.startswith(("postgresql://", "mysql://", "sqlite://")):
if not url.startswith(("postgresql+psycopg://", "mysql://", "sqlite://")):
print(
f"⚠️ Database {db_name}: URL format may be invalid (expected postgresql://, mysql://, or sqlite://)"
f"⚠️ Database {db_name}: URL format may be invalid (expected postgresql+psycopg://, mysql://, or sqlite://)"
)

except ValueError as e:
Expand Down
6 changes: 3 additions & 3 deletions src/chartreuse/config_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def url(self) -> str:
@classmethod
def validate_dialect(cls, v: str) -> str:
"""Validate database dialect."""
supported_dialects = ["postgresql", "mysql", "sqlite", "oracle", "mssql", "clickhouse"]
supported_dialects = ["postgresql+psycopg", "mysql", "sqlite", "oracle", "mssql", "clickhouse"]
if v.lower() not in supported_dialects:
logger.warning("Dialect '%s' might not be supported. Supported dialects: %s", v, supported_dialects)
return v
Expand Down Expand Up @@ -86,7 +86,7 @@ def load_multi_database_config(config_path: str) -> dict[str, DatabaseConfig]:
```yaml
databases:
main: # Database name/identifier
dialect: postgresql
dialect: postgresql+psycopg
user: app_user
password: app_password
host: postgres-main
Expand All @@ -99,7 +99,7 @@ def load_multi_database_config(config_path: str) -> dict[str, DatabaseConfig]:

# For single database setups, just include one database:
# analytics:
# dialect: postgresql
# dialect: postgresql+psycopg
# user: analytics_user
# password: analytics_password
# host: postgres-analytics
Expand Down
2 changes: 1 addition & 1 deletion src/chartreuse/tests/e2e_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
ALEMBIC_PATH = os.path.join(EXAMPLE_PATH, "alembic")

# Calculated from deployed test helm chart + kubectl exec
POSTGRESQL_URL = "postgresql://foo:foo@localhost/foo?sslmode=prefer"
POSTGRESQL_URL = "postgresql+psycopg://foo:foo@localhost/foo?sslmode=prefer"


def _cluster_init(include_chartreuse: bool, pre_upgrade: bool = False) -> Generator:
Expand Down
30 changes: 15 additions & 15 deletions src/chartreuse/tests/unit_tests/test_alembic.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def test_detect_needed_migration(mocker: MockerFixture) -> None:
Test that chartreuse detects that a migration is needed.
"""
sample_alembic_output = """
2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - Database: postgresql://***/public
2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - Database: postgresql+psycopg://***/public
2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - redis instance at localhost is activated
2018-11-29 17:58:32 - alembic.runtime.migration - INFO - Context impl PostgresqlImpl.
2018-11-29 17:58:32 - alembic.runtime.migration - INFO - Will assume transactional DDL.
Expand All @@ -72,7 +72,7 @@ def test_detect_not_needed_migration(mocker: MockerFixture) -> None:
Test that chartreuse detects that a migration is not needed.
"""
sample_alembic_output = """
2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - Database: postgresql://***/public
2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - Database: postgresql+psycopg://***/public
2018-11-29 17:58:32 - wiremind_python.settings - DEBUG - redis instance at localhost is activated
2018-11-29 17:58:32 - alembic.runtime.migration - INFO - Context impl PostgresqlImpl.
2018-11-29 17:58:32 - alembic.runtime.migration - INFO - Will assume transactional DDL.
Expand Down Expand Up @@ -205,7 +205,7 @@ def test_multi_database_configuration_postgresql_section(mocker: MockerFixture)
# Sample alembic.ini content with multiple sections
sample_alembic_ini = """[postgresql]
script_location = postgresl
sqlalchemy.url = postgresql://wiremind_owner@localhost:5432/wiremind
sqlalchemy.url = postgresql+psycopg://wiremind_owner@localhost:5432/wiremind
prepend_sys_path = ..
file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s

Expand All @@ -229,7 +229,7 @@ def test_multi_database_configuration_postgresql_section(mocker: MockerFixture)
chartreuse.utils.AlembicMigrationHelper(
alembic_directory_path=temp_dir,
alembic_config_file_path="alembic.ini",
database_url="postgresql://new_user:new_pass@new_host:5432/new_db",
database_url="postgresql+psycopg://new_user:new_pass@new_host:5432/new_db",
alembic_section_name="postgresql",
configure=True,
skip_db_checks=True,
Expand All @@ -240,7 +240,7 @@ def test_multi_database_configuration_postgresql_section(mocker: MockerFixture)
content = f.read()

# Verify PostgreSQL URL was updated
assert "postgresql://new_user:new_pass@new_host:5432/new_db" in content
assert "postgresql+psycopg://new_user:new_pass@new_host:5432/new_db" in content
# Verify ClickHouse URL was NOT changed
assert "clickhouse://default@localhost:8123/wiremind" in content
# Verify sections are still intact
Expand All @@ -256,7 +256,7 @@ def test_multi_database_configuration_clickhouse_section(mocker: MockerFixture)
# Sample alembic.ini content with multiple sections
sample_alembic_ini = """[postgresql]
script_location = postgresl
sqlalchemy.url = postgresql://wiremind_owner@localhost:5432/wiremind
sqlalchemy.url = postgresql+psycopg://wiremind_owner@localhost:5432/wiremind
prepend_sys_path = ..
file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s

Expand Down Expand Up @@ -293,7 +293,7 @@ def test_multi_database_configuration_clickhouse_section(mocker: MockerFixture)
# Verify ClickHouse URL was updated
assert "clickhouse://new_user:new_pass@new_host:8123/new_db" in content
# Verify PostgreSQL URL was NOT changed
assert "postgresql://wiremind_owner@localhost:5432/wiremind" in content
assert "postgresql+psycopg://wiremind_owner@localhost:5432/wiremind" in content
# Verify sections are still intact
assert "[postgresql]" in content
assert "[clickhouse]" in content
Expand All @@ -307,7 +307,7 @@ def test_multi_database_configuration_both_sections(mocker: MockerFixture) -> No
# Sample alembic.ini content with multiple sections
sample_alembic_ini = """[postgresql]
script_location = postgresl
sqlalchemy.url = postgresql://wiremind_owner@localhost:5432/wiremind
sqlalchemy.url = postgresql+psycopg://wiremind_owner@localhost:5432/wiremind
prepend_sys_path = ..
file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s

Expand All @@ -331,7 +331,7 @@ def test_multi_database_configuration_both_sections(mocker: MockerFixture) -> No
chartreuse.utils.AlembicMigrationHelper(
alembic_directory_path=temp_dir,
alembic_config_file_path="alembic.ini",
database_url="postgresql://pg_user:pg_pass@pg_host:5432/pg_db",
database_url="postgresql+psycopg://pg_user:pg_pass@pg_host:5432/pg_db",
alembic_section_name="postgresql",
configure=True,
skip_db_checks=True,
Expand All @@ -352,10 +352,10 @@ def test_multi_database_configuration_both_sections(mocker: MockerFixture) -> No
final_content = f.read()

# Verify both URLs are now updated correctly
assert "postgresql://pg_user:pg_pass@pg_host:5432/pg_db" in final_content
assert "postgresql+psycopg://pg_user:pg_pass@pg_host:5432/pg_db" in final_content
assert "clickhouse://ch_user:ch_pass@ch_host:8123/ch_db" in final_content
# Verify original URLs are gone
assert "postgresql://wiremind_owner@localhost:5432/wiremind" not in final_content
assert "postgresql+psycopg://wiremind_owner@localhost:5432/wiremind" not in final_content
assert "clickhouse://default@localhost:8123/wiremind" not in final_content
# Verify sections are still intact
assert "[postgresql]" in final_content
Expand All @@ -370,7 +370,7 @@ def test_single_database_configuration_with_alembic_section(mocker: MockerFixtur
# Sample simple alembic.ini content (single database)
sample_alembic_ini = """[alembic]
script_location = alembic
sqlalchemy.url = postgresql://old@localhost:5432/old
sqlalchemy.url = postgresql+psycopg://old@localhost:5432/old
prepend_sys_path = ..
file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s
"""
Expand All @@ -385,7 +385,7 @@ def test_single_database_configuration_with_alembic_section(mocker: MockerFixtur
chartreuse.utils.AlembicMigrationHelper(
alembic_directory_path=temp_dir,
alembic_config_file_path="alembic.ini",
database_url="postgresql://new_user:new_pass@new_host:5432/new_db",
database_url="postgresql+psycopg://new_user:new_pass@new_host:5432/new_db",
alembic_section_name="alembic",
configure=True,
skip_db_checks=True,
Expand All @@ -396,8 +396,8 @@ def test_single_database_configuration_with_alembic_section(mocker: MockerFixtur
content = f.read()

# Verify URL was updated
assert "postgresql://new_user:new_pass@new_host:5432/new_db" in content
assert "postgresql+psycopg://new_user:new_pass@new_host:5432/new_db" in content
# Verify original URL is gone
assert "postgresql://old@localhost:5432/old" not in content
assert "postgresql+psycopg://old@localhost:5432/old" not in content
# Verify section is still intact
assert "[alembic]" in content
Loading
Loading