dbt-platform-helper 13.2.0__tar.gz → 13.3.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.
Potentially problematic release.
This version of dbt-platform-helper might be problematic. Click here for more details.
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/PKG-INFO +2 -2
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/codebase.py +10 -4
- dbt_platform_helper-13.3.0/dbt_platform_helper/commands/config.py +38 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/copilot.py +10 -6
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/database.py +17 -9
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/environment.py +2 -3
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/codebase.py +7 -7
- dbt_platform_helper-13.3.0/dbt_platform_helper/domain/config.py +345 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/copilot.py +155 -157
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/versioning.py +48 -7
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/aws/exceptions.py +10 -0
- dbt_platform_helper-13.3.0/dbt_platform_helper/providers/aws/sso_auth.py +61 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/config.py +2 -1
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/config_validator.py +15 -13
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/io.py +2 -2
- dbt_platform_helper-13.3.0/dbt_platform_helper/providers/parameter_store.py +47 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/platform_config_schema.py +17 -0
- dbt_platform_helper-13.3.0/dbt_platform_helper/providers/semantic_version.py +76 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/terraform_manifest.py +1 -0
- dbt_platform_helper-13.3.0/dbt_platform_helper/providers/version.py +136 -0
- dbt_platform_helper-13.2.0/dbt_platform_helper/providers/semantic_version.py → dbt_platform_helper-13.3.0/dbt_platform_helper/providers/version_status.py +1 -70
- dbt_platform_helper-13.3.0/dbt_platform_helper/utils/__init__.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/utils/aws.py +0 -141
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/utils/git.py +3 -1
- dbt_platform_helper-13.3.0/dbt_platform_helper/utils/tool_versioning.py +12 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/platform_helper.py +1 -1
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/pyproject.toml +2 -3
- dbt_platform_helper-13.2.0/dbt_platform_helper/commands/config.py +0 -340
- dbt_platform_helper-13.2.0/dbt_platform_helper/providers/version.py +0 -78
- dbt_platform_helper-13.2.0/dbt_platform_helper/templates/svc/manifest-backend.yml +0 -69
- dbt_platform_helper-13.2.0/dbt_platform_helper/templates/svc/manifest-public.yml +0 -109
- dbt_platform_helper-13.2.0/dbt_platform_helper/utils/cloudfoundry.py +0 -14
- dbt_platform_helper-13.2.0/dbt_platform_helper/utils/files.py +0 -53
- dbt_platform_helper-13.2.0/dbt_platform_helper/utils/manifests.py +0 -18
- dbt_platform_helper-13.2.0/dbt_platform_helper/utils/tool_versioning.py +0 -96
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/LICENSE +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/COMMANDS.md +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/README.md +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/__init__.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/addon-plans.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/__init__.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/application.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/conduit.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/generate.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/notify.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/pipeline.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/secrets.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/version.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/constants.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/default-extensions.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/__init__.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/conduit.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/copilot_environment.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/database_copy.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/maintenance_page.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/pipelines.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/terraform_environment.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/jinja2_tags.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/platform_exception.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/__init__.py +0 -0
- {dbt_platform_helper-13.2.0/dbt_platform_helper/utils → dbt_platform_helper-13.3.0/dbt_platform_helper/providers/aws}/__init__.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/aws/interfaces.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/aws/opensearch.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/aws/redis.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/cache.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/cloudformation.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/copilot.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/ecr.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/ecs.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/files.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/kms.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/load_balancers.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/secrets.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/validation.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/vpc.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/providers/yaml_file.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/.copilot/config.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/.copilot/image_build_run.sh +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/.copilot/phases/build.sh +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/.copilot/phases/install.sh +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/.copilot/phases/post_build.sh +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/.copilot/phases/pre_build.sh +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/COMMANDS.md.jinja +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/addon-instructions.txt +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/addons/README.md +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/addons/svc/appconfig-ipfilter.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/addons/svc/prometheus-policy.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/addons/svc/s3-cross-account-policy.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/addons/svc/s3-policy.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/addons/svc/subscription-filter.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/ci-codebuild-role-policy.json +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/create-codebuild-role.json +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/custom-codebuild-role-policy.json +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/env/manifest.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/env/terraform-overrides/cfn.patches.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/environment-pipelines/main.tf +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/svc/maintenance_pages/default.html +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/svc/maintenance_pages/dmas-migration.html +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/svc/maintenance_pages/migration.html +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/templates/svc/overrides/cfn.patches.yml +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/utils/application.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/utils/arn_parser.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/utils/click.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/utils/messages.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/utils/template.py +0 -0
- {dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/utils/validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dbt-platform-helper
|
|
3
|
-
Version: 13.
|
|
3
|
+
Version: 13.3.0
|
|
4
4
|
Summary: Set of tools to help transfer applications/services from GOV.UK PaaS to DBT PaaS augmenting AWS Copilot.
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Department for Business and Trade Platform Team
|
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
-
Requires-Dist: Jinja2 (==3.1.
|
|
15
|
+
Requires-Dist: Jinja2 (==3.1.6)
|
|
16
16
|
Requires-Dist: PyYAML (==6.0.1)
|
|
17
17
|
Requires-Dist: aiohttp (>=3.8.4,<4.0.0)
|
|
18
18
|
Requires-Dist: boto3 (>=1.28.24,<2.0.0)
|
{dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/codebase.py
RENAMED
|
@@ -4,6 +4,8 @@ from dbt_platform_helper.domain.codebase import Codebase
|
|
|
4
4
|
from dbt_platform_helper.domain.versioning import PlatformHelperVersioning
|
|
5
5
|
from dbt_platform_helper.platform_exception import PlatformException
|
|
6
6
|
from dbt_platform_helper.providers.io import ClickIOProvider
|
|
7
|
+
from dbt_platform_helper.providers.parameter_store import ParameterStore
|
|
8
|
+
from dbt_platform_helper.utils.aws import get_aws_session_or_abort
|
|
7
9
|
from dbt_platform_helper.utils.click import ClickDocOptGroup
|
|
8
10
|
|
|
9
11
|
|
|
@@ -17,7 +19,7 @@ def codebase():
|
|
|
17
19
|
def prepare():
|
|
18
20
|
"""Sets up an application codebase for use within a DBT platform project."""
|
|
19
21
|
try:
|
|
20
|
-
Codebase().prepare()
|
|
22
|
+
Codebase(ParameterStore(get_aws_session_or_abort().client("ssm"))).prepare()
|
|
21
23
|
except PlatformException as err:
|
|
22
24
|
ClickIOProvider().abort_with_error(str(err))
|
|
23
25
|
|
|
@@ -33,7 +35,7 @@ def prepare():
|
|
|
33
35
|
def list(app, with_images):
|
|
34
36
|
"""List available codebases for the application."""
|
|
35
37
|
try:
|
|
36
|
-
Codebase().list(app, with_images)
|
|
38
|
+
Codebase(ParameterStore(get_aws_session_or_abort().client("ssm"))).list(app, with_images)
|
|
37
39
|
except PlatformException as err:
|
|
38
40
|
ClickIOProvider().abort_with_error(str(err))
|
|
39
41
|
|
|
@@ -49,7 +51,9 @@ def list(app, with_images):
|
|
|
49
51
|
def build(app, codebase, commit):
|
|
50
52
|
"""Trigger a CodePipeline pipeline based build."""
|
|
51
53
|
try:
|
|
52
|
-
Codebase().build(
|
|
54
|
+
Codebase(ParameterStore(get_aws_session_or_abort().client("ssm"))).build(
|
|
55
|
+
app, codebase, commit
|
|
56
|
+
)
|
|
53
57
|
except PlatformException as err:
|
|
54
58
|
ClickIOProvider().abort_with_error(str(err))
|
|
55
59
|
|
|
@@ -65,6 +69,8 @@ def build(app, codebase, commit):
|
|
|
65
69
|
@click.option("--commit", help="GitHub commit hash", required=True)
|
|
66
70
|
def deploy(app, env, codebase, commit):
|
|
67
71
|
try:
|
|
68
|
-
Codebase().deploy(
|
|
72
|
+
Codebase(ParameterStore(get_aws_session_or_abort().client("ssm"))).deploy(
|
|
73
|
+
app, env, codebase, commit
|
|
74
|
+
)
|
|
69
75
|
except PlatformException as err:
|
|
70
76
|
ClickIOProvider().abort_with_error(str(err))
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from dbt_platform_helper.domain.config import Config
|
|
4
|
+
from dbt_platform_helper.platform_exception import PlatformException
|
|
5
|
+
from dbt_platform_helper.providers.aws.sso_auth import SSOAuthProvider
|
|
6
|
+
from dbt_platform_helper.providers.io import ClickIOProvider
|
|
7
|
+
from dbt_platform_helper.utils.aws import get_aws_session_or_abort
|
|
8
|
+
from dbt_platform_helper.utils.click import ClickDocOptGroup
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@click.group(cls=ClickDocOptGroup)
|
|
12
|
+
def config():
|
|
13
|
+
"""Perform actions on configuration files."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@config.command()
|
|
17
|
+
def validate():
|
|
18
|
+
"""Validate deployment or application configuration."""
|
|
19
|
+
try:
|
|
20
|
+
Config().validate()
|
|
21
|
+
except PlatformException as err:
|
|
22
|
+
ClickIOProvider().abort_with_error(str(err))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@config.command()
|
|
26
|
+
@click.option("--file-path", "-fp", default="~/.aws/config")
|
|
27
|
+
def aws(file_path):
|
|
28
|
+
"""
|
|
29
|
+
Writes a local config file containing all the AWS profiles to which the
|
|
30
|
+
logged in user has access.
|
|
31
|
+
|
|
32
|
+
If no `--file-path` is specified, defaults to `~/.aws/config`.
|
|
33
|
+
"""
|
|
34
|
+
try:
|
|
35
|
+
session = get_aws_session_or_abort()
|
|
36
|
+
Config(sso=SSOAuthProvider(session)).generate_aws(file_path)
|
|
37
|
+
except PlatformException as err:
|
|
38
|
+
ClickIOProvider().abort_with_error(str(err))
|
{dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/copilot.py
RENAMED
|
@@ -10,13 +10,10 @@ from dbt_platform_helper.providers.config_validator import ConfigValidator
|
|
|
10
10
|
from dbt_platform_helper.providers.files import FileProvider
|
|
11
11
|
from dbt_platform_helper.providers.io import ClickIOProvider
|
|
12
12
|
from dbt_platform_helper.providers.kms import KMSProvider
|
|
13
|
+
from dbt_platform_helper.providers.parameter_store import ParameterStore
|
|
13
14
|
from dbt_platform_helper.utils.aws import get_aws_session_or_abort
|
|
14
15
|
from dbt_platform_helper.utils.click import ClickDocOptGroup
|
|
15
16
|
|
|
16
|
-
# TODOs
|
|
17
|
-
# Figure out a pattern for copilot templating and the new copilot domain - probably a lot of overlap here that really belongs in the copilottemplating domain instead (atleast whatever is concerned with "templating")
|
|
18
|
-
# Check for E2E test coverage.
|
|
19
|
-
|
|
20
17
|
|
|
21
18
|
@click.group(chain=True, cls=ClickDocOptGroup)
|
|
22
19
|
def copilot():
|
|
@@ -28,8 +25,15 @@ def make_addons():
|
|
|
28
25
|
"""Generate addons CloudFormation for each environment."""
|
|
29
26
|
try:
|
|
30
27
|
session = get_aws_session_or_abort()
|
|
28
|
+
parameter_provider = ParameterStore(session.client("ssm"))
|
|
31
29
|
config_provider = ConfigProvider(ConfigValidator())
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
Copilot(
|
|
31
|
+
config_provider,
|
|
32
|
+
parameter_provider,
|
|
33
|
+
FileProvider(),
|
|
34
|
+
CopilotTemplating(),
|
|
35
|
+
KMSProvider,
|
|
36
|
+
session,
|
|
37
|
+
).make_addons()
|
|
34
38
|
except Exception as err:
|
|
35
39
|
ClickIOProvider().abort_with_error(str(err))
|
{dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/commands/database.py
RENAMED
|
@@ -2,6 +2,8 @@ import click
|
|
|
2
2
|
|
|
3
3
|
from dbt_platform_helper.commands.environment import AVAILABLE_TEMPLATES
|
|
4
4
|
from dbt_platform_helper.domain.database_copy import DatabaseCopy
|
|
5
|
+
from dbt_platform_helper.platform_exception import PlatformException
|
|
6
|
+
from dbt_platform_helper.providers.io import ClickIOProvider
|
|
5
7
|
from dbt_platform_helper.utils.click import ClickDocOptGroup
|
|
6
8
|
|
|
7
9
|
|
|
@@ -38,9 +40,11 @@ def database():
|
|
|
38
40
|
)
|
|
39
41
|
def dump(app, from_env, database, from_vpc, filename):
|
|
40
42
|
"""Dump a database into an S3 bucket."""
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
try:
|
|
44
|
+
data_copy = DatabaseCopy(app, database)
|
|
45
|
+
data_copy.dump(from_env, from_vpc, filename)
|
|
46
|
+
except PlatformException as err:
|
|
47
|
+
ClickIOProvider().abort_with_error(str(err))
|
|
44
48
|
|
|
45
49
|
|
|
46
50
|
@database.command(name="load")
|
|
@@ -68,9 +72,11 @@ def dump(app, from_env, database, from_vpc, filename):
|
|
|
68
72
|
)
|
|
69
73
|
def load(app, to_env, database, to_vpc, auto_approve, filename):
|
|
70
74
|
"""Load a database from an S3 bucket."""
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
try:
|
|
76
|
+
data_copy = DatabaseCopy(app, database, auto_approve)
|
|
77
|
+
data_copy.load(to_env, to_vpc, filename)
|
|
78
|
+
except PlatformException as err:
|
|
79
|
+
ClickIOProvider().abort_with_error(str(err))
|
|
74
80
|
|
|
75
81
|
|
|
76
82
|
@database.command(name="copy")
|
|
@@ -120,6 +126,8 @@ def copy(
|
|
|
120
126
|
no_maintenance_page,
|
|
121
127
|
):
|
|
122
128
|
"""Copy a database between environments."""
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
try:
|
|
130
|
+
data_copy = DatabaseCopy(app, database, auto_approve)
|
|
131
|
+
data_copy.copy(from_env, to_env, from_vpc, to_vpc, svc, template, no_maintenance_page)
|
|
132
|
+
except PlatformException as err:
|
|
133
|
+
ClickIOProvider().abort_with_error(str(err))
|
|
@@ -94,9 +94,8 @@ def generate(name):
|
|
|
94
94
|
def generate_terraform(name, terraform_platform_modules_version):
|
|
95
95
|
click_io = ClickIOProvider()
|
|
96
96
|
try:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
config_provider = ConfigProvider(ConfigValidator())
|
|
97
|
+
session = get_aws_session_or_abort()
|
|
98
|
+
config_provider = ConfigProvider(ConfigValidator(session=session))
|
|
100
99
|
TerraformEnvironment(config_provider).generate(name, terraform_platform_modules_version)
|
|
101
100
|
except PlatformException as err:
|
|
102
101
|
click_io.abort_with_error(str(err))
|
{dbt_platform_helper-13.2.0 → dbt_platform_helper-13.3.0}/dbt_platform_helper/domain/codebase.py
RENAMED
|
@@ -11,6 +11,7 @@ from boto3 import Session
|
|
|
11
11
|
from dbt_platform_helper.platform_exception import PlatformException
|
|
12
12
|
from dbt_platform_helper.providers.files import FileProvider
|
|
13
13
|
from dbt_platform_helper.providers.io import ClickIOProvider
|
|
14
|
+
from dbt_platform_helper.providers.parameter_store import ParameterStore
|
|
14
15
|
from dbt_platform_helper.utils.application import Application
|
|
15
16
|
from dbt_platform_helper.utils.application import (
|
|
16
17
|
ApplicationEnvironmentNotFoundException,
|
|
@@ -32,6 +33,7 @@ from dbt_platform_helper.utils.template import setup_templates
|
|
|
32
33
|
class Codebase:
|
|
33
34
|
def __init__(
|
|
34
35
|
self,
|
|
36
|
+
parameter_provider: ParameterStore,
|
|
35
37
|
io: ClickIOProvider = ClickIOProvider(),
|
|
36
38
|
load_application: Callable[[str], Application] = load_application,
|
|
37
39
|
get_aws_session_or_abort: Callable[[str], Session] = get_aws_session_or_abort,
|
|
@@ -50,6 +52,7 @@ class Codebase:
|
|
|
50
52
|
check_if_commit_exists: Callable[[str], str] = check_if_commit_exists,
|
|
51
53
|
run_subprocess: Callable[[str], str] = subprocess.run,
|
|
52
54
|
):
|
|
55
|
+
self.parameter_provider = parameter_provider
|
|
53
56
|
self.io = io
|
|
54
57
|
self.load_application = load_application
|
|
55
58
|
self.get_aws_session_or_abort = get_aws_session_or_abort
|
|
@@ -190,9 +193,8 @@ class Codebase:
|
|
|
190
193
|
"""List available codebases for the application."""
|
|
191
194
|
session = self.get_aws_session_or_abort()
|
|
192
195
|
application = self.load_application(app, session)
|
|
193
|
-
ssm_client = session.client("ssm")
|
|
194
196
|
ecr_client = session.client("ecr")
|
|
195
|
-
codebases = self.__get_codebases(application,
|
|
197
|
+
codebases = self.__get_codebases(application, session.client("ssm"))
|
|
196
198
|
|
|
197
199
|
self.io.info("The following codebases are available:")
|
|
198
200
|
|
|
@@ -209,11 +211,9 @@ class Codebase:
|
|
|
209
211
|
self.io.info("")
|
|
210
212
|
|
|
211
213
|
def __get_codebases(self, application, ssm_client):
|
|
212
|
-
parameters =
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
)["Parameters"]
|
|
216
|
-
|
|
214
|
+
parameters = self.parameter_provider.get_ssm_parameters_by_path(
|
|
215
|
+
f"/copilot/applications/{application.name}/codebases"
|
|
216
|
+
)
|
|
217
217
|
codebases = [json.loads(p["Value"]) for p in parameters]
|
|
218
218
|
|
|
219
219
|
if not codebases:
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import webbrowser
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Dict
|
|
6
|
+
|
|
7
|
+
from prettytable import PrettyTable
|
|
8
|
+
|
|
9
|
+
from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE
|
|
10
|
+
from dbt_platform_helper.domain.versioning import AWSVersioning
|
|
11
|
+
from dbt_platform_helper.domain.versioning import CopilotVersioning
|
|
12
|
+
from dbt_platform_helper.domain.versioning import PlatformHelperVersioning
|
|
13
|
+
from dbt_platform_helper.platform_exception import PlatformException
|
|
14
|
+
from dbt_platform_helper.providers.aws.sso_auth import SSOAuthProvider
|
|
15
|
+
from dbt_platform_helper.providers.io import ClickIOProvider
|
|
16
|
+
from dbt_platform_helper.providers.semantic_version import (
|
|
17
|
+
IncompatibleMajorVersionException,
|
|
18
|
+
)
|
|
19
|
+
from dbt_platform_helper.providers.semantic_version import SemanticVersion
|
|
20
|
+
from dbt_platform_helper.providers.validation import ValidationException
|
|
21
|
+
from dbt_platform_helper.providers.version_status import PlatformHelperVersionStatus
|
|
22
|
+
from dbt_platform_helper.providers.version_status import VersionStatus
|
|
23
|
+
|
|
24
|
+
yes = "\033[92m✔\033[0m"
|
|
25
|
+
no = "\033[91m✖\033[0m"
|
|
26
|
+
maybe = "\033[93m?\033[0m"
|
|
27
|
+
|
|
28
|
+
RECOMMENDATIONS = {
|
|
29
|
+
"dbt-platform-helper-upgrade": (
|
|
30
|
+
"Upgrade dbt-platform-helper to version {version} `pip install "
|
|
31
|
+
"--upgrade dbt-platform-helper=={version}`."
|
|
32
|
+
),
|
|
33
|
+
"dbt-platform-helper-upgrade-note": (
|
|
34
|
+
"Post upgrade, run `platform-helper copilot make-addons` to " "update your addon templates."
|
|
35
|
+
),
|
|
36
|
+
"generic-tool-upgrade": "Upgrade {tool} to version {version}.",
|
|
37
|
+
"install-copilot": "Install AWS Copilot https://aws.github.io/copilot-cli/",
|
|
38
|
+
"install-aws": "Install AWS CLI https://aws.amazon.com/cli/",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
AWS_CONFIG = """
|
|
42
|
+
#
|
|
43
|
+
# uktrade
|
|
44
|
+
#
|
|
45
|
+
|
|
46
|
+
[sso-session uktrade]
|
|
47
|
+
sso_start_url = https://uktrade.awsapps.com/start#/
|
|
48
|
+
sso_region = eu-west-2
|
|
49
|
+
sso_registration_scopes = sso:account:access
|
|
50
|
+
|
|
51
|
+
[default]
|
|
52
|
+
sso_session = uktrade
|
|
53
|
+
region = eu-west-2
|
|
54
|
+
output = json
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class NoDeploymentRepoConfigException(PlatformException):
|
|
60
|
+
def __init__(self):
|
|
61
|
+
super().__init__("Could not find a deployment repository, no checks to run.")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# TODO move to generic location so it can be reused
|
|
65
|
+
class NoPlatformConfigException(PlatformException):
|
|
66
|
+
def __init__(self):
|
|
67
|
+
super().__init__(
|
|
68
|
+
f"`platform-config.yml` is missing. "
|
|
69
|
+
"Please check it exists and you are in the root directory of your deployment project."
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class Config:
|
|
74
|
+
|
|
75
|
+
def __init__(
|
|
76
|
+
self,
|
|
77
|
+
io: ClickIOProvider = ClickIOProvider(),
|
|
78
|
+
platform_helper_versioning: PlatformHelperVersioning = PlatformHelperVersioning(),
|
|
79
|
+
aws_versioning: AWSVersioning = AWSVersioning(),
|
|
80
|
+
copilot_versioning: CopilotVersioning = CopilotVersioning(),
|
|
81
|
+
sso: SSOAuthProvider = None,
|
|
82
|
+
):
|
|
83
|
+
self.oidc_app = None
|
|
84
|
+
self.io = io
|
|
85
|
+
self.platform_helper_versioning = platform_helper_versioning
|
|
86
|
+
self.aws_versioning = aws_versioning
|
|
87
|
+
self.copilot_versioning = copilot_versioning
|
|
88
|
+
self.sso = sso or SSOAuthProvider()
|
|
89
|
+
self.SSO_START_URL = "https://uktrade.awsapps.com/start"
|
|
90
|
+
|
|
91
|
+
def validate(self):
|
|
92
|
+
if not Path("copilot").exists():
|
|
93
|
+
raise NoDeploymentRepoConfigException()
|
|
94
|
+
if not Path(PLATFORM_CONFIG_FILE).exists():
|
|
95
|
+
raise NoPlatformConfigException()
|
|
96
|
+
|
|
97
|
+
self.io.debug("\nDetected a deployment repository\n")
|
|
98
|
+
platform_helper_version_status = self.platform_helper_versioning._get_version_status(
|
|
99
|
+
include_project_versions=True
|
|
100
|
+
)
|
|
101
|
+
self.io.process_messages(platform_helper_version_status.validate())
|
|
102
|
+
aws_version_status = self.aws_versioning.get_version_status()
|
|
103
|
+
copilot_version_status = self.copilot_versioning.get_version_status()
|
|
104
|
+
|
|
105
|
+
self._check_tool_versions(
|
|
106
|
+
platform_helper_version_status, aws_version_status, copilot_version_status
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
compatible = self._check_addon_versions(platform_helper_version_status)
|
|
110
|
+
|
|
111
|
+
exit(0 if compatible else 1)
|
|
112
|
+
|
|
113
|
+
def generate_aws(self, file_path):
|
|
114
|
+
self.oidc_app = self._create_oidc_application()
|
|
115
|
+
verification_url, device_code = self._get_device_code(self.oidc_app)
|
|
116
|
+
|
|
117
|
+
if self.io.confirm(
|
|
118
|
+
"You are about to be redirected to a verification page. You will need to complete sign-in before returning to the command line. Do you want to continue?",
|
|
119
|
+
):
|
|
120
|
+
webbrowser.open(verification_url)
|
|
121
|
+
|
|
122
|
+
if self.io.confirm(
|
|
123
|
+
"Have you completed the sign-in process in your browser?",
|
|
124
|
+
):
|
|
125
|
+
access_token = self.sso.create_access_token(
|
|
126
|
+
client_id=self.oidc_app[0],
|
|
127
|
+
client_secret=self.oidc_app[1],
|
|
128
|
+
device_code=device_code,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
aws_config_path = os.path.expanduser(file_path)
|
|
132
|
+
|
|
133
|
+
if self.io.confirm(
|
|
134
|
+
f"This command is destructive and will overwrite file contents at {file_path}. Are you sure you want to continue?"
|
|
135
|
+
):
|
|
136
|
+
with open(aws_config_path, "w") as config_file:
|
|
137
|
+
config_file.write(AWS_CONFIG)
|
|
138
|
+
|
|
139
|
+
for account in self._retrieve_aws_accounts(access_token):
|
|
140
|
+
config_file.write(f"[profile {account['accountName']}]\n")
|
|
141
|
+
config_file.write("sso_session = uktrade\n")
|
|
142
|
+
config_file.write(f"sso_account_id = {account['accountId']}\n")
|
|
143
|
+
config_file.write("sso_role_name = AdministratorAccess\n")
|
|
144
|
+
config_file.write("region = eu-west-2\n")
|
|
145
|
+
config_file.write("output = json\n")
|
|
146
|
+
config_file.write("\n")
|
|
147
|
+
|
|
148
|
+
def _create_oidc_application(self):
|
|
149
|
+
self.io.debug("Creating temporary AWS SSO OIDC application")
|
|
150
|
+
client_id, client_secret = self.sso.register(
|
|
151
|
+
client_name="platform-helper",
|
|
152
|
+
client_type="public",
|
|
153
|
+
)
|
|
154
|
+
return client_id, client_secret
|
|
155
|
+
|
|
156
|
+
def _get_device_code(self, oidc_application):
|
|
157
|
+
self.io.debug("Initiating device code flow")
|
|
158
|
+
url, device_code = self.sso.start_device_authorization(
|
|
159
|
+
client_id=oidc_application[0],
|
|
160
|
+
client_secret=oidc_application[1],
|
|
161
|
+
start_url=self.SSO_START_URL,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return url, device_code
|
|
165
|
+
|
|
166
|
+
def _retrieve_aws_accounts(self, aws_sso_token):
|
|
167
|
+
accounts_list = self.sso.list_accounts(
|
|
168
|
+
access_token=aws_sso_token,
|
|
169
|
+
max_results=100,
|
|
170
|
+
)
|
|
171
|
+
return accounts_list
|
|
172
|
+
|
|
173
|
+
def _add_version_status_row(
|
|
174
|
+
self, table: PrettyTable, header: str, version_status: VersionStatus
|
|
175
|
+
):
|
|
176
|
+
table.add_row(
|
|
177
|
+
[
|
|
178
|
+
header,
|
|
179
|
+
str(version_status.installed),
|
|
180
|
+
str(version_status.latest),
|
|
181
|
+
no if version_status.is_outdated() else yes,
|
|
182
|
+
]
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
def _check_tool_versions(
|
|
186
|
+
self,
|
|
187
|
+
platform_helper_version_status: PlatformHelperVersionStatus,
|
|
188
|
+
aws_version_status: VersionStatus,
|
|
189
|
+
copilot_version_status: VersionStatus,
|
|
190
|
+
):
|
|
191
|
+
self.io.debug("Checking tooling versions...")
|
|
192
|
+
|
|
193
|
+
recommendations = {}
|
|
194
|
+
|
|
195
|
+
if copilot_version_status.installed is None:
|
|
196
|
+
recommendations["install-copilot"] = RECOMMENDATIONS["install-copilot"]
|
|
197
|
+
|
|
198
|
+
if aws_version_status.installed is None:
|
|
199
|
+
recommendations["install-aws"] = RECOMMENDATIONS["install-aws"]
|
|
200
|
+
|
|
201
|
+
tool_versions_table = PrettyTable()
|
|
202
|
+
tool_versions_table.field_names = [
|
|
203
|
+
"Tool",
|
|
204
|
+
"Local version",
|
|
205
|
+
"Released version",
|
|
206
|
+
"Running latest?",
|
|
207
|
+
]
|
|
208
|
+
tool_versions_table.align["Tool"] = "l"
|
|
209
|
+
|
|
210
|
+
self._add_version_status_row(tool_versions_table, "aws", aws_version_status)
|
|
211
|
+
self._add_version_status_row(tool_versions_table, "copilot", copilot_version_status)
|
|
212
|
+
self._add_version_status_row(
|
|
213
|
+
tool_versions_table, "dbt-platform-helper", platform_helper_version_status
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
self.io.info(tool_versions_table)
|
|
217
|
+
|
|
218
|
+
if aws_version_status.is_outdated() and "install-aws" not in recommendations:
|
|
219
|
+
recommendations["aws-upgrade"] = RECOMMENDATIONS["generic-tool-upgrade"].format(
|
|
220
|
+
tool="AWS CLI",
|
|
221
|
+
version=str(aws_version_status.latest),
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
if copilot_version_status.is_outdated() and "install-copilot" not in recommendations:
|
|
225
|
+
recommendations["copilot-upgrade"] = RECOMMENDATIONS["generic-tool-upgrade"].format(
|
|
226
|
+
tool="AWS Copilot",
|
|
227
|
+
version=str(copilot_version_status.latest),
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
if platform_helper_version_status.is_outdated():
|
|
231
|
+
recommendations["dbt-platform-helper-upgrade"] = RECOMMENDATIONS[
|
|
232
|
+
"dbt-platform-helper-upgrade"
|
|
233
|
+
].format(version=str(platform_helper_version_status.latest))
|
|
234
|
+
recommendations["dbt-platform-helper-upgrade-note"] = RECOMMENDATIONS[
|
|
235
|
+
"dbt-platform-helper-upgrade-note"
|
|
236
|
+
]
|
|
237
|
+
|
|
238
|
+
self._render_recommendations(recommendations)
|
|
239
|
+
|
|
240
|
+
def _check_addon_versions(self, platform_helper_versions: PlatformHelperVersionStatus) -> bool:
|
|
241
|
+
|
|
242
|
+
self.io.debug("Checking addons templates versions...")
|
|
243
|
+
|
|
244
|
+
compatible = True
|
|
245
|
+
recommendations = {}
|
|
246
|
+
|
|
247
|
+
local_version = platform_helper_versions.installed
|
|
248
|
+
latest_release = platform_helper_versions.latest
|
|
249
|
+
|
|
250
|
+
addons_templates_table = PrettyTable()
|
|
251
|
+
addons_templates_table.field_names = [
|
|
252
|
+
"Addons Template File",
|
|
253
|
+
"Generated with",
|
|
254
|
+
"Compatible with local?",
|
|
255
|
+
"Compatible with latest?",
|
|
256
|
+
]
|
|
257
|
+
addons_templates_table.align["Addons Template File"] = "l"
|
|
258
|
+
|
|
259
|
+
addons_templates = list(Path("./copilot").glob("**/addons/*"))
|
|
260
|
+
# Sort by template file path
|
|
261
|
+
addons_templates.sort(key=lambda e: str(e))
|
|
262
|
+
# Bring environment addons to the top
|
|
263
|
+
addons_templates.sort(key=lambda e: "environments/" not in str(e))
|
|
264
|
+
|
|
265
|
+
for template_file in addons_templates:
|
|
266
|
+
generated_with_version = maybe
|
|
267
|
+
local_compatible_symbol = yes
|
|
268
|
+
latest_compatible_symbol = yes
|
|
269
|
+
|
|
270
|
+
generated_with_version = None
|
|
271
|
+
|
|
272
|
+
try:
|
|
273
|
+
generated_with_version = self.__get_template_generated_with_version(
|
|
274
|
+
str(template_file.resolve())
|
|
275
|
+
)
|
|
276
|
+
except ValidationException:
|
|
277
|
+
local_compatible_symbol = maybe
|
|
278
|
+
compatible = False
|
|
279
|
+
recommendations["dbt-platform-helper-upgrade"] = RECOMMENDATIONS[
|
|
280
|
+
"dbt-platform-helper-upgrade"
|
|
281
|
+
].format(version=latest_release)
|
|
282
|
+
recommendations["dbt-platform-helper-upgrade-note"] = RECOMMENDATIONS[
|
|
283
|
+
"dbt-platform-helper-upgrade-note"
|
|
284
|
+
]
|
|
285
|
+
|
|
286
|
+
try:
|
|
287
|
+
local_version.validate_compatibility_with(generated_with_version)
|
|
288
|
+
except IncompatibleMajorVersionException:
|
|
289
|
+
local_compatible_symbol = no
|
|
290
|
+
compatible = False
|
|
291
|
+
recommendations["dbt-platform-helper-upgrade"] = RECOMMENDATIONS[
|
|
292
|
+
"dbt-platform-helper-upgrade"
|
|
293
|
+
].format(version=latest_release)
|
|
294
|
+
recommendations["dbt-platform-helper-upgrade-note"] = RECOMMENDATIONS[
|
|
295
|
+
"dbt-platform-helper-upgrade-note"
|
|
296
|
+
]
|
|
297
|
+
except ValidationException:
|
|
298
|
+
local_compatible_symbol = maybe
|
|
299
|
+
compatible = False
|
|
300
|
+
|
|
301
|
+
try:
|
|
302
|
+
latest_release.validate_compatibility_with(generated_with_version)
|
|
303
|
+
except IncompatibleMajorVersionException:
|
|
304
|
+
latest_compatible_symbol = no
|
|
305
|
+
compatible = False
|
|
306
|
+
except ValidationException:
|
|
307
|
+
latest_compatible_symbol = maybe
|
|
308
|
+
compatible = False
|
|
309
|
+
|
|
310
|
+
addons_templates_table.add_row(
|
|
311
|
+
[
|
|
312
|
+
template_file.relative_to("."),
|
|
313
|
+
(maybe if latest_compatible_symbol is maybe else str(generated_with_version)),
|
|
314
|
+
local_compatible_symbol,
|
|
315
|
+
latest_compatible_symbol,
|
|
316
|
+
]
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
self.io.info(addons_templates_table)
|
|
320
|
+
self._render_recommendations(recommendations)
|
|
321
|
+
|
|
322
|
+
return compatible
|
|
323
|
+
|
|
324
|
+
def _render_recommendations(self, recommendations: Dict[str, str]):
|
|
325
|
+
if recommendations:
|
|
326
|
+
self.io.info("\nRecommendations:\n", bold=True)
|
|
327
|
+
|
|
328
|
+
for name, recommendation in recommendations.items():
|
|
329
|
+
if name.endswith("-note"):
|
|
330
|
+
continue
|
|
331
|
+
self.io.info(f" - {recommendation}")
|
|
332
|
+
if recommendations.get(f"{name}-note", False):
|
|
333
|
+
self.io.info(f" {recommendations.get(f'{name}-note')}")
|
|
334
|
+
|
|
335
|
+
self.io.info("")
|
|
336
|
+
|
|
337
|
+
def __get_template_generated_with_version(self, template_file_path: str) -> SemanticVersion:
|
|
338
|
+
try:
|
|
339
|
+
template_contents = Path(template_file_path).read_text()
|
|
340
|
+
template_version = re.search(
|
|
341
|
+
r"# Generated by platform-helper ([v.\-0-9]+)", template_contents
|
|
342
|
+
).group(1)
|
|
343
|
+
return SemanticVersion.from_string(template_version)
|
|
344
|
+
except (IndexError, AttributeError):
|
|
345
|
+
raise ValidationException(f"Template {template_file_path} has no version information")
|