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,62 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
# flake8: noqa
|
|
4
|
+
|
|
5
|
+
# import all models into this package
|
|
6
|
+
# if you have many models here with many references from one model to another this may
|
|
7
|
+
# raise a RecursionError
|
|
8
|
+
# to avoid this, import only the models that you directly need like:
|
|
9
|
+
# from from paasta_tools.paastaapi.model.pet import Pet
|
|
10
|
+
# or import this package, but before doing it, use:
|
|
11
|
+
# import sys
|
|
12
|
+
# sys.setrecursionlimit(n)
|
|
13
|
+
|
|
14
|
+
from paasta_tools.paastaapi.model.adhoc_launch_history import AdhocLaunchHistory
|
|
15
|
+
from paasta_tools.paastaapi.model.autoscaler_count_msg import AutoscalerCountMsg
|
|
16
|
+
from paasta_tools.paastaapi.model.deploy_queue import DeployQueue
|
|
17
|
+
from paasta_tools.paastaapi.model.deploy_queue_service_instance import DeployQueueServiceInstance
|
|
18
|
+
from paasta_tools.paastaapi.model.envoy_backend import EnvoyBackend
|
|
19
|
+
from paasta_tools.paastaapi.model.envoy_location import EnvoyLocation
|
|
20
|
+
from paasta_tools.paastaapi.model.envoy_status import EnvoyStatus
|
|
21
|
+
from paasta_tools.paastaapi.model.flink_cluster_overview import FlinkClusterOverview
|
|
22
|
+
from paasta_tools.paastaapi.model.flink_config import FlinkConfig
|
|
23
|
+
from paasta_tools.paastaapi.model.flink_job import FlinkJob
|
|
24
|
+
from paasta_tools.paastaapi.model.flink_job_details import FlinkJobDetails
|
|
25
|
+
from paasta_tools.paastaapi.model.flink_jobs import FlinkJobs
|
|
26
|
+
from paasta_tools.paastaapi.model.float_and_error import FloatAndError
|
|
27
|
+
from paasta_tools.paastaapi.model.hpa_metric import HPAMetric
|
|
28
|
+
from paasta_tools.paastaapi.model.inline_object import InlineObject
|
|
29
|
+
from paasta_tools.paastaapi.model.inline_response200 import InlineResponse200
|
|
30
|
+
from paasta_tools.paastaapi.model.inline_response2001 import InlineResponse2001
|
|
31
|
+
from paasta_tools.paastaapi.model.instance_bounce_status import InstanceBounceStatus
|
|
32
|
+
from paasta_tools.paastaapi.model.instance_mesh_status import InstanceMeshStatus
|
|
33
|
+
from paasta_tools.paastaapi.model.instance_status import InstanceStatus
|
|
34
|
+
from paasta_tools.paastaapi.model.instance_status_adhoc import InstanceStatusAdhoc
|
|
35
|
+
from paasta_tools.paastaapi.model.instance_status_cassandracluster import InstanceStatusCassandracluster
|
|
36
|
+
from paasta_tools.paastaapi.model.instance_status_flink import InstanceStatusFlink
|
|
37
|
+
from paasta_tools.paastaapi.model.instance_status_kafkacluster import InstanceStatusKafkacluster
|
|
38
|
+
from paasta_tools.paastaapi.model.instance_status_kubernetes import InstanceStatusKubernetes
|
|
39
|
+
from paasta_tools.paastaapi.model.instance_status_kubernetes_autoscaling_status import InstanceStatusKubernetesAutoscalingStatus
|
|
40
|
+
from paasta_tools.paastaapi.model.instance_status_kubernetes_v2 import InstanceStatusKubernetesV2
|
|
41
|
+
from paasta_tools.paastaapi.model.instance_status_tron import InstanceStatusTron
|
|
42
|
+
from paasta_tools.paastaapi.model.instance_tasks import InstanceTasks
|
|
43
|
+
from paasta_tools.paastaapi.model.integer_and_error import IntegerAndError
|
|
44
|
+
from paasta_tools.paastaapi.model.kubernetes_container import KubernetesContainer
|
|
45
|
+
from paasta_tools.paastaapi.model.kubernetes_container_v2 import KubernetesContainerV2
|
|
46
|
+
from paasta_tools.paastaapi.model.kubernetes_healthcheck import KubernetesHealthcheck
|
|
47
|
+
from paasta_tools.paastaapi.model.kubernetes_pod import KubernetesPod
|
|
48
|
+
from paasta_tools.paastaapi.model.kubernetes_pod_event import KubernetesPodEvent
|
|
49
|
+
from paasta_tools.paastaapi.model.kubernetes_pod_v2 import KubernetesPodV2
|
|
50
|
+
from paasta_tools.paastaapi.model.kubernetes_replica_set import KubernetesReplicaSet
|
|
51
|
+
from paasta_tools.paastaapi.model.kubernetes_version import KubernetesVersion
|
|
52
|
+
from paasta_tools.paastaapi.model.remote_run_outcome import RemoteRunOutcome
|
|
53
|
+
from paasta_tools.paastaapi.model.remote_run_start import RemoteRunStart
|
|
54
|
+
from paasta_tools.paastaapi.model.remote_run_stop import RemoteRunStop
|
|
55
|
+
from paasta_tools.paastaapi.model.remote_run_token import RemoteRunToken
|
|
56
|
+
from paasta_tools.paastaapi.model.resource import Resource
|
|
57
|
+
from paasta_tools.paastaapi.model.resource_item import ResourceItem
|
|
58
|
+
from paasta_tools.paastaapi.model.resource_value import ResourceValue
|
|
59
|
+
from paasta_tools.paastaapi.model.smartstack_backend import SmartstackBackend
|
|
60
|
+
from paasta_tools.paastaapi.model.smartstack_location import SmartstackLocation
|
|
61
|
+
from paasta_tools.paastaapi.model.smartstack_status import SmartstackStatus
|
|
62
|
+
from paasta_tools.paastaapi.model.task_tail_lines import TaskTailLines
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Paasta API
|
|
5
|
+
|
|
6
|
+
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
|
|
7
|
+
|
|
8
|
+
The version of the OpenAPI document: 1.2.0
|
|
9
|
+
Generated by: https://openapi-generator.tech
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
import io
|
|
14
|
+
import json
|
|
15
|
+
import logging
|
|
16
|
+
import re
|
|
17
|
+
import ssl
|
|
18
|
+
from urllib.parse import urlencode
|
|
19
|
+
|
|
20
|
+
import certifi
|
|
21
|
+
import urllib3
|
|
22
|
+
|
|
23
|
+
from paasta_tools.paastaapi.exceptions import ApiException, ApiValueError
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class RESTResponse(io.IOBase):
|
|
30
|
+
|
|
31
|
+
def __init__(self, resp):
|
|
32
|
+
self.urllib3_response = resp
|
|
33
|
+
self.status = resp.status
|
|
34
|
+
self.reason = resp.reason
|
|
35
|
+
self.data = resp.data
|
|
36
|
+
|
|
37
|
+
def getheaders(self):
|
|
38
|
+
"""Returns a dictionary of the response headers."""
|
|
39
|
+
return self.urllib3_response.getheaders()
|
|
40
|
+
|
|
41
|
+
def getheader(self, name, default=None):
|
|
42
|
+
"""Returns a given response header."""
|
|
43
|
+
return self.urllib3_response.getheader(name, default)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class RESTClientObject(object):
|
|
47
|
+
|
|
48
|
+
def __init__(self, configuration, pools_size=4, maxsize=None):
|
|
49
|
+
# urllib3.PoolManager will pass all kw parameters to connectionpool
|
|
50
|
+
# https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501
|
|
51
|
+
# https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501
|
|
52
|
+
# maxsize is the number of requests to host that are allowed in parallel # noqa: E501
|
|
53
|
+
# Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501
|
|
54
|
+
|
|
55
|
+
# cert_reqs
|
|
56
|
+
if configuration.verify_ssl:
|
|
57
|
+
cert_reqs = ssl.CERT_REQUIRED
|
|
58
|
+
else:
|
|
59
|
+
cert_reqs = ssl.CERT_NONE
|
|
60
|
+
|
|
61
|
+
# ca_certs
|
|
62
|
+
if configuration.ssl_ca_cert:
|
|
63
|
+
ca_certs = configuration.ssl_ca_cert
|
|
64
|
+
else:
|
|
65
|
+
# if not set certificate file, use Mozilla's root certificates.
|
|
66
|
+
ca_certs = certifi.where()
|
|
67
|
+
|
|
68
|
+
addition_pool_args = {}
|
|
69
|
+
if configuration.assert_hostname is not None:
|
|
70
|
+
addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501
|
|
71
|
+
|
|
72
|
+
if configuration.retries is not None:
|
|
73
|
+
addition_pool_args['retries'] = configuration.retries
|
|
74
|
+
|
|
75
|
+
if maxsize is None:
|
|
76
|
+
if configuration.connection_pool_maxsize is not None:
|
|
77
|
+
maxsize = configuration.connection_pool_maxsize
|
|
78
|
+
else:
|
|
79
|
+
maxsize = 4
|
|
80
|
+
|
|
81
|
+
# https pool manager
|
|
82
|
+
if configuration.proxy:
|
|
83
|
+
self.pool_manager = urllib3.ProxyManager(
|
|
84
|
+
num_pools=pools_size,
|
|
85
|
+
maxsize=maxsize,
|
|
86
|
+
cert_reqs=cert_reqs,
|
|
87
|
+
ca_certs=ca_certs,
|
|
88
|
+
cert_file=configuration.cert_file,
|
|
89
|
+
key_file=configuration.key_file,
|
|
90
|
+
proxy_url=configuration.proxy,
|
|
91
|
+
proxy_headers=configuration.proxy_headers,
|
|
92
|
+
**addition_pool_args
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
self.pool_manager = urllib3.PoolManager(
|
|
96
|
+
num_pools=pools_size,
|
|
97
|
+
maxsize=maxsize,
|
|
98
|
+
cert_reqs=cert_reqs,
|
|
99
|
+
ca_certs=ca_certs,
|
|
100
|
+
cert_file=configuration.cert_file,
|
|
101
|
+
key_file=configuration.key_file,
|
|
102
|
+
**addition_pool_args
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
def request(self, method, url, query_params=None, headers=None,
|
|
106
|
+
body=None, post_params=None, _preload_content=True,
|
|
107
|
+
_request_timeout=None):
|
|
108
|
+
"""Perform requests.
|
|
109
|
+
|
|
110
|
+
:param method: http request method
|
|
111
|
+
:param url: http request url
|
|
112
|
+
:param query_params: query parameters in the url
|
|
113
|
+
:param headers: http request headers
|
|
114
|
+
:param body: request json body, for `application/json`
|
|
115
|
+
:param post_params: request post parameters,
|
|
116
|
+
`application/x-www-form-urlencoded`
|
|
117
|
+
and `multipart/form-data`
|
|
118
|
+
:param _preload_content: if False, the urllib3.HTTPResponse object will
|
|
119
|
+
be returned without reading/decoding response
|
|
120
|
+
data. Default is True.
|
|
121
|
+
:param _request_timeout: timeout setting for this request. If one
|
|
122
|
+
number provided, it will be total request
|
|
123
|
+
timeout. It can also be a pair (tuple) of
|
|
124
|
+
(connection, read) timeouts.
|
|
125
|
+
"""
|
|
126
|
+
method = method.upper()
|
|
127
|
+
assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT',
|
|
128
|
+
'PATCH', 'OPTIONS']
|
|
129
|
+
|
|
130
|
+
if post_params and body:
|
|
131
|
+
raise ApiValueError(
|
|
132
|
+
"body parameter cannot be used with post_params parameter."
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
post_params = post_params or {}
|
|
136
|
+
headers = headers or {}
|
|
137
|
+
|
|
138
|
+
timeout = None
|
|
139
|
+
if _request_timeout:
|
|
140
|
+
if isinstance(_request_timeout, (int, float)): # noqa: E501,F821
|
|
141
|
+
timeout = urllib3.Timeout(total=_request_timeout)
|
|
142
|
+
elif (isinstance(_request_timeout, tuple) and
|
|
143
|
+
len(_request_timeout) == 2):
|
|
144
|
+
timeout = urllib3.Timeout(
|
|
145
|
+
connect=_request_timeout[0], read=_request_timeout[1])
|
|
146
|
+
|
|
147
|
+
if 'Content-Type' not in headers:
|
|
148
|
+
headers['Content-Type'] = 'application/json'
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
|
|
152
|
+
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
|
|
153
|
+
if query_params:
|
|
154
|
+
url += '?' + urlencode(query_params)
|
|
155
|
+
if re.search('json', headers['Content-Type'], re.IGNORECASE):
|
|
156
|
+
request_body = None
|
|
157
|
+
if body is not None:
|
|
158
|
+
request_body = json.dumps(body)
|
|
159
|
+
r = self.pool_manager.request(
|
|
160
|
+
method, url,
|
|
161
|
+
body=request_body,
|
|
162
|
+
preload_content=_preload_content,
|
|
163
|
+
timeout=timeout,
|
|
164
|
+
headers=headers)
|
|
165
|
+
elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501
|
|
166
|
+
r = self.pool_manager.request(
|
|
167
|
+
method, url,
|
|
168
|
+
fields=post_params,
|
|
169
|
+
encode_multipart=False,
|
|
170
|
+
preload_content=_preload_content,
|
|
171
|
+
timeout=timeout,
|
|
172
|
+
headers=headers)
|
|
173
|
+
elif headers['Content-Type'] == 'multipart/form-data':
|
|
174
|
+
# must del headers['Content-Type'], or the correct
|
|
175
|
+
# Content-Type which generated by urllib3 will be
|
|
176
|
+
# overwritten.
|
|
177
|
+
del headers['Content-Type']
|
|
178
|
+
r = self.pool_manager.request(
|
|
179
|
+
method, url,
|
|
180
|
+
fields=post_params,
|
|
181
|
+
encode_multipart=True,
|
|
182
|
+
preload_content=_preload_content,
|
|
183
|
+
timeout=timeout,
|
|
184
|
+
headers=headers)
|
|
185
|
+
# Pass a `string` parameter directly in the body to support
|
|
186
|
+
# other content types than Json when `body` argument is
|
|
187
|
+
# provided in serialized form
|
|
188
|
+
elif isinstance(body, str) or isinstance(body, bytes):
|
|
189
|
+
request_body = body
|
|
190
|
+
r = self.pool_manager.request(
|
|
191
|
+
method, url,
|
|
192
|
+
body=request_body,
|
|
193
|
+
preload_content=_preload_content,
|
|
194
|
+
timeout=timeout,
|
|
195
|
+
headers=headers)
|
|
196
|
+
else:
|
|
197
|
+
# Cannot generate the request from given parameters
|
|
198
|
+
msg = """Cannot prepare a request message for provided
|
|
199
|
+
arguments. Please check that your arguments match
|
|
200
|
+
declared content type."""
|
|
201
|
+
raise ApiException(status=0, reason=msg)
|
|
202
|
+
# For `GET`, `HEAD`
|
|
203
|
+
else:
|
|
204
|
+
r = self.pool_manager.request(method, url,
|
|
205
|
+
fields=query_params,
|
|
206
|
+
preload_content=_preload_content,
|
|
207
|
+
timeout=timeout,
|
|
208
|
+
headers=headers)
|
|
209
|
+
except urllib3.exceptions.SSLError as e:
|
|
210
|
+
msg = "{0}\n{1}".format(type(e).__name__, str(e))
|
|
211
|
+
raise ApiException(status=0, reason=msg)
|
|
212
|
+
|
|
213
|
+
if _preload_content:
|
|
214
|
+
r = RESTResponse(r)
|
|
215
|
+
|
|
216
|
+
# log response body
|
|
217
|
+
logger.debug("response body: %s", r.data)
|
|
218
|
+
|
|
219
|
+
if not 200 <= r.status <= 299:
|
|
220
|
+
raise ApiException(http_resp=r)
|
|
221
|
+
|
|
222
|
+
return r
|
|
223
|
+
|
|
224
|
+
def GET(self, url, headers=None, query_params=None, _preload_content=True,
|
|
225
|
+
_request_timeout=None):
|
|
226
|
+
return self.request("GET", url,
|
|
227
|
+
headers=headers,
|
|
228
|
+
_preload_content=_preload_content,
|
|
229
|
+
_request_timeout=_request_timeout,
|
|
230
|
+
query_params=query_params)
|
|
231
|
+
|
|
232
|
+
def HEAD(self, url, headers=None, query_params=None, _preload_content=True,
|
|
233
|
+
_request_timeout=None):
|
|
234
|
+
return self.request("HEAD", url,
|
|
235
|
+
headers=headers,
|
|
236
|
+
_preload_content=_preload_content,
|
|
237
|
+
_request_timeout=_request_timeout,
|
|
238
|
+
query_params=query_params)
|
|
239
|
+
|
|
240
|
+
def OPTIONS(self, url, headers=None, query_params=None, post_params=None,
|
|
241
|
+
body=None, _preload_content=True, _request_timeout=None):
|
|
242
|
+
return self.request("OPTIONS", url,
|
|
243
|
+
headers=headers,
|
|
244
|
+
query_params=query_params,
|
|
245
|
+
post_params=post_params,
|
|
246
|
+
_preload_content=_preload_content,
|
|
247
|
+
_request_timeout=_request_timeout,
|
|
248
|
+
body=body)
|
|
249
|
+
|
|
250
|
+
def DELETE(self, url, headers=None, query_params=None, body=None,
|
|
251
|
+
_preload_content=True, _request_timeout=None):
|
|
252
|
+
return self.request("DELETE", url,
|
|
253
|
+
headers=headers,
|
|
254
|
+
query_params=query_params,
|
|
255
|
+
_preload_content=_preload_content,
|
|
256
|
+
_request_timeout=_request_timeout,
|
|
257
|
+
body=body)
|
|
258
|
+
|
|
259
|
+
def POST(self, url, headers=None, query_params=None, post_params=None,
|
|
260
|
+
body=None, _preload_content=True, _request_timeout=None):
|
|
261
|
+
return self.request("POST", url,
|
|
262
|
+
headers=headers,
|
|
263
|
+
query_params=query_params,
|
|
264
|
+
post_params=post_params,
|
|
265
|
+
_preload_content=_preload_content,
|
|
266
|
+
_request_timeout=_request_timeout,
|
|
267
|
+
body=body)
|
|
268
|
+
|
|
269
|
+
def PUT(self, url, headers=None, query_params=None, post_params=None,
|
|
270
|
+
body=None, _preload_content=True, _request_timeout=None):
|
|
271
|
+
return self.request("PUT", url,
|
|
272
|
+
headers=headers,
|
|
273
|
+
query_params=query_params,
|
|
274
|
+
post_params=post_params,
|
|
275
|
+
_preload_content=_preload_content,
|
|
276
|
+
_request_timeout=_request_timeout,
|
|
277
|
+
body=body)
|
|
278
|
+
|
|
279
|
+
def PATCH(self, url, headers=None, query_params=None, post_params=None,
|
|
280
|
+
body=None, _preload_content=True, _request_timeout=None):
|
|
281
|
+
return self.request("PATCH", url,
|
|
282
|
+
headers=headers,
|
|
283
|
+
query_params=query_params,
|
|
284
|
+
post_params=post_params,
|
|
285
|
+
_preload_content=_preload_content,
|
|
286
|
+
_request_timeout=_request_timeout,
|
|
287
|
+
body=body)
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import logging
|
|
3
|
+
import sys
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Sequence
|
|
6
|
+
|
|
7
|
+
from dateutil.tz import tzutc
|
|
8
|
+
from kubernetes.client import V1Pod
|
|
9
|
+
|
|
10
|
+
from paasta_tools.kubernetes_tools import get_all_pods
|
|
11
|
+
from paasta_tools.kubernetes_tools import get_pod_condition
|
|
12
|
+
from paasta_tools.kubernetes_tools import is_pod_completed
|
|
13
|
+
from paasta_tools.kubernetes_tools import KubeClient
|
|
14
|
+
|
|
15
|
+
log = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def parse_args():
|
|
19
|
+
parser = argparse.ArgumentParser(
|
|
20
|
+
description="Terminates completed pods based on namespace and minutes since completion"
|
|
21
|
+
)
|
|
22
|
+
parser.add_argument(
|
|
23
|
+
"-n",
|
|
24
|
+
"--namespace",
|
|
25
|
+
help="Namespace of the pods to terminate from",
|
|
26
|
+
required=True,
|
|
27
|
+
)
|
|
28
|
+
parser.add_argument(
|
|
29
|
+
"-m",
|
|
30
|
+
"--minutes",
|
|
31
|
+
help="Minutes since the pods' completion. Terminates pods based on time since completion.",
|
|
32
|
+
required=True,
|
|
33
|
+
type=int,
|
|
34
|
+
)
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
"-e",
|
|
37
|
+
"--error-minutes",
|
|
38
|
+
help="Minutes since the pod encountered an error. Terminates pods based on time since failure.",
|
|
39
|
+
# this can't be required until we've rolled this out everywhere AND have updated all the callsites
|
|
40
|
+
required=False,
|
|
41
|
+
type=int,
|
|
42
|
+
)
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
"-p",
|
|
45
|
+
"--pending-minutes",
|
|
46
|
+
help="Minutes since the pod was scheduled. Terminates pods whose phase is Pending based on time since scheduled. Including pod status Pending/ContainerCreating/Terminating.",
|
|
47
|
+
required=False,
|
|
48
|
+
type=int,
|
|
49
|
+
)
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
"--dry-run",
|
|
52
|
+
dest="dry_run",
|
|
53
|
+
action="store_true",
|
|
54
|
+
help="Print pods to be terminated, instead of terminating them",
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"-v", "--verbose", dest="verbose", action="store_true", default=False
|
|
58
|
+
)
|
|
59
|
+
args = parser.parse_args()
|
|
60
|
+
return args
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def setup_logging(verbose):
|
|
64
|
+
level = logging.DEBUG if verbose else logging.WARNING
|
|
65
|
+
logging.basicConfig(level=level)
|
|
66
|
+
# Remove pod metadata logs
|
|
67
|
+
logging.getLogger("kubernetes.client.rest").setLevel(logging.ERROR)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def __condition_transition_longer_than_threshold(
|
|
71
|
+
pod: V1Pod, condition: str, threshold: int
|
|
72
|
+
) -> bool:
|
|
73
|
+
time_finished = get_pod_condition(pod, condition).last_transition_time
|
|
74
|
+
time_now = datetime.now(tzutc())
|
|
75
|
+
|
|
76
|
+
# convert total seconds since completion to minutes
|
|
77
|
+
since_minutes = (time_now - time_finished).total_seconds() / 60
|
|
78
|
+
|
|
79
|
+
return since_minutes > threshold
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _completed_longer_than_threshold(pod: V1Pod, threshold: int) -> bool:
|
|
83
|
+
return __condition_transition_longer_than_threshold(
|
|
84
|
+
pod, "ContainersReady", threshold
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _scheduled_longer_than_threshold(pod: V1Pod, threshold: int) -> bool:
|
|
89
|
+
return __condition_transition_longer_than_threshold(pod, "PodScheduled", threshold)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def terminate_pods(pods: Sequence[V1Pod], kube_client) -> tuple:
|
|
93
|
+
successes = []
|
|
94
|
+
errors = []
|
|
95
|
+
|
|
96
|
+
for pod in pods:
|
|
97
|
+
try:
|
|
98
|
+
kube_client.core.delete_namespaced_pod(
|
|
99
|
+
name=pod.metadata.name,
|
|
100
|
+
namespace=pod.metadata.namespace,
|
|
101
|
+
grace_period_seconds=0,
|
|
102
|
+
propagation_policy="Background",
|
|
103
|
+
)
|
|
104
|
+
successes.append(pod.metadata.name)
|
|
105
|
+
except Exception as e:
|
|
106
|
+
errors.append((pod.metadata.name, e))
|
|
107
|
+
|
|
108
|
+
return (successes, errors)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def main():
|
|
112
|
+
args = parse_args()
|
|
113
|
+
setup_logging(args.verbose)
|
|
114
|
+
|
|
115
|
+
kube_client = KubeClient()
|
|
116
|
+
pods = get_all_pods(kube_client, args.namespace)
|
|
117
|
+
|
|
118
|
+
allowed_uptime_minutes = args.minutes
|
|
119
|
+
allowed_error_minutes = args.error_minutes
|
|
120
|
+
allowed_pending_minues = args.pending_minutes
|
|
121
|
+
|
|
122
|
+
completed_pods = []
|
|
123
|
+
errored_pods = []
|
|
124
|
+
pending_pods = []
|
|
125
|
+
|
|
126
|
+
for pod in pods:
|
|
127
|
+
if is_pod_completed(pod) and _completed_longer_than_threshold(
|
|
128
|
+
pod, allowed_uptime_minutes
|
|
129
|
+
):
|
|
130
|
+
completed_pods.append(pod)
|
|
131
|
+
elif (
|
|
132
|
+
# this is currently optional
|
|
133
|
+
allowed_error_minutes is not None
|
|
134
|
+
# there's no direct way to get what type of "bad" state these Pods ended up
|
|
135
|
+
# (kubectl looks at phase and then container statuses to give something descriptive)
|
|
136
|
+
# but, in the end, we really just care that a Pod is in a Failed phase
|
|
137
|
+
and pod.status.phase == "Failed"
|
|
138
|
+
):
|
|
139
|
+
try:
|
|
140
|
+
# and that said Pod has been around for a while (generally longer than we'd leave
|
|
141
|
+
# Pods that exited sucessfully)
|
|
142
|
+
# NOTE: we do this in a try-except since we're intermittently seeing pods in an error
|
|
143
|
+
# state without a PodScheduled condition (even though that should be impossible)
|
|
144
|
+
# this is not ideal, but its fine to skip these since this isn't a critical process
|
|
145
|
+
if _scheduled_longer_than_threshold(pod, allowed_error_minutes):
|
|
146
|
+
errored_pods.append(pod)
|
|
147
|
+
except AttributeError:
|
|
148
|
+
log.exception(
|
|
149
|
+
f"Unable to check {pod.metadata.name}'s schedule time. Pod status: {pod.status}.'"
|
|
150
|
+
)
|
|
151
|
+
elif (
|
|
152
|
+
# this is currently optional
|
|
153
|
+
allowed_pending_minues is not None
|
|
154
|
+
and pod.status.phase == "Pending"
|
|
155
|
+
):
|
|
156
|
+
try:
|
|
157
|
+
if _scheduled_longer_than_threshold(pod, allowed_pending_minues):
|
|
158
|
+
pending_pods.append(pod)
|
|
159
|
+
except AttributeError:
|
|
160
|
+
log.exception(
|
|
161
|
+
f"Unable to check {pod.metadata.name}'s schedule time. Pod status: {pod.status}.'"
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
if not (completed_pods or errored_pods or pending_pods):
|
|
165
|
+
log.debug("No pods to terminate.")
|
|
166
|
+
sys.exit(0)
|
|
167
|
+
|
|
168
|
+
if args.dry_run:
|
|
169
|
+
log.debug(
|
|
170
|
+
"Dry run would have terminated the following completed pods:\n "
|
|
171
|
+
+ "\n ".join([pod.metadata.name for pod in completed_pods])
|
|
172
|
+
)
|
|
173
|
+
log.debug(
|
|
174
|
+
"Dry run would have terminated the following errored pods:\n "
|
|
175
|
+
+ "\n ".join([pod.metadata.name for pod in errored_pods])
|
|
176
|
+
)
|
|
177
|
+
log.debug(
|
|
178
|
+
"Dry run would have terminated the following pending pods:\n "
|
|
179
|
+
+ "\n ".join([pod.metadata.name for pod in pending_pods])
|
|
180
|
+
)
|
|
181
|
+
sys.exit(0)
|
|
182
|
+
|
|
183
|
+
completed_successes, completed_errors = terminate_pods(completed_pods, kube_client)
|
|
184
|
+
errored_successes, errored_errors = terminate_pods(errored_pods, kube_client)
|
|
185
|
+
pending_successes, pending_errors = terminate_pods(pending_pods, kube_client)
|
|
186
|
+
|
|
187
|
+
successes = {
|
|
188
|
+
"completed": completed_successes,
|
|
189
|
+
"errored": errored_successes,
|
|
190
|
+
"pending": pending_successes,
|
|
191
|
+
}
|
|
192
|
+
errors = {
|
|
193
|
+
"completed": completed_errors,
|
|
194
|
+
"errored": errored_errors,
|
|
195
|
+
"pending": pending_errors,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for typ, pod_names in successes.items():
|
|
199
|
+
if pod_names:
|
|
200
|
+
log.debug(
|
|
201
|
+
f"Successfully terminated the following {typ} pods:\n"
|
|
202
|
+
+ "\n ".join(pod_names)
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# we've only really seen this fail recently due to the k8s API being flaky and returning
|
|
206
|
+
# 404s for Pods that its returning to us when we get all Pods, so we just print the error
|
|
207
|
+
# here for now and don't exit with a non-zero exit code since, again, this isn't a critical
|
|
208
|
+
# process
|
|
209
|
+
for typ, pod_names_and_errors in errors.items():
|
|
210
|
+
if pod_names_and_errors:
|
|
211
|
+
log.error(
|
|
212
|
+
f"Failed to terminate the following {typ} pods:\n"
|
|
213
|
+
+ "\n ".join(
|
|
214
|
+
f"{pod_name}: {error}" for pod_name, error in pod_names_and_errors
|
|
215
|
+
)
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
if __name__ == "__main__":
|
|
220
|
+
main()
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
from typing import Tuple
|
|
6
|
+
|
|
7
|
+
import service_configuration_lib
|
|
8
|
+
|
|
9
|
+
from paasta_tools.long_running_service_tools import load_service_namespace_config
|
|
10
|
+
from paasta_tools.long_running_service_tools import ServiceNamespaceConfig
|
|
11
|
+
from paasta_tools.utils import compose_job_id
|
|
12
|
+
|
|
13
|
+
PUPPET_SERVICE_DIR = "/etc/nerve/puppet_services.d"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_puppet_services_that_run_here() -> Dict[str, List[str]]:
|
|
17
|
+
# find all files in the PUPPET_SERVICE_DIR, but discard broken symlinks
|
|
18
|
+
# this allows us to (de)register services on a machine by
|
|
19
|
+
# breaking/healing a symlink placed by Puppet.
|
|
20
|
+
puppet_service_dir_services = {}
|
|
21
|
+
if os.path.exists(PUPPET_SERVICE_DIR):
|
|
22
|
+
for service_name in os.listdir(PUPPET_SERVICE_DIR):
|
|
23
|
+
if not os.path.exists(os.path.join(PUPPET_SERVICE_DIR, service_name)):
|
|
24
|
+
continue
|
|
25
|
+
with open(os.path.join(PUPPET_SERVICE_DIR, service_name)) as f:
|
|
26
|
+
puppet_service_data = json.load(f)
|
|
27
|
+
puppet_service_dir_services[service_name] = puppet_service_data[
|
|
28
|
+
"namespaces"
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
return puppet_service_dir_services
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_puppet_services_running_here_for_nerve(
|
|
35
|
+
soa_dir: str,
|
|
36
|
+
) -> List[Tuple[str, ServiceNamespaceConfig]]:
|
|
37
|
+
puppet_services = []
|
|
38
|
+
for service, namespaces in sorted(get_puppet_services_that_run_here().items()):
|
|
39
|
+
for namespace in namespaces:
|
|
40
|
+
puppet_services.append(
|
|
41
|
+
_namespaced_get_classic_service_information_for_nerve(
|
|
42
|
+
service, namespace, soa_dir
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
return puppet_services
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _namespaced_get_classic_service_information_for_nerve(
|
|
49
|
+
name: str, namespace: str, soa_dir: str
|
|
50
|
+
) -> Tuple[str, ServiceNamespaceConfig]:
|
|
51
|
+
nerve_dict = load_service_namespace_config(name, namespace, soa_dir)
|
|
52
|
+
port_file = os.path.join(soa_dir, name, "port")
|
|
53
|
+
# If the namespace defines a port, prefer that, otherwise use the
|
|
54
|
+
# service wide port file.
|
|
55
|
+
nerve_dict["port"] = nerve_dict.get(
|
|
56
|
+
"port", None
|
|
57
|
+
) or service_configuration_lib.read_port(port_file)
|
|
58
|
+
nerve_name = compose_job_id(name, namespace)
|
|
59
|
+
return (nerve_name, nerve_dict)
|
paasta_tools/py.typed
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Marker file for PEP 561. The paasta package uses inline types.
|