pragmatiks-gcp-provider 0.84.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.
- pragmatiks_gcp_provider-0.84.0/PKG-INFO +100 -0
- pragmatiks_gcp_provider-0.84.0/README.md +85 -0
- pragmatiks_gcp_provider-0.84.0/pyproject.toml +55 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/__init__.py +53 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/py.typed +0 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/resources/__init__.py +45 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/resources/cloudsql/__init__.py +32 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/resources/cloudsql/database.py +155 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/resources/cloudsql/database_instance.py +464 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/resources/cloudsql/helpers.py +98 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/resources/cloudsql/user.py +176 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/resources/gke.py +454 -0
- pragmatiks_gcp_provider-0.84.0/src/gcp_provider/resources/secret.py +169 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: pragmatiks-gcp-provider
|
|
3
|
+
Version: 0.84.0
|
|
4
|
+
Summary: GCP provider for Pragmatiks
|
|
5
|
+
Author: Pragmatiks
|
|
6
|
+
Author-email: Pragmatiks <team@pragmatiks.io>
|
|
7
|
+
Requires-Dist: pragmatiks-sdk>=0.17.1
|
|
8
|
+
Requires-Dist: google-cloud-container>=2.50.0
|
|
9
|
+
Requires-Dist: google-cloud-logging>=3.10.0
|
|
10
|
+
Requires-Dist: google-cloud-secret-manager>=2.20.0
|
|
11
|
+
Requires-Dist: google-api-python-client>=2.150.0
|
|
12
|
+
Requires-Dist: google-auth>=2.35.0
|
|
13
|
+
Requires-Python: >=3.13
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# GCP Provider
|
|
17
|
+
|
|
18
|
+
GCP provider for Pragmatiks - manage Google Cloud resources declaratively.
|
|
19
|
+
|
|
20
|
+
## Available Resources
|
|
21
|
+
|
|
22
|
+
### Secret (gcp/secret)
|
|
23
|
+
|
|
24
|
+
Manages secrets in GCP Secret Manager using user-provided service account credentials.
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from gcp_provider import Secret, SecretConfig
|
|
28
|
+
|
|
29
|
+
# Define a secret
|
|
30
|
+
secret = Secret(
|
|
31
|
+
name="my-api-key",
|
|
32
|
+
config=SecretConfig(
|
|
33
|
+
project_id="my-gcp-project",
|
|
34
|
+
secret_id="api-key",
|
|
35
|
+
data="super-secret-value",
|
|
36
|
+
credentials={"type": "service_account", ...}, # or JSON string
|
|
37
|
+
),
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Config:**
|
|
42
|
+
- `project_id` - GCP project ID where the secret will be created
|
|
43
|
+
- `secret_id` - Identifier for the secret (must be unique per project)
|
|
44
|
+
- `data` - Secret payload data to store
|
|
45
|
+
- `credentials` - GCP service account credentials (JSON object or string)
|
|
46
|
+
|
|
47
|
+
**Outputs:**
|
|
48
|
+
- `resource_name` - Full GCP resource name (`projects/{project}/secrets/{id}`)
|
|
49
|
+
- `version_name` - Full version resource name including version number
|
|
50
|
+
- `version_id` - The version number as a string
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install pragmatiks-gcp-provider
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Development
|
|
59
|
+
|
|
60
|
+
### Testing
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Install dependencies
|
|
64
|
+
uv sync --dev
|
|
65
|
+
|
|
66
|
+
# Run tests
|
|
67
|
+
uv run pytest tests/
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Writing Tests
|
|
71
|
+
|
|
72
|
+
Use `ProviderHarness` to test lifecycle methods:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from pragma_sdk.provider import ProviderHarness
|
|
76
|
+
from gcp_provider import Secret, SecretConfig
|
|
77
|
+
|
|
78
|
+
async def test_create_secret():
|
|
79
|
+
harness = ProviderHarness()
|
|
80
|
+
result = await harness.invoke_create(
|
|
81
|
+
Secret,
|
|
82
|
+
name="test-secret",
|
|
83
|
+
config=SecretConfig(
|
|
84
|
+
project_id="test-project",
|
|
85
|
+
secret_id="my-secret",
|
|
86
|
+
data="secret-value",
|
|
87
|
+
credentials=mock_credentials,
|
|
88
|
+
),
|
|
89
|
+
)
|
|
90
|
+
assert result.success
|
|
91
|
+
assert result.outputs.resource_name is not None
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Deployment
|
|
95
|
+
|
|
96
|
+
Push your provider to Pragmatiks platform:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pragma provider push
|
|
100
|
+
```
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# GCP Provider
|
|
2
|
+
|
|
3
|
+
GCP provider for Pragmatiks - manage Google Cloud resources declaratively.
|
|
4
|
+
|
|
5
|
+
## Available Resources
|
|
6
|
+
|
|
7
|
+
### Secret (gcp/secret)
|
|
8
|
+
|
|
9
|
+
Manages secrets in GCP Secret Manager using user-provided service account credentials.
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
from gcp_provider import Secret, SecretConfig
|
|
13
|
+
|
|
14
|
+
# Define a secret
|
|
15
|
+
secret = Secret(
|
|
16
|
+
name="my-api-key",
|
|
17
|
+
config=SecretConfig(
|
|
18
|
+
project_id="my-gcp-project",
|
|
19
|
+
secret_id="api-key",
|
|
20
|
+
data="super-secret-value",
|
|
21
|
+
credentials={"type": "service_account", ...}, # or JSON string
|
|
22
|
+
),
|
|
23
|
+
)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Config:**
|
|
27
|
+
- `project_id` - GCP project ID where the secret will be created
|
|
28
|
+
- `secret_id` - Identifier for the secret (must be unique per project)
|
|
29
|
+
- `data` - Secret payload data to store
|
|
30
|
+
- `credentials` - GCP service account credentials (JSON object or string)
|
|
31
|
+
|
|
32
|
+
**Outputs:**
|
|
33
|
+
- `resource_name` - Full GCP resource name (`projects/{project}/secrets/{id}`)
|
|
34
|
+
- `version_name` - Full version resource name including version number
|
|
35
|
+
- `version_id` - The version number as a string
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install pragmatiks-gcp-provider
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Development
|
|
44
|
+
|
|
45
|
+
### Testing
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Install dependencies
|
|
49
|
+
uv sync --dev
|
|
50
|
+
|
|
51
|
+
# Run tests
|
|
52
|
+
uv run pytest tests/
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Writing Tests
|
|
56
|
+
|
|
57
|
+
Use `ProviderHarness` to test lifecycle methods:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from pragma_sdk.provider import ProviderHarness
|
|
61
|
+
from gcp_provider import Secret, SecretConfig
|
|
62
|
+
|
|
63
|
+
async def test_create_secret():
|
|
64
|
+
harness = ProviderHarness()
|
|
65
|
+
result = await harness.invoke_create(
|
|
66
|
+
Secret,
|
|
67
|
+
name="test-secret",
|
|
68
|
+
config=SecretConfig(
|
|
69
|
+
project_id="test-project",
|
|
70
|
+
secret_id="my-secret",
|
|
71
|
+
data="secret-value",
|
|
72
|
+
credentials=mock_credentials,
|
|
73
|
+
),
|
|
74
|
+
)
|
|
75
|
+
assert result.success
|
|
76
|
+
assert result.outputs.resource_name is not None
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Deployment
|
|
80
|
+
|
|
81
|
+
Push your provider to Pragmatiks platform:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pragma provider push
|
|
85
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pragmatiks-gcp-provider"
|
|
3
|
+
version = "0.84.0"
|
|
4
|
+
description = "GCP provider for Pragmatiks"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"pragmatiks-sdk>=0.17.1",
|
|
9
|
+
"google-cloud-container>=2.50.0",
|
|
10
|
+
"google-cloud-logging>=3.10.0",
|
|
11
|
+
"google-cloud-secret-manager>=2.20.0",
|
|
12
|
+
"google-api-python-client>=2.150.0",
|
|
13
|
+
"google-auth>=2.35.0",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
authors = [
|
|
17
|
+
{ name = "Pragmatiks", email = "team@pragmatiks.io" },
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[dependency-groups]
|
|
21
|
+
dev = [
|
|
22
|
+
"pytest>=8.4.1",
|
|
23
|
+
"pytest-asyncio>=1.0.0",
|
|
24
|
+
"pytest-cov>=7.0.0",
|
|
25
|
+
"pytest-mock>=3.14.0",
|
|
26
|
+
"ty>=0.0.14",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[tool.pragma]
|
|
30
|
+
# Provider metadata - used by the platform for discovery and deployment
|
|
31
|
+
provider = "gcp"
|
|
32
|
+
package = "gcp_provider"
|
|
33
|
+
|
|
34
|
+
[tool.pytest.ini_options]
|
|
35
|
+
asyncio_mode = "auto"
|
|
36
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
37
|
+
|
|
38
|
+
[tool.commitizen]
|
|
39
|
+
name = "cz_conventional_commits"
|
|
40
|
+
version = "0.84.0"
|
|
41
|
+
version_files = ["pyproject.toml:^version"]
|
|
42
|
+
tag_format = "gcp-v$version"
|
|
43
|
+
update_changelog_on_bump = true
|
|
44
|
+
changelog_file = "CHANGELOG.md"
|
|
45
|
+
|
|
46
|
+
[tool.ruff]
|
|
47
|
+
extend = "../../pyproject.toml"
|
|
48
|
+
line-length = 120
|
|
49
|
+
|
|
50
|
+
[tool.uv.build-backend]
|
|
51
|
+
module-name = "gcp_provider"
|
|
52
|
+
|
|
53
|
+
[build-system]
|
|
54
|
+
requires = ["uv_build>=0.9.8,<0.10.0"]
|
|
55
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""GCP provider for Pragmatiks.
|
|
2
|
+
|
|
3
|
+
Provides GCP resources for managing infrastructure in Google Cloud Platform
|
|
4
|
+
using user-provided credentials (multi-tenant SaaS pattern).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pragma_sdk import Provider
|
|
8
|
+
|
|
9
|
+
from gcp_provider.resources import (
|
|
10
|
+
GKE,
|
|
11
|
+
Database,
|
|
12
|
+
DatabaseConfig,
|
|
13
|
+
DatabaseInstance,
|
|
14
|
+
DatabaseInstanceConfig,
|
|
15
|
+
DatabaseInstanceOutputs,
|
|
16
|
+
DatabaseOutputs,
|
|
17
|
+
GKEConfig,
|
|
18
|
+
GKEOutputs,
|
|
19
|
+
Secret,
|
|
20
|
+
SecretConfig,
|
|
21
|
+
SecretOutputs,
|
|
22
|
+
User,
|
|
23
|
+
UserConfig,
|
|
24
|
+
UserOutputs,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
gcp = Provider(name="gcp")
|
|
29
|
+
|
|
30
|
+
gcp.resource("cloudsql/database_instance")(DatabaseInstance)
|
|
31
|
+
gcp.resource("cloudsql/database")(Database)
|
|
32
|
+
gcp.resource("cloudsql/user")(User)
|
|
33
|
+
gcp.resource("gke")(GKE)
|
|
34
|
+
gcp.resource("secret")(Secret)
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"gcp",
|
|
38
|
+
"Database",
|
|
39
|
+
"DatabaseConfig",
|
|
40
|
+
"DatabaseInstance",
|
|
41
|
+
"DatabaseInstanceConfig",
|
|
42
|
+
"DatabaseInstanceOutputs",
|
|
43
|
+
"DatabaseOutputs",
|
|
44
|
+
"GKE",
|
|
45
|
+
"GKEConfig",
|
|
46
|
+
"GKEOutputs",
|
|
47
|
+
"Secret",
|
|
48
|
+
"SecretConfig",
|
|
49
|
+
"SecretOutputs",
|
|
50
|
+
"User",
|
|
51
|
+
"UserConfig",
|
|
52
|
+
"UserOutputs",
|
|
53
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Resource definitions for gcp provider.
|
|
2
|
+
|
|
3
|
+
Import and export your Resource classes here for discovery by the runtime.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from gcp_provider.resources.cloudsql import (
|
|
7
|
+
Database,
|
|
8
|
+
DatabaseConfig,
|
|
9
|
+
DatabaseInstance,
|
|
10
|
+
DatabaseInstanceConfig,
|
|
11
|
+
DatabaseInstanceOutputs,
|
|
12
|
+
DatabaseOutputs,
|
|
13
|
+
User,
|
|
14
|
+
UserConfig,
|
|
15
|
+
UserOutputs,
|
|
16
|
+
)
|
|
17
|
+
from gcp_provider.resources.gke import (
|
|
18
|
+
GKE,
|
|
19
|
+
GKEConfig,
|
|
20
|
+
GKEOutputs,
|
|
21
|
+
)
|
|
22
|
+
from gcp_provider.resources.secret import (
|
|
23
|
+
Secret,
|
|
24
|
+
SecretConfig,
|
|
25
|
+
SecretOutputs,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"Database",
|
|
31
|
+
"DatabaseConfig",
|
|
32
|
+
"DatabaseInstance",
|
|
33
|
+
"DatabaseInstanceConfig",
|
|
34
|
+
"DatabaseInstanceOutputs",
|
|
35
|
+
"DatabaseOutputs",
|
|
36
|
+
"GKE",
|
|
37
|
+
"GKEConfig",
|
|
38
|
+
"GKEOutputs",
|
|
39
|
+
"Secret",
|
|
40
|
+
"SecretConfig",
|
|
41
|
+
"SecretOutputs",
|
|
42
|
+
"User",
|
|
43
|
+
"UserConfig",
|
|
44
|
+
"UserOutputs",
|
|
45
|
+
]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""GCP Cloud SQL resources for database instances, databases, and users."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from gcp_provider.resources.cloudsql.database import (
|
|
6
|
+
Database,
|
|
7
|
+
DatabaseConfig,
|
|
8
|
+
DatabaseOutputs,
|
|
9
|
+
)
|
|
10
|
+
from gcp_provider.resources.cloudsql.database_instance import (
|
|
11
|
+
DatabaseInstance,
|
|
12
|
+
DatabaseInstanceConfig,
|
|
13
|
+
DatabaseInstanceOutputs,
|
|
14
|
+
)
|
|
15
|
+
from gcp_provider.resources.cloudsql.user import (
|
|
16
|
+
User,
|
|
17
|
+
UserConfig,
|
|
18
|
+
UserOutputs,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"Database",
|
|
24
|
+
"DatabaseConfig",
|
|
25
|
+
"DatabaseInstance",
|
|
26
|
+
"DatabaseInstanceConfig",
|
|
27
|
+
"DatabaseInstanceOutputs",
|
|
28
|
+
"DatabaseOutputs",
|
|
29
|
+
"User",
|
|
30
|
+
"UserConfig",
|
|
31
|
+
"UserOutputs",
|
|
32
|
+
]
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""GCP Cloud SQL database resource."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, ClassVar
|
|
6
|
+
|
|
7
|
+
from pragma_sdk import Config, Dependency, Outputs, Resource
|
|
8
|
+
from pydantic import Field
|
|
9
|
+
|
|
10
|
+
from gcp_provider.resources.cloudsql.database_instance import DatabaseInstance
|
|
11
|
+
from gcp_provider.resources.cloudsql.helpers import (
|
|
12
|
+
connection_info,
|
|
13
|
+
execute,
|
|
14
|
+
extract_ips,
|
|
15
|
+
get_credentials,
|
|
16
|
+
get_sqladmin_service,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class DatabaseConfig(Config):
|
|
21
|
+
"""Configuration for a Cloud SQL database.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
instance: The Cloud SQL instance that hosts this database.
|
|
25
|
+
database_name: Name of the database to create.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
instance: Dependency[DatabaseInstance]
|
|
29
|
+
database_name: str = Field(json_schema_extra={"immutable": True})
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class DatabaseOutputs(Outputs):
|
|
33
|
+
"""Outputs from Cloud SQL database creation.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
database_name: Name of the created database.
|
|
37
|
+
instance_name: Name of the hosting instance.
|
|
38
|
+
host: Database host (IP address or connection name).
|
|
39
|
+
port: Database port (5432 for postgres, 3306 for mysql).
|
|
40
|
+
url: Connection URL format (without credentials).
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
database_name: str
|
|
44
|
+
instance_name: str
|
|
45
|
+
host: str
|
|
46
|
+
port: int
|
|
47
|
+
url: str
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class Database(Resource[DatabaseConfig, DatabaseOutputs]):
|
|
51
|
+
"""GCP Cloud SQL database resource.
|
|
52
|
+
|
|
53
|
+
Creates and manages databases within a Cloud SQL instance.
|
|
54
|
+
Changing the instance triggers replacement (delete from old, create in new).
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
provider: ClassVar[str] = "gcp"
|
|
58
|
+
resource: ClassVar[str] = "cloudsql/database"
|
|
59
|
+
|
|
60
|
+
async def on_create(self) -> DatabaseOutputs:
|
|
61
|
+
"""Create database in the Cloud SQL instance.
|
|
62
|
+
|
|
63
|
+
Idempotent: If database already exists, returns its current state.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
DatabaseOutputs with database details.
|
|
67
|
+
"""
|
|
68
|
+
instance_resource = await self.config.instance.resolve()
|
|
69
|
+
inst = instance_resource.config
|
|
70
|
+
service = get_sqladmin_service(get_credentials(inst.credentials))
|
|
71
|
+
|
|
72
|
+
await execute(
|
|
73
|
+
service.databases().insert(
|
|
74
|
+
project=inst.project_id,
|
|
75
|
+
instance=inst.instance_name,
|
|
76
|
+
body={
|
|
77
|
+
"name": self.config.database_name,
|
|
78
|
+
"project": inst.project_id,
|
|
79
|
+
"instance": inst.instance_name,
|
|
80
|
+
},
|
|
81
|
+
),
|
|
82
|
+
ignore_exists=True,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return await self._build_outputs(inst, service)
|
|
86
|
+
|
|
87
|
+
async def on_update(self, previous_config: DatabaseConfig) -> DatabaseOutputs:
|
|
88
|
+
"""Handle database updates.
|
|
89
|
+
|
|
90
|
+
If instance changed, delete from old instance and create in new one.
|
|
91
|
+
database_name cannot be changed (truly immutable).
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
DatabaseOutputs with database details.
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
ValueError: If database_name changed (immutable field).
|
|
98
|
+
"""
|
|
99
|
+
if previous_config.database_name != self.config.database_name:
|
|
100
|
+
msg = "Cannot change database_name; delete and recreate resource"
|
|
101
|
+
raise ValueError(msg)
|
|
102
|
+
|
|
103
|
+
if previous_config.instance != self.config.instance:
|
|
104
|
+
await self._delete(previous_config)
|
|
105
|
+
return await self.on_create()
|
|
106
|
+
|
|
107
|
+
instance_resource = await self.config.instance.resolve()
|
|
108
|
+
inst = instance_resource.config
|
|
109
|
+
service = get_sqladmin_service(get_credentials(inst.credentials))
|
|
110
|
+
|
|
111
|
+
return await self._build_outputs(inst, service)
|
|
112
|
+
|
|
113
|
+
async def on_delete(self) -> None:
|
|
114
|
+
"""Delete database. Idempotent: succeeds if database doesn't exist."""
|
|
115
|
+
await self._delete(self.config)
|
|
116
|
+
|
|
117
|
+
async def _delete(self, config: DatabaseConfig) -> None:
|
|
118
|
+
"""Delete database from instance. Idempotent: succeeds if not found."""
|
|
119
|
+
instance_resource = await config.instance.resolve()
|
|
120
|
+
inst = instance_resource.config
|
|
121
|
+
service = get_sqladmin_service(get_credentials(inst.credentials))
|
|
122
|
+
|
|
123
|
+
await execute(
|
|
124
|
+
service.databases().delete(
|
|
125
|
+
project=inst.project_id,
|
|
126
|
+
instance=inst.instance_name,
|
|
127
|
+
database=config.database_name,
|
|
128
|
+
),
|
|
129
|
+
ignore_404=True,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
async def _build_outputs(self, inst: Any, service: Any) -> DatabaseOutputs:
|
|
133
|
+
"""Fetch instance info and build outputs.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
DatabaseOutputs with connection details.
|
|
137
|
+
"""
|
|
138
|
+
instance = await execute(
|
|
139
|
+
service.instances().get(
|
|
140
|
+
project=inst.project_id,
|
|
141
|
+
instance=inst.instance_name,
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
public_ip, private_ip = extract_ips(instance)
|
|
146
|
+
db_type, db_port = connection_info(instance.get("databaseVersion", "POSTGRES_15"))
|
|
147
|
+
host = public_ip or private_ip or f"{inst.project_id}:{instance.get('region')}:{inst.instance_name}"
|
|
148
|
+
|
|
149
|
+
return DatabaseOutputs(
|
|
150
|
+
database_name=self.config.database_name,
|
|
151
|
+
instance_name=inst.instance_name,
|
|
152
|
+
host=host,
|
|
153
|
+
port=int(db_port),
|
|
154
|
+
url=f"{db_type}://{host}:{db_port}/{self.config.database_name}",
|
|
155
|
+
)
|