dbt-platform-helper 12.4.1__tar.gz → 12.5.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.

Files changed (102) hide show
  1. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/PKG-INFO +2 -2
  2. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/COMMANDS.md +0 -3
  3. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/config.py +2 -2
  4. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/copilot.py +47 -28
  5. dbt_platform_helper-12.5.0/dbt_platform_helper/commands/environment.py +86 -0
  6. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/pipeline.py +4 -5
  7. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/constants.py +9 -0
  8. dbt_platform_helper-12.5.0/dbt_platform_helper/domain/config_validator.py +242 -0
  9. dbt_platform_helper-12.5.0/dbt_platform_helper/domain/copilot_environment.py +204 -0
  10. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/domain/database_copy.py +7 -5
  11. dbt_platform_helper-12.5.0/dbt_platform_helper/domain/terraform_environment.py +53 -0
  12. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/jinja2_tags.py +1 -1
  13. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/providers/cache.py +15 -21
  14. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/providers/cloudformation.py +0 -1
  15. dbt_platform_helper-12.5.0/dbt_platform_helper/providers/config.py +90 -0
  16. dbt_platform_helper-12.5.0/dbt_platform_helper/providers/opensearch.py +36 -0
  17. dbt_platform_helper-12.5.0/dbt_platform_helper/providers/platform_config_schema.py +667 -0
  18. dbt_platform_helper-12.5.0/dbt_platform_helper/providers/redis.py +34 -0
  19. dbt_platform_helper-12.5.0/dbt_platform_helper/providers/yaml_file.py +83 -0
  20. dbt_platform_helper-12.5.0/dbt_platform_helper/templates/addons/svc/s3-cross-account-policy.yml +67 -0
  21. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/aws.py +1 -57
  22. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/files.py +0 -36
  23. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/template.py +10 -0
  24. dbt_platform_helper-12.5.0/dbt_platform_helper/utils/validation.py +32 -0
  25. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/pyproject.toml +2 -1
  26. dbt_platform_helper-12.4.1/dbt_platform_helper/commands/environment.py +0 -248
  27. dbt_platform_helper-12.4.1/dbt_platform_helper/providers/platform_config_schema.py +0 -605
  28. dbt_platform_helper-12.4.1/dbt_platform_helper/utils/validation.py +0 -354
  29. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/LICENSE +0 -0
  30. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/README.md +0 -0
  31. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/__init__.py +0 -0
  32. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/addon-plans.yml +0 -0
  33. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/__init__.py +0 -0
  34. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/application.py +0 -0
  35. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/codebase.py +0 -0
  36. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/conduit.py +0 -0
  37. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/database.py +0 -0
  38. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/generate.py +0 -0
  39. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/notify.py +0 -0
  40. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/secrets.py +0 -0
  41. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/commands/version.py +0 -0
  42. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/default-extensions.yml +0 -0
  43. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/domain/__init__.py +0 -0
  44. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/domain/codebase.py +0 -0
  45. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/domain/conduit.py +0 -0
  46. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/domain/maintenance_page.py +0 -0
  47. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/platform_exception.py +0 -0
  48. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/providers/__init__.py +0 -0
  49. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/providers/aws.py +0 -0
  50. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/providers/copilot.py +0 -0
  51. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/providers/ecs.py +0 -0
  52. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/providers/load_balancers.py +0 -0
  53. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/providers/secrets.py +0 -0
  54. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/providers/validation.py +0 -0
  55. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/.copilot/config.yml +0 -0
  56. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/.copilot/image_build_run.sh +0 -0
  57. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/.copilot/phases/build.sh +0 -0
  58. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/.copilot/phases/install.sh +0 -0
  59. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/.copilot/phases/post_build.sh +0 -0
  60. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/.copilot/phases/pre_build.sh +0 -0
  61. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/COMMANDS.md.jinja +0 -0
  62. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/addon-instructions.txt +0 -0
  63. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/addons/README.md +0 -0
  64. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/addons/svc/appconfig-ipfilter.yml +0 -0
  65. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/addons/svc/prometheus-policy.yml +0 -0
  66. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/addons/svc/s3-policy.yml +0 -0
  67. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/addons/svc/subscription-filter.yml +0 -0
  68. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/ci-codebuild-role-policy.json +0 -0
  69. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/create-codebuild-role.json +0 -0
  70. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/custom-codebuild-role-policy.json +0 -0
  71. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/env/manifest.yml +0 -0
  72. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/env/terraform-overrides/cfn.patches.yml +0 -0
  73. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/environment-pipelines/main.tf +0 -0
  74. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/environments/main.tf +0 -0
  75. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/manifest.yml +0 -0
  76. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/.gitignore +0 -0
  77. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/bin/override.ts +0 -0
  78. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/buildspec.deploy.yml +0 -0
  79. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/buildspec.image.yml +0 -0
  80. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/cdk.json +0 -0
  81. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/package-lock.json +0 -0
  82. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/package.json +0 -0
  83. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/stack.ts +0 -0
  84. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/tsconfig.json +0 -0
  85. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/pipelines/codebase/overrides/types.ts +0 -0
  86. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/svc/maintenance_pages/default.html +0 -0
  87. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/svc/maintenance_pages/dmas-migration.html +0 -0
  88. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/svc/maintenance_pages/migration.html +0 -0
  89. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/svc/manifest-backend.yml +0 -0
  90. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/svc/manifest-public.yml +0 -0
  91. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/templates/svc/overrides/cfn.patches.yml +0 -0
  92. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/__init__.py +0 -0
  93. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/application.py +0 -0
  94. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/arn_parser.py +0 -0
  95. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/click.py +0 -0
  96. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/cloudfoundry.py +0 -0
  97. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/git.py +0 -0
  98. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/manifests.py +0 -0
  99. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/messages.py +0 -0
  100. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/platform_config.py +0 -0
  101. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/dbt_platform_helper/utils/versioning.py +0 -0
  102. {dbt_platform_helper-12.4.1 → dbt_platform_helper-12.5.0}/platform_helper.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: dbt-platform-helper
3
- Version: 12.4.1
3
+ Version: 12.5.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
@@ -551,9 +551,6 @@ platform-helper pipeline generate
551
551
  This command does the following in relation to the codebase pipelines:
552
552
  - Generates the copilot pipeline manifest.yml for copilot/pipelines/<codebase_pipeline_name>
553
553
 
554
- (Deprecated) This command does the following for non terraform projects (legacy AWS Copilot):
555
- - Generates the copilot manifest.yml for copilot/environments/<environment>
556
-
557
554
  ## Usage
558
555
 
559
556
  ```
@@ -8,11 +8,11 @@ import botocore
8
8
  import click
9
9
  from prettytable import PrettyTable
10
10
 
11
+ from dbt_platform_helper.providers.config import ConfigProvider
11
12
  from dbt_platform_helper.providers.validation import IncompatibleMajorVersionException
12
13
  from dbt_platform_helper.providers.validation import ValidationException
13
14
  from dbt_platform_helper.utils import versioning
14
15
  from dbt_platform_helper.utils.click import ClickDocOptGroup
15
- from dbt_platform_helper.utils.validation import config_file_check
16
16
  from dbt_platform_helper.utils.versioning import get_platform_helper_versions
17
17
 
18
18
  yes = "\033[92m✔\033[0m"
@@ -98,7 +98,7 @@ def deployment():
98
98
 
99
99
  recommendations = {}
100
100
 
101
- config_file_check()
101
+ ConfigProvider.config_file_check()
102
102
 
103
103
  for template_file in addons_templates:
104
104
  generated_with_version = maybe
@@ -7,17 +7,22 @@ from pathlib import PosixPath
7
7
 
8
8
  import click
9
9
  import yaml
10
+ from schema import SchemaError
10
11
 
11
12
  from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE
13
+ from dbt_platform_helper.domain.config_validator import ConfigValidator
14
+ from dbt_platform_helper.domain.copilot_environment import CopilotTemplating
15
+ from dbt_platform_helper.providers.config import ConfigProvider
12
16
  from dbt_platform_helper.utils.application import get_application_name
13
17
  from dbt_platform_helper.utils.application import load_application
14
18
  from dbt_platform_helper.utils.aws import get_aws_session_or_abort
15
19
  from dbt_platform_helper.utils.click import ClickDocOptGroup
16
20
  from dbt_platform_helper.utils.files import generate_override_files
17
21
  from dbt_platform_helper.utils.files import mkfile
22
+ from dbt_platform_helper.utils.messages import abort_with_error
23
+ from dbt_platform_helper.utils.template import ADDON_TEMPLATE_MAP
18
24
  from dbt_platform_helper.utils.template import camel_case
19
25
  from dbt_platform_helper.utils.template import setup_templates
20
- from dbt_platform_helper.utils.validation import config_file_check
21
26
  from dbt_platform_helper.utils.validation import validate_addons
22
27
  from dbt_platform_helper.utils.versioning import (
23
28
  check_platform_helper_version_needs_update,
@@ -35,14 +40,6 @@ SERVICE_TYPES = [
35
40
  "Worker Service",
36
41
  ]
37
42
 
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
-
46
43
 
47
44
  def list_copilot_local_environments():
48
45
  return [
@@ -244,25 +241,42 @@ def _get_s3_kms_alias_arns(session, application_name, config):
244
241
  return arns
245
242
 
246
243
 
244
+ def copilot_provider():
245
+ return CopilotTemplating()
246
+
247
+
247
248
  @copilot.command()
248
249
  def make_addons():
249
250
  """Generate addons CloudFormation for each environment."""
250
- output_dir = Path(".").absolute()
251
- config_file_check()
251
+ try:
252
+ config_provider = ConfigProvider(ConfigValidator())
253
+ _make_addons(config_provider)
254
+ except Exception as exc:
255
+ abort_with_error(exc)
256
+
257
+
258
+ def _make_addons(config_provider: ConfigProvider):
259
+ config_provider.config_file_check()
260
+ try:
261
+ config = config_provider.load_and_validate_platform_config()
262
+ except SchemaError as ex:
263
+ click.secho(f"Invalid `{PLATFORM_CONFIG_FILE}` file: {str(ex)}", fg="red")
264
+ raise click.Abort
252
265
 
253
266
  templates = setup_templates()
254
- config = _get_config()
267
+ extensions = _get_extensions()
255
268
  session = get_aws_session_or_abort()
256
269
 
257
270
  application_name = get_application_name()
258
271
 
259
272
  click.echo("\n>>> Generating Terraform compatible addons CloudFormation\n")
260
273
 
274
+ output_dir = Path(".").absolute()
261
275
  env_path = Path(f"copilot/environments/")
262
276
  env_addons_path = env_path / "addons"
263
277
  env_overrides_path = env_path / "overrides"
264
278
 
265
- _cleanup_old_files(config, output_dir, env_addons_path, env_overrides_path)
279
+ _cleanup_old_files(extensions, output_dir, env_addons_path, env_overrides_path)
266
280
  _generate_env_overrides(output_dir)
267
281
 
268
282
  svc_names = list_copilot_local_services()
@@ -271,33 +285,33 @@ def make_addons():
271
285
  _generate_svc_overrides(base_path, templates, svc_name)
272
286
 
273
287
  services = []
274
- for addon_name, addon_config in config.items():
275
- print(f">>>>>>>>> {addon_name}")
276
- addon_type = addon_config.pop("type")
277
- environments = addon_config.pop("environments")
288
+ for ext_name, ext_data in extensions.items():
289
+ extension = {**ext_data}
290
+ addon_type = extension.pop("type")
291
+ environments = extension.pop("environments")
278
292
  environment_addon_config = {
279
293
  "addon_type": addon_type,
280
294
  "environments": environments,
281
- "name": addon_config.get("name", None) or addon_name,
282
- "prefix": camel_case(addon_name),
283
- "secret_name": addon_name.upper().replace("-", "_"),
284
- **addon_config,
295
+ "name": extension.get("name", None) or ext_name,
296
+ "prefix": camel_case(ext_name),
297
+ "secret_name": ext_name.upper().replace("-", "_"),
298
+ **extension,
285
299
  }
286
300
 
287
301
  services.append(environment_addon_config)
288
302
 
289
303
  service_addon_config = {
290
304
  "application_name": application_name,
291
- "name": addon_config.get("name", None) or addon_name,
292
- "prefix": camel_case(addon_name),
305
+ "name": extension.get("name", None) or ext_name,
306
+ "prefix": camel_case(ext_name),
293
307
  "environments": environments,
294
- **addon_config,
308
+ **extension,
295
309
  }
296
310
 
297
311
  log_destination_arns = get_log_destination_arn()
298
312
 
299
313
  if addon_type in ["s3", "s3-policy"]:
300
- if config[addon_name].get("serve_static_content"):
314
+ if extensions[ext_name].get("serve_static_content"):
301
315
  continue
302
316
 
303
317
  s3_kms_arns = _get_s3_kms_alias_arns(session, application_name, environments)
@@ -307,8 +321,8 @@ def make_addons():
307
321
  )
308
322
 
309
323
  _generate_service_addons(
310
- addon_config,
311
- addon_name,
324
+ extension,
325
+ ext_name,
312
326
  addon_type,
313
327
  output_dir,
314
328
  service_addon_config,
@@ -316,10 +330,15 @@ def make_addons():
316
330
  log_destination_arns,
317
331
  )
318
332
 
333
+ environments = config_provider.apply_environment_defaults(config)["environments"]
334
+
335
+ provider = copilot_provider()
336
+ provider.generate_cross_account_s3_policies(environments, extensions)
337
+
319
338
  click.echo(templates.get_template("addon-instructions.txt").render(services=services))
320
339
 
321
340
 
322
- def _get_config():
341
+ def _get_extensions():
323
342
  config = _validate_and_normalise_extensions_config(PACKAGE_DIR / "default-extensions.yml")
324
343
  project_config = _validate_and_normalise_extensions_config(PLATFORM_CONFIG_FILE, "extensions")
325
344
  config.update(project_config)
@@ -0,0 +1,86 @@
1
+ import click
2
+ from schema import SchemaError
3
+
4
+ from dbt_platform_helper.constants import DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION
5
+ from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE
6
+ from dbt_platform_helper.domain.config_validator import ConfigValidator
7
+ from dbt_platform_helper.domain.copilot_environment import CopilotEnvironment
8
+ from dbt_platform_helper.domain.maintenance_page import MaintenancePageProvider
9
+ from dbt_platform_helper.domain.terraform_environment import TerraformEnvironment
10
+ from dbt_platform_helper.platform_exception import PlatformException
11
+ from dbt_platform_helper.providers.config import ConfigProvider
12
+ from dbt_platform_helper.utils.click import ClickDocOptGroup
13
+ from dbt_platform_helper.utils.versioning import (
14
+ check_platform_helper_version_needs_update,
15
+ )
16
+
17
+ AVAILABLE_TEMPLATES = ["default", "migration", "dmas-migration"]
18
+
19
+
20
+ @click.group(cls=ClickDocOptGroup)
21
+ def environment():
22
+ """Commands affecting environments."""
23
+ check_platform_helper_version_needs_update()
24
+
25
+
26
+ @environment.command()
27
+ @click.option("--app", type=str, required=True)
28
+ @click.option("--env", type=str, required=True)
29
+ @click.option("--svc", type=str, required=True, multiple=True, default=["web"])
30
+ @click.option(
31
+ "--template",
32
+ type=click.Choice(AVAILABLE_TEMPLATES),
33
+ default="default",
34
+ help="The maintenance page you wish to put up.",
35
+ )
36
+ @click.option("--vpc", type=str)
37
+ def offline(app, env, svc, template, vpc):
38
+ """Take load-balanced web services offline with a maintenance page."""
39
+ try:
40
+ MaintenancePageProvider().activate(app, env, svc, template, vpc)
41
+ except PlatformException as err:
42
+ click.secho(str(err), fg="red")
43
+ raise click.Abort
44
+
45
+
46
+ @environment.command()
47
+ @click.option("--app", type=str, required=True)
48
+ @click.option("--env", type=str, required=True)
49
+ def online(app, env):
50
+ """Remove a maintenance page from an environment."""
51
+ try:
52
+ MaintenancePageProvider().deactivate(app, env)
53
+ except PlatformException as err:
54
+ click.secho(str(err), fg="red")
55
+ raise click.Abort
56
+
57
+
58
+ @environment.command()
59
+ @click.option("--vpc-name", hidden=True)
60
+ @click.option("--name", "-n", required=True)
61
+ def generate(name, vpc_name):
62
+ if vpc_name:
63
+ click.secho(
64
+ f"This option is deprecated. Please add the VPC name for your envs to {PLATFORM_CONFIG_FILE}",
65
+ fg="red",
66
+ )
67
+ raise click.Abort
68
+ try:
69
+ config_provider = ConfigProvider(ConfigValidator())
70
+ CopilotEnvironment(config_provider).generate(name)
71
+ except SchemaError as ex:
72
+ click.secho(f"Invalid `{PLATFORM_CONFIG_FILE}` file: {str(ex)}", fg="red")
73
+ raise click.Abort
74
+
75
+
76
+ @environment.command(help="Generate terraform manifest for the specified environment.")
77
+ @click.option(
78
+ "--name", "-n", required=True, help="The name of the environment to generate a manifest for."
79
+ )
80
+ @click.option(
81
+ "--terraform-platform-modules-version",
82
+ help=f"Override the default version of terraform-platform-modules. (Default version is '{DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION}').",
83
+ )
84
+ def generate_terraform(name, terraform_platform_modules_version):
85
+ config_provider = ConfigProvider(ConfigValidator())
86
+ TerraformEnvironment(config_provider).generate(name, terraform_platform_modules_version)
@@ -6,6 +6,8 @@ from shutil import rmtree
6
6
  import click
7
7
 
8
8
  from dbt_platform_helper.constants import DEFAULT_TERRAFORM_PLATFORM_MODULES_VERSION
9
+ from dbt_platform_helper.domain.config_validator import ConfigValidator
10
+ from dbt_platform_helper.providers.config import ConfigProvider
9
11
  from dbt_platform_helper.utils.application import get_application_name
10
12
  from dbt_platform_helper.utils.aws import get_account_details
11
13
  from dbt_platform_helper.utils.aws import get_codestar_connection_arn
@@ -16,7 +18,6 @@ from dbt_platform_helper.utils.files import mkfile
16
18
  from dbt_platform_helper.utils.git import git_remote
17
19
  from dbt_platform_helper.utils.messages import abort_with_error
18
20
  from dbt_platform_helper.utils.template import setup_templates
19
- from dbt_platform_helper.utils.validation import load_and_validate_platform_config
20
21
  from dbt_platform_helper.utils.versioning import (
21
22
  check_platform_helper_version_needs_update,
22
23
  )
@@ -60,11 +61,9 @@ def generate(terraform_platform_modules_version, deploy_branch):
60
61
 
61
62
  This command does the following in relation to the codebase pipelines:
62
63
  - Generates the copilot pipeline manifest.yml for copilot/pipelines/<codebase_pipeline_name>
63
-
64
- (Deprecated) This command does the following for non terraform projects (legacy AWS Copilot):
65
- - Generates the copilot manifest.yml for copilot/environments/<environment>
66
64
  """
67
- pipeline_config = load_and_validate_platform_config()
65
+ config_provider = ConfigProvider(ConfigValidator())
66
+ pipeline_config = config_provider.load_and_validate_platform_config()
68
67
 
69
68
  has_codebase_pipelines = CODEBASE_PIPELINES_KEY in pipeline_config
70
69
  has_environment_pipelines = ENVIRONMENT_PIPELINES_KEY in pipeline_config
@@ -16,3 +16,12 @@ CONDUIT_ADDON_TYPES = [
16
16
  "redis",
17
17
  ]
18
18
  CONDUIT_DOCKER_IMAGE_LOCATION = "public.ecr.aws/uktrade/tunnel"
19
+ HYPHENATED_APPLICATION_NAME = "hyphenated-application-name"
20
+ ALPHANUMERIC_ENVIRONMENT_NAME = "alphanumericenvironmentname123"
21
+ ALPHANUMERIC_SERVICE_NAME = "alphanumericservicename123"
22
+ COPILOT_IDENTIFIER = "c0PIlotiD3ntIF3r"
23
+ CLUSTER_NAME_SUFFIX = f"Cluster-{COPILOT_IDENTIFIER}"
24
+ SERVICE_NAME_SUFFIX = f"Service-{COPILOT_IDENTIFIER}"
25
+ REFRESH_TOKEN_MESSAGE = (
26
+ "To refresh this SSO session run `aws sso login` with the corresponding profile"
27
+ )
@@ -0,0 +1,242 @@
1
+ from typing import Callable
2
+
3
+ import boto3
4
+ import click
5
+
6
+ from dbt_platform_helper.constants import CODEBASE_PIPELINES_KEY
7
+ from dbt_platform_helper.constants import ENVIRONMENTS_KEY
8
+ from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE
9
+ from dbt_platform_helper.providers.opensearch import OpensearchProvider
10
+ from dbt_platform_helper.providers.redis import RedisProvider
11
+ from dbt_platform_helper.utils.messages import abort_with_error
12
+
13
+
14
+ class ConfigValidator:
15
+
16
+ def __init__(self, validations: Callable[[dict], None] = None):
17
+ self.validations = validations or [
18
+ self.validate_supported_redis_versions,
19
+ self.validate_supported_opensearch_versions,
20
+ self.validate_environment_pipelines,
21
+ self.validate_codebase_pipelines,
22
+ self.validate_environment_pipelines_triggers,
23
+ self.validate_database_copy_section,
24
+ ]
25
+
26
+ def run_validations(self, config: dict):
27
+ for validation in self.validations:
28
+ validation(config)
29
+
30
+ def _validate_extension_supported_versions(
31
+ self, config, extension_type, version_key, get_supported_versions
32
+ ):
33
+ extensions = config.get("extensions", {})
34
+ if not extensions:
35
+ return
36
+
37
+ extensions_for_type = [
38
+ extension
39
+ for extension in config.get("extensions", {}).values()
40
+ if extension.get("type") == extension_type
41
+ ]
42
+
43
+ supported_extension_versions = get_supported_versions()
44
+ extensions_with_invalid_version = []
45
+
46
+ for extension in extensions_for_type:
47
+
48
+ environments = extension.get("environments", {})
49
+
50
+ if not isinstance(environments, dict):
51
+ click.secho(
52
+ f"Error: {extension_type} extension definition is invalid type, expected dictionary",
53
+ fg="red",
54
+ )
55
+ continue
56
+ for environment, env_config in environments.items():
57
+
58
+ # An extension version doesn't need to be specified for all environments, provided one is specified under "*".
59
+ # So check if the version is set before checking if it's supported
60
+ extension_version = env_config.get(version_key)
61
+ if extension_version and extension_version not in supported_extension_versions:
62
+ extensions_with_invalid_version.append(
63
+ {"environment": environment, "version": extension_version}
64
+ )
65
+
66
+ for version_failure in extensions_with_invalid_version:
67
+ click.secho(
68
+ f"{extension_type} version for environment {version_failure['environment']} is not in the list of supported {extension_type} versions: {supported_extension_versions}. Provided Version: {version_failure['version']}",
69
+ fg="red",
70
+ )
71
+
72
+ def validate_supported_redis_versions(self, config):
73
+ return self._validate_extension_supported_versions(
74
+ config=config,
75
+ extension_type="redis",
76
+ version_key="engine",
77
+ get_supported_versions=RedisProvider(
78
+ boto3.client("elasticache")
79
+ ).get_supported_redis_versions,
80
+ )
81
+
82
+ def validate_supported_opensearch_versions(self, config):
83
+ return self._validate_extension_supported_versions(
84
+ config=config,
85
+ extension_type="opensearch",
86
+ version_key="engine",
87
+ get_supported_versions=OpensearchProvider(
88
+ boto3.client("opensearch")
89
+ ).get_supported_opensearch_versions,
90
+ )
91
+
92
+ def validate_environment_pipelines(self, config):
93
+ bad_pipelines = {}
94
+ for pipeline_name, pipeline in config.get("environment_pipelines", {}).items():
95
+ bad_envs = []
96
+ pipeline_account = pipeline.get("account", None)
97
+ if pipeline_account:
98
+ for env in pipeline.get("environments", {}).keys():
99
+ env_account = (
100
+ config.get("environments", {})
101
+ .get(env, {})
102
+ .get("accounts", {})
103
+ .get("deploy", {})
104
+ .get("name")
105
+ )
106
+ if not env_account == pipeline_account:
107
+ bad_envs.append(env)
108
+ if bad_envs:
109
+ bad_pipelines[pipeline_name] = {"account": pipeline_account, "bad_envs": bad_envs}
110
+ if bad_pipelines:
111
+ message = "The following pipelines are misconfigured:"
112
+ for pipeline, detail in bad_pipelines.items():
113
+ envs = detail["bad_envs"]
114
+ acc = detail["account"]
115
+ message += f" '{pipeline}' - these environments are not in the '{acc}' account: {', '.join(envs)}\n"
116
+ abort_with_error(message)
117
+
118
+ def validate_codebase_pipelines(self, config):
119
+ if CODEBASE_PIPELINES_KEY in config:
120
+ for codebase in config[CODEBASE_PIPELINES_KEY]:
121
+ codebase_environments = []
122
+
123
+ for pipeline in codebase["pipelines"]:
124
+ codebase_environments += [e["name"] for e in pipeline[ENVIRONMENTS_KEY]]
125
+
126
+ unique_codebase_environments = sorted(list(set(codebase_environments)))
127
+
128
+ if sorted(codebase_environments) != sorted(unique_codebase_environments):
129
+ abort_with_error(
130
+ f"The {PLATFORM_CONFIG_FILE} file is invalid, each environment can only be "
131
+ "listed in a single pipeline per codebase"
132
+ )
133
+
134
+ def validate_environment_pipelines_triggers(self, config):
135
+ errors = []
136
+ pipelines_with_triggers = {
137
+ pipeline_name: pipeline
138
+ for pipeline_name, pipeline in config.get("environment_pipelines", {}).items()
139
+ if "pipeline_to_trigger" in pipeline
140
+ }
141
+
142
+ for pipeline_name, pipeline in pipelines_with_triggers.items():
143
+ pipeline_to_trigger = pipeline["pipeline_to_trigger"]
144
+ if pipeline_to_trigger not in config.get("environment_pipelines", {}):
145
+ message = f" '{pipeline_name}' - '{pipeline_to_trigger}' is not a valid target pipeline to trigger"
146
+
147
+ errors.append(message)
148
+ continue
149
+
150
+ if pipeline_to_trigger == pipeline_name:
151
+ message = f" '{pipeline_name}' - pipelines cannot trigger themselves"
152
+ errors.append(message)
153
+
154
+ if errors:
155
+ error_message = "The following pipelines are misconfigured: \n"
156
+ abort_with_error(error_message + "\n ".join(errors))
157
+
158
+ def validate_database_copy_section(self, config):
159
+ extensions = config.get("extensions", {})
160
+ if not extensions:
161
+ return
162
+
163
+ postgres_extensions = {
164
+ key: ext for key, ext in extensions.items() if ext.get("type", None) == "postgres"
165
+ }
166
+
167
+ if not postgres_extensions:
168
+ return
169
+
170
+ errors = []
171
+
172
+ for extension_name, extension in postgres_extensions.items():
173
+ database_copy_sections = extension.get("database_copy", [])
174
+
175
+ if not database_copy_sections:
176
+ return
177
+
178
+ all_environments = [
179
+ env for env in config.get("environments", {}).keys() if not env == "*"
180
+ ]
181
+ all_envs_string = ", ".join(all_environments)
182
+
183
+ for section in database_copy_sections:
184
+ from_env = section["from"]
185
+ to_env = section["to"]
186
+
187
+ from_account = (
188
+ config.get("environments", {})
189
+ .get(from_env, {})
190
+ .get("accounts", {})
191
+ .get("deploy", {})
192
+ .get("id")
193
+ )
194
+ to_account = (
195
+ config.get("environments", {})
196
+ .get(to_env, {})
197
+ .get("accounts", {})
198
+ .get("deploy", {})
199
+ .get("id")
200
+ )
201
+
202
+ if from_env == to_env:
203
+ errors.append(
204
+ f"database_copy 'to' and 'from' cannot be the same environment in extension '{extension_name}'."
205
+ )
206
+
207
+ if "prod" in to_env:
208
+ errors.append(
209
+ f"Copying to a prod environment is not supported: database_copy 'to' cannot be '{to_env}' in extension '{extension_name}'."
210
+ )
211
+
212
+ if from_env not in all_environments:
213
+ errors.append(
214
+ f"database_copy 'from' parameter must be a valid environment ({all_envs_string}) but was '{from_env}' in extension '{extension_name}'."
215
+ )
216
+
217
+ if to_env not in all_environments:
218
+ errors.append(
219
+ f"database_copy 'to' parameter must be a valid environment ({all_envs_string}) but was '{to_env}' in extension '{extension_name}'."
220
+ )
221
+
222
+ if from_account != to_account:
223
+ if "from_account" not in section:
224
+ errors.append(
225
+ f"Environments '{from_env}' and '{to_env}' are in different AWS accounts. The 'from_account' parameter must be present."
226
+ )
227
+ elif section["from_account"] != from_account:
228
+ errors.append(
229
+ f"Incorrect value for 'from_account' for environment '{from_env}'"
230
+ )
231
+
232
+ if "to_account" not in section:
233
+ errors.append(
234
+ f"Environments '{from_env}' and '{to_env}' are in different AWS accounts. The 'to_account' parameter must be present."
235
+ )
236
+ elif section["to_account"] != to_account:
237
+ errors.append(
238
+ f"Incorrect value for 'to_account' for environment '{to_env}'"
239
+ )
240
+
241
+ if errors:
242
+ abort_with_error("\n".join(errors))