dbt-platform-helper 12.3.0__py3-none-any.whl → 12.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dbt-platform-helper might be problematic. Click here for more details.

Files changed (32) hide show
  1. dbt_platform_helper/COMMANDS.md +6 -1
  2. dbt_platform_helper/commands/codebase.py +1 -1
  3. dbt_platform_helper/commands/conduit.py +2 -2
  4. dbt_platform_helper/commands/config.py +4 -4
  5. dbt_platform_helper/commands/copilot.py +13 -15
  6. dbt_platform_helper/commands/database.py +17 -4
  7. dbt_platform_helper/commands/environment.py +3 -2
  8. dbt_platform_helper/domain/codebase.py +23 -5
  9. dbt_platform_helper/domain/conduit.py +0 -6
  10. dbt_platform_helper/domain/database_copy.py +14 -13
  11. dbt_platform_helper/domain/maintenance_page.py +8 -8
  12. dbt_platform_helper/platform_exception.py +5 -0
  13. dbt_platform_helper/providers/aws.py +32 -0
  14. dbt_platform_helper/providers/cloudformation.py +8 -1
  15. dbt_platform_helper/providers/copilot.py +2 -5
  16. dbt_platform_helper/providers/ecs.py +19 -4
  17. dbt_platform_helper/providers/load_balancers.py +11 -5
  18. dbt_platform_helper/providers/secrets.py +51 -10
  19. dbt_platform_helper/providers/validation.py +19 -0
  20. dbt_platform_helper/utils/application.py +14 -2
  21. dbt_platform_helper/utils/arn_parser.py +1 -1
  22. dbt_platform_helper/utils/aws.py +13 -10
  23. dbt_platform_helper/utils/git.py +2 -2
  24. dbt_platform_helper/utils/validation.py +18 -4
  25. dbt_platform_helper/utils/versioning.py +8 -8
  26. {dbt_platform_helper-12.3.0.dist-info → dbt_platform_helper-12.4.0.dist-info}/METADATA +1 -1
  27. {dbt_platform_helper-12.3.0.dist-info → dbt_platform_helper-12.4.0.dist-info}/RECORD +30 -29
  28. dbt_platform_helper/addons-template-map.yml +0 -29
  29. dbt_platform_helper/exceptions.py +0 -147
  30. {dbt_platform_helper-12.3.0.dist-info → dbt_platform_helper-12.4.0.dist-info}/LICENSE +0 -0
  31. {dbt_platform_helper-12.3.0.dist-info → dbt_platform_helper-12.4.0.dist-info}/WHEEL +0 -0
  32. {dbt_platform_helper-12.3.0.dist-info → dbt_platform_helper-12.4.0.dist-info}/entry_points.txt +0 -0
@@ -765,6 +765,7 @@ platform-helper database (dump|load|copy)
765
765
  ```
766
766
  platform-helper database dump --from <from_env> --database <database>
767
767
  [--app <application>] [--from-vpc <from_vpc>]
768
+ [--filename <filename>]
768
769
  ```
769
770
 
770
771
  ## Options
@@ -777,6 +778,8 @@ platform-helper database dump --from <from_env> --database <database>
777
778
  - The name of the database you are dumping data from
778
779
  - `--from-vpc <text>`
779
780
  - The vpc the specified environment is running in. Required unless you are running the command from your deploy repo
781
+ - `--filename <text>`
782
+ - Specify a name for the database dump file. Recommended if the same dump database is being used for multiple load environments
780
783
  - `--help <boolean>` _Defaults to False._
781
784
  - Show this message and exit.
782
785
 
@@ -791,7 +794,7 @@ platform-helper database dump --from <from_env> --database <database>
791
794
  ```
792
795
  platform-helper database load --to <to_env> --database <database>
793
796
  [--app <application>] [--to-vpc <to_vpc>]
794
- [--auto-approve]
797
+ [--filename <filename>] [--auto-approve]
795
798
  ```
796
799
 
797
800
  ## Options
@@ -806,6 +809,8 @@ platform-helper database load --to <to_env> --database <database>
806
809
  - The vpc the specified environment is running in. Required unless you are running the command from your deploy repo
807
810
  - `--auto-approve <boolean>` _Defaults to False._
808
811
 
812
+ - `--filename <text>`
813
+ - Specify a name for the database dump file. Recommended if the same dump database is being used for multiple load environments
809
814
  - `--help <boolean>` _Defaults to False._
810
815
  - Show this message and exit.
811
816
 
@@ -1,7 +1,7 @@
1
1
  import click
2
2
 
3
3
  from dbt_platform_helper.domain.codebase import Codebase
4
- from dbt_platform_helper.exceptions import PlatformException
4
+ from dbt_platform_helper.platform_exception import PlatformException
5
5
  from dbt_platform_helper.utils.click import ClickDocOptGroup
6
6
  from dbt_platform_helper.utils.versioning import (
7
7
  check_platform_helper_version_needs_update,
@@ -1,7 +1,7 @@
1
1
  import click
2
2
 
3
3
  from dbt_platform_helper.domain.conduit import Conduit
4
- from dbt_platform_helper.exceptions import AWSException
4
+ from dbt_platform_helper.platform_exception import PlatformException
5
5
  from dbt_platform_helper.providers.cloudformation import CloudFormation
6
6
  from dbt_platform_helper.providers.ecs import ECS
7
7
  from dbt_platform_helper.providers.secrets import Secrets
@@ -53,6 +53,6 @@ def conduit(addon_name: str, app: str, env: str, access: str):
53
53
  Conduit(application, secrets_provider, cloudformation_provider, ecs_provider).start(
54
54
  env, addon_name, access
55
55
  )
56
- except AWSException as err:
56
+ except PlatformException as err:
57
57
  click.secho(str(err), fg="red")
58
58
  raise click.Abort
@@ -8,8 +8,8 @@ import botocore
8
8
  import click
9
9
  from prettytable import PrettyTable
10
10
 
11
- from dbt_platform_helper.exceptions import IncompatibleMajorVersion
12
- from dbt_platform_helper.exceptions import ValidationException
11
+ from dbt_platform_helper.providers.validation import IncompatibleMajorVersionException
12
+ from dbt_platform_helper.providers.validation import ValidationException
13
13
  from dbt_platform_helper.utils import versioning
14
14
  from dbt_platform_helper.utils.click import ClickDocOptGroup
15
15
  from dbt_platform_helper.utils.validation import config_file_check
@@ -110,7 +110,7 @@ def deployment():
110
110
  str(template_file.resolve())
111
111
  )
112
112
  versioning.validate_template_version(local_version, str(template_file.resolve()))
113
- except IncompatibleMajorVersion:
113
+ except IncompatibleMajorVersionException:
114
114
  local_compatible_symbol = no
115
115
  compatible = False
116
116
  recommendations["dbt-platform-helper-upgrade"] = RECOMMENDATIONS[
@@ -134,7 +134,7 @@ def deployment():
134
134
  str(template_file.resolve())
135
135
  )
136
136
  versioning.validate_template_version(latest_release, str(template_file.resolve()))
137
- except IncompatibleMajorVersion:
137
+ except IncompatibleMajorVersionException:
138
138
  latest_compatible_symbol = no
139
139
  compatible = False
140
140
  except ValidationException:
@@ -35,6 +35,14 @@ SERVICE_TYPES = [
35
35
  "Worker Service",
36
36
  ]
37
37
 
38
+ ADDON_TEMPLATE_MAP = {
39
+ "s3": ["addons/svc/s3-policy.yml"],
40
+ "s3-policy": ["addons/svc/s3-policy.yml"],
41
+ "appconfig-ipfilter": ["addons/svc/appconfig-ipfilter.yml"],
42
+ "subscription-filter": ["addons/svc/subscription-filter.yml"],
43
+ "prometheus-policy": ["addons/svc/prometheus-policy.yml"],
44
+ }
45
+
38
46
 
39
47
  def list_copilot_local_environments():
40
48
  return [
@@ -248,9 +256,6 @@ def make_addons():
248
256
 
249
257
  application_name = get_application_name()
250
258
 
251
- with open(PACKAGE_DIR / "addons-template-map.yml") as fd:
252
- addon_template_map = yaml.safe_load(fd)
253
-
254
259
  click.echo("\n>>> Generating Terraform compatible addons CloudFormation\n")
255
260
 
256
261
  env_path = Path(f"copilot/environments/")
@@ -270,11 +275,6 @@ def make_addons():
270
275
  print(f">>>>>>>>> {addon_name}")
271
276
  addon_type = addon_config.pop("type")
272
277
  environments = addon_config.pop("environments")
273
- if addon_template_map[addon_type].get("requires_addons_parameters", False):
274
- pass
275
- if addon_type in ["postgres"]:
276
- pass
277
-
278
278
  environment_addon_config = {
279
279
  "addon_type": addon_type,
280
280
  "environments": environments,
@@ -309,7 +309,6 @@ def make_addons():
309
309
  _generate_service_addons(
310
310
  addon_config,
311
311
  addon_name,
312
- addon_template_map,
313
312
  addon_type,
314
313
  output_dir,
315
314
  service_addon_config,
@@ -339,7 +338,6 @@ def _generate_env_overrides(output_dir):
339
338
  def _generate_service_addons(
340
339
  addon_config,
341
340
  addon_name,
342
- addon_template_map,
343
341
  addon_type,
344
342
  output_dir,
345
343
  service_addon_config,
@@ -347,8 +345,8 @@ def _generate_service_addons(
347
345
  log_destination_arns,
348
346
  ):
349
347
  # generate svc addons
350
- for addon in addon_template_map[addon_type].get("svc", []):
351
- template = templates.get_template(addon["template"])
348
+ for addon_template in ADDON_TEMPLATE_MAP.get(addon_type, []):
349
+ template = templates.get_template(addon_template)
352
350
 
353
351
  for svc in addon_config.get("services", []):
354
352
  service_path = Path(f"copilot/{svc}/addons/")
@@ -360,10 +358,10 @@ def _generate_service_addons(
360
358
  }
361
359
  )
362
360
 
363
- filename = addon.get("filename", f"{addon_name}.yml")
364
-
365
361
  (output_dir / service_path).mkdir(parents=True, exist_ok=True)
366
- click.echo(mkfile(output_dir, service_path / filename, contents, overwrite=True))
362
+ click.echo(
363
+ mkfile(output_dir, service_path / f"{addon_name}.yml", contents, overwrite=True)
364
+ )
367
365
 
368
366
 
369
367
  def _cleanup_old_files(config, output_dir, env_addons_path, env_overrides_path):
@@ -31,10 +31,16 @@ def database():
31
31
  type=str,
32
32
  help="The vpc the specified environment is running in. Required unless you are running the command from your deploy repo",
33
33
  )
34
- def dump(app, from_env, database, from_vpc):
34
+ @click.option(
35
+ "--filename",
36
+ type=str,
37
+ help="Specify a name for the database dump file. Recommended if the same dump database is being used for multiple load environments",
38
+ )
39
+ def dump(app, from_env, database, from_vpc, filename):
35
40
  """Dump a database into an S3 bucket."""
36
41
  data_copy = DatabaseCopy(app, database)
37
- data_copy.dump(from_env, from_vpc)
42
+ data_copy.dump(from_env, from_vpc, filename)
43
+ # Todo: Catch expected errors and output message
38
44
 
39
45
 
40
46
  @database.command(name="load")
@@ -55,10 +61,16 @@ def dump(app, from_env, database, from_vpc):
55
61
  help="The vpc the specified environment is running in. Required unless you are running the command from your deploy repo",
56
62
  )
57
63
  @click.option("--auto-approve/--no-auto-approve", default=False)
58
- def load(app, to_env, database, to_vpc, auto_approve):
64
+ @click.option(
65
+ "--filename",
66
+ type=str,
67
+ help="Specify a name for the database dump file. Recommended if the same dump database is being used for multiple load environments",
68
+ )
69
+ def load(app, to_env, database, to_vpc, auto_approve, filename):
59
70
  """Load a database from an S3 bucket."""
60
71
  data_copy = DatabaseCopy(app, database, auto_approve)
61
- data_copy.load(to_env, to_vpc)
72
+ data_copy.load(to_env, to_vpc, filename)
73
+ # Todo: Catch expected errors and output message
62
74
 
63
75
 
64
76
  @database.command(name="copy")
@@ -110,3 +122,4 @@ def copy(
110
122
  """Copy a database between environments."""
111
123
  data_copy = DatabaseCopy(app, database, auto_approve)
112
124
  data_copy.copy(from_env, to_env, from_vpc, to_vpc, svc, template, no_maintenance_page)
125
+ # Todo: Catch expected errors and output message
@@ -5,6 +5,7 @@ from schema import SchemaError
5
5
  from dbt_platform_helper.constants import DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION
6
6
  from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE
7
7
  from dbt_platform_helper.domain.maintenance_page import MaintenancePageProvider
8
+ from dbt_platform_helper.platform_exception import PlatformException
8
9
  from dbt_platform_helper.providers.load_balancers import find_https_listener
9
10
  from dbt_platform_helper.utils.aws import get_aws_session_or_abort
10
11
  from dbt_platform_helper.utils.click import ClickDocOptGroup
@@ -238,10 +239,10 @@ def find_https_certificate(session: boto3.Session, app: str, env: str) -> str:
238
239
  try:
239
240
  certificate_arn = next(c["CertificateArn"] for c in certificates if c["IsDefault"])
240
241
  except StopIteration:
241
- raise CertificateNotFoundError()
242
+ raise CertificateNotFoundException()
242
243
 
243
244
  return certificate_arn
244
245
 
245
246
 
246
- class CertificateNotFoundError(Exception):
247
+ class CertificateNotFoundException(PlatformException):
247
248
  pass
@@ -9,10 +9,9 @@ import requests
9
9
  import yaml
10
10
  from boto3 import Session
11
11
 
12
- from dbt_platform_helper.exceptions import ApplicationDeploymentNotTriggered
13
- from dbt_platform_helper.exceptions import ApplicationEnvironmentNotFoundError
14
- from dbt_platform_helper.exceptions import NotInCodeBaseRepositoryError
12
+ from dbt_platform_helper.platform_exception import PlatformException
15
13
  from dbt_platform_helper.utils.application import Application
14
+ from dbt_platform_helper.utils.application import ApplicationException
16
15
  from dbt_platform_helper.utils.application import load_application
17
16
  from dbt_platform_helper.utils.aws import check_codebase_exists
18
17
  from dbt_platform_helper.utils.aws import check_image_exists
@@ -68,7 +67,7 @@ class Codebase:
68
67
  .removesuffix(".git")
69
68
  )
70
69
  if repository.endswith("-deploy") or Path("./copilot").exists():
71
- raise NotInCodeBaseRepositoryError()
70
+ raise NotInCodeBaseRepositoryException()
72
71
 
73
72
  builder_configuration_url = "https://raw.githubusercontent.com/uktrade/ci-image-builder/main/image_builder/configuration/builder_configuration.yml"
74
73
  builder_configuration_response = requests.get(builder_configuration_url)
@@ -143,7 +142,7 @@ class Codebase:
143
142
 
144
143
  application = self.load_application(app, default_session=session)
145
144
  if not application.environments.get(env):
146
- raise ApplicationEnvironmentNotFoundError(env)
145
+ raise ApplicationEnvironmentNotFoundException(env)
147
146
 
148
147
  self.check_codebase_exists(session, application, codebase)
149
148
 
@@ -220,3 +219,22 @@ class Codebase:
220
219
  build_arn = self.start_build_extraction(codebuild_client, build_options)
221
220
  return get_build_url_from_arn(build_arn)
222
221
  return None
222
+
223
+
224
+ class ApplicationDeploymentNotTriggered(PlatformException):
225
+ def __init__(self, codebase: str):
226
+ super().__init__(f"""Your deployment for {codebase} was not triggered.""")
227
+
228
+
229
+ class ApplicationEnvironmentNotFoundException(ApplicationException):
230
+ def __init__(self, environment: str):
231
+ super().__init__(
232
+ f"""The environment "{environment}" either does not exist or has not been deployed."""
233
+ )
234
+
235
+
236
+ class NotInCodeBaseRepositoryException(PlatformException):
237
+ def __init__(self):
238
+ super().__init__(
239
+ "You are in the deploy repository; make sure you are in the application codebase repository.",
240
+ )
@@ -6,7 +6,6 @@ import click
6
6
  from dbt_platform_helper.providers.cloudformation import CloudFormation
7
7
  from dbt_platform_helper.providers.copilot import connect_to_addon_client_task
8
8
  from dbt_platform_helper.providers.copilot import create_addon_client_task
9
- from dbt_platform_helper.providers.copilot import create_postgres_admin_task
10
9
  from dbt_platform_helper.providers.ecs import ECS
11
10
  from dbt_platform_helper.providers.secrets import Secrets
12
11
  from dbt_platform_helper.utils.application import Application
@@ -23,7 +22,6 @@ class Conduit:
23
22
  subprocess: subprocess = subprocess,
24
23
  connect_to_addon_client_task=connect_to_addon_client_task,
25
24
  create_addon_client_task=create_addon_client_task,
26
- create_postgres_admin_task=create_postgres_admin_task,
27
25
  ):
28
26
 
29
27
  self.application = application
@@ -34,7 +32,6 @@ class Conduit:
34
32
  self.echo = echo
35
33
  self.connect_to_addon_client_task = connect_to_addon_client_task
36
34
  self.create_addon_client_task = create_addon_client_task
37
- self.create_postgres_admin_task = create_postgres_admin_task
38
35
 
39
36
  def start(self, env: str, addon_name: str, access: str = "read"):
40
37
  clients = self._initialise_clients(env)
@@ -49,7 +46,6 @@ class Conduit:
49
46
  self.create_addon_client_task(
50
47
  clients["iam"],
51
48
  clients["ssm"],
52
- clients["secrets_manager"],
53
49
  self.subprocess,
54
50
  self.application,
55
51
  env,
@@ -89,8 +85,6 @@ class Conduit:
89
85
  "ecs": self.application.environments[env].session.client("ecs"),
90
86
  "iam": self.application.environments[env].session.client("iam"),
91
87
  "ssm": self.application.environments[env].session.client("ssm"),
92
- "cloudformation": self.application.environments[env].session.client("cloudformation"),
93
- "secrets_manager": self.application.environments[env].session.client("secretsmanager"),
94
88
  }
95
89
 
96
90
  def _get_addon_details(self, addon_name, access):
@@ -8,9 +8,9 @@ from boto3 import Session
8
8
 
9
9
  from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE
10
10
  from dbt_platform_helper.domain.maintenance_page import MaintenancePageProvider
11
- from dbt_platform_helper.exceptions import ApplicationNotFoundError
12
- from dbt_platform_helper.exceptions import AWSException
11
+ from dbt_platform_helper.providers.aws import AWSException
13
12
  from dbt_platform_helper.utils.application import Application
13
+ from dbt_platform_helper.utils.application import ApplicationNotFoundException
14
14
  from dbt_platform_helper.utils.application import load_application
15
15
  from dbt_platform_helper.utils.aws import Vpc
16
16
  from dbt_platform_helper.utils.aws import get_connection_string
@@ -58,10 +58,10 @@ class DatabaseCopy:
58
58
 
59
59
  try:
60
60
  self.application = load_application(self.app)
61
- except ApplicationNotFoundError:
61
+ except ApplicationNotFoundException:
62
62
  abort(f"No such application '{app}'.")
63
63
 
64
- def _execute_operation(self, is_dump: bool, env: str, vpc_name: str, to_env: str):
64
+ def _execute_operation(self, is_dump: bool, env: str, vpc_name: str, filename: str):
65
65
  vpc_name = self.enrich_vpc_name(env, vpc_name)
66
66
 
67
67
  environments = self.application.environments
@@ -89,7 +89,7 @@ class DatabaseCopy:
89
89
 
90
90
  try:
91
91
  task_arn = self.run_database_copy_task(
92
- env_session, env, vpc_config, is_dump, db_connection_string, to_env
92
+ env_session, env, vpc_config, is_dump, db_connection_string, filename
93
93
  )
94
94
  except Exception as exc:
95
95
  self.abort(f"{exc} (Account id: {self.account_id(env)})")
@@ -122,14 +122,15 @@ class DatabaseCopy:
122
122
  vpc_config: Vpc,
123
123
  is_dump: bool,
124
124
  db_connection_string: str,
125
- to_env: str,
125
+ filename: str,
126
126
  ) -> str:
127
127
  client = session.client("ecs")
128
128
  action = "dump" if is_dump else "load"
129
+ dump_file_name = filename if filename else "data_dump"
129
130
  env_vars = [
130
131
  {"name": "DATA_COPY_OPERATION", "value": action.upper()},
131
132
  {"name": "DB_CONNECTION_STRING", "value": db_connection_string},
132
- {"name": "TO_ENVIRONMENT", "value": to_env},
133
+ {"name": "DUMP_FILE_NAME", "value": dump_file_name},
133
134
  ]
134
135
  if not is_dump:
135
136
  env_vars.append({"name": "ECS_CLUSTER", "value": f"{self.app}-{env}"})
@@ -159,12 +160,12 @@ class DatabaseCopy:
159
160
 
160
161
  return response.get("tasks", [{}])[0].get("taskArn")
161
162
 
162
- def dump(self, env: str, vpc_name: str, to_env: str):
163
- self._execute_operation(True, env, vpc_name, to_env)
163
+ def dump(self, env: str, vpc_name: str, filename: str = None):
164
+ self._execute_operation(True, env, vpc_name, filename)
164
165
 
165
- def load(self, env: str, vpc_name: str):
166
+ def load(self, env: str, vpc_name: str, filename: str = None):
166
167
  if self.is_confirmed_ready_to_load(env):
167
- self._execute_operation(False, env, vpc_name, to_env=env)
168
+ self._execute_operation(False, env, vpc_name, filename)
168
169
 
169
170
  def copy(
170
171
  self,
@@ -179,8 +180,8 @@ class DatabaseCopy:
179
180
  to_vpc = self.enrich_vpc_name(to_env, to_vpc)
180
181
  if not no_maintenance_page:
181
182
  self.maintenance_page_provider.activate(self.app, to_env, services, template, to_vpc)
182
- self.dump(from_env, from_vpc, to_env)
183
- self.load(to_env, to_vpc)
183
+ self.dump(from_env, from_vpc, f"data_dump_{to_env}")
184
+ self.load(to_env, to_vpc, f"data_dump_{to_env}")
184
185
  if not no_maintenance_page:
185
186
  self.maintenance_page_provider.deactivate(self.app, to_env)
186
187
 
@@ -9,9 +9,9 @@ from typing import Union
9
9
  import boto3
10
10
  import click
11
11
 
12
- from dbt_platform_helper.providers.load_balancers import ListenerNotFoundError
13
- from dbt_platform_helper.providers.load_balancers import ListenerRuleNotFoundError
14
- from dbt_platform_helper.providers.load_balancers import LoadBalancerNotFoundError
12
+ from dbt_platform_helper.providers.load_balancers import ListenerNotFoundException
13
+ from dbt_platform_helper.providers.load_balancers import ListenerRuleNotFoundException
14
+ from dbt_platform_helper.providers.load_balancers import LoadBalancerNotFoundException
15
15
  from dbt_platform_helper.providers.load_balancers import find_https_listener
16
16
  from dbt_platform_helper.utils.application import Environment
17
17
  from dbt_platform_helper.utils.application import Service
@@ -75,13 +75,13 @@ class MaintenancePageProvider:
75
75
  else:
76
76
  raise click.Abort
77
77
 
78
- except LoadBalancerNotFoundError:
78
+ except LoadBalancerNotFoundException:
79
79
  click.secho(
80
80
  f"No load balancer found for environment {env} in the application {app}.", fg="red"
81
81
  )
82
82
  raise click.Abort
83
83
 
84
- except ListenerNotFoundError:
84
+ except ListenerNotFoundException:
85
85
  click.secho(
86
86
  f"No HTTPS listener found for environment {env} in the application {app}.", fg="red"
87
87
  )
@@ -110,13 +110,13 @@ class MaintenancePageProvider:
110
110
  f"Maintenance page removed from environment {env} in application {app}", fg="green"
111
111
  )
112
112
 
113
- except LoadBalancerNotFoundError:
113
+ except LoadBalancerNotFoundException:
114
114
  click.secho(
115
115
  f"No load balancer found for environment {env} in the application {app}.", fg="red"
116
116
  )
117
117
  raise click.Abort
118
118
 
119
- except ListenerNotFoundError:
119
+ except ListenerNotFoundException:
120
120
  click.secho(
121
121
  f"No HTTPS listener found for environment {env} in the application {app}.", fg="red"
122
122
  )
@@ -180,7 +180,7 @@ def remove_maintenance_page(session: boto3.Session, listener_arn: str):
180
180
  deleted = delete_listener_rule(tag_descriptions, name, lb_client)
181
181
 
182
182
  if name == "MaintenancePage" and not deleted:
183
- raise ListenerRuleNotFoundError()
183
+ raise ListenerRuleNotFoundException()
184
184
 
185
185
 
186
186
  def get_rules_tag_descriptions(rules: list, lb_client):
@@ -0,0 +1,5 @@
1
+ # This exception exists so that we can easily catch exceptions
2
+ # at the command level where we know we can just output the
3
+ # error and abort.
4
+ class PlatformException(Exception):
5
+ pass
@@ -0,0 +1,32 @@
1
+ from dbt_platform_helper.platform_exception import PlatformException
2
+
3
+
4
+ class AWSException(PlatformException):
5
+ pass
6
+
7
+
8
+ class CreateTaskTimeoutException(AWSException):
9
+ def __init__(self, addon_name: str, application_name: str, environment: str):
10
+ super().__init__(
11
+ f"""Client ({addon_name}) ECS task has failed to start for "{application_name}" in "{environment}" environment."""
12
+ )
13
+
14
+
15
+ class ImageNotFoundException(AWSException):
16
+ def __init__(self, commit: str):
17
+ super().__init__(
18
+ f"""The commit hash "{commit}" has not been built into an image, try the `platform-helper codebase build` command first."""
19
+ )
20
+
21
+
22
+ class LogGroupNotFoundException(AWSException):
23
+ def __init__(self, log_group_name: str):
24
+ super().__init__(f"""No log group called "{log_group_name}".""")
25
+
26
+
27
+ # Todo: This should probably be in the AWS Copilot provider, but was causing circular import when we tried it pre refactoring the utils/aws.py
28
+ class CopilotCodebaseNotFoundException(PlatformException):
29
+ def __init__(self, codebase: str):
30
+ super().__init__(
31
+ f"""The codebase "{codebase}" either does not exist or has not been deployed."""
32
+ )
@@ -4,7 +4,7 @@ import botocore
4
4
  from cfn_tools import dump_yaml
5
5
  from cfn_tools import load_yaml
6
6
 
7
- from dbt_platform_helper.exceptions import CloudFormationException
7
+ from dbt_platform_helper.platform_exception import PlatformException
8
8
 
9
9
 
10
10
  class CloudFormation:
@@ -125,3 +125,10 @@ class CloudFormation:
125
125
  raise CloudFormationException(
126
126
  stack_name, f"Error while waiting for stack status: {str(err)}"
127
127
  )
128
+
129
+
130
+ class CloudFormationException(PlatformException):
131
+ def __init__(self, stack_name: str, current_status: str):
132
+ super().__init__(
133
+ f"The CloudFormation stack '{stack_name}' is not in a good state: {current_status}"
134
+ )
@@ -4,7 +4,7 @@ import time
4
4
  from botocore.exceptions import ClientError
5
5
 
6
6
  from dbt_platform_helper.constants import CONDUIT_DOCKER_IMAGE_LOCATION
7
- from dbt_platform_helper.exceptions import CreateTaskTimeoutError
7
+ from dbt_platform_helper.providers.aws import CreateTaskTimeoutException
8
8
  from dbt_platform_helper.providers.secrets import Secrets
9
9
  from dbt_platform_helper.utils.application import Application
10
10
  from dbt_platform_helper.utils.messages import abort_with_error
@@ -13,7 +13,6 @@ from dbt_platform_helper.utils.messages import abort_with_error
13
13
  def create_addon_client_task(
14
14
  iam_client,
15
15
  ssm_client,
16
- secrets_manager_client,
17
16
  subprocess,
18
17
  application: Application,
19
18
  env: str,
@@ -32,7 +31,6 @@ def create_addon_client_task(
32
31
  elif access == "admin":
33
32
  create_postgres_admin_task(
34
33
  ssm_client,
35
- secrets_manager_client,
36
34
  subprocess,
37
35
  application,
38
36
  addon_name,
@@ -74,7 +72,6 @@ def create_addon_client_task(
74
72
 
75
73
  def create_postgres_admin_task(
76
74
  ssm_client,
77
- secrets_manager_client,
78
75
  subprocess,
79
76
  app: Application,
80
77
  addon_name: str,
@@ -147,7 +144,7 @@ def connect_to_addon_client_task(
147
144
  time.sleep(1)
148
145
 
149
146
  if not running:
150
- raise CreateTaskTimeoutError(task_name, application_name, env)
147
+ raise CreateTaskTimeoutException(task_name, application_name, env)
151
148
 
152
149
 
153
150
  def _normalise_secret_name(addon_name: str) -> str:
@@ -3,8 +3,7 @@ import string
3
3
  import time
4
4
  from typing import List
5
5
 
6
- from dbt_platform_helper.exceptions import ECSAgentNotRunning
7
- from dbt_platform_helper.exceptions import NoClusterError
6
+ from dbt_platform_helper.platform_exception import PlatformException
8
7
 
9
8
 
10
9
  class ECS:
@@ -36,7 +35,7 @@ class ECS:
36
35
  if app_key_found and env_key_found and cluster_key_found:
37
36
  return cluster_arn
38
37
 
39
- raise NoClusterError(self.application_name, self.env)
38
+ raise NoClusterException(self.application_name, self.env)
40
39
 
41
40
  def get_or_create_task_name(self, addon_name: str, parameter_name: str) -> str:
42
41
  """Fetches the task name from SSM or creates a new one if not found."""
@@ -84,4 +83,20 @@ class ECS:
84
83
  time.sleep(1)
85
84
 
86
85
  if execute_command_agent_status != "RUNNING":
87
- raise ECSAgentNotRunning
86
+ raise ECSAgentNotRunningException
87
+
88
+
89
+ class ECSException(PlatformException):
90
+ pass
91
+
92
+
93
+ class ECSAgentNotRunningException(ECSException):
94
+ def __init__(self):
95
+ super().__init__("""ECS exec agent never reached "RUNNING" status""")
96
+
97
+
98
+ class NoClusterException(ECSException):
99
+ def __init__(self, application_name: str, environment: str):
100
+ super().__init__(
101
+ f"""No ECS cluster found for "{application_name}" in "{environment}" environment."""
102
+ )
@@ -1,5 +1,7 @@
1
1
  import boto3
2
2
 
3
+ from dbt_platform_helper.platform_exception import PlatformException
4
+
3
5
 
4
6
  def find_load_balancer(session: boto3.Session, app: str, env: str) -> str:
5
7
  lb_client = session.client("elbv2")
@@ -16,7 +18,7 @@ def find_load_balancer(session: boto3.Session, app: str, env: str) -> str:
16
18
  load_balancer_arn = lb["ResourceArn"]
17
19
 
18
20
  if not load_balancer_arn:
19
- raise LoadBalancerNotFoundError()
21
+ raise LoadBalancerNotFoundException()
20
22
 
21
23
  return load_balancer_arn
22
24
 
@@ -34,18 +36,22 @@ def find_https_listener(session: boto3.Session, app: str, env: str) -> str:
34
36
  pass
35
37
 
36
38
  if not listener_arn:
37
- raise ListenerNotFoundError()
39
+ raise ListenerNotFoundException()
38
40
 
39
41
  return listener_arn
40
42
 
41
43
 
42
- class LoadBalancerNotFoundError(Exception):
44
+ class LoadBalancerException(PlatformException):
45
+ pass
46
+
47
+
48
+ class LoadBalancerNotFoundException(LoadBalancerException):
43
49
  pass
44
50
 
45
51
 
46
- class ListenerNotFoundError(Exception):
52
+ class ListenerNotFoundException(LoadBalancerException):
47
53
  pass
48
54
 
49
55
 
50
- class ListenerRuleNotFoundError(Exception):
56
+ class ListenerRuleNotFoundException(LoadBalancerException):
51
57
  pass
@@ -2,11 +2,7 @@ import json
2
2
  import urllib
3
3
 
4
4
  from dbt_platform_helper.constants import CONDUIT_ADDON_TYPES
5
- from dbt_platform_helper.exceptions import AddonNotFoundError
6
- from dbt_platform_helper.exceptions import AddonTypeMissingFromConfigError
7
- from dbt_platform_helper.exceptions import InvalidAddonTypeError
8
- from dbt_platform_helper.exceptions import ParameterNotFoundError
9
- from dbt_platform_helper.exceptions import SecretNotFoundError
5
+ from dbt_platform_helper.platform_exception import PlatformException
10
6
 
11
7
 
12
8
  class Secrets:
@@ -43,8 +39,9 @@ class Secrets:
43
39
  except self.secrets_manager_client.exceptions.ResourceNotFoundException:
44
40
  pass
45
41
 
46
- raise SecretNotFoundError(secret_name)
42
+ raise SecretNotFoundException(secret_name)
47
43
 
44
+ # Todo: This probably does not belong in the secrets provider. When it moves, take the Todoed exceptions from below
48
45
  def get_addon_type(self, addon_name: str) -> str:
49
46
  addon_type = None
50
47
  try:
@@ -54,19 +51,19 @@ class Secrets:
54
51
  )["Parameter"]["Value"]
55
52
  )
56
53
  except self.ssm_client.exceptions.ParameterNotFound:
57
- raise ParameterNotFoundError(self.application_name, self.env)
54
+ raise ParameterNotFoundException(self.application_name, self.env)
58
55
 
59
56
  if addon_name not in addon_config.keys():
60
- raise AddonNotFoundError(addon_name)
57
+ raise AddonNotFoundException(addon_name)
61
58
 
62
59
  for name, config in addon_config.items():
63
60
  if name == addon_name:
64
61
  if not config.get("type"):
65
- raise AddonTypeMissingFromConfigError(addon_name)
62
+ raise AddonTypeMissingFromConfigException(addon_name)
66
63
  addon_type = config["type"]
67
64
 
68
65
  if not addon_type or addon_type not in CONDUIT_ADDON_TYPES:
69
- raise InvalidAddonTypeError(addon_type)
66
+ raise InvalidAddonTypeException(addon_type)
70
67
 
71
68
  if "postgres" in addon_type:
72
69
  addon_type = "postgres"
@@ -83,3 +80,47 @@ class Secrets:
83
80
 
84
81
  def _normalise_secret_name(self, addon_name: str) -> str:
85
82
  return addon_name.replace("-", "_").upper()
83
+
84
+
85
+ # Todo: This probably does not belong in the secrets provider. Move it when we find a better home for get_addon_type()
86
+ class AddonException(PlatformException):
87
+ pass
88
+
89
+
90
+ # Todo: This probably does not belong in the secrets provider. Move it when we find a better home for get_addon_type()
91
+ class AddonNotFoundException(AddonException):
92
+ def __init__(self, addon_name: str):
93
+ super().__init__(f"""Addon "{addon_name}" does not exist.""")
94
+
95
+
96
+ # Todo: This probably does not belong in the secrets provider. Move it when we find a better home for get_addon_type()
97
+ class AddonTypeMissingFromConfigException(AddonException):
98
+ def __init__(self, addon_name: str):
99
+ super().__init__(
100
+ f"""The configuration for the addon {addon_name}, is misconfigured and missing the addon type."""
101
+ )
102
+
103
+
104
+ # Todo: This probably does not belong in the secrets provider. Move it when we find a better home for get_addon_type()
105
+ class InvalidAddonTypeException(AddonException):
106
+ def __init__(self, addon_type):
107
+ self.addon_type = addon_type
108
+ super().__init__(
109
+ f"""Addon type "{self.addon_type}" is not supported, we support: {", ".join(CONDUIT_ADDON_TYPES)}."""
110
+ )
111
+
112
+
113
+ class SecretException(PlatformException):
114
+ pass
115
+
116
+
117
+ class ParameterNotFoundException(SecretException):
118
+ def __init__(self, application_name: str, environment: str):
119
+ super().__init__(
120
+ f"""No parameter called "/copilot/applications/{application_name}/environments/{environment}/addons". Try deploying the "{application_name}" "{environment}" environment."""
121
+ )
122
+
123
+
124
+ class SecretNotFoundException(SecretException):
125
+ def __init__(self, secret_name: str):
126
+ super().__init__(f"""No secret called "{secret_name}".""")
@@ -0,0 +1,19 @@
1
+ from dbt_platform_helper.platform_exception import PlatformException
2
+
3
+
4
+ class ValidationException(PlatformException):
5
+ pass
6
+
7
+
8
+ class IncompatibleMajorVersionException(ValidationException):
9
+ def __init__(self, app_version: str, check_version: str):
10
+ super().__init__()
11
+ self.app_version = app_version
12
+ self.check_version = check_version
13
+
14
+
15
+ class IncompatibleMinorVersionException(ValidationException):
16
+ def __init__(self, app_version: str, check_version: str):
17
+ super().__init__()
18
+ self.app_version = app_version
19
+ self.check_version = check_version
@@ -1,4 +1,5 @@
1
1
  import json
2
+ import os
2
3
  import re
3
4
  from pathlib import Path
4
5
  from typing import Dict
@@ -8,7 +9,7 @@ import yaml
8
9
  from boto3 import Session
9
10
  from yaml.parser import ParserError
10
11
 
11
- from dbt_platform_helper.exceptions import ApplicationNotFoundError
12
+ from dbt_platform_helper.platform_exception import PlatformException
12
13
  from dbt_platform_helper.utils.aws import get_aws_session_or_abort
13
14
  from dbt_platform_helper.utils.aws import get_profile_name_from_account_id
14
15
  from dbt_platform_helper.utils.aws import get_ssm_secrets
@@ -80,7 +81,7 @@ def load_application(app: str = None, default_session: Session = None) -> Applic
80
81
  WithDecryption=False,
81
82
  )
82
83
  except ssm_client.exceptions.ParameterNotFound:
83
- raise ApplicationNotFoundError(app)
84
+ raise ApplicationNotFoundException(app)
84
85
 
85
86
  path = f"/copilot/applications/{application.name}/environments"
86
87
  secrets = get_ssm_secrets(app, None, current_session, path)
@@ -135,3 +136,14 @@ def get_application_name():
135
136
  abort_with_error("Cannot get application name. No copilot/.workspace file found")
136
137
 
137
138
  return app_name
139
+
140
+
141
+ class ApplicationException(PlatformException):
142
+ pass
143
+
144
+
145
+ class ApplicationNotFoundException(ApplicationException):
146
+ def __init__(self, application_name: str):
147
+ super().__init__(
148
+ f"""The account "{os.environ.get("AWS_PROFILE")}" does not contain the application "{application_name}"; ensure you have set the environment variable "AWS_PROFILE" correctly."""
149
+ )
@@ -1,4 +1,4 @@
1
- from dbt_platform_helper.exceptions import ValidationException
1
+ from dbt_platform_helper.providers.validation import ValidationException
2
2
 
3
3
 
4
4
  class ARN:
@@ -13,11 +13,12 @@ import click
13
13
  import yaml
14
14
  from boto3 import Session
15
15
 
16
- from dbt_platform_helper.exceptions import AWSException
17
- from dbt_platform_helper.exceptions import CopilotCodebaseNotFoundError
18
- from dbt_platform_helper.exceptions import ImageNotFoundError
19
- from dbt_platform_helper.exceptions import ResourceNotFoundException
20
- from dbt_platform_helper.exceptions import ValidationException
16
+ from dbt_platform_helper.platform_exception import PlatformException
17
+ from dbt_platform_helper.providers.aws import AWSException
18
+ from dbt_platform_helper.providers.aws import CopilotCodebaseNotFoundException
19
+ from dbt_platform_helper.providers.aws import ImageNotFoundException
20
+ from dbt_platform_helper.providers.aws import LogGroupNotFoundException
21
+ from dbt_platform_helper.providers.validation import ValidationException
21
22
  from dbt_platform_helper.utils.files import cache_refresh_required
22
23
  from dbt_platform_helper.utils.files import read_supported_versions_from_cache
23
24
  from dbt_platform_helper.utils.files import write_to_cache
@@ -95,7 +96,7 @@ def _log_account_info(account_name: list, account_id: str) -> None:
95
96
  )
96
97
 
97
98
 
98
- class NoProfileForAccountIdError(Exception):
99
+ class NoProfileForAccountIdException(PlatformException):
99
100
  def __init__(self, account_id):
100
101
  super().__init__(f"No profile found for account {account_id}")
101
102
 
@@ -110,7 +111,7 @@ def get_profile_name_from_account_id(account_id: str):
110
111
  if account_id == found_account_id:
111
112
  return section.removeprefix("profile ")
112
113
 
113
- raise NoProfileForAccountIdError(account_id)
114
+ raise NoProfileForAccountIdException(account_id)
114
115
 
115
116
 
116
117
  def get_ssm_secret_names(app, env):
@@ -488,8 +489,10 @@ def start_build_extraction(codebuild_client, build_options):
488
489
  return response["build"]["arn"]
489
490
 
490
491
 
492
+ # Todo: This should probably be in the AWS Copilot provider
491
493
  def check_codebase_exists(session: Session, application, codebase: str):
492
494
  try:
495
+ # Todo: Can this leverage dbt_platform_helper.providers.secrets.Secrets.get_connection_secret_arn?
493
496
  ssm_client = session.client("ssm")
494
497
  json.loads(
495
498
  ssm_client.get_parameter(
@@ -502,7 +505,7 @@ def check_codebase_exists(session: Session, application, codebase: str):
502
505
  ssm_client.exceptions.ParameterNotFound,
503
506
  json.JSONDecodeError,
504
507
  ):
505
- raise CopilotCodebaseNotFoundError(codebase)
508
+ raise CopilotCodebaseNotFoundException(codebase)
506
509
 
507
510
 
508
511
  def check_image_exists(session, application, codebase, commit):
@@ -516,7 +519,7 @@ def check_image_exists(session, application, codebase, commit):
516
519
  ecr_client.exceptions.RepositoryNotFoundException,
517
520
  ecr_client.exceptions.ImageNotFoundException,
518
521
  ):
519
- raise ImageNotFoundError(commit)
522
+ raise ImageNotFoundException(commit)
520
523
 
521
524
 
522
525
  def get_build_url_from_arn(build_arn: str) -> str:
@@ -577,4 +580,4 @@ def wait_for_log_group_to_exist(log_client, log_group_name, attempts=30):
577
580
  time.sleep(1)
578
581
 
579
582
  if not log_group_exists:
580
- raise ResourceNotFoundException
583
+ raise LogGroupNotFoundException(log_group_name)
@@ -2,7 +2,7 @@ import re
2
2
  import subprocess
3
3
 
4
4
 
5
- class CommitNotFoundError(Exception):
5
+ class CommitNotFoundException(Exception):
6
6
  pass
7
7
 
8
8
 
@@ -26,4 +26,4 @@ def check_if_commit_exists(commit):
26
26
  )
27
27
 
28
28
  if branches_containing_commit.stderr:
29
- raise CommitNotFoundError()
29
+ raise CommitNotFoundException()
@@ -215,6 +215,7 @@ DATABASE_COPY = {
215
215
  "to": ENV_NAME,
216
216
  Optional("from_account"): str,
217
217
  Optional("to_account"): str,
218
+ Optional("pipeline"): {Optional("schedule"): str},
218
219
  }
219
220
 
220
221
  POSTGRES_DEFINITION = {
@@ -285,9 +286,19 @@ EXTERNAL_ROLE_ACCESS = {
285
286
  "cyber_sign_off_by": dbt_email_address_regex("cyber_sign_off_by"),
286
287
  }
287
288
 
288
- EXTERNAL_ROLE_ACCESS_NAME = Regex(
289
- r"^([a-z][a-zA-Z0-9_-]*)$",
290
- error="External role access block name {} is invalid: names must only contain lowercase alphanumeric characters separated by hypen or underscore",
289
+ CROSS_ENVIRONMENT_SERVICE_ACCESS = {
290
+ "application": str,
291
+ "environment": ENV_NAME,
292
+ "account": str,
293
+ "service": str,
294
+ "read": bool,
295
+ "write": bool,
296
+ "cyber_sign_off_by": dbt_email_address_regex("cyber_sign_off_by"),
297
+ }
298
+
299
+ LOWER_ALPHANUMERIC = Regex(
300
+ r"^([a-z][a-zA-Z0-9_-]*|\*)$",
301
+ error="{} is invalid: must only contain lowercase alphanumeric characters separated by hyphen or underscore",
291
302
  )
292
303
 
293
304
  DATA_IMPORT = {
@@ -312,7 +323,10 @@ S3_BASE = {
312
323
  Optional("versioning"): bool,
313
324
  Optional("lifecycle_rules"): [LIFECYCLE_RULE],
314
325
  Optional("data_migration"): DATA_MIGRATION,
315
- Optional("external_role_access"): {EXTERNAL_ROLE_ACCESS_NAME: EXTERNAL_ROLE_ACCESS},
326
+ Optional("external_role_access"): {LOWER_ALPHANUMERIC: EXTERNAL_ROLE_ACCESS},
327
+ Optional("cross_environment_service_access"): {
328
+ LOWER_ALPHANUMERIC: CROSS_ENVIRONMENT_SERVICE_ACCESS
329
+ },
316
330
  },
317
331
  },
318
332
  }
@@ -13,9 +13,9 @@ import requests
13
13
 
14
14
  from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE
15
15
  from dbt_platform_helper.constants import PLATFORM_HELPER_VERSION_FILE
16
- from dbt_platform_helper.exceptions import IncompatibleMajorVersion
17
- from dbt_platform_helper.exceptions import IncompatibleMinorVersion
18
- from dbt_platform_helper.exceptions import ValidationException
16
+ from dbt_platform_helper.providers.validation import IncompatibleMajorVersionException
17
+ from dbt_platform_helper.providers.validation import IncompatibleMinorVersionException
18
+ from dbt_platform_helper.providers.validation import ValidationException
19
19
  from dbt_platform_helper.utils.platform_config import load_unvalidated_config_file
20
20
 
21
21
  VersionTuple = Optional[Tuple[int, int, int]]
@@ -198,13 +198,13 @@ def validate_version_compatibility(
198
198
  if (app_major == 0 and check_major == 0) and (
199
199
  app_minor != check_minor or app_patch != check_patch
200
200
  ):
201
- raise IncompatibleMajorVersion(app_version_as_string, check_version_as_string)
201
+ raise IncompatibleMajorVersionException(app_version_as_string, check_version_as_string)
202
202
 
203
203
  if app_major != check_major:
204
- raise IncompatibleMajorVersion(app_version_as_string, check_version_as_string)
204
+ raise IncompatibleMajorVersionException(app_version_as_string, check_version_as_string)
205
205
 
206
206
  if app_minor != check_minor:
207
- raise IncompatibleMinorVersion(app_version_as_string, check_version_as_string)
207
+ raise IncompatibleMinorVersionException(app_version_as_string, check_version_as_string)
208
208
 
209
209
 
210
210
  def check_version_on_file_compatibility(
@@ -248,9 +248,9 @@ def check_platform_helper_version_needs_update():
248
248
  )
249
249
  try:
250
250
  validate_version_compatibility(local_version, latest_release)
251
- except IncompatibleMajorVersion:
251
+ except IncompatibleMajorVersionException:
252
252
  click.secho(message, fg="red")
253
- except IncompatibleMinorVersion:
253
+ except IncompatibleMinorVersionException:
254
254
  click.secho(message, fg="yellow")
255
255
 
256
256
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbt-platform-helper
3
- Version: 12.3.0
3
+ Version: 12.4.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
@@ -1,16 +1,15 @@
1
- dbt_platform_helper/COMMANDS.md,sha256=V75r1y9dSDz6s9pshHh79SzEH9MeLMQF3N7KnOOe1YU,21824
1
+ dbt_platform_helper/COMMANDS.md,sha256=6VGkyKa_AB1adSlyhWIKrfDckq2n-xxqnBbBpgO5bnc,22207
2
2
  dbt_platform_helper/README.md,sha256=B0qN2_u_ASqqgkGDWY2iwNGZt_9tUgMb9XqtaTuzYjw,1530
3
3
  dbt_platform_helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  dbt_platform_helper/addon-plans.yml,sha256=O46a_ODsGG9KXmQY_1XbSGqrpSaHSLDe-SdROzHx8Go,4545
5
- dbt_platform_helper/addons-template-map.yml,sha256=kYv_ZoZGWNeNBCnR_9wSeLhJuWOTHx-vn7ub74MgGb4,546
6
5
  dbt_platform_helper/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
6
  dbt_platform_helper/commands/application.py,sha256=eVwCaYuwBlk0zx0xfA6fW7b-S1pl8gkyT1lHKeeh2R0,10147
8
- dbt_platform_helper/commands/codebase.py,sha256=-R-DaT3TOCRc2f2-0Wy5wg2jBd2m-SLIKk2wMKD25eA,2262
9
- dbt_platform_helper/commands/conduit.py,sha256=gsiSzimX-pjBr6hegTxuVvwLqxlxGMV67lmnLbgmw4w,2254
10
- dbt_platform_helper/commands/config.py,sha256=NOHea7OAjrl6XHlW6HMLn0m0T5lFPyNH3HXoyCOWsJk,12070
11
- dbt_platform_helper/commands/copilot.py,sha256=i7FLSF-p9P5JQ36e_V8THXxdXG_g1hI7fHxemxQG82A,12927
12
- dbt_platform_helper/commands/database.py,sha256=_HnuOxlfVIFGkDotGv0SGb6oWrnm517FSvLv0aGcLJQ,3542
13
- dbt_platform_helper/commands/environment.py,sha256=-j-PYLHlrMH4F-DLhCCF3AYKP5z-Tzw7E8SbjMsMPnE,9209
7
+ dbt_platform_helper/commands/codebase.py,sha256=KB8irKyFtb6pKn5cQ0MmTywGW7Vd8SSbWjT2mRnh3JA,2270
8
+ dbt_platform_helper/commands/conduit.py,sha256=KqRWiirl5Xl7qcJXOAsirbTLlV1XquOjddsopuj0Kp4,2272
9
+ dbt_platform_helper/commands/config.py,sha256=LKHPBR0xCPiX_oR2Gtl0_KO9WqABNDF5w_dI7WRxhWk,12117
10
+ dbt_platform_helper/commands/copilot.py,sha256=XizScFxONNB3RLecRfEgCv--TwQ1j2rCUKGCx0nPq4I,12883
11
+ dbt_platform_helper/commands/database.py,sha256=aG3zcMHL5PE96b7LSAu0FGCbgcycQej3AGRcd-bpXUo,4115
12
+ dbt_platform_helper/commands/environment.py,sha256=VNIzuCM6RT-jVMk3Km0d88NEhrkTEWNqscEypVwLSWU,9294
14
13
  dbt_platform_helper/commands/generate.py,sha256=YLCPb-xcPapGcsLn-7d1Am7BpGp5l0iecIDTOdNGjHk,722
15
14
  dbt_platform_helper/commands/notify.py,sha256=kVJ0s78QMiaEWPVKu_bbMko4DW2uJy2fu8-HNJsglyk,3748
16
15
  dbt_platform_helper/commands/pipeline.py,sha256=_52bDSDa8DoyOA4VFxFJhwaiKCPHKqPtK2LWDLFaKlA,9452
@@ -19,18 +18,20 @@ dbt_platform_helper/commands/version.py,sha256=XVfSd53TDti4cceBqTmRfq_yZnvxs14Rb
19
18
  dbt_platform_helper/constants.py,sha256=HVaaO7hlQB41GrBBxcgk7hHie9tKbeYhJc-cRyYuIE0,453
20
19
  dbt_platform_helper/default-extensions.yml,sha256=SU1ZitskbuEBpvE7efc3s56eAUF11j70brhj_XrNMMo,493
21
20
  dbt_platform_helper/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- dbt_platform_helper/domain/codebase.py,sha256=M-Eb7SU1CJpKZcPyu67xXi4Pt3U1WvKHxO6L9RpGnbM,9108
23
- dbt_platform_helper/domain/conduit.py,sha256=O1GZ_IVXgqefIHWZJ76jQ7HCFQ3fvytCOWkHAr_ThI4,4796
24
- dbt_platform_helper/domain/database_copy.py,sha256=RLQMAr0hinCFUV0Qa8JfWQSOoGRrMwViFIh_W1AaPsM,8824
25
- dbt_platform_helper/domain/maintenance_page.py,sha256=NFHN_J0NthhJ1YkcOTJ8c0R8y33TrDZq3ka2fmMRM1g,15708
26
- dbt_platform_helper/exceptions.py,sha256=LA0tMBncOw0YrmHFspf4C2LVqtRBwbSfaQl_yCB_MKg,4704
21
+ dbt_platform_helper/domain/codebase.py,sha256=vs25ytD0iKwfuX-EoYHwG6qiZAmfvKyQiYT9BeWZ_s4,9688
22
+ dbt_platform_helper/domain/conduit.py,sha256=mvjDzxh-SCUCY5qGL73kG8TT7YqeQR8XtNcHx26SW2w,4344
23
+ dbt_platform_helper/domain/database_copy.py,sha256=m25FA6DkF_yG3lVcbxBEleYxwHA85hQrB5fFeIg6adM,8988
24
+ dbt_platform_helper/domain/maintenance_page.py,sha256=JN1ksJ9viZ8SjPkO48y_GqrqTgR5B3T1aiye0XlUp4I,15740
27
25
  dbt_platform_helper/jinja2_tags.py,sha256=jFyN_Sxmko1GSfvrqRIGQ80CCW8EwlCV3su0ahJPfoE,541
26
+ dbt_platform_helper/platform_exception.py,sha256=bheZV9lqGvrCVTNT92349dVntNDEDWTEwciZgC83WzE,187
28
27
  dbt_platform_helper/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- dbt_platform_helper/providers/cloudformation.py,sha256=geraDvXZ1UZAYO_hGlNiHbEtcg9JbGdeW9BO5etlnco,4728
30
- dbt_platform_helper/providers/copilot.py,sha256=-LNOUeOg2lWQ8Ig2himFgYTXGQKP-tjZKMTdi0FzVAA,5330
31
- dbt_platform_helper/providers/ecs.py,sha256=tgc1HKy5jjt3WBui4HbBGSuoY4GKYO30TgvgPGg3dzQ,3437
32
- dbt_platform_helper/providers/load_balancers.py,sha256=e1SPrWbBWq95paSVd3Y5yORIrHAZxcVabBYDjPyUTsU,1430
33
- dbt_platform_helper/providers/secrets.py,sha256=OMRtPNFgBv_aSMDGq-l6TQtE06InOC4U6TNd64NJalg,3634
28
+ dbt_platform_helper/providers/aws.py,sha256=KHgySe6cwEw1wePjw6DL7uSyZRk3DN_Aqqi8KnRoB3M,1208
29
+ dbt_platform_helper/providers/cloudformation.py,sha256=YmeofMMxh9hzhU4Osa1vR41s18jNXzsZdEfpQUk1Lc4,4976
30
+ dbt_platform_helper/providers/copilot.py,sha256=2BkQXn17GC1oGfCSCXXapTqT5OEhpEBeNkQ33g-U6wU,5245
31
+ dbt_platform_helper/providers/ecs.py,sha256=XlQHYhZiLGrqR-1ZWMagGH2R2Hy7mCP6676eZL3YbNQ,3842
32
+ dbt_platform_helper/providers/load_balancers.py,sha256=0tPkuQ_jWfan44HrBA5EMLqrZaYQl-Lw5PavZ1a1iag,1615
33
+ dbt_platform_helper/providers/secrets.py,sha256=6cYIR15dLdHmqxtWQpM6R71e0_Xgsg9V291HBG-0LV0,5272
34
+ dbt_platform_helper/providers/validation.py,sha256=d_YzJZVjGNO65pXcPIcFc9I-FRCESeEC7GvUzP8n-As,596
34
35
  dbt_platform_helper/templates/.copilot/config.yml,sha256=J_bA9sCtBdCPBRImpCBRnYvhQd4vpLYIXIU-lq9vbkA,158
35
36
  dbt_platform_helper/templates/.copilot/image_build_run.sh,sha256=adYucYXEB-kAgZNjTQo0T6EIAY8sh_xCEvVhWKKQ8mw,164
36
37
  dbt_platform_helper/templates/.copilot/phases/build.sh,sha256=umKXePcRvx4XyrRY0fAWIyYFtNjqBI2L8vIJk-V7C60,121
@@ -72,22 +73,22 @@ dbt_platform_helper/templates/svc/manifest-backend.yml,sha256=aAD9ndkbXnF7JBAKS2
72
73
  dbt_platform_helper/templates/svc/manifest-public.yml,sha256=6NHVR_onBu5hbwynLrB6roDRce7JcylSc0qeYvzlPdI,3664
73
74
  dbt_platform_helper/templates/svc/overrides/cfn.patches.yml,sha256=W7-d017akuUq9kda64DQxazavcRcCPDjaAik6t1EZqM,742
74
75
  dbt_platform_helper/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
- dbt_platform_helper/utils/application.py,sha256=brEREkgP2QVVS0Id5rApNfKm6UqveQ5LNbvXJNzzzHA,4132
76
- dbt_platform_helper/utils/arn_parser.py,sha256=1jY0elpAe4YL3ulrrCf1YiKmjI-7YXz4gJASqkIFHTc,1294
77
- dbt_platform_helper/utils/aws.py,sha256=zmUYOoSM0LphuXPN7Cnf-Lm1_DjFQ_nVn0m_OByHX8s,19465
76
+ dbt_platform_helper/utils/application.py,sha256=ugY3nbUHRNFvJgaD4446EdSvIyILEN6ouuuk7eoyXe8,4538
77
+ dbt_platform_helper/utils/arn_parser.py,sha256=BaXzIxSOLdFmP_IfAxRq-0j-0Re1iCN7L4j2Zi5-CRQ,1304
78
+ dbt_platform_helper/utils/aws.py,sha256=sO5EHTbjzOYc0aPmpRupbcACwIBCHz8YUZfqz0vXydI,19771
78
79
  dbt_platform_helper/utils/click.py,sha256=Fx4y4bbve1zypvog_sgK7tJtCocmzheoEFLBRv1lfdM,2943
79
80
  dbt_platform_helper/utils/cloudfoundry.py,sha256=GnQ4fVLnDfOdNSrsJjI6ElZHqpgwINeoPn77cUH2UFY,484
80
81
  dbt_platform_helper/utils/files.py,sha256=pa5uwwrEFIAgXZUyH2KEr2Yiu6bKuV4EMlhn9BcUMsY,5296
81
- dbt_platform_helper/utils/git.py,sha256=aI7pCst5hm4XACiubsTpGJV1UEBLnxLpUGXu4h4hofM,696
82
+ dbt_platform_helper/utils/git.py,sha256=7JGZMaI8-cU6-GjXIXjOlsYfKu_RppLOGyAicBd4n_8,704
82
83
  dbt_platform_helper/utils/manifests.py,sha256=ji3UYHCxq9tTpkm4MlRa2y0-JOYYqq1pWZ2h_zpj0UU,507
83
84
  dbt_platform_helper/utils/messages.py,sha256=aLx6s9utt__IqlDdeIYq4n82ERwludu2Zfqy0Q2t-x8,115
84
85
  dbt_platform_helper/utils/platform_config.py,sha256=2RfIxBAT5fv7WR4YuP3yomUK7sKZFL77xevuHnUALdg,676
85
86
  dbt_platform_helper/utils/template.py,sha256=raRx4QUCVJtKfvJK08Egg6gwWcs3r3V4nPWcJW4xNhA,574
86
- dbt_platform_helper/utils/validation.py,sha256=LspCvwuOM1xz9xTy1YEnYBN3gdmwt_Zo53rvKu35jYg,30309
87
- dbt_platform_helper/utils/versioning.py,sha256=IBxdocJ8ZyJib38d1ja87tTuFE0iJ4npaDcAHQAKQ58,10825
87
+ dbt_platform_helper/utils/validation.py,sha256=ANGIA3k2_ATyZsPs7iqnXMNVjZC6o-rIbONxO9QZ8JU,30701
88
+ dbt_platform_helper/utils/versioning.py,sha256=rLCofLHPXoyc3v9ArDKcjW902p-UX6GCn8n7cjg5I-U,10918
88
89
  platform_helper.py,sha256=bly3JkwbfwnWTZSZziu40dbgzQItsK-DIMMvL6ArFDY,1893
89
- dbt_platform_helper-12.3.0.dist-info/LICENSE,sha256=dP79lN73--7LMApnankTGLqDbImXg8iYFqWgnExGkGk,1090
90
- dbt_platform_helper-12.3.0.dist-info/METADATA,sha256=_Ey-bDTeSkkSz4ozaGGo-ni6dO6gzKSghyFGGediWVY,3212
91
- dbt_platform_helper-12.3.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
92
- dbt_platform_helper-12.3.0.dist-info/entry_points.txt,sha256=QhbY8F434A-onsg0-FsdMd2U6HKh6Q7yCFFZrGUh5-M,67
93
- dbt_platform_helper-12.3.0.dist-info/RECORD,,
90
+ dbt_platform_helper-12.4.0.dist-info/LICENSE,sha256=dP79lN73--7LMApnankTGLqDbImXg8iYFqWgnExGkGk,1090
91
+ dbt_platform_helper-12.4.0.dist-info/METADATA,sha256=UuLXRBbntAkchMbR3jEaD2FCze0dH-3i54tIcpG49mo,3212
92
+ dbt_platform_helper-12.4.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
93
+ dbt_platform_helper-12.4.0.dist-info/entry_points.txt,sha256=QhbY8F434A-onsg0-FsdMd2U6HKh6Q7yCFFZrGUh5-M,67
94
+ dbt_platform_helper-12.4.0.dist-info/RECORD,,
@@ -1,29 +0,0 @@
1
- # This file maps addon types to svc level templates
2
-
3
- # explanation:
4
-
5
- # {addons-type}:
6
- # svc:
7
- # - template: path/to/template.yml
8
-
9
- redis: {}
10
- postgres: {}
11
- opensearch: {}
12
- s3:
13
- svc:
14
- - template: addons/svc/s3-policy.yml
15
- s3-policy:
16
- svc:
17
- - template: addons/svc/s3-policy.yml
18
- appconfig-ipfilter:
19
- svc:
20
- - template: addons/svc/appconfig-ipfilter.yml
21
- subscription-filter:
22
- svc:
23
- - template: addons/svc/subscription-filter.yml
24
- monitoring: {}
25
- vpc: {}
26
- alb: {}
27
- prometheus-policy:
28
- svc:
29
- - template: addons/svc/prometheus-policy.yml
@@ -1,147 +0,0 @@
1
- import os
2
-
3
- from dbt_platform_helper.constants import CONDUIT_ADDON_TYPES
4
-
5
-
6
- class ValidationException(Exception):
7
- pass
8
-
9
-
10
- class PlatformException(Exception):
11
- pass
12
-
13
-
14
- class AWSException(PlatformException):
15
- pass
16
-
17
-
18
- class ApplicationException(PlatformException):
19
- pass
20
-
21
-
22
- class CloudFormationException(AWSException):
23
- def __init__(self, stack_name: str, current_status: str):
24
- super().__init__(
25
- f"The CloudFormation stack '{stack_name}' is not in a good state: {current_status}"
26
- )
27
-
28
-
29
- class CommitNotFoundError:
30
- def __init__(self, commit: str):
31
- super().__init__(
32
- f"""The commit hash "{commit}" either does not exist or you need to run `git fetch`."""
33
- )
34
-
35
-
36
- class IncompatibleMajorVersion(ValidationException):
37
- def __init__(self, app_version: str, check_version: str):
38
- super().__init__()
39
- self.app_version = app_version
40
- self.check_version = check_version
41
-
42
-
43
- class IncompatibleMinorVersion(ValidationException):
44
- def __init__(self, app_version: str, check_version: str):
45
- super().__init__()
46
- self.app_version = app_version
47
- self.check_version = check_version
48
-
49
-
50
- class NoClusterError(AWSException):
51
- def __init__(self, application_name: str, environment: str):
52
- super().__init__(
53
- f"""No ECS cluster found for "{application_name}" in "{environment}" environment."""
54
- )
55
-
56
-
57
- class CreateTaskTimeoutError(AWSException):
58
- def __init__(self, addon_name: str, application_name: str, environment: str):
59
- super().__init__(
60
- f"""Client ({addon_name}) ECS task has failed to start for "{application_name}" in "{environment}" environment."""
61
- )
62
-
63
-
64
- class ParameterNotFoundError(AWSException):
65
- def __init__(self, application_name: str, environment: str):
66
- super().__init__(
67
- f"""No parameter called "/copilot/applications/{application_name}/environments/{environment}/addons". Try deploying the "{application_name}" "{environment}" environment."""
68
- )
69
-
70
-
71
- class AddonNotFoundError(AWSException):
72
- def __init__(self, addon_name: str):
73
- super().__init__(f"""Addon "{addon_name}" does not exist.""")
74
-
75
-
76
- class InvalidAddonTypeError(AWSException):
77
- def __init__(self, addon_type):
78
- self.addon_type = addon_type
79
- super().__init__(
80
- f"""Addon type "{self.addon_type}" is not supported, we support: {", ".join(CONDUIT_ADDON_TYPES)}."""
81
- )
82
-
83
-
84
- class AddonTypeMissingFromConfigError(AWSException):
85
- def __init__(self, addon_name: str):
86
- super().__init__(
87
- f"""The configuration for the addon {addon_name}, is misconfigured and missing the addon type."""
88
- )
89
-
90
-
91
- class CopilotCodebaseNotFoundError(PlatformException):
92
- def __init__(self, codebase: str):
93
- super().__init__(
94
- f"""The codebase "{codebase}" either does not exist or has not been deployed."""
95
- )
96
-
97
-
98
- class NotInCodeBaseRepositoryError(PlatformException):
99
- def __init__(self):
100
- super().__init__(
101
- "You are in the deploy repository; make sure you are in the application codebase repository.",
102
- )
103
-
104
-
105
- class NoCopilotCodebasesFoundError(PlatformException):
106
- def __init__(self, application_name: str):
107
- super().__init__(f"""No codebases found for application "{application_name}".""")
108
-
109
-
110
- class ImageNotFoundError(PlatformException):
111
- def __init__(self, commit: str):
112
- super().__init__(
113
- f"""The commit hash "{commit}" has not been built into an image, try the `platform-helper codebase build` command first."""
114
- )
115
-
116
-
117
- class ApplicationDeploymentNotTriggered(PlatformException):
118
- def __init__(self, codebase: str):
119
- super().__init__(f"""Your deployment for {codebase} was not triggered.""")
120
-
121
-
122
- class ApplicationNotFoundError(ApplicationException):
123
- def __init__(self, application_name: str):
124
- super().__init__(
125
- f"""The account "{os.environ.get("AWS_PROFILE")}" does not contain the application "{application_name}"; ensure you have set the environment variable "AWS_PROFILE" correctly."""
126
- )
127
-
128
-
129
- class ApplicationEnvironmentNotFoundError(ApplicationException):
130
- def __init__(self, environment: str):
131
- super().__init__(
132
- f"""The environment "{environment}" either does not exist or has not been deployed."""
133
- )
134
-
135
-
136
- class SecretNotFoundError(AWSException):
137
- def __init__(self, secret_name: str):
138
- super().__init__(f"""No secret called "{secret_name}".""")
139
-
140
-
141
- class ECSAgentNotRunning(AWSException):
142
- def __init__(self):
143
- super().__init__("""ECS exec agent never reached "RUNNING" status""")
144
-
145
-
146
- class ResourceNotFoundException(AWSException):
147
- pass