magic-pocket-cli 0.8.0__tar.gz → 0.9.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.
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/PKG-INFO +2 -2
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/lambdahandler.py +18 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/rds.py +146 -59
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pyproject.toml +2 -2
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/.gitignore +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/__init__.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/__init__.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/aws_auth.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/awscontainer_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/cloudfront_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/cloudfront_keys_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/cloudfront_waf_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/deploy_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/destroy_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/dsql_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/main_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/migrate_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/neon_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/permissions_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/rds_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/runtime_config_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/s3_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/status_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/store_url_helper.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/tidb_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/upstash_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/vpc_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/cli/waf_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/django_cli.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/mediator.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/__init__.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/__init__.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/__init__.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/codebuild.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/depot.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/docker.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/dockerignore.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/cloudformation.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/ecr.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/efs.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/s3_utils.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/state.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/awscontainer.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/cloudfront.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/cloudfront_acm.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/cloudfront_keys.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/cloudfront_waf.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/dsql.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/neon.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/s3.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/tidb.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/upstash.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/vpc.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/awscontainer.yaml +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/cf_function_api_host.js +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/cf_function_spa_auth.js +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/cf_function_spa_fallback.js +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/cloudfront.yaml +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/cloudfront_acm.yaml +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/cloudfront_keys.yaml +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/cloudfront_waf.yaml +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/vpc.yaml +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/init/django-dotenv.env +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/init/django-settings.py +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/init/pocket.Dockerfile +0 -0
- {magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/init/pocket_simple.toml +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: magic-pocket-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: CLI and deploy tools for magic-pocket.
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Requires-Dist: awscrt>=0.19.0
|
|
7
7
|
Requires-Dist: click>=8.1.7
|
|
8
8
|
Requires-Dist: deepdiff>=6.7.1
|
|
9
9
|
Requires-Dist: jinja2>=3.1.3
|
|
10
|
-
Requires-Dist: magic-pocket>=0.
|
|
10
|
+
Requires-Dist: magic-pocket>=0.9.0
|
|
11
11
|
Requires-Dist: pathspec>=1.0.4
|
|
12
12
|
Requires-Dist: python-on-whales>=0.68.0
|
|
13
13
|
Requires-Dist: pyyaml>=6.0.1
|
|
@@ -11,11 +11,17 @@ from botocore.exceptions import ClientError
|
|
|
11
11
|
from pydantic import BaseModel, Field
|
|
12
12
|
|
|
13
13
|
from pocket.resources.base import ResourceStatus
|
|
14
|
+
from pocket.utils import MANAGE_HANDLER_SUCCESS_SENTINEL
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
16
17
|
from pocket.context import LambdaHandlerContext
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
class ManagementCommandFailed(Exception):
|
|
21
|
+
"""management_command_handler の invoke が失敗した (成功センチネルが出ないまま
|
|
22
|
+
Lambda 実行が終わった) ことを示す。CLI を非ゼロ終了させ false green を防ぐ。"""
|
|
23
|
+
|
|
24
|
+
|
|
19
25
|
class Configuration(BaseModel):
|
|
20
26
|
hash: str | None = Field(alias="CodeSha256", default=None)
|
|
21
27
|
last_update_status: str | None = Field(alias="LastUpdateStatus", default=None)
|
|
@@ -132,6 +138,10 @@ class LambdaHandler:
|
|
|
132
138
|
events = self._find_events(start_pattern, created_at)
|
|
133
139
|
print("Log stream found: %s" % events[0]["logStreamName"])
|
|
134
140
|
printed = []
|
|
141
|
+
# 成功センチネル (management_command_handler が例外なく完了したときだけ印字)
|
|
142
|
+
# を REPORT 行までに観測できたかで成否を判定する。非同期 invoke では
|
|
143
|
+
# ハンドラの例外が呼び出し側に伝わらないため、ログ経由で判定する。
|
|
144
|
+
success_seen = False
|
|
135
145
|
sleep_seconds = 5
|
|
136
146
|
for _i in range(timeout_seconds // sleep_seconds):
|
|
137
147
|
res = self.logs_client.filter_log_events(
|
|
@@ -145,8 +155,16 @@ class LambdaHandler:
|
|
|
145
155
|
for message in messages[len(printed) :]:
|
|
146
156
|
print(message.strip())
|
|
147
157
|
printed.append(message)
|
|
158
|
+
if MANAGE_HANDLER_SUCCESS_SENTINEL in message:
|
|
159
|
+
success_seen = True
|
|
148
160
|
time.sleep(0.05)
|
|
149
161
|
if message.startswith(report_prefix):
|
|
162
|
+
if not success_seen:
|
|
163
|
+
raise ManagementCommandFailed(
|
|
164
|
+
"management command handler did not complete successfully "
|
|
165
|
+
"(no success marker before REPORT). "
|
|
166
|
+
"上の CloudWatch ログの traceback を確認してください。"
|
|
167
|
+
)
|
|
150
168
|
return
|
|
151
169
|
time.sleep(sleep_seconds)
|
|
152
170
|
print("Timeout %s seconds. Please check logs in cloudwatch." % timeout_seconds)
|
|
@@ -44,8 +44,9 @@ class Rds:
|
|
|
44
44
|
self._sm_client = boto3.client("secretsmanager", region_name=context.region)
|
|
45
45
|
self._ssm_client = boto3.client("ssm", region_name=context.region)
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
def _describe_cluster(self) -> dict | None:
|
|
48
|
+
"""クラスタを都度 API で引く (キャッシュしない)。create() の存在判定など、
|
|
49
|
+
作成前後で最新値が要る箇所はこちらを使う。"""
|
|
49
50
|
try:
|
|
50
51
|
res = self._rds_client.describe_db_clusters(
|
|
51
52
|
DBClusterIdentifier=self.context.cluster_identifier
|
|
@@ -60,7 +61,10 @@ class Rds:
|
|
|
60
61
|
raise
|
|
61
62
|
|
|
62
63
|
@cached_property
|
|
63
|
-
def
|
|
64
|
+
def cluster(self) -> dict | None:
|
|
65
|
+
return self._describe_cluster()
|
|
66
|
+
|
|
67
|
+
def _describe_instance(self) -> dict | None:
|
|
64
68
|
try:
|
|
65
69
|
res = self._rds_client.describe_db_instances(
|
|
66
70
|
DBInstanceIdentifier=self.context.instance_identifier
|
|
@@ -75,7 +79,10 @@ class Rds:
|
|
|
75
79
|
raise
|
|
76
80
|
|
|
77
81
|
@cached_property
|
|
78
|
-
def
|
|
82
|
+
def instance(self) -> dict | None:
|
|
83
|
+
return self._describe_instance()
|
|
84
|
+
|
|
85
|
+
def _describe_security_group(self) -> dict | None:
|
|
79
86
|
res = self._ec2_client.describe_security_groups(
|
|
80
87
|
Filters=[
|
|
81
88
|
{"Name": "tag:Name", "Values": [self.context.security_group_name]},
|
|
@@ -86,6 +93,10 @@ class Rds:
|
|
|
86
93
|
return groups[0]
|
|
87
94
|
return None
|
|
88
95
|
|
|
96
|
+
@cached_property
|
|
97
|
+
def _security_group(self) -> dict | None:
|
|
98
|
+
return self._describe_security_group()
|
|
99
|
+
|
|
89
100
|
@property
|
|
90
101
|
def security_group_id(self) -> str | None:
|
|
91
102
|
if self._security_group:
|
|
@@ -276,26 +287,34 @@ class Rds:
|
|
|
276
287
|
# managed VPC の COMPLETED 待ちは deploy_resources で行う
|
|
277
288
|
# (deploy_init 時点ではまだ VPC が作成されていない場合がある)
|
|
278
289
|
|
|
279
|
-
def
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
290
|
+
def _ensure_subnet_group(self, subnet_ids: list[str]) -> None:
|
|
291
|
+
"""DB Subnet Group を作成 (既存なら再利用)。"""
|
|
292
|
+
try:
|
|
293
|
+
echo.log("Creating DB Subnet Group: %s" % self.context.subnet_group_name)
|
|
294
|
+
self._rds_client.create_db_subnet_group(
|
|
295
|
+
DBSubnetGroupName=self.context.subnet_group_name,
|
|
296
|
+
DBSubnetGroupDescription="Aurora subnet group for %s"
|
|
297
|
+
% self.context.cluster_identifier,
|
|
298
|
+
SubnetIds=subnet_ids,
|
|
299
|
+
Tags=[{"Key": "Name", "Value": self.context.subnet_group_name}],
|
|
300
|
+
)
|
|
301
|
+
except ClientError as e:
|
|
302
|
+
if e.response["Error"]["Code"] != "DBSubnetGroupAlreadyExistsFault":
|
|
303
|
+
raise
|
|
304
|
+
echo.log(
|
|
305
|
+
"DB Subnet Group %s already exists; reusing."
|
|
306
|
+
% self.context.subnet_group_name
|
|
307
|
+
)
|
|
297
308
|
|
|
298
|
-
|
|
309
|
+
def _ensure_security_group(self, vpc_id: str) -> str:
|
|
310
|
+
"""RDS 用 Security Group を作成 (Name タグで既存を検出したら再利用)。"""
|
|
311
|
+
existing_sg = self._describe_security_group()
|
|
312
|
+
if existing_sg:
|
|
313
|
+
echo.log(
|
|
314
|
+
"Security Group %s already exists; reusing."
|
|
315
|
+
% self.context.security_group_name
|
|
316
|
+
)
|
|
317
|
+
return existing_sg["GroupId"]
|
|
299
318
|
echo.log("Creating Security Group: %s" % self.context.security_group_name)
|
|
300
319
|
sg_res = self._ec2_client.create_security_group(
|
|
301
320
|
GroupName=self.context.security_group_name,
|
|
@@ -311,20 +330,25 @@ class Rds:
|
|
|
311
330
|
}
|
|
312
331
|
],
|
|
313
332
|
)
|
|
314
|
-
|
|
333
|
+
return sg_res["GroupId"]
|
|
315
334
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
335
|
+
def _create_or_restore_cluster(
|
|
336
|
+
self, sg_id: str, static: bool
|
|
337
|
+
) -> tuple[bool, str | None]:
|
|
338
|
+
"""クラスタを作成/復元 (既存なら skip)。
|
|
319
339
|
|
|
320
|
-
|
|
340
|
+
戻り値は (このセッションで新規作成/復元したか, 生成した master password)。
|
|
341
|
+
"""
|
|
342
|
+
if self._describe_cluster() is not None:
|
|
343
|
+
echo.log(
|
|
344
|
+
"Aurora cluster %s already exists; skipping creation."
|
|
345
|
+
% self.context.cluster_identifier
|
|
346
|
+
)
|
|
347
|
+
return False, None
|
|
321
348
|
if self.context.snapshot_identifier:
|
|
322
349
|
echo.log(
|
|
323
350
|
"Restoring Aurora cluster %s from snapshot %s"
|
|
324
|
-
% (
|
|
325
|
-
self.context.cluster_identifier,
|
|
326
|
-
self.context.snapshot_identifier,
|
|
327
|
-
)
|
|
351
|
+
% (self.context.cluster_identifier, self.context.snapshot_identifier)
|
|
328
352
|
)
|
|
329
353
|
self._rds_client.restore_db_cluster_from_snapshot(
|
|
330
354
|
DBClusterIdentifier=self.context.cluster_identifier,
|
|
@@ -340,31 +364,40 @@ class Rds:
|
|
|
340
364
|
},
|
|
341
365
|
Tags=[{"Key": "Name", "Value": self.context.cluster_identifier}],
|
|
342
366
|
)
|
|
367
|
+
return True, None
|
|
368
|
+
echo.log("Creating Aurora cluster: %s" % self.context.cluster_identifier)
|
|
369
|
+
password: str | None = None
|
|
370
|
+
password_kwargs: dict = {}
|
|
371
|
+
if static:
|
|
372
|
+
password = _generate_master_password()
|
|
373
|
+
password_kwargs["MasterUserPassword"] = password
|
|
343
374
|
else:
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
self.
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
"MaxCapacity": self.context.max_capacity,
|
|
362
|
-
},
|
|
363
|
-
Tags=[{"Key": "Name", "Value": self.context.cluster_identifier}],
|
|
364
|
-
**password_kwargs,
|
|
365
|
-
)
|
|
375
|
+
password_kwargs["ManageMasterUserPassword"] = True
|
|
376
|
+
self._rds_client.create_db_cluster(
|
|
377
|
+
DBClusterIdentifier=self.context.cluster_identifier,
|
|
378
|
+
Engine="aurora-postgresql",
|
|
379
|
+
EngineMode="provisioned",
|
|
380
|
+
DatabaseName=self.context.database_name,
|
|
381
|
+
MasterUsername=self.context.master_username,
|
|
382
|
+
DBSubnetGroupName=self.context.subnet_group_name,
|
|
383
|
+
VpcSecurityGroupIds=[sg_id],
|
|
384
|
+
ServerlessV2ScalingConfiguration={
|
|
385
|
+
"MinCapacity": self.context.min_capacity,
|
|
386
|
+
"MaxCapacity": self.context.max_capacity,
|
|
387
|
+
},
|
|
388
|
+
Tags=[{"Key": "Name", "Value": self.context.cluster_identifier}],
|
|
389
|
+
**password_kwargs,
|
|
390
|
+
)
|
|
391
|
+
return True, password
|
|
366
392
|
|
|
367
|
-
|
|
393
|
+
def _ensure_instance(self) -> None:
|
|
394
|
+
"""Aurora インスタンスを作成 (既存なら skip)。"""
|
|
395
|
+
if self._describe_instance() is not None:
|
|
396
|
+
echo.log(
|
|
397
|
+
"Aurora instance %s already exists; skipping creation."
|
|
398
|
+
% self.context.instance_identifier
|
|
399
|
+
)
|
|
400
|
+
return
|
|
368
401
|
echo.log("Creating Aurora instance: %s" % self.context.instance_identifier)
|
|
369
402
|
self._rds_client.create_db_instance(
|
|
370
403
|
DBInstanceIdentifier=self.context.instance_identifier,
|
|
@@ -374,14 +407,48 @@ class Rds:
|
|
|
374
407
|
Tags=[{"Key": "Name", "Value": self.context.instance_identifier}],
|
|
375
408
|
)
|
|
376
409
|
|
|
377
|
-
|
|
410
|
+
def create(self):
|
|
411
|
+
# VPC スタックの完了を待つ
|
|
412
|
+
if not self.context.vpc:
|
|
413
|
+
raise RuntimeError("vpc context is not configured")
|
|
414
|
+
if self.context.vpc.manage:
|
|
415
|
+
Vpc(self.context.vpc).stack.wait_status("COMPLETED")
|
|
416
|
+
subnet_ids = self._get_vpc_subnet_ids()
|
|
417
|
+
vpc_id = self._get_vpc_id()
|
|
418
|
+
|
|
419
|
+
# 各ステップは「既に在れば再利用」で冪等にしてある。途中で失敗した
|
|
420
|
+
# deploy の再実行や、一部リソースだけ先行作成済みのケースでも
|
|
421
|
+
# AlreadyExists で落ちず、未完了のステップから続行できる。
|
|
422
|
+
|
|
423
|
+
static = self.context.password_strategy == "static" # noqa: S105 戦略名/保存先種別であって secret 値ではない
|
|
424
|
+
|
|
425
|
+
# 1. DB Subnet Group / 2. Security Group
|
|
426
|
+
self._ensure_subnet_group(subnet_ids)
|
|
427
|
+
sg_id = self._ensure_security_group(vpc_id)
|
|
428
|
+
|
|
429
|
+
# 3. Aurora クラスター (snapshot があれば復元)。cluster_created =
|
|
430
|
+
# このセッションで新規作成したか。password 切替 modify や static secret の
|
|
431
|
+
# 保存は「新規作成時のみ」実施する (再実行で static パスワードを作り直さない。
|
|
432
|
+
# 既存クラスタの調整は update() が担う)。
|
|
433
|
+
cluster_created, password = self._create_or_restore_cluster(sg_id, static)
|
|
434
|
+
|
|
435
|
+
# 4. Aurora インスタンス
|
|
436
|
+
self._ensure_instance()
|
|
437
|
+
|
|
438
|
+
# 5. クラスター/インスタンス available を待機(最大30分)。
|
|
439
|
+
# cluster available だけでは instance がまだ creating のことがあるため、
|
|
440
|
+
# 後続の modify_db_cluster (password 切替) の前に instance available まで
|
|
441
|
+
# 待つ。待たないと restore 直後の modify が反映されない/失敗しうる。
|
|
378
442
|
echo.log("Waiting for Aurora cluster to become available...")
|
|
379
443
|
self._wait_cluster_available(timeout=1800)
|
|
444
|
+
echo.log("Waiting for Aurora instance to become available...")
|
|
445
|
+
self._wait_instance_available(timeout=1800)
|
|
380
446
|
|
|
381
447
|
# 6. snapshot から復元した場合、マスターパスワードを設定し直す。
|
|
382
448
|
# (RestoreDBClusterFromSnapshot は snapshot の元パスワードを引き継ぐため、
|
|
383
449
|
# pocket が参照できる認証情報を改めて確立する必要がある)
|
|
384
|
-
|
|
450
|
+
# 新規に復元したときだけ実施 (再実行時の再切替を避ける)。
|
|
451
|
+
if cluster_created and self.context.snapshot_identifier:
|
|
385
452
|
if static:
|
|
386
453
|
echo.log("Setting a pocket-managed static master password...")
|
|
387
454
|
password = _generate_master_password()
|
|
@@ -404,8 +471,8 @@ class Rds:
|
|
|
404
471
|
|
|
405
472
|
# 7. static: 生成したパスワードを pocket 所有の secret に保存する。
|
|
406
473
|
# この secret を MasterUserSecret 相当として Lambda へ渡すため、ローテーション
|
|
407
|
-
# 用 Lambda は付けない (= 自動ローテーションしない)
|
|
408
|
-
if static:
|
|
474
|
+
# 用 Lambda は付けない (= 自動ローテーションしない)。新規作成時のみ。
|
|
475
|
+
if cluster_created and static:
|
|
409
476
|
if password is None:
|
|
410
477
|
raise RuntimeError("password must be set for static credentials")
|
|
411
478
|
self._store_static_credentials(password)
|
|
@@ -646,6 +713,26 @@ class Rds:
|
|
|
646
713
|
"Cluster did not become available within %s seconds" % timeout
|
|
647
714
|
)
|
|
648
715
|
|
|
716
|
+
def _wait_instance_available(self, timeout: int = 1800, interval: int = 10):
|
|
717
|
+
for i in range(timeout // interval):
|
|
718
|
+
try:
|
|
719
|
+
res = self._rds_client.describe_db_instances(
|
|
720
|
+
DBInstanceIdentifier=self.context.instance_identifier
|
|
721
|
+
)
|
|
722
|
+
status = res["DBInstances"][0]["DBInstanceStatus"]
|
|
723
|
+
if status == "available":
|
|
724
|
+
print("")
|
|
725
|
+
return
|
|
726
|
+
except ClientError:
|
|
727
|
+
pass
|
|
728
|
+
if i == 0:
|
|
729
|
+
print("Waiting for instance to be available", end="", flush=True)
|
|
730
|
+
print(".", end="", flush=True)
|
|
731
|
+
time.sleep(interval)
|
|
732
|
+
raise TimeoutError(
|
|
733
|
+
"Instance did not become available within %s seconds" % timeout
|
|
734
|
+
)
|
|
735
|
+
|
|
649
736
|
def _wait_instance_deleted(self, timeout: int = 600, interval: int = 10):
|
|
650
737
|
for i in range(timeout // interval):
|
|
651
738
|
try:
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "magic-pocket-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.9.0"
|
|
4
4
|
description = "CLI and deploy tools for magic-pocket."
|
|
5
5
|
requires-python = ">=3.10"
|
|
6
6
|
dependencies = [
|
|
7
|
-
"magic-pocket>=0.
|
|
7
|
+
"magic-pocket>=0.9.0",
|
|
8
8
|
"click>=8.1.7",
|
|
9
9
|
"jinja2>=3.1.3",
|
|
10
10
|
"python-on-whales>=0.68.0",
|
|
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
|
|
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
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/__init__.py
RENAMED
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/codebuild.py
RENAMED
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/depot.py
RENAMED
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/docker.py
RENAMED
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/builders/dockerignore.py
RENAMED
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/resources/aws/cloudformation.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/cloudformation/vpc.yaml
RENAMED
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/init/django-dotenv.env
RENAMED
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/init/django-settings.py
RENAMED
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/init/pocket.Dockerfile
RENAMED
|
File without changes
|
{magic_pocket_cli-0.8.0 → magic_pocket_cli-0.9.0}/pocket_cli/templates/init/pocket_simple.toml
RENAMED
|
File without changes
|