magic-pocket-cli 0.17.0__tar.gz → 0.18.1__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.18.1/.gitignore +42 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/PKG-INFO +2 -2
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/awscontainer_cli.py +36 -23
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/cloudfront_cli.py +14 -6
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/cloudfront_keys_cli.py +15 -6
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/cloudfront_waf_cli.py +14 -6
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/deploy_cli.py +40 -27
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/destroy_cli.py +93 -46
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/dsql_cli.py +4 -3
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/migrate_cli.py +70 -11
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/neon_cli.py +16 -6
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/rds_cli.py +2 -3
- magic_pocket_cli-0.18.1/pocket_cli/cli/resource_helper.py +25 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/runtime_config_cli.py +35 -20
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/s3_cli.py +4 -4
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/store_url_helper.py +2 -4
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/tidb_cli.py +30 -6
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/upstash_cli.py +4 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/url_helper.py +16 -13
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/django_cli.py +32 -37
- magic_pocket_cli-0.18.1/pocket_cli/mediator.py +235 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/builders/codebuild.py +10 -26
- magic_pocket_cli-0.18.1/pocket_cli/resources/aws/builders/dockerignore.py +81 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/cloudformation.py +66 -91
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/ecr.py +21 -8
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/efs.py +23 -30
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/lambdahandler.py +60 -14
- magic_pocket_cli-0.18.1/pocket_cli/resources/aws/poll.py +35 -0
- magic_pocket_cli-0.18.1/pocket_cli/resources/aws/stack_backed.py +62 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/state.py +17 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/cloudfront.py +11 -8
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/cloudfront_acm.py +6 -20
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/cloudfront_keys.py +22 -19
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/cloudfront_waf.py +4 -21
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/dsql.py +25 -19
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/rds.py +76 -88
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/tidb.py +6 -2
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/awscontainer.yaml +26 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pyproject.toml +2 -2
- magic_pocket_cli-0.17.0/.gitignore +0 -31
- magic_pocket_cli-0.17.0/pocket_cli/mediator.py +0 -463
- magic_pocket_cli-0.17.0/pocket_cli/resources/aws/builders/dockerignore.py +0 -44
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/__init__.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/__init__.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/aws_auth.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/main_cli.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/permissions_cli.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/status_cli.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/vpc_cli.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/cli/waf_cli.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/__init__.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/__init__.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/builders/__init__.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/builders/depot.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/builders/docker.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/aws/s3_utils.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/awscontainer.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/neon.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/s3.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/upstash.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/resources/vpc.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/cf_function_api_host.js +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/cf_function_host_redirect_prelude.js +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/cf_function_spa_auth.js +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/cf_function_spa_fallback.js +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/cloudfront.yaml +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/cloudfront_acm.yaml +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/cloudfront_keys.yaml +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/cloudfront_waf.yaml +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/cloudformation/vpc.yaml +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/init/django-dotenv.env +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/init/django-settings.py +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/init/pocket.Dockerfile +0 -0
- {magic_pocket_cli-0.17.0 → magic_pocket_cli-0.18.1}/pocket_cli/templates/init/pocket_simple.toml +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# python generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# venv
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# editors
|
|
13
|
+
.vscode/
|
|
14
|
+
|
|
15
|
+
# local env
|
|
16
|
+
.env
|
|
17
|
+
.envrc.local
|
|
18
|
+
|
|
19
|
+
# Rust
|
|
20
|
+
/target/
|
|
21
|
+
|
|
22
|
+
# Zensical build output
|
|
23
|
+
site/
|
|
24
|
+
|
|
25
|
+
# Vendor wheels (built locally for examples)
|
|
26
|
+
vendor/
|
|
27
|
+
|
|
28
|
+
# Forge
|
|
29
|
+
forge.local.toml
|
|
30
|
+
|
|
31
|
+
/CLAUDE.md
|
|
32
|
+
|
|
33
|
+
# Activity Docs (作業ローカルの working doc。公開 repo には出さない)
|
|
34
|
+
/docs/activity/
|
|
35
|
+
|
|
36
|
+
# example deploy 生成物 (pocket が生成: runtime config / collectstatic 出力 / cache)
|
|
37
|
+
/example-neon/pocket.runtime.toml
|
|
38
|
+
/example-neon/pocket_cache/
|
|
39
|
+
/example-neon/staticfiles/
|
|
40
|
+
/example-tidb/pocket.runtime.toml
|
|
41
|
+
/example-tidb/pocket_cache/
|
|
42
|
+
/example-tidb/staticfiles/
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: magic-pocket-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.18.1
|
|
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.18.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
|
|
@@ -9,6 +9,11 @@ from botocore.exceptions import ClientError
|
|
|
9
9
|
from pocket.context import Context
|
|
10
10
|
from pocket.runtime import get_secrets
|
|
11
11
|
from pocket.utils import echo
|
|
12
|
+
from pocket_cli.cli.destroy_cli import (
|
|
13
|
+
_collect_awscontainer_targets,
|
|
14
|
+
_destroy_awscontainer,
|
|
15
|
+
)
|
|
16
|
+
from pocket_cli.cli.resource_helper import require_configured
|
|
12
17
|
from pocket_cli.mediator import Mediator
|
|
13
18
|
from pocket_cli.resources.awscontainer import AwsContainer
|
|
14
19
|
|
|
@@ -20,10 +25,11 @@ def awscontainer():
|
|
|
20
25
|
|
|
21
26
|
def get_awscontainer_resource(stage):
|
|
22
27
|
context = Context.from_toml(stage=stage)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
return AwsContainer(
|
|
29
|
+
context=require_configured(
|
|
30
|
+
context.awscontainer, "awscontainer is not configured for this stage"
|
|
31
|
+
)
|
|
32
|
+
)
|
|
27
33
|
|
|
28
34
|
|
|
29
35
|
@awscontainer.command()
|
|
@@ -135,25 +141,32 @@ def create(stage):
|
|
|
135
141
|
@awscontainer.command()
|
|
136
142
|
@click.option("--stage", envvar="POCKET_DEPLOY_STAGE", prompt=True)
|
|
137
143
|
@click.option("--with-secrets", is_flag=True, default=False)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
echo.warning("
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
144
|
+
@click.option(
|
|
145
|
+
"--yes", "-y", is_flag=True, default=False, help="確認プロンプトをスキップ"
|
|
146
|
+
)
|
|
147
|
+
def destroy(stage, with_secrets, yes):
|
|
148
|
+
"""AwsContainer 関連リソースを削除する。
|
|
149
|
+
|
|
150
|
+
トップレベル `pocket destroy` と同じ実装を使う (共有 ECR の削除ガード /
|
|
151
|
+
stack 削除完了待ち / CodeBuild / log group 掃除を含む)。
|
|
152
|
+
"""
|
|
153
|
+
context = Context.from_toml(stage=stage)
|
|
154
|
+
if not context.awscontainer:
|
|
155
|
+
echo.warning("awscontainer is not configured for this stage")
|
|
156
|
+
return
|
|
157
|
+
targets = _collect_awscontainer_targets(context, with_secrets)
|
|
158
|
+
if not targets:
|
|
159
|
+
echo.warning("削除対象のリソースが見つかりません。")
|
|
160
|
+
return
|
|
161
|
+
echo.danger("以下のリソースを削除します:")
|
|
162
|
+
for target in targets:
|
|
163
|
+
echo.info(" - %s" % target)
|
|
164
|
+
echo.danger("この操作は取り消せません!")
|
|
165
|
+
if not yes:
|
|
166
|
+
click.confirm(
|
|
167
|
+
"stage '%s' の AwsContainer リソースを削除しますか?" % stage, abort=True
|
|
168
|
+
)
|
|
169
|
+
_destroy_awscontainer(context, with_secrets)
|
|
157
170
|
|
|
158
171
|
|
|
159
172
|
@awscontainer.command()
|
|
@@ -2,6 +2,7 @@ import click
|
|
|
2
2
|
|
|
3
3
|
from pocket.context import Context
|
|
4
4
|
from pocket.utils import echo
|
|
5
|
+
from pocket_cli.cli.resource_helper import require_configured
|
|
5
6
|
from pocket_cli.resources.cloudfront import CloudFront
|
|
6
7
|
|
|
7
8
|
|
|
@@ -12,13 +13,12 @@ def cloudfront():
|
|
|
12
13
|
|
|
13
14
|
def get_cloudfront_resources(stage, name=None):
|
|
14
15
|
context = Context.from_toml(stage=stage)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
require_configured(
|
|
17
|
+
context.cloudfront, "cloudfront is not configured for this stage"
|
|
18
|
+
)
|
|
18
19
|
if name:
|
|
19
20
|
if name not in context.cloudfront:
|
|
20
|
-
|
|
21
|
-
raise Exception("cloudfront '%s' is not configured" % name)
|
|
21
|
+
raise click.ClickException("cloudfront '%s' is not configured" % name)
|
|
22
22
|
return [CloudFront(context.cloudfront[name])]
|
|
23
23
|
return [CloudFront(cf_ctx) for cf_ctx in context.cloudfront.values()]
|
|
24
24
|
|
|
@@ -63,7 +63,15 @@ def create(stage, name):
|
|
|
63
63
|
@cloudfront.command()
|
|
64
64
|
@click.option("--stage", envvar="POCKET_DEPLOY_STAGE", prompt=True)
|
|
65
65
|
@click.option("--name", default=None)
|
|
66
|
-
|
|
66
|
+
@click.option(
|
|
67
|
+
"--yes", "-y", is_flag=True, default=False, help="確認プロンプトをスキップ"
|
|
68
|
+
)
|
|
69
|
+
def destroy(stage, name, yes):
|
|
70
|
+
if not yes:
|
|
71
|
+
click.confirm(
|
|
72
|
+
"stage '%s' の CloudFront distribution を削除しますか?" % stage,
|
|
73
|
+
abort=True,
|
|
74
|
+
)
|
|
67
75
|
for cf in get_cloudfront_resources(stage, name):
|
|
68
76
|
echo.info("[%s]" % cf.context.name)
|
|
69
77
|
cf.delete()
|
|
@@ -2,6 +2,7 @@ import click
|
|
|
2
2
|
|
|
3
3
|
from pocket.context import Context
|
|
4
4
|
from pocket.utils import echo
|
|
5
|
+
from pocket_cli.cli.resource_helper import require_configured
|
|
5
6
|
from pocket_cli.resources.cloudfront_keys import CloudFrontKeys
|
|
6
7
|
|
|
7
8
|
|
|
@@ -12,9 +13,9 @@ def cloudfront_keys():
|
|
|
12
13
|
|
|
13
14
|
def get_cloudfront_keys_resources(stage, name=None):
|
|
14
15
|
context = Context.from_toml(stage=stage)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
require_configured(
|
|
17
|
+
context.cloudfront, "cloudfront is not configured for this stage"
|
|
18
|
+
)
|
|
18
19
|
results = []
|
|
19
20
|
for cf_name, cf_ctx in context.cloudfront.items():
|
|
20
21
|
if not cf_ctx.signing_key:
|
|
@@ -23,8 +24,7 @@ def get_cloudfront_keys_resources(stage, name=None):
|
|
|
23
24
|
continue
|
|
24
25
|
results.append(CloudFrontKeys(cf_ctx))
|
|
25
26
|
if name and not results:
|
|
26
|
-
|
|
27
|
-
raise Exception("cloudfront_keys '%s' is not configured" % name)
|
|
27
|
+
raise click.ClickException("cloudfront_keys '%s' is not configured" % name)
|
|
28
28
|
return results
|
|
29
29
|
|
|
30
30
|
|
|
@@ -61,7 +61,16 @@ def status(stage, name):
|
|
|
61
61
|
@cloudfront_keys.command()
|
|
62
62
|
@click.option("--stage", envvar="POCKET_DEPLOY_STAGE", prompt=True)
|
|
63
63
|
@click.option("--name", default=None)
|
|
64
|
-
|
|
64
|
+
@click.option(
|
|
65
|
+
"--yes", "-y", is_flag=True, default=False, help="確認プロンプトをスキップ"
|
|
66
|
+
)
|
|
67
|
+
def destroy(stage, name, yes):
|
|
68
|
+
if not yes:
|
|
69
|
+
click.confirm(
|
|
70
|
+
"stage '%s' の CloudFront signing key リソースを削除しますか?"
|
|
71
|
+
"(署名済み URL が無効になります)" % stage,
|
|
72
|
+
abort=True,
|
|
73
|
+
)
|
|
65
74
|
for cfk in get_cloudfront_keys_resources(stage, name):
|
|
66
75
|
echo.info("[%s]" % cfk.context.name)
|
|
67
76
|
cfk.delete()
|
|
@@ -2,6 +2,7 @@ import click
|
|
|
2
2
|
|
|
3
3
|
from pocket.context import Context
|
|
4
4
|
from pocket.utils import echo
|
|
5
|
+
from pocket_cli.cli.resource_helper import require_configured
|
|
5
6
|
from pocket_cli.resources.cloudfront_waf import CloudFrontWaf
|
|
6
7
|
|
|
7
8
|
|
|
@@ -12,9 +13,9 @@ def cloudfront_waf():
|
|
|
12
13
|
|
|
13
14
|
def get_cloudfront_waf_resources(stage, name=None):
|
|
14
15
|
context = Context.from_toml(stage=stage)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
require_configured(
|
|
17
|
+
context.cloudfront, "cloudfront is not configured for this stage"
|
|
18
|
+
)
|
|
18
19
|
results = []
|
|
19
20
|
for cf_name, cf_ctx in context.cloudfront.items():
|
|
20
21
|
if cf_ctx.waf is None:
|
|
@@ -23,8 +24,7 @@ def get_cloudfront_waf_resources(stage, name=None):
|
|
|
23
24
|
continue
|
|
24
25
|
results.append(CloudFrontWaf(cf_ctx))
|
|
25
26
|
if name and not results:
|
|
26
|
-
|
|
27
|
-
raise Exception("cloudfront_waf '%s' is not configured" % name)
|
|
27
|
+
raise click.ClickException("cloudfront_waf '%s' is not configured" % name)
|
|
28
28
|
return results
|
|
29
29
|
|
|
30
30
|
|
|
@@ -61,7 +61,15 @@ def status(stage, name):
|
|
|
61
61
|
@cloudfront_waf.command()
|
|
62
62
|
@click.option("--stage", envvar="POCKET_DEPLOY_STAGE", prompt=True)
|
|
63
63
|
@click.option("--name", default=None)
|
|
64
|
-
|
|
64
|
+
@click.option(
|
|
65
|
+
"--yes", "-y", is_flag=True, default=False, help="確認プロンプトをスキップ"
|
|
66
|
+
)
|
|
67
|
+
def destroy(stage, name, yes):
|
|
68
|
+
if not yes:
|
|
69
|
+
click.confirm(
|
|
70
|
+
"stage '%s' の WAF WebACL を削除しますか?(IP 制限が解除されます)" % stage,
|
|
71
|
+
abort=True,
|
|
72
|
+
)
|
|
65
73
|
for waf in get_cloudfront_waf_resources(stage, name):
|
|
66
74
|
echo.info("[%s]" % waf.context.name)
|
|
67
75
|
waf.delete()
|
|
@@ -6,7 +6,7 @@ import click
|
|
|
6
6
|
from pocket.context import Context, deploy_hash_report
|
|
7
7
|
from pocket.utils import echo
|
|
8
8
|
from pocket_cli.mediator import Mediator
|
|
9
|
-
from pocket_cli.resources.aws.state import StateStore
|
|
9
|
+
from pocket_cli.resources.aws.state import StateStore, create_state_store
|
|
10
10
|
from pocket_cli.resources.awscontainer import AwsContainer
|
|
11
11
|
from pocket_cli.resources.cloudfront import CloudFront
|
|
12
12
|
from pocket_cli.resources.cloudfront_acm import CloudFrontAcm
|
|
@@ -72,15 +72,7 @@ def get_resources(context: Context, *, state_bucket: str = ""):
|
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
def _create_state_store(context: Context) -> StateStore:
|
|
75
|
-
|
|
76
|
-
raise RuntimeError("general context is not configured")
|
|
77
|
-
resource_prefix = context.general.prefix_template.format(
|
|
78
|
-
stage=context.stage,
|
|
79
|
-
project=context.project_name,
|
|
80
|
-
namespace=context.general.namespace,
|
|
81
|
-
)
|
|
82
|
-
bucket_name = f"{resource_prefix}state"
|
|
83
|
-
return StateStore(bucket_name, context.general.region)
|
|
75
|
+
return create_state_store(context)
|
|
84
76
|
|
|
85
77
|
|
|
86
78
|
def deploy_init_resources(context: Context, *, state_bucket: str = ""):
|
|
@@ -114,6 +106,43 @@ def upload_managed_assets(context: Context):
|
|
|
114
106
|
cf.upload_managed_assets()
|
|
115
107
|
|
|
116
108
|
|
|
109
|
+
def _deploy_resource(resource, mediator: Mediator, state_store: StateStore):
|
|
110
|
+
target_name = resource.__class__.__name__
|
|
111
|
+
# template hash に影響する入力 (secret 値等) を status 判定前に読み込む。
|
|
112
|
+
# 空のまま hash を計算すると deploy 済み hash と一致せず、secret 焼き込み
|
|
113
|
+
# 構成 (enable_origin_verify / signing_key) で毎回 REQUIRE_UPDATE になる
|
|
114
|
+
prepare = getattr(resource, "prepare_deploy", None)
|
|
115
|
+
if prepare is not None:
|
|
116
|
+
prepare(mediator)
|
|
117
|
+
if resource.status == "NOEXIST":
|
|
118
|
+
echo.log("Creating %s..." % target_name)
|
|
119
|
+
if "mediator" in inspect.signature(resource.create).parameters:
|
|
120
|
+
resource.create(mediator)
|
|
121
|
+
else:
|
|
122
|
+
resource.create()
|
|
123
|
+
state_store.record(resource.state_info())
|
|
124
|
+
elif resource.status == "REQUIRE_UPDATE":
|
|
125
|
+
echo.log("Updating %s..." % target_name)
|
|
126
|
+
if "mediator" in inspect.signature(resource.update).parameters:
|
|
127
|
+
resource.update(mediator)
|
|
128
|
+
else:
|
|
129
|
+
resource.update()
|
|
130
|
+
state_store.record(resource.state_info())
|
|
131
|
+
elif resource.status == "FAILED":
|
|
132
|
+
# 黙ってスキップすると deploy が exit 0 で成功表示になる
|
|
133
|
+
raise RuntimeError(
|
|
134
|
+
"%s が FAILED 状態です。AWS コンソール等で状態を確認して"
|
|
135
|
+
"解消してから再実行してください。" % target_name
|
|
136
|
+
)
|
|
137
|
+
elif resource.status == "PROGRESS":
|
|
138
|
+
raise RuntimeError(
|
|
139
|
+
"%s の前回操作が進行中です。完了を待ってから再実行してください。"
|
|
140
|
+
% target_name
|
|
141
|
+
)
|
|
142
|
+
else:
|
|
143
|
+
echo.log("%s is already the latest version." % target_name)
|
|
144
|
+
|
|
145
|
+
|
|
117
146
|
def deploy_resources(context: Context, *, state_bucket: str = ""):
|
|
118
147
|
state_store = _create_state_store(context)
|
|
119
148
|
# state bucket は deploy_init_resources の前に作成済み
|
|
@@ -123,23 +152,7 @@ def deploy_resources(context: Context, *, state_bucket: str = ""):
|
|
|
123
152
|
mediator = Mediator(context)
|
|
124
153
|
resources = get_resources(context, state_bucket=state_bucket)
|
|
125
154
|
for resource in resources:
|
|
126
|
-
|
|
127
|
-
if resource.status == "NOEXIST":
|
|
128
|
-
echo.log("Creating %s..." % target_name)
|
|
129
|
-
if "mediator" in inspect.signature(resource.create).parameters:
|
|
130
|
-
resource.create(mediator)
|
|
131
|
-
else:
|
|
132
|
-
resource.create()
|
|
133
|
-
state_store.record(resource.state_info())
|
|
134
|
-
elif resource.status == "REQUIRE_UPDATE":
|
|
135
|
-
echo.log("Updating %s..." % target_name)
|
|
136
|
-
if "mediator" in inspect.signature(resource.update).parameters:
|
|
137
|
-
resource.update(mediator)
|
|
138
|
-
else:
|
|
139
|
-
resource.update()
|
|
140
|
-
state_store.record(resource.state_info())
|
|
141
|
-
else:
|
|
142
|
-
echo.log("%s is already the latest version." % target_name)
|
|
155
|
+
_deploy_resource(resource, mediator, state_store)
|
|
143
156
|
# stack 作成/更新が終わった後の後付け状態 (bucket policy / KVS など) を
|
|
144
157
|
# 冪等に確保する。wait_status が timeout した次の deploy でも復旧できる。
|
|
145
158
|
for resource in resources:
|
|
@@ -4,7 +4,10 @@ import click
|
|
|
4
4
|
from pocket.context import Context
|
|
5
5
|
from pocket.utils import echo
|
|
6
6
|
from pocket_cli.resources.aws.builders.codebuild import CodeBuildBuilder
|
|
7
|
-
from pocket_cli.resources.aws.state import
|
|
7
|
+
from pocket_cli.resources.aws.state import (
|
|
8
|
+
context_resource_prefix,
|
|
9
|
+
create_state_store,
|
|
10
|
+
)
|
|
8
11
|
from pocket_cli.resources.awscontainer import AwsContainer
|
|
9
12
|
from pocket_cli.resources.cloudfront import CloudFront
|
|
10
13
|
from pocket_cli.resources.cloudfront_acm import CloudFrontAcm
|
|
@@ -18,32 +21,15 @@ from pocket_cli.resources.upstash import Upstash
|
|
|
18
21
|
from pocket_cli.resources.vpc import Vpc
|
|
19
22
|
|
|
20
23
|
|
|
21
|
-
def _create_state_store(context: Context) -> StateStore:
|
|
22
|
-
if not context.general:
|
|
23
|
-
raise RuntimeError("general context is not configured")
|
|
24
|
-
resource_prefix = context.general.prefix_template.format(
|
|
25
|
-
stage=context.stage,
|
|
26
|
-
project=context.project_name,
|
|
27
|
-
namespace=context.general.namespace,
|
|
28
|
-
)
|
|
29
|
-
bucket_name = f"{resource_prefix}state"
|
|
30
|
-
return StateStore(bucket_name, context.general.region)
|
|
31
|
-
|
|
32
|
-
|
|
33
24
|
def _create_codebuild_builder(context: Context) -> CodeBuildBuilder | None:
|
|
34
25
|
"""CodeBuildBuilder インスタンスを作成(リソース確認用)"""
|
|
35
26
|
if not context.awscontainer or not context.general:
|
|
36
27
|
return None
|
|
37
|
-
resource_prefix = context
|
|
38
|
-
stage=context.stage,
|
|
39
|
-
project=context.project_name,
|
|
40
|
-
namespace=context.general.namespace,
|
|
41
|
-
)
|
|
42
|
-
state_bucket = f"{resource_prefix}state"
|
|
28
|
+
resource_prefix = context_resource_prefix(context)
|
|
43
29
|
return CodeBuildBuilder(
|
|
44
30
|
region=context.general.region,
|
|
45
31
|
resource_prefix=resource_prefix,
|
|
46
|
-
state_bucket=
|
|
32
|
+
state_bucket=f"{resource_prefix}state",
|
|
47
33
|
permissions_boundary=context.awscontainer.permissions_boundary,
|
|
48
34
|
)
|
|
49
35
|
|
|
@@ -89,13 +75,18 @@ def _collect_awscontainer_targets(context: Context, with_secrets: bool):
|
|
|
89
75
|
parts.append("CodeBuild")
|
|
90
76
|
|
|
91
77
|
targets.append("AwsContainer (%s)" % " + ".join(parts))
|
|
92
|
-
targets.extend(_collect_vpc_targets(context))
|
|
93
78
|
|
|
94
79
|
return targets
|
|
95
80
|
|
|
96
81
|
|
|
97
|
-
def
|
|
98
|
-
|
|
82
|
+
def _warn_command_provisioned(label: str, hint: str):
|
|
83
|
+
echo.warning(
|
|
84
|
+
'%s は provisioning="command" のため destroy では削除しません。'
|
|
85
|
+
"%s で削除してください。" % (label, hint)
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _collect_aws_database_targets(context: Context) -> list[str]:
|
|
99
90
|
targets: list[str] = []
|
|
100
91
|
if context.dsql:
|
|
101
92
|
dsql = Dsql(context.dsql)
|
|
@@ -105,15 +96,36 @@ def _collect_database_targets(context: Context) -> list[str]:
|
|
|
105
96
|
rds = Rds(context.rds)
|
|
106
97
|
if rds.status != "NOEXIST":
|
|
107
98
|
targets.append("RDS Aurora クラスター: %s" % context.rds.cluster_identifier)
|
|
108
|
-
if context.tidb:
|
|
109
|
-
targets.append("TiDB クラスタ")
|
|
110
|
-
if context.upstash:
|
|
111
|
-
targets.append("Upstash Redis: %s" % context.upstash.database_name)
|
|
112
|
-
if context.neon:
|
|
113
|
-
targets.append("Neon ブランチ")
|
|
114
99
|
return targets
|
|
115
100
|
|
|
116
101
|
|
|
102
|
+
def _collect_external_database_targets(context: Context) -> list[str]:
|
|
103
|
+
"""外部 DB (TiDB / Upstash / Neon) の削除対象を収集
|
|
104
|
+
|
|
105
|
+
provisioning="command" の DB は deploy 同様 destroy も管理しない
|
|
106
|
+
(credential レス運用のため provider API を叩かない)。
|
|
107
|
+
dsql/rds と同様に存在確認し、確認プロンプトの一覧を実態に合わせる。
|
|
108
|
+
"""
|
|
109
|
+
targets: list[str] = []
|
|
110
|
+
if context.tidb and context.tidb.provisioning != "command":
|
|
111
|
+
if TiDb(context.tidb).cluster:
|
|
112
|
+
targets.append("TiDB クラスタ")
|
|
113
|
+
if context.upstash and context.upstash.provisioning != "command":
|
|
114
|
+
if Upstash(context.upstash).database:
|
|
115
|
+
targets.append("Upstash Redis: %s" % context.upstash.database_name)
|
|
116
|
+
if context.neon and context.neon.provisioning != "command":
|
|
117
|
+
if Neon(context.neon).branch:
|
|
118
|
+
targets.append("Neon ブランチ")
|
|
119
|
+
return targets
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _collect_database_targets(context: Context) -> list[str]:
|
|
123
|
+
"""データベース関連の削除対象を収集"""
|
|
124
|
+
return _collect_aws_database_targets(context) + _collect_external_database_targets(
|
|
125
|
+
context
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
117
129
|
def _collect_targets(context: Context, with_secrets: bool, with_state_bucket: bool):
|
|
118
130
|
"""削除対象のリソース一覧を収集"""
|
|
119
131
|
targets: list[str] = []
|
|
@@ -125,6 +137,7 @@ def _collect_targets(context: Context, with_secrets: bool, with_state_bucket: bo
|
|
|
125
137
|
|
|
126
138
|
targets.extend(_collect_awscontainer_targets(context, with_secrets))
|
|
127
139
|
targets.extend(_collect_database_targets(context))
|
|
140
|
+
targets.extend(_collect_vpc_targets(context))
|
|
128
141
|
|
|
129
142
|
for name, cf_ctx in context.cloudfront.items():
|
|
130
143
|
if cf_ctx.signing_key:
|
|
@@ -173,6 +186,9 @@ def _destroy_awscontainer(context: Context, with_secrets: bool):
|
|
|
173
186
|
if ac.stack.status != "NOEXIST":
|
|
174
187
|
echo.log("Destroying AwsContainer stack...")
|
|
175
188
|
ac.stack.delete()
|
|
189
|
+
# Lambda が VPC 内にある場合、ENI 解放を含む削除完了を待たないと
|
|
190
|
+
# 後続の VPC 削除が subnet 使用中で DELETE_FAILED になる
|
|
191
|
+
ac.stack.wait_status("NOEXIST", timeout=1800, interval=10)
|
|
176
192
|
echo.success("AwsContainer stack was destroyed.")
|
|
177
193
|
|
|
178
194
|
if ac.ecr.exists():
|
|
@@ -196,8 +212,6 @@ def _destroy_awscontainer(context: Context, with_secrets: bool):
|
|
|
196
212
|
context.awscontainer.secrets.pocket_store.delete_secrets()
|
|
197
213
|
echo.success("Pocket managed secrets were deleted.")
|
|
198
214
|
|
|
199
|
-
_destroy_vpc(context)
|
|
200
|
-
|
|
201
215
|
|
|
202
216
|
def _destroy_dsql(context: Context):
|
|
203
217
|
"""DSQL クラスターを削除"""
|
|
@@ -252,6 +266,44 @@ def _destroy_vpc(context: Context):
|
|
|
252
266
|
echo.success("VPC was destroyed.")
|
|
253
267
|
|
|
254
268
|
|
|
269
|
+
def _destroy_tidb(context: Context):
|
|
270
|
+
"""TiDB クラスタを削除 (provisioning="command" は管理外)"""
|
|
271
|
+
if not context.tidb:
|
|
272
|
+
return
|
|
273
|
+
if context.tidb.provisioning == "command":
|
|
274
|
+
_warn_command_provisioned("TiDB", "pocket resource tidb delete")
|
|
275
|
+
return
|
|
276
|
+
if TiDb(context.tidb).cluster:
|
|
277
|
+
echo.log("Destroying TiDB cluster...")
|
|
278
|
+
TiDb(context.tidb).delete_cluster()
|
|
279
|
+
echo.success("TiDB cluster was deleted.")
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _destroy_upstash(context: Context):
|
|
283
|
+
"""Upstash Redis を削除 (provisioning="command" は管理外)"""
|
|
284
|
+
if not context.upstash:
|
|
285
|
+
return
|
|
286
|
+
if context.upstash.provisioning == "command":
|
|
287
|
+
_warn_command_provisioned("Upstash", "Upstash コンソール等")
|
|
288
|
+
return
|
|
289
|
+
upstash = Upstash(context.upstash)
|
|
290
|
+
if upstash.database:
|
|
291
|
+
upstash.delete_database()
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _destroy_neon(context: Context):
|
|
295
|
+
"""Neon ブランチを削除 (provisioning="command" は管理外)"""
|
|
296
|
+
if not context.neon:
|
|
297
|
+
return
|
|
298
|
+
if context.neon.provisioning == "command":
|
|
299
|
+
_warn_command_provisioned("Neon", "pocket resource neon delete")
|
|
300
|
+
return
|
|
301
|
+
if Neon(context.neon).branch:
|
|
302
|
+
echo.log("Destroying Neon branch...")
|
|
303
|
+
Neon(context.neon).delete_branch()
|
|
304
|
+
echo.success("Neon branch was deleted.")
|
|
305
|
+
|
|
306
|
+
|
|
255
307
|
def _destroy_cloudfront_and_acm(context: Context):
|
|
256
308
|
"""CloudFront ディストリビューションと ACM 証明書を削除"""
|
|
257
309
|
for name, cf_ctx in context.cloudfront.items():
|
|
@@ -273,7 +325,7 @@ def _destroy_resources(context: Context, with_secrets: bool, with_state_bucket:
|
|
|
273
325
|
# 1. CloudFront + ACM
|
|
274
326
|
_destroy_cloudfront_and_acm(context)
|
|
275
327
|
|
|
276
|
-
# 2. AwsContainer (CFNスタック + ECR + secrets)
|
|
328
|
+
# 2. AwsContainer (CFNスタック + ECR + secrets)
|
|
277
329
|
_destroy_awscontainer(context, with_secrets)
|
|
278
330
|
|
|
279
331
|
# 2.5. DSQL
|
|
@@ -282,6 +334,10 @@ def _destroy_resources(context: Context, with_secrets: bool, with_state_bucket:
|
|
|
282
334
|
# 2.6. RDS(AwsContainer の後、VPC の前)
|
|
283
335
|
_destroy_rds(context)
|
|
284
336
|
|
|
337
|
+
# 3. VPC(RDS の後。RDS が VPC の subnet / SG を使用しているため、
|
|
338
|
+
# 先に VPC を消すと DELETE_FAILED になる)
|
|
339
|
+
_destroy_vpc(context)
|
|
340
|
+
|
|
285
341
|
# 3.5. CloudFrontKeys(AwsContainer の後、S3 の前)
|
|
286
342
|
for name, cf_ctx in context.cloudfront.items():
|
|
287
343
|
if cf_ctx.signing_key:
|
|
@@ -297,27 +353,18 @@ def _destroy_resources(context: Context, with_secrets: bool, with_state_bucket:
|
|
|
297
353
|
S3(context.s3).delete()
|
|
298
354
|
echo.success("S3 bucket was deleted.")
|
|
299
355
|
|
|
300
|
-
# 5. TiDB クラスタ
|
|
301
|
-
|
|
302
|
-
echo.log("Destroying TiDB cluster...")
|
|
303
|
-
TiDb(context.tidb).delete_cluster()
|
|
304
|
-
echo.success("TiDB cluster was deleted.")
|
|
356
|
+
# 5. TiDB クラスタ (provisioning="command" は deploy 同様 destroy も管理しない)
|
|
357
|
+
_destroy_tidb(context)
|
|
305
358
|
|
|
306
359
|
# 5.5. Upstash Redis
|
|
307
|
-
|
|
308
|
-
upstash = Upstash(context.upstash)
|
|
309
|
-
if upstash.database:
|
|
310
|
-
upstash.delete_database()
|
|
360
|
+
_destroy_upstash(context)
|
|
311
361
|
|
|
312
362
|
# 6. Neon ブランチ
|
|
313
|
-
|
|
314
|
-
echo.log("Destroying Neon branch...")
|
|
315
|
-
Neon(context.neon).delete_branch()
|
|
316
|
-
echo.success("Neon branch was deleted.")
|
|
363
|
+
_destroy_neon(context)
|
|
317
364
|
|
|
318
365
|
# 7. ステートバケット
|
|
319
366
|
if with_state_bucket:
|
|
320
|
-
state_store =
|
|
367
|
+
state_store = create_state_store(context)
|
|
321
368
|
echo.log("Destroying state bucket...")
|
|
322
369
|
state_store.delete_bucket()
|
|
323
370
|
echo.success("State bucket was deleted.")
|
|
@@ -4,14 +4,15 @@ import click
|
|
|
4
4
|
|
|
5
5
|
from pocket.context import Context
|
|
6
6
|
from pocket.utils import echo
|
|
7
|
+
from pocket_cli.cli.resource_helper import require_configured
|
|
7
8
|
from pocket_cli.resources.dsql import Dsql
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def _get_dsql_resource(stage: str) -> Dsql:
|
|
11
12
|
context = Context.from_toml(stage=stage)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
return Dsql(
|
|
14
|
+
require_configured(context.dsql, "dsql is not configured for this stage")
|
|
15
|
+
)
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
@click.group()
|