magic-pocket-cli 0.2.0__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.
- magic_pocket_cli-0.2.0.dist-info/METADATA +14 -0
- magic_pocket_cli-0.2.0.dist-info/RECORD +65 -0
- magic_pocket_cli-0.2.0.dist-info/WHEEL +4 -0
- magic_pocket_cli-0.2.0.dist-info/entry_points.txt +2 -0
- pocket_cli/__init__.py +0 -0
- pocket_cli/cli/__init__.py +0 -0
- pocket_cli/cli/aws_auth.py +48 -0
- pocket_cli/cli/awscontainer_cli.py +328 -0
- pocket_cli/cli/cloudfront_cli.py +116 -0
- pocket_cli/cli/cloudfront_keys_cli.py +68 -0
- pocket_cli/cli/cloudfront_waf_cli.py +68 -0
- pocket_cli/cli/deploy_cli.py +274 -0
- pocket_cli/cli/destroy_cli.py +358 -0
- pocket_cli/cli/dsql_cli.py +60 -0
- pocket_cli/cli/main_cli.py +91 -0
- pocket_cli/cli/migrate_cli.py +148 -0
- pocket_cli/cli/neon_cli.py +97 -0
- pocket_cli/cli/permissions_cli.py +46 -0
- pocket_cli/cli/rds_cli.py +63 -0
- pocket_cli/cli/runtime_config_cli.py +185 -0
- pocket_cli/cli/s3_cli.py +69 -0
- pocket_cli/cli/status_cli.py +56 -0
- pocket_cli/cli/tidb_cli.py +73 -0
- pocket_cli/cli/vpc_cli.py +92 -0
- pocket_cli/cli/waf_cli.py +182 -0
- pocket_cli/django_cli.py +412 -0
- pocket_cli/mediator.py +220 -0
- pocket_cli/resources/__init__.py +0 -0
- pocket_cli/resources/aws/__init__.py +0 -0
- pocket_cli/resources/aws/builders/__init__.py +57 -0
- pocket_cli/resources/aws/builders/codebuild.py +363 -0
- pocket_cli/resources/aws/builders/depot.py +84 -0
- pocket_cli/resources/aws/builders/docker.py +34 -0
- pocket_cli/resources/aws/builders/dockerignore.py +44 -0
- pocket_cli/resources/aws/cloudformation.py +790 -0
- pocket_cli/resources/aws/ecr.py +145 -0
- pocket_cli/resources/aws/efs.py +138 -0
- pocket_cli/resources/aws/lambdahandler.py +182 -0
- pocket_cli/resources/aws/s3_utils.py +58 -0
- pocket_cli/resources/aws/state.py +74 -0
- pocket_cli/resources/awscontainer.py +265 -0
- pocket_cli/resources/cloudfront.py +491 -0
- pocket_cli/resources/cloudfront_acm.py +55 -0
- pocket_cli/resources/cloudfront_keys.py +81 -0
- pocket_cli/resources/cloudfront_waf.py +67 -0
- pocket_cli/resources/dsql.py +142 -0
- pocket_cli/resources/neon.py +353 -0
- pocket_cli/resources/rds.py +680 -0
- pocket_cli/resources/s3.py +307 -0
- pocket_cli/resources/tidb.py +298 -0
- pocket_cli/resources/upstash.py +152 -0
- pocket_cli/resources/vpc.py +67 -0
- pocket_cli/templates/cloudformation/awscontainer.yaml +516 -0
- pocket_cli/templates/cloudformation/cf_function_api_host.js +5 -0
- pocket_cli/templates/cloudformation/cf_function_spa_auth.js +28 -0
- pocket_cli/templates/cloudformation/cf_function_spa_fallback.js +8 -0
- pocket_cli/templates/cloudformation/cloudfront.yaml +309 -0
- pocket_cli/templates/cloudformation/cloudfront_acm.yaml +43 -0
- pocket_cli/templates/cloudformation/cloudfront_keys.yaml +32 -0
- pocket_cli/templates/cloudformation/cloudfront_waf.yaml +97 -0
- pocket_cli/templates/cloudformation/vpc.yaml +213 -0
- pocket_cli/templates/init/django-dotenv.env +3 -0
- pocket_cli/templates/init/django-settings.py +140 -0
- pocket_cli/templates/init/pocket.Dockerfile +26 -0
- pocket_cli/templates/init/pocket_simple.toml +31 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from functools import cached_property
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from pocket.resources.base import ResourceStatus
|
|
10
|
+
from pocket.utils import echo
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from pocket.context import UpstashContext
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class UpstashResourceIsNotReady(Exception):
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class UpstashDatabase(BaseModel):
|
|
21
|
+
database_id: str
|
|
22
|
+
database_name: str
|
|
23
|
+
endpoint: str
|
|
24
|
+
port: int
|
|
25
|
+
password: str
|
|
26
|
+
tls: bool
|
|
27
|
+
state: str
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class UpstashApi:
|
|
31
|
+
base_url = "https://api.upstash.com/v2/redis"
|
|
32
|
+
|
|
33
|
+
def __init__(self, email: str, api_key: str) -> None:
|
|
34
|
+
self.auth = (email, api_key)
|
|
35
|
+
|
|
36
|
+
def get(self, path: str) -> requests.Response:
|
|
37
|
+
res = requests.get(f"{self.base_url}/{path}", auth=self.auth)
|
|
38
|
+
if 200 <= res.status_code < 300:
|
|
39
|
+
return res
|
|
40
|
+
raise RuntimeError("Upstash API error: %s %s" % (res.status_code, res.text))
|
|
41
|
+
|
|
42
|
+
def post(self, path: str, data: dict) -> requests.Response:
|
|
43
|
+
res = requests.post(f"{self.base_url}/{path}", auth=self.auth, json=data)
|
|
44
|
+
if 200 <= res.status_code < 300:
|
|
45
|
+
return res
|
|
46
|
+
raise RuntimeError("Upstash API error: %s %s" % (res.status_code, res.text))
|
|
47
|
+
|
|
48
|
+
def delete(self, path: str) -> requests.Response:
|
|
49
|
+
res = requests.delete(f"{self.base_url}/{path}", auth=self.auth)
|
|
50
|
+
if 200 <= res.status_code < 300:
|
|
51
|
+
return res
|
|
52
|
+
raise RuntimeError("Upstash API error: %s %s" % (res.status_code, res.text))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class Upstash:
|
|
56
|
+
context: UpstashContext
|
|
57
|
+
|
|
58
|
+
def __init__(self, context: UpstashContext) -> None:
|
|
59
|
+
self.context = context
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def api(self) -> UpstashApi:
|
|
63
|
+
if not self.context.email or not self.context.api_key:
|
|
64
|
+
raise UpstashResourceIsNotReady(
|
|
65
|
+
"UPSTASH_EMAIL と UPSTASH_API_KEY を設定してください"
|
|
66
|
+
)
|
|
67
|
+
return UpstashApi(self.context.email, self.context.api_key)
|
|
68
|
+
|
|
69
|
+
@cached_property
|
|
70
|
+
def database(self) -> UpstashDatabase | None:
|
|
71
|
+
res = self.api.get("databases")
|
|
72
|
+
for db in res.json():
|
|
73
|
+
if db["database_name"] == self.context.database_name:
|
|
74
|
+
return UpstashDatabase(
|
|
75
|
+
**{k: db[k] for k in UpstashDatabase.model_fields if k in db}
|
|
76
|
+
)
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def redis_url(self) -> str:
|
|
81
|
+
if self.database is None:
|
|
82
|
+
raise UpstashResourceIsNotReady("データベースが見つかりません")
|
|
83
|
+
if self.database.state != "active":
|
|
84
|
+
raise UpstashResourceIsNotReady(
|
|
85
|
+
"データベースが active ではありません: %s" % self.database.state
|
|
86
|
+
)
|
|
87
|
+
protocol = "rediss" if self.database.tls else "redis"
|
|
88
|
+
return "%s://default:%s@%s:%d" % (
|
|
89
|
+
protocol,
|
|
90
|
+
self.database.password,
|
|
91
|
+
self.database.endpoint,
|
|
92
|
+
self.database.port,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def status(self) -> ResourceStatus:
|
|
97
|
+
if self.context.skip_check_existing:
|
|
98
|
+
# 存在確認の Upstash API call を skip し COMPLETED 固定 (settings 参照)。
|
|
99
|
+
return "COMPLETED"
|
|
100
|
+
if self.database and self.database.state == "active":
|
|
101
|
+
return "COMPLETED"
|
|
102
|
+
return "NOEXIST"
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def description(self):
|
|
106
|
+
return "Create Upstash Redis database: %s" % self.context.database_name
|
|
107
|
+
|
|
108
|
+
def state_info(self):
|
|
109
|
+
return {
|
|
110
|
+
"upstash": {
|
|
111
|
+
"database_name": self.context.database_name,
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
def deploy_init(self):
|
|
116
|
+
pass
|
|
117
|
+
|
|
118
|
+
def create(self):
|
|
119
|
+
if self.database is not None:
|
|
120
|
+
echo.info(
|
|
121
|
+
"Upstash データベース '%s' は既に存在します"
|
|
122
|
+
% self.context.database_name
|
|
123
|
+
)
|
|
124
|
+
return
|
|
125
|
+
echo.log("Upstash データベースを作成します: %s" % self.context.database_name)
|
|
126
|
+
self.api.post(
|
|
127
|
+
"database",
|
|
128
|
+
{
|
|
129
|
+
"database_name": self.context.database_name,
|
|
130
|
+
"platform": "aws",
|
|
131
|
+
"primary_region": "ap-southeast-1",
|
|
132
|
+
"plan": "payg",
|
|
133
|
+
"budget": self.context.budget,
|
|
134
|
+
"tls": True,
|
|
135
|
+
"eviction": True,
|
|
136
|
+
},
|
|
137
|
+
)
|
|
138
|
+
if hasattr(self, "database"):
|
|
139
|
+
del self.database
|
|
140
|
+
echo.success(
|
|
141
|
+
"Upstash データベースを作成しました: %s" % self.context.database_name
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def delete_database(self):
|
|
145
|
+
if self.database is None:
|
|
146
|
+
echo.warning("Upstash データベースが見つかりません")
|
|
147
|
+
return
|
|
148
|
+
echo.log("Upstash データベースを削除します: %s" % self.context.database_name)
|
|
149
|
+
self.api.delete("database/%s" % self.database.database_id)
|
|
150
|
+
if hasattr(self, "database"):
|
|
151
|
+
del self.database
|
|
152
|
+
echo.success("Upstash データベースを削除しました")
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from pocket.resources.base import ResourceStatus
|
|
6
|
+
from pocket_cli.resources.aws.cloudformation import VpcStack
|
|
7
|
+
from pocket_cli.resources.aws.efs import Efs
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from pocket.general_context import VpcContext
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Vpc:
|
|
14
|
+
context: VpcContext
|
|
15
|
+
|
|
16
|
+
def __init__(self, context: VpcContext):
|
|
17
|
+
self.context = context
|
|
18
|
+
self.main_context = context
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def stack(self):
|
|
22
|
+
return VpcStack(self.context)
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def efs(self):
|
|
26
|
+
if self.context.efs:
|
|
27
|
+
return Efs(self.context.efs)
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def status(self) -> ResourceStatus:
|
|
31
|
+
return self.stack.status
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def vpc_id(self):
|
|
35
|
+
if self.stack.output:
|
|
36
|
+
return self.stack.output[self.stack.export["vpc_id"]]
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def description(self):
|
|
40
|
+
description = "Create aws cloudformation stack: %s" % self.stack.name
|
|
41
|
+
if self.efs:
|
|
42
|
+
description += "\nCreate efs: %s" % self.efs.context.name
|
|
43
|
+
return description
|
|
44
|
+
|
|
45
|
+
def state_info(self):
|
|
46
|
+
if self.context.efs:
|
|
47
|
+
return {"efs": {"name": self.context.efs.name}}
|
|
48
|
+
return {}
|
|
49
|
+
|
|
50
|
+
def deploy_init(self):
|
|
51
|
+
if self.efs:
|
|
52
|
+
self.efs.ensure_exists()
|
|
53
|
+
|
|
54
|
+
def create(self):
|
|
55
|
+
print("Creating cloudformation stack for vpc ...")
|
|
56
|
+
self.stack.create()
|
|
57
|
+
|
|
58
|
+
def delete(self):
|
|
59
|
+
if self.stack.status != "NOEXIST":
|
|
60
|
+
self.stack.delete()
|
|
61
|
+
self.stack.wait_status("NOEXIST", timeout=300, interval=10)
|
|
62
|
+
if self.efs and self.efs.exists():
|
|
63
|
+
self.efs.delete()
|
|
64
|
+
|
|
65
|
+
def update(self):
|
|
66
|
+
if not self.stack.yaml_synced:
|
|
67
|
+
self.stack.update()
|