dbt-platform-helper 15.10.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.
- dbt_platform_helper/COMMANDS.md +0 -91
- dbt_platform_helper/commands/internal.py +111 -0
- dbt_platform_helper/constants.py +14 -0
- dbt_platform_helper/domain/conduit.py +1 -1
- dbt_platform_helper/domain/config.py +30 -1
- dbt_platform_helper/domain/maintenance_page.py +10 -8
- dbt_platform_helper/domain/service.py +270 -66
- dbt_platform_helper/domain/update_alb_rules.py +346 -0
- dbt_platform_helper/entities/platform_config_schema.py +0 -3
- dbt_platform_helper/entities/service.py +139 -13
- dbt_platform_helper/providers/aws/exceptions.py +5 -0
- dbt_platform_helper/providers/aws/sso_auth.py +14 -0
- dbt_platform_helper/providers/config.py +0 -11
- dbt_platform_helper/providers/ecs.py +104 -11
- dbt_platform_helper/providers/load_balancers.py +86 -8
- dbt_platform_helper/providers/logs.py +57 -0
- dbt_platform_helper/providers/s3.py +21 -0
- dbt_platform_helper/providers/terraform_manifest.py +3 -5
- dbt_platform_helper/providers/yaml_file.py +13 -5
- {dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/METADATA +1 -1
- {dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/RECORD +25 -23
- platform_helper.py +0 -2
- dbt_platform_helper/commands/service.py +0 -53
- {dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/WHEEL +0 -0
- {dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/entry_points.txt +0 -0
- {dbt_platform_helper-15.10.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
|
|
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:
|
|
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(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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:
|
|
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
|
|
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.
|
|
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
|
|
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(
|
|
192
|
-
chunk =
|
|
193
|
-
resource_arns = [r[
|
|
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
|
|
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
|
|
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(
|
|
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,
|
|
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,
|
|
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 [
|
|
112
|
+
return [
|
|
113
|
+
YamlFileProvider.find_and_replace(item, strings, replacements) for item in config
|
|
114
|
+
]
|
|
109
115
|
elif isinstance(config, str):
|
|
110
|
-
|
|
116
|
+
for s, r in zip(strings, replacements):
|
|
117
|
+
config = config.replace(s, r)
|
|
118
|
+
return config
|
|
111
119
|
else:
|
|
112
|
-
return
|
|
120
|
+
return replacements if config == strings else config
|
|
113
121
|
|
|
114
122
|
|
|
115
123
|
def account_number_representer(dumper, data):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
dbt_platform_helper/COMMANDS.md,sha256=
|
|
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,64 +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=
|
|
13
|
+
dbt_platform_helper/commands/internal.py,sha256=oo7bMUEiZRlmZQYi3Kbej-SK8nwUxFnFcUqEoh-5vL8,4709
|
|
14
14
|
dbt_platform_helper/commands/notify.py,sha256=DMXA0AHot6-7CMzmY0PXPMMBVnLgvQgXr6np6OnSQh4,3401
|
|
15
15
|
dbt_platform_helper/commands/pipeline.py,sha256=PGpDDmyReVa4gdpXDwJEsHN51f5MgTIbm2AibTkuWrE,2580
|
|
16
16
|
dbt_platform_helper/commands/secrets.py,sha256=AMwLCi7uxuMMfhDfGD8OcuIYMzU8q2VQXWxaiuztvzA,3296
|
|
17
|
-
dbt_platform_helper/commands/service.py,sha256=Lqo4vmNHxa0ofTWIYEpwKoyT1iqsTCkMjz3HeqSE4og,1702
|
|
18
17
|
dbt_platform_helper/commands/version.py,sha256=2GltWeeN7cqhVj9FhYWSbXSQSyNILHVNOeANGWtAllY,1097
|
|
19
|
-
dbt_platform_helper/constants.py,sha256=
|
|
18
|
+
dbt_platform_helper/constants.py,sha256=POxZqjnqp9R3kIj5TxN57FpBSrdw9LWzlHwe81PTEm0,2418
|
|
20
19
|
dbt_platform_helper/default-extensions.yml,sha256=SU1ZitskbuEBpvE7efc3s56eAUF11j70brhj_XrNMMo,493
|
|
21
20
|
dbt_platform_helper/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
21
|
dbt_platform_helper/domain/codebase.py,sha256=2hJoBiDB2ciOudT_YUR44XV0ZQPWUJld_UIuds4XOt8,12481
|
|
23
|
-
dbt_platform_helper/domain/conduit.py,sha256=
|
|
24
|
-
dbt_platform_helper/domain/config.py,sha256=
|
|
22
|
+
dbt_platform_helper/domain/conduit.py,sha256=DOL4GET0D9UHvnmpQZTRrkdEcYKxV35AncJX_AzA488,12520
|
|
23
|
+
dbt_platform_helper/domain/config.py,sha256=tLDX3oDMicduN0MH3RZxiK7aBG1U1-BXyG8y6U1pbqI,14877
|
|
25
24
|
dbt_platform_helper/domain/copilot.py,sha256=g8W2LaskyhOvtNoCoNbwucGTrfdAzj-AJ0J98tgLbhA,15138
|
|
26
25
|
dbt_platform_helper/domain/copilot_environment.py,sha256=fL3XJCOfO0BJRCrCoBPFCcshrQoX1FeSYNTziOEaH4A,9093
|
|
27
26
|
dbt_platform_helper/domain/database_copy.py,sha256=4A84xqj3c_VjYlXb81B8Kt8us8IcCQVVF6GyPAAmwyo,9638
|
|
28
|
-
dbt_platform_helper/domain/maintenance_page.py,sha256=
|
|
27
|
+
dbt_platform_helper/domain/maintenance_page.py,sha256=FtDQ43Wye_z8MlkT7pGButwHRPFJX9nfVOPr6BDRfJk,15958
|
|
29
28
|
dbt_platform_helper/domain/notify.py,sha256=_BWj5znDWtrSdJ5xzDBgnao4ukliBA5wiUZGobIDyiI,1894
|
|
30
29
|
dbt_platform_helper/domain/pipelines.py,sha256=NrH9dl5Pzdds9TdWJmPZmgyBhHfcaN6byouBWI0W67s,8565
|
|
31
30
|
dbt_platform_helper/domain/plans.py,sha256=X5-jKGiJDVWn0CRH1k5aV74fTH0E41HqFQcCo5kB4hI,1160
|
|
32
|
-
dbt_platform_helper/domain/service.py,sha256=
|
|
31
|
+
dbt_platform_helper/domain/service.py,sha256=1lWXxAmb6URXJCQlgMZMoJ2OYQLEdXVbMG0_yFWZsRI,17862
|
|
33
32
|
dbt_platform_helper/domain/terraform_environment.py,sha256=g9PSuZeVXgboGNDXU7OGMiRATd67NU8S92HUGri1fbo,2471
|
|
33
|
+
dbt_platform_helper/domain/update_alb_rules.py,sha256=DiFxw0Gf7ZBsUaMbQmHuOYLJzFoUKuzZY5a09QIcTzs,14964
|
|
34
34
|
dbt_platform_helper/domain/versioning.py,sha256=pIL8VPAJHqX5kJBp3QIxII5vmUo4aIYW_U9u_KxUJd0,5494
|
|
35
|
-
dbt_platform_helper/entities/platform_config_schema.py,sha256=
|
|
35
|
+
dbt_platform_helper/entities/platform_config_schema.py,sha256=OJlPMBkV2h8HbxSui-c6CXoqAAg2UN-V2Lq5qn5SwxY,27533
|
|
36
36
|
dbt_platform_helper/entities/semantic_version.py,sha256=VgQ6V6OgSaleuVmMB8Kl_yLoakXl2auapJTDbK00mfc,2679
|
|
37
|
-
dbt_platform_helper/entities/service.py,sha256=
|
|
37
|
+
dbt_platform_helper/entities/service.py,sha256=Vdzu4zeazuS0j0C9jgvKKNORRyVcjU77CIoLv3V6CPM,9343
|
|
38
38
|
dbt_platform_helper/jinja2_tags.py,sha256=hKG6RS3zlxJHQ-Op9r2U2-MhWp4s3lZir4Ihe24ApJ0,540
|
|
39
39
|
dbt_platform_helper/platform_exception.py,sha256=HGfCYRD20REsynqMKmyZndTfdkMd5dLSIEB2qGGCeP8,244
|
|
40
40
|
dbt_platform_helper/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
41
|
dbt_platform_helper/providers/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
|
-
dbt_platform_helper/providers/aws/exceptions.py,sha256=
|
|
42
|
+
dbt_platform_helper/providers/aws/exceptions.py,sha256=88EA__k0Rg3PrHw_Oq2ZiPfA34vcQO_mqN2Cbg2I7s0,2528
|
|
43
43
|
dbt_platform_helper/providers/aws/interfaces.py,sha256=0JFggcUTJ8zERdxNVVpIiKvaaZeT2c-VECDG--MOi8E,285
|
|
44
44
|
dbt_platform_helper/providers/aws/opensearch.py,sha256=Qne2SoPllmacVSc7AxtjBlEbSBsRMbR_ySEkEymSF9k,581
|
|
45
45
|
dbt_platform_helper/providers/aws/redis.py,sha256=i3Kb00_BdqssjQg1wgZ-8GRXcEWQiORWnIEq6qkAXjQ,551
|
|
46
|
-
dbt_platform_helper/providers/aws/sso_auth.py,sha256=
|
|
46
|
+
dbt_platform_helper/providers/aws/sso_auth.py,sha256=fl1WSmhpyt8WZAe6EY5WDA33nEPrIIQzO-DVuWlFjsA,2844
|
|
47
47
|
dbt_platform_helper/providers/cache.py,sha256=1hEwp0y9WYbEfgsp-RU9MyzIgCt1-4BxApgd_0uVweE,3615
|
|
48
48
|
dbt_platform_helper/providers/cloudformation.py,sha256=syMH6xc-ALRbsYQvlw9RcjX7c1MufFzwEdEzp_ucWig,5359
|
|
49
|
-
dbt_platform_helper/providers/config.py,sha256=
|
|
49
|
+
dbt_platform_helper/providers/config.py,sha256=8eLz22fOrz28fKGCbQn-j3FDGhI8bY5WCpBc1_THDwg,10505
|
|
50
50
|
dbt_platform_helper/providers/config_validator.py,sha256=kZZAJIApKKZ9yjDwCnZ6oL6ZSfaA-CxQrisnAWNgIhw,10966
|
|
51
51
|
dbt_platform_helper/providers/copilot.py,sha256=voFVGhvtOElulx6Cgd1KQGkybrg8v4oGkJTr_xRpF18,5582
|
|
52
52
|
dbt_platform_helper/providers/ecr.py,sha256=eYXSY1-pFN6F3Es1WSZgv3dmvX2oD-baqhHDO-QzgVg,4382
|
|
53
|
-
dbt_platform_helper/providers/ecs.py,sha256=
|
|
53
|
+
dbt_platform_helper/providers/ecs.py,sha256=nx1KZdsz6DLS23M9cSvMXQRuSqk5DF2XQ6njrrcLE0s,9989
|
|
54
54
|
dbt_platform_helper/providers/environment_variable.py,sha256=PopMLKnWcoObQrgg7xSEb-pzVT54_QGFsb_HtL_9YU8,794
|
|
55
55
|
dbt_platform_helper/providers/files.py,sha256=sH02Ka_WaDBFtN4Y0i9kuo9YQoKn2rhUy0Dn8LPMrEw,857
|
|
56
56
|
dbt_platform_helper/providers/io.py,sha256=-C_NLHH_ebN2G5ZMtAAj4E9AqcDZX98mIWgAV34Dm7U,1737
|
|
57
57
|
dbt_platform_helper/providers/kms.py,sha256=JR2EU3icXePoJCtr7QnqDPj1wWbyn5Uf9CRFq3_4lRs,647
|
|
58
|
-
dbt_platform_helper/providers/load_balancers.py,sha256=
|
|
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
|
|
59
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
|
|
60
62
|
dbt_platform_helper/providers/schema_migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
61
63
|
dbt_platform_helper/providers/schema_migrations/schema_v0_to_v1_migration.py,sha256=dplbvEAc8l8F4dEAy3JwLP1Phjkt4QVuQYNX_EKe_Ls,2036
|
|
62
64
|
dbt_platform_helper/providers/schema_migrator.py,sha256=qk14k3hMz1av9VrxHyJw2OKJLQnCBv_ugOoxZr3tFXQ,2854
|
|
63
65
|
dbt_platform_helper/providers/secrets.py,sha256=mOTIrcRRxxV2tS40U8onAjWekfPS3NzCvvyCMjr_yrU,5327
|
|
64
66
|
dbt_platform_helper/providers/slack_channel_notifier.py,sha256=G8etEcaBQSNHg8BnyC5UPv6l3vUB14cYWjcaAQksaEk,2135
|
|
65
|
-
dbt_platform_helper/providers/terraform_manifest.py,sha256=
|
|
67
|
+
dbt_platform_helper/providers/terraform_manifest.py,sha256=Nkc-1LbmlrBk4Bt6bCC1lexp0jkfyaGuYTJFq6Xi8kI,14111
|
|
66
68
|
dbt_platform_helper/providers/validation.py,sha256=i2g-Mrd4hy_fGIfGa6ZQy4vTJ40OM44Fe_XpEifGWxs,126
|
|
67
69
|
dbt_platform_helper/providers/version.py,sha256=QNGrV5nyJi0JysXowYUU4OrXGDn27WmFezlV8benpdY,4251
|
|
68
70
|
dbt_platform_helper/providers/version_status.py,sha256=qafnhZrEc9k1cvXJpvJhkGj6WtkzcsoQhqS_Y6JXy48,929
|
|
69
71
|
dbt_platform_helper/providers/vpc.py,sha256=KdgwyHv2RwNpq16Sa2FtWm7DMJlTNmsPbXkbMNMYiQo,4082
|
|
70
|
-
dbt_platform_helper/providers/yaml_file.py,sha256=
|
|
72
|
+
dbt_platform_helper/providers/yaml_file.py,sha256=rWWYTXUgfklrFC7wcdfloJbJyQTDL7HKpoPM-qf_vBU,4304
|
|
71
73
|
dbt_platform_helper/templates/.copilot/config.yml,sha256=J_bA9sCtBdCPBRImpCBRnYvhQd4vpLYIXIU-lq9vbkA,158
|
|
72
74
|
dbt_platform_helper/templates/.copilot/image_build_run.sh,sha256=adYucYXEB-kAgZNjTQo0T6EIAY8sh_xCEvVhWKKQ8mw,164
|
|
73
75
|
dbt_platform_helper/templates/.copilot/phases/build.sh,sha256=umKXePcRvx4XyrRY0fAWIyYFtNjqBI2L8vIJk-V7C60,121
|
|
@@ -103,12 +105,12 @@ dbt_platform_helper/utils/git.py,sha256=9jyLhv37KKE6r-_hb3zvjhTbluA81kdrOdNeG6MB
|
|
|
103
105
|
dbt_platform_helper/utils/messages.py,sha256=nWA7BWLb7ND0WH5TejDN4OQUJSKYBxU4tyCzteCrfT0,142
|
|
104
106
|
dbt_platform_helper/utils/template.py,sha256=g-Db-0I6a6diOHkgK1nYA0IxJSO4TRrjqOvlyeOR32o,950
|
|
105
107
|
dbt_platform_helper/utils/validation.py,sha256=W5jKC2zp5Q7cJ0PT57GB-s9FkJXrNt1jmWojXRFymcY,1187
|
|
106
|
-
platform_helper.py,sha256=
|
|
108
|
+
platform_helper.py,sha256=JKfXj2lptIc2CRHxo8u79kDKQH_IRV3jwPaL8T-1aAs,2052
|
|
107
109
|
terraform/elasticache-redis/plans.yml,sha256=efJfkLuLC_5TwhLb9DalKHOuZFO79y6iei6Dg_tqKjI,1831
|
|
108
110
|
terraform/opensearch/plans.yml,sha256=lQbUSNMGfvUeDMcGx8mSwzGQhMJU3EZ4J4tPzPKaq6c,1471
|
|
109
111
|
terraform/postgres/plans.yml,sha256=plwCklW1VB_tNJFyUduRMZx9UANgiWH_7TGLWUaUEus,2553
|
|
110
|
-
dbt_platform_helper-15.
|
|
111
|
-
dbt_platform_helper-15.
|
|
112
|
-
dbt_platform_helper-15.
|
|
113
|
-
dbt_platform_helper-15.
|
|
114
|
-
dbt_platform_helper-15.
|
|
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,,
|
platform_helper.py
CHANGED
|
@@ -16,7 +16,6 @@ from dbt_platform_helper.commands.internal import internal as internal_commands
|
|
|
16
16
|
from dbt_platform_helper.commands.notify import notify as notify_commands
|
|
17
17
|
from dbt_platform_helper.commands.pipeline import pipeline as pipeline_commands
|
|
18
18
|
from dbt_platform_helper.commands.secrets import secrets as secrets_commands
|
|
19
|
-
from dbt_platform_helper.commands.service import service as service_commands
|
|
20
19
|
from dbt_platform_helper.commands.version import version as version_commands
|
|
21
20
|
from dbt_platform_helper.utils.click import ClickDocOptGroup
|
|
22
21
|
|
|
@@ -40,7 +39,6 @@ platform_helper.add_command(generate_commands)
|
|
|
40
39
|
platform_helper.add_command(internal_commands)
|
|
41
40
|
platform_helper.add_command(pipeline_commands)
|
|
42
41
|
platform_helper.add_command(secrets_commands)
|
|
43
|
-
platform_helper.add_command(service_commands)
|
|
44
42
|
platform_helper.add_command(notify_commands)
|
|
45
43
|
platform_helper.add_command(database_commands)
|
|
46
44
|
platform_helper.add_command(version_commands)
|
|
@@ -1,53 +0,0 @@
|
|
|
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))
|
|
File without changes
|
{dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{dbt_platform_helper-15.10.0.dist-info → dbt_platform_helper-15.11.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|