paasta-tools 1.21.3__py3-none-any.whl → 1.22.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.
Files changed (77) hide show
  1. paasta_tools/__init__.py +1 -1
  2. paasta_tools/api/api.py +5 -0
  3. paasta_tools/api/api_docs/swagger.json +92 -0
  4. paasta_tools/api/views/autoscaler.py +122 -0
  5. paasta_tools/cli/authentication.py +6 -39
  6. paasta_tools/cli/cmds/autoscale.py +126 -7
  7. paasta_tools/cli/cmds/logs.py +7 -7
  8. paasta_tools/cli/schemas/service_schema.json +4 -1
  9. paasta_tools/generate_deployments_for_service.py +4 -0
  10. paasta_tools/kubernetes/application/controller_wrappers.py +16 -2
  11. paasta_tools/kubernetes_tools.py +77 -1
  12. paasta_tools/paastaapi/api/autoscaler_api.py +140 -1
  13. paasta_tools/paastaapi/model/autoscaling_override.py +180 -0
  14. paasta_tools/paastaapi/model/inline_response202.py +182 -0
  15. paasta_tools/paastaapi/models/__init__.py +2 -0
  16. paasta_tools/setup_istio_mesh.py +1 -1
  17. paasta_tools/setup_kubernetes_job.py +105 -1
  18. paasta_tools/smartstack_tools.py +2 -2
  19. paasta_tools/spark_tools.py +2 -2
  20. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/generate_deployments_for_service.py +4 -0
  21. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/setup_istio_mesh.py +1 -1
  22. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/setup_kubernetes_job.py +105 -1
  23. {paasta_tools-1.21.3.dist-info → paasta_tools-1.22.0.dist-info}/METADATA +2 -2
  24. {paasta_tools-1.21.3.dist-info → paasta_tools-1.22.0.dist-info}/RECORD +77 -75
  25. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/apply_external_resources.py +0 -0
  26. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/bounce_log_latency_parser.py +0 -0
  27. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/check_autoscaler_max_instances.py +0 -0
  28. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/check_cassandracluster_services_replication.py +0 -0
  29. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/check_flink_services_health.py +0 -0
  30. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/check_kubernetes_api.py +0 -0
  31. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/check_kubernetes_services_replication.py +0 -0
  32. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/check_manual_oapi_changes.sh +0 -0
  33. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/check_oom_events.py +0 -0
  34. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/check_orphans.py +0 -0
  35. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/check_spark_jobs.py +0 -0
  36. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/cleanup_kubernetes_cr.py +0 -0
  37. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/cleanup_kubernetes_crd.py +0 -0
  38. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/cleanup_kubernetes_jobs.py +0 -0
  39. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/create_dynamodb_table.py +0 -0
  40. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/create_paasta_playground.py +0 -0
  41. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/delete_kubernetes_deployments.py +0 -0
  42. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/emit_allocated_cpu_metrics.py +0 -0
  43. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/generate_all_deployments +0 -0
  44. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/generate_authenticating_services.py +0 -0
  45. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/generate_services_file.py +0 -0
  46. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/generate_services_yaml.py +0 -0
  47. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/get_running_task_allocation.py +0 -0
  48. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/habitat_fixer.py +0 -0
  49. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/ide_helper.py +0 -0
  50. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/is_pod_healthy_in_proxy.py +0 -0
  51. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/is_pod_healthy_in_smartstack.py +0 -0
  52. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/kill_bad_containers.py +0 -0
  53. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/kubernetes_remove_evicted_pods.py +0 -0
  54. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/mass-deploy-tag.sh +0 -0
  55. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/mock_patch_checker.py +0 -0
  56. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/paasta_cleanup_remote_run_resources.py +0 -0
  57. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/paasta_cleanup_stale_nodes.py +0 -0
  58. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/paasta_deploy_tron_jobs +0 -0
  59. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/paasta_execute_docker_command.py +0 -0
  60. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/paasta_secrets_sync.py +0 -0
  61. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/paasta_tabcomplete.sh +0 -0
  62. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/paasta_update_soa_memcpu.py +0 -0
  63. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/render_template.py +0 -0
  64. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/rightsizer_soaconfigs_update.py +0 -0
  65. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/service_shard_remove.py +0 -0
  66. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/service_shard_update.py +0 -0
  67. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/setup_kubernetes_cr.py +0 -0
  68. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/setup_kubernetes_crd.py +0 -0
  69. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/setup_kubernetes_internal_crd.py +0 -0
  70. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/setup_prometheus_adapter_config.py +0 -0
  71. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/shared_ip_check.py +0 -0
  72. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/synapse_srv_namespaces_fact.py +0 -0
  73. {paasta_tools-1.21.3.data → paasta_tools-1.22.0.data}/scripts/timeouts_metrics_prom.py +0 -0
  74. {paasta_tools-1.21.3.dist-info → paasta_tools-1.22.0.dist-info}/LICENSE +0 -0
  75. {paasta_tools-1.21.3.dist-info → paasta_tools-1.22.0.dist-info}/WHEEL +0 -0
  76. {paasta_tools-1.21.3.dist-info → paasta_tools-1.22.0.dist-info}/entry_points.txt +0 -0
  77. {paasta_tools-1.21.3.dist-info → paasta_tools-1.22.0.dist-info}/top_level.txt +0 -0
@@ -21,9 +21,12 @@ Command line options:
21
21
  - -v, --verbose: Verbose output
22
22
  """
23
23
  import argparse
24
+ import json
24
25
  import logging
25
26
  import sys
27
+ import time
26
28
  import traceback
29
+ from typing import Dict
27
30
  from typing import List
28
31
  from typing import Optional
29
32
  from typing import Sequence
@@ -36,7 +39,11 @@ from paasta_tools.kubernetes.application.controller_wrappers import Application
36
39
  from paasta_tools.kubernetes.application.controller_wrappers import (
37
40
  get_application_wrapper,
38
41
  )
42
+ from paasta_tools.kubernetes_tools import AUTOSCALING_OVERRIDES_CONFIGMAP_NAME
43
+ from paasta_tools.kubernetes_tools import AUTOSCALING_OVERRIDES_CONFIGMAP_NAMESPACE
39
44
  from paasta_tools.kubernetes_tools import ensure_namespace
45
+ from paasta_tools.kubernetes_tools import get_namespaced_configmap
46
+ from paasta_tools.kubernetes_tools import HpaOverride
40
47
  from paasta_tools.kubernetes_tools import InvalidKubernetesConfig
41
48
  from paasta_tools.kubernetes_tools import KubeClient
42
49
  from paasta_tools.kubernetes_tools import KubernetesDeploymentConfig
@@ -129,6 +136,8 @@ def main() -> None:
129
136
  kube_client = KubeClient()
130
137
  service_instances_valid = True
131
138
 
139
+ hpa_overrides = get_hpa_overrides(kube_client)
140
+
132
141
  # validate the service_instance names
133
142
  service_instances_with_valid_names = get_service_instances_with_valid_names(
134
143
  service_instances=args.service_instance_list
@@ -162,6 +171,7 @@ def main() -> None:
162
171
  soa_dir=soa_dir,
163
172
  metrics_interface=deploy_metrics,
164
173
  eks=args.eks,
174
+ hpa_overrides=hpa_overrides,
165
175
  )
166
176
  else:
167
177
  setup_kube_succeeded = False
@@ -239,6 +249,92 @@ def get_kubernetes_deployment_config(
239
249
  return service_instance_configs_list
240
250
 
241
251
 
252
+ def get_hpa_overrides(kube_client: KubeClient) -> Dict[str, Dict[str, HpaOverride]]:
253
+ """
254
+ Load autoscaling overrides from the ConfigMap once.
255
+
256
+ This function reads the "paasta-autoscaling-overrides" ConfigMap in the "paasta" namespace
257
+ and extracts all valid (non-expired) overrides to return a dictionary mapping
258
+ service.instance pairs to override data (currently, just min_instances and when the
259
+ override should expire by).
260
+
261
+ The incoming ConfigMap is expected to have the following format:
262
+ {
263
+ $SERVICE_A.$INSTANCE_A: {
264
+ "min_instances": 2,
265
+ "expire_after": "2023-10-01T00:00:00Z"
266
+ },
267
+ $SERVICE_A.$INSTANCE_B: {
268
+ "min_instances": 3,
269
+ "expire_after": "2023-10-01T00:00:00Z"
270
+ },
271
+ ...
272
+ },
273
+ $SERVICE_B.$INSTANCE_A: {
274
+ "min_instances": 1,
275
+ "expire_after": "2023-10-01T00:00:00Z"
276
+ },
277
+ $SERVICE_B.$INSTANCE_B: {
278
+ "min_instances": 2,
279
+ "expire_after": "2023-10-01T00:00:00Z"
280
+ },
281
+ ...
282
+ }
283
+ """
284
+ overrides: Dict[str, Dict[str, HpaOverride]] = {}
285
+ try:
286
+ configmap = get_namespaced_configmap(
287
+ name=AUTOSCALING_OVERRIDES_CONFIGMAP_NAME,
288
+ namespace=AUTOSCALING_OVERRIDES_CONFIGMAP_NAMESPACE,
289
+ kube_client=kube_client,
290
+ )
291
+
292
+ if configmap.data:
293
+ current_time = time.time()
294
+
295
+ for service_instance, override_json in configmap.data.items():
296
+ try:
297
+ service, instance = service_instance.split(".")
298
+ override_metadata = json.loads(override_json)
299
+ expire_after = override_metadata.get("expire_after")
300
+ min_instances = override_metadata.get("min_instances")
301
+
302
+ if expire_after and min_instances:
303
+ if current_time < expire_after:
304
+ if service not in overrides:
305
+ overrides[service] = {}
306
+
307
+ overrides[service][instance] = {
308
+ "min_instances": min_instances,
309
+ "expire_after": expire_after,
310
+ }
311
+ log.info(
312
+ f"Found valid HPA override for {service}: "
313
+ f"{override_metadata.get('min_instances')} (expires at {expire_after})"
314
+ )
315
+ else:
316
+ log.info(
317
+ f"Ignoring expired HPA override for {service}.{instance}"
318
+ f"(expired at {expire_after})"
319
+ )
320
+ else:
321
+ log.warning(
322
+ f"Invalid HPA override for {service}.{instance}: "
323
+ f"missing 'min_instances' or 'expire_after': {override_metadata}"
324
+ )
325
+ except Exception:
326
+ log.exception(
327
+ f"Error parsing override for {service} - proceeding without overrides for this service."
328
+ )
329
+ except Exception:
330
+ # If ConfigMap doesn't exist or there's an error, just return empty dict
331
+ log.exception(
332
+ f"Unable to load the {AUTOSCALING_OVERRIDES_CONFIGMAP_NAME} ConfigMap - proceeding without overrides"
333
+ )
334
+
335
+ return overrides
336
+
337
+
242
338
  def setup_kube_deployments(
243
339
  kube_client: KubeClient,
244
340
  cluster: str,
@@ -249,6 +345,7 @@ def setup_kube_deployments(
249
345
  soa_dir: str = DEFAULT_SOA_DIR,
250
346
  metrics_interface: metrics_lib.BaseMetrics = metrics_lib.NoMetrics("paasta"),
251
347
  eks: bool = False,
348
+ hpa_overrides: Optional[Dict[str, Dict[str, HpaOverride]]] = None,
252
349
  ) -> bool:
253
350
 
254
351
  if not service_instance_configs_list:
@@ -260,12 +357,17 @@ def setup_kube_deployments(
260
357
  for deployment in existing_kube_deployments
261
358
  }
262
359
 
360
+ hpa_overrides = hpa_overrides or {}
361
+
263
362
  applications = [
264
363
  create_application_object(
265
364
  cluster=cluster,
266
365
  soa_dir=soa_dir,
267
366
  service_instance_config=service_instance,
268
367
  eks=eks,
368
+ hpa_override=hpa_overrides.get(service_instance.service, {}).get(
369
+ service_instance.instance, None
370
+ ),
269
371
  )
270
372
  if service_instance
271
373
  else (_, None)
@@ -337,6 +439,7 @@ def create_application_object(
337
439
  soa_dir: str,
338
440
  service_instance_config: Union[KubernetesDeploymentConfig, EksDeploymentConfig],
339
441
  eks: bool = False,
442
+ hpa_override: Optional[HpaOverride] = None,
340
443
  ) -> Tuple[bool, Optional[Application]]:
341
444
  try:
342
445
  formatted_application = service_instance_config.format_kubernetes_app()
@@ -344,8 +447,9 @@ def create_application_object(
344
447
  log.error(traceback.format_exc())
345
448
  return False, None
346
449
 
347
- app = get_application_wrapper(formatted_application)
450
+ app = get_application_wrapper(formatted_application, hpa_override)
348
451
  app.load_local_config(soa_dir, cluster, eks)
452
+
349
453
  return True, app
350
454
 
351
455
 
@@ -473,7 +473,7 @@ def get_service_discovery_providers(
473
473
  elif name == "envoy":
474
474
  providers.append(EnvoyServiceDiscovery(system_paasta_config))
475
475
  else:
476
- log.warn("unknown provider")
476
+ log.warning("unknown provider")
477
477
  return providers
478
478
 
479
479
 
@@ -530,7 +530,7 @@ class BaseReplicationChecker(ReplicationChecker):
530
530
  )
531
531
  break
532
532
  except Exception as e:
533
- log.warn(
533
+ log.warning(
534
534
  f"Error while getting replication info for {location} from {hostname}: {e}"
535
535
  )
536
536
  if hostname == hostnames[-1]:
@@ -133,7 +133,7 @@ def setup_volume_mounts(volumes: List[DockerVolume]) -> Dict[str, str]:
133
133
  )
134
134
 
135
135
  if host_path in seen_paths:
136
- log.warn(f"Skipping {host_path} - already added a binding for it.")
136
+ log.warning(f"Skipping {host_path} - already added a binding for it.")
137
137
  continue
138
138
  seen_paths.add(host_path)
139
139
 
@@ -209,7 +209,7 @@ def auto_add_timeout_for_spark_job(
209
209
  f"'timeout' could not be added to spark command: '{cmd}' due to error '{e}'. "
210
210
  "Please report to #spark."
211
211
  )
212
- log.warn(err_msg)
212
+ log.warning(err_msg)
213
213
  print(PaastaColors.red(err_msg))
214
214
  return cmd
215
215
 
@@ -130,6 +130,10 @@ def get_deploy_group_mappings(
130
130
  v2_mappings: V2_Mappings = {"deployments": {}, "controls": {}}
131
131
  git_url = get_git_url(service=service, soa_dir=soa_dir)
132
132
 
133
+ # Some pseudo-services like toolboxes explicitly have no git_url, and therefore no deployments
134
+ if git_url is None:
135
+ return mappings, v2_mappings
136
+
133
137
  # Most of the time of this function is in two parts:
134
138
  # 1. getting remote refs from git. (Mostly IO, just waiting for git to get back to us.)
135
139
  # 2. loading instance configs. (Mostly CPU, copy.deepcopying yaml over and over again)
@@ -103,7 +103,7 @@ def load_smartstack_namespaces(soa_dir: str = DEFAULT_SOA_DIR) -> Mapping:
103
103
  for (ns, details) in svc_namespaces.items():
104
104
  namespaces[f"{dir}.{ns}"] = details
105
105
  except Exception as err:
106
- log.warn(f"Failed to load namespaces for {dir}: {err}")
106
+ log.warning(f"Failed to load namespaces for {dir}: {err}")
107
107
 
108
108
  return namespaces
109
109
 
@@ -21,9 +21,12 @@ Command line options:
21
21
  - -v, --verbose: Verbose output
22
22
  """
23
23
  import argparse
24
+ import json
24
25
  import logging
25
26
  import sys
27
+ import time
26
28
  import traceback
29
+ from typing import Dict
27
30
  from typing import List
28
31
  from typing import Optional
29
32
  from typing import Sequence
@@ -36,7 +39,11 @@ from paasta_tools.kubernetes.application.controller_wrappers import Application
36
39
  from paasta_tools.kubernetes.application.controller_wrappers import (
37
40
  get_application_wrapper,
38
41
  )
42
+ from paasta_tools.kubernetes_tools import AUTOSCALING_OVERRIDES_CONFIGMAP_NAME
43
+ from paasta_tools.kubernetes_tools import AUTOSCALING_OVERRIDES_CONFIGMAP_NAMESPACE
39
44
  from paasta_tools.kubernetes_tools import ensure_namespace
45
+ from paasta_tools.kubernetes_tools import get_namespaced_configmap
46
+ from paasta_tools.kubernetes_tools import HpaOverride
40
47
  from paasta_tools.kubernetes_tools import InvalidKubernetesConfig
41
48
  from paasta_tools.kubernetes_tools import KubeClient
42
49
  from paasta_tools.kubernetes_tools import KubernetesDeploymentConfig
@@ -129,6 +136,8 @@ def main() -> None:
129
136
  kube_client = KubeClient()
130
137
  service_instances_valid = True
131
138
 
139
+ hpa_overrides = get_hpa_overrides(kube_client)
140
+
132
141
  # validate the service_instance names
133
142
  service_instances_with_valid_names = get_service_instances_with_valid_names(
134
143
  service_instances=args.service_instance_list
@@ -162,6 +171,7 @@ def main() -> None:
162
171
  soa_dir=soa_dir,
163
172
  metrics_interface=deploy_metrics,
164
173
  eks=args.eks,
174
+ hpa_overrides=hpa_overrides,
165
175
  )
166
176
  else:
167
177
  setup_kube_succeeded = False
@@ -239,6 +249,92 @@ def get_kubernetes_deployment_config(
239
249
  return service_instance_configs_list
240
250
 
241
251
 
252
+ def get_hpa_overrides(kube_client: KubeClient) -> Dict[str, Dict[str, HpaOverride]]:
253
+ """
254
+ Load autoscaling overrides from the ConfigMap once.
255
+
256
+ This function reads the "paasta-autoscaling-overrides" ConfigMap in the "paasta" namespace
257
+ and extracts all valid (non-expired) overrides to return a dictionary mapping
258
+ service.instance pairs to override data (currently, just min_instances and when the
259
+ override should expire by).
260
+
261
+ The incoming ConfigMap is expected to have the following format:
262
+ {
263
+ $SERVICE_A.$INSTANCE_A: {
264
+ "min_instances": 2,
265
+ "expire_after": "2023-10-01T00:00:00Z"
266
+ },
267
+ $SERVICE_A.$INSTANCE_B: {
268
+ "min_instances": 3,
269
+ "expire_after": "2023-10-01T00:00:00Z"
270
+ },
271
+ ...
272
+ },
273
+ $SERVICE_B.$INSTANCE_A: {
274
+ "min_instances": 1,
275
+ "expire_after": "2023-10-01T00:00:00Z"
276
+ },
277
+ $SERVICE_B.$INSTANCE_B: {
278
+ "min_instances": 2,
279
+ "expire_after": "2023-10-01T00:00:00Z"
280
+ },
281
+ ...
282
+ }
283
+ """
284
+ overrides: Dict[str, Dict[str, HpaOverride]] = {}
285
+ try:
286
+ configmap = get_namespaced_configmap(
287
+ name=AUTOSCALING_OVERRIDES_CONFIGMAP_NAME,
288
+ namespace=AUTOSCALING_OVERRIDES_CONFIGMAP_NAMESPACE,
289
+ kube_client=kube_client,
290
+ )
291
+
292
+ if configmap.data:
293
+ current_time = time.time()
294
+
295
+ for service_instance, override_json in configmap.data.items():
296
+ try:
297
+ service, instance = service_instance.split(".")
298
+ override_metadata = json.loads(override_json)
299
+ expire_after = override_metadata.get("expire_after")
300
+ min_instances = override_metadata.get("min_instances")
301
+
302
+ if expire_after and min_instances:
303
+ if current_time < expire_after:
304
+ if service not in overrides:
305
+ overrides[service] = {}
306
+
307
+ overrides[service][instance] = {
308
+ "min_instances": min_instances,
309
+ "expire_after": expire_after,
310
+ }
311
+ log.info(
312
+ f"Found valid HPA override for {service}: "
313
+ f"{override_metadata.get('min_instances')} (expires at {expire_after})"
314
+ )
315
+ else:
316
+ log.info(
317
+ f"Ignoring expired HPA override for {service}.{instance}"
318
+ f"(expired at {expire_after})"
319
+ )
320
+ else:
321
+ log.warning(
322
+ f"Invalid HPA override for {service}.{instance}: "
323
+ f"missing 'min_instances' or 'expire_after': {override_metadata}"
324
+ )
325
+ except Exception:
326
+ log.exception(
327
+ f"Error parsing override for {service} - proceeding without overrides for this service."
328
+ )
329
+ except Exception:
330
+ # If ConfigMap doesn't exist or there's an error, just return empty dict
331
+ log.exception(
332
+ f"Unable to load the {AUTOSCALING_OVERRIDES_CONFIGMAP_NAME} ConfigMap - proceeding without overrides"
333
+ )
334
+
335
+ return overrides
336
+
337
+
242
338
  def setup_kube_deployments(
243
339
  kube_client: KubeClient,
244
340
  cluster: str,
@@ -249,6 +345,7 @@ def setup_kube_deployments(
249
345
  soa_dir: str = DEFAULT_SOA_DIR,
250
346
  metrics_interface: metrics_lib.BaseMetrics = metrics_lib.NoMetrics("paasta"),
251
347
  eks: bool = False,
348
+ hpa_overrides: Optional[Dict[str, Dict[str, HpaOverride]]] = None,
252
349
  ) -> bool:
253
350
 
254
351
  if not service_instance_configs_list:
@@ -260,12 +357,17 @@ def setup_kube_deployments(
260
357
  for deployment in existing_kube_deployments
261
358
  }
262
359
 
360
+ hpa_overrides = hpa_overrides or {}
361
+
263
362
  applications = [
264
363
  create_application_object(
265
364
  cluster=cluster,
266
365
  soa_dir=soa_dir,
267
366
  service_instance_config=service_instance,
268
367
  eks=eks,
368
+ hpa_override=hpa_overrides.get(service_instance.service, {}).get(
369
+ service_instance.instance, None
370
+ ),
269
371
  )
270
372
  if service_instance
271
373
  else (_, None)
@@ -337,6 +439,7 @@ def create_application_object(
337
439
  soa_dir: str,
338
440
  service_instance_config: Union[KubernetesDeploymentConfig, EksDeploymentConfig],
339
441
  eks: bool = False,
442
+ hpa_override: Optional[HpaOverride] = None,
340
443
  ) -> Tuple[bool, Optional[Application]]:
341
444
  try:
342
445
  formatted_application = service_instance_config.format_kubernetes_app()
@@ -344,8 +447,9 @@ def create_application_object(
344
447
  log.error(traceback.format_exc())
345
448
  return False, None
346
449
 
347
- app = get_application_wrapper(formatted_application)
450
+ app = get_application_wrapper(formatted_application, hpa_override)
348
451
  app.load_local_config(soa_dir, cluster, eks)
452
+
349
453
  return True, app
350
454
 
351
455
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: paasta-tools
3
- Version: 1.21.3
3
+ Version: 1.22.0
4
4
  Summary: Tools for Yelps SOA infrastructure
5
5
  Author: Compute Infrastructure @ Yelp
6
6
  Author-email: compute-infra@yelp.com
@@ -58,7 +58,7 @@ Requires-Dist: requests-cache >=0.4.10
58
58
  Requires-Dist: retry
59
59
  Requires-Dist: ruamel.yaml
60
60
  Requires-Dist: sensu-plugin
61
- Requires-Dist: service-configuration-lib >=3.2.0
61
+ Requires-Dist: service-configuration-lib >=3.3.2
62
62
  Requires-Dist: signalfx
63
63
  Requires-Dist: slackclient >=1.2.1
64
64
  Requires-Dist: sticht >=1.1.0