dbt-platform-helper 15.6.0__tar.gz → 15.7.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 (111) hide show
  1. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/PKG-INFO +4 -5
  2. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/COMMANDS.md +51 -0
  3. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/secrets.py +0 -20
  4. dbt_platform_helper-15.7.0/dbt_platform_helper/commands/service.py +53 -0
  5. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/constants.py +8 -0
  6. dbt_platform_helper-15.7.0/dbt_platform_helper/domain/service.py +153 -0
  7. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/entities/platform_config_schema.py +8 -1
  8. dbt_platform_helper-15.7.0/dbt_platform_helper/entities/service.py +114 -0
  9. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/config.py +28 -0
  10. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/config_validator.py +23 -0
  11. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/environment_variable.py +2 -2
  12. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/terraform_manifest.py +74 -4
  13. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/svc/overrides/cfn.patches.yml +5 -0
  14. dbt_platform_helper-15.7.0/dbt_platform_helper/utils/deep_merge.py +10 -0
  15. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/platform_helper.py +2 -0
  16. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/pyproject.toml +5 -6
  17. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/LICENSE +0 -0
  18. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/README.md +0 -0
  19. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/__init__.py +0 -0
  20. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/__init__.py +0 -0
  21. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/application.py +0 -0
  22. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/codebase.py +0 -0
  23. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/conduit.py +0 -0
  24. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/config.py +0 -0
  25. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/copilot.py +0 -0
  26. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/database.py +0 -0
  27. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/environment.py +0 -0
  28. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/generate.py +0 -0
  29. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/notify.py +0 -0
  30. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/pipeline.py +0 -0
  31. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/commands/version.py +0 -0
  32. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/default-extensions.yml +0 -0
  33. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/__init__.py +0 -0
  34. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/codebase.py +0 -0
  35. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/conduit.py +0 -0
  36. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/config.py +0 -0
  37. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/copilot.py +0 -0
  38. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/copilot_environment.py +0 -0
  39. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/database_copy.py +0 -0
  40. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/maintenance_page.py +0 -0
  41. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/notify.py +0 -0
  42. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/pipelines.py +0 -0
  43. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/plans.py +0 -0
  44. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/terraform_environment.py +0 -0
  45. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/domain/versioning.py +0 -0
  46. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/entities/semantic_version.py +0 -0
  47. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/jinja2_tags.py +0 -0
  48. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/platform_exception.py +0 -0
  49. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/__init__.py +0 -0
  50. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/aws/__init__.py +0 -0
  51. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/aws/exceptions.py +0 -0
  52. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/aws/interfaces.py +0 -0
  53. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/aws/opensearch.py +0 -0
  54. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/aws/redis.py +0 -0
  55. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/aws/sso_auth.py +0 -0
  56. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/cache.py +0 -0
  57. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/cloudformation.py +0 -0
  58. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/copilot.py +0 -0
  59. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/ecr.py +0 -0
  60. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/ecs.py +0 -0
  61. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/files.py +0 -0
  62. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/io.py +0 -0
  63. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/kms.py +0 -0
  64. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/load_balancers.py +0 -0
  65. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/parameter_store.py +0 -0
  66. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/schema_migrations/__init__.py +0 -0
  67. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/schema_migrations/schema_v0_to_v1_migration.py +0 -0
  68. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/schema_migrator.py +0 -0
  69. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/secrets.py +0 -0
  70. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/slack_channel_notifier.py +0 -0
  71. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/validation.py +0 -0
  72. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/version.py +0 -0
  73. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/version_status.py +0 -0
  74. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/vpc.py +0 -0
  75. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/providers/yaml_file.py +0 -0
  76. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/.copilot/config.yml +0 -0
  77. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/.copilot/image_build_run.sh +0 -0
  78. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/.copilot/phases/build.sh +0 -0
  79. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/.copilot/phases/install.sh +0 -0
  80. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/.copilot/phases/post_build.sh +0 -0
  81. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/.copilot/phases/pre_build.sh +0 -0
  82. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/COMMANDS.md.jinja +0 -0
  83. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/addon-instructions.txt +0 -0
  84. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/addons/README.md +0 -0
  85. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/addons/svc/appconfig-ipfilter.yml +0 -0
  86. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/addons/svc/prometheus-policy.yml +0 -0
  87. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/addons/svc/s3-cross-account-policy.yml +0 -0
  88. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/addons/svc/s3-policy.yml +0 -0
  89. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/addons/svc/subscription-filter.yml +0 -0
  90. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/ci-codebuild-role-policy.json +0 -0
  91. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/create-codebuild-role.json +0 -0
  92. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/custom-codebuild-role-policy.json +0 -0
  93. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/env/manifest.yml +0 -0
  94. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/env/terraform-overrides/cfn.patches.yml +0 -0
  95. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/environment-pipelines/main.tf +0 -0
  96. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/svc/maintenance_pages/default.html +0 -0
  97. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/svc/maintenance_pages/dmas-migration.html +0 -0
  98. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/templates/svc/maintenance_pages/migration.html +0 -0
  99. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utilities/decorators.py +0 -0
  100. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utils/__init__.py +0 -0
  101. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utils/application.py +0 -0
  102. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utils/arn_parser.py +0 -0
  103. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utils/aws.py +0 -0
  104. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utils/click.py +0 -0
  105. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utils/git.py +0 -0
  106. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utils/messages.py +0 -0
  107. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utils/template.py +0 -0
  108. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/dbt_platform_helper/utils/validation.py +0 -0
  109. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/terraform/elasticache-redis/plans.yml +0 -0
  110. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/terraform/opensearch/plans.yml +0 -0
  111. {dbt_platform_helper-15.6.0 → dbt_platform_helper-15.7.0}/terraform/postgres/plans.yml +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dbt-platform-helper
3
- Version: 15.6.0
3
+ Version: 15.7.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
7
7
  Author-email: sre-team@digital.trade.gov.uk
8
- Requires-Python: >=3.9, !=2.7.*, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*, !=3.7.*, !=3.8.*
8
+ Requires-Python: >3.9.1,<4.0
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.10
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
15
  Requires-Dist: Jinja2 (==3.1.6)
16
- Requires-Dist: PyYAML (==6.0.1)
16
+ Requires-Dist: PyYAML (==6.0.2)
17
17
  Requires-Dist: aiohttp (>=3.11.16,<4.0.0)
18
18
  Requires-Dist: boto3 (>=1.35.2,<2.0.0)
19
19
  Requires-Dist: boto3-stubs (>=1.26.148,<2.0.0)
@@ -23,7 +23,6 @@ Requires-Dist: cfn-flip (==1.3.0)
23
23
  Requires-Dist: cfn-lint (>=1.4.2,<2.0.0)
24
24
  Requires-Dist: checkov (>=3.2.405,<4.0.0)
25
25
  Requires-Dist: click (>=8.1.3,<9.0.0)
26
- Requires-Dist: cloudfoundry-client (==1.35.2)
27
26
  Requires-Dist: cryptography (>=44.0.1,<45)
28
27
  Requires-Dist: jinja2-simple-tags (>=0.5.0,<0.6.0)
29
28
  Requires-Dist: jsonschema (>=4.17.0,<4.18.0)
@@ -34,7 +33,7 @@ Requires-Dist: requests (>=2.31.0,<3.0.0)
34
33
  Requires-Dist: schema (==0.7.5)
35
34
  Requires-Dist: semver (>=3.0.2,<4.0.0)
36
35
  Requires-Dist: slack-sdk (>=3.27.1,<4.0.0)
37
- Requires-Dist: tomlkit (>=0.12.2,<0.13.0)
36
+ Requires-Dist: tomlkit (>=0.12.2,<0.14.0)
38
37
  Requires-Dist: yamllint (>=1.35.1,<2.0.0)
39
38
  Description-Content-Type: text/markdown
40
39
 
@@ -27,6 +27,8 @@
27
27
  - [platform-helper secrets](#platform-helper-secrets)
28
28
  - [platform-helper secrets copy](#platform-helper-secrets-copy)
29
29
  - [platform-helper secrets list](#platform-helper-secrets-list)
30
+ - [platform-helper service](#platform-helper-service)
31
+ - [platform-helper service generate](#platform-helper-service-generate)
30
32
  - [platform-helper notify](#platform-helper-notify)
31
33
  - [platform-helper notify environment-progress](#platform-helper-notify-environment-progress)
32
34
  - [platform-helper notify post-message](#platform-helper-notify-post-message)
@@ -66,6 +68,7 @@ platform-helper <command> [--version]
66
68
  - [`notify` ↪](#platform-helper-notify)
67
69
  - [`pipeline` ↪](#platform-helper-pipeline)
68
70
  - [`secrets` ↪](#platform-helper-secrets)
71
+ - [`service` ↪](#platform-helper-service)
69
72
  - [`version` ↪](#platform-helper-version)
70
73
 
71
74
  # platform-helper application
@@ -660,6 +663,54 @@ platform-helper secrets list <application> <environment>
660
663
  - `--help <boolean>` _Defaults to False._
661
664
  - Show this message and exit.
662
665
 
666
+ # platform-helper service
667
+
668
+ [↩ Parent](#platform-helper)
669
+
670
+ Commands affecting services.
671
+
672
+ ## Usage
673
+
674
+ ```
675
+ platform-helper service generate
676
+ ```
677
+
678
+ ## Options
679
+
680
+ - `--help <boolean>` _Defaults to False._
681
+ - Show this message and exit.
682
+
683
+ ## Commands
684
+
685
+ - [`generate` ↪](#platform-helper-service-generate)
686
+
687
+ # platform-helper service generate
688
+
689
+ [↩ Parent](#platform-helper-service)
690
+
691
+ Generate terraform manifest for the specified service(s).
692
+
693
+ ## Usage
694
+
695
+ ```
696
+ platform-helper service generate [--name <name>] [--environment <environment>]
697
+ [--image-tag <image_tag>]
698
+ ```
699
+
700
+ ## Options
701
+
702
+ - `--name
703
+ -n <text>`
704
+ - The name of the service to generate a manifest for. Multiple values accepted.
705
+ - `--environment
706
+ -e <text>`
707
+ - The name of the environment to generate service manifests for. Multiple values accepted.
708
+ - `--image-tag
709
+ -i <text>`
710
+ - Docker image tag to deploy for the service. Overrides the $IMAGE_TAG environment variable.
711
+ - `--help <boolean>` _Defaults to False._
712
+ - Show this message and exit.
713
+
663
714
  # platform-helper notify
664
715
 
665
716
  [↩ Parent](#platform-helper)
@@ -4,7 +4,6 @@ from pathlib import Path
4
4
 
5
5
  import click
6
6
  from botocore.exceptions import ClientError
7
- from cloudfoundry_client.client import CloudFoundryClient
8
7
 
9
8
  from dbt_platform_helper.domain.versioning import PlatformHelperVersioning
10
9
  from dbt_platform_helper.utils.application import get_application_name
@@ -19,25 +18,6 @@ def secret_should_be_skipped(secret_name):
19
18
  return "AWS_" in secret_name
20
19
 
21
20
 
22
- def get_paas_env_vars(client: CloudFoundryClient, paas: str) -> dict:
23
- org, space, app = paas.split("/")
24
-
25
- env_vars = None
26
-
27
- for paas_org in client.v2.organizations:
28
- if paas_org["entity"]["name"] == org:
29
- for paas_space in paas_org.spaces():
30
- if paas_space["entity"]["name"] == space:
31
- for paas_app in paas_space.apps():
32
- if paas_app["entity"]["name"] == app:
33
- env_vars = paas_app["entity"]["environment_json"]
34
-
35
- if not env_vars:
36
- raise Exception(f"Application {paas} not found")
37
-
38
- return dict(env_vars)
39
-
40
-
41
21
  @click.group(chain=True, cls=ClickDocOptGroup)
42
22
  def secrets():
43
23
  PlatformHelperVersioning().check_if_needs_update()
@@ -0,0 +1,53 @@
1
+ import click
2
+
3
+ from dbt_platform_helper.domain.service import ServiceManager
4
+ from dbt_platform_helper.domain.versioning import PlatformHelperVersioning
5
+ from dbt_platform_helper.platform_exception import PlatformException
6
+ from dbt_platform_helper.providers.io import ClickIOProvider
7
+ from dbt_platform_helper.utils.click import ClickDocOptGroup
8
+
9
+
10
+ @click.group(cls=ClickDocOptGroup)
11
+ def service():
12
+ """Commands affecting services."""
13
+ PlatformHelperVersioning().check_if_needs_update()
14
+
15
+
16
+ @service.command(help="Generate terraform manifest for the specified service(s).")
17
+ @click.option(
18
+ "--name",
19
+ "-n",
20
+ required=False,
21
+ help="The name of the service to generate a manifest for. Multiple values accepted.",
22
+ multiple=True,
23
+ )
24
+ @click.option(
25
+ "--environment",
26
+ "-e",
27
+ required=False,
28
+ multiple=True,
29
+ help="The name of the environment to generate service manifests for. Multiple values accepted.",
30
+ )
31
+ @click.option(
32
+ "--image-tag",
33
+ "-i",
34
+ required=False,
35
+ help="Docker image tag to deploy for the service. Overrides the $IMAGE_TAG environment variable.",
36
+ )
37
+ def generate(name, environment, image_tag):
38
+ """Validates the service-config.yml format, applies the environment-specific
39
+ overrides, and generates a Terraform manifest at
40
+ /terraform/services/<environment>/<service>/main.tf.json."""
41
+
42
+ services = list(name)
43
+ environments = list(environment)
44
+ click_io = ClickIOProvider()
45
+
46
+ try:
47
+ service_manager = ServiceManager()
48
+ service_manager.generate(
49
+ environments=environments, services=services, image_tag_flag=image_tag
50
+ )
51
+
52
+ except PlatformException as err:
53
+ click_io.abort_with_error(str(err))
@@ -1,5 +1,7 @@
1
1
  # TODO: DBTP-1888: Move to Config provider
2
2
  PLATFORM_CONFIG_FILE = "platform-config.yml"
3
+ SERVICE_DIRECTORY = "services"
4
+ SERVICE_CONFIG_FILE = "service-config.yml"
3
5
  PLATFORM_HELPER_VERSION_OVERRIDE_KEY = "PLATFORM_HELPER_VERSION_OVERRIDE"
4
6
  TERRAFORM_EXTENSIONS_MODULE_SOURCE_OVERRIDE_ENV_VAR = "TERRAFORM_EXTENSIONS_MODULE_SOURCE_OVERRIDE"
5
7
  TERRAFORM_ENVIRONMENT_PIPELINES_MODULE_SOURCE_OVERRIDE_ENV_VAR = (
@@ -8,6 +10,11 @@ TERRAFORM_ENVIRONMENT_PIPELINES_MODULE_SOURCE_OVERRIDE_ENV_VAR = (
8
10
  TERRAFORM_CODEBASE_PIPELINES_MODULE_SOURCE_OVERRIDE_ENV_VAR = (
9
11
  "TERRAFORM_CODEBASE_PIPELINES_MODULE_SOURCE_OVERRIDE"
10
12
  )
13
+ TERRAFORM_ECS_SERVICE_MODULE_SOURCE_OVERRIDE_ENV_VAR = (
14
+ "TERRAFORM_ECS_SERVICE_MODULE_SOURCE_OVERRIDE"
15
+ )
16
+ TERRAFORM_MODULE_SOURCE_TYPE_ENV_VAR = "TERRAFORM_MODULE_SOURCE_TYPE" # "LOCAL", "SSH", "OVERRIDE"
17
+ IMAGE_TAG_ENV_VAR = "IMAGE_TAG"
11
18
  PLATFORM_HELPER_PACKAGE_NAME = "dbt-platform-helper"
12
19
  SUPPORTED_TERRAFORM_VERSION = "~> 1.8"
13
20
  SUPPORTED_AWS_PROVIDER_VERSION = "~> 5"
@@ -15,6 +22,7 @@ FIRST_UPGRADABLE_PLATFORM_HELPER_MAJOR_VERSION = 13
15
22
 
16
23
  MERGED_TPM_PLATFORM_HELPER_VERSION = 14
17
24
  PLATFORM_CONFIG_SCHEMA_VERSION = 1
25
+ SERVICE_CONFIG_SCHEMA_VERSION = 1
18
26
 
19
27
  # Keys
20
28
  CODEBASE_PIPELINES_KEY = "codebase_pipelines"
@@ -0,0 +1,153 @@
1
+ from datetime import datetime
2
+ from importlib.metadata import version
3
+ from pathlib import Path
4
+
5
+ from dbt_platform_helper.constants import IMAGE_TAG_ENV_VAR
6
+ from dbt_platform_helper.constants import PLATFORM_HELPER_VERSION_OVERRIDE_KEY
7
+ from dbt_platform_helper.constants import SERVICE_CONFIG_FILE
8
+ from dbt_platform_helper.constants import SERVICE_DIRECTORY
9
+ from dbt_platform_helper.constants import (
10
+ TERRAFORM_ECS_SERVICE_MODULE_SOURCE_OVERRIDE_ENV_VAR,
11
+ )
12
+ from dbt_platform_helper.constants import TERRAFORM_MODULE_SOURCE_TYPE_ENV_VAR
13
+ from dbt_platform_helper.domain.terraform_environment import (
14
+ EnvironmentNotFoundException,
15
+ )
16
+ from dbt_platform_helper.entities.service import ServiceConfig
17
+ from dbt_platform_helper.platform_exception import PlatformException
18
+ from dbt_platform_helper.providers.config import ConfigLoader
19
+ from dbt_platform_helper.providers.config import ConfigProvider
20
+ from dbt_platform_helper.providers.config_validator import ConfigValidator
21
+ from dbt_platform_helper.providers.environment_variable import (
22
+ EnvironmentVariableProvider,
23
+ )
24
+ from dbt_platform_helper.providers.io import ClickIOProvider
25
+ from dbt_platform_helper.providers.terraform_manifest import TerraformManifestProvider
26
+ from dbt_platform_helper.providers.yaml_file import YamlFileProvider
27
+ from dbt_platform_helper.utils.application import load_application
28
+ from dbt_platform_helper.utils.deep_merge import deep_merge
29
+
30
+ # TODO add schema version too service config
31
+
32
+
33
+ class ServiceManager:
34
+ def __init__(
35
+ self,
36
+ config_provider=ConfigProvider(ConfigValidator()),
37
+ loader: ConfigLoader = ConfigLoader(),
38
+ io: ClickIOProvider = ClickIOProvider(),
39
+ file_provider=YamlFileProvider,
40
+ environment_variable_provider: EnvironmentVariableProvider = None,
41
+ manifest_provider: TerraformManifestProvider = None,
42
+ platform_helper_version_override: str = None,
43
+ load_application=load_application,
44
+ ):
45
+
46
+ self.file_provider = file_provider
47
+ self.config_provider = config_provider
48
+ self.loader = loader
49
+ self.io = io
50
+ self.environment_variable_provider = (
51
+ environment_variable_provider or EnvironmentVariableProvider()
52
+ )
53
+ self.manifest_provider = manifest_provider or TerraformManifestProvider()
54
+ self.platform_helper_version_override = (
55
+ platform_helper_version_override
56
+ or self.environment_variable_provider.get(PLATFORM_HELPER_VERSION_OVERRIDE_KEY)
57
+ )
58
+ self.load_application = load_application
59
+
60
+ def generate(self, environments: list[str], services: list[str], image_tag_flag: str = None):
61
+
62
+ config = self.config_provider.get_enriched_config()
63
+ application_name = config.get("application", "")
64
+ application = self.load_application(app=application_name)
65
+
66
+ if not environments:
67
+ for environment in application.environments:
68
+ environments.append(environment)
69
+ else:
70
+ for environment in environments:
71
+ if environment not in application.environments:
72
+ raise EnvironmentNotFoundException(
73
+ f"cannot generate terraform for environment {environment}. It does not exist in your configuration"
74
+ )
75
+
76
+ if not services:
77
+ try:
78
+ for dir in Path("services").iterdir():
79
+ if dir.is_dir():
80
+ config_path = dir / SERVICE_CONFIG_FILE
81
+ if config_path.exists():
82
+ services.append(dir.name)
83
+ else:
84
+ self.io.warn(
85
+ f"Failed loading service name from {dir.name}.\n"
86
+ "Please ensure that your '/services' directory follows the correct structure (i.e. /services/<service_name>/service-config.yml) and the 'service-config.yml' contents are correct."
87
+ )
88
+ except Exception as e:
89
+ self.io.abort_with_error(f"Failed extracting services with exception, {e}")
90
+ service_models = []
91
+ for service in services:
92
+ service_models.append(
93
+ self.loader.load_into_model(
94
+ f"{SERVICE_DIRECTORY}/{service}/{SERVICE_CONFIG_FILE}",
95
+ ServiceConfig,
96
+ )
97
+ )
98
+
99
+ platform_helper_version_for_template: str = (
100
+ self.platform_helper_version_override
101
+ or config.get("default_versions", {}).get("platform-helper")
102
+ )
103
+
104
+ source_type = self.environment_variable_provider.get(TERRAFORM_MODULE_SOURCE_TYPE_ENV_VAR)
105
+
106
+ if source_type == "LOCAL":
107
+ module_source_override = ServiceConfig.local_terraform_source
108
+ elif source_type == "OVERRIDE":
109
+ module_source_override = self.environment_variable_provider.get(
110
+ TERRAFORM_ECS_SERVICE_MODULE_SOURCE_OVERRIDE_ENV_VAR
111
+ )
112
+ else:
113
+ module_source_override = None
114
+
115
+ image_tag = image_tag_flag or self.environment_variable_provider.get(IMAGE_TAG_ENV_VAR)
116
+ if not image_tag:
117
+ raise PlatformException(
118
+ f"An image tag must be provided to deploy a service. This can be set by the $IMAGE_TAG environment variable, or the --image-tag flag."
119
+ )
120
+
121
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
122
+
123
+ for service in service_models:
124
+
125
+ for environment in environments:
126
+
127
+ model_dump = service.model_dump(exclude_none=True)
128
+ env_overrides = model_dump.get("environments", {}).get(environment)
129
+ if env_overrides:
130
+ merged_config = deep_merge(model_dump, env_overrides)
131
+ else:
132
+ merged_config = model_dump.copy()
133
+ merged_config.pop("environments", None)
134
+
135
+ output_path = Path(
136
+ f"terraform/{SERVICE_DIRECTORY}/{environment}/{service.name}/{SERVICE_CONFIG_FILE}"
137
+ )
138
+ output_path.parent.mkdir(parents=True, exist_ok=True)
139
+
140
+ self.file_provider.write(
141
+ str(output_path),
142
+ merged_config,
143
+ f"# WARNING: This is an autogenerated file, not for manual editing.\n# Generated by platform-helper {version('dbt-platform-helper')} / {timestamp}.\n",
144
+ )
145
+
146
+ self.manifest_provider.generate_service_config(
147
+ service,
148
+ environment,
149
+ image_tag,
150
+ platform_helper_version_for_template,
151
+ config,
152
+ module_source_override,
153
+ )
@@ -152,7 +152,7 @@ class PlatformConfigSchema:
152
152
  {
153
153
  "name": str,
154
154
  Optional("requires_approval"): bool,
155
- }
155
+ },
156
156
  ],
157
157
  },
158
158
  {
@@ -167,9 +167,16 @@ class PlatformConfigSchema:
167
167
  },
168
168
  ),
169
169
  ],
170
+ Optional("cache_invalidation"): {
171
+ "domains": PlatformConfigSchema.__cache_invalidation_domains_schema(),
172
+ },
170
173
  },
171
174
  }
172
175
 
176
+ @staticmethod
177
+ def __cache_invalidation_domains_schema() -> dict:
178
+ return {str: {"paths": [str], "environment": str}}
179
+
173
180
  @staticmethod
174
181
  def __default_versions_schema() -> dict:
175
182
  return {
@@ -0,0 +1,114 @@
1
+ from typing import ClassVar
2
+ from typing import Dict
3
+ from typing import Optional
4
+ from typing import Union
5
+
6
+ from pydantic import BaseModel
7
+ from pydantic import Field
8
+
9
+
10
+ class HealthCheck(BaseModel):
11
+ path: Optional[str] = Field(description="""Path the healthcheck calls""", default=None)
12
+ port: Optional[int] = Field(description="""Port the healthcheck calls""", default=None)
13
+ success_codes: Optional[str] = Field(
14
+ description="""The success codes the healthcheck looks for""", default=None
15
+ )
16
+ healthy_threshold: Optional[int] = Field(description="""The number of """, default=None)
17
+ unhealthy_threshold: Optional[int] = Field(description="""The number of """, default=None)
18
+ interval: Optional[str] = Field(
19
+ description="""The interval inbetween health check calls""", default=None
20
+ )
21
+ timeout: Optional[str] = Field(
22
+ description="""The timeout for a healthcheck call""", default=None
23
+ )
24
+ grace_period: Optional[str] = Field(description="""The time""", default=None)
25
+
26
+
27
+ class Http(BaseModel):
28
+ path: Optional[str] = Field(
29
+ description="""Requests to this path will be forwarded to your service.""", default=None
30
+ )
31
+ alb: Optional[str] = Field(default=None)
32
+ target_container: Optional[str] = Field(
33
+ description="""Target container for the requests""", default=None
34
+ )
35
+ healthcheck: Optional[HealthCheck] = Field(default=None)
36
+
37
+
38
+ class Sidecar(BaseModel):
39
+ port: int = Field()
40
+ image: str = Field()
41
+ essential: Optional[bool] = Field(default=None)
42
+ variables: Optional[Dict[str, Union[str, int, bool]]] = Field(default=None)
43
+ secrets: Optional[Dict[str, str]] = Field(default=None)
44
+
45
+
46
+ class SidecarOverride(BaseModel):
47
+ port: Optional[int] = Field(default=None)
48
+ image: Optional[str] = Field(default=None)
49
+ essential: Optional[bool] = Field(default=None)
50
+ variables: Optional[Dict[str, Union[str, int, bool]]] = Field(default=None)
51
+ secrets: Optional[Dict[str, str]] = Field(default=None)
52
+
53
+
54
+ class Image(BaseModel):
55
+ build: Optional[str] = Field(default=None)
56
+ location: Optional[str] = Field(default=None)
57
+ port: int = Field()
58
+
59
+
60
+ class VPC(BaseModel):
61
+ placement: str = Field()
62
+
63
+
64
+ class Network(BaseModel):
65
+ connect: bool = Field(
66
+ description="Enable Service Connect for intra-environment traffic between services."
67
+ )
68
+ vpc: Optional[VPC] = Field(default=None)
69
+
70
+
71
+ class Storage(BaseModel):
72
+ readonly_fs: bool
73
+
74
+
75
+ class ServiceConfigEnvironmentOverride(BaseModel):
76
+ http: Optional[Http] = Field(default=None)
77
+ sidecars: Optional[Dict[str, SidecarOverride]] = Field(default=None)
78
+ image: Optional[Image] = Field(default=None)
79
+
80
+ cpu: Optional[int] = Field(default=None)
81
+ memory: Optional[int] = Field(default=None)
82
+ count: Optional[int] = Field(default=None)
83
+ exec: Optional[bool] = Field(default=None)
84
+ network: Optional[Network] = Field(default=None)
85
+
86
+ storage: Optional[Storage] = Field(default=None)
87
+
88
+ variables: Optional[Dict[str, Union[str, int, bool]]] = Field(default=None)
89
+ secrets: Optional[Dict[str, str]] = Field(default=None)
90
+
91
+
92
+ class ServiceConfig(BaseModel):
93
+ name: str = Field(description="""Name of the Service.""")
94
+ type: str = Field(description="""The type of service""")
95
+
96
+ http: Optional[Http] = Field(default=None) # TODO http required if service type load balancer
97
+ sidecars: Optional[Dict[str, Sidecar]] = Field(default=None)
98
+ image: Image = Field()
99
+
100
+ cpu: int = Field()
101
+ memory: int = Field()
102
+ count: int = Field()
103
+ exec: Optional[bool] = Field(default=None)
104
+ network: Optional[Network] = Field(default=None)
105
+
106
+ storage: Optional[Storage] = Field(default=None)
107
+
108
+ variables: Optional[Dict[str, Union[str, int, bool]]] = Field(default=None)
109
+ secrets: Optional[Dict[str, str]] = Field(default=None)
110
+ # Environment overrides can override almost the full config
111
+ environments: Optional[Dict[str, ServiceConfigEnvironmentOverride]] = Field(default=None)
112
+
113
+ # Class based variable used when handling the obejct
114
+ local_terraform_source: ClassVar[str] = "../../../../../platform-tools/terraform/ecs-service"
@@ -25,6 +25,34 @@ PLEASE_UPGRADE_TO_V13_MESSAGE = """Please ensure that you have already upgraded
25
25
  Then upgrade platform-helper to version {installed_platform_helper_version} and run 'platform-helper config migrate' to upgrade the configuration to the current schema version."""
26
26
 
27
27
 
28
+ class ConfigLoader:
29
+ def __init__(self, file_provider=YamlFileProvider, io: ClickIOProvider = ClickIOProvider()):
30
+ self.io = io
31
+ self.file_provider = file_provider
32
+
33
+ def load_into_model(self, path, model):
34
+ try:
35
+ file_content = self.file_provider.load(path)
36
+ return model(**file_content)
37
+ except FileNotFoundException as e:
38
+ self.io.abort_with_error(
39
+ f"{e} Please check it exists and you are in the root directory of your -deploy repository."
40
+ )
41
+ except FileProviderException as e:
42
+ self.io.abort_with_error(f"Error loading configuration from {path}: {e}")
43
+
44
+ def load(self, path):
45
+ try:
46
+ file_content = self.file_provider.load(path)
47
+ return file_content
48
+ except FileNotFoundException as e:
49
+ self.io.abort_with_error(
50
+ f"{e} Please check it exists and you are in the root directory of your -deploy repository."
51
+ )
52
+ except FileProviderException as e:
53
+ self.io.abort_with_error(f"Error loading configuration from {path}: {e}")
54
+
55
+
28
56
  class ConfigProvider:
29
57
  def __init__(
30
58
  self,
@@ -29,6 +29,7 @@ class ConfigValidator:
29
29
  self.validate_environment_pipelines_triggers,
30
30
  self.validate_database_copy_section,
31
31
  self.validate_database_migration_input_sources,
32
+ self.validate_cache_invalidation_config,
32
33
  ]
33
34
  self.io = io
34
35
  self.session = session
@@ -232,3 +233,25 @@ class ConfigValidator:
232
233
  )
233
234
  if errors:
234
235
  raise ConfigValidatorError("\n".join(errors))
236
+
237
+ def validate_cache_invalidation_config(self, config: dict):
238
+ codebase_pipelines = config.get("codebase_pipelines")
239
+ if not codebase_pipelines:
240
+ return
241
+
242
+ errors = []
243
+
244
+ all_environments = [env for env in config.get("environments", {}).keys() if not env == "*"]
245
+
246
+ for codebase in codebase_pipelines.values():
247
+ cache_invalidation_config = codebase.get("cache_invalidation")
248
+ if cache_invalidation_config:
249
+ for domain, config in cache_invalidation_config.get("domains").items():
250
+ environment = config.get("environment")
251
+ if environment not in all_environments:
252
+ errors.append(
253
+ f"Error in cache invalidation configuration for the domain '{domain}'. Environment '{environment}' is not defined for this application"
254
+ )
255
+
256
+ if errors:
257
+ raise ConfigValidatorError("\n".join(errors))
@@ -7,12 +7,12 @@ from dbt_platform_helper.platform_exception import PlatformException
7
7
  class EnvironmentVariableProvider:
8
8
 
9
9
  @staticmethod
10
- def get(env_var: str) -> Optional[str]:
10
+ def get(env_var: str, default=None) -> Optional[str]:
11
11
  """Returns the stripped value or None if not set or empty."""
12
12
  value = os.environ.get(env_var)
13
13
  if value and value.strip():
14
14
  return value.strip()
15
- return None
15
+ return default
16
16
 
17
17
  @staticmethod
18
18
  def get_required(env_var: str) -> str:
@@ -17,6 +17,68 @@ class TerraformManifestProvider:
17
17
  self.file_provider = file_provider
18
18
  self.io = io
19
19
 
20
+ def generate_service_config(
21
+ self,
22
+ config_object,
23
+ environment,
24
+ image_tag,
25
+ platform_helper_version: str,
26
+ platform_config,
27
+ module_source_override: str = None,
28
+ ):
29
+
30
+ service_dir = f"terraform/services/{environment}/{config_object.name}"
31
+ platform_config = ConfigProvider.apply_environment_defaults(platform_config)
32
+ account = self._get_account_for_env(environment, platform_config)
33
+ state_key_suffix = f"{config_object.name}-{environment}"
34
+
35
+ terraform = {}
36
+ self._add_header(terraform)
37
+
38
+ self._add_service_locals(terraform, environment, image_tag)
39
+
40
+ self._add_provider(terraform, account)
41
+ self._add_backend(
42
+ terraform, platform_config, account, f"tfstate/services/{state_key_suffix}.tfstate"
43
+ )
44
+
45
+ self._add_service_module(terraform, platform_helper_version, module_source_override)
46
+
47
+ self._write_terraform_json(terraform, service_dir)
48
+
49
+ def _add_service_locals(self, terraform, environment, image_tag):
50
+ terraform["locals"] = {
51
+ "environment": environment,
52
+ "image_tag": image_tag,
53
+ "platform_config": '${yamldecode(file("../../../../platform-config.yml"))}',
54
+ "application": '${local.platform_config["application"]}',
55
+ "environments": '${local.platform_config["environments"]}',
56
+ "env_config": '${{for name, config in local.environments: name => merge(lookup(local.environments, "*", {}), config)}}',
57
+ "service_config": '${yamldecode(templatefile("./service-config.yml", {COPILOT_ENVIRONMENT_NAME = local.environment, IMAGE_TAG = local.image_tag}))}',
58
+ "raw_env_config": '${local.platform_config["environments"]}',
59
+ "combined_env_config": '${{for name, config in local.raw_env_config: name => merge(lookup(local.raw_env_config, "*", {}), config)}}',
60
+ "service_deployment_mode": '${lookup(local.combined_env_config[local.environment], "service-deployment-mode", "copilot")}',
61
+ "non_copilot_service_deployment_mode": '${local.service_deployment_mode == "dual-deploy-copilot-traffic" || local.service_deployment_mode == "dual-deploy-platform-traffic" || local.service_deployment_mode == "platform" ? 1 : 0}',
62
+ }
63
+
64
+ def _add_service_module(
65
+ self, terraform: dict, platform_helper_version: str, module_source_override: str = None
66
+ ):
67
+ source = (
68
+ module_source_override
69
+ or f"git::git@github.com:uktrade/platform-tools.git//terraform/ecs-service?depth=1&ref={platform_helper_version}"
70
+ )
71
+ terraform["module"] = {
72
+ "ecs-service": {
73
+ "source": source,
74
+ "count": "${local.non_copilot_service_deployment_mode}",
75
+ "application": "${local.application}",
76
+ "environment": "${local.environment}",
77
+ "service_config": "${local.service_config}",
78
+ "env_config": "${local.env_config}",
79
+ }
80
+ }
81
+
20
82
  def generate_codebase_pipeline_config(
21
83
  self,
22
84
  platform_config: dict,
@@ -32,7 +94,12 @@ class TerraformManifestProvider:
32
94
  self._add_header(terraform)
33
95
  self._add_codebase_pipeline_locals(terraform)
34
96
  self._add_provider(terraform, default_account)
35
- self._add_backend(terraform, platform_config, default_account, state_key_suffix)
97
+ self._add_backend(
98
+ terraform,
99
+ platform_config,
100
+ default_account,
101
+ f"tfstate/application/{state_key_suffix}.tfstate",
102
+ )
36
103
  self._add_codebase_pipeline_module(
37
104
  terraform, platform_helper_version, deploy_repository, module_source
38
105
  )
@@ -56,7 +123,9 @@ class TerraformManifestProvider:
56
123
  terraform = {}
57
124
  self._add_header(terraform)
58
125
  self._add_environment_locals(terraform, application_name)
59
- self._add_backend(terraform, platform_config, account, state_key_suffix)
126
+ self._add_backend(
127
+ terraform, platform_config, account, f"tfstate/application/{state_key_suffix}.tfstate"
128
+ )
60
129
  self._add_extensions_module(terraform, platform_helper_version, env, module_source_override)
61
130
  self._add_moved(terraform, platform_config)
62
131
  self._ensure_no_hcl_manifest_file(env_dir)
@@ -99,13 +168,13 @@ class TerraformManifestProvider:
99
168
  terraform["provider"]["aws"]["shared_credentials_files"] = ["~/.aws/config"]
100
169
 
101
170
  @staticmethod
102
- def _add_backend(terraform: dict, platform_config: dict, account: str, state_key_suffix: str):
171
+ def _add_backend(terraform: dict, platform_config: dict, account: str, state_key: str):
103
172
  terraform["terraform"] = {
104
173
  "required_version": SUPPORTED_TERRAFORM_VERSION,
105
174
  "backend": {
106
175
  "s3": {
107
176
  "bucket": f"terraform-platform-state-{account}",
108
- "key": f"tfstate/application/{state_key_suffix}.tfstate",
177
+ "key": state_key,
109
178
  "region": "eu-west-2",
110
179
  "encrypt": True,
111
180
  "kms_key_id": f"alias/terraform-platform-state-s3-key-{account}",
@@ -135,6 +204,7 @@ class TerraformManifestProvider:
135
204
  "deploy_repository": f"{deploy_repository}",
136
205
  "deploy_repository_branch": '${lookup(each.value, "deploy_repository_branch", "main")}',
137
206
  "additional_ecr_repository": '${lookup(each.value, "additional_ecr_repository", null)}',
207
+ "cache_invalidation": '${lookup(each.value, "cache_invalidation", null)}',
138
208
  "pipelines": '${lookup(each.value, "pipelines", [])}',
139
209
  "services": "${each.value.services}",
140
210
  "requires_image_build": '${lookup(each.value, "requires_image_build", true)}',
@@ -24,3 +24,8 @@
24
24
  Condition:
25
25
  StringEquals:
26
26
  'ssm:ResourceTag/copilot-application': '__all__'
27
+
28
+ - op: add
29
+ path: /Resources/TaskDefinition/Properties/pidMode
30
+ value:
31
+ task
@@ -0,0 +1,10 @@
1
+ def deep_merge(base, override):
2
+ result = base.copy()
3
+
4
+ for k, v in override.items():
5
+ if k in result and isinstance(result[k], dict) and isinstance(v, dict):
6
+ result[k] = deep_merge(result[k], v)
7
+ else:
8
+ result[k] = v
9
+
10
+ return result
@@ -15,6 +15,7 @@ from dbt_platform_helper.commands.generate import generate as generate_commands
15
15
  from dbt_platform_helper.commands.notify import notify as notify_commands
16
16
  from dbt_platform_helper.commands.pipeline import pipeline as pipeline_commands
17
17
  from dbt_platform_helper.commands.secrets import secrets as secrets_commands
18
+ from dbt_platform_helper.commands.service import service as service_commands
18
19
  from dbt_platform_helper.commands.version import version as version_commands
19
20
  from dbt_platform_helper.utils.click import ClickDocOptGroup
20
21
 
@@ -37,6 +38,7 @@ platform_helper.add_command(environment_commands)
37
38
  platform_helper.add_command(generate_commands)
38
39
  platform_helper.add_command(pipeline_commands)
39
40
  platform_helper.add_command(secrets_commands)
41
+ platform_helper.add_command(service_commands)
40
42
  platform_helper.add_command(notify_commands)
41
43
  platform_helper.add_command(database_commands)
42
44
  platform_helper.add_command(version_commands)
@@ -3,7 +3,7 @@ line-length = 100
3
3
 
4
4
  [tool.poetry]
5
5
  name = "dbt-platform-helper"
6
- version = "15.6.0"
6
+ version = "15.7.0"
7
7
  description = "Set of tools to help transfer applications/services from GOV.UK PaaS to DBT PaaS augmenting AWS Copilot."
8
8
  authors = ["Department for Business and Trade Platform Team <sre-team@digital.trade.gov.uk>"]
9
9
  license = "MIT"
@@ -21,15 +21,14 @@ platform-helper = "platform_helper:platform_helper"
21
21
 
22
22
  [tool.poetry.dependencies]
23
23
  Jinja2 = "3.1.6"
24
- PyYAML = "6.0.1"
24
+ PyYAML = "6.0.2"
25
25
  yamllint = "^1.35.1"
26
26
  boto3 = "^1.35.2"
27
27
  boto3-stubs = "^1.26.148"
28
28
  botocore = "^1.34.85"
29
29
  click = "^8.1.3"
30
- cloudfoundry-client = "1.35.2"
31
30
  mypy-boto3-codebuild = "^1.26.0.post1"
32
- python = ">3.9.0,<3.9.1 || >3.9.1,<4.0"
31
+ python = ">3.9.1,<4.0"
33
32
  schema = "0.7.5"
34
33
  cfn-flip = "1.3.0"
35
34
  aiohttp = "^3.11.16"
@@ -39,7 +38,7 @@ jinja2-simple-tags = "^0.5.0"
39
38
  requests = "^2.31.0"
40
39
  prettytable = "^3.9.0"
41
40
  semver = "^3.0.2"
42
- tomlkit = "^0.12.2"
41
+ tomlkit = ">=0.12.2,<0.14.0"
43
42
  slack-sdk = "^3.27.1"
44
43
  jsonschema = "~=4.17.0"
45
44
  cfn-lint = "^1.4.2"
@@ -50,7 +49,7 @@ checkov = "^3.2.405"
50
49
  moto = {extras = ["all"], version = "^5.0.28"}
51
50
  pyfakefs = "^5.2.2"
52
51
  pytest = "^8.3.5"
53
- pytest-env = "^0.8.1"
52
+ pytest-env = ">=0.8.1,<1.2.0"
54
53
  tox = "^4.6.0"
55
54
  pre-commit = "^3.3.3"
56
55
  freezegun = "^1.2.2"