mirror of
https://github.com/neondatabase/neon.git
synced 2026-01-08 22:12:56 +00:00
and add /metrics endpoint to compute_ctl to expose such metrics
metric format example for extension pg_rag
with versions 1.2.3 and 1.4.2
installed in 3 and 1 databases respectively:
neon_extensions_installed{extension="pg_rag", version="1.2.3"} = 3
neon_extensions_installed{extension="pg_rag", version="1.4.2"} = 1
------
infra part: https://github.com/neondatabase/flux-fleet/pull/251
---------
Co-authored-by: Tristan Partin <tristan@neon.tech>
145 lines
4.9 KiB
Python
145 lines
4.9 KiB
Python
from __future__ import annotations
|
|
|
|
import time
|
|
from logging import info
|
|
from typing import TYPE_CHECKING
|
|
|
|
from fixtures.log_helper import log
|
|
from fixtures.metrics import parse_metrics
|
|
|
|
if TYPE_CHECKING:
|
|
from fixtures.neon_fixtures import NeonEnv
|
|
|
|
|
|
def test_installed_extensions(neon_simple_env: NeonEnv):
|
|
"""basic test for the endpoint that returns the list of installed extensions"""
|
|
|
|
env = neon_simple_env
|
|
|
|
env.create_branch("test_installed_extensions")
|
|
|
|
endpoint = env.endpoints.create_start("test_installed_extensions")
|
|
|
|
endpoint.safe_psql("CREATE DATABASE test_installed_extensions")
|
|
endpoint.safe_psql("CREATE DATABASE test_installed_extensions_2")
|
|
|
|
client = endpoint.http_client()
|
|
res = client.installed_extensions()
|
|
|
|
info("Extensions list: %s", res)
|
|
info("Extensions: %s", res["extensions"])
|
|
# 'plpgsql' is a default extension that is always installed.
|
|
assert any(
|
|
ext["extname"] == "plpgsql" and ext["versions"] == ["1.0"] for ext in res["extensions"]
|
|
), "The 'plpgsql' extension is missing"
|
|
|
|
# check that the neon_test_utils extension is not installed
|
|
assert not any(
|
|
ext["extname"] == "neon_test_utils" for ext in res["extensions"]
|
|
), "The 'neon_test_utils' extension is installed"
|
|
|
|
pg_conn = endpoint.connect(dbname="test_installed_extensions")
|
|
with pg_conn.cursor() as cur:
|
|
cur.execute("CREATE EXTENSION neon_test_utils")
|
|
cur.execute(
|
|
"SELECT default_version FROM pg_available_extensions WHERE name = 'neon_test_utils'"
|
|
)
|
|
res = cur.fetchone()
|
|
neon_test_utils_version = res[0]
|
|
|
|
with pg_conn.cursor() as cur:
|
|
cur.execute("CREATE EXTENSION neon version '1.1'")
|
|
|
|
pg_conn_2 = endpoint.connect(dbname="test_installed_extensions_2")
|
|
with pg_conn_2.cursor() as cur:
|
|
cur.execute("CREATE EXTENSION neon version '1.2'")
|
|
|
|
res = client.installed_extensions()
|
|
|
|
info("Extensions list: %s", res)
|
|
info("Extensions: %s", res["extensions"])
|
|
|
|
# check that the neon_test_utils extension is installed only in 1 database
|
|
# and has the expected version
|
|
assert any(
|
|
ext["extname"] == "neon_test_utils"
|
|
and ext["versions"] == [neon_test_utils_version]
|
|
and ext["n_databases"] == 1
|
|
for ext in res["extensions"]
|
|
)
|
|
|
|
# check that the plpgsql extension is installed in all databases
|
|
# this is a default extension that is always installed
|
|
assert any(ext["extname"] == "plpgsql" and ext["n_databases"] == 4 for ext in res["extensions"])
|
|
|
|
# check that the neon extension is installed and has expected versions
|
|
for ext in res["extensions"]:
|
|
if ext["extname"] == "neon":
|
|
assert ext["n_databases"] == 2
|
|
ext["versions"].sort()
|
|
assert ext["versions"] == ["1.1", "1.2"]
|
|
|
|
with pg_conn.cursor() as cur:
|
|
cur.execute("ALTER EXTENSION neon UPDATE TO '1.3'")
|
|
|
|
res = client.installed_extensions()
|
|
|
|
info("Extensions list: %s", res)
|
|
info("Extensions: %s", res["extensions"])
|
|
|
|
# check that the neon_test_utils extension is updated
|
|
for ext in res["extensions"]:
|
|
if ext["extname"] == "neon":
|
|
assert ext["n_databases"] == 2
|
|
ext["versions"].sort()
|
|
assert ext["versions"] == ["1.2", "1.3"]
|
|
|
|
# check that /metrics endpoint is available
|
|
# ensure that we see the metric before and after restart
|
|
res = client.metrics()
|
|
info("Metrics: %s", res)
|
|
m = parse_metrics(res)
|
|
neon_m = m.query_all("installed_extensions", {"extension_name": "neon", "version": "1.2"})
|
|
assert len(neon_m) == 1
|
|
for sample in neon_m:
|
|
assert sample.value == 2
|
|
neon_m = m.query_all("installed_extensions", {"extension_name": "neon", "version": "1.3"})
|
|
assert len(neon_m) == 1
|
|
for sample in neon_m:
|
|
assert sample.value == 1
|
|
|
|
endpoint.stop()
|
|
endpoint.start()
|
|
|
|
timeout = 10
|
|
while timeout > 0:
|
|
try:
|
|
res = client.metrics()
|
|
timeout = -1
|
|
if len(parse_metrics(res).query_all("installed_extensions")) < 4:
|
|
# Assume that not all metrics that are collected yet
|
|
time.sleep(1)
|
|
timeout -= 1
|
|
continue
|
|
except Exception:
|
|
log.exception("failed to get metrics, assume they are not collected yet")
|
|
time.sleep(1)
|
|
timeout -= 1
|
|
continue
|
|
|
|
assert (
|
|
len(parse_metrics(res).query_all("installed_extensions")) >= 4
|
|
), "Not all metrics are collected"
|
|
|
|
info("After restart metrics: %s", res)
|
|
m = parse_metrics(res)
|
|
neon_m = m.query_all("installed_extensions", {"extension_name": "neon", "version": "1.2"})
|
|
assert len(neon_m) == 1
|
|
for sample in neon_m:
|
|
assert sample.value == 1
|
|
|
|
neon_m = m.query_all("installed_extensions", {"extension_name": "neon", "version": "1.3"})
|
|
assert len(neon_m) == 1
|
|
for sample in neon_m:
|
|
assert sample.value == 1
|