render 1.0.1__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 (799) hide show
  1. render/__init__.py +98 -0
  2. render/client/__init__.py +119 -0
  3. render/client/client.py +110 -0
  4. render/client/errors.py +39 -0
  5. render/client/sse.py +90 -0
  6. render/client/sse_sync.py +20 -0
  7. render/client/tests/__init__.py +0 -0
  8. render/client/tests/test_client.py +379 -0
  9. render/client/tests/test_method_parity.py +118 -0
  10. render/client/tests/test_render.py +52 -0
  11. render/client/tests/test_sse.py +67 -0
  12. render/client/tests/test_util.py +303 -0
  13. render/client/tests/test_util_sync.py +73 -0
  14. render/client/tests/test_workflows_sync.py +313 -0
  15. render/client/types.py +52 -0
  16. render/client/util.py +285 -0
  17. render/client/util_sync.py +83 -0
  18. render/client/workflows.py +363 -0
  19. render/client/workflows_sync.py +298 -0
  20. render/experimental/__init__.py +37 -0
  21. render/experimental/experimental.py +93 -0
  22. render/experimental/experimental_sync.py +78 -0
  23. render/experimental/key_value/__init__.py +33 -0
  24. render/experimental/key_value/api.py +243 -0
  25. render/experimental/key_value/compare.py +83 -0
  26. render/experimental/key_value/provider.py +285 -0
  27. render/experimental/key_value/tests/__init__.py +0 -0
  28. render/experimental/key_value/tests/test_api.py +371 -0
  29. render/experimental/key_value/tests/test_compare.py +136 -0
  30. render/experimental/key_value/tests/test_provider.py +1016 -0
  31. render/experimental/key_value/types.py +130 -0
  32. render/experimental/key_value/utils.py +11 -0
  33. render/experimental/object/__init__.py +38 -0
  34. render/experimental/object/api.py +250 -0
  35. render/experimental/object/api_sync.py +250 -0
  36. render/experimental/object/client.py +545 -0
  37. render/experimental/object/client_sync.py +547 -0
  38. render/experimental/object/e2e_helpers.py +78 -0
  39. render/experimental/object/tests/__init__.py +0 -0
  40. render/experimental/object/tests/test_client.py +228 -0
  41. render/experimental/object/tests/test_e2e.py +125 -0
  42. render/experimental/object/types.py +87 -0
  43. render/experimental/sandbox/__init__.py +31 -0
  44. render/experimental/sandbox/_tar.py +278 -0
  45. render/experimental/sandbox/api.py +518 -0
  46. render/experimental/sandbox/api_sync.py +514 -0
  47. render/experimental/sandbox/client.py +168 -0
  48. render/experimental/sandbox/client_sync.py +170 -0
  49. render/experimental/sandbox/errors.py +37 -0
  50. render/experimental/sandbox/files.py +378 -0
  51. render/experimental/sandbox/tests/__init__.py +0 -0
  52. render/experimental/sandbox/tests/test_client.py +802 -0
  53. render/experimental/sandbox/tests/test_download.py +728 -0
  54. render/experimental/sandbox/tests/test_e2e.py +252 -0
  55. render/experimental/sandbox/tests/test_tar.py +153 -0
  56. render/experimental/sandbox/tests/test_types.py +57 -0
  57. render/experimental/sandbox/types.py +46 -0
  58. render/public_api/__init__.py +8 -0
  59. render/public_api/api/__init__.py +1 -0
  60. render/public_api/api/artifact_sources/__init__.py +1 -0
  61. render/public_api/api/artifact_sources/add_or_update_artifact_source_secret_file.py +252 -0
  62. render/public_api/api/artifact_sources/create_artifact_source.py +243 -0
  63. render/public_api/api/artifact_sources/delete_artifact_source.py +188 -0
  64. render/public_api/api/artifact_sources/delete_artifact_source_env_var.py +223 -0
  65. render/public_api/api/artifact_sources/delete_artifact_source_secret_file.py +223 -0
  66. render/public_api/api/artifact_sources/get_artifact_source.py +185 -0
  67. render/public_api/api/artifact_sources/get_env_vars_for_artifact_source.py +241 -0
  68. render/public_api/api/artifact_sources/link_artifact_source_to_env_group.py +215 -0
  69. render/public_api/api/artifact_sources/list_artifact_sources.py +338 -0
  70. render/public_api/api/artifact_sources/list_artifacts_in_artifact_source.py +241 -0
  71. render/public_api/api/artifact_sources/list_secret_files_for_artifact_source.py +241 -0
  72. render/public_api/api/artifact_sources/retrieve_artifact_source_env_var.py +225 -0
  73. render/public_api/api/artifact_sources/retrieve_artifact_source_secret_file.py +225 -0
  74. render/public_api/api/artifact_sources/unlink_artifact_source_from_env_group.py +209 -0
  75. render/public_api/api/artifact_sources/update_artifact_source.py +244 -0
  76. render/public_api/api/artifact_sources/update_artifact_source_env_var.py +257 -0
  77. render/public_api/api/artifact_sources/update_env_vars_for_artifact_source.py +245 -0
  78. render/public_api/api/artifact_sources/update_secret_files_for_artifact_source.py +255 -0
  79. render/public_api/api/audit_logs/__init__.py +1 -0
  80. render/public_api/api/audit_logs/list_organization_audit_logs.py +303 -0
  81. render/public_api/api/audit_logs/list_owner_audit_logs.py +303 -0
  82. render/public_api/api/blueprints/__init__.py +1 -0
  83. render/public_api/api/blueprints/disconnect_blueprint.py +210 -0
  84. render/public_api/api/blueprints/list_blueprint_syncs.py +241 -0
  85. render/public_api/api/blueprints/list_blueprints.py +251 -0
  86. render/public_api/api/blueprints/retrieve_blueprint.py +200 -0
  87. render/public_api/api/blueprints/update_blueprint.py +222 -0
  88. render/public_api/api/blueprints/validate_blueprint.py +217 -0
  89. render/public_api/api/custom_domains/__init__.py +1 -0
  90. render/public_api/api/custom_domains/create_custom_domain.py +242 -0
  91. render/public_api/api/custom_domains/delete_custom_domain.py +216 -0
  92. render/public_api/api/custom_domains/list_custom_domains.py +346 -0
  93. render/public_api/api/custom_domains/refresh_custom_domain.py +216 -0
  94. render/public_api/api/custom_domains/retrieve_custom_domain.py +218 -0
  95. render/public_api/api/dedicated_i_ps/__init__.py +1 -0
  96. render/public_api/api/dedicated_i_ps/create_dedicated_ip.py +234 -0
  97. render/public_api/api/dedicated_i_ps/delete_dedicated_ip.py +198 -0
  98. render/public_api/api/dedicated_i_ps/list_dedicated_ips.py +223 -0
  99. render/public_api/api/dedicated_i_ps/retrieve_dedicated_ip.py +200 -0
  100. render/public_api/api/dedicated_i_ps/update_dedicated_ip.py +244 -0
  101. render/public_api/api/deploys/__init__.py +1 -0
  102. render/public_api/api/deploys/cancel_deploy.py +216 -0
  103. render/public_api/api/deploys/create_deploy.py +231 -0
  104. render/public_api/api/deploys/list_deploys.py +377 -0
  105. render/public_api/api/deploys/retrieve_deploy.py +213 -0
  106. render/public_api/api/deploys/rollback_deploy.py +241 -0
  107. render/public_api/api/disks/__init__.py +1 -0
  108. render/public_api/api/disks/add_disk.py +222 -0
  109. render/public_api/api/disks/delete_disk.py +210 -0
  110. render/public_api/api/disks/list_disks.py +381 -0
  111. render/public_api/api/disks/list_snapshots.py +214 -0
  112. render/public_api/api/disks/restore_snapshot.py +255 -0
  113. render/public_api/api/disks/retrieve_disk.py +200 -0
  114. render/public_api/api/disks/update_disk.py +243 -0
  115. render/public_api/api/environment_groups/__init__.py +1 -0
  116. render/public_api/api/environment_groups/create_env_group.py +199 -0
  117. render/public_api/api/environment_groups/delete_env_group.py +192 -0
  118. render/public_api/api/environment_groups/delete_env_group_env_var.py +201 -0
  119. render/public_api/api/environment_groups/delete_env_group_secret_file.py +201 -0
  120. render/public_api/api/environment_groups/link_service_to_env_group.py +211 -0
  121. render/public_api/api/environment_groups/list_env_groups.py +352 -0
  122. render/public_api/api/environment_groups/retrieve_env_group.py +190 -0
  123. render/public_api/api/environment_groups/retrieve_env_group_env_var.py +203 -0
  124. render/public_api/api/environment_groups/retrieve_env_group_secret_file.py +203 -0
  125. render/public_api/api/environment_groups/unlink_service_from_env_group.py +209 -0
  126. render/public_api/api/environment_groups/update_env_group.py +212 -0
  127. render/public_api/api/environment_groups/update_env_group_env_var.py +230 -0
  128. render/public_api/api/environment_groups/update_env_group_secret_file.py +225 -0
  129. render/public_api/api/events/__init__.py +1 -0
  130. render/public_api/api/events/retrieve_event.py +205 -0
  131. render/public_api/api/key_value/__init__.py +1 -0
  132. render/public_api/api/key_value/create_key_value.py +199 -0
  133. render/public_api/api/key_value/delete_key_value.py +188 -0
  134. render/public_api/api/key_value/list_key_value.py +380 -0
  135. render/public_api/api/key_value/resume_key_value.py +203 -0
  136. render/public_api/api/key_value/retrieve_key_value.py +190 -0
  137. render/public_api/api/key_value/retrieve_key_value_connection_info.py +194 -0
  138. render/public_api/api/key_value/suspend_key_value.py +203 -0
  139. render/public_api/api/key_value/update_key_value.py +221 -0
  140. render/public_api/api/logs/__init__.py +1 -0
  141. render/public_api/api/logs/delete_owner_log_stream.py +188 -0
  142. render/public_api/api/logs/delete_resource_log_stream.py +192 -0
  143. render/public_api/api/logs/get_owner_log_stream.py +205 -0
  144. render/public_api/api/logs/get_resource_log_stream.py +209 -0
  145. render/public_api/api/logs/list_logs.py +535 -0
  146. render/public_api/api/logs/list_logs_values.py +527 -0
  147. render/public_api/api/logs/list_resource_log_streams.py +317 -0
  148. render/public_api/api/logs/subscribe_logs.py +527 -0
  149. render/public_api/api/logs/update_owner_log_stream.py +231 -0
  150. render/public_api/api/logs/update_resource_log_stream.py +231 -0
  151. render/public_api/api/maintenance/__init__.py +1 -0
  152. render/public_api/api/maintenance/list_maintenance.py +249 -0
  153. render/public_api/api/maintenance/retrieve_maintenance.py +190 -0
  154. render/public_api/api/maintenance/trigger_maintenance.py +212 -0
  155. render/public_api/api/maintenance/update_maintenance.py +222 -0
  156. render/public_api/api/metrics/__init__.py +1 -0
  157. render/public_api/api/metrics/delete_owner_metrics_stream.py +172 -0
  158. render/public_api/api/metrics/get_active_connections.py +237 -0
  159. render/public_api/api/metrics/get_bandwidth.py +237 -0
  160. render/public_api/api/metrics/get_bandwidth_sources.py +250 -0
  161. render/public_api/api/metrics/get_cpu.py +287 -0
  162. render/public_api/api/metrics/get_cpu_limit.py +267 -0
  163. render/public_api/api/metrics/get_cpu_target.py +267 -0
  164. render/public_api/api/metrics/get_disk_capacity.py +252 -0
  165. render/public_api/api/metrics/get_disk_usage.py +252 -0
  166. render/public_api/api/metrics/get_http_latency.py +297 -0
  167. render/public_api/api/metrics/get_http_requests.py +302 -0
  168. render/public_api/api/metrics/get_instance_count.py +252 -0
  169. render/public_api/api/metrics/get_memory.py +267 -0
  170. render/public_api/api/metrics/get_memory_limit.py +267 -0
  171. render/public_api/api/metrics/get_memory_target.py +267 -0
  172. render/public_api/api/metrics/get_owner_metrics_stream.py +174 -0
  173. render/public_api/api/metrics/get_replication_lag.py +237 -0
  174. render/public_api/api/metrics/get_task_runs_completed.py +281 -0
  175. render/public_api/api/metrics/get_task_runs_queued.py +237 -0
  176. render/public_api/api/metrics/list_application_filter_values.py +254 -0
  177. render/public_api/api/metrics/list_http_filter_values.py +282 -0
  178. render/public_api/api/metrics/list_path_filter_values.py +289 -0
  179. render/public_api/api/metrics/upsert_owner_metrics_stream.py +192 -0
  180. render/public_api/api/notification_settings/__init__.py +1 -0
  181. render/public_api/api/notification_settings/list_notification_overrides.py +255 -0
  182. render/public_api/api/notification_settings/patch_owner_notification_settings.py +207 -0
  183. render/public_api/api/notification_settings/patch_service_notification_overrides.py +207 -0
  184. render/public_api/api/notification_settings/retrieve_owner_notification_settings.py +193 -0
  185. render/public_api/api/notification_settings/retrieve_service_notification_overrides.py +193 -0
  186. render/public_api/api/object_storage/__init__.py +1 -0
  187. render/public_api/api/object_storage/delete_object.py +215 -0
  188. render/public_api/api/object_storage/get_object.py +221 -0
  189. render/public_api/api/object_storage/list_objects.py +240 -0
  190. render/public_api/api/object_storage/put_object.py +248 -0
  191. render/public_api/api/one_off_jobs/__init__.py +1 -0
  192. render/public_api/api/one_off_jobs/cancel_job.py +203 -0
  193. render/public_api/api/one_off_jobs/list_job.py +367 -0
  194. render/public_api/api/one_off_jobs/post_job.py +216 -0
  195. render/public_api/api/one_off_jobs/retrieve_job.py +203 -0
  196. render/public_api/api/postgres/__init__.py +1 -0
  197. render/public_api/api/postgres/create_postgres.py +199 -0
  198. render/public_api/api/postgres/create_postgres_export.py +207 -0
  199. render/public_api/api/postgres/create_postgres_user.py +229 -0
  200. render/public_api/api/postgres/delete_postgres.py +192 -0
  201. render/public_api/api/postgres/delete_postgres_user.py +201 -0
  202. render/public_api/api/postgres/failover_postgres.py +207 -0
  203. render/public_api/api/postgres/list_available_postgres_parameter_overrides.py +190 -0
  204. render/public_api/api/postgres/list_postgres.py +418 -0
  205. render/public_api/api/postgres/list_postgres_export.py +199 -0
  206. render/public_api/api/postgres/list_postgres_parameter_overrides.py +190 -0
  207. render/public_api/api/postgres/list_postgres_processes.py +190 -0
  208. render/public_api/api/postgres/list_postgres_sizes.py +190 -0
  209. render/public_api/api/postgres/list_postgres_table_scans.py +190 -0
  210. render/public_api/api/postgres/list_postgres_top_queries.py +194 -0
  211. render/public_api/api/postgres/list_postgres_users.py +195 -0
  212. render/public_api/api/postgres/promote_postgres.py +203 -0
  213. render/public_api/api/postgres/recover_postgres.py +231 -0
  214. render/public_api/api/postgres/restart_postgres.py +203 -0
  215. render/public_api/api/postgres/resume_postgres.py +203 -0
  216. render/public_api/api/postgres/retrieve_postgres.py +190 -0
  217. render/public_api/api/postgres/retrieve_postgres_connection_info.py +194 -0
  218. render/public_api/api/postgres/retrieve_postgres_recovery_info.py +194 -0
  219. render/public_api/api/postgres/setup_postgres_replication.py +231 -0
  220. render/public_api/api/postgres/suspend_postgres.py +203 -0
  221. render/public_api/api/postgres/update_postgres.py +217 -0
  222. render/public_api/api/postgres/update_postgres_parameter_overrides.py +217 -0
  223. render/public_api/api/projects_environments/__init__.py +1 -0
  224. render/public_api/api/projects_environments/add_resources_to_environment.py +212 -0
  225. render/public_api/api/projects_environments/create_environment.py +199 -0
  226. render/public_api/api/projects_environments/create_project.py +199 -0
  227. render/public_api/api/projects_environments/delete_environment.py +216 -0
  228. render/public_api/api/projects_environments/delete_project.py +216 -0
  229. render/public_api/api/projects_environments/list_environments.py +369 -0
  230. render/public_api/api/projects_environments/list_projects.py +329 -0
  231. render/public_api/api/projects_environments/remove_resources_from_environment.py +211 -0
  232. render/public_api/api/projects_environments/retrieve_environment.py +190 -0
  233. render/public_api/api/projects_environments/retrieve_project.py +190 -0
  234. render/public_api/api/projects_environments/update_environment.py +212 -0
  235. render/public_api/api/projects_environments/update_project.py +224 -0
  236. render/public_api/api/redis_deprecated/__init__.py +1 -0
  237. render/public_api/api/redis_deprecated/create_redis.py +199 -0
  238. render/public_api/api/redis_deprecated/delete_redis.py +188 -0
  239. render/public_api/api/redis_deprecated/list_redis.py +384 -0
  240. render/public_api/api/redis_deprecated/resume_redis.py +203 -0
  241. render/public_api/api/redis_deprecated/retrieve_redis.py +190 -0
  242. render/public_api/api/redis_deprecated/retrieve_redis_connection_info.py +194 -0
  243. render/public_api/api/redis_deprecated/suspend_redis.py +203 -0
  244. render/public_api/api/redis_deprecated/update_redis.py +217 -0
  245. render/public_api/api/registry_credentials/__init__.py +1 -0
  246. render/public_api/api/registry_credentials/create_registry_credential.py +209 -0
  247. render/public_api/api/registry_credentials/delete_registry_credential.py +198 -0
  248. render/public_api/api/registry_credentials/list_registry_credentials.py +370 -0
  249. render/public_api/api/registry_credentials/retrieve_registry_credential.py +200 -0
  250. render/public_api/api/registry_credentials/update_registry_credential.py +241 -0
  251. render/public_api/api/sandboxes/__init__.py +1 -0
  252. render/public_api/api/sandboxes/connect_sandbox_files.py +281 -0
  253. render/public_api/api/sandboxes/connect_sandbox_run.py +271 -0
  254. render/public_api/api/sandboxes/create_sandbox.py +199 -0
  255. render/public_api/api/sandboxes/list_sandbox_files.py +244 -0
  256. render/public_api/api/sandboxes/list_sandbox_groups.py +216 -0
  257. render/public_api/api/sandboxes/list_sandboxes.py +269 -0
  258. render/public_api/api/sandboxes/retrieve_sandbox.py +211 -0
  259. render/public_api/api/sandboxes/retrieve_sandbox_execution.py +224 -0
  260. render/public_api/api/sandboxes/stream_sandbox_logs.py +274 -0
  261. render/public_api/api/sandboxes/terminate_sandbox.py +217 -0
  262. render/public_api/api/sandboxes/update_sandbox_exec.py +258 -0
  263. render/public_api/api/services/__init__.py +1 -0
  264. render/public_api/api/services/add_or_update_secret_file.py +252 -0
  265. render/public_api/api/services/autoscale_service.py +230 -0
  266. render/public_api/api/services/create_ephemeral_shell.py +217 -0
  267. render/public_api/api/services/create_service.py +204 -0
  268. render/public_api/api/services/delete_autoscaling_config.py +198 -0
  269. render/public_api/api/services/delete_env_var.py +223 -0
  270. render/public_api/api/services/delete_secret_file.py +223 -0
  271. render/public_api/api/services/delete_service.py +198 -0
  272. render/public_api/api/services/get_env_vars_for_service.py +241 -0
  273. render/public_api/api/services/list_events.py +288 -0
  274. render/public_api/api/services/list_instances.py +190 -0
  275. render/public_api/api/services/list_secret_files_for_service.py +241 -0
  276. render/public_api/api/services/list_services.py +439 -0
  277. render/public_api/api/services/preview_service.py +227 -0
  278. render/public_api/api/services/purge_cache.py +203 -0
  279. render/public_api/api/services/restart_service.py +211 -0
  280. render/public_api/api/services/resume_service.py +203 -0
  281. render/public_api/api/services/retrieve_env_var.py +225 -0
  282. render/public_api/api/services/retrieve_secret_file.py +225 -0
  283. render/public_api/api/services/retrieve_service.py +190 -0
  284. render/public_api/api/services/retrieve_service_outbound_ips.py +207 -0
  285. render/public_api/api/services/scale_service.py +237 -0
  286. render/public_api/api/services/suspend_service.py +203 -0
  287. render/public_api/api/services/update_env_var.py +257 -0
  288. render/public_api/api/services/update_env_vars_for_service.py +241 -0
  289. render/public_api/api/services/update_secret_files_for_service.py +255 -0
  290. render/public_api/api/services/update_service.py +227 -0
  291. render/public_api/api/services_cron_jobs/__init__.py +1 -0
  292. render/public_api/api/services_cron_jobs/cancel_cron_job_run.py +183 -0
  293. render/public_api/api/services_cron_jobs/run_cron_job.py +185 -0
  294. render/public_api/api/services_headers/__init__.py +1 -0
  295. render/public_api/api/services_headers/add_headers.py +222 -0
  296. render/public_api/api/services_headers/delete_header.py +211 -0
  297. render/public_api/api/services_headers/list_headers.py +302 -0
  298. render/public_api/api/services_headers/update_headers.py +243 -0
  299. render/public_api/api/services_routes/__init__.py +1 -0
  300. render/public_api/api/services_routes/add_route.py +227 -0
  301. render/public_api/api/services_routes/delete_route.py +211 -0
  302. render/public_api/api/services_routes/list_routes.py +306 -0
  303. render/public_api/api/services_routes/patch_route.py +259 -0
  304. render/public_api/api/services_routes/put_routes.py +259 -0
  305. render/public_api/api/users/__init__.py +1 -0
  306. render/public_api/api/users/get_user.py +161 -0
  307. render/public_api/api/webhooks/__init__.py +1 -0
  308. render/public_api/api/webhooks/create_webhook.py +199 -0
  309. render/public_api/api/webhooks/delete_webhook.py +183 -0
  310. render/public_api/api/webhooks/list_webhook_events.py +268 -0
  311. render/public_api/api/webhooks/list_webhooks.py +237 -0
  312. render/public_api/api/webhooks/retrieve_webhook.py +185 -0
  313. render/public_api/api/webhooks/update_webhook.py +212 -0
  314. render/public_api/api/workflow_tasks_beta/__init__.py +1 -0
  315. render/public_api/api/workflow_tasks_beta/cancel_task_run.py +188 -0
  316. render/public_api/api/workflow_tasks_beta/create_task.py +204 -0
  317. render/public_api/api/workflow_tasks_beta/get_task.py +190 -0
  318. render/public_api/api/workflow_tasks_beta/get_task_run.py +190 -0
  319. render/public_api/api/workflow_tasks_beta/list_task_runs.py +317 -0
  320. render/public_api/api/workflow_tasks_beta/list_tasks.py +298 -0
  321. render/public_api/api/workflow_tasks_beta/stream_task_runs_events.py +230 -0
  322. render/public_api/api/workflows_beta/__init__.py +1 -0
  323. render/public_api/api/workflows_beta/create_workflow.py +199 -0
  324. render/public_api/api/workflows_beta/create_workflow_version.py +197 -0
  325. render/public_api/api/workflows_beta/delete_workflow.py +188 -0
  326. render/public_api/api/workflows_beta/get_workflow.py +190 -0
  327. render/public_api/api/workflows_beta/get_workflow_version.py +190 -0
  328. render/public_api/api/workflows_beta/list_workflow_versions.py +275 -0
  329. render/public_api/api/workflows_beta/list_workflows.py +298 -0
  330. render/public_api/api/workflows_beta/update_workflow.py +212 -0
  331. render/public_api/api/workspaces/__init__.py +1 -0
  332. render/public_api/api/workspaces/list_owners.py +255 -0
  333. render/public_api/api/workspaces/remove_workspace_member.py +206 -0
  334. render/public_api/api/workspaces/retrieve_owner.py +207 -0
  335. render/public_api/api/workspaces/retrieve_owner_members.py +200 -0
  336. render/public_api/api/workspaces/update_workspace_member.py +235 -0
  337. render/public_api/client.py +268 -0
  338. render/public_api/errors.py +16 -0
  339. render/public_api/models/__init__.py +861 -0
  340. render/public_api/models/add_headers_response_201.py +72 -0
  341. render/public_api/models/add_or_update_artifact_source_secret_file_body.py +59 -0
  342. render/public_api/models/add_or_update_secret_file_body.py +59 -0
  343. render/public_api/models/artifact.py +145 -0
  344. render/public_api/models/artifact_fetch_failed.py +67 -0
  345. render/public_api/models/artifact_source.py +162 -0
  346. render/public_api/models/artifact_source_changed.py +70 -0
  347. render/public_api/models/artifact_source_git.py +167 -0
  348. render/public_api/models/artifact_source_git_region.py +12 -0
  349. render/public_api/models/artifact_source_git_runtime.py +14 -0
  350. render/public_api/models/artifact_source_image.py +78 -0
  351. render/public_api/models/artifact_source_patch_git.py +175 -0
  352. render/public_api/models/artifact_source_patch_git_region.py +12 -0
  353. render/public_api/models/artifact_source_patch_git_runtime.py +14 -0
  354. render/public_api/models/artifact_source_patch_image.py +71 -0
  355. render/public_api/models/artifact_source_patch_input.py +101 -0
  356. render/public_api/models/artifact_source_post_input.py +213 -0
  357. render/public_api/models/artifact_source_service_link.py +67 -0
  358. render/public_api/models/artifact_source_with_cursor.py +73 -0
  359. render/public_api/models/audit_log.py +113 -0
  360. render/public_api/models/audit_log_actor.py +80 -0
  361. render/public_api/models/audit_log_actor_type.py +10 -0
  362. render/public_api/models/audit_log_event.py +87 -0
  363. render/public_api/models/audit_log_metadata.py +49 -0
  364. render/public_api/models/audit_log_status.py +9 -0
  365. render/public_api/models/audit_log_with_cursor.py +73 -0
  366. render/public_api/models/auto_deploy.py +9 -0
  367. render/public_api/models/auto_deploy_disabled.py +79 -0
  368. render/public_api/models/auto_deploy_enabled.py +68 -0
  369. render/public_api/models/auto_deploy_trigger.py +10 -0
  370. render/public_api/models/autoscaling_config.py +89 -0
  371. render/public_api/models/autoscaling_config_changed.py +83 -0
  372. render/public_api/models/autoscaling_criteria.py +73 -0
  373. render/public_api/models/autoscaling_criteria_percentage.py +68 -0
  374. render/public_api/models/autoscaling_ended.py +67 -0
  375. render/public_api/models/autoscaling_started.py +105 -0
  376. render/public_api/models/background_worker_details.py +256 -0
  377. render/public_api/models/background_worker_details_patch.py +184 -0
  378. render/public_api/models/background_worker_details_post.py +266 -0
  379. render/public_api/models/blueprint.py +128 -0
  380. render/public_api/models/blueprint_detail.py +150 -0
  381. render/public_api/models/blueprint_patch.py +77 -0
  382. render/public_api/models/blueprint_with_cursor.py +74 -0
  383. render/public_api/models/branch_deleted.py +67 -0
  384. render/public_api/models/build.py +148 -0
  385. render/public_api/models/build_config.py +96 -0
  386. render/public_api/models/build_deploy_end_reason.py +122 -0
  387. render/public_api/models/build_deploy_end_reason_id.py +59 -0
  388. render/public_api/models/build_deploy_trigger.py +150 -0
  389. render/public_api/models/build_ended.py +91 -0
  390. render/public_api/models/build_filter.py +67 -0
  391. render/public_api/models/build_plan.py +9 -0
  392. render/public_api/models/build_runtime.py +14 -0
  393. render/public_api/models/build_started.py +73 -0
  394. render/public_api/models/build_status.py +13 -0
  395. render/public_api/models/cache.py +61 -0
  396. render/public_api/models/cache_profile.py +10 -0
  397. render/public_api/models/cidr_block_and_description.py +67 -0
  398. render/public_api/models/commit_ignored.py +67 -0
  399. render/public_api/models/commit_ref.py +59 -0
  400. render/public_api/models/connect_sandbox_files_operation.py +9 -0
  401. render/public_api/models/connect_sandbox_run_operation.py +9 -0
  402. render/public_api/models/create_custom_domain_body.py +59 -0
  403. render/public_api/models/create_deploy_body.py +130 -0
  404. render/public_api/models/create_deploy_body_clear_cache.py +9 -0
  405. render/public_api/models/create_ephemeral_shell_body.py +69 -0
  406. render/public_api/models/create_ephemeral_shell_response_201.py +59 -0
  407. render/public_api/models/create_registry_credential_body.py +93 -0
  408. render/public_api/models/create_version.py +70 -0
  409. render/public_api/models/credential_create_input.py +59 -0
  410. render/public_api/models/cron_job_details.py +163 -0
  411. render/public_api/models/cron_job_details_patch.py +138 -0
  412. render/public_api/models/cron_job_details_post.py +172 -0
  413. render/public_api/models/cron_job_run.py +123 -0
  414. render/public_api/models/cron_job_run_ended.py +110 -0
  415. render/public_api/models/cron_job_run_started.py +59 -0
  416. render/public_api/models/cron_job_run_status.py +11 -0
  417. render/public_api/models/custom_domain.py +135 -0
  418. render/public_api/models/custom_domain_domain_type.py +9 -0
  419. render/public_api/models/custom_domain_server.py +68 -0
  420. render/public_api/models/custom_domain_verification_status.py +9 -0
  421. render/public_api/models/custom_domain_with_cursor.py +73 -0
  422. render/public_api/models/database_role.py +9 -0
  423. render/public_api/models/database_status.py +18 -0
  424. render/public_api/models/dedicated_ip.py +146 -0
  425. render/public_api/models/dedicated_ip_status.py +14 -0
  426. render/public_api/models/dedicated_ippatch.py +81 -0
  427. render/public_api/models/dedicated_ippost.py +100 -0
  428. render/public_api/models/deploy.py +211 -0
  429. render/public_api/models/deploy_commit.py +86 -0
  430. render/public_api/models/deploy_ended.py +102 -0
  431. render/public_api/models/deploy_image.py +78 -0
  432. render/public_api/models/deploy_mode.py +9 -0
  433. render/public_api/models/deploy_started.py +85 -0
  434. render/public_api/models/deploy_status.py +18 -0
  435. render/public_api/models/deploy_trigger.py +17 -0
  436. render/public_api/models/deploy_with_cursor.py +81 -0
  437. render/public_api/models/disk.py +83 -0
  438. render/public_api/models/disk_created.py +67 -0
  439. render/public_api/models/disk_deleted.py +59 -0
  440. render/public_api/models/disk_details.py +112 -0
  441. render/public_api/models/disk_patch.py +77 -0
  442. render/public_api/models/disk_post.py +83 -0
  443. render/public_api/models/disk_snapshot.py +88 -0
  444. render/public_api/models/disk_updated.py +75 -0
  445. render/public_api/models/disk_with_cursor.py +73 -0
  446. render/public_api/models/docker_details.py +108 -0
  447. render/public_api/models/docker_details_patch.py +86 -0
  448. render/public_api/models/docker_details_post.py +86 -0
  449. render/public_api/models/edge_cache_disabled.py +65 -0
  450. render/public_api/models/edge_cache_enabled.py +65 -0
  451. render/public_api/models/edge_cache_purged.py +65 -0
  452. render/public_api/models/edge_cache_trigger.py +91 -0
  453. render/public_api/models/env_group.py +162 -0
  454. render/public_api/models/env_group_link.py +77 -0
  455. render/public_api/models/env_group_meta.py +126 -0
  456. render/public_api/models/env_group_patch_input.py +59 -0
  457. render/public_api/models/env_group_post_input.py +161 -0
  458. render/public_api/models/env_var.py +67 -0
  459. render/public_api/models/env_var_generate_value.py +59 -0
  460. render/public_api/models/env_var_key_generate_value.py +68 -0
  461. render/public_api/models/env_var_key_value.py +67 -0
  462. render/public_api/models/env_var_value.py +59 -0
  463. render/public_api/models/env_var_with_cursor.py +73 -0
  464. render/public_api/models/environment.py +152 -0
  465. render/public_api/models/environment_patch_input.py +112 -0
  466. render/public_api/models/environment_post_input.py +122 -0
  467. render/public_api/models/environment_resources_post_input.py +59 -0
  468. render/public_api/models/environment_with_cursor.py +74 -0
  469. render/public_api/models/error.py +79 -0
  470. render/public_api/models/error_code.py +10 -0
  471. render/public_api/models/event.py +1122 -0
  472. render/public_api/models/event_status.py +10 -0
  473. render/public_api/models/event_type.py +74 -0
  474. render/public_api/models/execution.py +144 -0
  475. render/public_api/models/execution_operation.py +11 -0
  476. render/public_api/models/execution_type.py +9 -0
  477. render/public_api/models/failure_reason.py +138 -0
  478. render/public_api/models/filter_application_values_collection_item.py +78 -0
  479. render/public_api/models/filter_application_values_collection_item_filter.py +8 -0
  480. render/public_api/models/filter_http_values_collection_item.py +78 -0
  481. render/public_api/models/filter_http_values_collection_item_filter.py +9 -0
  482. render/public_api/models/get_bandwidth_sources_response_200.py +75 -0
  483. render/public_api/models/get_bandwidth_sources_response_200_data_item.py +101 -0
  484. render/public_api/models/get_bandwidth_sources_response_200_data_item_labels.py +78 -0
  485. render/public_api/models/get_bandwidth_sources_response_200_data_item_labels_traffic_source.py +12 -0
  486. render/public_api/models/get_bandwidth_sources_response_200_data_item_values_item.py +68 -0
  487. render/public_api/models/get_cpu_aggregation_method.py +10 -0
  488. render/public_api/models/get_http_requests_aggregate_by.py +9 -0
  489. render/public_api/models/get_object_output.py +71 -0
  490. render/public_api/models/get_task_runs_completed_aggregate_by.py +8 -0
  491. render/public_api/models/get_task_runs_completed_state.py +9 -0
  492. render/public_api/models/header.py +83 -0
  493. render/public_api/models/header_input.py +76 -0
  494. render/public_api/models/header_with_cursor.py +73 -0
  495. render/public_api/models/image.py +80 -0
  496. render/public_api/models/image_pull_failed.py +67 -0
  497. render/public_api/models/initial_deploy_hook_ended.py +59 -0
  498. render/public_api/models/initial_deploy_hook_started.py +59 -0
  499. render/public_api/models/instance_count_changed.py +67 -0
  500. render/public_api/models/instance_type_changed.py +67 -0
  501. render/public_api/models/internal_routing.py +8 -0
  502. render/public_api/models/job.py +144 -0
  503. render/public_api/models/job_run_ended.py +92 -0
  504. render/public_api/models/job_status.py +12 -0
  505. render/public_api/models/job_with_cursor.py +73 -0
  506. render/public_api/models/key_value.py +182 -0
  507. render/public_api/models/key_value_available.py +44 -0
  508. render/public_api/models/key_value_config_restart.py +67 -0
  509. render/public_api/models/key_value_connection_info.py +76 -0
  510. render/public_api/models/key_value_detail.py +192 -0
  511. render/public_api/models/key_value_options.py +79 -0
  512. render/public_api/models/key_value_patch_input.py +138 -0
  513. render/public_api/models/key_value_plan.py +13 -0
  514. render/public_api/models/key_value_post_input.py +166 -0
  515. render/public_api/models/key_value_unhealthy.py +44 -0
  516. render/public_api/models/key_value_with_cursor.py +73 -0
  517. render/public_api/models/label.py +68 -0
  518. render/public_api/models/list_custom_domains_domain_type.py +9 -0
  519. render/public_api/models/list_custom_domains_verification_status.py +9 -0
  520. render/public_api/models/list_logs_response_200.py +102 -0
  521. render/public_api/models/list_logs_values_label.py +13 -0
  522. render/public_api/models/list_objects_response.py +92 -0
  523. render/public_api/models/list_postgres_suspended_item.py +9 -0
  524. render/public_api/models/list_postgres_users_response_200_item.py +86 -0
  525. render/public_api/models/list_routes_type_item.py +9 -0
  526. render/public_api/models/list_services_suspended_item.py +9 -0
  527. render/public_api/models/log.py +100 -0
  528. render/public_api/models/log_direction.py +9 -0
  529. render/public_api/models/log_label.py +70 -0
  530. render/public_api/models/log_label_name.py +22 -0
  531. render/public_api/models/log_stream_owner_update.py +80 -0
  532. render/public_api/models/log_stream_preview_setting.py +9 -0
  533. render/public_api/models/log_stream_resource_update.py +80 -0
  534. render/public_api/models/log_stream_setting.py +9 -0
  535. render/public_api/models/maintenance_ended.py +44 -0
  536. render/public_api/models/maintenance_mode.py +68 -0
  537. render/public_api/models/maintenance_mode_enabled.py +59 -0
  538. render/public_api/models/maintenance_mode_uri_updated.py +67 -0
  539. render/public_api/models/maintenance_run.py +105 -0
  540. render/public_api/models/maintenance_run_patch.py +69 -0
  541. render/public_api/models/maintenance_run_with_resource.py +114 -0
  542. render/public_api/models/maintenance_started.py +65 -0
  543. render/public_api/models/maintenance_state.py +13 -0
  544. render/public_api/models/maintenance_trigger.py +91 -0
  545. render/public_api/models/maxmemory_policy.py +15 -0
  546. render/public_api/models/metrics_stream.py +77 -0
  547. render/public_api/models/metrics_stream_input.py +86 -0
  548. render/public_api/models/native_environment_details.py +78 -0
  549. render/public_api/models/native_environment_details_patch.py +68 -0
  550. render/public_api/models/native_environment_details_post.py +68 -0
  551. render/public_api/models/notification_override.py +78 -0
  552. render/public_api/models/notification_override_with_cursor.py +73 -0
  553. render/public_api/models/notification_service_override.py +78 -0
  554. render/public_api/models/notification_service_override_patch.py +84 -0
  555. render/public_api/models/notification_setting.py +93 -0
  556. render/public_api/models/notification_setting_patch.py +85 -0
  557. render/public_api/models/notify_override.py +11 -0
  558. render/public_api/models/notify_preview_override.py +10 -0
  559. render/public_api/models/notify_setting.py +10 -0
  560. render/public_api/models/notify_setting_v2.py +10 -0
  561. render/public_api/models/object_metadata.py +77 -0
  562. render/public_api/models/object_with_cursor.py +73 -0
  563. render/public_api/models/oom_killed.py +59 -0
  564. render/public_api/models/otel_provider_type.py +16 -0
  565. render/public_api/models/outbound_ips.py +81 -0
  566. render/public_api/models/outbound_ips_type.py +9 -0
  567. render/public_api/models/owner.py +121 -0
  568. render/public_api/models/owner_log_stream_setting.py +86 -0
  569. render/public_api/models/owner_type.py +9 -0
  570. render/public_api/models/owner_with_cursor.py +81 -0
  571. render/public_api/models/paid_plan.py +13 -0
  572. render/public_api/models/patch_route_response_200.py +72 -0
  573. render/public_api/models/persistence_mode.py +10 -0
  574. render/public_api/models/pipeline_minutes_exhausted.py +73 -0
  575. render/public_api/models/plan.py +22 -0
  576. render/public_api/models/post_job_body.py +70 -0
  577. render/public_api/models/postgres.py +300 -0
  578. render/public_api/models/postgres_available.py +44 -0
  579. render/public_api/models/postgres_available_parameter_override.py +106 -0
  580. render/public_api/models/postgres_available_parameter_overrides_result.py +75 -0
  581. render/public_api/models/postgres_backup_completed.py +44 -0
  582. render/public_api/models/postgres_backup_failed.py +44 -0
  583. render/public_api/models/postgres_backup_started.py +44 -0
  584. render/public_api/models/postgres_cluster_leader_changed.py +59 -0
  585. render/public_api/models/postgres_connection_info.py +103 -0
  586. render/public_api/models/postgres_connection_pool_changed.py +91 -0
  587. render/public_api/models/postgres_connection_pool_enabled_changed.py +83 -0
  588. render/public_api/models/postgres_created.py +72 -0
  589. render/public_api/models/postgres_detail.py +336 -0
  590. render/public_api/models/postgres_detail_suspended.py +9 -0
  591. render/public_api/models/postgres_disk_size_changed.py +91 -0
  592. render/public_api/models/postgres_export.py +80 -0
  593. render/public_api/models/postgres_ha_status_changed.py +67 -0
  594. render/public_api/models/postgres_parameter_overrides.py +44 -0
  595. render/public_api/models/postgres_parameter_overrides_wrapper.py +65 -0
  596. render/public_api/models/postgres_patch_input.py +199 -0
  597. render/public_api/models/postgres_pitr_checkpoint_completed.py +44 -0
  598. render/public_api/models/postgres_pitr_checkpoint_failed.py +44 -0
  599. render/public_api/models/postgres_pitr_checkpoint_started.py +44 -0
  600. render/public_api/models/postgres_plans.py +35 -0
  601. render/public_api/models/postgres_post_input.py +254 -0
  602. render/public_api/models/postgres_process.py +185 -0
  603. render/public_api/models/postgres_processes_result.py +73 -0
  604. render/public_api/models/postgres_put_parameter_overrides_result.py +82 -0
  605. render/public_api/models/postgres_query_statistic.py +222 -0
  606. render/public_api/models/postgres_read_replica_stale.py +44 -0
  607. render/public_api/models/postgres_read_replicas_changed.py +67 -0
  608. render/public_api/models/postgres_replication_setup_input.py +96 -0
  609. render/public_api/models/postgres_restarted.py +72 -0
  610. render/public_api/models/postgres_size.py +96 -0
  611. render/public_api/models/postgres_sizes_result.py +73 -0
  612. render/public_api/models/postgres_suspended.py +9 -0
  613. render/public_api/models/postgres_table_scan.py +87 -0
  614. render/public_api/models/postgres_table_scans_result.py +73 -0
  615. render/public_api/models/postgres_top_queries_result.py +73 -0
  616. render/public_api/models/postgres_unavailable.py +44 -0
  617. render/public_api/models/postgres_upgrade_failed.py +67 -0
  618. render/public_api/models/postgres_upgrade_started.py +91 -0
  619. render/public_api/models/postgres_upgrade_succeeded.py +67 -0
  620. render/public_api/models/postgres_version.py +15 -0
  621. render/public_api/models/postgres_with_cursor.py +73 -0
  622. render/public_api/models/pre_deploy_ended.py +99 -0
  623. render/public_api/models/pre_deploy_started.py +67 -0
  624. render/public_api/models/preview_input.py +94 -0
  625. render/public_api/models/previews.py +67 -0
  626. render/public_api/models/previews_generation.py +10 -0
  627. render/public_api/models/private_service_details.py +282 -0
  628. render/public_api/models/private_service_details_patch.py +184 -0
  629. render/public_api/models/private_service_details_post.py +266 -0
  630. render/public_api/models/project.py +108 -0
  631. render/public_api/models/project_patch_input.py +60 -0
  632. render/public_api/models/project_post_environment_input.py +114 -0
  633. render/public_api/models/project_post_input.py +89 -0
  634. render/public_api/models/project_with_cursor.py +73 -0
  635. render/public_api/models/protected_status.py +9 -0
  636. render/public_api/models/pull_request_previews_enabled.py +9 -0
  637. render/public_api/models/put_object_input.py +59 -0
  638. render/public_api/models/put_object_output.py +79 -0
  639. render/public_api/models/read_replica.py +91 -0
  640. render/public_api/models/read_replica_input.py +83 -0
  641. render/public_api/models/recovery_info.py +80 -0
  642. render/public_api/models/recovery_info_recovery_status.py +10 -0
  643. render/public_api/models/recovery_input.py +114 -0
  644. render/public_api/models/redis.py +182 -0
  645. render/public_api/models/redis_connection_info.py +76 -0
  646. render/public_api/models/redis_detail.py +192 -0
  647. render/public_api/models/redis_options.py +79 -0
  648. render/public_api/models/redis_patch_input.py +138 -0
  649. render/public_api/models/redis_plan.py +13 -0
  650. render/public_api/models/redis_post_input.py +166 -0
  651. render/public_api/models/redis_with_cursor.py +73 -0
  652. render/public_api/models/region.py +12 -0
  653. render/public_api/models/registry_credential.py +95 -0
  654. render/public_api/models/registry_credential_registry.py +12 -0
  655. render/public_api/models/registry_credential_summary.py +67 -0
  656. render/public_api/models/render_subdomain_policy.py +9 -0
  657. render/public_api/models/resource.py +67 -0
  658. render/public_api/models/resource_log_stream_setting.py +87 -0
  659. render/public_api/models/resource_ref.py +77 -0
  660. render/public_api/models/resource_ref_type.py +17 -0
  661. render/public_api/models/rollback_deploy_body.py +59 -0
  662. render/public_api/models/route.py +93 -0
  663. render/public_api/models/route_patch.py +60 -0
  664. render/public_api/models/route_post.py +88 -0
  665. render/public_api/models/route_put.py +77 -0
  666. render/public_api/models/route_type.py +9 -0
  667. render/public_api/models/route_with_cursor.py +73 -0
  668. render/public_api/models/run_task.py +96 -0
  669. render/public_api/models/runtime.py +12 -0
  670. render/public_api/models/sandbox.py +149 -0
  671. render/public_api/models/sandbox_connect_request.py +62 -0
  672. render/public_api/models/sandbox_connect_response.py +98 -0
  673. render/public_api/models/sandbox_directory_listing.py +82 -0
  674. render/public_api/models/sandbox_exec_update_request.py +60 -0
  675. render/public_api/models/sandbox_exec_update_response.py +130 -0
  676. render/public_api/models/sandbox_file_entry.py +98 -0
  677. render/public_api/models/sandbox_file_entry_type.py +10 -0
  678. render/public_api/models/sandbox_group.py +141 -0
  679. render/public_api/models/sandbox_group_with_cursor.py +74 -0
  680. render/public_api/models/sandbox_network_policy.py +61 -0
  681. render/public_api/models/sandbox_network_policy_default.py +9 -0
  682. render/public_api/models/sandbox_plan.py +10 -0
  683. render/public_api/models/sandbox_post.py +138 -0
  684. render/public_api/models/sandbox_post_env.py +44 -0
  685. render/public_api/models/sandbox_status.py +13 -0
  686. render/public_api/models/sandbox_with_cursor.py +74 -0
  687. render/public_api/models/scale_service_body.py +59 -0
  688. render/public_api/models/schemas_build_filter.py +70 -0
  689. render/public_api/models/schemas_image.py +96 -0
  690. render/public_api/models/schemas_user.py +68 -0
  691. render/public_api/models/secret_file.py +67 -0
  692. render/public_api/models/secret_file_input.py +67 -0
  693. render/public_api/models/secret_file_with_cursor.py +73 -0
  694. render/public_api/models/server_available.py +44 -0
  695. render/public_api/models/server_failed.py +81 -0
  696. render/public_api/models/server_hardware_failure.py +44 -0
  697. render/public_api/models/server_port.py +69 -0
  698. render/public_api/models/server_port_protocol.py +9 -0
  699. render/public_api/models/server_restarted.py +66 -0
  700. render/public_api/models/service_disk.py +78 -0
  701. render/public_api/models/service_env.py +15 -0
  702. render/public_api/models/service_event.py +770 -0
  703. render/public_api/models/service_event_type.py +48 -0
  704. render/public_api/models/service_event_with_cursor.py +66 -0
  705. render/public_api/models/service_instance.py +69 -0
  706. render/public_api/models/service_patch.py +273 -0
  707. render/public_api/models/service_post.py +357 -0
  708. render/public_api/models/service_resumed.py +44 -0
  709. render/public_api/models/service_runtime.py +15 -0
  710. render/public_api/models/service_suspended.py +44 -0
  711. render/public_api/models/service_type.py +12 -0
  712. render/public_api/models/service_type_short.py +12 -0
  713. render/public_api/models/setup_postgres_replication_response_201.py +44 -0
  714. render/public_api/models/snapshot_restore_post.py +72 -0
  715. render/public_api/models/static_site_details.py +183 -0
  716. render/public_api/models/static_site_details_patch.py +147 -0
  717. render/public_api/models/static_site_details_post.py +189 -0
  718. render/public_api/models/status.py +12 -0
  719. render/public_api/models/stream_sandbox_logs_accept.py +8 -0
  720. render/public_api/models/stream_task_runs_events_accept.py +8 -0
  721. render/public_api/models/suspender_added.py +83 -0
  722. render/public_api/models/suspender_removed.py +83 -0
  723. render/public_api/models/suspender_type.py +14 -0
  724. render/public_api/models/sync.py +118 -0
  725. render/public_api/models/sync_state.py +12 -0
  726. render/public_api/models/sync_with_cursor.py +74 -0
  727. render/public_api/models/task.py +97 -0
  728. render/public_api/models/task_attempt.py +121 -0
  729. render/public_api/models/task_attempt_details.py +141 -0
  730. render/public_api/models/task_data_type_1.py +44 -0
  731. render/public_api/models/task_run.py +168 -0
  732. render/public_api/models/task_run_details.py +216 -0
  733. render/public_api/models/task_run_status.py +14 -0
  734. render/public_api/models/task_run_with_cursor.py +73 -0
  735. render/public_api/models/task_with_cursor.py +73 -0
  736. render/public_api/models/team_member.py +102 -0
  737. render/public_api/models/team_member_role.py +12 -0
  738. render/public_api/models/team_member_status.py +9 -0
  739. render/public_api/models/time_series.py +100 -0
  740. render/public_api/models/time_series_value.py +70 -0
  741. render/public_api/models/update_env_group_secret_file_body.py +59 -0
  742. render/public_api/models/update_registry_credential_body.py +85 -0
  743. render/public_api/models/update_workspace_member_body.py +61 -0
  744. render/public_api/models/user.py +67 -0
  745. render/public_api/models/validate_blueprint_request.py +84 -0
  746. render/public_api/models/validate_blueprint_response.py +105 -0
  747. render/public_api/models/validation_error.py +88 -0
  748. render/public_api/models/validation_plan_summary.py +107 -0
  749. render/public_api/models/web_service_details.py +385 -0
  750. render/public_api/models/web_service_details_patch.py +270 -0
  751. render/public_api/models/web_service_details_post.py +354 -0
  752. render/public_api/models/webhook.py +110 -0
  753. render/public_api/models/webhook_event.py +115 -0
  754. render/public_api/models/webhook_event_with_cursor.py +73 -0
  755. render/public_api/models/webhook_patch_input.py +98 -0
  756. render/public_api/models/webhook_post_input.py +102 -0
  757. render/public_api/models/webhook_with_cursor.py +73 -0
  758. render/public_api/models/workflow.py +163 -0
  759. render/public_api/models/workflow_create.py +169 -0
  760. render/public_api/models/workflow_update.py +109 -0
  761. render/public_api/models/workflow_version.py +95 -0
  762. render/public_api/models/workflow_version_status.py +13 -0
  763. render/public_api/models/workflow_version_with_cursor.py +73 -0
  764. render/public_api/models/workflow_with_cursor.py +73 -0
  765. render/public_api/models/zero_downtime_redeploy_ended.py +44 -0
  766. render/public_api/models/zero_downtime_redeploy_started.py +59 -0
  767. render/public_api/py.typed +1 -0
  768. render/public_api/types.py +54 -0
  769. render/py.typed +0 -0
  770. render/render.py +81 -0
  771. render/render_async.py +80 -0
  772. render/version.py +27 -0
  773. render/workflows/__init__.py +25 -0
  774. render/workflows/_callback_models.py +194 -0
  775. render/workflows/_uds_http.py +128 -0
  776. render/workflows/app.py +263 -0
  777. render/workflows/cli.py +62 -0
  778. render/workflows/client.py +354 -0
  779. render/workflows/context.py +75 -0
  780. render/workflows/executor.py +86 -0
  781. render/workflows/runner.py +174 -0
  782. render/workflows/task.py +348 -0
  783. render/workflows/tests/__init__.py +0 -0
  784. render/workflows/tests/test_app.py +343 -0
  785. render/workflows/tests/test_cli.py +134 -0
  786. render/workflows/tests/test_client.py +59 -0
  787. render/workflows/tests/test_context.py +118 -0
  788. render/workflows/tests/test_end_to_end.py +307 -0
  789. render/workflows/tests/test_executor.py +221 -0
  790. render/workflows/tests/test_lazy_imports.py +100 -0
  791. render/workflows/tests/test_registration.py +293 -0
  792. render/workflows/tests/test_translate_errors.py +126 -0
  793. render/workflows/tests/test_uds_http.py +199 -0
  794. render/workflows/tests/test_version.py +15 -0
  795. render-1.0.1.dist-info/METADATA +382 -0
  796. render-1.0.1.dist-info/RECORD +799 -0
  797. render-1.0.1.dist-info/WHEEL +4 -0
  798. render-1.0.1.dist-info/entry_points.txt +2 -0
  799. render-1.0.1.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,1016 @@
1
+ """Tests for KeyValueProvider."""
2
+
3
+ from unittest.mock import AsyncMock, MagicMock, patch
4
+
5
+ import pytest
6
+
7
+ from render.client.errors import RenderError
8
+ from render.experimental.key_value.provider import KeyValueProvider
9
+ from render.experimental.key_value.types import (
10
+ InstanceConfiguration,
11
+ KeyValueInstance,
12
+ NameOwnerIdOptions,
13
+ ServiceIdOptions,
14
+ )
15
+ from render.public_api.models.database_status import DatabaseStatus
16
+ from render.public_api.models.key_value_plan import KeyValuePlan
17
+ from render.public_api.models.maxmemory_policy import MaxmemoryPolicy
18
+
19
+
20
+ def make_detail(
21
+ id_: str = "red-abc",
22
+ status: DatabaseStatus = DatabaseStatus.AVAILABLE,
23
+ plan: str = "free",
24
+ maxmemory_policy: MaxmemoryPolicy = MaxmemoryPolicy.ALLKEYS_LRU,
25
+ ip_allow_list=None,
26
+ ) -> KeyValueInstance:
27
+ return KeyValueInstance(
28
+ id=id_,
29
+ status=status,
30
+ plan=KeyValuePlan(plan),
31
+ maxmemory_policy=maxmemory_policy,
32
+ ip_allow_list=ip_allow_list if ip_allow_list is not None else [],
33
+ )
34
+
35
+
36
+ @pytest.fixture
37
+ def api():
38
+ mock = MagicMock()
39
+ mock.find_by_id = AsyncMock(
40
+ side_effect=Exception("find_by_id should not be called")
41
+ )
42
+ mock.find_by_name = AsyncMock(
43
+ side_effect=Exception("find_by_name should not be called")
44
+ )
45
+ mock.get_connection_info = AsyncMock(
46
+ side_effect=Exception("get_connection_info should not be called")
47
+ )
48
+ mock.create_instance = AsyncMock(
49
+ side_effect=Exception("create_instance should not be called")
50
+ )
51
+ mock.update_instance = AsyncMock(
52
+ side_effect=Exception("update_instance should not be called")
53
+ )
54
+ return mock
55
+
56
+
57
+ @pytest.fixture(autouse=True)
58
+ def mock_sleep(mocker):
59
+ return mocker.patch(
60
+ "render.experimental.key_value.provider.asyncio.sleep",
61
+ new_callable=AsyncMock,
62
+ )
63
+
64
+
65
+ @pytest.fixture(autouse=True)
66
+ def mock_redis(mocker):
67
+ return mocker.patch("redis.asyncio.Redis.from_url", return_value=MagicMock())
68
+
69
+
70
+ class TestWithDefaultOwnerId:
71
+ @pytest.fixture
72
+ def client(self, api):
73
+ return KeyValueProvider(api, default_owner_id="tea-abc")
74
+
75
+ @pytest.mark.asyncio
76
+ async def test_new_client_with_name_creates_client(self, client, api):
77
+ api.find_by_name.side_effect = None
78
+ api.find_by_name.return_value = make_detail()
79
+ api.get_connection_info.side_effect = None
80
+ api.get_connection_info.return_value = "redis://localhosta:6239"
81
+
82
+ result = await client.new_client(NameOwnerIdOptions(name="test-redis"))
83
+
84
+ assert result is not None
85
+ api.get_connection_info.assert_called_once_with("red-abc")
86
+
87
+ @pytest.mark.asyncio
88
+ async def test_connection_info_with_name_parses_connection(self, client, api):
89
+ api.find_by_name.side_effect = None
90
+ api.find_by_name.return_value = make_detail()
91
+ api.get_connection_info.side_effect = None
92
+ api.get_connection_info.return_value = "redis://localhosta:6239"
93
+
94
+ result = await client.connection_info(NameOwnerIdOptions(name="test-redis"))
95
+
96
+ assert result.host == "localhosta"
97
+ assert result.port == 6239
98
+ api.get_connection_info.assert_called_once_with("red-abc")
99
+
100
+
101
+ class TestWithoutDefaultOwnerId:
102
+ @pytest.fixture
103
+ def client(self, api):
104
+ return KeyValueProvider(api)
105
+
106
+ class TestNewClientWithServiceId:
107
+ @pytest.mark.asyncio
108
+ async def test_creates_client(self, client, api):
109
+ api.find_by_id.side_effect = None
110
+ api.find_by_id.return_value = make_detail()
111
+ api.get_connection_info.side_effect = None
112
+ api.get_connection_info.return_value = "redis://localhosta:6239"
113
+
114
+ result = await client.new_client(ServiceIdOptions(service_id="red-abc"))
115
+
116
+ assert result is not None
117
+ api.get_connection_info.assert_called_once_with("red-abc")
118
+
119
+ @pytest.mark.asyncio
120
+ async def test_errors_if_service_id_not_found(self, client, api):
121
+ error = RenderError("Unable to find ID")
122
+ api.find_by_id.side_effect = error
123
+
124
+ with pytest.raises(RenderError):
125
+ await client.new_client(ServiceIdOptions(service_id="red-abc"))
126
+
127
+ @pytest.mark.asyncio
128
+ async def test_errors_if_connection_info_not_found(self, client, api):
129
+ api.find_by_id.side_effect = None
130
+ api.find_by_id.return_value = make_detail()
131
+ api.get_connection_info.side_effect = RenderError(
132
+ "Unable to find connection info"
133
+ )
134
+
135
+ with pytest.raises(RenderError):
136
+ await client.new_client(ServiceIdOptions(service_id="red-abc"))
137
+
138
+ class TestNewClientWithName:
139
+ @pytest.mark.asyncio
140
+ async def test_creates_client(self, client, api):
141
+ api.find_by_name.side_effect = None
142
+ api.find_by_name.return_value = make_detail()
143
+ api.get_connection_info.side_effect = None
144
+ api.get_connection_info.return_value = "redis://localhosta:6239"
145
+
146
+ result = await client.new_client(
147
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
148
+ )
149
+
150
+ assert result is not None
151
+ api.get_connection_info.assert_called_once_with("red-abc")
152
+
153
+ @pytest.mark.asyncio
154
+ async def test_errors_if_owner_id_missing(self, client, api):
155
+ with pytest.raises(RenderError, match="owner_id is required"):
156
+ await client.new_client(NameOwnerIdOptions(name="test-redis"))
157
+
158
+ @pytest.mark.asyncio
159
+ async def test_errors_if_not_found_and_auto_provision_disabled(
160
+ self, client, api
161
+ ):
162
+ api.find_by_name.side_effect = None
163
+ api.find_by_name.return_value = None
164
+
165
+ with pytest.raises(RenderError, match="Unable to locate Key Value"):
166
+ await client.new_client(
167
+ NameOwnerIdOptions(
168
+ name="test-redis",
169
+ owner_id="tea-abc",
170
+ auto_provision=False,
171
+ )
172
+ )
173
+
174
+ @pytest.mark.asyncio
175
+ async def test_errors_if_connection_info_not_found(self, client, api):
176
+ api.find_by_name.side_effect = None
177
+ api.find_by_name.return_value = make_detail()
178
+ api.get_connection_info.side_effect = RenderError(
179
+ "Unable to find connection info"
180
+ )
181
+
182
+ with pytest.raises(RenderError):
183
+ await client.new_client(
184
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
185
+ )
186
+
187
+ class TestConnectionInfoWithServiceId:
188
+ @pytest.mark.asyncio
189
+ async def test_parses_connection_info(self, client, api):
190
+ api.find_by_id.side_effect = None
191
+ api.find_by_id.return_value = make_detail()
192
+ api.get_connection_info.side_effect = None
193
+ api.get_connection_info.return_value = "redis://localhosta:6239"
194
+
195
+ result = await client.connection_info(
196
+ ServiceIdOptions(service_id="red-abc")
197
+ )
198
+
199
+ assert result.host == "localhosta"
200
+ assert result.port == 6239
201
+ assert result.username is None
202
+ assert result.password is None
203
+
204
+ @pytest.mark.asyncio
205
+ async def test_parses_connection_info_with_credentials(self, client, api):
206
+ api.find_by_id.side_effect = None
207
+ api.find_by_id.return_value = make_detail()
208
+ api.get_connection_info.side_effect = None
209
+ api.get_connection_info.return_value = "redis://user:pass@localhosta:6239"
210
+
211
+ result = await client.connection_info(
212
+ ServiceIdOptions(service_id="red-abc")
213
+ )
214
+
215
+ assert result.host == "localhosta"
216
+ assert result.port == 6239
217
+ assert result.username == "user"
218
+ assert result.password == "pass" # noqa: S105 (not a hardcoded password)
219
+
220
+ @pytest.mark.asyncio
221
+ async def test_errors_on_invalid_connection_string_format(self, client, api):
222
+ api.find_by_id.side_effect = None
223
+ api.find_by_id.return_value = make_detail()
224
+ api.get_connection_info.side_effect = None
225
+ api.get_connection_info.return_value = "redis://noport.com"
226
+
227
+ with pytest.raises(RenderError, match="unexpected format"):
228
+ await client.connection_info(ServiceIdOptions(service_id="red-abc"))
229
+
230
+ @pytest.mark.asyncio
231
+ async def test_errors_if_service_id_not_found(self, client, api):
232
+ api.find_by_id.side_effect = RenderError("Unable to find service ID")
233
+
234
+ with pytest.raises(RenderError):
235
+ await client.connection_info(ServiceIdOptions(service_id="red-abc"))
236
+
237
+ @pytest.mark.asyncio
238
+ async def test_errors_if_connection_info_not_found(self, client, api):
239
+ api.find_by_id.side_effect = None
240
+ api.find_by_id.return_value = make_detail()
241
+ api.get_connection_info.side_effect = RenderError(
242
+ "Unable to find connection info"
243
+ )
244
+
245
+ with pytest.raises(RenderError):
246
+ await client.connection_info(ServiceIdOptions(service_id="red-abc"))
247
+
248
+ class TestConnectionInfoWithName:
249
+ @pytest.mark.asyncio
250
+ async def test_parses_connection_info(self, client, api):
251
+ api.find_by_name.side_effect = None
252
+ api.find_by_name.return_value = make_detail()
253
+ api.get_connection_info.side_effect = None
254
+ api.get_connection_info.return_value = "rediss://localhosta:6239"
255
+
256
+ result = await client.connection_info(
257
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
258
+ )
259
+
260
+ assert result.host == "localhosta"
261
+ assert result.port == 6239
262
+
263
+ @pytest.mark.asyncio
264
+ async def test_parses_connection_info_with_credentials(self, client, api):
265
+ api.find_by_name.side_effect = None
266
+ api.find_by_name.return_value = make_detail()
267
+ api.get_connection_info.side_effect = None
268
+ api.get_connection_info.return_value = "rediss://user:pass@localhosta:6239"
269
+
270
+ result = await client.connection_info(
271
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
272
+ )
273
+
274
+ assert result.host == "localhosta"
275
+ assert result.port == 6239
276
+ assert result.username == "user"
277
+ assert result.password == "pass" # noqa: S105 (not a hardcoded password)
278
+
279
+ @pytest.mark.asyncio
280
+ async def test_errors_on_invalid_connection_string_format(self, client, api):
281
+ api.find_by_name.side_effect = None
282
+ api.find_by_name.return_value = make_detail()
283
+ api.get_connection_info.side_effect = None
284
+ api.get_connection_info.return_value = "redis://noport.com"
285
+
286
+ with pytest.raises(RenderError, match="unexpected format"):
287
+ await client.connection_info(
288
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
289
+ )
290
+
291
+ @pytest.mark.asyncio
292
+ async def test_errors_if_owner_id_missing(self, client, api):
293
+ with pytest.raises(RenderError, match="owner_id is required"):
294
+ await client.connection_info(NameOwnerIdOptions(name="test-redis"))
295
+
296
+ @pytest.mark.asyncio
297
+ async def test_errors_if_not_found_and_auto_provision_disabled(
298
+ self, client, api
299
+ ):
300
+ api.find_by_name.side_effect = None
301
+ api.find_by_name.return_value = None
302
+
303
+ with pytest.raises(RenderError, match="Unable to locate Key Value"):
304
+ await client.connection_info(
305
+ NameOwnerIdOptions(
306
+ name="test-redis",
307
+ owner_id="tea-abc",
308
+ auto_provision=False,
309
+ )
310
+ )
311
+
312
+ @pytest.mark.asyncio
313
+ async def test_errors_if_connection_info_not_found(self, client, api):
314
+ api.find_by_name.side_effect = None
315
+ api.find_by_name.return_value = make_detail()
316
+ api.get_connection_info.side_effect = RenderError(
317
+ "Unable to locate connection info"
318
+ )
319
+
320
+ with pytest.raises(RenderError):
321
+ await client.connection_info(
322
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
323
+ )
324
+
325
+ class TestAutomaticProvisioning:
326
+ """Tests for auto-provisioning when no instance is found by name."""
327
+
328
+ @pytest.fixture(autouse=True)
329
+ def setup(self, api):
330
+ api.find_by_name.side_effect = None
331
+ api.find_by_name.return_value = None
332
+ api.get_connection_info.side_effect = None
333
+ api.get_connection_info.return_value = "rediss://localhosta:6239"
334
+
335
+ @pytest.mark.asyncio
336
+ async def test_new_client_sends_post_with_options_if_not_found(
337
+ self, client, api
338
+ ):
339
+ api.create_instance.side_effect = RenderError("Early exit")
340
+
341
+ with pytest.raises(RenderError):
342
+ await client.new_client(
343
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
344
+ )
345
+
346
+ api.create_instance.assert_called_once()
347
+ call_body = api.create_instance.call_args.args[0]
348
+ assert call_body.name == "test-redis"
349
+ assert call_body.owner_id == "tea-abc"
350
+ assert call_body.plan == KeyValuePlan.FREE
351
+
352
+ @pytest.mark.asyncio
353
+ async def test_new_client_waits_for_available_after_creating(self, client, api):
354
+ api.create_instance.side_effect = None
355
+ api.create_instance.return_value = make_detail(
356
+ status=DatabaseStatus.CREATING
357
+ )
358
+ api.find_by_id.side_effect = [
359
+ make_detail(status=DatabaseStatus.CREATING),
360
+ make_detail(status=DatabaseStatus.AVAILABLE),
361
+ ]
362
+
363
+ result = await client.new_client(
364
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
365
+ )
366
+
367
+ assert result is not None
368
+ assert api.find_by_id.call_count == 2
369
+
370
+ @pytest.mark.asyncio
371
+ async def test_new_client_errors_on_unrecoverable_status(self, client, api):
372
+ api.create_instance.side_effect = None
373
+ api.create_instance.return_value = make_detail(
374
+ status=DatabaseStatus.CREATING
375
+ )
376
+ api.find_by_id.side_effect = [
377
+ make_detail(status=DatabaseStatus.CREATING),
378
+ make_detail(status=DatabaseStatus.RECOVERY_FAILED),
379
+ ]
380
+
381
+ with pytest.raises(RenderError, match="instance is not available"):
382
+ await client.new_client(
383
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
384
+ )
385
+
386
+ assert api.find_by_id.call_count == 2
387
+
388
+ @pytest.mark.asyncio
389
+ async def test_connection_info_sends_post_with_options_if_not_found(
390
+ self, client, api
391
+ ):
392
+ api.create_instance.side_effect = RenderError("Early exit")
393
+
394
+ with pytest.raises(RenderError):
395
+ await client.connection_info(
396
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
397
+ )
398
+
399
+ api.create_instance.assert_called_once()
400
+ call_body = api.create_instance.call_args.args[0]
401
+ assert call_body.name == "test-redis"
402
+ assert call_body.owner_id == "tea-abc"
403
+ assert call_body.plan == KeyValuePlan.FREE
404
+
405
+ @pytest.mark.asyncio
406
+ async def test_connection_info_waits_for_available_after_creating(
407
+ self, client, api
408
+ ):
409
+ api.create_instance.side_effect = None
410
+ api.create_instance.return_value = make_detail(
411
+ status=DatabaseStatus.CREATING
412
+ )
413
+ api.find_by_id.side_effect = [
414
+ make_detail(status=DatabaseStatus.CREATING),
415
+ make_detail(status=DatabaseStatus.AVAILABLE),
416
+ ]
417
+
418
+ result = await client.connection_info(
419
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
420
+ )
421
+
422
+ assert result.host == "localhosta"
423
+ assert result.port == 6239
424
+ assert api.find_by_id.call_count == 2
425
+
426
+ @pytest.mark.asyncio
427
+ async def test_connection_info_errors_on_unrecoverable_status(
428
+ self, client, api
429
+ ):
430
+ api.create_instance.side_effect = None
431
+ api.create_instance.return_value = make_detail(
432
+ status=DatabaseStatus.CREATING
433
+ )
434
+ api.find_by_id.side_effect = [
435
+ make_detail(status=DatabaseStatus.CREATING),
436
+ make_detail(status=DatabaseStatus.RECOVERY_FAILED),
437
+ ]
438
+
439
+ with pytest.raises(RenderError, match="instance is not available"):
440
+ await client.connection_info(
441
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
442
+ )
443
+
444
+ assert api.find_by_id.call_count == 2
445
+
446
+ class TestConfigurationSync:
447
+ """Tests for configuration sync when options differ from current state."""
448
+
449
+ CONNECTION_STRING = "rediss://user:pass@localhosta:6239"
450
+
451
+ @pytest.fixture(autouse=True)
452
+ def setup(self, api):
453
+ api.get_connection_info.side_effect = None
454
+ api.get_connection_info.return_value = self.CONNECTION_STRING
455
+
456
+ class TestNewClientWithServiceId:
457
+ @pytest.mark.asyncio
458
+ async def test_no_update_if_no_settings_set(self, client, api):
459
+ api.find_by_id.side_effect = None
460
+ api.find_by_id.return_value = make_detail(plan="starter")
461
+
462
+ result = await client.new_client(ServiceIdOptions(service_id="red-abc"))
463
+
464
+ assert result is not None
465
+ api.update_instance.assert_not_called()
466
+ assert api.find_by_id.call_count == 1
467
+
468
+ @pytest.mark.asyncio
469
+ async def test_no_update_if_config_matches(self, client, api):
470
+ api.find_by_id.side_effect = None
471
+ api.find_by_id.return_value = make_detail(
472
+ plan="starter", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
473
+ )
474
+
475
+ result = await client.new_client(
476
+ ServiceIdOptions(
477
+ service_id="red-abc",
478
+ auto_provision=InstanceConfiguration(
479
+ plan="starter",
480
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU,
481
+ ),
482
+ )
483
+ )
484
+
485
+ assert result is not None
486
+ api.update_instance.assert_not_called()
487
+ assert api.find_by_id.call_count == 1
488
+
489
+ @pytest.mark.asyncio
490
+ async def test_sends_patch_if_changes_needed(self, client, api):
491
+ api.find_by_id.side_effect = None
492
+ api.find_by_id.return_value = make_detail(
493
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
494
+ )
495
+ api.update_instance.side_effect = RenderError("early exit")
496
+
497
+ with pytest.raises(RenderError):
498
+ await client.new_client(
499
+ ServiceIdOptions(
500
+ service_id="red-abc",
501
+ auto_provision=InstanceConfiguration(
502
+ plan="starter",
503
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
504
+ ),
505
+ )
506
+ )
507
+
508
+ api.update_instance.assert_called_once()
509
+ assert api.update_instance.call_args.args[0] == "red-abc"
510
+ patch = api.update_instance.call_args.args[1]
511
+ assert patch.plan == KeyValuePlan.STARTER
512
+ assert patch.maxmemory_policy == MaxmemoryPolicy.ALLKEYS_RANDOM
513
+
514
+ @pytest.mark.asyncio
515
+ async def test_waits_for_available_after_update(self, client, api):
516
+ available = make_detail(
517
+ plan="starter", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM
518
+ )
519
+ updating = make_detail(
520
+ plan="starter",
521
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
522
+ status=DatabaseStatus.UPDATING_INSTANCE,
523
+ )
524
+ api.find_by_id.side_effect = [
525
+ make_detail(
526
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
527
+ ),
528
+ updating,
529
+ available,
530
+ ]
531
+ api.update_instance.side_effect = None
532
+ api.update_instance.return_value = updating
533
+
534
+ result = await client.new_client(
535
+ ServiceIdOptions(
536
+ service_id="red-abc",
537
+ auto_provision=InstanceConfiguration(
538
+ plan="starter",
539
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
540
+ ),
541
+ )
542
+ )
543
+
544
+ assert result is not None
545
+ assert api.find_by_id.call_count == 3
546
+
547
+ @pytest.mark.asyncio
548
+ async def test_errors_on_unrecoverable_state_after_update(
549
+ self, client, api
550
+ ):
551
+ updating = make_detail(
552
+ plan="starter",
553
+ status=DatabaseStatus.UPDATING_INSTANCE,
554
+ )
555
+ failed = make_detail(
556
+ plan="starter", status=DatabaseStatus.RECOVERY_FAILED
557
+ )
558
+ api.find_by_id.side_effect = [
559
+ make_detail(plan="free"),
560
+ updating,
561
+ failed,
562
+ ]
563
+ api.update_instance.side_effect = None
564
+ api.update_instance.return_value = updating
565
+
566
+ with pytest.raises(RenderError, match="instance is not available"):
567
+ await client.new_client(
568
+ ServiceIdOptions(
569
+ service_id="red-abc",
570
+ auto_provision=InstanceConfiguration(
571
+ plan="starter",
572
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
573
+ ),
574
+ )
575
+ )
576
+
577
+ assert api.find_by_id.call_count == 3
578
+
579
+ class TestNewClientWithNameAndOwnerId:
580
+ @pytest.mark.asyncio
581
+ async def test_no_update_if_no_settings_set(self, client, api):
582
+ api.find_by_name.side_effect = None
583
+ api.find_by_name.return_value = make_detail(plan="starter")
584
+
585
+ result = await client.new_client(
586
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
587
+ )
588
+
589
+ assert result is not None
590
+ api.update_instance.assert_not_called()
591
+ api.find_by_name.assert_called_once()
592
+ api.find_by_id.assert_not_called()
593
+
594
+ @pytest.mark.asyncio
595
+ async def test_no_update_if_config_matches(self, client, api):
596
+ api.find_by_name.side_effect = None
597
+ api.find_by_name.return_value = make_detail(
598
+ plan="starter", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
599
+ )
600
+
601
+ result = await client.new_client(
602
+ NameOwnerIdOptions(
603
+ name="test-redis",
604
+ owner_id="tea-abc",
605
+ auto_provision=InstanceConfiguration(
606
+ plan="starter",
607
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU,
608
+ ),
609
+ )
610
+ )
611
+
612
+ assert result is not None
613
+ api.update_instance.assert_not_called()
614
+ api.find_by_name.assert_called_once()
615
+ api.find_by_id.assert_not_called()
616
+
617
+ @pytest.mark.asyncio
618
+ async def test_sends_patch_if_changes_needed(self, client, api):
619
+ api.find_by_name.side_effect = None
620
+ api.find_by_name.return_value = make_detail(
621
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
622
+ )
623
+ api.update_instance.side_effect = RenderError("early exit")
624
+
625
+ with pytest.raises(RenderError):
626
+ await client.new_client(
627
+ NameOwnerIdOptions(
628
+ name="test-redis",
629
+ owner_id="tea-abc",
630
+ auto_provision=InstanceConfiguration(
631
+ plan="starter",
632
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
633
+ ),
634
+ )
635
+ )
636
+
637
+ api.update_instance.assert_called_once()
638
+ assert api.update_instance.call_args.args[0] == "red-abc"
639
+ patch = api.update_instance.call_args.args[1]
640
+ assert patch.plan == KeyValuePlan.STARTER
641
+ assert patch.maxmemory_policy == MaxmemoryPolicy.ALLKEYS_RANDOM
642
+
643
+ @pytest.mark.asyncio
644
+ async def test_waits_for_available_after_update(self, client, api):
645
+ api.find_by_name.side_effect = None
646
+ api.find_by_name.return_value = make_detail(
647
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
648
+ )
649
+ updating = make_detail(
650
+ plan="starter",
651
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
652
+ status=DatabaseStatus.UPDATING_INSTANCE,
653
+ )
654
+ available = make_detail(
655
+ plan="starter", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM
656
+ )
657
+ api.find_by_id.side_effect = [updating, available]
658
+ api.update_instance.side_effect = None
659
+ api.update_instance.return_value = updating
660
+
661
+ result = await client.new_client(
662
+ NameOwnerIdOptions(
663
+ name="test-redis",
664
+ owner_id="tea-abc",
665
+ auto_provision=InstanceConfiguration(
666
+ plan="starter",
667
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
668
+ ),
669
+ )
670
+ )
671
+
672
+ assert result is not None
673
+ assert api.find_by_id.call_count == 2
674
+
675
+ @pytest.mark.asyncio
676
+ async def test_errors_on_unrecoverable_state_after_update(
677
+ self, client, api
678
+ ):
679
+ api.find_by_name.side_effect = None
680
+ api.find_by_name.return_value = make_detail(
681
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
682
+ )
683
+ updating = make_detail(
684
+ plan="starter",
685
+ status=DatabaseStatus.UPDATING_INSTANCE,
686
+ )
687
+ failed = make_detail(
688
+ plan="starter", status=DatabaseStatus.RECOVERY_FAILED
689
+ )
690
+ api.find_by_id.side_effect = [updating, failed]
691
+ api.update_instance.side_effect = None
692
+ api.update_instance.return_value = updating
693
+
694
+ with pytest.raises(RenderError, match="instance is not available"):
695
+ await client.new_client(
696
+ NameOwnerIdOptions(
697
+ name="test-redis",
698
+ owner_id="tea-abc",
699
+ auto_provision=InstanceConfiguration(
700
+ plan="starter",
701
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
702
+ ),
703
+ )
704
+ )
705
+
706
+ assert api.find_by_id.call_count == 2
707
+
708
+ class TestConnectionInfoWithServiceId:
709
+ @pytest.mark.asyncio
710
+ async def test_no_update_if_no_settings_set(self, client, api):
711
+ api.find_by_id.side_effect = None
712
+ api.find_by_id.return_value = make_detail(plan="starter")
713
+
714
+ result = await client.connection_info(
715
+ ServiceIdOptions(service_id="red-abc")
716
+ )
717
+
718
+ assert result.username == "user"
719
+ assert (
720
+ result.password == "pass" # noqa: S105 (not a hardcoded password)
721
+ )
722
+ assert result.host == "localhosta"
723
+ assert result.port == 6239
724
+ api.update_instance.assert_not_called()
725
+ assert api.find_by_id.call_count == 1
726
+
727
+ @pytest.mark.asyncio
728
+ async def test_no_update_if_config_matches(self, client, api):
729
+ api.find_by_id.side_effect = None
730
+ api.find_by_id.return_value = make_detail(
731
+ plan="starter", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
732
+ )
733
+
734
+ result = await client.connection_info(
735
+ ServiceIdOptions(
736
+ service_id="red-abc",
737
+ auto_provision=InstanceConfiguration(
738
+ plan="starter",
739
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU,
740
+ ),
741
+ )
742
+ )
743
+
744
+ assert result.host == "localhosta"
745
+ api.update_instance.assert_not_called()
746
+ assert api.find_by_id.call_count == 1
747
+
748
+ @pytest.mark.asyncio
749
+ async def test_sends_patch_if_changes_needed(self, client, api):
750
+ api.find_by_id.side_effect = None
751
+ api.find_by_id.return_value = make_detail(
752
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
753
+ )
754
+ api.update_instance.side_effect = RenderError("early exit")
755
+
756
+ with pytest.raises(RenderError):
757
+ await client.connection_info(
758
+ ServiceIdOptions(
759
+ service_id="red-abc",
760
+ auto_provision=InstanceConfiguration(
761
+ plan="starter",
762
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
763
+ ),
764
+ )
765
+ )
766
+
767
+ api.update_instance.assert_called_once()
768
+ assert api.update_instance.call_args.args[0] == "red-abc"
769
+
770
+ @pytest.mark.asyncio
771
+ async def test_waits_for_available_after_update(self, client, api):
772
+ available = make_detail(
773
+ plan="starter", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM
774
+ )
775
+ updating = make_detail(
776
+ plan="starter",
777
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
778
+ status=DatabaseStatus.UPDATING_INSTANCE,
779
+ )
780
+ api.find_by_id.side_effect = [
781
+ make_detail(
782
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
783
+ ),
784
+ updating,
785
+ available,
786
+ ]
787
+ api.update_instance.side_effect = None
788
+ api.update_instance.return_value = updating
789
+
790
+ result = await client.connection_info(
791
+ ServiceIdOptions(
792
+ service_id="red-abc",
793
+ auto_provision=InstanceConfiguration(
794
+ plan="starter",
795
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
796
+ ),
797
+ )
798
+ )
799
+
800
+ assert result.host == "localhosta"
801
+ assert api.find_by_id.call_count == 3
802
+
803
+ @pytest.mark.asyncio
804
+ async def test_errors_on_unrecoverable_state_after_update(
805
+ self, client, api
806
+ ):
807
+ updating = make_detail(
808
+ plan="starter",
809
+ status=DatabaseStatus.UPDATING_INSTANCE,
810
+ )
811
+ failed = make_detail(
812
+ plan="starter", status=DatabaseStatus.RECOVERY_FAILED
813
+ )
814
+ api.find_by_id.side_effect = [
815
+ make_detail(plan="free"),
816
+ updating,
817
+ failed,
818
+ ]
819
+ api.update_instance.side_effect = None
820
+ api.update_instance.return_value = updating
821
+
822
+ with pytest.raises(RenderError, match="instance is not available"):
823
+ await client.connection_info(
824
+ ServiceIdOptions(
825
+ service_id="red-abc",
826
+ auto_provision=InstanceConfiguration(
827
+ plan="starter",
828
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
829
+ ),
830
+ )
831
+ )
832
+
833
+ assert api.find_by_id.call_count == 3
834
+
835
+ class TestConnectionInfoWithNameAndOwnerId:
836
+ @pytest.mark.asyncio
837
+ async def test_no_update_if_no_settings_set(self, client, api):
838
+ api.find_by_name.side_effect = None
839
+ api.find_by_name.return_value = make_detail(plan="starter")
840
+
841
+ result = await client.connection_info(
842
+ NameOwnerIdOptions(name="test-redis", owner_id="tea-abc")
843
+ )
844
+
845
+ assert result.username == "user"
846
+ assert (
847
+ result.password == "pass" # noqa: S105 (not a hardcoded password)
848
+ )
849
+ assert result.host == "localhosta"
850
+ assert result.port == 6239
851
+ api.update_instance.assert_not_called()
852
+ api.find_by_name.assert_called_once()
853
+ api.find_by_id.assert_not_called()
854
+
855
+ @pytest.mark.asyncio
856
+ async def test_no_update_if_config_matches(self, client, api):
857
+ api.find_by_name.side_effect = None
858
+ api.find_by_name.return_value = make_detail(
859
+ plan="starter", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
860
+ )
861
+
862
+ result = await client.connection_info(
863
+ NameOwnerIdOptions(
864
+ name="test-redis",
865
+ owner_id="tea-abc",
866
+ auto_provision=InstanceConfiguration(
867
+ plan="starter",
868
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU,
869
+ ),
870
+ )
871
+ )
872
+
873
+ assert result.host == "localhosta"
874
+ api.update_instance.assert_not_called()
875
+ api.find_by_name.assert_called_once()
876
+ api.find_by_id.assert_not_called()
877
+
878
+ @pytest.mark.asyncio
879
+ async def test_sends_patch_if_changes_needed(self, client, api):
880
+ api.find_by_name.side_effect = None
881
+ api.find_by_name.return_value = make_detail(
882
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
883
+ )
884
+ api.update_instance.side_effect = RenderError("early exit")
885
+
886
+ with pytest.raises(RenderError):
887
+ await client.connection_info(
888
+ NameOwnerIdOptions(
889
+ name="test-redis",
890
+ owner_id="tea-abc",
891
+ auto_provision=InstanceConfiguration(
892
+ plan="starter",
893
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
894
+ ),
895
+ )
896
+ )
897
+
898
+ api.update_instance.assert_called_once()
899
+ assert api.update_instance.call_args.args[0] == "red-abc"
900
+
901
+ @pytest.mark.asyncio
902
+ async def test_waits_for_available_after_update(self, client, api):
903
+ api.find_by_name.side_effect = None
904
+ api.find_by_name.return_value = make_detail(
905
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
906
+ )
907
+ updating = make_detail(
908
+ plan="starter",
909
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
910
+ status=DatabaseStatus.UPDATING_INSTANCE,
911
+ )
912
+ available = make_detail(
913
+ plan="starter", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM
914
+ )
915
+ api.find_by_id.side_effect = [updating, available]
916
+ api.update_instance.side_effect = None
917
+ api.update_instance.return_value = updating
918
+
919
+ result = await client.connection_info(
920
+ NameOwnerIdOptions(
921
+ name="test-redis",
922
+ owner_id="tea-abc",
923
+ auto_provision=InstanceConfiguration(
924
+ plan="starter",
925
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
926
+ ),
927
+ )
928
+ )
929
+
930
+ assert result.host == "localhosta"
931
+ assert api.find_by_id.call_count == 2
932
+
933
+ @pytest.mark.asyncio
934
+ async def test_errors_on_unrecoverable_state_after_update(
935
+ self, client, api
936
+ ):
937
+ api.find_by_name.side_effect = None
938
+ api.find_by_name.return_value = make_detail(
939
+ plan="free", maxmemory_policy=MaxmemoryPolicy.ALLKEYS_LRU
940
+ )
941
+ updating = make_detail(
942
+ plan="starter",
943
+ status=DatabaseStatus.UPDATING_INSTANCE,
944
+ )
945
+ failed = make_detail(
946
+ plan="starter", status=DatabaseStatus.RECOVERY_FAILED
947
+ )
948
+ api.find_by_id.side_effect = [updating, failed]
949
+ api.update_instance.side_effect = None
950
+ api.update_instance.return_value = updating
951
+
952
+ with pytest.raises(RenderError, match="instance is not available"):
953
+ await client.connection_info(
954
+ NameOwnerIdOptions(
955
+ name="test-redis",
956
+ owner_id="tea-abc",
957
+ auto_provision=InstanceConfiguration(
958
+ plan="starter",
959
+ maxmemory_policy=MaxmemoryPolicy.ALLKEYS_RANDOM,
960
+ ),
961
+ )
962
+ )
963
+
964
+ assert api.find_by_id.call_count == 2
965
+
966
+
967
+ class TestLocalDevMode:
968
+ @pytest.fixture
969
+ def client(self, api):
970
+ return KeyValueProvider(api, default_owner_id="tea-abc")
971
+
972
+ class TestNewClient:
973
+ @pytest.mark.asyncio
974
+ @patch.dict("os.environ", {"RENDER_USE_LOCAL_DEV": "true"})
975
+ async def test_loads_with_no_overrides(self, client):
976
+ result = await client.new_client(NameOwnerIdOptions(name="test-redis"))
977
+
978
+ assert result is not None
979
+
980
+ @pytest.mark.asyncio
981
+ @patch.dict(
982
+ "os.environ",
983
+ {
984
+ "RENDER_USE_LOCAL_DEV": "true",
985
+ "RENDER_LOCAL_REDIS_HOST": "localhosta",
986
+ "RENDER_LOCAL_REDIS_PORT": "1234",
987
+ },
988
+ )
989
+ async def test_loads_with_overrides(self, client):
990
+ result = await client.new_client(NameOwnerIdOptions(name="test-redis"))
991
+
992
+ assert result is not None
993
+
994
+ class TestConnectionInfo:
995
+ @pytest.mark.asyncio
996
+ @patch.dict("os.environ", {"RENDER_USE_LOCAL_DEV": "true"})
997
+ async def test_returns_defaults_if_no_overrides(self, client):
998
+ result = await client.connection_info(NameOwnerIdOptions(name="test-redis"))
999
+
1000
+ assert result.host == "localhost"
1001
+ assert result.port == 6379
1002
+
1003
+ @pytest.mark.asyncio
1004
+ @patch.dict(
1005
+ "os.environ",
1006
+ {
1007
+ "RENDER_USE_LOCAL_DEV": "true",
1008
+ "RENDER_LOCAL_REDIS_HOST": "localhosta",
1009
+ "RENDER_LOCAL_REDIS_PORT": "1234",
1010
+ },
1011
+ )
1012
+ async def test_returns_overrides_if_present(self, client):
1013
+ result = await client.connection_info(NameOwnerIdOptions(name="test-redis"))
1014
+
1015
+ assert result.host == "localhosta"
1016
+ assert result.port == 1234