dbt-platform-helper 15.10.0__py3-none-any.whl → 15.12.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 (27) hide show
  1. dbt_platform_helper/COMMANDS.md +0 -91
  2. dbt_platform_helper/commands/internal.py +114 -0
  3. dbt_platform_helper/constants.py +17 -0
  4. dbt_platform_helper/domain/conduit.py +13 -5
  5. dbt_platform_helper/domain/config.py +30 -1
  6. dbt_platform_helper/domain/maintenance_page.py +10 -8
  7. dbt_platform_helper/domain/service.py +274 -66
  8. dbt_platform_helper/domain/update_alb_rules.py +346 -0
  9. dbt_platform_helper/entities/platform_config_schema.py +0 -3
  10. dbt_platform_helper/entities/service.py +139 -13
  11. dbt_platform_helper/providers/aws/exceptions.py +5 -0
  12. dbt_platform_helper/providers/aws/sso_auth.py +14 -0
  13. dbt_platform_helper/providers/config.py +0 -11
  14. dbt_platform_helper/providers/ecs.py +104 -11
  15. dbt_platform_helper/providers/load_balancers.py +119 -14
  16. dbt_platform_helper/providers/logs.py +57 -0
  17. dbt_platform_helper/providers/s3.py +21 -0
  18. dbt_platform_helper/providers/terraform_manifest.py +3 -5
  19. dbt_platform_helper/providers/yaml_file.py +13 -5
  20. dbt_platform_helper/utils/application.py +66 -16
  21. {dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.12.0.dist-info}/METADATA +1 -1
  22. {dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.12.0.dist-info}/RECORD +26 -24
  23. platform_helper.py +0 -2
  24. dbt_platform_helper/commands/service.py +0 -53
  25. {dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.12.0.dist-info}/WHEEL +0 -0
  26. {dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.12.0.dist-info}/entry_points.txt +0 -0
  27. {dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.12.0.dist-info}/licenses/LICENSE +0 -0
@@ -22,15 +22,11 @@
22
22
  - [platform-helper environment generate](#platform-helper-environment-generate)
23
23
  - [platform-helper environment generate-terraform](#platform-helper-environment-generate-terraform)
24
24
  - [platform-helper generate](#platform-helper-generate)
25
- - [platform-helper internal](#platform-helper-internal)
26
- - [platform-helper internal migrate-service-manifests](#platform-helper-internal-migrate-service-manifests)
27
25
  - [platform-helper pipeline](#platform-helper-pipeline)
28
26
  - [platform-helper pipeline generate](#platform-helper-pipeline-generate)
29
27
  - [platform-helper secrets](#platform-helper-secrets)
30
28
  - [platform-helper secrets copy](#platform-helper-secrets-copy)
31
29
  - [platform-helper secrets list](#platform-helper-secrets-list)
32
- - [platform-helper service](#platform-helper-service)
33
- - [platform-helper service generate](#platform-helper-service-generate)
34
30
  - [platform-helper notify](#platform-helper-notify)
35
31
  - [platform-helper notify environment-progress](#platform-helper-notify-environment-progress)
36
32
  - [platform-helper notify post-message](#platform-helper-notify-post-message)
@@ -71,7 +67,6 @@ platform-helper <command> [--version]
71
67
  - [`notify` ↪](#platform-helper-notify)
72
68
  - [`pipeline` ↪](#platform-helper-pipeline)
73
69
  - [`secrets` ↪](#platform-helper-secrets)
74
- - [`service` ↪](#platform-helper-service)
75
70
  - [`version` ↪](#platform-helper-version)
76
71
 
77
72
  # platform-helper application
@@ -542,44 +537,6 @@ platform-helper generate
542
537
 
543
538
  ## Options
544
539
 
545
- - `--help <boolean>` _Defaults to False._
546
- - Show this message and exit.
547
-
548
- # platform-helper internal
549
-
550
- [↩ Parent](#platform-helper)
551
-
552
- Internal commands for use within pipelines or by Platform Team.
553
-
554
- ## Usage
555
-
556
- ```
557
- platform-helper internal migrate-service-manifests
558
- ```
559
-
560
- ## Options
561
-
562
- - `--help <boolean>` _Defaults to False._
563
- - Show this message and exit.
564
-
565
- ## Commands
566
-
567
- - [`migrate-service-manifests` ↪](#platform-helper-internal-migrate-service-manifests)
568
-
569
- # platform-helper internal migrate-service-manifests
570
-
571
- [↩ Parent](#platform-helper-internal)
572
-
573
- Migrate copilot manifests to service manifests.
574
-
575
- ## Usage
576
-
577
- ```
578
- platform-helper internal migrate-service-manifests
579
- ```
580
-
581
- ## Options
582
-
583
540
  - `--help <boolean>` _Defaults to False._
584
541
  - Show this message and exit.
585
542
 
@@ -704,54 +661,6 @@ platform-helper secrets list <application> <environment>
704
661
  - `--help <boolean>` _Defaults to False._
705
662
  - Show this message and exit.
706
663
 
707
- # platform-helper service
708
-
709
- [↩ Parent](#platform-helper)
710
-
711
- Commands affecting services.
712
-
713
- ## Usage
714
-
715
- ```
716
- platform-helper service generate
717
- ```
718
-
719
- ## Options
720
-
721
- - `--help <boolean>` _Defaults to False._
722
- - Show this message and exit.
723
-
724
- ## Commands
725
-
726
- - [`generate` ↪](#platform-helper-service-generate)
727
-
728
- # platform-helper service generate
729
-
730
- [↩ Parent](#platform-helper-service)
731
-
732
- Generate terraform manifest for the specified service(s).
733
-
734
- ## Usage
735
-
736
- ```
737
- platform-helper service generate [--name <name>] [--environment <environment>]
738
- [--image-tag <image_tag>]
739
- ```
740
-
741
- ## Options
742
-
743
- - `--name
744
- -n <text>`
745
- - The name of the service to generate a manifest for. Multiple values accepted.
746
- - `--environment
747
- -e <text>`
748
- - The name of the environment to generate service manifests for. Multiple values accepted.
749
- - `--image-tag
750
- -i <text>`
751
- - Docker image tag to deploy for the service. Overrides the $IMAGE_TAG environment variable.
752
- - `--help <boolean>` _Defaults to False._
753
- - Show this message and exit.
754
-
755
664
  # platform-helper notify
756
665
 
757
666
  [↩ Parent](#platform-helper)
@@ -1,8 +1,17 @@
1
1
  import click
2
2
 
3
3
  from dbt_platform_helper.domain.service import ServiceManager
4
+ from dbt_platform_helper.domain.update_alb_rules import UpdateALBRules
5
+ from dbt_platform_helper.domain.versioning import PlatformHelperVersioning
4
6
  from dbt_platform_helper.platform_exception import PlatformException
7
+ from dbt_platform_helper.providers.config import ConfigProvider
8
+ from dbt_platform_helper.providers.config_validator import ConfigValidator
9
+ from dbt_platform_helper.providers.ecs import ECS
5
10
  from dbt_platform_helper.providers.io import ClickIOProvider
11
+ from dbt_platform_helper.providers.logs import LogsProvider
12
+ from dbt_platform_helper.providers.s3 import S3Provider
13
+ from dbt_platform_helper.utils.application import load_application
14
+ from dbt_platform_helper.utils.aws import get_aws_session_or_abort
6
15
  from dbt_platform_helper.utils.click import ClickDocOptGroup
7
16
 
8
17
 
@@ -21,3 +30,108 @@ def migrate_service_manifests():
21
30
  service_manager.migrate_copilot_manifests()
22
31
  except PlatformException as error:
23
32
  click_io.abort_with_error(str(error))
33
+
34
+
35
+ @internal.group(cls=ClickDocOptGroup)
36
+ def service():
37
+ """Subgroup for 'internal service' commands."""
38
+
39
+
40
+ @service.command(help="Trigger an ECS deployment.")
41
+ @click.option("--name", required=True, help="The name of the ECS service to create or update.")
42
+ @click.option(
43
+ "--env",
44
+ required=True,
45
+ help="The name of the environment where the ECS service will be created or updated.",
46
+ )
47
+ @click.option(
48
+ "--image-tag",
49
+ required=True,
50
+ help="Image tag to deploy for the service(s). Takes precedence over the $IMAGE_TAG environment variable.",
51
+ )
52
+ def deploy(name, env, image_tag):
53
+ """Register a new ECS task definition from an S3 JSON template, update the
54
+ ECS service, and tail CloudWatch logs until the ECS rollout is complete."""
55
+ click_io = ClickIOProvider()
56
+
57
+ try:
58
+
59
+ config = ConfigProvider(ConfigValidator()).get_enriched_config()
60
+ application_name = config.get("application", "")
61
+ application = load_application(app=application_name, env=env)
62
+
63
+ ecs_client = application.environments[env].session.client("ecs")
64
+ ssm_client = application.environments[env].session.client("ssm")
65
+ s3_client = application.environments[env].session.client("s3")
66
+ logs_client = application.environments[env].session.client("logs")
67
+
68
+ ecs_provider = ECS(
69
+ ecs_client=ecs_client,
70
+ ssm_client=ssm_client,
71
+ application_name=application.name,
72
+ env=env,
73
+ )
74
+ s3_provider = S3Provider(client=s3_client)
75
+ logs_provider = LogsProvider(client=logs_client)
76
+
77
+ account_id = application.environments.get(env).account_id
78
+
79
+ service_manager = ServiceManager(
80
+ ecs_provider=ecs_provider, s3_provider=s3_provider, logs_provider=logs_provider
81
+ )
82
+ service_manager.deploy(
83
+ service=name,
84
+ environment=env,
85
+ application=application.name,
86
+ account_id=account_id,
87
+ image_tag=image_tag,
88
+ )
89
+ except PlatformException as error:
90
+ click_io.abort_with_error(str(error))
91
+
92
+
93
+ @service.command(help="Generate Terraform manifest for the specified service(s).")
94
+ @click.option(
95
+ "--name",
96
+ required=False,
97
+ help="The name of the service(s) to generate service manifest(s) for.",
98
+ multiple=True,
99
+ )
100
+ @click.option(
101
+ "--env",
102
+ required=True,
103
+ help="The name of the environment to generate service manifests for.",
104
+ )
105
+ def generate(name, env):
106
+ """Validates the service-config.yml format, applies the environment-specific
107
+ overrides, and generates a Terraform manifest at
108
+ /terraform/services/<environment>/<service>/main.tf.json."""
109
+
110
+ services = list(name)
111
+ click_io = ClickIOProvider()
112
+
113
+ try:
114
+ service_manager = ServiceManager()
115
+ service_manager.generate(environment=env, services=services)
116
+
117
+ except PlatformException as err:
118
+ click_io.abort_with_error(str(err))
119
+
120
+
121
+ @internal.group(cls=ClickDocOptGroup)
122
+ def alb():
123
+ """Load Balancer related commands."""
124
+ PlatformHelperVersioning().check_if_needs_update()
125
+
126
+
127
+ @alb.command()
128
+ @click.option("--env", type=str, required=True)
129
+ def update_rules(env: str):
130
+ """Update alb rules based on service-deployment-mode for a given
131
+ environment."""
132
+ try:
133
+ session = get_aws_session_or_abort()
134
+ update_aws = UpdateALBRules(session)
135
+ update_aws.update_alb_rules(environment=env)
136
+ except PlatformException as err:
137
+ ClickIOProvider().abort_with_error(str(err))
@@ -1,4 +1,5 @@
1
1
  # TODO: DBTP-1888: Move to Config provider
2
+ REPO_ORG = "uktrade"
2
3
  PLATFORM_CONFIG_FILE = "platform-config.yml"
3
4
  SERVICE_DIRECTORY = "services"
4
5
  SERVICE_CONFIG_FILE = "service-config.yml"
@@ -45,3 +46,19 @@ SERVICE_NAME_SUFFIX = f"Service-{COPILOT_IDENTIFIER}"
45
46
  REFRESH_TOKEN_MESSAGE = (
46
47
  "To refresh this SSO session run `aws sso login` with the corresponding profile"
47
48
  )
49
+ COPILOT_RULE_PRIORITY = 48000
50
+ PLATFORM_RULE_STARTING_PRIORITY = 10000
51
+ RULE_PRIORITY_INCREMENT = 100
52
+ DUMMY_RULE_REASON = "DummyRule"
53
+ MAINTENANCE_PAGE_TAGS = ["MaintenancePage", "AllowedIps", "BypassIpFilter", "AllowedSourceIps"]
54
+ MAINTENANCE_PAGE_REASON = "MaintenancePage"
55
+ MANAGED_BY_PLATFORM = "DBT Platform"
56
+ MANAGED_BY_SERVICE_TERRAFORM = "DBT Platform - Service Terraform"
57
+ MANAGED_BY_PLATFORM_TERRAFORM = "DBT Platform - Terraform"
58
+ STANDARD_PLATFORM_SSO_ROLES = [
59
+ "AdministratorAccess",
60
+ "DBTPlatformDeveloperWrite",
61
+ "DBTPlatformDeveloperRead",
62
+ ]
63
+ ROUTED_TO_PLATFORM_MODES = ["platform", "dual-deploy-platform-traffic"]
64
+ ROUTED_TO_COPILOT_MODES = ["copilot", "dual-deploy-copilot-traffic"]
@@ -56,10 +56,16 @@ class TerraformConduitStrategy(ConduitECSStrategy):
56
56
 
57
57
  def get_data(self):
58
58
  self.io.info("Starting conduit in Terraform mode.")
59
- return {
60
- "cluster_arn": self.ecs_provider.get_cluster_arn_by_name(
59
+ try:
60
+ cluster_arn = self.ecs_provider.get_cluster_arn_by_name(
61
+ f"{self.application.name}-{self.env}-cluster"
62
+ )
63
+ except:
64
+ cluster_arn = self.ecs_provider.get_cluster_arn_by_name(
61
65
  f"{self.application.name}-{self.env}"
62
- ),
66
+ )
67
+ return {
68
+ "cluster_arn": cluster_arn,
63
69
  "task_def_family": self._generate_container_name(),
64
70
  "vpc_name": self._resolve_vpc_name(),
65
71
  "addon_type": self.addon_type,
@@ -94,8 +100,10 @@ class TerraformConduitStrategy(ConduitECSStrategy):
94
100
  },
95
101
  ]
96
102
 
103
+ cluster_name = data_context["cluster_arn"].split("/")[-1]
104
+
97
105
  self.ecs_provider.start_ecs_task(
98
- f"{self.application.name}-{self.env}",
106
+ cluster_name,
99
107
  self._generate_container_name(),
100
108
  data_context["task_def_family"],
101
109
  vpc_config,
@@ -326,7 +334,7 @@ class Conduit:
326
334
  data_context = strategy.get_data()
327
335
 
328
336
  data_context["task_arns"] = self.ecs_provider.get_ecs_task_arns(
329
- data_context["cluster_arn"], data_context["task_def_family"]
337
+ cluster=data_context["cluster_arn"], task_def_family=data_context["task_def_family"]
330
338
  )
331
339
 
332
340
  info_log = (
@@ -7,6 +7,7 @@ from typing import Dict
7
7
  from prettytable import PrettyTable
8
8
 
9
9
  from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE
10
+ from dbt_platform_helper.constants import STANDARD_PLATFORM_SSO_ROLES
10
11
  from dbt_platform_helper.domain.versioning import AWSVersioning
11
12
  from dbt_platform_helper.domain.versioning import CopilotVersioning
12
13
  from dbt_platform_helper.domain.versioning import PlatformHelperVersioning
@@ -140,6 +141,10 @@ class Config:
140
141
  if self.io.confirm(
141
142
  f"This command is destructive and will overwrite file contents at {file_path}. Are you sure you want to continue?"
142
143
  ):
144
+ self.io.info(
145
+ "Fetching credentials... this may take longer if you have access to many accounts."
146
+ )
147
+
143
148
  with open(aws_config_path, "w") as config_file:
144
149
  config_file.write(AWS_CONFIG)
145
150
 
@@ -147,7 +152,9 @@ class Config:
147
152
  config_file.write(f"[profile {account['accountName']}]\n")
148
153
  config_file.write("sso_session = uktrade\n")
149
154
  config_file.write(f"sso_account_id = {account['accountId']}\n")
150
- config_file.write("sso_role_name = AdministratorAccess\n")
155
+ config_file.write(
156
+ f"sso_role_name = {self._retrieve_role_for_aws_account(aws_sso_token=access_token, account_id=account['accountId'])}\n"
157
+ )
151
158
  config_file.write("region = eu-west-2\n")
152
159
  config_file.write("output = json\n")
153
160
  config_file.write("\n")
@@ -177,6 +184,28 @@ class Config:
177
184
  )
178
185
  return accounts_list
179
186
 
187
+ def _retrieve_role_for_aws_account(self, aws_sso_token, account_id):
188
+ """
189
+ Selects the most appropriate IAM role for a given AWS account.
190
+
191
+ Roles listed in STANDARD_PLATFORM_SSO_ROLES are preferred if available.
192
+ If none are found, the first available role returned by
193
+ sso.list_account_roles is used.
194
+ """
195
+
196
+ role_list = self.sso.list_account_roles(
197
+ access_token=aws_sso_token,
198
+ account_id=account_id,
199
+ max_results=100,
200
+ )
201
+
202
+ roles_retrieved = [r["roleName"] for r in role_list]
203
+
204
+ for role in STANDARD_PLATFORM_SSO_ROLES:
205
+ if role in roles_retrieved:
206
+ return role
207
+ return role_list[0]["roleName"]
208
+
180
209
  def _add_version_status_row(
181
210
  self, table: PrettyTable, header: str, version_status: VersionStatus
182
211
  ):
@@ -10,6 +10,8 @@ from typing import Union
10
10
 
11
11
  import click
12
12
 
13
+ from dbt_platform_helper.constants import MAINTENANCE_PAGE_REASON
14
+ from dbt_platform_helper.constants import MANAGED_BY_PLATFORM
13
15
  from dbt_platform_helper.platform_exception import PlatformException
14
16
  from dbt_platform_helper.providers.io import ClickIOProvider
15
17
  from dbt_platform_helper.providers.load_balancers import ListenerRuleNotFoundException
@@ -202,8 +204,8 @@ class MaintenancePage:
202
204
  [
203
205
  {"Key": "application", "Value": app},
204
206
  {"Key": "environment", "Value": env},
205
- {"Key": "reason", "Value": "MaintenancePage"},
206
- {"Key": "managed-by", "Value": "DBT Platform"},
207
+ {"Key": "reason", "Value": MAINTENANCE_PAGE_REASON},
208
+ {"Key": "managed-by", "Value": MANAGED_BY_PLATFORM},
207
209
  {"Key": "service", "Value": svc.name},
208
210
  ],
209
211
  )
@@ -217,8 +219,8 @@ class MaintenancePage:
217
219
  [
218
220
  {"Key": "application", "Value": app},
219
221
  {"Key": "environment", "Value": env},
220
- {"Key": "reason", "Value": "MaintenancePage"},
221
- {"Key": "managed-by", "Value": "DBT Platform"},
222
+ {"Key": "reason", "Value": MAINTENANCE_PAGE_REASON},
223
+ {"Key": "managed-by", "Value": MANAGED_BY_PLATFORM},
222
224
  {"Key": "service", "Value": svc.name},
223
225
  ],
224
226
  )
@@ -234,8 +236,8 @@ class MaintenancePage:
234
236
  [
235
237
  {"Key": "application", "Value": app},
236
238
  {"Key": "environment", "Value": env},
237
- {"Key": "reason", "Value": "MaintenancePage"},
238
- {"Key": "managed-by", "Value": "DBT Platform"},
239
+ {"Key": "reason", "Value": MAINTENANCE_PAGE_REASON},
240
+ {"Key": "managed-by", "Value": MANAGED_BY_PLATFORM},
239
241
  {"Key": "service", "Value": svc.name},
240
242
  ],
241
243
  )
@@ -287,10 +289,10 @@ class MaintenancePage:
287
289
  tags=[
288
290
  {"Key": "application", "Value": app},
289
291
  {"Key": "environment", "Value": env},
290
- {"Key": "reason", "Value": "MaintenancePage"},
292
+ {"Key": "reason", "Value": MAINTENANCE_PAGE_REASON},
291
293
  {"Key": "name", "Value": "MaintenancePage"},
292
294
  {"Key": "type", "Value": template},
293
- {"Key": "managed-by", "Value": "DBT Platform"},
295
+ {"Key": "managed-by", "Value": MANAGED_BY_PLATFORM},
294
296
  ],
295
297
  )
296
298
  except Exception as e: