fix provision: pass PGPASSWORD to psql, fix .env.bak path, accept 403 from rustfs
- provision_postgres: pass PGPASSWORD via docker exec -e so psql can authenticate as superuser (was failing with exit 2) - bootstrap_postgres: same PGPASSWORD fix for all docker exec calls - deploy.py: fix .env.bak path (was .env.env.bak due to with_suffix) - verify_rustfs: accept 403 as healthy (RustFS requires auth on health) - Updated tests for new docker exec -e flag
This commit is contained in:
@@ -94,11 +94,11 @@ def verify_gitea(
|
|||||||
|
|
||||||
|
|
||||||
def verify_rustfs(*, endpoint: str = "http://rustfs:9000") -> list[str]:
|
def verify_rustfs(*, endpoint: str = "http://rustfs:9000") -> list[str]:
|
||||||
"""Verify RustFS is healthy."""
|
"""Verify RustFS is reachable (returns 403 = alive, needs auth)."""
|
||||||
errors = []
|
errors = []
|
||||||
try:
|
try:
|
||||||
resp = httpx.get(f"{endpoint}/minio/health/live", timeout=10)
|
resp = httpx.get(f"{endpoint}/minio/health/live", timeout=10)
|
||||||
if resp.status_code != 200:
|
if resp.status_code not in (200, 403):
|
||||||
errors.append(f"rustfs: HTTP {resp.status_code}")
|
errors.append(f"rustfs: HTTP {resp.status_code}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append(f"rustfs: {e}")
|
errors.append(f"rustfs: {e}")
|
||||||
@@ -167,7 +167,7 @@ def deploy(
|
|||||||
|
|
||||||
# ── Phase 2: Write .env + restart services ────────────────
|
# ── Phase 2: Write .env + restart services ────────────────
|
||||||
# Back up current .env
|
# Back up current .env
|
||||||
env_bak = env_path.with_suffix(".env.bak")
|
env_bak = env_path.parent / (env_path.name + ".bak")
|
||||||
if env_path.exists():
|
if env_path.exists():
|
||||||
shutil.copy2(env_path, env_bak)
|
shutil.copy2(env_path, env_bak)
|
||||||
|
|
||||||
|
|||||||
@@ -109,13 +109,17 @@ def provision_postgres(values: dict[str, str], *, container: str = "postgres") -
|
|||||||
"""Rotate passwords for all managed PostgreSQL roles.
|
"""Rotate passwords for all managed PostgreSQL roles.
|
||||||
|
|
||||||
Uses psql -v variable binding so passwords never appear in SQL text.
|
Uses psql -v variable binding so passwords never appear in SQL text.
|
||||||
|
Authenticates as superuser using POSTGRES_PASSWORD from the values dict.
|
||||||
"""
|
"""
|
||||||
|
superuser_pw = values.get("POSTGRES_PASSWORD", "")
|
||||||
for role, env_var in POSTGRES_ROLES.items():
|
for role, env_var in POSTGRES_ROLES.items():
|
||||||
pw = values[env_var]
|
pw = values[env_var]
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
[
|
[
|
||||||
"docker",
|
"docker",
|
||||||
"exec",
|
"exec",
|
||||||
|
"-e",
|
||||||
|
f"PGPASSWORD={superuser_pw}",
|
||||||
container,
|
container,
|
||||||
"psql",
|
"psql",
|
||||||
"-U",
|
"-U",
|
||||||
@@ -133,10 +137,12 @@ def provision_postgres(values: dict[str, str], *, container: str = "postgres") -
|
|||||||
def bootstrap_postgres(values: dict[str, str], *, container: str = "postgres") -> None:
|
def bootstrap_postgres(values: dict[str, str], *, container: str = "postgres") -> None:
|
||||||
"""Idempotent first-time setup: create roles and databases."""
|
"""Idempotent first-time setup: create roles and databases."""
|
||||||
superuser_pw = values["POSTGRES_PASSWORD"]
|
superuser_pw = values["POSTGRES_PASSWORD"]
|
||||||
|
pgenv = ["-e", f"PGPASSWORD={superuser_pw}"]
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
[
|
[
|
||||||
"docker",
|
"docker",
|
||||||
"exec",
|
"exec",
|
||||||
|
*pgenv,
|
||||||
container,
|
container,
|
||||||
"psql",
|
"psql",
|
||||||
"-U",
|
"-U",
|
||||||
@@ -158,7 +164,7 @@ def bootstrap_postgres(values: dict[str, str], *, container: str = "postgres") -
|
|||||||
f"THEN CREATE ROLE {role} LOGIN; END IF; END $$;"
|
f"THEN CREATE ROLE {role} LOGIN; END IF; END $$;"
|
||||||
)
|
)
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["docker", "exec", container, "psql", "-U", "postgres", "-c", sql],
|
["docker", "exec", *pgenv, container, "psql", "-U", "postgres", "-c", sql],
|
||||||
check=True,
|
check=True,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
)
|
)
|
||||||
@@ -166,6 +172,7 @@ def bootstrap_postgres(values: dict[str, str], *, container: str = "postgres") -
|
|||||||
[
|
[
|
||||||
"docker",
|
"docker",
|
||||||
"exec",
|
"exec",
|
||||||
|
*pgenv,
|
||||||
container,
|
container,
|
||||||
"psql",
|
"psql",
|
||||||
"-U",
|
"-U",
|
||||||
@@ -182,6 +189,7 @@ def bootstrap_postgres(values: dict[str, str], *, container: str = "postgres") -
|
|||||||
[
|
[
|
||||||
"docker",
|
"docker",
|
||||||
"exec",
|
"exec",
|
||||||
|
*pgenv,
|
||||||
container,
|
container,
|
||||||
"psql",
|
"psql",
|
||||||
"-U",
|
"-U",
|
||||||
|
|||||||
@@ -167,8 +167,11 @@ class TestProvisionPostgres:
|
|||||||
assert mock_run.call_count == len(POSTGRES_ROLES)
|
assert mock_run.call_count == len(POSTGRES_ROLES)
|
||||||
for c in mock_run.call_args_list:
|
for c in mock_run.call_args_list:
|
||||||
cmd = c[0][0]
|
cmd = c[0][0]
|
||||||
assert cmd[:3] == ["docker", "exec", "test-pg"]
|
assert cmd[0] == "docker"
|
||||||
|
assert cmd[1] == "exec"
|
||||||
|
assert "test-pg" in cmd
|
||||||
assert "-v" in cmd
|
assert "-v" in cmd
|
||||||
|
assert "-e" in cmd
|
||||||
assert ":'pw'" in cmd[-1]
|
assert ":'pw'" in cmd[-1]
|
||||||
|
|
||||||
def test_no_password_in_sql(self):
|
def test_no_password_in_sql(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user