mirror of
https://github.com/neondatabase/neon.git
synced 2026-05-20 06:30:43 +00:00
compute_ctl: catalog API endpoints (#7575)
## Problem There are two cloud's features that require extra compute endpoints. 1. We are running pg_dump to get DB schemas. Currently, we are using a special service for this. But it would be great to execute pg_dump in an isolated environment. And we already have such an environment, it's our compute! And likely enough pg_dump already exists there too! (see https://github.com/neondatabase/cloud/issues/11644#issuecomment-2084617832) 2. We need to have a way to get databases and roles from compute after time travel (see https://github.com/neondatabase/cloud/issues/12109) ## Summary of changes It adds two API endpoints to compute_ctl HTTP API that target both of the aforementioned cases. --------- Co-authored-by: Tristan Partin <tristan@neon.tech>
This commit is contained in:
0
test_runner/fixtures/endpoint/__init__.py
Normal file
0
test_runner/fixtures/endpoint/__init__.py
Normal file
23
test_runner/fixtures/endpoint/http.py
Normal file
23
test_runner/fixtures/endpoint/http.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import requests
|
||||
from requests.adapters import HTTPAdapter
|
||||
|
||||
|
||||
class EndpointHttpClient(requests.Session):
|
||||
def __init__(
|
||||
self,
|
||||
port: int,
|
||||
):
|
||||
super().__init__()
|
||||
self.port = port
|
||||
|
||||
self.mount("http://", HTTPAdapter())
|
||||
|
||||
def dbs_and_roles(self):
|
||||
res = self.get(f"http://localhost:{self.port}/dbs_and_roles")
|
||||
res.raise_for_status()
|
||||
return res.json()
|
||||
|
||||
def database_schema(self, database: str):
|
||||
res = self.get(f"http://localhost:{self.port}/database_schema?database={database}")
|
||||
res.raise_for_status()
|
||||
return res.text
|
||||
@@ -48,6 +48,7 @@ from urllib3.util.retry import Retry
|
||||
from fixtures import overlayfs
|
||||
from fixtures.broker import NeonBroker
|
||||
from fixtures.common_types import Lsn, TenantId, TenantShardId, TimelineId
|
||||
from fixtures.endpoint.http import EndpointHttpClient
|
||||
from fixtures.log_helper import log
|
||||
from fixtures.metrics import Metrics, MetricsGetter, parse_metrics
|
||||
from fixtures.pageserver.allowed_errors import (
|
||||
@@ -3373,6 +3374,13 @@ class Endpoint(PgProtocol):
|
||||
self.active_safekeepers: List[int] = list(map(lambda sk: sk.id, env.safekeepers))
|
||||
# path to conf is <repo_dir>/endpoints/<endpoint_id>/pgdata/postgresql.conf
|
||||
|
||||
def http_client(
|
||||
self, auth_token: Optional[str] = None, retries: Optional[Retry] = None
|
||||
) -> EndpointHttpClient:
|
||||
return EndpointHttpClient(
|
||||
port=self.http_port,
|
||||
)
|
||||
|
||||
def create(
|
||||
self,
|
||||
branch_name: str,
|
||||
|
||||
34
test_runner/regress/test_compute_catalog.py
Normal file
34
test_runner/regress/test_compute_catalog.py
Normal file
@@ -0,0 +1,34 @@
|
||||
import requests
|
||||
from fixtures.neon_fixtures import NeonEnv
|
||||
|
||||
|
||||
def test_compute_catalog(neon_simple_env: NeonEnv):
|
||||
env = neon_simple_env
|
||||
env.neon_cli.create_branch("test_config", "empty")
|
||||
|
||||
endpoint = env.endpoints.create_start("test_config", config_lines=["log_min_messages=debug1"])
|
||||
client = endpoint.http_client()
|
||||
|
||||
objects = client.dbs_and_roles()
|
||||
|
||||
# Assert that 'cloud_admin' role exists in the 'roles' list
|
||||
assert any(
|
||||
role["name"] == "cloud_admin" for role in objects["roles"]
|
||||
), "The 'cloud_admin' role is missing"
|
||||
|
||||
# Assert that 'postgres' database exists in the 'databases' list
|
||||
assert any(
|
||||
db["name"] == "postgres" for db in objects["databases"]
|
||||
), "The 'postgres' database is missing"
|
||||
|
||||
ddl = client.database_schema(database="postgres")
|
||||
|
||||
assert "-- PostgreSQL database dump" in ddl
|
||||
|
||||
try:
|
||||
client.database_schema(database="nonexistentdb")
|
||||
raise AssertionError("Expected HTTPError was not raised")
|
||||
except requests.exceptions.HTTPError as e:
|
||||
assert (
|
||||
e.response.status_code == 404
|
||||
), f"Expected 404 status code, but got {e.response.status_code}"
|
||||
Reference in New Issue
Block a user