dbt-platform-helper 15.9.0__py3-none-any.whl → 15.11.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 (26) hide show
  1. dbt_platform_helper/COMMANDS.md +1 -51
  2. dbt_platform_helper/commands/internal.py +134 -0
  3. dbt_platform_helper/constants.py +14 -0
  4. dbt_platform_helper/domain/conduit.py +1 -1
  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 +317 -53
  8. dbt_platform_helper/domain/update_alb_rules.py +346 -0
  9. dbt_platform_helper/entities/platform_config_schema.py +4 -5
  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 +86 -8
  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-15.9.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/METADATA +5 -3
  21. {dbt_platform_helper-15.9.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/RECORD +25 -22
  22. {dbt_platform_helper-15.9.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/WHEEL +1 -1
  23. platform_helper.py +2 -2
  24. dbt_platform_helper/commands/service.py +0 -53
  25. {dbt_platform_helper-15.9.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/entry_points.txt +0 -0
  26. {dbt_platform_helper-15.9.0.dist-info → dbt_platform_helper-15.11.0.dist-info/licenses}/LICENSE +0 -0
@@ -1,7 +1,10 @@
1
1
  import random
2
2
  import string
3
3
  import subprocess
4
- from typing import List
4
+ from typing import Any
5
+ from typing import Optional
6
+
7
+ from botocore.exceptions import ClientError
5
8
 
6
9
  from dbt_platform_helper.platform_exception import PlatformException
7
10
  from dbt_platform_helper.platform_exception import ValidationException
@@ -39,7 +42,7 @@ class ECS:
39
42
  container_name: str,
40
43
  task_def_arn: str,
41
44
  vpc_config: Vpc,
42
- env_vars: List[dict] = None,
45
+ env_vars: list[dict] = None,
43
46
  ):
44
47
  container_override = {"name": container_name}
45
48
  if env_vars:
@@ -107,13 +110,31 @@ class ECS:
107
110
  random_id = "".join(random.choices(string.ascii_lowercase + string.digits, k=12))
108
111
  return f"conduit-{self.application_name}-{self.env}-{addon_name}-{random_id}"
109
112
 
110
- def get_ecs_task_arns(self, cluster_arn: str, task_def_family: str):
111
- """Gets the ECS task ARNs for a given task name and cluster ARN."""
112
- tasks = self.ecs_client.list_tasks(
113
- cluster=cluster_arn,
114
- desiredStatus="RUNNING",
115
- family=task_def_family,
116
- )
113
+ def get_ecs_task_arns(
114
+ self,
115
+ cluster: str,
116
+ max_results: int = 100,
117
+ desired_status: str = "RUNNING",
118
+ service_name: Optional[str] = None,
119
+ started_by: Optional[str] = None,
120
+ task_def_family: Optional[str] = None,
121
+ ) -> list[str]:
122
+ """Returns the ECS task ARNs based on the parameters provided."""
123
+
124
+ params = {
125
+ "cluster": cluster,
126
+ "maxResults": max_results,
127
+ "desiredStatus": desired_status,
128
+ }
129
+
130
+ if service_name:
131
+ params["serviceName"] = service_name
132
+ if started_by:
133
+ params["startedBy"] = started_by
134
+ if task_def_family:
135
+ params["family"] = task_def_family
136
+
137
+ tasks = self.ecs_client.list_tasks(**params)
117
138
 
118
139
  if not tasks["taskArns"]:
119
140
  return []
@@ -137,7 +158,7 @@ class ECS:
137
158
  exceptions_to_catch=(ECSException,),
138
159
  message_on_false="ECS Agent Not running",
139
160
  )
140
- def ecs_exec_is_available(self, cluster_arn: str, task_arns: List[str]) -> bool:
161
+ def ecs_exec_is_available(self, cluster_arn: str, task_arns: list[str]) -> bool:
141
162
  """
142
163
  Checks if the ExecuteCommandAgent is running on the specified ECS task.
143
164
 
@@ -168,7 +189,79 @@ class ECS:
168
189
  message_on_false="ECS task did not register in time",
169
190
  )
170
191
  def wait_for_task_to_register(self, cluster_arn: str, task_family: str) -> list[str]:
171
- task_arns = self.get_ecs_task_arns(cluster_arn, task_family)
192
+ task_arns = self.get_ecs_task_arns(cluster=cluster_arn, task_def_family=task_family)
172
193
  if task_arns:
173
194
  return task_arns
174
195
  return False
196
+
197
+ def get_service_rollout_state(
198
+ self, cluster_name: str, service_name: str, start_time: float
199
+ ) -> tuple[Optional[str], Optional[str]]:
200
+ """
201
+ Returns status & statusReason for the deployment of an ECS service.
202
+
203
+ statusReason can be:
204
+ PENDING | SUCCESSFUL | STOPPED | STOP_REQUESTED |
205
+ IN_PROGRESS | ROLLBACK_REQUESTED | ROLLBACK_IN_PROGRESS |
206
+ ROLLBACK_SUCCESSFUL | ROLLBACK_FAILED
207
+ """
208
+ resp = self.ecs_client.list_service_deployments(
209
+ cluster=cluster_name, service=service_name, createdAt={"after": start_time - 180}
210
+ )
211
+ deployments = resp.get("serviceDeployments", [])
212
+
213
+ if not deployments:
214
+ return None, f"No deployments found for '{service_name}'"
215
+
216
+ return deployments[0].get("status"), deployments[0].get("statusReason")
217
+
218
+ def get_container_names_from_ecs_tasks(
219
+ self, cluster_name: str, task_ids: list[str]
220
+ ) -> list[str]:
221
+ """Retrieve container names from each ECS task provided."""
222
+
223
+ response = self.ecs_client.describe_tasks(cluster=cluster_name, tasks=task_ids)
224
+
225
+ names = []
226
+ for task in response.get("tasks", []):
227
+ for container in task.get("containers", []):
228
+ if container["name"] not in names:
229
+ names.append(container["name"])
230
+ return names
231
+
232
+ def register_task_definition(
233
+ self,
234
+ service: str,
235
+ task_definition: dict,
236
+ image_tag: Optional[str] = None,
237
+ ) -> str:
238
+ """Register a new task definition revision using provided model and
239
+ containerDefinitions."""
240
+
241
+ if image_tag:
242
+ for container in task_definition["containerDefinitions"]:
243
+ if container["name"] == service:
244
+ image_uri = container["image"].rsplit(":", 1)[0]
245
+ container["image"] = f"{image_uri}:{image_tag}"
246
+ break
247
+
248
+ try:
249
+ task_definition_response = self.ecs_client.register_task_definition(**task_definition)
250
+ return task_definition_response["taskDefinition"]["taskDefinitionArn"]
251
+ except ClientError as err:
252
+ raise PlatformException(f"Error registering task definition: {err}")
253
+
254
+ def update_service(
255
+ self, service: str, task_def_arn: str, environment: str, application: str
256
+ ) -> dict[str, Any]:
257
+ """Update an ECS service and return the response."""
258
+
259
+ try:
260
+ service_response = self.ecs_client.update_service(
261
+ cluster=f"{application}-{environment}-cluster",
262
+ service=f"{application}-{environment}-{service}",
263
+ taskDefinition=task_def_arn,
264
+ )
265
+ return service_response["service"]
266
+ except ClientError as err:
267
+ raise PlatformException(f"Error updating ECS service: {err}")
@@ -1,5 +1,9 @@
1
+ from typing import Dict
2
+ from typing import List
3
+
1
4
  from boto3 import Session
2
5
 
6
+ from dbt_platform_helper.constants import MANAGED_BY_PLATFORM_TERRAFORM
3
7
  from dbt_platform_helper.platform_exception import PlatformException
4
8
  from dbt_platform_helper.providers.io import ClickIOProvider
5
9
  from dbt_platform_helper.utils.aws import get_aws_session_or_abort
@@ -12,6 +16,17 @@ def normalise_to_cidr(ip: str):
12
16
  return f"{ip}/{SINGLE_IPV4_CIDR_PREFIX_LENGTH}"
13
17
 
14
18
 
19
+ class ALBDataNormaliser:
20
+
21
+ @staticmethod
22
+ def tags_to_dict(tags: List[Dict[str, str]]) -> Dict[str, str]:
23
+ return {tag.get("Key", ""): tag.get("Value", "") for tag in tags}
24
+
25
+ @staticmethod
26
+ def conditions_to_dict(conditions: List[Dict[str, List[str]]]) -> Dict[str, List[str]]:
27
+ return {condition.get("Field", ""): condition.get("Values", "") for condition in conditions}
28
+
29
+
15
30
  class LoadBalancerProvider:
16
31
 
17
32
  def __init__(self, session: Session = None, io: ClickIOProvider = ClickIOProvider()):
@@ -69,6 +84,29 @@ class LoadBalancerProvider:
69
84
 
70
85
  return target_group_arn
71
86
 
87
+ def get_target_groups(self, target_group_arns: List[str]) -> List[dict]:
88
+ tgs = []
89
+ paginator = self.evlb_client.get_paginator("describe_target_groups")
90
+ page_iterator = paginator.paginate(TargetGroupArns=target_group_arns)
91
+ for page in page_iterator:
92
+ tgs.extend(page["TargetGroups"])
93
+
94
+ return tgs
95
+
96
+ def get_target_groups_with_tags(
97
+ self, target_group_arns: List[str], normalise: bool = True
98
+ ) -> List[dict]:
99
+ target_groups = self.get_target_groups(target_group_arns)
100
+
101
+ tags = self.get_resources_tag_descriptions(target_groups, "TargetGroupArn")
102
+
103
+ tgs_with_tags = self.merge_in_tags_by_resource_arn(target_groups, tags, "TargetGroupArn")
104
+
105
+ if normalise:
106
+ for tg in tgs_with_tags:
107
+ tg["Tags"] = ALBDataNormaliser.tags_to_dict(tg["Tags"])
108
+ return tgs_with_tags
109
+
72
110
  def get_https_certificate_for_listener(self, listener_arn: str, env: str):
73
111
  certificates = []
74
112
  paginator = self.evlb_client.get_paginator("describe_listener_certificates")
@@ -87,7 +125,7 @@ class LoadBalancerProvider:
87
125
  listener_arn = self.get_https_listener_for_application(app, env)
88
126
  return self.get_https_certificate_for_listener(listener_arn, env)
89
127
 
90
- def get_listeners_for_load_balancer(self, load_balancer_arn):
128
+ def get_listeners_for_load_balancer(self, load_balancer_arn: str) -> List[dict]:
91
129
  listeners = []
92
130
  paginator = self.evlb_client.get_paginator("describe_listeners")
93
131
  page_iterator = paginator.paginate(LoadBalancerArn=load_balancer_arn)
@@ -98,6 +136,7 @@ class LoadBalancerProvider:
98
136
 
99
137
  def get_https_listener_for_application(self, app: str, env: str) -> str:
100
138
  load_balancer_arn = self.get_load_balancer_for_application(app, env)
139
+ self.io.debug(f"Load Balancer ARN: {load_balancer_arn}")
101
140
  listeners = self.get_listeners_for_load_balancer(load_balancer_arn)
102
141
 
103
142
  listener_arn = None
@@ -112,7 +151,7 @@ class LoadBalancerProvider:
112
151
 
113
152
  return listener_arn
114
153
 
115
- def get_load_balancers(self):
154
+ def get_load_balancers(self) -> List[dict]:
116
155
  load_balancers = []
117
156
  paginator = self.evlb_client.get_paginator("describe_load_balancers")
118
157
  page_iterator = paginator.paginate()
@@ -133,7 +172,11 @@ class LoadBalancerProvider:
133
172
  for lb in tag_descriptions:
134
173
  tags = {t["Key"]: t["Value"] for t in lb["Tags"]}
135
174
  # TODO: DBTP-1967: copilot hangover, creates coupling to specific tags could update to check application and environment
136
- if tags.get("copilot-application") == app and tags.get("copilot-environment") == env:
175
+ if (
176
+ tags.get("copilot-application") == app
177
+ and tags.get("copilot-environment") == env
178
+ and tags.get("managed-by", "") == MANAGED_BY_PLATFORM_TERRAFORM
179
+ ):
137
180
  return lb["ResourceArn"]
138
181
 
139
182
  raise LoadBalancerNotFoundException(app, env)
@@ -173,7 +216,37 @@ class LoadBalancerProvider:
173
216
  def get_rules_tag_descriptions_by_listener_arn(self, listener_arn: str) -> list:
174
217
  rules = self.get_listener_rules_by_listener_arn(listener_arn)
175
218
 
176
- return self.get_rules_tag_descriptions(rules)
219
+ return self.get_resources_tag_descriptions(rules)
220
+
221
+ def merge_in_tags_by_resource_arn(
222
+ self,
223
+ resources: List[dict],
224
+ tag_descriptions: List[dict],
225
+ resources_identifier: str = "RuleArn",
226
+ ):
227
+ tags_by_resource_arn = {
228
+ rule_tags.get("ResourceArn"): rule_tags for rule_tags in tag_descriptions if rule_tags
229
+ }
230
+ for resource in resources:
231
+ tags = tags_by_resource_arn[resource[resources_identifier]]
232
+ resource.update(tags)
233
+ return resources
234
+
235
+ def get_rules_with_tags_by_listener_arn(
236
+ self, listener_arn: str, normalise: bool = True
237
+ ) -> list:
238
+ rules = self.get_listener_rules_by_listener_arn(listener_arn)
239
+
240
+ tags = self.get_resources_tag_descriptions(rules)
241
+
242
+ rules_with_tags = self.merge_in_tags_by_resource_arn(rules, tags)
243
+
244
+ if normalise:
245
+ for rule in rules_with_tags:
246
+ rule["Conditions"] = ALBDataNormaliser.conditions_to_dict(rule["Conditions"])
247
+ rule["Tags"] = ALBDataNormaliser.tags_to_dict(rule["Tags"])
248
+
249
+ return rules_with_tags
177
250
 
178
251
  def get_listener_rules_by_listener_arn(self, listener_arn: str) -> list:
179
252
  rules = []
@@ -184,13 +257,15 @@ class LoadBalancerProvider:
184
257
 
185
258
  return rules
186
259
 
187
- def get_rules_tag_descriptions(self, rules: list) -> list:
260
+ def get_resources_tag_descriptions(
261
+ self, resources: list, resource_identifier: str = "RuleArn"
262
+ ) -> list:
188
263
  tag_descriptions = []
189
264
  chunk_size = 20
190
265
 
191
- for i in range(0, len(rules), chunk_size):
192
- chunk = rules[i : i + chunk_size]
193
- resource_arns = [r["RuleArn"] for r in chunk]
266
+ for i in range(0, len(resources), chunk_size):
267
+ chunk = resources[i : i + chunk_size]
268
+ resource_arns = [r[resource_identifier] for r in chunk]
194
269
  response = self.evlb_client.describe_tags(
195
270
  ResourceArns=resource_arns
196
271
  ) # describe_tags cannot be paginated - 04/04/2025
@@ -305,6 +380,9 @@ class LoadBalancerProvider:
305
380
 
306
381
  return deleted_rules
307
382
 
383
+ def delete_listener_rule_by_resource_arn(self, resource_arn: str) -> list:
384
+ return self.evlb_client.delete_rule(RuleArn=resource_arn)
385
+
308
386
 
309
387
  class LoadBalancerException(PlatformException):
310
388
  pass
@@ -0,0 +1,57 @@
1
+ import time
2
+
3
+ import boto3
4
+ from botocore.exceptions import ClientError
5
+
6
+ from dbt_platform_helper.platform_exception import PlatformException
7
+
8
+
9
+ class LogsProvider:
10
+
11
+ def __init__(self, client: boto3.client):
12
+ self.client = client
13
+
14
+ def check_log_streams_present(self, log_group: str, expected_log_streams: list[str]) -> bool:
15
+ """
16
+ Check whether the logs streams provided exist or not.
17
+
18
+ Retry for up to 5 minutes.
19
+ """
20
+
21
+ found_log_streams = set()
22
+ expected_log_streams = set(expected_log_streams)
23
+ timeout_seconds = 300
24
+ poll_interval_seconds = 2
25
+ deadline_seconds = time.monotonic() + timeout_seconds
26
+
27
+ while time.monotonic() < deadline_seconds:
28
+
29
+ remaining_log_streams = expected_log_streams - found_log_streams
30
+ if not remaining_log_streams:
31
+ return True
32
+
33
+ for log_stream in list(remaining_log_streams):
34
+ try:
35
+ response = self.client.describe_log_streams(
36
+ logGroupName=log_group, logStreamNamePrefix=log_stream, limit=1
37
+ )
38
+ except ClientError as e:
39
+ code = e.response.get("Error", {}).get("Code")
40
+ if code == "ResourceNotFoundException":
41
+ continue # Log stream not there yet, keep going
42
+ else:
43
+ raise PlatformException(
44
+ f"Failed to check if log stream '{log_stream}' exists due to an error {e}"
45
+ )
46
+
47
+ for ls in response.get("logStreams", []):
48
+ if ls.get("logStreamName") == log_stream:
49
+ found_log_streams.add(log_stream)
50
+
51
+ if expected_log_streams - found_log_streams:
52
+ time.sleep(poll_interval_seconds)
53
+
54
+ missing_log_streams = expected_log_streams - found_log_streams
55
+ raise PlatformException(
56
+ f"Timed out waiting for the following log streams to create: {missing_log_streams}"
57
+ )
@@ -0,0 +1,21 @@
1
+ import boto3
2
+ from botocore.exceptions import ClientError
3
+
4
+ from dbt_platform_helper.platform_exception import PlatformException
5
+
6
+
7
+ class S3Provider:
8
+
9
+ def __init__(self, client: boto3.client):
10
+ self.client = client
11
+
12
+ def get_object(self, bucket_name: str, object_key: str) -> str:
13
+ """Returns an object from an S3 bucket."""
14
+
15
+ try:
16
+ content = self.client.get_object(Bucket=bucket_name, Key=object_key)
17
+ return content["Body"].read().decode("utf-8")
18
+ except ClientError as e:
19
+ raise PlatformException(
20
+ f"Failed to get '{object_key}' from '{bucket_name}'. Error: {e}"
21
+ )
@@ -21,7 +21,6 @@ class TerraformManifestProvider:
21
21
  self,
22
22
  config_object,
23
23
  environment,
24
- image_tag,
25
24
  platform_helper_version: str,
26
25
  platform_config,
27
26
  module_source_override: str = None,
@@ -36,7 +35,7 @@ class TerraformManifestProvider:
36
35
  terraform = {}
37
36
  self._add_header(terraform)
38
37
 
39
- self._add_service_locals(terraform, environment, image_tag)
38
+ self._add_service_locals(terraform, environment)
40
39
 
41
40
  self._add_provider(terraform, account, deploy_to_account_id)
42
41
  self._add_backend(
@@ -47,15 +46,14 @@ class TerraformManifestProvider:
47
46
 
48
47
  self._write_terraform_json(terraform, service_dir)
49
48
 
50
- def _add_service_locals(self, terraform, environment, image_tag):
49
+ def _add_service_locals(self, terraform, environment):
51
50
  terraform["locals"] = {
52
51
  "environment": environment,
53
- "image_tag": image_tag,
54
52
  "platform_config": '${yamldecode(file("../../../../platform-config.yml"))}',
55
53
  "application": '${local.platform_config["application"]}',
56
54
  "environments": '${local.platform_config["environments"]}',
57
55
  "env_config": '${{for name, config in local.environments: name => merge(lookup(local.environments, "*", {}), config)}}',
58
- "service_config": '${yamldecode(templatefile("./service-config.yml", {PLATFORM_ENVIRONMENT_NAME = local.environment, IMAGE_TAG = local.image_tag}))}',
56
+ "service_config": '${yamldecode(file("./service-config.yml"))}',
59
57
  "raw_env_config": '${local.platform_config["environments"]}',
60
58
  "combined_env_config": '${{for name, config in local.raw_env_config: name => merge(lookup(local.raw_env_config, "*", {}), config)}}',
61
59
  "service_deployment_mode": '${lookup(local.combined_env_config[local.environment], "service-deployment-mode", "copilot")}',
@@ -98,18 +98,26 @@ class YamlFileProvider:
98
98
  return cleaned
99
99
 
100
100
  @staticmethod
101
- def find_and_replace(config, string: str, replacement: str):
101
+ def find_and_replace(config, strings: list, replacements: list):
102
+ if len(strings) != len(replacements):
103
+ raise ValueError("'strings' and 'replacements' must be the same length.")
104
+ if not isinstance(strings, list) or not isinstance(replacements, list):
105
+ raise ValueError("'strings' and 'replacements' must both be lists.")
102
106
  if isinstance(config, (dict, OrderedDict)):
103
107
  return {
104
- k: YamlFileProvider.find_and_replace(v, string, replacement)
108
+ k: YamlFileProvider.find_and_replace(v, strings, replacements)
105
109
  for k, v in config.items()
106
110
  }
107
111
  elif isinstance(config, list):
108
- return [YamlFileProvider.find_and_replace(item, string, replacement) for item in config]
112
+ return [
113
+ YamlFileProvider.find_and_replace(item, strings, replacements) for item in config
114
+ ]
109
115
  elif isinstance(config, str):
110
- return config.replace(string, replacement)
116
+ for s, r in zip(strings, replacements):
117
+ config = config.replace(s, r)
118
+ return config
111
119
  else:
112
- return replacement if config == string else config
120
+ return replacements if config == strings else config
113
121
 
114
122
 
115
123
  def account_number_representer(dumper, data):
@@ -1,8 +1,9 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: dbt-platform-helper
3
- Version: 15.9.0
3
+ Version: 15.11.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
+ License-File: LICENSE
6
7
  Author: Department for Business and Trade Platform Team
7
8
  Author-email: sre-team@digital.trade.gov.uk
8
9
  Requires-Python: >3.9.1,<4.0
@@ -12,12 +13,13 @@ Classifier: Programming Language :: Python :: 3.10
12
13
  Classifier: Programming Language :: Python :: 3.11
13
14
  Classifier: Programming Language :: Python :: 3.12
14
15
  Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
15
17
  Requires-Dist: Jinja2 (==3.1.6)
16
18
  Requires-Dist: boto3 (>=1.35.2,<2.0.0)
17
19
  Requires-Dist: botocore (>=1.34.85,<2.0.0)
18
20
  Requires-Dist: cfn-flip (>=1.3.0,<2.0.0)
19
21
  Requires-Dist: click (>=8.1.3,<9.0.0)
20
- Requires-Dist: jinja2-simple-tags (>=0.5.0,<0.6.0)
22
+ Requires-Dist: jinja2-simple-tags (>=0.5,<0.7)
21
23
  Requires-Dist: prettytable (>=3.9.0,<4.0.0)
22
24
  Requires-Dist: psycopg2-binary (>=2.9.9,<3.0.0)
23
25
  Requires-Dist: pydantic (>=2.11.7,<3.0.0)
@@ -1,4 +1,4 @@
1
- dbt_platform_helper/COMMANDS.md,sha256=eR_fK_iMO59_PjGWZIv3MDD61zG5Hlp9hbHeoXaHwyY,25096
1
+ dbt_platform_helper/COMMANDS.md,sha256=8TJM8M7hUymuRVGI0jsIJFD_ONTU8sT1EyywwO44WlU,23929
2
2
  dbt_platform_helper/README.md,sha256=B0qN2_u_ASqqgkGDWY2iwNGZt_9tUgMb9XqtaTuzYjw,1530
3
3
  dbt_platform_helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  dbt_platform_helper/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -10,63 +10,66 @@ dbt_platform_helper/commands/copilot.py,sha256=L9UUuqD62q0aFrTTEUla3A1WJBz-vFBfV
10
10
  dbt_platform_helper/commands/database.py,sha256=2RJZEzaSqcNtDG1M2mZw-nB6agAd3GNAJsg2pjFF7vc,4407
11
11
  dbt_platform_helper/commands/environment.py,sha256=zexiry6_dbOmD8w2lBrgdcFQKAG7XyJg9pvNtwtgPRk,3616
12
12
  dbt_platform_helper/commands/generate.py,sha256=4M0ZiGN2w-bwgPMxeItFfT6vA7sOMjuceHEN7RAYkhc,735
13
+ dbt_platform_helper/commands/internal.py,sha256=oo7bMUEiZRlmZQYi3Kbej-SK8nwUxFnFcUqEoh-5vL8,4709
13
14
  dbt_platform_helper/commands/notify.py,sha256=DMXA0AHot6-7CMzmY0PXPMMBVnLgvQgXr6np6OnSQh4,3401
14
15
  dbt_platform_helper/commands/pipeline.py,sha256=PGpDDmyReVa4gdpXDwJEsHN51f5MgTIbm2AibTkuWrE,2580
15
16
  dbt_platform_helper/commands/secrets.py,sha256=AMwLCi7uxuMMfhDfGD8OcuIYMzU8q2VQXWxaiuztvzA,3296
16
- dbt_platform_helper/commands/service.py,sha256=Lqo4vmNHxa0ofTWIYEpwKoyT1iqsTCkMjz3HeqSE4og,1702
17
17
  dbt_platform_helper/commands/version.py,sha256=2GltWeeN7cqhVj9FhYWSbXSQSyNILHVNOeANGWtAllY,1097
18
- dbt_platform_helper/constants.py,sha256=vIe6SyesBDtkjgRieT-Ui1ZLS_4c1YoqN7JE9qXt1uQ,1858
18
+ dbt_platform_helper/constants.py,sha256=POxZqjnqp9R3kIj5TxN57FpBSrdw9LWzlHwe81PTEm0,2418
19
19
  dbt_platform_helper/default-extensions.yml,sha256=SU1ZitskbuEBpvE7efc3s56eAUF11j70brhj_XrNMMo,493
20
20
  dbt_platform_helper/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  dbt_platform_helper/domain/codebase.py,sha256=2hJoBiDB2ciOudT_YUR44XV0ZQPWUJld_UIuds4XOt8,12481
22
- dbt_platform_helper/domain/conduit.py,sha256=0aX5rhynkkJj8rJUwfyLENyCwlAI67_Vkky1lOEl6rw,12496
23
- dbt_platform_helper/domain/config.py,sha256=Iyf-lV4YDD6BHH-RRaTvp-7qPS8BYeHM_SkSfeU7si4,13802
22
+ dbt_platform_helper/domain/conduit.py,sha256=DOL4GET0D9UHvnmpQZTRrkdEcYKxV35AncJX_AzA488,12520
23
+ dbt_platform_helper/domain/config.py,sha256=tLDX3oDMicduN0MH3RZxiK7aBG1U1-BXyG8y6U1pbqI,14877
24
24
  dbt_platform_helper/domain/copilot.py,sha256=g8W2LaskyhOvtNoCoNbwucGTrfdAzj-AJ0J98tgLbhA,15138
25
25
  dbt_platform_helper/domain/copilot_environment.py,sha256=fL3XJCOfO0BJRCrCoBPFCcshrQoX1FeSYNTziOEaH4A,9093
26
26
  dbt_platform_helper/domain/database_copy.py,sha256=4A84xqj3c_VjYlXb81B8Kt8us8IcCQVVF6GyPAAmwyo,9638
27
- dbt_platform_helper/domain/maintenance_page.py,sha256=pTY_GXAMzqowdLCXM7BmsbsUeZ8oPO4mI8pUae66cjU,15786
27
+ dbt_platform_helper/domain/maintenance_page.py,sha256=FtDQ43Wye_z8MlkT7pGButwHRPFJX9nfVOPr6BDRfJk,15958
28
28
  dbt_platform_helper/domain/notify.py,sha256=_BWj5znDWtrSdJ5xzDBgnao4ukliBA5wiUZGobIDyiI,1894
29
29
  dbt_platform_helper/domain/pipelines.py,sha256=NrH9dl5Pzdds9TdWJmPZmgyBhHfcaN6byouBWI0W67s,8565
30
30
  dbt_platform_helper/domain/plans.py,sha256=X5-jKGiJDVWn0CRH1k5aV74fTH0E41HqFQcCo5kB4hI,1160
31
- dbt_platform_helper/domain/service.py,sha256=b1wtvINDhyMmauTb4Ed2wyyGQXsKPfB-SIcewjXiCwA,6771
31
+ dbt_platform_helper/domain/service.py,sha256=1lWXxAmb6URXJCQlgMZMoJ2OYQLEdXVbMG0_yFWZsRI,17862
32
32
  dbt_platform_helper/domain/terraform_environment.py,sha256=g9PSuZeVXgboGNDXU7OGMiRATd67NU8S92HUGri1fbo,2471
33
+ dbt_platform_helper/domain/update_alb_rules.py,sha256=DiFxw0Gf7ZBsUaMbQmHuOYLJzFoUKuzZY5a09QIcTzs,14964
33
34
  dbt_platform_helper/domain/versioning.py,sha256=pIL8VPAJHqX5kJBp3QIxII5vmUo4aIYW_U9u_KxUJd0,5494
34
- dbt_platform_helper/entities/platform_config_schema.py,sha256=IUwjxQ19SotiAHLe5K9lpftaw4tJmMk-U6PQbe-HzEU,27551
35
+ dbt_platform_helper/entities/platform_config_schema.py,sha256=OJlPMBkV2h8HbxSui-c6CXoqAAg2UN-V2Lq5qn5SwxY,27533
35
36
  dbt_platform_helper/entities/semantic_version.py,sha256=VgQ6V6OgSaleuVmMB8Kl_yLoakXl2auapJTDbK00mfc,2679
36
- dbt_platform_helper/entities/service.py,sha256=GExA0gOiKIcY3WX4vx_j9VSv6BAeRm9-tIUbs7YkyFI,4169
37
+ dbt_platform_helper/entities/service.py,sha256=Vdzu4zeazuS0j0C9jgvKKNORRyVcjU77CIoLv3V6CPM,9343
37
38
  dbt_platform_helper/jinja2_tags.py,sha256=hKG6RS3zlxJHQ-Op9r2U2-MhWp4s3lZir4Ihe24ApJ0,540
38
39
  dbt_platform_helper/platform_exception.py,sha256=HGfCYRD20REsynqMKmyZndTfdkMd5dLSIEB2qGGCeP8,244
39
40
  dbt_platform_helper/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
41
  dbt_platform_helper/providers/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
- dbt_platform_helper/providers/aws/exceptions.py,sha256=7zrbzGuZhZypmT7LB4pK7TrYD4kn5H0L_lgx07o2VPg,2332
42
+ dbt_platform_helper/providers/aws/exceptions.py,sha256=88EA__k0Rg3PrHw_Oq2ZiPfA34vcQO_mqN2Cbg2I7s0,2528
42
43
  dbt_platform_helper/providers/aws/interfaces.py,sha256=0JFggcUTJ8zERdxNVVpIiKvaaZeT2c-VECDG--MOi8E,285
43
44
  dbt_platform_helper/providers/aws/opensearch.py,sha256=Qne2SoPllmacVSc7AxtjBlEbSBsRMbR_ySEkEymSF9k,581
44
45
  dbt_platform_helper/providers/aws/redis.py,sha256=i3Kb00_BdqssjQg1wgZ-8GRXcEWQiORWnIEq6qkAXjQ,551
45
- dbt_platform_helper/providers/aws/sso_auth.py,sha256=1cE9gVu0XZoE3Nycs1anShistRU_CZCOGMFzFpaAq0w,2275
46
+ dbt_platform_helper/providers/aws/sso_auth.py,sha256=fl1WSmhpyt8WZAe6EY5WDA33nEPrIIQzO-DVuWlFjsA,2844
46
47
  dbt_platform_helper/providers/cache.py,sha256=1hEwp0y9WYbEfgsp-RU9MyzIgCt1-4BxApgd_0uVweE,3615
47
48
  dbt_platform_helper/providers/cloudformation.py,sha256=syMH6xc-ALRbsYQvlw9RcjX7c1MufFzwEdEzp_ucWig,5359
48
- dbt_platform_helper/providers/config.py,sha256=652JeXsZgRcV2vN-mKDh_FwapaGdL4dOkHx8mRRohG4,10993
49
+ dbt_platform_helper/providers/config.py,sha256=8eLz22fOrz28fKGCbQn-j3FDGhI8bY5WCpBc1_THDwg,10505
49
50
  dbt_platform_helper/providers/config_validator.py,sha256=kZZAJIApKKZ9yjDwCnZ6oL6ZSfaA-CxQrisnAWNgIhw,10966
50
51
  dbt_platform_helper/providers/copilot.py,sha256=voFVGhvtOElulx6Cgd1KQGkybrg8v4oGkJTr_xRpF18,5582
51
52
  dbt_platform_helper/providers/ecr.py,sha256=eYXSY1-pFN6F3Es1WSZgv3dmvX2oD-baqhHDO-QzgVg,4382
52
- dbt_platform_helper/providers/ecs.py,sha256=4XRpOgcl7KFiTp9lhNrp4Lvmje0ZFYuUh9Z_eEqhyhA,6538
53
+ dbt_platform_helper/providers/ecs.py,sha256=nx1KZdsz6DLS23M9cSvMXQRuSqk5DF2XQ6njrrcLE0s,9989
53
54
  dbt_platform_helper/providers/environment_variable.py,sha256=PopMLKnWcoObQrgg7xSEb-pzVT54_QGFsb_HtL_9YU8,794
54
55
  dbt_platform_helper/providers/files.py,sha256=sH02Ka_WaDBFtN4Y0i9kuo9YQoKn2rhUy0Dn8LPMrEw,857
55
56
  dbt_platform_helper/providers/io.py,sha256=-C_NLHH_ebN2G5ZMtAAj4E9AqcDZX98mIWgAV34Dm7U,1737
56
57
  dbt_platform_helper/providers/kms.py,sha256=JR2EU3icXePoJCtr7QnqDPj1wWbyn5Uf9CRFq3_4lRs,647
57
- dbt_platform_helper/providers/load_balancers.py,sha256=Xm7cyFIKfGPeD1HzIFCT8XQ6QJA8yJOwZjTuc6k8zcw,11800
58
+ dbt_platform_helper/providers/load_balancers.py,sha256=HKC5gYRDeyRTzGfMqt6seIj0UE-NpNksmQrni-8v-Jo,14734
59
+ dbt_platform_helper/providers/logs.py,sha256=fntPhkvHXq0h1gvSQ4Sdnq9rwpWup2Q-i4Gkn_mYkfQ,2076
58
60
  dbt_platform_helper/providers/parameter_store.py,sha256=klxDhcQ65Yc2KAc4Gf5P0vhpZOW7_vZalAVb-LLAA4s,1568
61
+ dbt_platform_helper/providers/s3.py,sha256=A-0sfQuHBbfRJ1txNQ_NXTrqNRrvw4LTZVaxK08q8I4,661
59
62
  dbt_platform_helper/providers/schema_migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
63
  dbt_platform_helper/providers/schema_migrations/schema_v0_to_v1_migration.py,sha256=dplbvEAc8l8F4dEAy3JwLP1Phjkt4QVuQYNX_EKe_Ls,2036
61
64
  dbt_platform_helper/providers/schema_migrator.py,sha256=qk14k3hMz1av9VrxHyJw2OKJLQnCBv_ugOoxZr3tFXQ,2854
62
65
  dbt_platform_helper/providers/secrets.py,sha256=mOTIrcRRxxV2tS40U8onAjWekfPS3NzCvvyCMjr_yrU,5327
63
66
  dbt_platform_helper/providers/slack_channel_notifier.py,sha256=G8etEcaBQSNHg8BnyC5UPv6l3vUB14cYWjcaAQksaEk,2135
64
- dbt_platform_helper/providers/terraform_manifest.py,sha256=SEdlylBIpe0qsQFEG0ttJeoE9BthkzJ7VGQOfgOoC3g,14274
67
+ dbt_platform_helper/providers/terraform_manifest.py,sha256=Nkc-1LbmlrBk4Bt6bCC1lexp0jkfyaGuYTJFq6Xi8kI,14111
65
68
  dbt_platform_helper/providers/validation.py,sha256=i2g-Mrd4hy_fGIfGa6ZQy4vTJ40OM44Fe_XpEifGWxs,126
66
69
  dbt_platform_helper/providers/version.py,sha256=QNGrV5nyJi0JysXowYUU4OrXGDn27WmFezlV8benpdY,4251
67
70
  dbt_platform_helper/providers/version_status.py,sha256=qafnhZrEc9k1cvXJpvJhkGj6WtkzcsoQhqS_Y6JXy48,929
68
71
  dbt_platform_helper/providers/vpc.py,sha256=KdgwyHv2RwNpq16Sa2FtWm7DMJlTNmsPbXkbMNMYiQo,4082
69
- dbt_platform_helper/providers/yaml_file.py,sha256=pgSgC20_Se43HfMbpkTGyn4MkXkuA963t9djxxBoJnI,3902
72
+ dbt_platform_helper/providers/yaml_file.py,sha256=rWWYTXUgfklrFC7wcdfloJbJyQTDL7HKpoPM-qf_vBU,4304
70
73
  dbt_platform_helper/templates/.copilot/config.yml,sha256=J_bA9sCtBdCPBRImpCBRnYvhQd4vpLYIXIU-lq9vbkA,158
71
74
  dbt_platform_helper/templates/.copilot/image_build_run.sh,sha256=adYucYXEB-kAgZNjTQo0T6EIAY8sh_xCEvVhWKKQ8mw,164
72
75
  dbt_platform_helper/templates/.copilot/phases/build.sh,sha256=umKXePcRvx4XyrRY0fAWIyYFtNjqBI2L8vIJk-V7C60,121
@@ -102,12 +105,12 @@ dbt_platform_helper/utils/git.py,sha256=9jyLhv37KKE6r-_hb3zvjhTbluA81kdrOdNeG6MB
102
105
  dbt_platform_helper/utils/messages.py,sha256=nWA7BWLb7ND0WH5TejDN4OQUJSKYBxU4tyCzteCrfT0,142
103
106
  dbt_platform_helper/utils/template.py,sha256=g-Db-0I6a6diOHkgK1nYA0IxJSO4TRrjqOvlyeOR32o,950
104
107
  dbt_platform_helper/utils/validation.py,sha256=W5jKC2zp5Q7cJ0PT57GB-s9FkJXrNt1jmWojXRFymcY,1187
105
- platform_helper.py,sha256=LP9o5_1H9-FKbBa85FqW07QFPn6STg6D4gM2-QHaaD4,2048
108
+ platform_helper.py,sha256=JKfXj2lptIc2CRHxo8u79kDKQH_IRV3jwPaL8T-1aAs,2052
106
109
  terraform/elasticache-redis/plans.yml,sha256=efJfkLuLC_5TwhLb9DalKHOuZFO79y6iei6Dg_tqKjI,1831
107
110
  terraform/opensearch/plans.yml,sha256=lQbUSNMGfvUeDMcGx8mSwzGQhMJU3EZ4J4tPzPKaq6c,1471
108
111
  terraform/postgres/plans.yml,sha256=plwCklW1VB_tNJFyUduRMZx9UANgiWH_7TGLWUaUEus,2553
109
- dbt_platform_helper-15.9.0.dist-info/LICENSE,sha256=dP79lN73--7LMApnankTGLqDbImXg8iYFqWgnExGkGk,1090
110
- dbt_platform_helper-15.9.0.dist-info/METADATA,sha256=nM4pw5jMBBu4AIRNHM_QXTqBJJupwtz8P6MlzWE9p3w,2732
111
- dbt_platform_helper-15.9.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
112
- dbt_platform_helper-15.9.0.dist-info/entry_points.txt,sha256=QhbY8F434A-onsg0-FsdMd2U6HKh6Q7yCFFZrGUh5-M,67
113
- dbt_platform_helper-15.9.0.dist-info/RECORD,,
112
+ dbt_platform_helper-15.11.0.dist-info/METADATA,sha256=Jt6FOZ7eqigWjVHeUZlxvwxYiiUrpuybPfi-8aMNLts,2802
113
+ dbt_platform_helper-15.11.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
114
+ dbt_platform_helper-15.11.0.dist-info/entry_points.txt,sha256=QhbY8F434A-onsg0-FsdMd2U6HKh6Q7yCFFZrGUh5-M,67
115
+ dbt_platform_helper-15.11.0.dist-info/licenses/LICENSE,sha256=dP79lN73--7LMApnankTGLqDbImXg8iYFqWgnExGkGk,1090
116
+ dbt_platform_helper-15.11.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.3
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
platform_helper.py CHANGED
@@ -12,10 +12,10 @@ from dbt_platform_helper.commands.copilot import copilot as copilot_commands
12
12
  from dbt_platform_helper.commands.database import database as database_commands
13
13
  from dbt_platform_helper.commands.environment import environment as environment_commands
14
14
  from dbt_platform_helper.commands.generate import generate as generate_commands
15
+ from dbt_platform_helper.commands.internal import internal as internal_commands
15
16
  from dbt_platform_helper.commands.notify import notify as notify_commands
16
17
  from dbt_platform_helper.commands.pipeline import pipeline as pipeline_commands
17
18
  from dbt_platform_helper.commands.secrets import secrets as secrets_commands
18
- from dbt_platform_helper.commands.service import service as service_commands
19
19
  from dbt_platform_helper.commands.version import version as version_commands
20
20
  from dbt_platform_helper.utils.click import ClickDocOptGroup
21
21
 
@@ -36,9 +36,9 @@ platform_helper.add_command(config_commands)
36
36
  platform_helper.add_command(copilot_commands)
37
37
  platform_helper.add_command(environment_commands)
38
38
  platform_helper.add_command(generate_commands)
39
+ platform_helper.add_command(internal_commands)
39
40
  platform_helper.add_command(pipeline_commands)
40
41
  platform_helper.add_command(secrets_commands)
41
- platform_helper.add_command(service_commands)
42
42
  platform_helper.add_command(notify_commands)
43
43
  platform_helper.add_command(database_commands)
44
44
  platform_helper.add_command(version_commands)