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.
Files changed (348) hide show
  1. k8s_itests/__init__.py +0 -0
  2. k8s_itests/test_autoscaling.py +23 -0
  3. k8s_itests/utils.py +38 -0
  4. paasta_tools/__init__.py +20 -0
  5. paasta_tools/adhoc_tools.py +142 -0
  6. paasta_tools/api/__init__.py +13 -0
  7. paasta_tools/api/api.py +330 -0
  8. paasta_tools/api/api_docs/swagger.json +2323 -0
  9. paasta_tools/api/client.py +106 -0
  10. paasta_tools/api/settings.py +33 -0
  11. paasta_tools/api/tweens/__init__.py +6 -0
  12. paasta_tools/api/tweens/auth.py +125 -0
  13. paasta_tools/api/tweens/profiling.py +108 -0
  14. paasta_tools/api/tweens/request_logger.py +124 -0
  15. paasta_tools/api/views/__init__.py +13 -0
  16. paasta_tools/api/views/autoscaler.py +100 -0
  17. paasta_tools/api/views/exception.py +45 -0
  18. paasta_tools/api/views/flink.py +73 -0
  19. paasta_tools/api/views/instance.py +395 -0
  20. paasta_tools/api/views/pause_autoscaler.py +71 -0
  21. paasta_tools/api/views/remote_run.py +113 -0
  22. paasta_tools/api/views/resources.py +76 -0
  23. paasta_tools/api/views/service.py +35 -0
  24. paasta_tools/api/views/version.py +25 -0
  25. paasta_tools/apply_external_resources.py +79 -0
  26. paasta_tools/async_utils.py +109 -0
  27. paasta_tools/autoscaling/__init__.py +0 -0
  28. paasta_tools/autoscaling/autoscaling_service_lib.py +57 -0
  29. paasta_tools/autoscaling/forecasting.py +106 -0
  30. paasta_tools/autoscaling/max_all_k8s_services.py +41 -0
  31. paasta_tools/autoscaling/pause_service_autoscaler.py +77 -0
  32. paasta_tools/autoscaling/utils.py +52 -0
  33. paasta_tools/bounce_lib.py +184 -0
  34. paasta_tools/broadcast_log_to_services.py +62 -0
  35. paasta_tools/cassandracluster_tools.py +210 -0
  36. paasta_tools/check_autoscaler_max_instances.py +212 -0
  37. paasta_tools/check_cassandracluster_services_replication.py +35 -0
  38. paasta_tools/check_flink_services_health.py +203 -0
  39. paasta_tools/check_kubernetes_api.py +57 -0
  40. paasta_tools/check_kubernetes_services_replication.py +141 -0
  41. paasta_tools/check_oom_events.py +244 -0
  42. paasta_tools/check_services_replication_tools.py +324 -0
  43. paasta_tools/check_spark_jobs.py +234 -0
  44. paasta_tools/cleanup_kubernetes_cr.py +138 -0
  45. paasta_tools/cleanup_kubernetes_crd.py +145 -0
  46. paasta_tools/cleanup_kubernetes_jobs.py +344 -0
  47. paasta_tools/cleanup_tron_namespaces.py +96 -0
  48. paasta_tools/cli/__init__.py +13 -0
  49. paasta_tools/cli/authentication.py +85 -0
  50. paasta_tools/cli/cli.py +260 -0
  51. paasta_tools/cli/cmds/__init__.py +13 -0
  52. paasta_tools/cli/cmds/autoscale.py +143 -0
  53. paasta_tools/cli/cmds/check.py +334 -0
  54. paasta_tools/cli/cmds/cook_image.py +147 -0
  55. paasta_tools/cli/cmds/get_docker_image.py +76 -0
  56. paasta_tools/cli/cmds/get_image_version.py +172 -0
  57. paasta_tools/cli/cmds/get_latest_deployment.py +93 -0
  58. paasta_tools/cli/cmds/info.py +155 -0
  59. paasta_tools/cli/cmds/itest.py +117 -0
  60. paasta_tools/cli/cmds/list.py +66 -0
  61. paasta_tools/cli/cmds/list_clusters.py +42 -0
  62. paasta_tools/cli/cmds/list_deploy_queue.py +171 -0
  63. paasta_tools/cli/cmds/list_namespaces.py +84 -0
  64. paasta_tools/cli/cmds/local_run.py +1396 -0
  65. paasta_tools/cli/cmds/logs.py +1601 -0
  66. paasta_tools/cli/cmds/mark_for_deployment.py +1988 -0
  67. paasta_tools/cli/cmds/mesh_status.py +174 -0
  68. paasta_tools/cli/cmds/pause_service_autoscaler.py +107 -0
  69. paasta_tools/cli/cmds/push_to_registry.py +275 -0
  70. paasta_tools/cli/cmds/remote_run.py +252 -0
  71. paasta_tools/cli/cmds/rollback.py +347 -0
  72. paasta_tools/cli/cmds/secret.py +549 -0
  73. paasta_tools/cli/cmds/security_check.py +59 -0
  74. paasta_tools/cli/cmds/spark_run.py +1400 -0
  75. paasta_tools/cli/cmds/start_stop_restart.py +401 -0
  76. paasta_tools/cli/cmds/status.py +2302 -0
  77. paasta_tools/cli/cmds/validate.py +1012 -0
  78. paasta_tools/cli/cmds/wait_for_deployment.py +275 -0
  79. paasta_tools/cli/fsm/__init__.py +13 -0
  80. paasta_tools/cli/fsm/autosuggest.py +82 -0
  81. paasta_tools/cli/fsm/template/README.md +8 -0
  82. paasta_tools/cli/fsm/template/cookiecutter.json +7 -0
  83. paasta_tools/cli/fsm/template/{{cookiecutter.service}}/kubernetes-PROD.yaml +91 -0
  84. paasta_tools/cli/fsm/template/{{cookiecutter.service}}/monitoring.yaml +20 -0
  85. paasta_tools/cli/fsm/template/{{cookiecutter.service}}/service.yaml +8 -0
  86. paasta_tools/cli/fsm/template/{{cookiecutter.service}}/smartstack.yaml +6 -0
  87. paasta_tools/cli/fsm_cmd.py +121 -0
  88. paasta_tools/cli/paasta_tabcomplete.sh +23 -0
  89. paasta_tools/cli/schemas/adhoc_schema.json +199 -0
  90. paasta_tools/cli/schemas/autoscaling_schema.json +91 -0
  91. paasta_tools/cli/schemas/autotuned_defaults/cassandracluster_schema.json +37 -0
  92. paasta_tools/cli/schemas/autotuned_defaults/kubernetes_schema.json +89 -0
  93. paasta_tools/cli/schemas/deploy_schema.json +173 -0
  94. paasta_tools/cli/schemas/eks_schema.json +970 -0
  95. paasta_tools/cli/schemas/kubernetes_schema.json +970 -0
  96. paasta_tools/cli/schemas/rollback_schema.json +160 -0
  97. paasta_tools/cli/schemas/service_schema.json +25 -0
  98. paasta_tools/cli/schemas/smartstack_schema.json +322 -0
  99. paasta_tools/cli/schemas/tron_schema.json +699 -0
  100. paasta_tools/cli/utils.py +1118 -0
  101. paasta_tools/clusterman.py +21 -0
  102. paasta_tools/config_utils.py +385 -0
  103. paasta_tools/contrib/__init__.py +0 -0
  104. paasta_tools/contrib/bounce_log_latency_parser.py +68 -0
  105. paasta_tools/contrib/check_manual_oapi_changes.sh +24 -0
  106. paasta_tools/contrib/check_orphans.py +306 -0
  107. paasta_tools/contrib/create_dynamodb_table.py +35 -0
  108. paasta_tools/contrib/create_paasta_playground.py +105 -0
  109. paasta_tools/contrib/emit_allocated_cpu_metrics.py +50 -0
  110. paasta_tools/contrib/get_running_task_allocation.py +346 -0
  111. paasta_tools/contrib/habitat_fixer.py +86 -0
  112. paasta_tools/contrib/ide_helper.py +316 -0
  113. paasta_tools/contrib/is_pod_healthy_in_proxy.py +139 -0
  114. paasta_tools/contrib/is_pod_healthy_in_smartstack.py +50 -0
  115. paasta_tools/contrib/kill_bad_containers.py +109 -0
  116. paasta_tools/contrib/mass-deploy-tag.sh +44 -0
  117. paasta_tools/contrib/mock_patch_checker.py +86 -0
  118. paasta_tools/contrib/paasta_update_soa_memcpu.py +520 -0
  119. paasta_tools/contrib/render_template.py +129 -0
  120. paasta_tools/contrib/rightsizer_soaconfigs_update.py +348 -0
  121. paasta_tools/contrib/service_shard_remove.py +157 -0
  122. paasta_tools/contrib/service_shard_update.py +373 -0
  123. paasta_tools/contrib/shared_ip_check.py +77 -0
  124. paasta_tools/contrib/timeouts_metrics_prom.py +64 -0
  125. paasta_tools/delete_kubernetes_deployments.py +89 -0
  126. paasta_tools/deployment_utils.py +44 -0
  127. paasta_tools/docker_wrapper.py +234 -0
  128. paasta_tools/docker_wrapper_imports.py +13 -0
  129. paasta_tools/drain_lib.py +351 -0
  130. paasta_tools/dump_locally_running_services.py +71 -0
  131. paasta_tools/eks_tools.py +119 -0
  132. paasta_tools/envoy_tools.py +373 -0
  133. paasta_tools/firewall.py +504 -0
  134. paasta_tools/firewall_logging.py +154 -0
  135. paasta_tools/firewall_update.py +172 -0
  136. paasta_tools/flink_tools.py +345 -0
  137. paasta_tools/flinkeks_tools.py +90 -0
  138. paasta_tools/frameworks/__init__.py +0 -0
  139. paasta_tools/frameworks/adhoc_scheduler.py +71 -0
  140. paasta_tools/frameworks/constraints.py +87 -0
  141. paasta_tools/frameworks/native_scheduler.py +652 -0
  142. paasta_tools/frameworks/native_service_config.py +301 -0
  143. paasta_tools/frameworks/task_store.py +245 -0
  144. paasta_tools/generate_all_deployments +9 -0
  145. paasta_tools/generate_authenticating_services.py +94 -0
  146. paasta_tools/generate_deployments_for_service.py +255 -0
  147. paasta_tools/generate_services_file.py +114 -0
  148. paasta_tools/generate_services_yaml.py +30 -0
  149. paasta_tools/hacheck.py +76 -0
  150. paasta_tools/instance/__init__.py +0 -0
  151. paasta_tools/instance/hpa_metrics_parser.py +122 -0
  152. paasta_tools/instance/kubernetes.py +1362 -0
  153. paasta_tools/iptables.py +240 -0
  154. paasta_tools/kafkacluster_tools.py +143 -0
  155. paasta_tools/kubernetes/__init__.py +0 -0
  156. paasta_tools/kubernetes/application/__init__.py +0 -0
  157. paasta_tools/kubernetes/application/controller_wrappers.py +476 -0
  158. paasta_tools/kubernetes/application/tools.py +90 -0
  159. paasta_tools/kubernetes/bin/__init__.py +0 -0
  160. paasta_tools/kubernetes/bin/kubernetes_remove_evicted_pods.py +164 -0
  161. paasta_tools/kubernetes/bin/paasta_cleanup_remote_run_resources.py +135 -0
  162. paasta_tools/kubernetes/bin/paasta_cleanup_stale_nodes.py +181 -0
  163. paasta_tools/kubernetes/bin/paasta_secrets_sync.py +758 -0
  164. paasta_tools/kubernetes/remote_run.py +558 -0
  165. paasta_tools/kubernetes_tools.py +4679 -0
  166. paasta_tools/list_kubernetes_service_instances.py +128 -0
  167. paasta_tools/list_tron_namespaces.py +60 -0
  168. paasta_tools/long_running_service_tools.py +678 -0
  169. paasta_tools/mac_address.py +44 -0
  170. paasta_tools/marathon_dashboard.py +0 -0
  171. paasta_tools/mesos/__init__.py +0 -0
  172. paasta_tools/mesos/cfg.py +46 -0
  173. paasta_tools/mesos/cluster.py +60 -0
  174. paasta_tools/mesos/exceptions.py +59 -0
  175. paasta_tools/mesos/framework.py +77 -0
  176. paasta_tools/mesos/log.py +48 -0
  177. paasta_tools/mesos/master.py +306 -0
  178. paasta_tools/mesos/mesos_file.py +169 -0
  179. paasta_tools/mesos/parallel.py +52 -0
  180. paasta_tools/mesos/slave.py +115 -0
  181. paasta_tools/mesos/task.py +94 -0
  182. paasta_tools/mesos/util.py +69 -0
  183. paasta_tools/mesos/zookeeper.py +37 -0
  184. paasta_tools/mesos_maintenance.py +848 -0
  185. paasta_tools/mesos_tools.py +1051 -0
  186. paasta_tools/metrics/__init__.py +0 -0
  187. paasta_tools/metrics/metastatus_lib.py +1110 -0
  188. paasta_tools/metrics/metrics_lib.py +217 -0
  189. paasta_tools/monitoring/__init__.py +13 -0
  190. paasta_tools/monitoring/check_k8s_api_performance.py +110 -0
  191. paasta_tools/monitoring_tools.py +652 -0
  192. paasta_tools/monkrelaycluster_tools.py +146 -0
  193. paasta_tools/nrtsearchservice_tools.py +143 -0
  194. paasta_tools/nrtsearchserviceeks_tools.py +68 -0
  195. paasta_tools/oom_logger.py +321 -0
  196. paasta_tools/paasta_deploy_tron_jobs +3 -0
  197. paasta_tools/paasta_execute_docker_command.py +123 -0
  198. paasta_tools/paasta_native_serviceinit.py +21 -0
  199. paasta_tools/paasta_service_config_loader.py +201 -0
  200. paasta_tools/paastaapi/__init__.py +29 -0
  201. paasta_tools/paastaapi/api/__init__.py +3 -0
  202. paasta_tools/paastaapi/api/autoscaler_api.py +302 -0
  203. paasta_tools/paastaapi/api/default_api.py +569 -0
  204. paasta_tools/paastaapi/api/remote_run_api.py +604 -0
  205. paasta_tools/paastaapi/api/resources_api.py +157 -0
  206. paasta_tools/paastaapi/api/service_api.py +1736 -0
  207. paasta_tools/paastaapi/api_client.py +818 -0
  208. paasta_tools/paastaapi/apis/__init__.py +22 -0
  209. paasta_tools/paastaapi/configuration.py +455 -0
  210. paasta_tools/paastaapi/exceptions.py +137 -0
  211. paasta_tools/paastaapi/model/__init__.py +5 -0
  212. paasta_tools/paastaapi/model/adhoc_launch_history.py +176 -0
  213. paasta_tools/paastaapi/model/autoscaler_count_msg.py +176 -0
  214. paasta_tools/paastaapi/model/deploy_queue.py +178 -0
  215. paasta_tools/paastaapi/model/deploy_queue_service_instance.py +194 -0
  216. paasta_tools/paastaapi/model/envoy_backend.py +185 -0
  217. paasta_tools/paastaapi/model/envoy_location.py +184 -0
  218. paasta_tools/paastaapi/model/envoy_status.py +181 -0
  219. paasta_tools/paastaapi/model/flink_cluster_overview.py +188 -0
  220. paasta_tools/paastaapi/model/flink_config.py +173 -0
  221. paasta_tools/paastaapi/model/flink_job.py +186 -0
  222. paasta_tools/paastaapi/model/flink_job_details.py +192 -0
  223. paasta_tools/paastaapi/model/flink_jobs.py +175 -0
  224. paasta_tools/paastaapi/model/float_and_error.py +173 -0
  225. paasta_tools/paastaapi/model/hpa_metric.py +176 -0
  226. paasta_tools/paastaapi/model/inline_object.py +170 -0
  227. paasta_tools/paastaapi/model/inline_response200.py +170 -0
  228. paasta_tools/paastaapi/model/inline_response2001.py +170 -0
  229. paasta_tools/paastaapi/model/instance_bounce_status.py +200 -0
  230. paasta_tools/paastaapi/model/instance_mesh_status.py +186 -0
  231. paasta_tools/paastaapi/model/instance_status.py +220 -0
  232. paasta_tools/paastaapi/model/instance_status_adhoc.py +187 -0
  233. paasta_tools/paastaapi/model/instance_status_cassandracluster.py +173 -0
  234. paasta_tools/paastaapi/model/instance_status_flink.py +173 -0
  235. paasta_tools/paastaapi/model/instance_status_kafkacluster.py +173 -0
  236. paasta_tools/paastaapi/model/instance_status_kubernetes.py +263 -0
  237. paasta_tools/paastaapi/model/instance_status_kubernetes_autoscaling_status.py +187 -0
  238. paasta_tools/paastaapi/model/instance_status_kubernetes_v2.py +197 -0
  239. paasta_tools/paastaapi/model/instance_status_tron.py +204 -0
  240. paasta_tools/paastaapi/model/instance_tasks.py +182 -0
  241. paasta_tools/paastaapi/model/integer_and_error.py +173 -0
  242. paasta_tools/paastaapi/model/kubernetes_container.py +178 -0
  243. paasta_tools/paastaapi/model/kubernetes_container_v2.py +219 -0
  244. paasta_tools/paastaapi/model/kubernetes_healthcheck.py +176 -0
  245. paasta_tools/paastaapi/model/kubernetes_pod.py +201 -0
  246. paasta_tools/paastaapi/model/kubernetes_pod_event.py +176 -0
  247. paasta_tools/paastaapi/model/kubernetes_pod_v2.py +213 -0
  248. paasta_tools/paastaapi/model/kubernetes_replica_set.py +185 -0
  249. paasta_tools/paastaapi/model/kubernetes_version.py +202 -0
  250. paasta_tools/paastaapi/model/remote_run_outcome.py +189 -0
  251. paasta_tools/paastaapi/model/remote_run_start.py +185 -0
  252. paasta_tools/paastaapi/model/remote_run_stop.py +176 -0
  253. paasta_tools/paastaapi/model/remote_run_token.py +173 -0
  254. paasta_tools/paastaapi/model/resource.py +187 -0
  255. paasta_tools/paastaapi/model/resource_item.py +187 -0
  256. paasta_tools/paastaapi/model/resource_value.py +176 -0
  257. paasta_tools/paastaapi/model/smartstack_backend.py +191 -0
  258. paasta_tools/paastaapi/model/smartstack_location.py +181 -0
  259. paasta_tools/paastaapi/model/smartstack_status.py +181 -0
  260. paasta_tools/paastaapi/model/task_tail_lines.py +176 -0
  261. paasta_tools/paastaapi/model_utils.py +1879 -0
  262. paasta_tools/paastaapi/models/__init__.py +62 -0
  263. paasta_tools/paastaapi/rest.py +287 -0
  264. paasta_tools/prune_completed_pods.py +220 -0
  265. paasta_tools/puppet_service_tools.py +59 -0
  266. paasta_tools/py.typed +1 -0
  267. paasta_tools/remote_git.py +127 -0
  268. paasta_tools/run-paasta-api-in-dev-mode.py +57 -0
  269. paasta_tools/run-paasta-api-playground.py +51 -0
  270. paasta_tools/secret_providers/__init__.py +66 -0
  271. paasta_tools/secret_providers/vault.py +214 -0
  272. paasta_tools/secret_tools.py +277 -0
  273. paasta_tools/setup_istio_mesh.py +353 -0
  274. paasta_tools/setup_kubernetes_cr.py +412 -0
  275. paasta_tools/setup_kubernetes_crd.py +138 -0
  276. paasta_tools/setup_kubernetes_internal_crd.py +154 -0
  277. paasta_tools/setup_kubernetes_job.py +353 -0
  278. paasta_tools/setup_prometheus_adapter_config.py +1028 -0
  279. paasta_tools/setup_tron_namespace.py +248 -0
  280. paasta_tools/slack.py +75 -0
  281. paasta_tools/smartstack_tools.py +676 -0
  282. paasta_tools/spark_tools.py +283 -0
  283. paasta_tools/synapse_srv_namespaces_fact.py +42 -0
  284. paasta_tools/tron/__init__.py +0 -0
  285. paasta_tools/tron/client.py +158 -0
  286. paasta_tools/tron/tron_command_context.py +194 -0
  287. paasta_tools/tron/tron_timeutils.py +101 -0
  288. paasta_tools/tron_tools.py +1448 -0
  289. paasta_tools/utils.py +4307 -0
  290. paasta_tools/yaml_tools.py +44 -0
  291. paasta_tools-1.21.3.data/scripts/apply_external_resources.py +79 -0
  292. paasta_tools-1.21.3.data/scripts/bounce_log_latency_parser.py +68 -0
  293. paasta_tools-1.21.3.data/scripts/check_autoscaler_max_instances.py +212 -0
  294. paasta_tools-1.21.3.data/scripts/check_cassandracluster_services_replication.py +35 -0
  295. paasta_tools-1.21.3.data/scripts/check_flink_services_health.py +203 -0
  296. paasta_tools-1.21.3.data/scripts/check_kubernetes_api.py +57 -0
  297. paasta_tools-1.21.3.data/scripts/check_kubernetes_services_replication.py +141 -0
  298. paasta_tools-1.21.3.data/scripts/check_manual_oapi_changes.sh +24 -0
  299. paasta_tools-1.21.3.data/scripts/check_oom_events.py +244 -0
  300. paasta_tools-1.21.3.data/scripts/check_orphans.py +306 -0
  301. paasta_tools-1.21.3.data/scripts/check_spark_jobs.py +234 -0
  302. paasta_tools-1.21.3.data/scripts/cleanup_kubernetes_cr.py +138 -0
  303. paasta_tools-1.21.3.data/scripts/cleanup_kubernetes_crd.py +145 -0
  304. paasta_tools-1.21.3.data/scripts/cleanup_kubernetes_jobs.py +344 -0
  305. paasta_tools-1.21.3.data/scripts/create_dynamodb_table.py +35 -0
  306. paasta_tools-1.21.3.data/scripts/create_paasta_playground.py +105 -0
  307. paasta_tools-1.21.3.data/scripts/delete_kubernetes_deployments.py +89 -0
  308. paasta_tools-1.21.3.data/scripts/emit_allocated_cpu_metrics.py +50 -0
  309. paasta_tools-1.21.3.data/scripts/generate_all_deployments +9 -0
  310. paasta_tools-1.21.3.data/scripts/generate_authenticating_services.py +94 -0
  311. paasta_tools-1.21.3.data/scripts/generate_deployments_for_service.py +255 -0
  312. paasta_tools-1.21.3.data/scripts/generate_services_file.py +114 -0
  313. paasta_tools-1.21.3.data/scripts/generate_services_yaml.py +30 -0
  314. paasta_tools-1.21.3.data/scripts/get_running_task_allocation.py +346 -0
  315. paasta_tools-1.21.3.data/scripts/habitat_fixer.py +86 -0
  316. paasta_tools-1.21.3.data/scripts/ide_helper.py +316 -0
  317. paasta_tools-1.21.3.data/scripts/is_pod_healthy_in_proxy.py +139 -0
  318. paasta_tools-1.21.3.data/scripts/is_pod_healthy_in_smartstack.py +50 -0
  319. paasta_tools-1.21.3.data/scripts/kill_bad_containers.py +109 -0
  320. paasta_tools-1.21.3.data/scripts/kubernetes_remove_evicted_pods.py +164 -0
  321. paasta_tools-1.21.3.data/scripts/mass-deploy-tag.sh +44 -0
  322. paasta_tools-1.21.3.data/scripts/mock_patch_checker.py +86 -0
  323. paasta_tools-1.21.3.data/scripts/paasta_cleanup_remote_run_resources.py +135 -0
  324. paasta_tools-1.21.3.data/scripts/paasta_cleanup_stale_nodes.py +181 -0
  325. paasta_tools-1.21.3.data/scripts/paasta_deploy_tron_jobs +3 -0
  326. paasta_tools-1.21.3.data/scripts/paasta_execute_docker_command.py +123 -0
  327. paasta_tools-1.21.3.data/scripts/paasta_secrets_sync.py +758 -0
  328. paasta_tools-1.21.3.data/scripts/paasta_tabcomplete.sh +23 -0
  329. paasta_tools-1.21.3.data/scripts/paasta_update_soa_memcpu.py +520 -0
  330. paasta_tools-1.21.3.data/scripts/render_template.py +129 -0
  331. paasta_tools-1.21.3.data/scripts/rightsizer_soaconfigs_update.py +348 -0
  332. paasta_tools-1.21.3.data/scripts/service_shard_remove.py +157 -0
  333. paasta_tools-1.21.3.data/scripts/service_shard_update.py +373 -0
  334. paasta_tools-1.21.3.data/scripts/setup_istio_mesh.py +353 -0
  335. paasta_tools-1.21.3.data/scripts/setup_kubernetes_cr.py +412 -0
  336. paasta_tools-1.21.3.data/scripts/setup_kubernetes_crd.py +138 -0
  337. paasta_tools-1.21.3.data/scripts/setup_kubernetes_internal_crd.py +154 -0
  338. paasta_tools-1.21.3.data/scripts/setup_kubernetes_job.py +353 -0
  339. paasta_tools-1.21.3.data/scripts/setup_prometheus_adapter_config.py +1028 -0
  340. paasta_tools-1.21.3.data/scripts/shared_ip_check.py +77 -0
  341. paasta_tools-1.21.3.data/scripts/synapse_srv_namespaces_fact.py +42 -0
  342. paasta_tools-1.21.3.data/scripts/timeouts_metrics_prom.py +64 -0
  343. paasta_tools-1.21.3.dist-info/LICENSE +201 -0
  344. paasta_tools-1.21.3.dist-info/METADATA +74 -0
  345. paasta_tools-1.21.3.dist-info/RECORD +348 -0
  346. paasta_tools-1.21.3.dist-info/WHEEL +5 -0
  347. paasta_tools-1.21.3.dist-info/entry_points.txt +20 -0
  348. paasta_tools-1.21.3.dist-info/top_level.txt +2 -0
@@ -0,0 +1,301 @@
1
+ #!/usr/bin/env python
2
+ import copy
3
+ from typing import Any
4
+ from typing import cast
5
+ from typing import List
6
+ from typing import Optional
7
+
8
+ from mypy_extensions import TypedDict
9
+
10
+ from paasta_tools.long_running_service_tools import load_service_namespace_config
11
+ from paasta_tools.long_running_service_tools import LongRunningServiceConfig
12
+ from paasta_tools.long_running_service_tools import LongRunningServiceConfigDict
13
+ from paasta_tools.long_running_service_tools import ServiceNamespaceConfig
14
+ from paasta_tools.utils import BranchDictV2
15
+ from paasta_tools.utils import compose_job_id
16
+ from paasta_tools.utils import Constraint # noqa, imported for typing.
17
+ from paasta_tools.utils import DEFAULT_SOA_DIR
18
+ from paasta_tools.utils import DockerParameter
19
+ from paasta_tools.utils import get_code_sha_from_dockerurl
20
+ from paasta_tools.utils import get_config_hash
21
+ from paasta_tools.utils import load_service_instance_config
22
+ from paasta_tools.utils import load_v2_deployments_json
23
+ from paasta_tools.utils import SystemPaastaConfig
24
+
25
+
26
+ MESOS_TASK_SPACER = "."
27
+
28
+
29
+ VolumeInfo = TypedDict(
30
+ "VolumeInfo", {"container_path": str, "host_path": str, "mode": str}
31
+ )
32
+
33
+ _Docker_PortMapping = TypedDict(
34
+ "_Docker_PortMapping", {"host_port": int, "container_port": int, "protocol": str}
35
+ )
36
+
37
+ DockerInfo = TypedDict(
38
+ "DockerInfo",
39
+ {
40
+ "image": str,
41
+ "network": str,
42
+ "port_mappings": List[_Docker_PortMapping],
43
+ "parameters": List[DockerParameter],
44
+ },
45
+ )
46
+
47
+ ContainerInfo = TypedDict(
48
+ "ContainerInfo", {"type": str, "docker": DockerInfo, "volumes": List[VolumeInfo]}
49
+ )
50
+
51
+
52
+ _CommandInfo_URI = TypedDict(
53
+ "_CommandInfo_URI",
54
+ {
55
+ "value": str,
56
+ "executable": bool,
57
+ "extract": bool,
58
+ "cache": bool,
59
+ "output_file": str,
60
+ },
61
+ total=False,
62
+ )
63
+
64
+ CommandInfo = TypedDict(
65
+ "CommandInfo",
66
+ {
67
+ "uris": List[_CommandInfo_URI],
68
+ "environment": Any,
69
+ "shell": bool,
70
+ "value": str,
71
+ "arguments": List[str],
72
+ "user": str,
73
+ },
74
+ total=False,
75
+ )
76
+
77
+ Value_Scalar = TypedDict("Value_Scalar", {"value": float})
78
+
79
+ Value_Range = TypedDict("Value_Range", {"begin": int, "end": int})
80
+
81
+ Value_Ranges = TypedDict("Value_Ranges", {"range": List[Value_Range]})
82
+
83
+ Resource = TypedDict(
84
+ "Resource",
85
+ {"name": str, "type": str, "scalar": Value_Scalar, "ranges": Value_Ranges},
86
+ total=False,
87
+ )
88
+
89
+
90
+ TaskID = TypedDict("TaskID", {"value": str})
91
+
92
+ SlaveID = TypedDict("SlaveID", {"value": str})
93
+
94
+
95
+ class TaskInfoBase(TypedDict):
96
+ name: str
97
+ task_id: TaskID
98
+ agent_id: SlaveID
99
+ resources: List[Resource]
100
+
101
+
102
+ class TaskInfo(TaskInfoBase):
103
+ container: ContainerInfo
104
+ command: CommandInfo
105
+
106
+
107
+ class NativeServiceConfigDict(LongRunningServiceConfigDict):
108
+ pass
109
+
110
+
111
+ class NativeServiceConfig(LongRunningServiceConfig):
112
+ config_dict: NativeServiceConfigDict
113
+ config_filename_prefix = "paasta_native"
114
+
115
+ def __init__(
116
+ self,
117
+ service: str,
118
+ instance: str,
119
+ cluster: str,
120
+ config_dict: NativeServiceConfigDict,
121
+ branch_dict: Optional[BranchDictV2],
122
+ soa_dir: str,
123
+ service_namespace_config: Optional[ServiceNamespaceConfig] = None,
124
+ ) -> None:
125
+ super().__init__(
126
+ cluster=cluster,
127
+ instance=instance,
128
+ service=service,
129
+ config_dict=config_dict,
130
+ branch_dict=branch_dict,
131
+ soa_dir=soa_dir,
132
+ )
133
+ # service_namespace_config may be omitted/set to None at first, then set
134
+ # after initializing. e.g. we do this in load_paasta_native_job_config
135
+ # so we can call get_nerve_namespace() to figure out what SNC to read.
136
+ # It may also be set to None if this service is not in nerve.
137
+ if service_namespace_config is not None:
138
+ self.service_namespace_config = service_namespace_config
139
+ else:
140
+ self.service_namespace_config = ServiceNamespaceConfig()
141
+
142
+ def task_name(self, base_task: TaskInfo) -> str:
143
+ code_sha = get_code_sha_from_dockerurl(
144
+ base_task["container"]["docker"]["image"]
145
+ )
146
+
147
+ filled_in_task = copy.deepcopy(base_task)
148
+ filled_in_task["name"] = ""
149
+ filled_in_task["task_id"] = {"value": ""}
150
+ filled_in_task["agent_id"] = {"value": ""}
151
+
152
+ config_hash = get_config_hash(
153
+ filled_in_task, force_bounce=self.get_force_bounce()
154
+ )
155
+
156
+ return compose_job_id(
157
+ self.service,
158
+ self.instance,
159
+ git_hash=code_sha,
160
+ config_hash=config_hash,
161
+ spacer=MESOS_TASK_SPACER,
162
+ )
163
+
164
+ def base_task(
165
+ self, system_paasta_config: SystemPaastaConfig, portMappings=True
166
+ ) -> TaskInfo:
167
+ """Return a TaskInfo Dict with all the fields corresponding to the
168
+ configuration filled in.
169
+
170
+ Does not include task.agent_id or a task.id; those need to be
171
+ computed separately.
172
+ """
173
+ docker_volumes = self.get_volumes(
174
+ system_volumes=system_paasta_config.get_volumes(),
175
+ )
176
+ task: TaskInfo = {
177
+ "name": "",
178
+ "task_id": {"value": ""},
179
+ "agent_id": {"value": ""},
180
+ "container": {
181
+ "type": "DOCKER",
182
+ "docker": {
183
+ "image": self.get_docker_url(),
184
+ "parameters": [
185
+ {"key": param["key"], "value": param["value"]}
186
+ for param in self.format_docker_parameters()
187
+ ],
188
+ "network": self.get_mesos_network_mode(),
189
+ "port_mappings": [],
190
+ },
191
+ "volumes": [
192
+ {
193
+ "container_path": volume["containerPath"],
194
+ "host_path": volume["hostPath"],
195
+ "mode": volume["mode"].upper(),
196
+ }
197
+ for volume in docker_volumes
198
+ ],
199
+ },
200
+ "command": {
201
+ "value": str(self.get_cmd()),
202
+ "uris": [
203
+ {
204
+ "value": system_paasta_config.get_dockercfg_location(),
205
+ "extract": False,
206
+ }
207
+ ],
208
+ },
209
+ "resources": [
210
+ {
211
+ "name": "cpus",
212
+ "type": "SCALAR",
213
+ "scalar": {"value": self.get_cpus()},
214
+ },
215
+ {"name": "mem", "type": "SCALAR", "scalar": {"value": self.get_mem()}},
216
+ ],
217
+ }
218
+
219
+ if portMappings:
220
+ task["container"]["docker"]["port_mappings"] = [
221
+ {
222
+ "container_port": self.get_container_port(),
223
+ # filled by tasks_and_state_for_offer()
224
+ "host_port": 0,
225
+ "protocol": "tcp",
226
+ }
227
+ ]
228
+
229
+ task["resources"].append(
230
+ {
231
+ "name": "ports",
232
+ "type": "RANGES",
233
+ "ranges": {
234
+ # filled by tasks_and_state_for_offer
235
+ "range": [{"begin": 0, "end": 0}]
236
+ },
237
+ }
238
+ )
239
+
240
+ task["name"] = self.task_name(task)
241
+
242
+ return task
243
+
244
+ def get_mesos_network_mode(self) -> str:
245
+ return self.get_net().upper()
246
+
247
+
248
+ def load_paasta_native_job_config(
249
+ service: str,
250
+ instance: str,
251
+ cluster: str,
252
+ load_deployments: bool = True,
253
+ soa_dir: str = DEFAULT_SOA_DIR,
254
+ instance_type: str = "paasta_native",
255
+ config_overrides: Optional[NativeServiceConfigDict] = None,
256
+ ) -> NativeServiceConfig:
257
+ instance_config_dict = cast(
258
+ NativeServiceConfigDict,
259
+ load_service_instance_config(
260
+ service=service,
261
+ instance=instance,
262
+ instance_type=instance_type,
263
+ cluster=cluster,
264
+ soa_dir=soa_dir,
265
+ ),
266
+ )
267
+ branch_dict: Optional[BranchDictV2] = None
268
+ instance_config_dict.update(config_overrides or {})
269
+ if load_deployments:
270
+ deployments_json = load_v2_deployments_json(service, soa_dir=soa_dir)
271
+ temp_instance_config = NativeServiceConfig(
272
+ service=service,
273
+ cluster=cluster,
274
+ instance=instance,
275
+ config_dict=instance_config_dict,
276
+ branch_dict=None,
277
+ soa_dir=soa_dir,
278
+ )
279
+ branch = temp_instance_config.get_branch()
280
+ deploy_group = temp_instance_config.get_deploy_group()
281
+ branch_dict = deployments_json.get_branch_dict(service, branch, deploy_group)
282
+
283
+ service_config = NativeServiceConfig(
284
+ service=service,
285
+ cluster=cluster,
286
+ instance=instance,
287
+ config_dict=instance_config_dict,
288
+ branch_dict=branch_dict,
289
+ soa_dir=soa_dir,
290
+ )
291
+
292
+ service_namespace_config = load_service_namespace_config(
293
+ service=service, namespace=service_config.get_nerve_namespace(), soa_dir=soa_dir
294
+ )
295
+ service_config.service_namespace_config = service_namespace_config
296
+
297
+ return service_config
298
+
299
+
300
+ class UnknownNativeServiceError(Exception):
301
+ pass
@@ -0,0 +1,245 @@
1
+ import copy
2
+ import json
3
+ from typing import Any
4
+ from typing import Dict
5
+ from typing import Tuple
6
+ from typing import Type
7
+ from typing import TypeVar
8
+ from typing import Union
9
+
10
+ from kazoo.client import KazooClient
11
+ from kazoo.exceptions import BadVersionError
12
+ from kazoo.exceptions import NodeExistsError
13
+ from kazoo.exceptions import NoNodeError
14
+ from kazoo.protocol.states import ZnodeStat
15
+
16
+ from paasta_tools.utils import _log
17
+
18
+
19
+ class MesosTaskParametersIsImmutableError(Exception):
20
+ pass
21
+
22
+
23
+ _SelfT = TypeVar("_SelfT", bound="MesosTaskParameters")
24
+
25
+
26
+ class MesosTaskParameters:
27
+ health: Any
28
+ mesos_task_state: str
29
+ is_draining: bool
30
+ is_healthy: bool
31
+ offer: Any
32
+ resources: Any
33
+
34
+ def __init__(
35
+ self,
36
+ health=None,
37
+ mesos_task_state=None,
38
+ is_draining=None,
39
+ is_healthy=None,
40
+ offer=None,
41
+ resources=None,
42
+ ):
43
+ self.__dict__["health"] = health
44
+ self.__dict__["mesos_task_state"] = mesos_task_state
45
+ self.__dict__["is_draining"] = is_draining
46
+ self.__dict__["is_healthy"] = is_healthy
47
+ self.__dict__["offer"] = offer
48
+ self.__dict__["resources"] = resources
49
+
50
+ def __eq__(self, other):
51
+ return self.__dict__ == other.__dict__
52
+
53
+ def __repr__(self):
54
+ return "{}(\n {})".format(
55
+ type(self).__name__,
56
+ ",\n ".join(["%s=%r" % kv for kv in self.__dict__.items()]),
57
+ )
58
+
59
+ def __setattr__(self, name, value):
60
+ raise MesosTaskParametersIsImmutableError()
61
+
62
+ def __delattr__(self, name):
63
+ raise MesosTaskParametersIsImmutableError()
64
+
65
+ def merge(self: _SelfT, **kwargs) -> "MesosTaskParameters":
66
+ """Return a merged MesosTaskParameters object, where attributes in other take precedence over self."""
67
+
68
+ new_dict = copy.deepcopy(self.__dict__)
69
+ new_dict.update(kwargs)
70
+
71
+ return MesosTaskParameters(**new_dict)
72
+
73
+ @classmethod
74
+ def deserialize(cls: Type[_SelfT], serialized_params: Union[str, bytes]) -> _SelfT:
75
+ return cls(**json.loads(serialized_params))
76
+
77
+ def serialize(self):
78
+ return json.dumps(self.__dict__).encode("utf-8")
79
+
80
+
81
+ class TaskStore:
82
+ def __init__(self, service_name, instance_name, framework_id, system_paasta_config):
83
+ self.service_name = service_name
84
+ self.instance_name = instance_name
85
+ self.framework_id = framework_id
86
+ self.system_paasta_config = system_paasta_config
87
+
88
+ def get_task(self, task_id: str) -> MesosTaskParameters:
89
+ """Get task data for task_id. If we don't know about task_id, return None"""
90
+ raise NotImplementedError()
91
+
92
+ def get_all_tasks(self) -> Dict[str, MesosTaskParameters]:
93
+ """Returns a dictionary of task_id -> MesosTaskParameters for all known tasks."""
94
+ raise NotImplementedError()
95
+
96
+ def overwrite_task(self, task_id: str, params: MesosTaskParameters) -> None:
97
+ raise NotImplementedError()
98
+
99
+ def add_task_if_doesnt_exist(self, task_id: str, **kwargs) -> None:
100
+ """Add a task if it does not already exist. If it already exists, do nothing."""
101
+ if self.get_task(task_id) is not None:
102
+ return
103
+ else:
104
+ self.overwrite_task(task_id, MesosTaskParameters(**kwargs))
105
+
106
+ def update_task(self, task_id: str, **kwargs) -> MesosTaskParameters:
107
+ existing_task = self.get_task(task_id)
108
+ if existing_task:
109
+ merged_params = existing_task.merge(**kwargs)
110
+ else:
111
+ merged_params = MesosTaskParameters(**kwargs)
112
+
113
+ self.overwrite_task(task_id, merged_params)
114
+ return merged_params
115
+
116
+ def garbage_collect_old_tasks(self, max_dead_task_age: float) -> None:
117
+ # TODO: call me.
118
+ # TODO: implement in base class.
119
+ raise NotImplementedError()
120
+
121
+ def close(self):
122
+ pass
123
+
124
+
125
+ class DictTaskStore(TaskStore):
126
+ def __init__(self, service_name, instance_name, framework_id, system_paasta_config):
127
+ self.tasks: Dict[str, MesosTaskParameters] = {}
128
+ super().__init__(
129
+ service_name, instance_name, framework_id, system_paasta_config
130
+ )
131
+
132
+ def get_task(self, task_id: str) -> MesosTaskParameters:
133
+ return self.tasks.get(task_id)
134
+
135
+ def get_all_tasks(self) -> Dict[str, MesosTaskParameters]:
136
+ """Returns a dictionary of task_id -> MesosTaskParameters for all known tasks."""
137
+ return dict(self.tasks)
138
+
139
+ def overwrite_task(self, task_id: str, params: MesosTaskParameters) -> None:
140
+ # serialize/deserialize to make sure the returned values are the same format as ZKTaskStore.
141
+ self.tasks[task_id] = MesosTaskParameters.deserialize(params.serialize())
142
+
143
+
144
+ class ZKTaskStore(TaskStore):
145
+ def __init__(self, service_name, instance_name, framework_id, system_paasta_config):
146
+ super().__init__(
147
+ service_name, instance_name, framework_id, system_paasta_config
148
+ )
149
+ self.zk_hosts = system_paasta_config.get_zk_hosts()
150
+
151
+ # For some reason, I could not get the code suggested by this SO post to work to ensure_path on the chroot.
152
+ # https://stackoverflow.com/a/32785625/25327
153
+ # Plus, it just felt dirty to modify instance attributes of a running connection, especially given that
154
+ # KazooClient.set_hosts() doesn't allow you to change the chroot. Must be for a good reason.
155
+
156
+ chroot = f"task_store/{service_name}/{instance_name}/{framework_id}"
157
+
158
+ temp_zk_client = KazooClient(hosts=self.zk_hosts)
159
+ temp_zk_client.start()
160
+ temp_zk_client.ensure_path(chroot)
161
+ temp_zk_client.stop()
162
+ temp_zk_client.close()
163
+
164
+ self.zk_client = KazooClient(hosts=f"{self.zk_hosts}/{chroot}")
165
+ self.zk_client.start()
166
+ self.zk_client.ensure_path("/")
167
+
168
+ def close(self):
169
+ self.zk_client.stop()
170
+ self.zk_client.close()
171
+
172
+ def get_task(self, task_id: str) -> MesosTaskParameters:
173
+ params, stat = self._get_task(task_id)
174
+ return params
175
+
176
+ def _get_task(self, task_id: str) -> Tuple[MesosTaskParameters, ZnodeStat]:
177
+ """Like get_task, but also returns the ZnodeStat that self.zk_client.get() returns"""
178
+ try:
179
+ data, stat = self.zk_client.get("/%s" % task_id)
180
+ return MesosTaskParameters.deserialize(data), stat
181
+ except NoNodeError:
182
+ return None, None
183
+ except json.decoder.JSONDecodeError:
184
+ _log(
185
+ service=self.service_name,
186
+ instance=self.instance_name,
187
+ level="debug",
188
+ component="deploy",
189
+ line=f"Warning: found non-json-decodable value in zookeeper for task {task_id}: {data}",
190
+ )
191
+ return None, None
192
+
193
+ def get_all_tasks(self):
194
+ all_tasks = {}
195
+
196
+ for child_path in self.zk_client.get_children("/"):
197
+ task_id = self._task_id_from_zk_path(child_path)
198
+ params = self.get_task(task_id)
199
+ # sometimes there are bogus child ZK nodes. Ignore them.
200
+ if params is not None:
201
+ all_tasks[task_id] = params
202
+
203
+ return all_tasks
204
+
205
+ def update_task(self, task_id: str, **kwargs):
206
+ retry = True
207
+ while retry:
208
+ retry = False
209
+ existing_task, stat = self._get_task(task_id)
210
+
211
+ zk_path = self._zk_path_from_task_id(task_id)
212
+ if existing_task:
213
+ merged_params = existing_task.merge(**kwargs)
214
+ try:
215
+ self.zk_client.set(
216
+ zk_path, merged_params.serialize(), version=stat.version
217
+ )
218
+ except BadVersionError:
219
+ retry = True
220
+ else:
221
+ merged_params = MesosTaskParameters(**kwargs)
222
+ try:
223
+ self.zk_client.create(zk_path, merged_params.serialize())
224
+ except NodeExistsError:
225
+ retry = True
226
+
227
+ return merged_params
228
+
229
+ def overwrite_task(
230
+ self, task_id: str, params: MesosTaskParameters, version=-1
231
+ ) -> None:
232
+ try:
233
+ self.zk_client.set(
234
+ self._zk_path_from_task_id(task_id), params.serialize(), version=version
235
+ )
236
+ except NoNodeError:
237
+ self.zk_client.create(
238
+ self._zk_path_from_task_id(task_id), params.serialize()
239
+ )
240
+
241
+ def _zk_path_from_task_id(self, task_id: str) -> str:
242
+ return "/%s" % task_id
243
+
244
+ def _task_id_from_zk_path(self, zk_path: str) -> str:
245
+ return zk_path.lstrip("/")
@@ -0,0 +1,9 @@
1
+ #!/bin/bash
2
+ #
3
+ # Generates all the per-service deployments.json files
4
+ #
5
+
6
+ set -eo pipefail
7
+
8
+ # xargs will return 0 if everything went ok, but 12X if something else went wrong
9
+ paasta list | shuf | xargs -n 1 -r -P 4 generate_deployments_for_service -s
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2015-2016 Yelp Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """
16
+ A simple script to enumerate all services participating in authenticated
17
+ communications, and list them in a YAML/JSON file.
18
+ """
19
+ import argparse
20
+ import glob
21
+ import logging
22
+ import os
23
+ from typing import Dict
24
+ from typing import List
25
+ from typing import Set
26
+
27
+ from paasta_tools import yaml_tools as yaml
28
+ from paasta_tools.utils import DEFAULT_SOA_DIR
29
+ from paasta_tools.utils import load_system_paasta_config
30
+ from paasta_tools.utils import write_json_configuration_file
31
+ from paasta_tools.utils import write_yaml_configuration_file
32
+
33
+
34
+ AUTHORIZATION_CONFIG_FILE = "authorization.yaml"
35
+
36
+
37
+ def list_services_in_authz_config(config_path: str) -> Set[str]:
38
+ auth_config: dict = {}
39
+ try:
40
+ with open(config_path) as f:
41
+ auth_config = yaml.safe_load(f)
42
+ except Exception as e:
43
+ logging.warning(f"Issue loading {config_path}: {e}")
44
+ return {
45
+ service
46
+ for rule in auth_config.get("authorization", {}).get("rules", [])
47
+ for service in rule.get("identity_groups", {}).get("services", [])
48
+ }
49
+
50
+
51
+ def enumerate_authenticating_services() -> Dict[str, List[str]]:
52
+ result = set()
53
+ config_path_pattern = os.path.join(DEFAULT_SOA_DIR, "*", AUTHORIZATION_CONFIG_FILE)
54
+ for authz_config in glob.glob(config_path_pattern):
55
+ result.update(list_services_in_authz_config(authz_config))
56
+ result.update(load_system_paasta_config().get_always_authenticating_services())
57
+ return {"services": sorted(result)}
58
+
59
+
60
+ def parse_args():
61
+ parser = argparse.ArgumentParser(description="")
62
+ parser.add_argument(
63
+ "-o",
64
+ "--output",
65
+ help="Output filepath",
66
+ dest="output_filename",
67
+ required=True,
68
+ )
69
+ parser.add_argument(
70
+ "-f",
71
+ "--format",
72
+ help="Output format. Defaults to %(default)s",
73
+ dest="output_format",
74
+ choices=["yaml", "json"],
75
+ default="yaml",
76
+ )
77
+ args = parser.parse_args()
78
+ return args
79
+
80
+
81
+ def main():
82
+ args = parse_args()
83
+ if args.output_format == "yaml":
84
+ writer = write_yaml_configuration_file
85
+ elif args.output_format == "json":
86
+ writer = write_json_configuration_file
87
+ else:
88
+ raise NotImplementedError(f"Unknown format: {args.output_format}")
89
+ configuration = enumerate_authenticating_services()
90
+ writer(filename=args.output_filename, configuration=configuration)
91
+
92
+
93
+ if __name__ == "__main__":
94
+ main()