paasta-tools 1.21.3__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.
- k8s_itests/__init__.py +0 -0
- k8s_itests/test_autoscaling.py +23 -0
- k8s_itests/utils.py +38 -0
- paasta_tools/__init__.py +20 -0
- paasta_tools/adhoc_tools.py +142 -0
- paasta_tools/api/__init__.py +13 -0
- paasta_tools/api/api.py +330 -0
- paasta_tools/api/api_docs/swagger.json +2323 -0
- paasta_tools/api/client.py +106 -0
- paasta_tools/api/settings.py +33 -0
- paasta_tools/api/tweens/__init__.py +6 -0
- paasta_tools/api/tweens/auth.py +125 -0
- paasta_tools/api/tweens/profiling.py +108 -0
- paasta_tools/api/tweens/request_logger.py +124 -0
- paasta_tools/api/views/__init__.py +13 -0
- paasta_tools/api/views/autoscaler.py +100 -0
- paasta_tools/api/views/exception.py +45 -0
- paasta_tools/api/views/flink.py +73 -0
- paasta_tools/api/views/instance.py +395 -0
- paasta_tools/api/views/pause_autoscaler.py +71 -0
- paasta_tools/api/views/remote_run.py +113 -0
- paasta_tools/api/views/resources.py +76 -0
- paasta_tools/api/views/service.py +35 -0
- paasta_tools/api/views/version.py +25 -0
- paasta_tools/apply_external_resources.py +79 -0
- paasta_tools/async_utils.py +109 -0
- paasta_tools/autoscaling/__init__.py +0 -0
- paasta_tools/autoscaling/autoscaling_service_lib.py +57 -0
- paasta_tools/autoscaling/forecasting.py +106 -0
- paasta_tools/autoscaling/max_all_k8s_services.py +41 -0
- paasta_tools/autoscaling/pause_service_autoscaler.py +77 -0
- paasta_tools/autoscaling/utils.py +52 -0
- paasta_tools/bounce_lib.py +184 -0
- paasta_tools/broadcast_log_to_services.py +62 -0
- paasta_tools/cassandracluster_tools.py +210 -0
- paasta_tools/check_autoscaler_max_instances.py +212 -0
- paasta_tools/check_cassandracluster_services_replication.py +35 -0
- paasta_tools/check_flink_services_health.py +203 -0
- paasta_tools/check_kubernetes_api.py +57 -0
- paasta_tools/check_kubernetes_services_replication.py +141 -0
- paasta_tools/check_oom_events.py +244 -0
- paasta_tools/check_services_replication_tools.py +324 -0
- paasta_tools/check_spark_jobs.py +234 -0
- paasta_tools/cleanup_kubernetes_cr.py +138 -0
- paasta_tools/cleanup_kubernetes_crd.py +145 -0
- paasta_tools/cleanup_kubernetes_jobs.py +344 -0
- paasta_tools/cleanup_tron_namespaces.py +96 -0
- paasta_tools/cli/__init__.py +13 -0
- paasta_tools/cli/authentication.py +85 -0
- paasta_tools/cli/cli.py +260 -0
- paasta_tools/cli/cmds/__init__.py +13 -0
- paasta_tools/cli/cmds/autoscale.py +143 -0
- paasta_tools/cli/cmds/check.py +334 -0
- paasta_tools/cli/cmds/cook_image.py +147 -0
- paasta_tools/cli/cmds/get_docker_image.py +76 -0
- paasta_tools/cli/cmds/get_image_version.py +172 -0
- paasta_tools/cli/cmds/get_latest_deployment.py +93 -0
- paasta_tools/cli/cmds/info.py +155 -0
- paasta_tools/cli/cmds/itest.py +117 -0
- paasta_tools/cli/cmds/list.py +66 -0
- paasta_tools/cli/cmds/list_clusters.py +42 -0
- paasta_tools/cli/cmds/list_deploy_queue.py +171 -0
- paasta_tools/cli/cmds/list_namespaces.py +84 -0
- paasta_tools/cli/cmds/local_run.py +1396 -0
- paasta_tools/cli/cmds/logs.py +1601 -0
- paasta_tools/cli/cmds/mark_for_deployment.py +1988 -0
- paasta_tools/cli/cmds/mesh_status.py +174 -0
- paasta_tools/cli/cmds/pause_service_autoscaler.py +107 -0
- paasta_tools/cli/cmds/push_to_registry.py +275 -0
- paasta_tools/cli/cmds/remote_run.py +252 -0
- paasta_tools/cli/cmds/rollback.py +347 -0
- paasta_tools/cli/cmds/secret.py +549 -0
- paasta_tools/cli/cmds/security_check.py +59 -0
- paasta_tools/cli/cmds/spark_run.py +1400 -0
- paasta_tools/cli/cmds/start_stop_restart.py +401 -0
- paasta_tools/cli/cmds/status.py +2302 -0
- paasta_tools/cli/cmds/validate.py +1012 -0
- paasta_tools/cli/cmds/wait_for_deployment.py +275 -0
- paasta_tools/cli/fsm/__init__.py +13 -0
- paasta_tools/cli/fsm/autosuggest.py +82 -0
- paasta_tools/cli/fsm/template/README.md +8 -0
- paasta_tools/cli/fsm/template/cookiecutter.json +7 -0
- paasta_tools/cli/fsm/template/{{cookiecutter.service}}/kubernetes-PROD.yaml +91 -0
- paasta_tools/cli/fsm/template/{{cookiecutter.service}}/monitoring.yaml +20 -0
- paasta_tools/cli/fsm/template/{{cookiecutter.service}}/service.yaml +8 -0
- paasta_tools/cli/fsm/template/{{cookiecutter.service}}/smartstack.yaml +6 -0
- paasta_tools/cli/fsm_cmd.py +121 -0
- paasta_tools/cli/paasta_tabcomplete.sh +23 -0
- paasta_tools/cli/schemas/adhoc_schema.json +199 -0
- paasta_tools/cli/schemas/autoscaling_schema.json +91 -0
- paasta_tools/cli/schemas/autotuned_defaults/cassandracluster_schema.json +37 -0
- paasta_tools/cli/schemas/autotuned_defaults/kubernetes_schema.json +89 -0
- paasta_tools/cli/schemas/deploy_schema.json +173 -0
- paasta_tools/cli/schemas/eks_schema.json +970 -0
- paasta_tools/cli/schemas/kubernetes_schema.json +970 -0
- paasta_tools/cli/schemas/rollback_schema.json +160 -0
- paasta_tools/cli/schemas/service_schema.json +25 -0
- paasta_tools/cli/schemas/smartstack_schema.json +322 -0
- paasta_tools/cli/schemas/tron_schema.json +699 -0
- paasta_tools/cli/utils.py +1118 -0
- paasta_tools/clusterman.py +21 -0
- paasta_tools/config_utils.py +385 -0
- paasta_tools/contrib/__init__.py +0 -0
- paasta_tools/contrib/bounce_log_latency_parser.py +68 -0
- paasta_tools/contrib/check_manual_oapi_changes.sh +24 -0
- paasta_tools/contrib/check_orphans.py +306 -0
- paasta_tools/contrib/create_dynamodb_table.py +35 -0
- paasta_tools/contrib/create_paasta_playground.py +105 -0
- paasta_tools/contrib/emit_allocated_cpu_metrics.py +50 -0
- paasta_tools/contrib/get_running_task_allocation.py +346 -0
- paasta_tools/contrib/habitat_fixer.py +86 -0
- paasta_tools/contrib/ide_helper.py +316 -0
- paasta_tools/contrib/is_pod_healthy_in_proxy.py +139 -0
- paasta_tools/contrib/is_pod_healthy_in_smartstack.py +50 -0
- paasta_tools/contrib/kill_bad_containers.py +109 -0
- paasta_tools/contrib/mass-deploy-tag.sh +44 -0
- paasta_tools/contrib/mock_patch_checker.py +86 -0
- paasta_tools/contrib/paasta_update_soa_memcpu.py +520 -0
- paasta_tools/contrib/render_template.py +129 -0
- paasta_tools/contrib/rightsizer_soaconfigs_update.py +348 -0
- paasta_tools/contrib/service_shard_remove.py +157 -0
- paasta_tools/contrib/service_shard_update.py +373 -0
- paasta_tools/contrib/shared_ip_check.py +77 -0
- paasta_tools/contrib/timeouts_metrics_prom.py +64 -0
- paasta_tools/delete_kubernetes_deployments.py +89 -0
- paasta_tools/deployment_utils.py +44 -0
- paasta_tools/docker_wrapper.py +234 -0
- paasta_tools/docker_wrapper_imports.py +13 -0
- paasta_tools/drain_lib.py +351 -0
- paasta_tools/dump_locally_running_services.py +71 -0
- paasta_tools/eks_tools.py +119 -0
- paasta_tools/envoy_tools.py +373 -0
- paasta_tools/firewall.py +504 -0
- paasta_tools/firewall_logging.py +154 -0
- paasta_tools/firewall_update.py +172 -0
- paasta_tools/flink_tools.py +345 -0
- paasta_tools/flinkeks_tools.py +90 -0
- paasta_tools/frameworks/__init__.py +0 -0
- paasta_tools/frameworks/adhoc_scheduler.py +71 -0
- paasta_tools/frameworks/constraints.py +87 -0
- paasta_tools/frameworks/native_scheduler.py +652 -0
- paasta_tools/frameworks/native_service_config.py +301 -0
- paasta_tools/frameworks/task_store.py +245 -0
- paasta_tools/generate_all_deployments +9 -0
- paasta_tools/generate_authenticating_services.py +94 -0
- paasta_tools/generate_deployments_for_service.py +255 -0
- paasta_tools/generate_services_file.py +114 -0
- paasta_tools/generate_services_yaml.py +30 -0
- paasta_tools/hacheck.py +76 -0
- paasta_tools/instance/__init__.py +0 -0
- paasta_tools/instance/hpa_metrics_parser.py +122 -0
- paasta_tools/instance/kubernetes.py +1362 -0
- paasta_tools/iptables.py +240 -0
- paasta_tools/kafkacluster_tools.py +143 -0
- paasta_tools/kubernetes/__init__.py +0 -0
- paasta_tools/kubernetes/application/__init__.py +0 -0
- paasta_tools/kubernetes/application/controller_wrappers.py +476 -0
- paasta_tools/kubernetes/application/tools.py +90 -0
- paasta_tools/kubernetes/bin/__init__.py +0 -0
- paasta_tools/kubernetes/bin/kubernetes_remove_evicted_pods.py +164 -0
- paasta_tools/kubernetes/bin/paasta_cleanup_remote_run_resources.py +135 -0
- paasta_tools/kubernetes/bin/paasta_cleanup_stale_nodes.py +181 -0
- paasta_tools/kubernetes/bin/paasta_secrets_sync.py +758 -0
- paasta_tools/kubernetes/remote_run.py +558 -0
- paasta_tools/kubernetes_tools.py +4679 -0
- paasta_tools/list_kubernetes_service_instances.py +128 -0
- paasta_tools/list_tron_namespaces.py +60 -0
- paasta_tools/long_running_service_tools.py +678 -0
- paasta_tools/mac_address.py +44 -0
- paasta_tools/marathon_dashboard.py +0 -0
- paasta_tools/mesos/__init__.py +0 -0
- paasta_tools/mesos/cfg.py +46 -0
- paasta_tools/mesos/cluster.py +60 -0
- paasta_tools/mesos/exceptions.py +59 -0
- paasta_tools/mesos/framework.py +77 -0
- paasta_tools/mesos/log.py +48 -0
- paasta_tools/mesos/master.py +306 -0
- paasta_tools/mesos/mesos_file.py +169 -0
- paasta_tools/mesos/parallel.py +52 -0
- paasta_tools/mesos/slave.py +115 -0
- paasta_tools/mesos/task.py +94 -0
- paasta_tools/mesos/util.py +69 -0
- paasta_tools/mesos/zookeeper.py +37 -0
- paasta_tools/mesos_maintenance.py +848 -0
- paasta_tools/mesos_tools.py +1051 -0
- paasta_tools/metrics/__init__.py +0 -0
- paasta_tools/metrics/metastatus_lib.py +1110 -0
- paasta_tools/metrics/metrics_lib.py +217 -0
- paasta_tools/monitoring/__init__.py +13 -0
- paasta_tools/monitoring/check_k8s_api_performance.py +110 -0
- paasta_tools/monitoring_tools.py +652 -0
- paasta_tools/monkrelaycluster_tools.py +146 -0
- paasta_tools/nrtsearchservice_tools.py +143 -0
- paasta_tools/nrtsearchserviceeks_tools.py +68 -0
- paasta_tools/oom_logger.py +321 -0
- paasta_tools/paasta_deploy_tron_jobs +3 -0
- paasta_tools/paasta_execute_docker_command.py +123 -0
- paasta_tools/paasta_native_serviceinit.py +21 -0
- paasta_tools/paasta_service_config_loader.py +201 -0
- paasta_tools/paastaapi/__init__.py +29 -0
- paasta_tools/paastaapi/api/__init__.py +3 -0
- paasta_tools/paastaapi/api/autoscaler_api.py +302 -0
- paasta_tools/paastaapi/api/default_api.py +569 -0
- paasta_tools/paastaapi/api/remote_run_api.py +604 -0
- paasta_tools/paastaapi/api/resources_api.py +157 -0
- paasta_tools/paastaapi/api/service_api.py +1736 -0
- paasta_tools/paastaapi/api_client.py +818 -0
- paasta_tools/paastaapi/apis/__init__.py +22 -0
- paasta_tools/paastaapi/configuration.py +455 -0
- paasta_tools/paastaapi/exceptions.py +137 -0
- paasta_tools/paastaapi/model/__init__.py +5 -0
- paasta_tools/paastaapi/model/adhoc_launch_history.py +176 -0
- paasta_tools/paastaapi/model/autoscaler_count_msg.py +176 -0
- paasta_tools/paastaapi/model/deploy_queue.py +178 -0
- paasta_tools/paastaapi/model/deploy_queue_service_instance.py +194 -0
- paasta_tools/paastaapi/model/envoy_backend.py +185 -0
- paasta_tools/paastaapi/model/envoy_location.py +184 -0
- paasta_tools/paastaapi/model/envoy_status.py +181 -0
- paasta_tools/paastaapi/model/flink_cluster_overview.py +188 -0
- paasta_tools/paastaapi/model/flink_config.py +173 -0
- paasta_tools/paastaapi/model/flink_job.py +186 -0
- paasta_tools/paastaapi/model/flink_job_details.py +192 -0
- paasta_tools/paastaapi/model/flink_jobs.py +175 -0
- paasta_tools/paastaapi/model/float_and_error.py +173 -0
- paasta_tools/paastaapi/model/hpa_metric.py +176 -0
- paasta_tools/paastaapi/model/inline_object.py +170 -0
- paasta_tools/paastaapi/model/inline_response200.py +170 -0
- paasta_tools/paastaapi/model/inline_response2001.py +170 -0
- paasta_tools/paastaapi/model/instance_bounce_status.py +200 -0
- paasta_tools/paastaapi/model/instance_mesh_status.py +186 -0
- paasta_tools/paastaapi/model/instance_status.py +220 -0
- paasta_tools/paastaapi/model/instance_status_adhoc.py +187 -0
- paasta_tools/paastaapi/model/instance_status_cassandracluster.py +173 -0
- paasta_tools/paastaapi/model/instance_status_flink.py +173 -0
- paasta_tools/paastaapi/model/instance_status_kafkacluster.py +173 -0
- paasta_tools/paastaapi/model/instance_status_kubernetes.py +263 -0
- paasta_tools/paastaapi/model/instance_status_kubernetes_autoscaling_status.py +187 -0
- paasta_tools/paastaapi/model/instance_status_kubernetes_v2.py +197 -0
- paasta_tools/paastaapi/model/instance_status_tron.py +204 -0
- paasta_tools/paastaapi/model/instance_tasks.py +182 -0
- paasta_tools/paastaapi/model/integer_and_error.py +173 -0
- paasta_tools/paastaapi/model/kubernetes_container.py +178 -0
- paasta_tools/paastaapi/model/kubernetes_container_v2.py +219 -0
- paasta_tools/paastaapi/model/kubernetes_healthcheck.py +176 -0
- paasta_tools/paastaapi/model/kubernetes_pod.py +201 -0
- paasta_tools/paastaapi/model/kubernetes_pod_event.py +176 -0
- paasta_tools/paastaapi/model/kubernetes_pod_v2.py +213 -0
- paasta_tools/paastaapi/model/kubernetes_replica_set.py +185 -0
- paasta_tools/paastaapi/model/kubernetes_version.py +202 -0
- paasta_tools/paastaapi/model/remote_run_outcome.py +189 -0
- paasta_tools/paastaapi/model/remote_run_start.py +185 -0
- paasta_tools/paastaapi/model/remote_run_stop.py +176 -0
- paasta_tools/paastaapi/model/remote_run_token.py +173 -0
- paasta_tools/paastaapi/model/resource.py +187 -0
- paasta_tools/paastaapi/model/resource_item.py +187 -0
- paasta_tools/paastaapi/model/resource_value.py +176 -0
- paasta_tools/paastaapi/model/smartstack_backend.py +191 -0
- paasta_tools/paastaapi/model/smartstack_location.py +181 -0
- paasta_tools/paastaapi/model/smartstack_status.py +181 -0
- paasta_tools/paastaapi/model/task_tail_lines.py +176 -0
- paasta_tools/paastaapi/model_utils.py +1879 -0
- paasta_tools/paastaapi/models/__init__.py +62 -0
- paasta_tools/paastaapi/rest.py +287 -0
- paasta_tools/prune_completed_pods.py +220 -0
- paasta_tools/puppet_service_tools.py +59 -0
- paasta_tools/py.typed +1 -0
- paasta_tools/remote_git.py +127 -0
- paasta_tools/run-paasta-api-in-dev-mode.py +57 -0
- paasta_tools/run-paasta-api-playground.py +51 -0
- paasta_tools/secret_providers/__init__.py +66 -0
- paasta_tools/secret_providers/vault.py +214 -0
- paasta_tools/secret_tools.py +277 -0
- paasta_tools/setup_istio_mesh.py +353 -0
- paasta_tools/setup_kubernetes_cr.py +412 -0
- paasta_tools/setup_kubernetes_crd.py +138 -0
- paasta_tools/setup_kubernetes_internal_crd.py +154 -0
- paasta_tools/setup_kubernetes_job.py +353 -0
- paasta_tools/setup_prometheus_adapter_config.py +1028 -0
- paasta_tools/setup_tron_namespace.py +248 -0
- paasta_tools/slack.py +75 -0
- paasta_tools/smartstack_tools.py +676 -0
- paasta_tools/spark_tools.py +283 -0
- paasta_tools/synapse_srv_namespaces_fact.py +42 -0
- paasta_tools/tron/__init__.py +0 -0
- paasta_tools/tron/client.py +158 -0
- paasta_tools/tron/tron_command_context.py +194 -0
- paasta_tools/tron/tron_timeutils.py +101 -0
- paasta_tools/tron_tools.py +1448 -0
- paasta_tools/utils.py +4307 -0
- paasta_tools/yaml_tools.py +44 -0
- paasta_tools-1.21.3.data/scripts/apply_external_resources.py +79 -0
- paasta_tools-1.21.3.data/scripts/bounce_log_latency_parser.py +68 -0
- paasta_tools-1.21.3.data/scripts/check_autoscaler_max_instances.py +212 -0
- paasta_tools-1.21.3.data/scripts/check_cassandracluster_services_replication.py +35 -0
- paasta_tools-1.21.3.data/scripts/check_flink_services_health.py +203 -0
- paasta_tools-1.21.3.data/scripts/check_kubernetes_api.py +57 -0
- paasta_tools-1.21.3.data/scripts/check_kubernetes_services_replication.py +141 -0
- paasta_tools-1.21.3.data/scripts/check_manual_oapi_changes.sh +24 -0
- paasta_tools-1.21.3.data/scripts/check_oom_events.py +244 -0
- paasta_tools-1.21.3.data/scripts/check_orphans.py +306 -0
- paasta_tools-1.21.3.data/scripts/check_spark_jobs.py +234 -0
- paasta_tools-1.21.3.data/scripts/cleanup_kubernetes_cr.py +138 -0
- paasta_tools-1.21.3.data/scripts/cleanup_kubernetes_crd.py +145 -0
- paasta_tools-1.21.3.data/scripts/cleanup_kubernetes_jobs.py +344 -0
- paasta_tools-1.21.3.data/scripts/create_dynamodb_table.py +35 -0
- paasta_tools-1.21.3.data/scripts/create_paasta_playground.py +105 -0
- paasta_tools-1.21.3.data/scripts/delete_kubernetes_deployments.py +89 -0
- paasta_tools-1.21.3.data/scripts/emit_allocated_cpu_metrics.py +50 -0
- paasta_tools-1.21.3.data/scripts/generate_all_deployments +9 -0
- paasta_tools-1.21.3.data/scripts/generate_authenticating_services.py +94 -0
- paasta_tools-1.21.3.data/scripts/generate_deployments_for_service.py +255 -0
- paasta_tools-1.21.3.data/scripts/generate_services_file.py +114 -0
- paasta_tools-1.21.3.data/scripts/generate_services_yaml.py +30 -0
- paasta_tools-1.21.3.data/scripts/get_running_task_allocation.py +346 -0
- paasta_tools-1.21.3.data/scripts/habitat_fixer.py +86 -0
- paasta_tools-1.21.3.data/scripts/ide_helper.py +316 -0
- paasta_tools-1.21.3.data/scripts/is_pod_healthy_in_proxy.py +139 -0
- paasta_tools-1.21.3.data/scripts/is_pod_healthy_in_smartstack.py +50 -0
- paasta_tools-1.21.3.data/scripts/kill_bad_containers.py +109 -0
- paasta_tools-1.21.3.data/scripts/kubernetes_remove_evicted_pods.py +164 -0
- paasta_tools-1.21.3.data/scripts/mass-deploy-tag.sh +44 -0
- paasta_tools-1.21.3.data/scripts/mock_patch_checker.py +86 -0
- paasta_tools-1.21.3.data/scripts/paasta_cleanup_remote_run_resources.py +135 -0
- paasta_tools-1.21.3.data/scripts/paasta_cleanup_stale_nodes.py +181 -0
- paasta_tools-1.21.3.data/scripts/paasta_deploy_tron_jobs +3 -0
- paasta_tools-1.21.3.data/scripts/paasta_execute_docker_command.py +123 -0
- paasta_tools-1.21.3.data/scripts/paasta_secrets_sync.py +758 -0
- paasta_tools-1.21.3.data/scripts/paasta_tabcomplete.sh +23 -0
- paasta_tools-1.21.3.data/scripts/paasta_update_soa_memcpu.py +520 -0
- paasta_tools-1.21.3.data/scripts/render_template.py +129 -0
- paasta_tools-1.21.3.data/scripts/rightsizer_soaconfigs_update.py +348 -0
- paasta_tools-1.21.3.data/scripts/service_shard_remove.py +157 -0
- paasta_tools-1.21.3.data/scripts/service_shard_update.py +373 -0
- paasta_tools-1.21.3.data/scripts/setup_istio_mesh.py +353 -0
- paasta_tools-1.21.3.data/scripts/setup_kubernetes_cr.py +412 -0
- paasta_tools-1.21.3.data/scripts/setup_kubernetes_crd.py +138 -0
- paasta_tools-1.21.3.data/scripts/setup_kubernetes_internal_crd.py +154 -0
- paasta_tools-1.21.3.data/scripts/setup_kubernetes_job.py +353 -0
- paasta_tools-1.21.3.data/scripts/setup_prometheus_adapter_config.py +1028 -0
- paasta_tools-1.21.3.data/scripts/shared_ip_check.py +77 -0
- paasta_tools-1.21.3.data/scripts/synapse_srv_namespaces_fact.py +42 -0
- paasta_tools-1.21.3.data/scripts/timeouts_metrics_prom.py +64 -0
- paasta_tools-1.21.3.dist-info/LICENSE +201 -0
- paasta_tools-1.21.3.dist-info/METADATA +74 -0
- paasta_tools-1.21.3.dist-info/RECORD +348 -0
- paasta_tools-1.21.3.dist-info/WHEEL +5 -0
- paasta_tools-1.21.3.dist-info/entry_points.txt +20 -0
- paasta_tools-1.21.3.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from abc import ABC
|
|
3
|
+
from abc import abstractmethod
|
|
4
|
+
from typing import Optional
|
|
5
|
+
from typing import Union
|
|
6
|
+
|
|
7
|
+
from kubernetes.client import V1DeleteOptions
|
|
8
|
+
from kubernetes.client import V1Deployment
|
|
9
|
+
from kubernetes.client import V1Job
|
|
10
|
+
from kubernetes.client import V1PodDisruptionBudget
|
|
11
|
+
from kubernetes.client import V1StatefulSet
|
|
12
|
+
from kubernetes.client.rest import ApiException
|
|
13
|
+
|
|
14
|
+
from paasta_tools.autoscaling.autoscaling_service_lib import autoscaling_is_paused
|
|
15
|
+
from paasta_tools.eks_tools import load_eks_service_config_no_cache
|
|
16
|
+
from paasta_tools.kubernetes_tools import create_deployment
|
|
17
|
+
from paasta_tools.kubernetes_tools import create_job
|
|
18
|
+
from paasta_tools.kubernetes_tools import create_pod_disruption_budget
|
|
19
|
+
from paasta_tools.kubernetes_tools import create_stateful_set
|
|
20
|
+
from paasta_tools.kubernetes_tools import ensure_service_account
|
|
21
|
+
from paasta_tools.kubernetes_tools import KubeClient
|
|
22
|
+
from paasta_tools.kubernetes_tools import KubeDeployment
|
|
23
|
+
from paasta_tools.kubernetes_tools import KubernetesDeploymentConfig
|
|
24
|
+
from paasta_tools.kubernetes_tools import load_kubernetes_service_config_no_cache
|
|
25
|
+
from paasta_tools.kubernetes_tools import paasta_prefixed
|
|
26
|
+
from paasta_tools.kubernetes_tools import pod_disruption_budget_for_service_instance
|
|
27
|
+
from paasta_tools.kubernetes_tools import update_deployment
|
|
28
|
+
from paasta_tools.kubernetes_tools import update_stateful_set
|
|
29
|
+
from paasta_tools.utils import load_system_paasta_config
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Application(ABC):
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
item: Union[V1Deployment, V1StatefulSet],
|
|
36
|
+
logging=logging.getLogger(__name__),
|
|
37
|
+
) -> None:
|
|
38
|
+
"""
|
|
39
|
+
This Application wrapper is an interface for creating/deleting k8s deployments and statefulsets
|
|
40
|
+
soa_config is KubernetesDeploymentConfig. It is not loaded in init because it is not always required.
|
|
41
|
+
:param item: Kubernetes Object(V1Deployment/V1StatefulSet) that has already been filled up.
|
|
42
|
+
:param logging: where logs go
|
|
43
|
+
"""
|
|
44
|
+
if not item.metadata.namespace:
|
|
45
|
+
item.metadata.namespace = "paasta"
|
|
46
|
+
attrs = {
|
|
47
|
+
attr: item.metadata.labels.get(paasta_prefixed(attr))
|
|
48
|
+
for attr in [
|
|
49
|
+
"service",
|
|
50
|
+
"instance",
|
|
51
|
+
"git_sha",
|
|
52
|
+
"image_version",
|
|
53
|
+
"config_sha",
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
replicas = (
|
|
58
|
+
item.spec.replicas
|
|
59
|
+
if item.metadata.labels.get(paasta_prefixed("autoscaled"), "false")
|
|
60
|
+
== "false"
|
|
61
|
+
else None
|
|
62
|
+
)
|
|
63
|
+
self.kube_deployment = KubeDeployment(
|
|
64
|
+
replicas=replicas, namespace=item.metadata.namespace, **attrs
|
|
65
|
+
)
|
|
66
|
+
self.item = item
|
|
67
|
+
self.soa_config = None # type: KubernetesDeploymentConfig
|
|
68
|
+
self.logging = logging
|
|
69
|
+
|
|
70
|
+
def load_local_config(
|
|
71
|
+
self, soa_dir: str, cluster: str, eks: bool = False
|
|
72
|
+
) -> Optional[KubernetesDeploymentConfig]:
|
|
73
|
+
if not self.soa_config:
|
|
74
|
+
if eks:
|
|
75
|
+
self.soa_config = load_eks_service_config_no_cache(
|
|
76
|
+
service=self.kube_deployment.service,
|
|
77
|
+
instance=self.kube_deployment.instance,
|
|
78
|
+
cluster=cluster,
|
|
79
|
+
soa_dir=soa_dir,
|
|
80
|
+
)
|
|
81
|
+
else:
|
|
82
|
+
self.soa_config = load_kubernetes_service_config_no_cache(
|
|
83
|
+
service=self.kube_deployment.service,
|
|
84
|
+
instance=self.kube_deployment.instance,
|
|
85
|
+
cluster=cluster,
|
|
86
|
+
soa_dir=soa_dir,
|
|
87
|
+
)
|
|
88
|
+
return self.soa_config
|
|
89
|
+
|
|
90
|
+
def __str__(self):
|
|
91
|
+
service = self.kube_deployment.service
|
|
92
|
+
instance = self.kube_deployment.instance
|
|
93
|
+
git_sha = self.kube_deployment.git_sha
|
|
94
|
+
config_sha = self.kube_deployment.config_sha
|
|
95
|
+
return f"{service}-{instance}-{git_sha}-{config_sha}"
|
|
96
|
+
|
|
97
|
+
@abstractmethod
|
|
98
|
+
def deep_delete(self, kube_client: KubeClient) -> None:
|
|
99
|
+
"""
|
|
100
|
+
Remove all controllers, pods, and pod disruption budgets related to this application
|
|
101
|
+
:param kube_client:
|
|
102
|
+
"""
|
|
103
|
+
pass
|
|
104
|
+
|
|
105
|
+
def create(self, kube_client: KubeClient):
|
|
106
|
+
"""
|
|
107
|
+
Create all controllers, HPA, and pod disruption budgets related to this application
|
|
108
|
+
:param kube_client:
|
|
109
|
+
"""
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
def update(self, kube_client: KubeClient):
|
|
113
|
+
"""
|
|
114
|
+
Update all controllers, HPA, and pod disruption budgets related to this application
|
|
115
|
+
:param kube_client:
|
|
116
|
+
"""
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
def update_related_api_objects(self, kube_client: KubeClient) -> None:
|
|
120
|
+
"""
|
|
121
|
+
Update related Kubernetes API objects such as HPAs and Pod Disruption Budgets
|
|
122
|
+
:param kube_client:
|
|
123
|
+
"""
|
|
124
|
+
self.ensure_pod_disruption_budget(kube_client, self.soa_config.get_namespace())
|
|
125
|
+
|
|
126
|
+
def update_dependency_api_objects(self, kube_client: KubeClient) -> None:
|
|
127
|
+
"""
|
|
128
|
+
Update related Kubernetes API objects that should be updated before the main object,
|
|
129
|
+
such as service accounts.
|
|
130
|
+
:param kube_client:
|
|
131
|
+
"""
|
|
132
|
+
self.ensure_service_account(kube_client)
|
|
133
|
+
|
|
134
|
+
def ensure_service_account(self, kube_client: KubeClient) -> None:
|
|
135
|
+
"""
|
|
136
|
+
Ensure that the service account for this application exists
|
|
137
|
+
:param kube_client:
|
|
138
|
+
"""
|
|
139
|
+
if self.soa_config.get_iam_role():
|
|
140
|
+
ensure_service_account(
|
|
141
|
+
iam_role=self.soa_config.get_iam_role(),
|
|
142
|
+
namespace=self.soa_config.get_namespace(),
|
|
143
|
+
kube_client=kube_client,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
def delete_pod_disruption_budget(self, kube_client: KubeClient) -> None:
|
|
147
|
+
try:
|
|
148
|
+
kube_client.policy.delete_namespaced_pod_disruption_budget(
|
|
149
|
+
name=self.item.metadata.name,
|
|
150
|
+
namespace=self.item.metadata.namespace,
|
|
151
|
+
body=V1DeleteOptions(),
|
|
152
|
+
)
|
|
153
|
+
except ApiException as e:
|
|
154
|
+
if e.status == 404:
|
|
155
|
+
# Deployment does not exist, nothing to delete but
|
|
156
|
+
# we can consider this a success.
|
|
157
|
+
self.logging.debug(
|
|
158
|
+
"not deleting nonexistent pod disruption budget/{} from namespace/{}".format(
|
|
159
|
+
self.item.metadata.name, self.item.metadata.namespace
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
else:
|
|
163
|
+
raise
|
|
164
|
+
else:
|
|
165
|
+
self.logging.info(
|
|
166
|
+
"deleted pod disruption budget/{} from namespace/{}".format(
|
|
167
|
+
self.item.metadata.name, self.item.metadata.namespace
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def ensure_pod_disruption_budget(
|
|
172
|
+
self, kube_client: KubeClient, namespace: str
|
|
173
|
+
) -> V1PodDisruptionBudget:
|
|
174
|
+
max_unavailable: Union[str, int]
|
|
175
|
+
if "bounce_margin_factor" in self.soa_config.config_dict:
|
|
176
|
+
max_unavailable = (
|
|
177
|
+
f"{int((1 - self.soa_config.get_bounce_margin_factor()) * 100)}%"
|
|
178
|
+
)
|
|
179
|
+
else:
|
|
180
|
+
system_paasta_config = load_system_paasta_config()
|
|
181
|
+
max_unavailable = system_paasta_config.get_pdb_max_unavailable()
|
|
182
|
+
|
|
183
|
+
pdr = pod_disruption_budget_for_service_instance(
|
|
184
|
+
service=self.kube_deployment.service,
|
|
185
|
+
instance=self.kube_deployment.instance,
|
|
186
|
+
max_unavailable=max_unavailable,
|
|
187
|
+
namespace=namespace,
|
|
188
|
+
)
|
|
189
|
+
try:
|
|
190
|
+
existing_pdr = kube_client.policy.read_namespaced_pod_disruption_budget(
|
|
191
|
+
name=pdr.metadata.name, namespace=pdr.metadata.namespace
|
|
192
|
+
)
|
|
193
|
+
except ApiException as e:
|
|
194
|
+
if e.status == 404:
|
|
195
|
+
existing_pdr = None
|
|
196
|
+
else:
|
|
197
|
+
raise
|
|
198
|
+
|
|
199
|
+
if existing_pdr:
|
|
200
|
+
if existing_pdr.spec.min_available is not None:
|
|
201
|
+
logging.info(
|
|
202
|
+
"Not updating poddisruptionbudget: can't have both "
|
|
203
|
+
"min_available and max_unavailable"
|
|
204
|
+
)
|
|
205
|
+
elif existing_pdr.spec.max_unavailable != pdr.spec.max_unavailable:
|
|
206
|
+
logging.info(f"Updating poddisruptionbudget {pdr.metadata.name}")
|
|
207
|
+
return kube_client.policy.patch_namespaced_pod_disruption_budget(
|
|
208
|
+
name=pdr.metadata.name, namespace=pdr.metadata.namespace, body=pdr
|
|
209
|
+
)
|
|
210
|
+
else:
|
|
211
|
+
logging.info(f"poddisruptionbudget {pdr.metadata.name} up to date")
|
|
212
|
+
else:
|
|
213
|
+
logging.info(f"creating poddisruptionbudget {pdr.metadata.name}")
|
|
214
|
+
return create_pod_disruption_budget(
|
|
215
|
+
kube_client=kube_client,
|
|
216
|
+
pod_disruption_budget=pdr,
|
|
217
|
+
namespace=pdr.metadata.namespace,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class DeploymentWrapper(Application):
|
|
222
|
+
def deep_delete(
|
|
223
|
+
self, kube_client: KubeClient, propagation_policy="Foreground"
|
|
224
|
+
) -> None:
|
|
225
|
+
"""
|
|
226
|
+
Remove all controllers, pods, and pod disruption budgets related to this application
|
|
227
|
+
:param kube_client:
|
|
228
|
+
"""
|
|
229
|
+
delete_options = V1DeleteOptions(propagation_policy=propagation_policy)
|
|
230
|
+
try:
|
|
231
|
+
kube_client.deployments.delete_namespaced_deployment(
|
|
232
|
+
self.item.metadata.name,
|
|
233
|
+
self.item.metadata.namespace,
|
|
234
|
+
body=delete_options,
|
|
235
|
+
)
|
|
236
|
+
except ApiException as e:
|
|
237
|
+
if e.status == 404:
|
|
238
|
+
# Deployment does not exist, nothing to delete but
|
|
239
|
+
# we can consider this a success.
|
|
240
|
+
self.logging.debug(
|
|
241
|
+
"not deleting nonexistent deploy/{} from namespace/{}".format(
|
|
242
|
+
self.item.metadata.name, self.item.metadata.namespace
|
|
243
|
+
)
|
|
244
|
+
)
|
|
245
|
+
else:
|
|
246
|
+
raise
|
|
247
|
+
else:
|
|
248
|
+
self.logging.info(
|
|
249
|
+
"deleted deploy/{} from namespace/{}".format(
|
|
250
|
+
self.item.metadata.name, self.item.metadata.namespace
|
|
251
|
+
)
|
|
252
|
+
)
|
|
253
|
+
self.delete_pod_disruption_budget(kube_client)
|
|
254
|
+
self.delete_horizontal_pod_autoscaler(kube_client)
|
|
255
|
+
|
|
256
|
+
def get_existing_app(self, kube_client: KubeClient):
|
|
257
|
+
return kube_client.deployments.read_namespaced_deployment(
|
|
258
|
+
name=self.item.metadata.name, namespace=self.item.metadata.namespace
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
def create(self, kube_client: KubeClient) -> None:
|
|
262
|
+
create_deployment(
|
|
263
|
+
kube_client=kube_client,
|
|
264
|
+
formatted_deployment=self.item,
|
|
265
|
+
namespace=self.soa_config.get_namespace(),
|
|
266
|
+
)
|
|
267
|
+
self.ensure_pod_disruption_budget(kube_client, self.soa_config.get_namespace())
|
|
268
|
+
self.sync_horizontal_pod_autoscaler(kube_client)
|
|
269
|
+
|
|
270
|
+
def update(self, kube_client: KubeClient) -> None:
|
|
271
|
+
# If HPA is enabled, do not update replicas.
|
|
272
|
+
# In all other cases, replica is set to max(instances, min_instances)
|
|
273
|
+
update_deployment(
|
|
274
|
+
kube_client=kube_client,
|
|
275
|
+
formatted_deployment=self.item,
|
|
276
|
+
namespace=self.soa_config.get_namespace(),
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
def update_related_api_objects(self, kube_client: KubeClient) -> None:
|
|
280
|
+
super().update_related_api_objects(kube_client)
|
|
281
|
+
self.sync_horizontal_pod_autoscaler(kube_client)
|
|
282
|
+
|
|
283
|
+
def sync_horizontal_pod_autoscaler(self, kube_client: KubeClient) -> None:
|
|
284
|
+
"""
|
|
285
|
+
In order for autoscaling to work, there needs to be at least two configurations
|
|
286
|
+
min_instnace, max_instance, and there cannot be instance.
|
|
287
|
+
"""
|
|
288
|
+
desired_hpa_spec = self.soa_config.get_autoscaling_metric_spec(
|
|
289
|
+
name=self.item.metadata.name,
|
|
290
|
+
cluster=self.soa_config.cluster,
|
|
291
|
+
kube_client=kube_client,
|
|
292
|
+
namespace=self.item.metadata.namespace,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
hpa_exists = self.exists_hpa(kube_client)
|
|
296
|
+
should_have_hpa = desired_hpa_spec and not autoscaling_is_paused()
|
|
297
|
+
|
|
298
|
+
if not should_have_hpa:
|
|
299
|
+
self.logging.info(
|
|
300
|
+
f"No HPA required for {self.item.metadata.name}/name in {self.item.metadata.namespace}"
|
|
301
|
+
)
|
|
302
|
+
if hpa_exists:
|
|
303
|
+
self.logging.info(
|
|
304
|
+
f"Deleting HPA for {self.item.metadata.name}/name in {self.item.metadata.namespace}"
|
|
305
|
+
)
|
|
306
|
+
self.delete_horizontal_pod_autoscaler(kube_client)
|
|
307
|
+
return
|
|
308
|
+
|
|
309
|
+
self.logging.info(
|
|
310
|
+
f"Syncing HPA setting for {self.item.metadata.name}/name in {self.item.metadata.namespace}"
|
|
311
|
+
)
|
|
312
|
+
self.logging.debug(desired_hpa_spec)
|
|
313
|
+
if not hpa_exists:
|
|
314
|
+
self.logging.info(
|
|
315
|
+
f"Creating new HPA for {self.item.metadata.name}/name in {self.item.metadata.namespace}"
|
|
316
|
+
)
|
|
317
|
+
kube_client.autoscaling.create_namespaced_horizontal_pod_autoscaler(
|
|
318
|
+
namespace=self.item.metadata.namespace,
|
|
319
|
+
body=desired_hpa_spec,
|
|
320
|
+
pretty=True,
|
|
321
|
+
)
|
|
322
|
+
else:
|
|
323
|
+
self.logging.info(
|
|
324
|
+
f"Updating new HPA for {self.item.metadata.name}/name in {self.item.metadata.namespace}/namespace"
|
|
325
|
+
)
|
|
326
|
+
kube_client.autoscaling.replace_namespaced_horizontal_pod_autoscaler(
|
|
327
|
+
name=self.item.metadata.name,
|
|
328
|
+
namespace=self.item.metadata.namespace,
|
|
329
|
+
body=desired_hpa_spec,
|
|
330
|
+
pretty=True,
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
def exists_hpa(self, kube_client: KubeClient) -> bool:
|
|
334
|
+
return (
|
|
335
|
+
len(
|
|
336
|
+
kube_client.autoscaling.list_namespaced_horizontal_pod_autoscaler(
|
|
337
|
+
field_selector=f"metadata.name={self.item.metadata.name}",
|
|
338
|
+
namespace=self.item.metadata.namespace,
|
|
339
|
+
).items
|
|
340
|
+
)
|
|
341
|
+
> 0
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
def delete_horizontal_pod_autoscaler(self, kube_client: KubeClient) -> None:
|
|
345
|
+
try:
|
|
346
|
+
kube_client.autoscaling.delete_namespaced_horizontal_pod_autoscaler(
|
|
347
|
+
name=self.item.metadata.name,
|
|
348
|
+
namespace=self.item.metadata.namespace,
|
|
349
|
+
body=V1DeleteOptions(),
|
|
350
|
+
)
|
|
351
|
+
except ApiException as e:
|
|
352
|
+
if e.status == 404:
|
|
353
|
+
# Deployment does not exist, nothing to delete but
|
|
354
|
+
# we can consider this a success.
|
|
355
|
+
self.logging.debug(
|
|
356
|
+
f"not deleting nonexistent HPA/{self.item.metadata.name} from namespace/{self.item.metadata.namespace}"
|
|
357
|
+
)
|
|
358
|
+
else:
|
|
359
|
+
raise
|
|
360
|
+
else:
|
|
361
|
+
self.logging.info(
|
|
362
|
+
"deleted HPA/{} from namespace/{}".format(
|
|
363
|
+
self.item.metadata.name, self.item.metadata.namespace
|
|
364
|
+
)
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
class StatefulSetWrapper(Application):
|
|
369
|
+
def deep_delete(self, kube_client: KubeClient) -> None:
|
|
370
|
+
"""
|
|
371
|
+
Remove all controllers, pods, and pod disruption budgets related to this application
|
|
372
|
+
:param kube_client:
|
|
373
|
+
"""
|
|
374
|
+
delete_options = V1DeleteOptions(propagation_policy="Foreground")
|
|
375
|
+
try:
|
|
376
|
+
kube_client.deployments.delete_namespaced_stateful_set(
|
|
377
|
+
self.item.metadata.name,
|
|
378
|
+
self.item.metadata.namespace,
|
|
379
|
+
body=delete_options,
|
|
380
|
+
)
|
|
381
|
+
except ApiException as e:
|
|
382
|
+
if e.status == 404:
|
|
383
|
+
# StatefulSet does not exist, nothing to delete but
|
|
384
|
+
# we can consider this a success.
|
|
385
|
+
self.logging.debug(
|
|
386
|
+
"not deleting nonexistent statefulset/{} from namespace/{}".format(
|
|
387
|
+
self.item.metadata.name, self.item.metadata.namespace
|
|
388
|
+
)
|
|
389
|
+
)
|
|
390
|
+
else:
|
|
391
|
+
raise
|
|
392
|
+
else:
|
|
393
|
+
self.logging.info(
|
|
394
|
+
"deleted statefulset/{} from namespace/{}".format(
|
|
395
|
+
self.item.metadata.name, self.item.metadata.namespace
|
|
396
|
+
)
|
|
397
|
+
)
|
|
398
|
+
self.delete_pod_disruption_budget(kube_client)
|
|
399
|
+
|
|
400
|
+
def create(self, kube_client: KubeClient):
|
|
401
|
+
create_stateful_set(
|
|
402
|
+
kube_client=kube_client,
|
|
403
|
+
formatted_stateful_set=self.item,
|
|
404
|
+
namespace=self.soa_config.get_namespace(),
|
|
405
|
+
)
|
|
406
|
+
self.ensure_pod_disruption_budget(kube_client, self.soa_config.get_namespace())
|
|
407
|
+
|
|
408
|
+
def update(self, kube_client: KubeClient):
|
|
409
|
+
update_stateful_set(
|
|
410
|
+
kube_client=kube_client,
|
|
411
|
+
formatted_stateful_set=self.item,
|
|
412
|
+
namespace=self.soa_config.get_namespace(),
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
class JobWrapper(Application):
|
|
417
|
+
def __init__(
|
|
418
|
+
self,
|
|
419
|
+
item: V1Job,
|
|
420
|
+
logging=logging.getLogger(__name__),
|
|
421
|
+
):
|
|
422
|
+
item.spec.replicas = None # avoid causing errors in parent class
|
|
423
|
+
super().__init__(item, logging)
|
|
424
|
+
|
|
425
|
+
def deep_delete(self, kube_client: KubeClient) -> None:
|
|
426
|
+
"""Remove resources related to the job"""
|
|
427
|
+
delete_options = V1DeleteOptions(propagation_policy="Foreground")
|
|
428
|
+
try:
|
|
429
|
+
kube_client.batches.delete_namespaced_job(
|
|
430
|
+
self.item.metadata.name,
|
|
431
|
+
self.item.metadata.namespace,
|
|
432
|
+
body=delete_options,
|
|
433
|
+
)
|
|
434
|
+
except ApiException as e:
|
|
435
|
+
if e.status == 404:
|
|
436
|
+
# Job does not exist, nothing to delete but
|
|
437
|
+
# we can consider this a success.
|
|
438
|
+
self.logging.debug(
|
|
439
|
+
"not deleting nonexistent job/{} from namespace/{}".format(
|
|
440
|
+
self.item.metadata.name,
|
|
441
|
+
self.item.metadata.namespace,
|
|
442
|
+
)
|
|
443
|
+
)
|
|
444
|
+
else:
|
|
445
|
+
raise
|
|
446
|
+
else:
|
|
447
|
+
self.logging.info(
|
|
448
|
+
"deleted job/{} from namespace/{}".format(
|
|
449
|
+
self.item.metadata.name,
|
|
450
|
+
self.item.metadata.namespace,
|
|
451
|
+
)
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
def create(self, kube_client: KubeClient):
|
|
455
|
+
"""Create and start Kubernetes Job"""
|
|
456
|
+
create_job(
|
|
457
|
+
kube_client=kube_client,
|
|
458
|
+
formatted_job=self.item,
|
|
459
|
+
namespace=self.soa_config.get_namespace(),
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
def get_application_wrapper(
|
|
464
|
+
formatted_application: Union[V1Deployment, V1StatefulSet, V1Job]
|
|
465
|
+
) -> Application:
|
|
466
|
+
app: Application
|
|
467
|
+
if isinstance(formatted_application, V1Deployment):
|
|
468
|
+
app = DeploymentWrapper(formatted_application)
|
|
469
|
+
elif isinstance(formatted_application, V1StatefulSet):
|
|
470
|
+
app = StatefulSetWrapper(formatted_application)
|
|
471
|
+
elif isinstance(formatted_application, V1Job):
|
|
472
|
+
app = JobWrapper(formatted_application)
|
|
473
|
+
else:
|
|
474
|
+
raise Exception("Unknown kubernetes object to update")
|
|
475
|
+
|
|
476
|
+
return app
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
from typing import Sequence
|
|
6
|
+
from typing import Tuple
|
|
7
|
+
|
|
8
|
+
from kubernetes.client import V1Deployment
|
|
9
|
+
from kubernetes.client import V1StatefulSet
|
|
10
|
+
|
|
11
|
+
from paasta_tools.kubernetes.application.controller_wrappers import Application
|
|
12
|
+
from paasta_tools.kubernetes.application.controller_wrappers import DeploymentWrapper
|
|
13
|
+
from paasta_tools.kubernetes.application.controller_wrappers import StatefulSetWrapper
|
|
14
|
+
from paasta_tools.kubernetes_tools import KubeClient
|
|
15
|
+
from paasta_tools.kubernetes_tools import paasta_prefixed
|
|
16
|
+
|
|
17
|
+
log = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def is_valid_application(deployment: V1Deployment):
|
|
21
|
+
is_valid = True
|
|
22
|
+
missing = []
|
|
23
|
+
for attr in ["service", "instance", "git_sha", "config_sha"]:
|
|
24
|
+
prefixed_attr = paasta_prefixed(attr)
|
|
25
|
+
if prefixed_attr not in deployment.metadata.labels:
|
|
26
|
+
is_valid = False
|
|
27
|
+
missing.append(prefixed_attr)
|
|
28
|
+
if missing:
|
|
29
|
+
log.warning(
|
|
30
|
+
f"deployment/{deployment.metadata.name} in "
|
|
31
|
+
f"namespace/{deployment.metadata.namespace} "
|
|
32
|
+
f"is missing following labels: {missing}"
|
|
33
|
+
)
|
|
34
|
+
return is_valid
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def list_paasta_managed_deployments(
|
|
38
|
+
kube_client: KubeClient, **kwargs
|
|
39
|
+
) -> Dict[Tuple[str, str], List[Application]]:
|
|
40
|
+
deployments: Dict[Tuple[str, str], List[Application]] = {}
|
|
41
|
+
for deployment in kube_client.deployments.list_deployment_for_all_namespaces(
|
|
42
|
+
label_selector=paasta_prefixed("managed"), **kwargs
|
|
43
|
+
).items:
|
|
44
|
+
if is_valid_application(deployment):
|
|
45
|
+
application = DeploymentWrapper(deployment)
|
|
46
|
+
service = application.kube_deployment.service
|
|
47
|
+
instance = application.kube_deployment.instance
|
|
48
|
+
if deployments.get((service, instance), None):
|
|
49
|
+
deployments[(service, instance)].append(application)
|
|
50
|
+
else:
|
|
51
|
+
deployments[(service, instance)] = [application]
|
|
52
|
+
return deployments
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def list_paasta_managed_stateful_sets(
|
|
56
|
+
kube_client: KubeClient, **kwargs
|
|
57
|
+
) -> Dict[Tuple[str, str], List[Application]]:
|
|
58
|
+
deployments: Dict[Tuple[str, str], List[Application]] = {}
|
|
59
|
+
for deployment in kube_client.deployments.list_stateful_set_for_all_namespaces(
|
|
60
|
+
label_selector=paasta_prefixed("managed"), **kwargs
|
|
61
|
+
).items:
|
|
62
|
+
if is_valid_application(deployment):
|
|
63
|
+
application = StatefulSetWrapper(deployment)
|
|
64
|
+
service = application.kube_deployment.service
|
|
65
|
+
instance = application.kube_deployment.instance
|
|
66
|
+
if deployments.get((service, instance), None):
|
|
67
|
+
deployments[(service, instance)].append(application)
|
|
68
|
+
else:
|
|
69
|
+
deployments[(service, instance)] = [application]
|
|
70
|
+
return deployments
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def list_all_applications(
|
|
74
|
+
kube_client: KubeClient, application_types: Sequence[Any]
|
|
75
|
+
) -> Dict[Tuple[str, str], List[Application]]:
|
|
76
|
+
"""
|
|
77
|
+
List all applications in the cluster of the types from application_types.
|
|
78
|
+
Only applications with complete set of labels are included (See is_valid_application()).
|
|
79
|
+
:param kube_client:
|
|
80
|
+
|
|
81
|
+
:param application_types: types of applications
|
|
82
|
+
:return: A mapping from (service, instance) to application
|
|
83
|
+
"""
|
|
84
|
+
apps: Dict[Tuple[str, str], List[Application]] = {}
|
|
85
|
+
for application_type in application_types:
|
|
86
|
+
if application_type == V1Deployment:
|
|
87
|
+
apps = {**apps, **list_paasta_managed_deployments(kube_client)}
|
|
88
|
+
elif application_type == V1StatefulSet:
|
|
89
|
+
apps.update(list_paasta_managed_stateful_sets(kube_client))
|
|
90
|
+
return apps
|
|
File without changes
|