mage-ai 0.9.65__py3-none-any.whl → 0.9.67__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.

Potentially problematic release.


This version of mage-ai might be problematic. Click here for more details.

Files changed (242) hide show
  1. mage_ai/api/monitors/BaseMonitor.py +38 -16
  2. mage_ai/api/policies/BackfillPolicy.py +1 -0
  3. mage_ai/api/resources/OauthResource.py +13 -5
  4. mage_ai/api/resources/SessionResource.py +6 -4
  5. mage_ai/authentication/ldap.py +19 -9
  6. mage_ai/authentication/oauth/constants.py +8 -14
  7. mage_ai/authentication/oauth/utils.py +18 -6
  8. mage_ai/authentication/providers/active_directory.py +21 -16
  9. mage_ai/authentication/providers/azure_devops.py +18 -0
  10. mage_ai/authentication/providers/bitbucket.py +10 -9
  11. mage_ai/authentication/providers/constants.py +2 -0
  12. mage_ai/authentication/providers/ghe.py +5 -9
  13. mage_ai/authentication/providers/gitlab.py +6 -9
  14. mage_ai/authentication/providers/google.py +9 -6
  15. mage_ai/authentication/providers/oidc.py +6 -4
  16. mage_ai/authentication/providers/okta.py +9 -6
  17. mage_ai/cluster_manager/kubernetes/workload_manager.py +10 -0
  18. mage_ai/cluster_manager/workspace/base.py +6 -1
  19. mage_ai/cluster_manager/workspace/kubernetes.py +3 -0
  20. mage_ai/data_preparation/decorators.py +15 -0
  21. mage_ai/data_preparation/executors/streaming_pipeline_executor.py +22 -12
  22. mage_ai/data_preparation/git/__init__.py +10 -1
  23. mage_ai/data_preparation/git/api.py +3 -0
  24. mage_ai/data_preparation/git/clients/azure_devops.py +106 -0
  25. mage_ai/data_preparation/git/clients/base.py +6 -0
  26. mage_ai/data_preparation/git/clients/gitlab.py +3 -2
  27. mage_ai/data_preparation/git/utils.py +31 -29
  28. mage_ai/data_preparation/models/block/__init__.py +27 -18
  29. mage_ai/data_preparation/models/block/dbt/block_sql.py +164 -0
  30. mage_ai/data_preparation/models/block/dynamic/variables.py +1 -2
  31. mage_ai/data_preparation/models/pipeline.py +3 -3
  32. mage_ai/data_preparation/models/triggers/__init__.py +6 -1
  33. mage_ai/data_preparation/preferences.py +42 -37
  34. mage_ai/data_preparation/repo_manager.py +21 -0
  35. mage_ai/data_preparation/storage/gcs_storage.py +27 -2
  36. mage_ai/data_preparation/storage/local_storage.py +18 -3
  37. mage_ai/data_preparation/storage/s3_storage.py +7 -2
  38. mage_ai/data_preparation/templates/data_loaders/streaming/generic_python.py +23 -0
  39. mage_ai/data_preparation/templates/main/metadata.yaml +6 -0
  40. mage_ai/data_preparation/templates/template.py +6 -2
  41. mage_ai/data_preparation/variable_manager.py +2 -1
  42. mage_ai/io/base.py +3 -0
  43. mage_ai/io/bigquery.py +2 -0
  44. mage_ai/io/export_utils.py +14 -9
  45. mage_ai/io/mssql.py +104 -25
  46. mage_ai/io/mysql.py +10 -9
  47. mage_ai/io/oracledb.py +14 -2
  48. mage_ai/io/postgres.py +3 -0
  49. mage_ai/io/sql.py +14 -6
  50. mage_ai/io/trino.py +10 -8
  51. mage_ai/orchestration/db/migrations/versions/90d978a8aef8_update_unique_constraint_for_secret.py +11 -5
  52. mage_ai/orchestration/db/models/schedules.py +25 -1
  53. mage_ai/orchestration/db/models/schedules_project_platform.py +24 -1
  54. mage_ai/orchestration/job_manager.py +6 -1
  55. mage_ai/orchestration/pipeline_scheduler_original.py +16 -10
  56. mage_ai/server/constants.py +1 -1
  57. mage_ai/server/file_observer.py +10 -0
  58. mage_ai/server/frontend_dist/404.html +2 -2
  59. mage_ai/server/frontend_dist/_next/static/chunks/{1557-a754b04510d50b80.js → 1557-01f0843dc6ac4971.js} +1 -1
  60. mage_ai/server/frontend_dist/_next/static/chunks/9440-4069842b90d4b801.js +1 -0
  61. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-1c1ffd928f5a00f7.js +1 -0
  62. mage_ai/server/frontend_dist/_next/static/chunks/pages/index-b7b8695a7f9efde2.js +1 -0
  63. mage_ai/server/frontend_dist/_next/static/chunks/pages/oauth-30e34ee15d410331.js +1 -0
  64. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +1 -0
  65. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-aaf393c86fc1bda3.js +1 -0
  66. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{edit-8d32ac7e8f023779.js → edit-36377e679da2cd91.js} +1 -1
  67. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-3f5c14076ddde20e.js +1 -0
  68. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-fe08120d9a6fb1b0.js → triggers-f508c2f261297724.js} +1 -1
  69. mage_ai/server/{frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-bcdb4ad41dd4c7d5.js → frontend_dist/_next/static/chunks/pages/pipelines-f99e99aa8f45529c.js} +1 -1
  70. mage_ai/server/frontend_dist/_next/static/chunks/pages/{sign-in-19b36600d908b711.js → sign-in-7d38b2f7c3e918a1.js} +1 -1
  71. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +1 -0
  72. mage_ai/server/frontend_dist/_next/static/chunks/{webpack-ac7fdc472bedf682.js → webpack-d079359c241db804.js} +1 -1
  73. mage_ai/server/frontend_dist/_next/static/{ZMrJfDouIX5AMb_RteRbL → vPsMu6Fi2zrHaf2fRXKRO}/_buildManifest.js +1 -1
  74. mage_ai/server/frontend_dist/block-layout.html +2 -2
  75. mage_ai/server/frontend_dist/compute.html +2 -2
  76. mage_ai/server/frontend_dist/files.html +2 -2
  77. mage_ai/server/frontend_dist/global-data-products/[...slug].html +2 -2
  78. mage_ai/server/frontend_dist/global-data-products.html +2 -2
  79. mage_ai/server/frontend_dist/global-hooks/[...slug].html +2 -2
  80. mage_ai/server/frontend_dist/global-hooks.html +2 -2
  81. mage_ai/server/frontend_dist/index.html +2 -2
  82. mage_ai/server/frontend_dist/manage/files.html +2 -2
  83. mage_ai/server/frontend_dist/manage/settings.html +2 -2
  84. mage_ai/server/frontend_dist/manage/users/[user].html +2 -2
  85. mage_ai/server/frontend_dist/manage/users/new.html +2 -2
  86. mage_ai/server/frontend_dist/manage/users.html +2 -2
  87. mage_ai/server/frontend_dist/manage.html +2 -2
  88. mage_ai/server/frontend_dist/oauth.html +2 -2
  89. mage_ai/server/frontend_dist/overview.html +2 -2
  90. mage_ai/server/frontend_dist/pipeline-runs.html +2 -2
  91. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +2 -2
  92. mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +2 -2
  93. mage_ai/server/frontend_dist/pipelines/[pipeline]/dashboard.html +2 -2
  94. mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
  95. mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +2 -2
  96. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +2 -2
  97. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
  98. mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +2 -2
  99. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +2 -2
  100. mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +2 -2
  101. mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +2 -2
  102. mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +2 -2
  103. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +2 -2
  104. mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +2 -2
  105. mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
  106. mage_ai/server/frontend_dist/pipelines.html +2 -2
  107. mage_ai/server/frontend_dist/platform/global-hooks/[...slug].html +2 -2
  108. mage_ai/server/frontend_dist/platform/global-hooks.html +2 -2
  109. mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
  110. mage_ai/server/frontend_dist/settings/platform/preferences.html +2 -2
  111. mage_ai/server/frontend_dist/settings/platform/settings.html +2 -2
  112. mage_ai/server/frontend_dist/settings/workspace/permissions/[...slug].html +2 -2
  113. mage_ai/server/frontend_dist/settings/workspace/permissions.html +2 -2
  114. mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
  115. mage_ai/server/frontend_dist/settings/workspace/roles/[...slug].html +2 -2
  116. mage_ai/server/frontend_dist/settings/workspace/roles.html +2 -2
  117. mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
  118. mage_ai/server/frontend_dist/settings/workspace/users/[...slug].html +2 -2
  119. mage_ai/server/frontend_dist/settings/workspace/users.html +2 -2
  120. mage_ai/server/frontend_dist/settings.html +2 -2
  121. mage_ai/server/frontend_dist/sign-in.html +2 -2
  122. mage_ai/server/frontend_dist/templates/[...slug].html +2 -2
  123. mage_ai/server/frontend_dist/templates.html +2 -2
  124. mage_ai/server/frontend_dist/terminal.html +2 -2
  125. mage_ai/server/frontend_dist/test.html +2 -2
  126. mage_ai/server/frontend_dist/triggers.html +2 -2
  127. mage_ai/server/frontend_dist/version-control.html +2 -2
  128. mage_ai/server/frontend_dist_base_path_template/404.html +2 -2
  129. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{1557-a754b04510d50b80.js → 1557-01f0843dc6ac4971.js} +1 -1
  130. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9440-4069842b90d4b801.js +1 -0
  131. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-1c1ffd928f5a00f7.js +1 -0
  132. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/index-b7b8695a7f9efde2.js +1 -0
  133. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/oauth-30e34ee15d410331.js +1 -0
  134. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-ff4bd7a8ec3bab40.js +1 -0
  135. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-aaf393c86fc1bda3.js +1 -0
  136. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{edit-8d32ac7e8f023779.js → edit-36377e679da2cd91.js} +1 -1
  137. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-3f5c14076ddde20e.js +1 -0
  138. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-fe08120d9a6fb1b0.js → triggers-f508c2f261297724.js} +1 -1
  139. mage_ai/server/{frontend_dist/_next/static/chunks/pages/pipelines-bcdb4ad41dd4c7d5.js → frontend_dist_base_path_template/_next/static/chunks/pages/pipelines-f99e99aa8f45529c.js} +1 -1
  140. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/{sign-in-19b36600d908b711.js → sign-in-7d38b2f7c3e918a1.js} +1 -1
  141. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-5753fac7c1bfdc88.js +1 -0
  142. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/{webpack-481689d9989710cd.js → webpack-68c003fb6a175cd7.js} +1 -1
  143. mage_ai/server/frontend_dist_base_path_template/_next/static/{QYwFH4sievaq5XyUjRriy → khKiaJtwrslgMmp4YSa1f}/_buildManifest.js +1 -1
  144. mage_ai/server/frontend_dist_base_path_template/block-layout.html +2 -2
  145. mage_ai/server/frontend_dist_base_path_template/compute.html +2 -2
  146. mage_ai/server/frontend_dist_base_path_template/files.html +2 -2
  147. mage_ai/server/frontend_dist_base_path_template/global-data-products/[...slug].html +2 -2
  148. mage_ai/server/frontend_dist_base_path_template/global-data-products.html +2 -2
  149. mage_ai/server/frontend_dist_base_path_template/global-hooks/[...slug].html +2 -2
  150. mage_ai/server/frontend_dist_base_path_template/global-hooks.html +2 -2
  151. mage_ai/server/frontend_dist_base_path_template/index.html +2 -2
  152. mage_ai/server/frontend_dist_base_path_template/manage/files.html +2 -2
  153. mage_ai/server/frontend_dist_base_path_template/manage/settings.html +2 -2
  154. mage_ai/server/frontend_dist_base_path_template/manage/users/[user].html +2 -2
  155. mage_ai/server/frontend_dist_base_path_template/manage/users/new.html +2 -2
  156. mage_ai/server/frontend_dist_base_path_template/manage/users.html +2 -2
  157. mage_ai/server/frontend_dist_base_path_template/manage.html +2 -2
  158. mage_ai/server/frontend_dist_base_path_template/oauth.html +2 -2
  159. mage_ai/server/frontend_dist_base_path_template/overview.html +2 -2
  160. mage_ai/server/frontend_dist_base_path_template/pipeline-runs.html +2 -2
  161. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills/[...slug].html +2 -2
  162. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/backfills.html +2 -2
  163. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/dashboard.html +2 -2
  164. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/edit.html +2 -2
  165. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/logs.html +2 -2
  166. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runs.html +2 -2
  167. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
  168. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/monitors.html +2 -2
  169. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs/[run].html +2 -2
  170. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/runs.html +2 -2
  171. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/settings.html +2 -2
  172. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/syncs.html +2 -2
  173. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers/[...slug].html +2 -2
  174. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline]/triggers.html +2 -2
  175. mage_ai/server/frontend_dist_base_path_template/pipelines/[pipeline].html +2 -2
  176. mage_ai/server/frontend_dist_base_path_template/pipelines.html +2 -2
  177. mage_ai/server/frontend_dist_base_path_template/platform/global-hooks/[...slug].html +2 -2
  178. mage_ai/server/frontend_dist_base_path_template/platform/global-hooks.html +2 -2
  179. mage_ai/server/frontend_dist_base_path_template/settings/account/profile.html +2 -2
  180. mage_ai/server/frontend_dist_base_path_template/settings/platform/preferences.html +2 -2
  181. mage_ai/server/frontend_dist_base_path_template/settings/platform/settings.html +2 -2
  182. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions/[...slug].html +2 -2
  183. mage_ai/server/frontend_dist_base_path_template/settings/workspace/permissions.html +2 -2
  184. mage_ai/server/frontend_dist_base_path_template/settings/workspace/preferences.html +2 -2
  185. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles/[...slug].html +2 -2
  186. mage_ai/server/frontend_dist_base_path_template/settings/workspace/roles.html +2 -2
  187. mage_ai/server/frontend_dist_base_path_template/settings/workspace/sync-data.html +2 -2
  188. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users/[...slug].html +2 -2
  189. mage_ai/server/frontend_dist_base_path_template/settings/workspace/users.html +2 -2
  190. mage_ai/server/frontend_dist_base_path_template/settings.html +2 -2
  191. mage_ai/server/frontend_dist_base_path_template/sign-in.html +2 -2
  192. mage_ai/server/frontend_dist_base_path_template/templates/[...slug].html +2 -2
  193. mage_ai/server/frontend_dist_base_path_template/templates.html +2 -2
  194. mage_ai/server/frontend_dist_base_path_template/terminal.html +2 -2
  195. mage_ai/server/frontend_dist_base_path_template/test.html +2 -2
  196. mage_ai/server/frontend_dist_base_path_template/triggers.html +2 -2
  197. mage_ai/server/frontend_dist_base_path_template/version-control.html +2 -2
  198. mage_ai/server/server.py +117 -87
  199. mage_ai/server/utils/output_display.py +6 -1
  200. mage_ai/services/aws/s3/s3.py +8 -2
  201. mage_ai/services/slack/slack.py +8 -8
  202. mage_ai/settings/__init__.py +36 -186
  203. mage_ai/settings/backends.py +95 -0
  204. mage_ai/settings/keys/__init__.py +1 -0
  205. mage_ai/settings/keys/auth.py +76 -0
  206. mage_ai/settings/server.py +187 -0
  207. mage_ai/shared/io.py +2 -2
  208. mage_ai/shared/logger.py +12 -6
  209. mage_ai/streaming/sources/base_python.py +30 -0
  210. mage_ai/streaming/sources/source_factory.py +25 -0
  211. mage_ai/tests/api/endpoints/test_oauths.py +13 -5
  212. mage_ai/tests/api/operations/test_operations.py +2 -2
  213. mage_ai/tests/api/operations/test_sessions.py +83 -48
  214. mage_ai/tests/authentication/oauth/test_utils.py +56 -6
  215. mage_ai/tests/authentication/providers/test_active_directory.py +9 -15
  216. mage_ai/tests/data_preparation/models/test_block.py +39 -2
  217. mage_ai/tests/orchestration/db/models/test_schedules.py +33 -1
  218. {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/METADATA +2 -1
  219. {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/RECORD +225 -217
  220. {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/WHEEL +1 -1
  221. mage_ai/server/frontend_dist/_next/static/chunks/9440-2bcbdc765ed82062.js +0 -1
  222. mage_ai/server/frontend_dist/_next/static/chunks/pages/_app-2ae1d919333f01fe.js +0 -1
  223. mage_ai/server/frontend_dist/_next/static/chunks/pages/index-64851458dde54ad9.js +0 -1
  224. mage_ai/server/frontend_dist/_next/static/chunks/pages/oauth-abe5ba687cb93509.js +0 -1
  225. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-22e49726eeed16ae.js +0 -1
  226. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c74507dce89b41a2.js +0 -1
  227. mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/logs-cf656cbe37ecaacc.js +0 -1
  228. mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-690206d30d8b412b.js +0 -1
  229. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/9440-2bcbdc765ed82062.js +0 -1
  230. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/_app-2ae1d919333f01fe.js +0 -1
  231. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/index-64851458dde54ad9.js +0 -1
  232. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/oauth-abe5ba687cb93509.js +0 -1
  233. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills/[...slug]-22e49726eeed16ae.js +0 -1
  234. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/backfills-c74507dce89b41a2.js +0 -1
  235. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/pipelines/[pipeline]/logs-cf656cbe37ecaacc.js +0 -1
  236. mage_ai/server/frontend_dist_base_path_template/_next/static/chunks/pages/version-control-690206d30d8b412b.js +0 -1
  237. mage_ai/settings/sso.py +0 -27
  238. /mage_ai/server/frontend_dist/_next/static/{ZMrJfDouIX5AMb_RteRbL → vPsMu6Fi2zrHaf2fRXKRO}/_ssgManifest.js +0 -0
  239. /mage_ai/server/frontend_dist_base_path_template/_next/static/{QYwFH4sievaq5XyUjRriy → khKiaJtwrslgMmp4YSa1f}/_ssgManifest.js +0 -0
  240. {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/LICENSE +0 -0
  241. {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/entry_points.txt +0 -0
  242. {mage_ai-0.9.65.dist-info → mage_ai-0.9.67.dist-info}/top_level.txt +0 -0
mage_ai/server/server.py CHANGED
@@ -17,6 +17,7 @@ from tornado import autoreload
17
17
  from tornado.ioloop import PeriodicCallback
18
18
  from tornado.log import enable_pretty_logging
19
19
  from tornado.options import options
20
+ from watchdog.observers import Observer
20
21
 
21
22
  from mage_ai.authentication.passwords import create_bcrypt_hash, generate_salt
22
23
  from mage_ai.cache.block import BlockCache
@@ -37,6 +38,7 @@ from mage_ai.data_preparation.repo_manager import (
37
38
  get_project_uuid,
38
39
  init_project_uuid,
39
40
  init_repo,
41
+ update_settings_on_metadata_change,
40
42
  )
41
43
  from mage_ai.data_preparation.shared.constants import MANAGE_ENV_VAR
42
44
  from mage_ai.orchestration.constants import Entity
@@ -63,6 +65,7 @@ from mage_ai.server.api.v1 import (
63
65
  )
64
66
  from mage_ai.server.constants import DATA_PREP_SERVER_PORT
65
67
  from mage_ai.server.docs_server import run_docs_server
68
+ from mage_ai.server.file_observer import MetadataEventHandler
66
69
  from mage_ai.server.kernel_output_parser import parse_output_message
67
70
  from mage_ai.server.kernels import DEFAULT_KERNEL_NAME
68
71
  from mage_ai.server.logger import Logger
@@ -85,7 +88,6 @@ from mage_ai.settings import (
85
88
  AUTHENTICATION_MODE,
86
89
  DISABLE_AUTO_BROWSER_OPEN,
87
90
  ENABLE_PROMETHEUS,
88
- LDAP_ADMIN_USERNAME,
89
91
  OAUTH2_APPLICATION_CLIENT_ID,
90
92
  OTEL_EXPORTER_OTLP_ENDPOINT,
91
93
  REDIS_URL,
@@ -97,11 +99,14 @@ from mage_ai.settings import (
97
99
  SERVER_VERBOSITY,
98
100
  SHELL_COMMAND,
99
101
  USE_UNIQUE_TERMINAL,
102
+ get_settings_value,
100
103
  )
104
+ from mage_ai.settings.keys import LDAP_ADMIN_USERNAME
101
105
  from mage_ai.settings.repo import (
102
106
  DEFAULT_MAGE_DATA_DIR,
103
107
  MAGE_CLUSTER_TYPE_ENV_VAR,
104
108
  MAGE_PROJECT_TYPE_ENV_VAR,
109
+ get_metadata_path,
105
110
  get_repo_name,
106
111
  get_variables_dir,
107
112
  set_repo_path,
@@ -220,7 +225,11 @@ def replace_base_path(base_path: str) -> str:
220
225
  return dst
221
226
 
222
227
 
223
- def make_app(template_dir: str = None, update_routes: bool = False):
228
+ def make_app(
229
+ template_dir: str = None,
230
+ update_routes: bool = False,
231
+ status_only: bool = False,
232
+ ):
224
233
  shell_command = SHELL_COMMAND
225
234
  if shell_command is None:
226
235
  shell_command = 'bash'
@@ -233,7 +242,20 @@ def make_app(template_dir: str = None, update_routes: bool = False):
233
242
 
234
243
  if template_dir is None:
235
244
  template_dir = os.path.join(os.path.dirname(__file__), EXPORTS_FOLDER)
236
- routes = [
245
+
246
+ routes_base = [
247
+ # API v1 routes
248
+ (
249
+ r'/api/status(?:es)?',
250
+ ApiListHandler,
251
+ {
252
+ 'resource': 'statuses',
253
+ 'bypass_oauth_check': True,
254
+ 'is_health_check': True,
255
+ },
256
+ ),
257
+ ]
258
+ routes_full = routes_base + [
237
259
  (r'/?', MainPageHandler),
238
260
  (r'/files', MainPageHandler),
239
261
  (r'/overview', MainPageHandler),
@@ -310,17 +332,6 @@ def make_app(template_dir: str = None, update_routes: bool = False):
310
332
  r'/api/downloads/(?P<token>[\w/%.-]+)',
311
333
  ApiResourceDownloadHandler
312
334
  ),
313
-
314
- # API v1 routes
315
- (
316
- r'/api/status(?:es)?',
317
- ApiListHandler,
318
- {
319
- 'resource': 'statuses',
320
- 'bypass_oauth_check': True,
321
- 'is_health_check': True,
322
- },
323
- ),
324
335
  (
325
336
  r'/api/(?P<resource>\w+)/(?P<pk>[\w\-\%2f\.]+)' \
326
337
  r'/(?P<child>\w+)/(?P<child_pk>[\w\-\%2f\.]+)',
@@ -346,6 +357,11 @@ def make_app(template_dir: str = None, update_routes: bool = False):
346
357
  (r'/version-control', MainPageHandler),
347
358
  ]
348
359
 
360
+ if status_only:
361
+ routes = routes_base
362
+ else:
363
+ routes = routes_full
364
+
349
365
  if ENABLE_PROMETHEUS or OTEL_EXPORTER_OTLP_ENDPOINT:
350
366
  from opentelemetry.instrumentation.tornado import TornadoInstrumentor
351
367
  TornadoInstrumentor().instrument()
@@ -455,7 +471,7 @@ def initialize_user_authentication(project_type: ProjectType) -> Oauth2Applicati
455
471
  if AUTHENTICATION_MODE.lower() == 'ldap':
456
472
  user = User.create(
457
473
  roles_new=[default_owner_role],
458
- username=LDAP_ADMIN_USERNAME,
474
+ username=get_settings_value(LDAP_ADMIN_USERNAME, 'admin'),
459
475
  )
460
476
  else:
461
477
  password_salt = generate_salt()
@@ -493,8 +509,10 @@ async def main(
493
509
  port: Union[str, None] = None,
494
510
  project: Union[str, None] = None,
495
511
  project_type: ProjectType = ProjectType.STANDALONE,
512
+ status_only: bool = False,
496
513
  ):
497
- switch_active_kernel(DEFAULT_KERNEL_NAME)
514
+ if not status_only:
515
+ switch_active_kernel(DEFAULT_KERNEL_NAME)
498
516
 
499
517
  # Update base path if environment variable is set
500
518
  update_routes = False
@@ -515,6 +533,7 @@ async def main(
515
533
  app = make_app(
516
534
  template_dir=template_dir,
517
535
  update_routes=update_routes,
536
+ status_only=status_only,
518
537
  )
519
538
 
520
539
  port = int(port)
@@ -539,7 +558,7 @@ async def main(
539
558
  if update_routes:
540
559
  url = f'{url}/{ROUTES_BASE_PATH}'
541
560
 
542
- if not DISABLE_AUTO_BROWSER_OPEN:
561
+ if not DISABLE_AUTO_BROWSER_OPEN and not status_only:
543
562
  webbrowser.open_new_tab(url)
544
563
  logger.info(f'Mage is running at {url} and serving project {project}')
545
564
 
@@ -569,72 +588,70 @@ async def main(
569
588
  except Exception:
570
589
  logger.exception('Failed to set up git repo')
571
590
 
572
- if REQUIRE_USER_AUTHENTICATION:
573
- initialize_user_authentication(project_type)
591
+ if not status_only:
592
+ # Initialize web server related settings and cache
593
+ if REQUIRE_USER_AUTHENTICATION:
594
+ initialize_user_authentication(project_type)
574
595
 
575
- if REQUIRE_USER_PERMISSIONS:
576
- logger.info('User permissions requirement is enabled.')
596
+ if REQUIRE_USER_PERMISSIONS:
597
+ logger.info('User permissions requirement is enabled.')
577
598
 
578
- try:
579
- logger.info('Initializing block cache.')
580
- logger.info('Initializing pipeline cache.')
581
- await BlockCache.initialize_cache(replace=True, caches=[PipelineCache])
582
- except Exception as err:
583
- print(f'[ERROR] PipelineCache.initialize_cache: {err}.')
584
- if is_debug():
585
- raise err
599
+ try:
600
+ logger.info('Initializing block cache.')
601
+ logger.info('Initializing pipeline cache.')
602
+ await BlockCache.initialize_cache(replace=True, caches=[PipelineCache])
603
+ except Exception as err:
604
+ print(f'[ERROR] PipelineCache.initialize_cache: {err}.')
605
+ if is_debug():
606
+ raise err
586
607
 
587
- logger.info('Initializing tag cache.')
588
- await TagCache.initialize_cache(replace=True)
608
+ logger.info('Initializing tag cache.')
609
+ await TagCache.initialize_cache(replace=True)
589
610
 
590
- logger.info('Initializing block action object cache.')
591
- await BlockActionObjectCache.initialize_cache(replace=True)
611
+ logger.info('Initializing block action object cache.')
612
+ await BlockActionObjectCache.initialize_cache(replace=True)
592
613
 
593
- project_model = Project(root_project=True)
594
- if project_model:
595
- if project_model.spark_config and \
596
- project_model.is_feature_enabled(FeatureUUID.COMPUTE_MANAGEMENT):
614
+ project_model = Project(root_project=True)
615
+ if project_model:
616
+ if project_model.spark_config and \
617
+ project_model.is_feature_enabled(FeatureUUID.COMPUTE_MANAGEMENT):
597
618
 
598
- Application.clear_cache()
619
+ Application.clear_cache()
599
620
 
600
- if project_model.is_feature_enabled(FeatureUUID.DBT_V2):
601
- try:
602
- logger.info('Initializing dbt cache.')
603
- dbt_cache = await DBTCache.initialize_cache_async(replace=True, root_project=True)
604
- logger.info(f'dbt cached in {dbt_cache.file_path}')
605
- except Exception as err:
606
- print(f'[ERROR] DBTCache.initialize_cache: {err}.')
607
- if is_debug():
608
- raise err
609
-
610
- if project_model.is_feature_enabled(FeatureUUID.COMMAND_CENTER):
611
- try:
612
- logger.info('Initializing file cache.')
613
- file_cache = FileCache.initialize_cache_with_settings(replace=True)
614
- count = len(file_cache._temp_data) if file_cache._temp_data else 0
615
- logger.info(
616
- f'{count} files cached in {file_cache.file_path}.',
617
- )
618
- except Exception as err:
619
- print(f'[ERROR] FileCache.initialize_cache_with_settings: {err}.')
620
- if is_debug():
621
- raise err
621
+ if project_model.is_feature_enabled(FeatureUUID.DBT_V2):
622
+ try:
623
+ logger.info('Initializing dbt cache.')
624
+ dbt_cache = await DBTCache.initialize_cache_async(
625
+ replace=True,
626
+ root_project=True,
627
+ )
628
+ logger.info(f'dbt cached in {dbt_cache.file_path}')
629
+ except Exception as err:
630
+ print(f'[ERROR] DBTCache.initialize_cache: {err}.')
631
+ if is_debug():
632
+ raise err
622
633
 
623
- try:
624
- from mage_ai.services.ssh.aws.emr.models import create_tunnel
625
-
626
- tunnel = create_tunnel(clean_up_on_failure=True)
627
- if tunnel:
628
- print(f'SSH tunnel active: {tunnel.is_active()}')
629
- except Exception as err:
630
- print(f'[WARNING] SSH tunnel failed to create and connect: {err}')
631
-
632
- # Check scheduler status periodically
633
- periodic_callback = PeriodicCallback(
634
- check_scheduler_status,
635
- SCHEDULER_AUTO_RESTART_INTERVAL,
636
- )
637
- periodic_callback.start()
634
+ if project_model.is_feature_enabled(FeatureUUID.COMMAND_CENTER):
635
+ try:
636
+ logger.info('Initializing file cache.')
637
+ file_cache = FileCache.initialize_cache_with_settings(replace=True)
638
+ count = len(file_cache._temp_data) if file_cache._temp_data else 0
639
+ logger.info(
640
+ f'{count} files cached in {file_cache.file_path}.',
641
+ )
642
+ except Exception as err:
643
+ print(f'[ERROR] FileCache.initialize_cache_with_settings: {err}.')
644
+ if is_debug():
645
+ raise err
646
+
647
+ try:
648
+ from mage_ai.services.ssh.aws.emr.models import create_tunnel
649
+
650
+ tunnel = create_tunnel(clean_up_on_failure=True)
651
+ if tunnel:
652
+ print(f'SSH tunnel active: {tunnel.is_active()}')
653
+ except Exception as err:
654
+ print(f'[WARNING] SSH tunnel failed to create and connect: {err}')
638
655
 
639
656
  if ProjectType.MAIN == project_type:
640
657
  # Check scheduler status periodically
@@ -643,6 +660,19 @@ async def main(
643
660
  60_000,
644
661
  )
645
662
  auto_termination_callback.start()
663
+ else:
664
+ # Check scheduler status periodically
665
+ periodic_callback = PeriodicCallback(
666
+ check_scheduler_status,
667
+ SCHEDULER_AUTO_RESTART_INTERVAL,
668
+ )
669
+ periodic_callback.start()
670
+
671
+ update_settings_on_metadata_change()
672
+ observer = Observer()
673
+ event_handler = MetadataEventHandler()
674
+ observer.schedule(event_handler, path=get_metadata_path(root_project=True))
675
+ observer.start()
646
676
 
647
677
  get_messages(
648
678
  lambda content: WebSocketServer.send_message(
@@ -699,7 +729,7 @@ def start_server(
699
729
  run_docs_server()
700
730
  else:
701
731
  set_db_schema()
702
- run_web_server = True
732
+ run_web_server_with_status_only = False
703
733
  project_type = get_project_type()
704
734
  if manage or project_type == ProjectType.MAIN:
705
735
  os.environ[MANAGE_ENV_VAR] = '1'
@@ -713,8 +743,8 @@ def start_server(
713
743
  scheduler_manager.start_scheduler()
714
744
  elif instance_type == InstanceType.SCHEDULER:
715
745
  # Start a subprocess for scheduler
716
- scheduler_manager.start_scheduler(foreground=True)
717
- run_web_server = False
746
+ scheduler_manager.start_scheduler()
747
+ run_web_server_with_status_only = True
718
748
  elif instance_type == InstanceType.WEB_SERVER:
719
749
  # run migrations to enable user authentication
720
750
  try:
@@ -722,16 +752,16 @@ def start_server(
722
752
  except Exception:
723
753
  traceback.print_exc()
724
754
 
725
- if run_web_server:
726
- # Start web server
727
- asyncio.run(
728
- main(
729
- host=host,
730
- port=port,
731
- project=project,
732
- project_type=project_type,
733
- )
755
+ # Start web server
756
+ asyncio.run(
757
+ main(
758
+ host=host,
759
+ port=port,
760
+ project=project,
761
+ project_type=project_type,
762
+ status_only=run_web_server_with_status_only,
734
763
  )
764
+ )
735
765
 
736
766
 
737
767
  if __name__ == '__main__':
@@ -223,7 +223,12 @@ def __custom_output():
223
223
  ):
224
224
  _sample = _internal_output_return.iloc[:{DATAFRAME_SAMPLE_COUNT_PREVIEW}]
225
225
  _columns = _sample.columns.tolist()[:{DATAFRAME_ANALYSIS_MAX_COLUMNS}]
226
- _rows = simplejson.loads(_sample[_columns].fillna('').to_json(
226
+ for col in _columns:
227
+ try:
228
+ _sample[col] = _sample[col].fillna('')
229
+ except Exception:
230
+ pass
231
+ _rows = simplejson.loads(_sample[_columns].to_json(
227
232
  date_format='iso',
228
233
  default_handler=str,
229
234
  orient='split',
@@ -45,11 +45,17 @@ class Client:
45
45
  },
46
46
  )
47
47
 
48
- def listdir(self, prefix: str, delimiter: str = '/', suffix: str = None):
48
+ def listdir(
49
+ self,
50
+ prefix: str,
51
+ delimiter: str = '/',
52
+ suffix: str = None,
53
+ max_results: int = None,
54
+ ):
49
55
  keys = []
50
56
  response = self.client.list_objects_v2(
51
57
  Bucket=self.bucket,
52
- MaxKeys=MAX_KEYS,
58
+ MaxKeys=max_results or MAX_KEYS,
53
59
  Prefix=prefix,
54
60
  Delimiter=delimiter,
55
61
  )
@@ -6,18 +6,18 @@ from mage_ai.services.slack.config import SlackConfig
6
6
 
7
7
 
8
8
  def send_slack_message(config: SlackConfig, message: str, title: str = None) -> None:
9
- message = message.replace("\\n", "\n")
9
+ message = message.replace('\\n', '\n')
10
10
  payload = {
11
- "blocks": [
11
+ 'blocks': [
12
12
  {
13
- "type": "header",
14
- "text": {
15
- "type": "plain_text",
16
- "text": title if title else "Mage Notification",
13
+ 'type': 'header',
14
+ 'text': {
15
+ 'type': 'plain_text',
16
+ 'text': title if title else 'Mage Notification',
17
17
  },
18
18
  },
19
- {"type": "divider"},
20
- {"type": "section", "text": {"type": "mrkdwn", "text": message}},
19
+ {'type': 'divider'},
20
+ {'type': 'section', 'text': {'type': 'mrkdwn', 'text': message}},
21
21
  ]
22
22
  }
23
23
 
@@ -1,199 +1,49 @@
1
- import os
2
-
3
- from .secret_generation import generate_jwt_secret
4
-
5
- # If you add a new environment variable, make sure to check if it should be added to
6
- # the `MAGE_SETTINGS_ENVIRONMENT_VARIABLES` list at the bottom of this file. Also, update
7
- # the environment variable documentation at docs/development/variables/environment-variables.mdx
8
-
9
- DEBUG = os.getenv('DEBUG', False)
10
- HIDE_ENV_VAR_VALUES = int(os.getenv('HIDE_ENV_VAR_VALUES', 1) or 1) == 1
11
- QUERY_API_KEY = 'api_key'
12
-
13
- """
14
- import secrets
15
- secrets.token_urlsafe()
16
-
17
- Make sure this value is the same in mage_ai/frontend/api/constants.ts
18
- """
19
- OAUTH2_APPLICATION_CLIENT_ID = 'zkWlN0PkIKSN0C11CfUHUj84OT5XOJ6tDZ6bDRO2'
20
-
21
- # valid values: 0, 1, 2
22
- try:
23
- DISABLE_NOTEBOOK_EDIT_ACCESS = int(os.getenv('DISABLE_NOTEBOOK_EDIT_ACCESS', 0))
24
- except ValueError:
25
- DISABLE_NOTEBOOK_EDIT_ACCESS = 1 if os.getenv('DISABLE_NOTEBOOK_EDIT_ACCESS') else 0
26
-
27
-
28
- def is_disable_pipeline_edit_access(
29
- disable_notebook_edit_access_override: int = None,
30
- ) -> bool:
31
- value = DISABLE_NOTEBOOK_EDIT_ACCESS
32
- if disable_notebook_edit_access_override is not None:
33
- value = disable_notebook_edit_access_override
34
- return value >= 1
35
-
36
-
37
- def get_bool_value(value: str) -> bool:
38
- """
39
- Converts a string environment variable to a bool value. Returns True if the value
40
- is 'true', '1', or 't' (case insensitive). Otherwise, False
41
- """
42
- if value is None:
43
- return False
44
-
45
- return value.lower() in ('true', '1', 't')
46
-
47
-
48
- # ------------------------- DISABLE TERMINAL ----------------------
49
-
50
- DISABLE_TERMINAL = os.getenv('DISABLE_TERMINAL', '0').lower() in ('true', '1', 't')
51
-
52
- # ----------------- Authentication settings ----------------
53
- REQUIRE_USER_AUTHENTICATION = get_bool_value(
54
- os.getenv('REQUIRE_USER_AUTHENTICATION', 'False')
55
- )
56
- REQUIRE_USER_PERMISSIONS = REQUIRE_USER_AUTHENTICATION and get_bool_value(
57
- os.getenv('REQUIRE_USER_PERMISSIONS', 'False')
1
+ from mage_ai.settings.backends import (
2
+ AWSSecretsManagerBackend,
3
+ BackendType,
4
+ SettingsBackend,
58
5
  )
59
- AUTHENTICATION_MODE = os.getenv('AUTHENTICATION_MODE', 'LOCAL')
60
- try:
61
- MAGE_ACCESS_TOKEN_EXPIRY_TIME = int(
62
- os.getenv('MAGE_ACCESS_TOKEN_EXPIRY_TIME', '2592000')
63
- )
64
- except ValueError:
65
- MAGE_ACCESS_TOKEN_EXPIRY_TIME = 2592000
6
+ from mage_ai.settings.server import * # noqa: F401, F403
66
7
 
67
- # Default access level to give to users created when authenticated through OAuth
68
- # for the first time. value should be the name of a Mage role (e.g. Viewer, Editor, Admin)
69
- OAUTH_DEFAULT_ACCESS = os.getenv('OAUTH_DEFAULT_ACCESS')
70
- LDAP_SERVER = os.getenv('LDAP_SERVER', 'ldaps://127.0.0.1:1636')
71
- LDAP_BIND_DN = os.getenv('LDAP_BIND_DN', 'cd=admin,dc=example,dc=org')
72
- LDAP_BIND_PASSWORD = os.getenv('LDAP_BIND_PASSWORD', 'admin_password')
73
- LDAP_BASE_DN = os.getenv('LDAP_BASE_DN', 'dc=example,dc=org')
74
- LDAP_AUTHENTICATION_FILTER = os.getenv(
75
- 'LDAP_AUTHENTICATION_FILTER',
76
- '(&(|(objectClass=Pers)(objectClass=gro))(cn={username}))',
77
- )
78
- LDAP_AUTHORIZATION_FILTER = os.getenv(
79
- 'LDAP_AUTHORIZATION_FILTER',
80
- '(&(objectClass=groupOfNames)(cn=group)(member={user_dn}))',
81
- )
82
- LDAP_ADMIN_USERNAME = os.getenv('LDAP_ADMIN_USERNAME', 'admin')
83
- # Default access level to give to users created when authenticated through LDAP
84
- # for the first time. value should be the name of a Mage role (e.g. Viewer, Editor, Admin)
85
- LDAP_DEFAULT_ACCESS = os.getenv('LDAP_DEFAULT_ACCESS', None)
86
- LDAP_GROUP_FIELD = os.getenv('LDAP_GROUP_FIELD', 'memberOf')
87
- LDAP_ROLES_MAPPING = os.getenv('LDAP_ROLES_MAPPING', None)
88
-
89
- ACTIVE_DIRECTORY_DIRECTORY_ID = os.getenv('ACTIVE_DIRECTORY_DIRECTORY_ID', None)
90
8
 
91
- # ----------------------------------------------------------
9
+ class Settings():
10
+ def __init__(self):
11
+ self.settings_backend = SettingsBackend()
92
12
 
93
- HOSTNAME = os.getenv('HOSTNAME')
94
- REDIS_URL = os.getenv('REDIS_URL')
95
- SERVER_VERBOSITY = os.getenv('SERVER_VERBOSITY', 'info') or 'info'
96
- SERVER_LOGGING_FORMAT = os.getenv('SERVER_LOGGING_FORMAT')
13
+ def set_settings_backend(self, backend_type: str = None, **kwargs):
14
+ """
15
+ Factory function to create a settings backend of the specified type.
97
16
 
98
- DISABLE_AUTO_BROWSER_OPEN = get_bool_value(os.getenv('DISABLE_AUTO_BROWSER_OPEN', 'False'))
17
+ Args:
18
+ type (str): Type of the settings backend to create
19
+ kwargs (Dict): Additional keyword arguments to pass to the settings backend constructor
99
20
 
100
- SHELL_COMMAND = os.getenv('SHELL_COMMAND', None)
101
- USE_UNIQUE_TERMINAL = os.getenv('USE_UNIQUE_TERMINAL', None)
21
+ Returns:
22
+ SettingsBackend: A settings backend instance of the specified type
23
+ """
24
+ if backend_type == BackendType.AWS_SECRETS_MANAGER:
25
+ self.settings_backend = AWSSecretsManagerBackend(**kwargs)
26
+ else:
27
+ self.settings_backend = SettingsBackend(**kwargs)
102
28
 
103
- # sentry environment variables
104
- SENTRY_DSN = os.getenv('SENTRY_DSN')
105
- SENTRY_TRACES_SAMPLE_RATE = os.getenv('SENTRY_TRACES_SAMPLE_RATE', 1.0)
29
+ def get_value(self, key: str, default: str = None) -> str:
30
+ """
31
+ Get the value of an environment variable. Add Mage specific logic to handle fetching
32
+ environment variables from other sources.
106
33
 
107
- # New relic enable environment variable
108
- ENABLE_NEW_RELIC = os.getenv('ENABLE_NEW_RELIC', False)
109
- NEW_RELIC_CONFIG_PATH = os.getenv('NEW_RELIC_CONFIG_PATH', '')
34
+ Args:
35
+ key (str): The name of the environment variable.
36
+ default (str, optional): The default value to return if the environment variable is
37
+ not set. Defaults to None.
110
38
 
111
- # If enabled, the /metrics route will expose Tornado server metrics
112
- ENABLE_PROMETHEUS = get_bool_value(os.getenv('ENABLE_PROMETHEUS', 'False'))
113
-
114
- # OpenTelemetry configuration
115
- OTEL_EXPORTER_OTLP_ENDPOINT = os.getenv('OTEL_EXPORTER_OTLP_ENDPOINT', None)
116
- OTEL_EXPORTER_OTLP_HTTP_ENDPOINT = os.getenv('OTEL_EXPORTER_HTTP_OTLP_ENDPOINT', None)
117
- OTEL_PYTHON_TORNADO_EXCLUDED_URLS = (
118
- os.getenv('OTEL_PYTHON_TORNADO_EXCLUDED_URLS') or '/api/statuses'
119
- )
39
+ Returns:
40
+ str: The value of the environment variable.
41
+ """
42
+ return self.settings_backend.get(key, default=default)
120
43
 
121
- DEFAULT_LOCALHOST_URL = 'http://localhost:6789'
122
- MAGE_PUBLIC_HOST = os.getenv('MAGE_PUBLIC_HOST') or DEFAULT_LOCALHOST_URL
123
44
 
124
- MAX_FILE_CACHE_SIZE = os.getenv('MAX_FILE_CACHE_SIZE') or (1024 * 1024) # 1 MB
45
+ settings = Settings()
125
46
 
126
- # All base path variables should not include a leading forward slash
127
- # e.g. MAGE_BASE_PATH = 'test_prefix' -> localhost:6789/test_prefix/pipelines
128
- BASE_PATH = os.getenv('MAGE_BASE_PATH')
129
- # Requests base path is used to configure the base path for the frontend requests. Defaults
130
- # to the MAGE_BASE_PATH environment variable.
131
- REQUESTS_BASE_PATH = os.getenv('MAGE_REQUESTS_BASE_PATH', BASE_PATH)
132
- # Routes base path is used to configure the base path for the backend routes. Defaults
133
- # to the MAGE_BASE_PATH environment variable.
134
- ROUTES_BASE_PATH = os.getenv('MAGE_ROUTES_BASE_PATH', BASE_PATH)
135
- # Used for OAUTH
136
- JWT_SECRET = os.getenv('JWT_SECRET', 'materia')
137
- # Used for generating download tokens
138
- JWT_DOWNLOAD_SECRET = os.getenv('JWT_DOWNLOAD_SECRET', generate_jwt_secret())
139
- # Sets the trigger interval of the scheduler to a numeric value, in seconds
140
- # Determines how often the scheduler gets invoked
141
- try:
142
- SCHEDULER_TRIGGER_INTERVAL = float(os.getenv('SCHEDULER_TRIGGER_INTERVAL', '10'))
143
- except ValueError:
144
- SCHEDULER_TRIGGER_INTERVAL = 10
145
47
 
146
- # List of environment variables used to configure Mage. The value of these settings
147
- # will be copied between workspaces.
148
- MAGE_SETTINGS_ENVIRONMENT_VARIABLES = [
149
- 'DISABLE_NOTEBOOK_EDIT_ACCESS',
150
- 'DISABLE_AUTO_BROWSER_OPEN',
151
- 'REQUIRE_USER_AUTHENTICATION',
152
- 'AUTHENTICATION_MODE',
153
- 'OAUTH_DEFAULT_ACCESS',
154
- 'LDAP_SERVER',
155
- 'LDAP_BIND_DN',
156
- 'LDAP_BIND_PASSWORD',
157
- 'LDAP_BASE_DN',
158
- 'LDAP_AUTHENTICATION_FILTER',
159
- 'LDAP_AUTHORIZATION_FILTER',
160
- 'LDAP_ADMIN_USERNAME',
161
- 'LDAP_DEFAULT_ACCESS',
162
- 'LDAP_GROUP_FIELD',
163
- 'LDAP_ROLES_MAPPING',
164
- 'SERVER_VERBOSITY',
165
- 'SERVER_LOGGING_FORMAT',
166
- 'SHELL_COMMAND',
167
- 'USE_UNIQUE_TERMINAL',
168
- 'SENTRY_DSN',
169
- 'SENTRY_TRACES_SAMPLE_RATE',
170
- 'MAGE_PUBLIC_HOST',
171
- 'SCHEDULER_TRIGGER_INTERVAL',
172
- 'REQUIRE_USER_PERMISSIONS',
173
- 'ENABLE_PROMETHEUS',
174
- 'OTEL_EXPORTER_OTLP_ENDPOINT',
175
- 'OTEL_EXPORTER_OTLP_HTTP_ENDPOINT',
176
- 'MAX_FILE_CACHE_SIZE',
177
- 'REDIS_URL',
178
- # Oauth variables
179
- 'ACTIVE_DIRECTORY_DIRECTORY_ID',
180
- 'ACTIVE_DIRECTORY_CLIENT_ID',
181
- 'ACTIVE_DIRECTORY_CLIENT_SECRET',
182
- 'OKTA_DOMAIN_URL',
183
- 'OKTA_CLIENT_ID',
184
- 'OKTA_CLIENT_SECRET',
185
- 'GOOGLE_CLIENT_ID',
186
- 'GOOGLE_CLIENT_SECRET',
187
- 'OIDC_CLIENT_ID',
188
- 'OIDC_CLIENT_SECRET',
189
- 'OIDC_DISCOVERY_URL',
190
- 'GHE_CLIENT_ID',
191
- 'GHE_CLIENT_SECRET',
192
- 'GHE_HOSTNAME',
193
- 'BITBUCKET_HOST',
194
- 'BITBUCKET_OAUTH_KEY',
195
- 'BITBUCKET_OAUTH_SECRET',
196
- 'GITLAB_HOST',
197
- 'GITLAB_CLIENT_ID',
198
- 'GITLAB_CLIENT_SECRET',
199
- ]
48
+ def get_settings_value(key: str, default: str = None) -> str:
49
+ return settings.get_value(key, default=default)