phlo-postgres 0.3.2__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/PKG-INFO +1 -2
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/pyproject.toml +1 -2
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres/__init__.py +1 -1
- phlo_postgres-0.4.0/src/phlo_postgres/authorization.py +41 -0
- phlo_postgres-0.4.0/src/phlo_postgres/cli_plugin.py +17 -0
- phlo_postgres-0.4.0/src/phlo_postgres/plugin.py +130 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres.egg-info/PKG-INFO +1 -2
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres.egg-info/requires.txt +0 -1
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/tests/test_authorization.py +1 -1
- phlo_postgres-0.3.2/src/phlo_postgres/authorization.py +0 -173
- phlo_postgres-0.3.2/src/phlo_postgres/cli_plugin.py +0 -88
- phlo_postgres-0.3.2/src/phlo_postgres/plugin.py +0 -213
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/README.md +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/setup.cfg +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres/cli.py +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres/exporter_service.yaml +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres/publish_target.py +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres/resource.py +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres/service.yaml +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres/settings.py +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres/volume_setup.yaml +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres.egg-info/SOURCES.txt +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres.egg-info/dependency_links.txt +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres.egg-info/entry_points.txt +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/src/phlo_postgres.egg-info/top_level.txt +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/tests/test_integration_postgres.py +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/tests/test_postgres_cli.py +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/tests/test_postgres_plugin.py +0 -0
- {phlo_postgres-0.3.2 → phlo_postgres-0.4.0}/tests/test_resource.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: phlo-postgres
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Postgres service plugin for Phlo
|
|
5
5
|
Author-email: Phlo Team <team@phlo.dev>
|
|
6
6
|
License: MIT
|
|
@@ -8,7 +8,6 @@ Requires-Python: >=3.11
|
|
|
8
8
|
Description-Content-Type: text/plain
|
|
9
9
|
Requires-Dist: phlo>=0.1.0
|
|
10
10
|
Requires-Dist: psycopg2-binary>=2.9.11
|
|
11
|
-
Requires-Dist: pyyaml>=6.0.1
|
|
12
11
|
Provides-Extra: dev
|
|
13
12
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
14
13
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
@@ -9,12 +9,11 @@ requires = [
|
|
|
9
9
|
dependencies = [
|
|
10
10
|
"phlo>=0.1.0",
|
|
11
11
|
"psycopg2-binary>=2.9.11",
|
|
12
|
-
"pyyaml>=6.0.1",
|
|
13
12
|
]
|
|
14
13
|
description = "Postgres service plugin for Phlo"
|
|
15
14
|
name = "phlo-postgres"
|
|
16
15
|
requires-python = ">=3.11"
|
|
17
|
-
version = "0.
|
|
16
|
+
version = "0.4.0"
|
|
18
17
|
|
|
19
18
|
[[project.authors]]
|
|
20
19
|
email = "team@phlo.dev"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""phlo_postgres CLI authorization table."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from phlo.cli.authorization import cli_surface_adapter_class
|
|
6
|
+
|
|
7
|
+
SURFACE_NAME = "phlo-postgres-cli"
|
|
8
|
+
FRAMEWORK_TYPE = "cli"
|
|
9
|
+
MUTATION_COMMANDS: frozenset[str] = frozenset(
|
|
10
|
+
["postgres", "postgres.dump", "postgres.query", "postgres.restore", "postgres.vacuum"]
|
|
11
|
+
)
|
|
12
|
+
READ_COMMANDS: frozenset[str] = frozenset([])
|
|
13
|
+
COMMAND_RESOURCE_MAP: dict[str, str] = {
|
|
14
|
+
"postgres.query": "dataset",
|
|
15
|
+
"postgres.dump": "dataset",
|
|
16
|
+
"postgres.restore": "dataset",
|
|
17
|
+
"postgres.vacuum": "dataset",
|
|
18
|
+
"postgres": "dataset",
|
|
19
|
+
}
|
|
20
|
+
COMMAND_ACTION_MAP: dict[str, str] = {
|
|
21
|
+
"postgres.query": "dataset.query",
|
|
22
|
+
"postgres.dump": "dataset.manage",
|
|
23
|
+
"postgres.restore": "dataset.manage",
|
|
24
|
+
"postgres.vacuum": "dataset.manage",
|
|
25
|
+
"postgres": "dataset.query",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
PostgresCliSurfaceAdapter = cli_surface_adapter_class(
|
|
29
|
+
"PostgresCliSurfaceAdapter",
|
|
30
|
+
surface_name=SURFACE_NAME,
|
|
31
|
+
mutation_commands=MUTATION_COMMANDS,
|
|
32
|
+
read_commands=READ_COMMANDS,
|
|
33
|
+
command_resource_map=COMMAND_RESOURCE_MAP,
|
|
34
|
+
command_action_map=COMMAND_ACTION_MAP,
|
|
35
|
+
default_action_prefix="postgres",
|
|
36
|
+
default_resource_prefix="postgres",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_postgres_cli_adapter() -> PostgresCliSurfaceAdapter:
|
|
41
|
+
return PostgresCliSurfaceAdapter.get_instance()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Postgres CLI plugin registration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from phlo.plugins.base import cli_command_plugin_class
|
|
7
|
+
|
|
8
|
+
from phlo_postgres.cli import postgres_group
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
PostgresCliPlugin = cli_command_plugin_class(
|
|
12
|
+
"PostgresCliPlugin",
|
|
13
|
+
name="postgres",
|
|
14
|
+
version="0.1.0",
|
|
15
|
+
description="CLI commands for PostgreSQL service access",
|
|
16
|
+
commands=[postgres_group],
|
|
17
|
+
)
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""PostgreSQL service plugin implementations.
|
|
2
|
+
|
|
3
|
+
This module provides plugin implementations that integrate PostgreSQL with the
|
|
4
|
+
phlo plugin system. It includes service plugins for the PostgreSQL database,
|
|
5
|
+
Prometheus exporter, and volume setup, as well as a resource provider plugin
|
|
6
|
+
that exposes PostgreSQL capabilities to the rest of the system.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
>>> from phlo_postgres.plugin import PostgresServicePlugin
|
|
10
|
+
>>> plugin = PostgresServicePlugin()
|
|
11
|
+
>>> print(plugin.metadata.name)
|
|
12
|
+
postgres
|
|
13
|
+
>>> definition = plugin.service_definition
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from phlo.capabilities import PublishTargetSpec, ResourceSpec
|
|
20
|
+
from phlo.plugins import PluginMetadata, ResourceProviderPlugin, service_plugin_class
|
|
21
|
+
|
|
22
|
+
from phlo_postgres.publish_target import PostgresPublishTarget
|
|
23
|
+
from phlo_postgres.resource import PostgresResource
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
PostgresServicePlugin = service_plugin_class(
|
|
27
|
+
"PostgresServicePlugin",
|
|
28
|
+
name="postgres",
|
|
29
|
+
version="0.1.0",
|
|
30
|
+
description="PostgreSQL database for metadata and operational storage",
|
|
31
|
+
author="Phlo Team",
|
|
32
|
+
tags=["core", "database", "postgres"],
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
PostgresExporterServicePlugin = service_plugin_class(
|
|
37
|
+
"PostgresExporterServicePlugin",
|
|
38
|
+
name="postgres-exporter",
|
|
39
|
+
version="0.1.0",
|
|
40
|
+
description="Prometheus exporter for PostgreSQL metrics",
|
|
41
|
+
author="Phlo Team",
|
|
42
|
+
tags=["observability", "metrics", "postgres"],
|
|
43
|
+
service_definition_file="exporter_service.yaml",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
PostgresVolumeSetupServicePlugin = service_plugin_class(
|
|
48
|
+
"PostgresVolumeSetupServicePlugin",
|
|
49
|
+
name="postgres-volume-setup",
|
|
50
|
+
version="0.1.0",
|
|
51
|
+
description="Initialize PostgreSQL data volume permissions",
|
|
52
|
+
author="Phlo Team",
|
|
53
|
+
tags=["core", "database", "postgres"],
|
|
54
|
+
service_definition_file="volume_setup.yaml",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class PostgresResourceProvider(ResourceProviderPlugin):
|
|
59
|
+
"""Resource provider plugin that exposes PostgreSQL capabilities.
|
|
60
|
+
|
|
61
|
+
This plugin registers the PostgresResource and PostgresPublishTarget with
|
|
62
|
+
the phlo resource system, making them available to other components for
|
|
63
|
+
database operations and data publishing.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
>>> provider = PostgresResourceProvider()
|
|
67
|
+
>>> resources = provider.get_resources()
|
|
68
|
+
>>> targets = provider.get_publish_targets()
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def metadata(self) -> PluginMetadata:
|
|
74
|
+
"""Return plugin metadata for the PostgreSQL resource provider.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
PluginMetadata: Metadata describing the resource provider plugin.
|
|
78
|
+
|
|
79
|
+
Example:
|
|
80
|
+
>>> provider = PostgresResourceProvider()
|
|
81
|
+
>>> meta = provider.metadata
|
|
82
|
+
>>> print(meta.name)
|
|
83
|
+
postgres
|
|
84
|
+
|
|
85
|
+
"""
|
|
86
|
+
return PluginMetadata(
|
|
87
|
+
name="postgres",
|
|
88
|
+
version="0.1.0",
|
|
89
|
+
description="Postgres resource for Phlo",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def get_resources(self) -> list[ResourceSpec]:
|
|
93
|
+
"""Return resource specifications exposed by this provider.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
list[ResourceSpec]: List of registered resource specifications
|
|
97
|
+
that can be accessed by other phlo components.
|
|
98
|
+
|
|
99
|
+
Example:
|
|
100
|
+
>>> provider = PostgresResourceProvider()
|
|
101
|
+
>>> specs = provider.get_resources()
|
|
102
|
+
>>> print(specs[0].name)
|
|
103
|
+
postgres
|
|
104
|
+
|
|
105
|
+
"""
|
|
106
|
+
return [ResourceSpec(name="postgres", resource=PostgresResource())]
|
|
107
|
+
|
|
108
|
+
def get_publish_targets(self) -> list[PublishTargetSpec]:
|
|
109
|
+
"""Return publish target capability specs exposed by this provider.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
list[PublishTargetSpec]: List of publish target specifications
|
|
113
|
+
that define where data can be published to PostgreSQL.
|
|
114
|
+
|
|
115
|
+
Example:
|
|
116
|
+
>>> provider = PostgresResourceProvider()
|
|
117
|
+
>>> targets = provider.get_publish_targets()
|
|
118
|
+
>>> print(targets[0].name)
|
|
119
|
+
postgres
|
|
120
|
+
>>> print(targets[0].metadata)
|
|
121
|
+
{'target_system': 'postgres', 'role': 'serving'}
|
|
122
|
+
|
|
123
|
+
"""
|
|
124
|
+
return [
|
|
125
|
+
PublishTargetSpec(
|
|
126
|
+
name="postgres",
|
|
127
|
+
provider=PostgresPublishTarget(),
|
|
128
|
+
metadata={"target_system": "postgres", "role": "serving"},
|
|
129
|
+
)
|
|
130
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: phlo-postgres
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Postgres service plugin for Phlo
|
|
5
5
|
Author-email: Phlo Team <team@phlo.dev>
|
|
6
6
|
License: MIT
|
|
@@ -8,7 +8,6 @@ Requires-Python: >=3.11
|
|
|
8
8
|
Description-Content-Type: text/plain
|
|
9
9
|
Requires-Dist: phlo>=0.1.0
|
|
10
10
|
Requires-Dist: psycopg2-binary>=2.9.11
|
|
11
|
-
Requires-Dist: pyyaml>=6.0.1
|
|
12
11
|
Provides-Extra: dev
|
|
13
12
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
14
13
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
@@ -111,7 +111,7 @@ class TestPostgresCliSurfaceAdapter:
|
|
|
111
111
|
mock_result = MagicMock()
|
|
112
112
|
mock_result.variant = "allow"
|
|
113
113
|
|
|
114
|
-
with patch("
|
|
114
|
+
with patch("phlo.cli.authorization.enforce", return_value=mock_result):
|
|
115
115
|
with patch.object(adapter, "_resolver"):
|
|
116
116
|
from phlo.capabilities.interfaces import AuthPrincipal
|
|
117
117
|
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
"""CLI regulated surface adapter for PostgreSQL.
|
|
2
|
-
|
|
3
|
-
This module provides the regulated surface adapter for the PostgreSQL CLI,
|
|
4
|
-
declaring mutation commands that require authorization and enforcing
|
|
5
|
-
through core enforcement.
|
|
6
|
-
|
|
7
|
-
Commands:
|
|
8
|
-
- postgres query: Execute SQL (mutation - can be SELECT or DDL/DML)
|
|
9
|
-
- postgres dump: Create database dump (mutation)
|
|
10
|
-
- postgres restore: Restore from dump (mutation)
|
|
11
|
-
- postgres vacuum: Run vacuumdb maintenance (mutation)
|
|
12
|
-
- postgres: Raw psql passthrough (mutation)
|
|
13
|
-
|
|
14
|
-
Resource/Action mapping:
|
|
15
|
-
- dataset.query: SQL execution
|
|
16
|
-
- dataset.manage: Database maintenance operations
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
from __future__ import annotations
|
|
20
|
-
|
|
21
|
-
import os
|
|
22
|
-
import threading
|
|
23
|
-
from typing import Any
|
|
24
|
-
|
|
25
|
-
from phlo.cli.authorization import CliPrincipalResolver
|
|
26
|
-
from phlo.logging import get_logger
|
|
27
|
-
from phlo.security.adapters import (
|
|
28
|
-
EnforcementResult,
|
|
29
|
-
SurfaceOperation,
|
|
30
|
-
)
|
|
31
|
-
from phlo.security.enforcement import enforce
|
|
32
|
-
|
|
33
|
-
logger = get_logger(__name__)
|
|
34
|
-
|
|
35
|
-
SURFACE_NAME = "phlo-postgres-cli"
|
|
36
|
-
FRAMEWORK_TYPE = "cli"
|
|
37
|
-
|
|
38
|
-
MUTATION_COMMANDS: frozenset[str] = frozenset(
|
|
39
|
-
{
|
|
40
|
-
"postgres.query",
|
|
41
|
-
"postgres.dump",
|
|
42
|
-
"postgres.restore",
|
|
43
|
-
"postgres.vacuum",
|
|
44
|
-
"postgres",
|
|
45
|
-
}
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
READ_COMMANDS: frozenset[str] = frozenset({})
|
|
49
|
-
|
|
50
|
-
COMMAND_RESOURCE_MAP: dict[str, str] = {
|
|
51
|
-
"postgres.query": "dataset",
|
|
52
|
-
"postgres.dump": "dataset",
|
|
53
|
-
"postgres.restore": "dataset",
|
|
54
|
-
"postgres.vacuum": "dataset",
|
|
55
|
-
"postgres": "dataset",
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
COMMAND_ACTION_MAP: dict[str, str] = {
|
|
59
|
-
"postgres.query": "dataset.query",
|
|
60
|
-
"postgres.dump": "dataset.manage",
|
|
61
|
-
"postgres.restore": "dataset.manage",
|
|
62
|
-
"postgres.vacuum": "dataset.manage",
|
|
63
|
-
"postgres": "dataset.query",
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class PostgresCliSurfaceAdapter:
|
|
68
|
-
"""Regulated surface adapter for PostgreSQL CLI."""
|
|
69
|
-
|
|
70
|
-
_instance: PostgresCliSurfaceAdapter | None = None
|
|
71
|
-
_lock = threading.Lock()
|
|
72
|
-
|
|
73
|
-
def __init__(self) -> None:
|
|
74
|
-
self._resolver = CliPrincipalResolver()
|
|
75
|
-
|
|
76
|
-
@classmethod
|
|
77
|
-
def get_instance(cls) -> PostgresCliSurfaceAdapter:
|
|
78
|
-
if cls._instance is None:
|
|
79
|
-
with cls._lock:
|
|
80
|
-
if cls._instance is None:
|
|
81
|
-
cls._instance = cls()
|
|
82
|
-
return cls._instance
|
|
83
|
-
|
|
84
|
-
@property
|
|
85
|
-
def surface_name(self) -> str:
|
|
86
|
-
return SURFACE_NAME
|
|
87
|
-
|
|
88
|
-
@property
|
|
89
|
-
def framework_type(self) -> str:
|
|
90
|
-
return FRAMEWORK_TYPE
|
|
91
|
-
|
|
92
|
-
def list_operations(self) -> list[SurfaceOperation]:
|
|
93
|
-
operations: list[SurfaceOperation] = []
|
|
94
|
-
for command in MUTATION_COMMANDS:
|
|
95
|
-
resource_type = COMMAND_RESOURCE_MAP.get(command, "dataset")
|
|
96
|
-
action = COMMAND_ACTION_MAP.get(command, "dataset.query")
|
|
97
|
-
operations.append(
|
|
98
|
-
SurfaceOperation(
|
|
99
|
-
action=action,
|
|
100
|
-
resource_type=resource_type,
|
|
101
|
-
operation_name=command,
|
|
102
|
-
resource_id_strategy=None,
|
|
103
|
-
framework_metadata={"command": command},
|
|
104
|
-
)
|
|
105
|
-
)
|
|
106
|
-
return operations
|
|
107
|
-
|
|
108
|
-
def is_active(self, runtime: Any) -> bool:
|
|
109
|
-
return True
|
|
110
|
-
|
|
111
|
-
def install(self, runtime: Any) -> None:
|
|
112
|
-
pass
|
|
113
|
-
|
|
114
|
-
def enforce_mutation(self, command: str, resource_id: str | None = None) -> EnforcementResult:
|
|
115
|
-
"""Enforce authorization for a mutation command."""
|
|
116
|
-
if command not in MUTATION_COMMANDS:
|
|
117
|
-
return EnforcementResult.allow()
|
|
118
|
-
|
|
119
|
-
action = COMMAND_ACTION_MAP.get(command, "dataset.query")
|
|
120
|
-
resource_type = COMMAND_RESOURCE_MAP.get(command, "dataset")
|
|
121
|
-
resource_id_final = resource_id or f"postgres:{command}"
|
|
122
|
-
|
|
123
|
-
principal = self._resolver.resolve()
|
|
124
|
-
|
|
125
|
-
from phlo.capabilities.interfaces import ResourceRef
|
|
126
|
-
|
|
127
|
-
resource = ResourceRef(
|
|
128
|
-
resource_type=resource_type,
|
|
129
|
-
resource_id=resource_id_final,
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
request_id = os.environ.get("PHLO_REQUEST_ID")
|
|
133
|
-
|
|
134
|
-
result = enforce(
|
|
135
|
-
principal=principal,
|
|
136
|
-
action=action,
|
|
137
|
-
resource=resource,
|
|
138
|
-
context=None,
|
|
139
|
-
request_id=request_id,
|
|
140
|
-
surface=SURFACE_NAME,
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
logger.debug(
|
|
144
|
-
"postgres_cli_mutation_enforcement_result",
|
|
145
|
-
command=command,
|
|
146
|
-
action=action,
|
|
147
|
-
result=result.variant,
|
|
148
|
-
subject=principal.subject,
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
return result
|
|
152
|
-
|
|
153
|
-
def check_command_authorization(self, command_path: str) -> EnforcementResult:
|
|
154
|
-
"""Check if a command is authorized to run."""
|
|
155
|
-
if command_path in READ_COMMANDS:
|
|
156
|
-
return EnforcementResult.allow()
|
|
157
|
-
|
|
158
|
-
if command_path in MUTATION_COMMANDS:
|
|
159
|
-
return self.enforce_mutation(command_path)
|
|
160
|
-
|
|
161
|
-
logger.warning(
|
|
162
|
-
"postgres_cli_unknown_command_classification",
|
|
163
|
-
command=command_path,
|
|
164
|
-
)
|
|
165
|
-
return EnforcementResult.deny(
|
|
166
|
-
reason_code="unknown_command",
|
|
167
|
-
explanation=f"Command '{command_path}' is not classified as read or mutation",
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
def get_postgres_cli_adapter() -> PostgresCliSurfaceAdapter:
|
|
172
|
-
"""Get the singleton PostgreSQL CLI surface adapter."""
|
|
173
|
-
return PostgresCliSurfaceAdapter.get_instance()
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
"""CLI plugin for PostgreSQL commands.
|
|
2
|
-
|
|
3
|
-
This module provides the CLI plugin implementation that registers PostgreSQL
|
|
4
|
-
commands with the phlo CLI system. It exposes the postgres command group and
|
|
5
|
-
its subcommands (query, dump, restore, vacuum) to the main phlo CLI.
|
|
6
|
-
|
|
7
|
-
Example:
|
|
8
|
-
>>> from phlo_postgres.cli_plugin import PostgresCliPlugin
|
|
9
|
-
>>> plugin = PostgresCliPlugin()
|
|
10
|
-
>>> commands = plugin.get_cli_commands()
|
|
11
|
-
>>> print(commands[0].name)
|
|
12
|
-
postgres
|
|
13
|
-
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
from __future__ import annotations
|
|
17
|
-
|
|
18
|
-
import click
|
|
19
|
-
|
|
20
|
-
from phlo.plugins.base import CliCommandPlugin, PluginMetadata
|
|
21
|
-
|
|
22
|
-
from phlo_postgres.cli import postgres_group
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class PostgresCliPlugin(CliCommandPlugin):
|
|
26
|
-
"""CLI plugin that registers PostgreSQL commands with the phlo CLI.
|
|
27
|
-
|
|
28
|
-
This plugin provides the main entry point for PostgreSQL-related CLI
|
|
29
|
-
commands. It registers the postgres command group which includes
|
|
30
|
-
subcommands for querying, dumping, restoring, and maintaining PostgreSQL
|
|
31
|
-
databases.
|
|
32
|
-
|
|
33
|
-
Attributes:
|
|
34
|
-
None (uses class-level plugin registration).
|
|
35
|
-
|
|
36
|
-
Example:
|
|
37
|
-
>>> plugin = PostgresCliPlugin()
|
|
38
|
-
>>> print(plugin.metadata.name)
|
|
39
|
-
postgres
|
|
40
|
-
>>> commands = plugin.get_cli_commands()
|
|
41
|
-
>>> print([cmd.name for cmd in commands])
|
|
42
|
-
['postgres']
|
|
43
|
-
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
@property
|
|
47
|
-
def metadata(self) -> PluginMetadata:
|
|
48
|
-
"""Return plugin metadata for the PostgreSQL CLI plugin.
|
|
49
|
-
|
|
50
|
-
Returns:
|
|
51
|
-
PluginMetadata: Metadata describing the CLI plugin including name,
|
|
52
|
-
version, and description for plugin discovery.
|
|
53
|
-
|
|
54
|
-
Example:
|
|
55
|
-
>>> plugin = PostgresCliPlugin()
|
|
56
|
-
>>> meta = plugin.metadata
|
|
57
|
-
>>> print(f"{meta.name} v{meta.version}")
|
|
58
|
-
postgres v0.1.0
|
|
59
|
-
>>> print(meta.description)
|
|
60
|
-
CLI commands for PostgreSQL service access
|
|
61
|
-
|
|
62
|
-
"""
|
|
63
|
-
return PluginMetadata(
|
|
64
|
-
name="postgres",
|
|
65
|
-
version="0.1.0",
|
|
66
|
-
description="CLI commands for PostgreSQL service access",
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
def get_cli_commands(self) -> list[click.Command]:
|
|
70
|
-
"""Return CLI commands provided by this plugin.
|
|
71
|
-
|
|
72
|
-
Returns:
|
|
73
|
-
list[click.Command]: List of Click command objects to register
|
|
74
|
-
with the main phlo CLI. Currently provides the postgres
|
|
75
|
-
command group which includes query, dump, restore, and
|
|
76
|
-
vacuum subcommands.
|
|
77
|
-
|
|
78
|
-
Example:
|
|
79
|
-
>>> plugin = PostgresCliPlugin()
|
|
80
|
-
>>> commands = plugin.get_cli_commands()
|
|
81
|
-
>>> cmd = commands[0]
|
|
82
|
-
>>> print(cmd.name)
|
|
83
|
-
postgres
|
|
84
|
-
>>> print([c.name for c in cmd.commands.values()])
|
|
85
|
-
['query', 'dump', 'restore', 'vacuum']
|
|
86
|
-
|
|
87
|
-
"""
|
|
88
|
-
return [postgres_group]
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
"""PostgreSQL service plugin implementations.
|
|
2
|
-
|
|
3
|
-
This module provides plugin implementations that integrate PostgreSQL with the
|
|
4
|
-
phlo plugin system. It includes service plugins for the PostgreSQL database,
|
|
5
|
-
Prometheus exporter, and volume setup, as well as a resource provider plugin
|
|
6
|
-
that exposes PostgreSQL capabilities to the rest of the system.
|
|
7
|
-
|
|
8
|
-
Example:
|
|
9
|
-
>>> from phlo_postgres.plugin import PostgresServicePlugin
|
|
10
|
-
>>> plugin = PostgresServicePlugin()
|
|
11
|
-
>>> print(plugin.metadata.name)
|
|
12
|
-
postgres
|
|
13
|
-
>>> definition = plugin.service_definition
|
|
14
|
-
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
from __future__ import annotations
|
|
18
|
-
|
|
19
|
-
from phlo.capabilities import PublishTargetSpec, ResourceSpec
|
|
20
|
-
from phlo.plugins import PackageYamlServicePlugin, PluginMetadata, ResourceProviderPlugin
|
|
21
|
-
|
|
22
|
-
from phlo_postgres.publish_target import PostgresPublishTarget
|
|
23
|
-
from phlo_postgres.resource import PostgresResource
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class PostgresServicePlugin(PackageYamlServicePlugin):
|
|
27
|
-
"""Service plugin for managing PostgreSQL as a phlo service.
|
|
28
|
-
|
|
29
|
-
This plugin provides the core PostgreSQL database service definition for
|
|
30
|
-
docker-compose integration. It loads service configuration from package
|
|
31
|
-
data (service.yaml) and exposes metadata for plugin discovery.
|
|
32
|
-
|
|
33
|
-
Example:
|
|
34
|
-
>>> plugin = PostgresServicePlugin()
|
|
35
|
-
>>> metadata = plugin.metadata
|
|
36
|
-
>>> print(f"Service: {metadata.name} v{metadata.version}")
|
|
37
|
-
Service: postgres v0.1.0
|
|
38
|
-
>>> definition = plugin.service_definition
|
|
39
|
-
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def metadata(self) -> PluginMetadata:
|
|
44
|
-
"""Return plugin metadata for the PostgreSQL service.
|
|
45
|
-
|
|
46
|
-
Returns:
|
|
47
|
-
PluginMetadata: Metadata describing the service plugin including
|
|
48
|
-
name, version, description, author, and tags for categorization.
|
|
49
|
-
|
|
50
|
-
Example:
|
|
51
|
-
>>> plugin = PostgresServicePlugin()
|
|
52
|
-
>>> meta = plugin.metadata
|
|
53
|
-
>>> print(meta.name)
|
|
54
|
-
postgres
|
|
55
|
-
>>> print(meta.tags)
|
|
56
|
-
['core', 'database', 'postgres']
|
|
57
|
-
|
|
58
|
-
"""
|
|
59
|
-
return PluginMetadata(
|
|
60
|
-
name="postgres",
|
|
61
|
-
version="0.1.0",
|
|
62
|
-
description="PostgreSQL database for metadata and operational storage",
|
|
63
|
-
author="Phlo Team",
|
|
64
|
-
tags=["core", "database", "postgres"],
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class PostgresExporterServicePlugin(PackageYamlServicePlugin):
|
|
69
|
-
"""Service plugin for PostgreSQL Prometheus metrics exporter.
|
|
70
|
-
|
|
71
|
-
This plugin provides a Prometheus exporter service that exposes PostgreSQL
|
|
72
|
-
metrics for monitoring and alerting. It runs as a sidecar service alongside
|
|
73
|
-
the main PostgreSQL container.
|
|
74
|
-
|
|
75
|
-
Example:
|
|
76
|
-
>>> plugin = PostgresExporterServicePlugin()
|
|
77
|
-
>>> print(plugin.metadata.name)
|
|
78
|
-
postgres-exporter
|
|
79
|
-
|
|
80
|
-
"""
|
|
81
|
-
|
|
82
|
-
_service_definition_file = "exporter_service.yaml"
|
|
83
|
-
|
|
84
|
-
@property
|
|
85
|
-
def metadata(self) -> PluginMetadata:
|
|
86
|
-
"""Return plugin metadata for the PostgreSQL exporter service.
|
|
87
|
-
|
|
88
|
-
Returns:
|
|
89
|
-
PluginMetadata: Metadata describing the exporter plugin.
|
|
90
|
-
|
|
91
|
-
Example:
|
|
92
|
-
>>> plugin = PostgresExporterServicePlugin()
|
|
93
|
-
>>> meta = plugin.metadata
|
|
94
|
-
>>> print(meta.description)
|
|
95
|
-
Prometheus exporter for PostgreSQL metrics
|
|
96
|
-
|
|
97
|
-
"""
|
|
98
|
-
return PluginMetadata(
|
|
99
|
-
name="postgres-exporter",
|
|
100
|
-
version="0.1.0",
|
|
101
|
-
description="Prometheus exporter for PostgreSQL metrics",
|
|
102
|
-
author="Phlo Team",
|
|
103
|
-
tags=["observability", "metrics", "postgres"],
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
class PostgresVolumeSetupServicePlugin(PackageYamlServicePlugin):
|
|
108
|
-
"""Service plugin for PostgreSQL data volume permission setup.
|
|
109
|
-
|
|
110
|
-
This plugin provides an initialization service that ensures proper
|
|
111
|
-
ownership and permissions on PostgreSQL data volumes before the main
|
|
112
|
-
database container starts. This is particularly important for bind mounts
|
|
113
|
-
on systems with strict permission requirements.
|
|
114
|
-
|
|
115
|
-
Example:
|
|
116
|
-
>>> plugin = PostgresVolumeSetupServicePlugin()
|
|
117
|
-
>>> print(plugin.metadata.name)
|
|
118
|
-
postgres-volume-setup
|
|
119
|
-
|
|
120
|
-
"""
|
|
121
|
-
|
|
122
|
-
_service_definition_file = "volume_setup.yaml"
|
|
123
|
-
|
|
124
|
-
@property
|
|
125
|
-
def metadata(self) -> PluginMetadata:
|
|
126
|
-
"""Return plugin metadata for the PostgreSQL volume setup service.
|
|
127
|
-
|
|
128
|
-
Returns:
|
|
129
|
-
PluginMetadata: Metadata describing the volume setup plugin.
|
|
130
|
-
|
|
131
|
-
"""
|
|
132
|
-
return PluginMetadata(
|
|
133
|
-
name="postgres-volume-setup",
|
|
134
|
-
version="0.1.0",
|
|
135
|
-
description="Initialize PostgreSQL data volume permissions",
|
|
136
|
-
author="Phlo Team",
|
|
137
|
-
tags=["core", "database", "postgres"],
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
class PostgresResourceProvider(ResourceProviderPlugin):
|
|
142
|
-
"""Resource provider plugin that exposes PostgreSQL capabilities.
|
|
143
|
-
|
|
144
|
-
This plugin registers the PostgresResource and PostgresPublishTarget with
|
|
145
|
-
the phlo resource system, making them available to other components for
|
|
146
|
-
database operations and data publishing.
|
|
147
|
-
|
|
148
|
-
Example:
|
|
149
|
-
>>> provider = PostgresResourceProvider()
|
|
150
|
-
>>> resources = provider.get_resources()
|
|
151
|
-
>>> targets = provider.get_publish_targets()
|
|
152
|
-
|
|
153
|
-
"""
|
|
154
|
-
|
|
155
|
-
@property
|
|
156
|
-
def metadata(self) -> PluginMetadata:
|
|
157
|
-
"""Return plugin metadata for the PostgreSQL resource provider.
|
|
158
|
-
|
|
159
|
-
Returns:
|
|
160
|
-
PluginMetadata: Metadata describing the resource provider plugin.
|
|
161
|
-
|
|
162
|
-
Example:
|
|
163
|
-
>>> provider = PostgresResourceProvider()
|
|
164
|
-
>>> meta = provider.metadata
|
|
165
|
-
>>> print(meta.name)
|
|
166
|
-
postgres
|
|
167
|
-
|
|
168
|
-
"""
|
|
169
|
-
return PluginMetadata(
|
|
170
|
-
name="postgres",
|
|
171
|
-
version="0.1.0",
|
|
172
|
-
description="Postgres resource for Phlo",
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
def get_resources(self) -> list[ResourceSpec]:
|
|
176
|
-
"""Return resource specifications exposed by this provider.
|
|
177
|
-
|
|
178
|
-
Returns:
|
|
179
|
-
list[ResourceSpec]: List of registered resource specifications
|
|
180
|
-
that can be accessed by other phlo components.
|
|
181
|
-
|
|
182
|
-
Example:
|
|
183
|
-
>>> provider = PostgresResourceProvider()
|
|
184
|
-
>>> specs = provider.get_resources()
|
|
185
|
-
>>> print(specs[0].name)
|
|
186
|
-
postgres
|
|
187
|
-
|
|
188
|
-
"""
|
|
189
|
-
return [ResourceSpec(name="postgres", resource=PostgresResource())]
|
|
190
|
-
|
|
191
|
-
def get_publish_targets(self) -> list[PublishTargetSpec]:
|
|
192
|
-
"""Return publish target capability specs exposed by this provider.
|
|
193
|
-
|
|
194
|
-
Returns:
|
|
195
|
-
list[PublishTargetSpec]: List of publish target specifications
|
|
196
|
-
that define where data can be published to PostgreSQL.
|
|
197
|
-
|
|
198
|
-
Example:
|
|
199
|
-
>>> provider = PostgresResourceProvider()
|
|
200
|
-
>>> targets = provider.get_publish_targets()
|
|
201
|
-
>>> print(targets[0].name)
|
|
202
|
-
postgres
|
|
203
|
-
>>> print(targets[0].metadata)
|
|
204
|
-
{'target_system': 'postgres', 'role': 'serving'}
|
|
205
|
-
|
|
206
|
-
"""
|
|
207
|
-
return [
|
|
208
|
-
PublishTargetSpec(
|
|
209
|
-
name="postgres",
|
|
210
|
-
provider=PostgresPublishTarget(),
|
|
211
|
-
metadata={"target_system": "postgres", "role": "serving"},
|
|
212
|
-
)
|
|
213
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|