airbyte-internal-ops 0.1.5__py3-none-any.whl → 0.1.6__py3-none-any.whl
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.
- {airbyte_internal_ops-0.1.5.dist-info → airbyte_internal_ops-0.1.6.dist-info}/METADATA +70 -1
- {airbyte_internal_ops-0.1.5.dist-info → airbyte_internal_ops-0.1.6.dist-info}/RECORD +25 -26
- airbyte_ops_mcp/__init__.py +30 -2
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_pipelines/airbyte_ci/connectors/pipeline.py +2 -8
- airbyte_ops_mcp/airbyte_repo/list_connectors.py +132 -0
- airbyte_ops_mcp/cli/registry.py +90 -1
- airbyte_ops_mcp/connection_config_retriever/__init__.py +26 -0
- airbyte_ops_mcp/{live_tests/_connection_retriever → connection_config_retriever}/audit_logging.py +5 -6
- airbyte_ops_mcp/{live_tests/_connection_retriever → connection_config_retriever}/retrieval.py +8 -22
- airbyte_ops_mcp/{live_tests/_connection_retriever → connection_config_retriever}/secrets_resolution.py +8 -42
- airbyte_ops_mcp/constants.py +35 -0
- airbyte_ops_mcp/live_tests/connection_secret_retriever.py +1 -1
- airbyte_ops_mcp/mcp/github_repo_ops.py +10 -0
- airbyte_ops_mcp/mcp/prod_db_queries.py +357 -0
- airbyte_ops_mcp/mcp/server.py +2 -0
- airbyte_ops_mcp/prod_db_access/__init__.py +34 -0
- airbyte_ops_mcp/prod_db_access/db_engine.py +127 -0
- airbyte_ops_mcp/prod_db_access/py.typed +0 -0
- airbyte_ops_mcp/prod_db_access/queries.py +272 -0
- airbyte_ops_mcp/prod_db_access/sql.py +353 -0
- airbyte_ops_mcp/registry/__init__.py +34 -0
- airbyte_ops_mcp/registry/models.py +63 -0
- airbyte_ops_mcp/registry/publish.py +368 -0
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_pipelines/airbyte_ci/connectors/publish/__init__.py +0 -3
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_pipelines/airbyte_ci/connectors/publish/commands.py +0 -242
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_pipelines/airbyte_ci/connectors/publish/context.py +0 -175
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_pipelines/airbyte_ci/connectors/publish/pipeline.py +0 -1056
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_pipelines/airbyte_ci/poetry/publish/__init__.py +0 -3
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_pipelines/airbyte_ci/poetry/publish/commands.py +0 -127
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_pipelines/airbyte_ci/steps/python_registry.py +0 -238
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_pipelines/models/contexts/python_registry_publish.py +0 -119
- airbyte_ops_mcp/live_tests/_connection_retriever/__init__.py +0 -35
- airbyte_ops_mcp/live_tests/_connection_retriever/consts.py +0 -33
- airbyte_ops_mcp/live_tests/_connection_retriever/db_access.py +0 -82
- {airbyte_internal_ops-0.1.5.dist-info → airbyte_internal_ops-0.1.6.dist-info}/WHEEL +0 -0
- {airbyte_internal_ops-0.1.5.dist-info → airbyte_internal_ops-0.1.6.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
|
|
2
|
+
"""Database engine and connection management for Airbyte Cloud Prod DB Replica.
|
|
3
|
+
|
|
4
|
+
This module provides connection pooling and engine management for querying
|
|
5
|
+
the Airbyte Cloud production database replica.
|
|
6
|
+
|
|
7
|
+
For SQL query templates and schema documentation, see sql.py.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import traceback
|
|
15
|
+
from typing import Any, Callable
|
|
16
|
+
|
|
17
|
+
import sqlalchemy
|
|
18
|
+
from google.cloud import secretmanager
|
|
19
|
+
from google.cloud.sql.connector import Connector
|
|
20
|
+
from google.cloud.sql.connector.enums import IPTypes
|
|
21
|
+
|
|
22
|
+
# Secret ID for database connection details
|
|
23
|
+
CONNECTION_RETRIEVER_PG_CONNECTION_DETAILS_SECRET_ID = (
|
|
24
|
+
"projects/587336813068/secrets/CONNECTION_RETRIEVER_PG_CONNECTION_DETAILS"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
PG_DRIVER = "pg8000"
|
|
28
|
+
|
|
29
|
+
# Lazy-initialized to avoid import-time GCP auth
|
|
30
|
+
_connector: Connector | None = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _get_connector() -> Connector:
|
|
34
|
+
"""Get the Cloud SQL connector, initializing lazily on first use."""
|
|
35
|
+
global _connector
|
|
36
|
+
if _connector is None:
|
|
37
|
+
_connector = Connector()
|
|
38
|
+
return _connector
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _get_secret_value(
|
|
42
|
+
gsm_client: secretmanager.SecretManagerServiceClient, secret_id: str
|
|
43
|
+
) -> str:
|
|
44
|
+
"""Get the value of the enabled version of a secret.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
gsm_client: GCP Secret Manager client
|
|
48
|
+
secret_id: The id of the secret
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
The value of the enabled version of the secret
|
|
52
|
+
"""
|
|
53
|
+
response = gsm_client.list_secret_versions(
|
|
54
|
+
request={"parent": secret_id, "filter": "state:ENABLED"}
|
|
55
|
+
)
|
|
56
|
+
if len(response.versions) == 0:
|
|
57
|
+
raise ValueError(f"No enabled version of secret {secret_id} found")
|
|
58
|
+
enabled_version = response.versions[0]
|
|
59
|
+
response = gsm_client.access_secret_version(name=enabled_version.name)
|
|
60
|
+
return response.payload.data.decode("UTF-8")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_database_creator(pg_connection_details: dict) -> Callable:
|
|
64
|
+
"""Create a database connection creator function."""
|
|
65
|
+
|
|
66
|
+
def creator() -> Any:
|
|
67
|
+
return _get_connector().connect(
|
|
68
|
+
pg_connection_details["database_address"],
|
|
69
|
+
PG_DRIVER,
|
|
70
|
+
user=pg_connection_details["pg_user"],
|
|
71
|
+
password=pg_connection_details["pg_password"],
|
|
72
|
+
db=pg_connection_details["database_name"],
|
|
73
|
+
ip_type=IPTypes.PRIVATE,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
return creator
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_pool(
|
|
80
|
+
gsm_client: secretmanager.SecretManagerServiceClient,
|
|
81
|
+
) -> sqlalchemy.Engine:
|
|
82
|
+
"""Get a SQLAlchemy connection pool for the Airbyte Cloud database.
|
|
83
|
+
|
|
84
|
+
This function supports two connection modes:
|
|
85
|
+
1. Direct connection via Cloud SQL Python Connector (default, requires VPC access)
|
|
86
|
+
2. Connection via Cloud SQL Auth Proxy (when CI or USE_CLOUD_SQL_PROXY env var is set)
|
|
87
|
+
|
|
88
|
+
For proxy mode, start the proxy with:
|
|
89
|
+
cloud-sql-proxy prod-ab-cloud-proj:us-west3:prod-pgsql-replica --port=<port>
|
|
90
|
+
|
|
91
|
+
Environment variables:
|
|
92
|
+
CI: If set, uses proxy connection mode
|
|
93
|
+
USE_CLOUD_SQL_PROXY: If set, uses proxy connection mode
|
|
94
|
+
DB_PORT: Port for proxy connection (default: 5432)
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
gsm_client: GCP Secret Manager client for retrieving credentials
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
SQLAlchemy Engine connected to the Prod DB Replica
|
|
101
|
+
"""
|
|
102
|
+
pg_connection_details = json.loads(
|
|
103
|
+
_get_secret_value(
|
|
104
|
+
gsm_client, CONNECTION_RETRIEVER_PG_CONNECTION_DETAILS_SECRET_ID
|
|
105
|
+
)
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if os.getenv("CI") or os.getenv("USE_CLOUD_SQL_PROXY"):
|
|
109
|
+
# Connect via Cloud SQL Auth Proxy, running on localhost
|
|
110
|
+
# Port can be configured via DB_PORT env var (default: 5432)
|
|
111
|
+
host = "127.0.0.1"
|
|
112
|
+
port = os.getenv("DB_PORT", "5432")
|
|
113
|
+
try:
|
|
114
|
+
return sqlalchemy.create_engine(
|
|
115
|
+
f"postgresql+{PG_DRIVER}://{pg_connection_details['pg_user']}:{pg_connection_details['pg_password']}@{host}:{port}/{pg_connection_details['database_name']}",
|
|
116
|
+
)
|
|
117
|
+
except Exception as e:
|
|
118
|
+
raise AssertionError(
|
|
119
|
+
f"sqlalchemy.create_engine exception; could not connect to the proxy at {host}:{port}. "
|
|
120
|
+
f"Error: {traceback.format_exception(e)}"
|
|
121
|
+
) from e
|
|
122
|
+
|
|
123
|
+
# Default: Connect via Cloud SQL Python Connector (requires VPC access)
|
|
124
|
+
return sqlalchemy.create_engine(
|
|
125
|
+
f"postgresql+{PG_DRIVER}://",
|
|
126
|
+
creator=get_database_creator(pg_connection_details),
|
|
127
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
|
|
2
|
+
"""Query execution functions for Airbyte Cloud Prod DB Replica.
|
|
3
|
+
|
|
4
|
+
This module provides functions that execute SQL queries against the Prod DB Replica
|
|
5
|
+
and return structured results. Each function wraps a SQL template from sql.py.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from collections.abc import Mapping
|
|
12
|
+
from datetime import datetime, timedelta, timezone
|
|
13
|
+
from time import perf_counter
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import sqlalchemy
|
|
17
|
+
from google.cloud import secretmanager
|
|
18
|
+
|
|
19
|
+
from airbyte_ops_mcp.prod_db_access.db_engine import get_pool
|
|
20
|
+
from airbyte_ops_mcp.prod_db_access.sql import (
|
|
21
|
+
SELECT_ACTORS_PINNED_TO_VERSION,
|
|
22
|
+
SELECT_CONNECTIONS_BY_CONNECTOR,
|
|
23
|
+
SELECT_CONNECTOR_VERSIONS,
|
|
24
|
+
SELECT_DATAPLANES_LIST,
|
|
25
|
+
SELECT_NEW_CONNECTOR_RELEASES,
|
|
26
|
+
SELECT_ORG_WORKSPACES,
|
|
27
|
+
SELECT_SUCCESSFUL_SYNCS_FOR_VERSION,
|
|
28
|
+
SELECT_SYNC_RESULTS_FOR_VERSION,
|
|
29
|
+
SELECT_WORKSPACE_INFO,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _run_sql_query(
|
|
36
|
+
statement: sqlalchemy.sql.elements.TextClause,
|
|
37
|
+
parameters: Mapping[str, Any] | None = None,
|
|
38
|
+
*,
|
|
39
|
+
query_name: str | None = None,
|
|
40
|
+
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
41
|
+
) -> list[dict[str, Any]]:
|
|
42
|
+
"""Execute a SQL text statement and return rows as list[dict], logging elapsed time.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
statement: SQLAlchemy text clause to execute
|
|
46
|
+
parameters: Query parameters to bind
|
|
47
|
+
query_name: Optional name for logging (defaults to first line of SQL)
|
|
48
|
+
gsm_client: GCP Secret Manager client for retrieving credentials.
|
|
49
|
+
If None, a new client will be instantiated.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
List of row dicts from the query result
|
|
53
|
+
"""
|
|
54
|
+
if gsm_client is None:
|
|
55
|
+
gsm_client = secretmanager.SecretManagerServiceClient()
|
|
56
|
+
pool = get_pool(gsm_client)
|
|
57
|
+
start = perf_counter()
|
|
58
|
+
with pool.connect() as conn:
|
|
59
|
+
result = conn.execute(statement, parameters or {})
|
|
60
|
+
rows = [dict(row._mapping) for row in result]
|
|
61
|
+
elapsed = perf_counter() - start
|
|
62
|
+
|
|
63
|
+
name = query_name or "SQL query"
|
|
64
|
+
logger.info("Prod DB query %s returned %d rows in %.3f s", name, len(rows), elapsed)
|
|
65
|
+
|
|
66
|
+
return rows
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def query_connections_by_connector(
|
|
70
|
+
connector_definition_id: str,
|
|
71
|
+
organization_id: str | None = None,
|
|
72
|
+
limit: int = 1000,
|
|
73
|
+
*,
|
|
74
|
+
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
75
|
+
) -> list[dict[str, Any]]:
|
|
76
|
+
"""Query connections by source connector type, optionally filtered by organization.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
connector_definition_id: Connector definition UUID to filter by
|
|
80
|
+
organization_id: Optional organization UUID to search within
|
|
81
|
+
limit: Maximum number of results (default: 1000)
|
|
82
|
+
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
List of connection records with workspace and dataplane info
|
|
86
|
+
"""
|
|
87
|
+
return _run_sql_query(
|
|
88
|
+
SELECT_CONNECTIONS_BY_CONNECTOR,
|
|
89
|
+
parameters={
|
|
90
|
+
"connector_definition_id": connector_definition_id,
|
|
91
|
+
"organization_id": organization_id,
|
|
92
|
+
"limit": limit,
|
|
93
|
+
},
|
|
94
|
+
query_name="SELECT_CONNECTIONS_BY_CONNECTOR",
|
|
95
|
+
gsm_client=gsm_client,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def query_connector_versions(
|
|
100
|
+
connector_definition_id: str,
|
|
101
|
+
*,
|
|
102
|
+
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
103
|
+
) -> list[dict[str, Any]]:
|
|
104
|
+
"""Query all versions for a connector definition.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
connector_definition_id: Connector definition UUID
|
|
108
|
+
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
List of version records ordered by last_published DESC
|
|
112
|
+
"""
|
|
113
|
+
return _run_sql_query(
|
|
114
|
+
SELECT_CONNECTOR_VERSIONS,
|
|
115
|
+
parameters={"actor_definition_id": connector_definition_id},
|
|
116
|
+
query_name="SELECT_CONNECTOR_VERSIONS",
|
|
117
|
+
gsm_client=gsm_client,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def query_new_connector_releases(
|
|
122
|
+
days: int = 7,
|
|
123
|
+
limit: int = 100,
|
|
124
|
+
*,
|
|
125
|
+
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
126
|
+
) -> list[dict[str, Any]]:
|
|
127
|
+
"""Query recently published connector versions.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
days: Number of days to look back (default: 7)
|
|
131
|
+
limit: Maximum number of results (default: 100)
|
|
132
|
+
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
List of recently published connector versions
|
|
136
|
+
"""
|
|
137
|
+
cutoff_date = datetime.now(timezone.utc) - timedelta(days=days)
|
|
138
|
+
return _run_sql_query(
|
|
139
|
+
SELECT_NEW_CONNECTOR_RELEASES,
|
|
140
|
+
parameters={"cutoff_date": cutoff_date, "limit": limit},
|
|
141
|
+
query_name="SELECT_NEW_CONNECTOR_RELEASES",
|
|
142
|
+
gsm_client=gsm_client,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def query_actors_pinned_to_version(
|
|
147
|
+
connector_version_id: str,
|
|
148
|
+
*,
|
|
149
|
+
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
150
|
+
) -> list[dict[str, Any]]:
|
|
151
|
+
"""Query actors (sources/destinations) pinned to a specific connector version.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
connector_version_id: Connector version UUID to search for
|
|
155
|
+
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
List of actors pinned to the specified version
|
|
159
|
+
"""
|
|
160
|
+
return _run_sql_query(
|
|
161
|
+
SELECT_ACTORS_PINNED_TO_VERSION,
|
|
162
|
+
parameters={"actor_definition_version_id": connector_version_id},
|
|
163
|
+
query_name="SELECT_ACTORS_PINNED_TO_VERSION",
|
|
164
|
+
gsm_client=gsm_client,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def query_sync_results_for_version(
|
|
169
|
+
connector_version_id: str,
|
|
170
|
+
days: int = 7,
|
|
171
|
+
limit: int = 100,
|
|
172
|
+
successful_only: bool = False,
|
|
173
|
+
*,
|
|
174
|
+
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
175
|
+
) -> list[dict[str, Any]]:
|
|
176
|
+
"""Query sync job results for actors pinned to a specific connector version.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
connector_version_id: Connector version UUID to filter by
|
|
180
|
+
days: Number of days to look back (default: 7)
|
|
181
|
+
limit: Maximum number of results (default: 100)
|
|
182
|
+
successful_only: If True, only return successful syncs (default: False)
|
|
183
|
+
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
List of sync job results
|
|
187
|
+
"""
|
|
188
|
+
cutoff_date = datetime.now(timezone.utc) - timedelta(days=days)
|
|
189
|
+
query = (
|
|
190
|
+
SELECT_SUCCESSFUL_SYNCS_FOR_VERSION
|
|
191
|
+
if successful_only
|
|
192
|
+
else SELECT_SYNC_RESULTS_FOR_VERSION
|
|
193
|
+
)
|
|
194
|
+
query_name = (
|
|
195
|
+
"SELECT_SUCCESSFUL_SYNCS_FOR_VERSION"
|
|
196
|
+
if successful_only
|
|
197
|
+
else "SELECT_SYNC_RESULTS_FOR_VERSION"
|
|
198
|
+
)
|
|
199
|
+
return _run_sql_query(
|
|
200
|
+
query,
|
|
201
|
+
parameters={
|
|
202
|
+
"actor_definition_version_id": connector_version_id,
|
|
203
|
+
"cutoff_date": cutoff_date,
|
|
204
|
+
"limit": limit,
|
|
205
|
+
},
|
|
206
|
+
query_name=query_name,
|
|
207
|
+
gsm_client=gsm_client,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def query_dataplanes_list(
|
|
212
|
+
*,
|
|
213
|
+
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
214
|
+
) -> list[dict[str, Any]]:
|
|
215
|
+
"""Query all dataplane groups with workspace counts.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
List of dataplane groups ordered by workspace count DESC
|
|
222
|
+
"""
|
|
223
|
+
return _run_sql_query(
|
|
224
|
+
SELECT_DATAPLANES_LIST,
|
|
225
|
+
query_name="SELECT_DATAPLANES_LIST",
|
|
226
|
+
gsm_client=gsm_client,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def query_workspace_info(
|
|
231
|
+
workspace_id: str,
|
|
232
|
+
*,
|
|
233
|
+
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
234
|
+
) -> dict[str, Any] | None:
|
|
235
|
+
"""Query workspace info including dataplane group.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
workspace_id: Workspace UUID
|
|
239
|
+
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Workspace info dict, or None if not found
|
|
243
|
+
"""
|
|
244
|
+
rows = _run_sql_query(
|
|
245
|
+
SELECT_WORKSPACE_INFO,
|
|
246
|
+
parameters={"workspace_id": workspace_id},
|
|
247
|
+
query_name="SELECT_WORKSPACE_INFO",
|
|
248
|
+
gsm_client=gsm_client,
|
|
249
|
+
)
|
|
250
|
+
return rows[0] if rows else None
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def query_org_workspaces(
|
|
254
|
+
organization_id: str,
|
|
255
|
+
*,
|
|
256
|
+
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
257
|
+
) -> list[dict[str, Any]]:
|
|
258
|
+
"""Query all workspaces in an organization with dataplane info.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
organization_id: Organization UUID
|
|
262
|
+
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
List of workspaces in the organization
|
|
266
|
+
"""
|
|
267
|
+
return _run_sql_query(
|
|
268
|
+
SELECT_ORG_WORKSPACES,
|
|
269
|
+
parameters={"organization_id": organization_id},
|
|
270
|
+
query_name="SELECT_ORG_WORKSPACES",
|
|
271
|
+
gsm_client=gsm_client,
|
|
272
|
+
)
|