cornflow 2.0.0a13__tar.gz → 2.0.0a15__tar.gz
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.
- {cornflow-2.0.0a13/cornflow.egg-info → cornflow-2.0.0a15}/PKG-INFO +2 -2
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/app.py +3 -1
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/__init__.py +4 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/actions.py +4 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/config.py +4 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/migrations.py +13 -8
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/permissions.py +4 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/roles.py +4 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/schemas.py +5 -0
- cornflow-2.0.0a15/cornflow/cli/service.py +399 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/tools/api_generator.py +13 -10
- cornflow-2.0.0a15/cornflow/cli/tools/endpoint_tools.py +283 -0
- cornflow-2.0.0a15/cornflow/cli/tools/models_tools.py +161 -0
- cornflow-2.0.0a15/cornflow/cli/tools/schema_generator.py +281 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/tools/schemas_tools.py +4 -5
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/users.py +8 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/views.py +4 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/dag.py +3 -2
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/schemas.py +6 -4
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/users.py +12 -17
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/config.py +3 -2
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/dag.py +27 -25
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/data_check.py +102 -164
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/example_data.py +9 -3
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/execution.py +27 -23
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/health.py +4 -5
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/instance.py +39 -12
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/meta_resource.py +4 -5
- cornflow-2.0.0a15/cornflow/shared/airflow.py +157 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/authentication/auth.py +73 -42
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/const.py +9 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/databricks.py +10 -10
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/exceptions.py +3 -1
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/utils_tables.py +36 -8
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/validators.py +1 -1
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/custom_test_case.py +4 -4
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_alarms.py +1 -2
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_cases.py +4 -7
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_executions.py +29 -20
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_log_in.py +46 -9
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_tables.py +3 -3
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/tools.py +31 -13
- {cornflow-2.0.0a13 → cornflow-2.0.0a15/cornflow.egg-info}/PKG-INFO +2 -2
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow.egg-info/SOURCES.txt +1 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow.egg-info/requires.txt +1 -1
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/requirements.txt +1 -1
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/setup.py +1 -1
- cornflow-2.0.0a13/cornflow/cli/service.py +0 -284
- cornflow-2.0.0a13/cornflow/cli/tools/endpoint_tools.py +0 -288
- cornflow-2.0.0a13/cornflow/cli/tools/models_tools.py +0 -134
- cornflow-2.0.0a13/cornflow/cli/tools/schema_generator.py +0 -187
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/MANIFEST.in +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/README.rst +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/airflow_config/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/airflow_config/airflow_local_settings.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/airflow_config/plugins/XCom/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/airflow_config/plugins/XCom/gce_xcom_backend.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/airflow_config/plugins/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/airflow_config/webserver_ldap.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/arguments.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/tools/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/tools/tools.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/cli/utils.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/access.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/actions.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/cleanup.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/permissions.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/roles.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/commands/views.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/action.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/alarms.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/apiview.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/case.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/licenses.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/login.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/main_alarms.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/permission.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/roles.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/schemas.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/signup.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/tables.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/token.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/user.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/endpoints/user_role.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/gunicorn.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/README +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/alembic.ini +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/env.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/script.py.mako +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/00757b557b02_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/1af47a419bbd_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/4aac5e0c6e66_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/7c3ea5ab5501_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/991b98e24225_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/999b98e24225.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/a472b5ad50b7_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/c2db9409cb5f_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/c8a6c762e818_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/ca449af8034c_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/d0e0700dcd8e_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/d1b5be1f0549_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/e1a50dae1ac9_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/e937a5234ce4_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/ebdd955fcc5e_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/migrations/versions/f3bee20314a2_.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/action.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/alarms.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/base_data_model.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/case.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/dag.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/dag_permissions.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/execution.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/instance.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/main_alarms.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/meta_models.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/permissions.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/role.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/user.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/user_role.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/models/view.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/orchestrator_constants.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/action.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/alarms.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/case.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/common.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/dag.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/example_data.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/execution.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/health.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/instance.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/main_alarms.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/model_json.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/patch.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/permissions.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/query.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/role.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/schemas.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/solution_log.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/tables.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/user.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/user_role.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/schemas/view.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/authentication/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/authentication/decorators.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/authentication/ldap.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/compress.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/email.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/licenses.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/log_config.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/query_tools.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/shared/utils.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/const.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/custom_liveServer.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/integration/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/integration/test_commands.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/integration/test_cornflowclient.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/ldap/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/ldap/test_ldap_authentication.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/__init__.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_actions.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_apiview.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_application.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_cli.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_commands.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_dags.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_data_checks.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_example_data.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_generate_from_schema.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_health.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_instances.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_instances_file.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_licenses.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_main_alarms.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_permissions.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_roles.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_schema_from_models.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_schemas.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_sign_up.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_token.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow/tests/unit/test_users.py +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow.egg-info/dependency_links.txt +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow.egg-info/entry_points.txt +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/cornflow.egg-info/top_level.txt +0 -0
- {cornflow-2.0.0a13 → cornflow-2.0.0a15}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: cornflow
|
3
|
-
Version: 2.0.
|
3
|
+
Version: 2.0.0a15
|
4
4
|
Summary: cornflow is an open source multi-solver optimization server with a REST API built using flask.
|
5
5
|
Home-page: https://github.com/baobabsoluciones/cornflow
|
6
6
|
Author: baobab soluciones
|
@@ -14,7 +14,7 @@ Requires-Dist: alembic==1.9.2
|
|
14
14
|
Requires-Dist: apispec<=6.3.0
|
15
15
|
Requires-Dist: cachetools==5.3.3
|
16
16
|
Requires-Dist: click<=8.1.7
|
17
|
-
Requires-Dist: cornflow-client==2.0.
|
17
|
+
Requires-Dist: cornflow-client==2.0.0a15
|
18
18
|
Requires-Dist: cryptography<=44.0.1
|
19
19
|
Requires-Dist: databricks-sdk==0.29.0
|
20
20
|
Requires-Dist: disposable-email-domains>=0.0.86
|
@@ -51,6 +51,8 @@ def create_app(env_name="development", dataconn=None):
|
|
51
51
|
"""
|
52
52
|
dictConfig(log_config(app_config[env_name].LOG_LEVEL))
|
53
53
|
|
54
|
+
# Note: Explicit CSRF protection is not configured as the application uses
|
55
|
+
# JWT for authentication via headers, mitigating standard CSRF vulnerabilities.
|
54
56
|
app = Flask(__name__)
|
55
57
|
app.json.sort_keys = False
|
56
58
|
app.logger.setLevel(app_config[env_name].LOG_LEVEL)
|
@@ -103,7 +105,7 @@ def create_app(env_name="development", dataconn=None):
|
|
103
105
|
else:
|
104
106
|
raise ConfigurationError(
|
105
107
|
error="Invalid authentication type",
|
106
|
-
log_txt="Error while configuring authentication. The authentication type is not valid."
|
108
|
+
log_txt="Error while configuring authentication. The authentication type is not valid.",
|
107
109
|
)
|
108
110
|
|
109
111
|
initialize_errorhandlers(app)
|
@@ -3,6 +3,7 @@ import os.path
|
|
3
3
|
|
4
4
|
import click
|
5
5
|
from cornflow.shared import db
|
6
|
+
from cornflow.shared.const import MIGRATIONS_DEFAULT_PATH
|
6
7
|
from flask_migrate import Migrate, migrate, upgrade, downgrade, init
|
7
8
|
|
8
9
|
from .utils import get_app
|
@@ -10,6 +11,10 @@ from .utils import get_app
|
|
10
11
|
|
11
12
|
@click.group(name="migrations", help="Commands to manage the migrations")
|
12
13
|
def migrations():
|
14
|
+
"""
|
15
|
+
This method is empty but it serves as the building block
|
16
|
+
for the rest of the commands
|
17
|
+
"""
|
13
18
|
pass
|
14
19
|
|
15
20
|
|
@@ -18,12 +23,12 @@ def migrate_migrations():
|
|
18
23
|
app = get_app()
|
19
24
|
external = int(os.getenv("EXTERNAL_APP", 0))
|
20
25
|
if external == 0:
|
21
|
-
path =
|
26
|
+
path = MIGRATIONS_DEFAULT_PATH
|
22
27
|
else:
|
23
28
|
path = f"./{os.getenv('EXTERNAL_APP_MODULE', 'external_app')}/migrations"
|
24
29
|
|
25
30
|
with app.app_context():
|
26
|
-
|
31
|
+
Migrate(app=app, db=db, directory=path)
|
27
32
|
migrate()
|
28
33
|
|
29
34
|
|
@@ -35,12 +40,12 @@ def upgrade_migrations(revision="head"):
|
|
35
40
|
app = get_app()
|
36
41
|
external = int(os.getenv("EXTERNAL_APP", 0))
|
37
42
|
if external == 0:
|
38
|
-
path =
|
43
|
+
path = MIGRATIONS_DEFAULT_PATH
|
39
44
|
else:
|
40
45
|
path = f"./{os.getenv('EXTERNAL_APP_MODULE', 'external_app')}/migrations"
|
41
46
|
|
42
47
|
with app.app_context():
|
43
|
-
|
48
|
+
Migrate(app=app, db=db, directory=path)
|
44
49
|
upgrade(revision=revision)
|
45
50
|
|
46
51
|
|
@@ -52,12 +57,12 @@ def downgrade_migrations(revision="-1"):
|
|
52
57
|
app = get_app()
|
53
58
|
external = int(os.getenv("EXTERNAL_APP", 0))
|
54
59
|
if external == 0:
|
55
|
-
path =
|
60
|
+
path = MIGRATIONS_DEFAULT_PATH
|
56
61
|
else:
|
57
62
|
path = f"./{os.getenv('EXTERNAL_APP_MODULE', 'external_app')}/migrations"
|
58
63
|
|
59
64
|
with app.app_context():
|
60
|
-
|
65
|
+
Migrate(app=app, db=db, directory=path)
|
61
66
|
downgrade(revision=revision)
|
62
67
|
|
63
68
|
|
@@ -69,10 +74,10 @@ def init_migrations():
|
|
69
74
|
app = get_app()
|
70
75
|
external = int(os.getenv("EXTERNAL_APP", 0))
|
71
76
|
if external == 0:
|
72
|
-
path =
|
77
|
+
path = MIGRATIONS_DEFAULT_PATH
|
73
78
|
else:
|
74
79
|
path = f"./{os.getenv('EXTERNAL_APP_MODULE', 'external_app')}/migrations"
|
75
80
|
|
76
81
|
with app.app_context():
|
77
|
-
|
82
|
+
Migrate(app=app, db=db, directory=path)
|
78
83
|
init()
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
File that implements the generate from schema cli command
|
3
3
|
"""
|
4
|
+
|
4
5
|
import click
|
5
6
|
from .tools.api_generator import APIGenerator
|
6
7
|
from .tools.schema_generator import SchemaGenerator
|
@@ -20,6 +21,10 @@ METHOD_OPTIONS = [
|
|
20
21
|
|
21
22
|
@click.group(name="schemas", help="Commands to manage the schemas")
|
22
23
|
def schemas():
|
24
|
+
"""
|
25
|
+
This method is empty but it serves as the building block
|
26
|
+
for the rest of the commands
|
27
|
+
"""
|
23
28
|
pass
|
24
29
|
|
25
30
|
|
@@ -0,0 +1,399 @@
|
|
1
|
+
import os
|
2
|
+
import subprocess
|
3
|
+
import sys
|
4
|
+
import time
|
5
|
+
from logging import error
|
6
|
+
|
7
|
+
|
8
|
+
import click
|
9
|
+
from .utils import get_db_conn
|
10
|
+
import cornflow
|
11
|
+
from cornflow.app import create_app
|
12
|
+
from cornflow.commands import (
|
13
|
+
access_init_command,
|
14
|
+
create_user_with_role,
|
15
|
+
register_deployed_dags_command,
|
16
|
+
register_dag_permissions_command,
|
17
|
+
update_schemas_command,
|
18
|
+
update_dag_registry_command,
|
19
|
+
)
|
20
|
+
from cornflow.shared.const import (
|
21
|
+
AUTH_DB,
|
22
|
+
AUTH_LDAP,
|
23
|
+
AUTH_OID,
|
24
|
+
ADMIN_ROLE,
|
25
|
+
SERVICE_ROLE,
|
26
|
+
PLANNER_ROLE,
|
27
|
+
DATABRICKS_BACKEND,
|
28
|
+
AIRFLOW_BACKEND,
|
29
|
+
)
|
30
|
+
from cornflow.shared import db
|
31
|
+
from cryptography.fernet import Fernet
|
32
|
+
from flask_migrate import Migrate, upgrade
|
33
|
+
|
34
|
+
MAIN_WD = "/usr/src/app"
|
35
|
+
|
36
|
+
|
37
|
+
@click.group(name="service", help="Commands to run the cornflow service")
|
38
|
+
def service():
|
39
|
+
"""
|
40
|
+
This method is empty but it serves as the building block
|
41
|
+
for the rest of the commands
|
42
|
+
"""
|
43
|
+
pass
|
44
|
+
|
45
|
+
|
46
|
+
@service.command(name="init", help="Initialize the service")
|
47
|
+
def init_cornflow_service():
|
48
|
+
click.echo("Starting the service")
|
49
|
+
os.chdir(MAIN_WD)
|
50
|
+
|
51
|
+
config = _setup_environment_variables()
|
52
|
+
_configure_logging(config["cornflow_logging"])
|
53
|
+
|
54
|
+
external_application = config["external_application"]
|
55
|
+
environment = config["environment"]
|
56
|
+
cornflow_db_conn = config["cornflow_db_conn"]
|
57
|
+
external_app_module = config["external_app_module"]
|
58
|
+
|
59
|
+
app = None # Initialize app to None
|
60
|
+
|
61
|
+
if external_application == 0:
|
62
|
+
click.echo("Initializing standard Cornflow application")
|
63
|
+
app = create_app(environment, cornflow_db_conn)
|
64
|
+
with app.app_context():
|
65
|
+
_initialize_database(app)
|
66
|
+
_create_initial_users(
|
67
|
+
config["auth"],
|
68
|
+
config["cornflow_admin_user"],
|
69
|
+
config["cornflow_admin_email"],
|
70
|
+
config["cornflow_admin_pwd"],
|
71
|
+
config["cornflow_service_user"],
|
72
|
+
config["cornflow_service_email"],
|
73
|
+
config["cornflow_service_pwd"],
|
74
|
+
)
|
75
|
+
if config["cornflow_backend"] == AIRFLOW_BACKEND:
|
76
|
+
_sync_with_airflow(
|
77
|
+
config["airflow_url"],
|
78
|
+
config["airflow_user"],
|
79
|
+
config["airflow_pwd"],
|
80
|
+
config["open_deployment"],
|
81
|
+
external_app=False,
|
82
|
+
)
|
83
|
+
_start_application(external_application, environment)
|
84
|
+
|
85
|
+
elif external_application == 1:
|
86
|
+
click.echo(f"Initializing Cornflow with external app: {external_app_module}")
|
87
|
+
if not external_app_module:
|
88
|
+
sys.exit("FATAL: EXTERNAL_APP is 1 but EXTERNAL_APP_MODULE is not set.")
|
89
|
+
|
90
|
+
_setup_external_app()
|
91
|
+
from importlib import import_module
|
92
|
+
|
93
|
+
external_app_lib = import_module(external_app_module)
|
94
|
+
app = external_app_lib.create_wsgi_app(environment, cornflow_db_conn)
|
95
|
+
|
96
|
+
with app.app_context():
|
97
|
+
_initialize_database(app, external_app_module)
|
98
|
+
_create_initial_users(
|
99
|
+
config["auth"],
|
100
|
+
config["cornflow_admin_user"],
|
101
|
+
config["cornflow_admin_email"],
|
102
|
+
config["cornflow_admin_pwd"],
|
103
|
+
config["cornflow_service_user"],
|
104
|
+
config["cornflow_service_email"],
|
105
|
+
config["cornflow_service_pwd"],
|
106
|
+
)
|
107
|
+
if config["cornflow_backend"] == AIRFLOW_BACKEND:
|
108
|
+
_sync_with_airflow(
|
109
|
+
config["airflow_url"],
|
110
|
+
config["airflow_user"],
|
111
|
+
config["airflow_pwd"],
|
112
|
+
config["open_deployment"],
|
113
|
+
external_app=True,
|
114
|
+
)
|
115
|
+
_start_application(external_application, environment, external_app_module)
|
116
|
+
|
117
|
+
else:
|
118
|
+
# This case should ideally be caught earlier or handled differently
|
119
|
+
sys.exit(f"FATAL: Invalid EXTERNAL_APP value: {external_application}")
|
120
|
+
|
121
|
+
|
122
|
+
def _setup_environment_variables():
|
123
|
+
"""Reads environment variables, sets defaults, and returns config values."""
|
124
|
+
environment = os.getenv("FLASK_ENV", "development")
|
125
|
+
os.environ["FLASK_ENV"] = environment
|
126
|
+
|
127
|
+
###################################
|
128
|
+
# Global defaults and back-compat #
|
129
|
+
###################################
|
130
|
+
# cornflow backend selection
|
131
|
+
cornflow_backend = os.getenv("CORNFLOW_BACKEND", str(AIRFLOW_BACKEND))
|
132
|
+
os.environ["CORNFLOW_BACKEND"] = cornflow_backend
|
133
|
+
cornflow_backend = int(cornflow_backend)
|
134
|
+
# Airflow global default conn
|
135
|
+
if cornflow_backend == AIRFLOW_BACKEND:
|
136
|
+
airflow_user = os.getenv("AIRFLOW_USER", "admin")
|
137
|
+
airflow_pwd = os.getenv("AIRFLOW_PWD", "admin")
|
138
|
+
airflow_url = os.getenv("AIRFLOW_URL", "http://webserver:8080")
|
139
|
+
os.environ["AIRFLOW_USER"] = airflow_user
|
140
|
+
os.environ["AIRFLOW_PWD"] = airflow_pwd
|
141
|
+
os.environ["AIRFLOW_URL"] = airflow_url
|
142
|
+
elif cornflow_backend == DATABRICKS_BACKEND:
|
143
|
+
databricks_url = os.getenv("DATABRICKS_HOST")
|
144
|
+
databricks_auth_secret = os.getenv("DATABRICKS_CLIENT_SECRET")
|
145
|
+
databricks_token_endpoint = os.getenv("DATABRICKS_TOKEN_ENDPOINT")
|
146
|
+
databricks_ep_clusters = os.getenv("DATABRICKS_EP_CLUSTERS")
|
147
|
+
databricks_client_id = os.getenv("DATABRICKS_CLIENT_ID")
|
148
|
+
os.environ["DATABRICKS_HOST"] = databricks_url
|
149
|
+
os.environ["DATABRICKS_CLIENT_SECRET"] = databricks_auth_secret
|
150
|
+
os.environ["DATABRICKS_TOKEN_ENDPOINT"] = databricks_token_endpoint
|
151
|
+
os.environ["DATABRICKS_EP_CLUSTERS"] = databricks_ep_clusters
|
152
|
+
os.environ["DATABRICKS_CLIENT_ID"] = databricks_client_id
|
153
|
+
else:
|
154
|
+
raise Exception("Selected backend not among valid options")
|
155
|
+
# Cornflow app config
|
156
|
+
os.environ.setdefault("cornflow_url", "http://cornflow:5000")
|
157
|
+
os.environ["FLASK_APP"] = "cornflow.app"
|
158
|
+
os.environ["SECRET_KEY"] = os.getenv("FERNET_KEY", Fernet.generate_key().decode())
|
159
|
+
|
160
|
+
# Cornflow db defaults
|
161
|
+
os.environ["DEFAULT_POSTGRES"] = "1"
|
162
|
+
cornflow_db_conn = get_db_conn()
|
163
|
+
os.environ["DATABASE_URL"] = cornflow_db_conn
|
164
|
+
|
165
|
+
# Platform auth config and service users
|
166
|
+
auth = int(os.getenv("AUTH_TYPE", AUTH_DB))
|
167
|
+
cornflow_admin_user = os.getenv("CORNFLOW_ADMIN_USER", "cornflow_admin")
|
168
|
+
cornflow_admin_email = os.getenv(
|
169
|
+
"CORNFLOW_ADMIN_EMAIL", "cornflow_admin@cornflow.com"
|
170
|
+
)
|
171
|
+
cornflow_admin_pwd = os.getenv("CORNFLOW_ADMIN_PWD", "Cornflow_admin1234")
|
172
|
+
cornflow_service_user = os.getenv("CORNFLOW_SERVICE_USER", "service_user")
|
173
|
+
cornflow_service_email = os.getenv(
|
174
|
+
"CORNFLOW_SERVICE_EMAIL", "service_user@cornflow.com"
|
175
|
+
)
|
176
|
+
cornflow_service_pwd = os.getenv("CORNFLOW_SERVICE_PWD", "Service_user1234")
|
177
|
+
|
178
|
+
# Cornflow logging and deployment config
|
179
|
+
cornflow_logging = os.getenv("CORNFLOW_LOGGING", "console")
|
180
|
+
os.environ["CORNFLOW_LOGGING"] = cornflow_logging
|
181
|
+
open_deployment = os.getenv("OPEN_DEPLOYMENT", 1)
|
182
|
+
os.environ["OPEN_DEPLOYMENT"] = str(open_deployment)
|
183
|
+
signup_activated = os.getenv("SIGNUP_ACTIVATED", 1)
|
184
|
+
os.environ["SIGNUP_ACTIVATED"] = str(signup_activated)
|
185
|
+
user_access_all_objects = os.getenv("USER_ACCESS_ALL_OBJECTS", 0)
|
186
|
+
os.environ["USER_ACCESS_ALL_OBJECTS"] = str(user_access_all_objects)
|
187
|
+
default_role = int(os.getenv("DEFAULT_ROLE", PLANNER_ROLE))
|
188
|
+
os.environ["DEFAULT_ROLE"] = str(default_role)
|
189
|
+
|
190
|
+
# Check LDAP parameters for active directory and show message
|
191
|
+
if auth == AUTH_LDAP:
|
192
|
+
click.echo(
|
193
|
+
"WARNING: Cornflow will be deployed with LDAP Authorization. "
|
194
|
+
"Please review your ldap auth configuration."
|
195
|
+
)
|
196
|
+
|
197
|
+
# check database param from docker env
|
198
|
+
if cornflow_db_conn is None:
|
199
|
+
sys.exit("FATAL: you need to provide a postgres database for Cornflow")
|
200
|
+
|
201
|
+
external_application = int(os.getenv("EXTERNAL_APP", 0))
|
202
|
+
external_app_module = os.getenv("EXTERNAL_APP_MODULE")
|
203
|
+
if cornflow_backend == AIRFLOW_BACKEND:
|
204
|
+
return {
|
205
|
+
"environment": environment,
|
206
|
+
"auth": auth,
|
207
|
+
"airflow_user": airflow_user,
|
208
|
+
"airflow_pwd": airflow_pwd,
|
209
|
+
"airflow_url": airflow_url,
|
210
|
+
"cornflow_db_conn": cornflow_db_conn,
|
211
|
+
"cornflow_admin_user": cornflow_admin_user,
|
212
|
+
"cornflow_admin_email": cornflow_admin_email,
|
213
|
+
"cornflow_admin_pwd": cornflow_admin_pwd,
|
214
|
+
"cornflow_service_user": cornflow_service_user,
|
215
|
+
"cornflow_service_email": cornflow_service_email,
|
216
|
+
"cornflow_service_pwd": cornflow_service_pwd,
|
217
|
+
"cornflow_logging": cornflow_logging,
|
218
|
+
"open_deployment": open_deployment,
|
219
|
+
"external_application": external_application,
|
220
|
+
"external_app_module": external_app_module,
|
221
|
+
}
|
222
|
+
elif cornflow_backend == DATABRICKS_BACKEND:
|
223
|
+
return {
|
224
|
+
"environment": environment,
|
225
|
+
"auth": auth,
|
226
|
+
"databricks_url": databricks_url,
|
227
|
+
"databricks_auth_secret": databricks_auth_secret,
|
228
|
+
"databricks_token_endpoint": databricks_token_endpoint,
|
229
|
+
"databricks_ep_clusters": databricks_ep_clusters,
|
230
|
+
"databricks_client_id": databricks_client_id,
|
231
|
+
"cornflow_db_conn": cornflow_db_conn,
|
232
|
+
"cornflow_admin_user": cornflow_admin_user,
|
233
|
+
"cornflow_admin_email": cornflow_admin_email,
|
234
|
+
"cornflow_admin_pwd": cornflow_admin_pwd,
|
235
|
+
"cornflow_service_user": cornflow_service_user,
|
236
|
+
"cornflow_service_email": cornflow_service_email,
|
237
|
+
"cornflow_service_pwd": cornflow_service_pwd,
|
238
|
+
"cornflow_logging": cornflow_logging,
|
239
|
+
"open_deployment": open_deployment,
|
240
|
+
"external_application": external_application,
|
241
|
+
"external_app_module": external_app_module,
|
242
|
+
}
|
243
|
+
else:
|
244
|
+
raise Exception("Selected backend not among valid options")
|
245
|
+
|
246
|
+
|
247
|
+
def _configure_logging(cornflow_logging):
|
248
|
+
"""Configures log rotation if logging to file."""
|
249
|
+
if cornflow_logging == "file":
|
250
|
+
try:
|
251
|
+
conf = f"""/usr/src/app/log/*.log {{
|
252
|
+
rotate 30
|
253
|
+
daily
|
254
|
+
compress
|
255
|
+
size 20M
|
256
|
+
postrotate
|
257
|
+
kill -HUP $(cat {MAIN_WD}/gunicorn.pid)
|
258
|
+
endscript}}"""
|
259
|
+
logrotate = subprocess.run(
|
260
|
+
f"cat > /etc/logrotate.d/cornflow <<EOF\n {conf} \nEOF",
|
261
|
+
shell=True,
|
262
|
+
capture_output=True,
|
263
|
+
text=True,
|
264
|
+
)
|
265
|
+
if logrotate.returncode != 0:
|
266
|
+
error(f"Error configuring logrotate: {logrotate.stderr}")
|
267
|
+
else:
|
268
|
+
print(logrotate.stdout)
|
269
|
+
except Exception as e:
|
270
|
+
error(f"Exception during logrotate configuration: {e}")
|
271
|
+
|
272
|
+
|
273
|
+
def _initialize_database(app, external_app_module=None):
|
274
|
+
"""Initializes the database and runs migrations."""
|
275
|
+
with app.app_context():
|
276
|
+
if external_app_module:
|
277
|
+
from importlib import import_module
|
278
|
+
|
279
|
+
external_app_lib = import_module(external_app_module)
|
280
|
+
migrations_path = f"{os.path.dirname(external_app_lib.__file__)}/migrations"
|
281
|
+
else:
|
282
|
+
migrations_path = f"{os.path.dirname(cornflow.__file__)}/migrations"
|
283
|
+
|
284
|
+
Migrate(app=app, db=db, directory=migrations_path)
|
285
|
+
upgrade()
|
286
|
+
access_init_command(verbose=False)
|
287
|
+
|
288
|
+
|
289
|
+
def _create_initial_users(
|
290
|
+
auth,
|
291
|
+
admin_user,
|
292
|
+
admin_email,
|
293
|
+
admin_pwd,
|
294
|
+
service_user,
|
295
|
+
service_email,
|
296
|
+
service_pwd,
|
297
|
+
):
|
298
|
+
"""Creates the initial admin and service users if using DB or OID auth."""
|
299
|
+
if auth == AUTH_DB or auth == AUTH_OID:
|
300
|
+
# create cornflow admin user
|
301
|
+
create_user_with_role(
|
302
|
+
admin_user,
|
303
|
+
admin_email,
|
304
|
+
admin_pwd,
|
305
|
+
"admin",
|
306
|
+
ADMIN_ROLE,
|
307
|
+
verbose=True,
|
308
|
+
)
|
309
|
+
# create cornflow service user
|
310
|
+
create_user_with_role(
|
311
|
+
service_user,
|
312
|
+
service_email,
|
313
|
+
service_pwd,
|
314
|
+
"serviceuser",
|
315
|
+
SERVICE_ROLE,
|
316
|
+
verbose=True,
|
317
|
+
)
|
318
|
+
|
319
|
+
|
320
|
+
def _sync_with_airflow(
|
321
|
+
airflow_url, airflow_user, airflow_pwd, open_deployment, external_app=False
|
322
|
+
):
|
323
|
+
"""Syncs DAGs, permissions, and schemas with Airflow."""
|
324
|
+
register_deployed_dags_command(airflow_url, airflow_user, airflow_pwd, verbose=True)
|
325
|
+
register_dag_permissions_command(open_deployment, verbose=True)
|
326
|
+
update_schemas_command(airflow_url, airflow_user, airflow_pwd, verbose=True)
|
327
|
+
if external_app:
|
328
|
+
update_dag_registry_command(
|
329
|
+
airflow_url, airflow_user, airflow_pwd, verbose=True
|
330
|
+
)
|
331
|
+
|
332
|
+
|
333
|
+
def _setup_external_app():
|
334
|
+
"""Performs setup steps specific to external applications."""
|
335
|
+
os.chdir(MAIN_WD)
|
336
|
+
if _register_key():
|
337
|
+
prefix = "CUSTOM_SSH_"
|
338
|
+
env_variables = {
|
339
|
+
key: value for key, value in os.environ.items() if key.startswith(prefix)
|
340
|
+
}
|
341
|
+
for _, value in env_variables.items():
|
342
|
+
_register_ssh_host(value)
|
343
|
+
|
344
|
+
# Install requirements for the external app
|
345
|
+
pip_install_cmd = "$(command -v pip) install --user -r requirements.txt"
|
346
|
+
click.echo(f"Running: {pip_install_cmd}")
|
347
|
+
result = subprocess.run(pip_install_cmd, shell=True, capture_output=True, text=True)
|
348
|
+
if result.returncode != 0:
|
349
|
+
error(f"Error installing requirements: {result.stderr}")
|
350
|
+
else:
|
351
|
+
print(result.stdout)
|
352
|
+
time.sleep(5) # Consider if this sleep is truly necessary
|
353
|
+
sys.path.append(MAIN_WD)
|
354
|
+
|
355
|
+
|
356
|
+
def _start_application(external_application, environment, external_app_module=None):
|
357
|
+
"""Starts the Gunicorn server."""
|
358
|
+
if external_application == 0:
|
359
|
+
os.environ["GUNICORN_WORKING_DIR"] = MAIN_WD
|
360
|
+
gunicorn_cmd = (
|
361
|
+
"/usr/local/bin/gunicorn -c python:cornflow.gunicorn "
|
362
|
+
f"\"cornflow.app:create_app('{environment}')\""
|
363
|
+
)
|
364
|
+
elif external_application == 1:
|
365
|
+
os.environ["GUNICORN_WORKING_DIR"] = MAIN_WD
|
366
|
+
if not external_app_module:
|
367
|
+
raise ValueError(
|
368
|
+
"EXTERNAL_APP_MODULE must be set for external applications"
|
369
|
+
)
|
370
|
+
gunicorn_cmd = (
|
371
|
+
"/usr/local/bin/gunicorn -c python:cornflow.gunicorn "
|
372
|
+
f"\"{external_app_module}:create_wsgi_app('{environment}')\""
|
373
|
+
)
|
374
|
+
else:
|
375
|
+
raise ValueError(f"Invalid EXTERNAL_APP value: {external_application}")
|
376
|
+
|
377
|
+
click.echo(f"Starting application with Gunicorn: {gunicorn_cmd}")
|
378
|
+
os.system(gunicorn_cmd)
|
379
|
+
|
380
|
+
|
381
|
+
def _register_ssh_host(host):
|
382
|
+
if host is not None:
|
383
|
+
add_host = f"ssh-keyscan {host} >> {MAIN_WD}/.ssh/known_hosts"
|
384
|
+
config_ssh_host = f"echo Host {host} >> {MAIN_WD}/.ssh/config"
|
385
|
+
config_ssh_key = (
|
386
|
+
'echo " IdentityFile {MAIN_WD}/.ssh/id_rsa" >> {MAIN_WD}/.ssh/config'
|
387
|
+
)
|
388
|
+
os.system(add_host)
|
389
|
+
os.system(config_ssh_host)
|
390
|
+
os.system(config_ssh_key)
|
391
|
+
|
392
|
+
|
393
|
+
def _register_key():
|
394
|
+
if os.path.isfile(f"{MAIN_WD}/.ssh/id_rsa"):
|
395
|
+
add_key = f"chmod 0600 {MAIN_WD}/.ssh/id_rsa && ssh-add {MAIN_WD}/.ssh/id_rsa"
|
396
|
+
os.system(add_key)
|
397
|
+
return True
|
398
|
+
else:
|
399
|
+
return False
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
This file has the class that creates the new API
|
3
3
|
"""
|
4
|
+
|
4
5
|
import json
|
5
6
|
import os
|
6
7
|
import re
|
@@ -10,6 +11,8 @@ from .models_tools import ModelGenerator, model_shared_imports
|
|
10
11
|
from .schemas_tools import SchemaGenerator, schemas_imports
|
11
12
|
from .tools import generate_class_def
|
12
13
|
|
14
|
+
INIT_FILE = "__init__.py"
|
15
|
+
|
13
16
|
|
14
17
|
class APIGenerator:
|
15
18
|
"""
|
@@ -52,7 +55,7 @@ class APIGenerator:
|
|
52
55
|
self.endpoint_path = os.path.join(self.output_path, "endpoints")
|
53
56
|
self.schema_path = os.path.join(self.output_path, "schemas")
|
54
57
|
self.init_resources = []
|
55
|
-
self.init_file = os.path.join(self.endpoint_path,
|
58
|
+
self.init_file = os.path.join(self.endpoint_path, INIT_FILE)
|
56
59
|
|
57
60
|
def import_schema(self) -> dict:
|
58
61
|
"""
|
@@ -77,23 +80,23 @@ class APIGenerator:
|
|
77
80
|
if not os.path.isdir(self.model_path):
|
78
81
|
os.mkdir(self.model_path)
|
79
82
|
|
80
|
-
init_path = os.path.join(self.model_path,
|
83
|
+
init_path = os.path.join(self.model_path, INIT_FILE)
|
81
84
|
with open(init_path, "w") as file:
|
82
|
-
file.write(
|
85
|
+
file.write("\nThis file exposes the models\n\n")
|
83
86
|
|
84
87
|
if not os.path.isdir(self.endpoint_path):
|
85
88
|
os.mkdir(self.endpoint_path)
|
86
89
|
|
87
|
-
init_path = os.path.join(self.endpoint_path,
|
90
|
+
init_path = os.path.join(self.endpoint_path, INIT_FILE)
|
88
91
|
with open(init_path, "w") as file:
|
89
|
-
file.write(
|
92
|
+
file.write("\nThis file exposes the endpoints\n\n")
|
90
93
|
|
91
94
|
if not os.path.isdir(self.schema_path):
|
92
95
|
os.mkdir(self.schema_path)
|
93
96
|
|
94
|
-
init_path = os.path.join(self.schema_path,
|
97
|
+
init_path = os.path.join(self.schema_path, INIT_FILE)
|
95
98
|
with open(init_path, "w") as file:
|
96
|
-
file.write(
|
99
|
+
file.write("\nThis file exposes the schemas\n\n")
|
97
100
|
|
98
101
|
def main(self):
|
99
102
|
"""
|
@@ -151,7 +154,7 @@ class APIGenerator:
|
|
151
154
|
fd.write(mg.generate_model_repr_str())
|
152
155
|
fd.write("\n")
|
153
156
|
|
154
|
-
init_file = os.path.join(self.model_path,
|
157
|
+
init_file = os.path.join(self.model_path, INIT_FILE)
|
155
158
|
|
156
159
|
with open(init_file, "a") as file:
|
157
160
|
file.write(f"from .{self.prefix}{table_name} import {class_name}\n")
|
@@ -207,7 +210,7 @@ class APIGenerator:
|
|
207
210
|
fd.write(generate_class_def(class_name_one, parents_class))
|
208
211
|
fd.write(sg.generate_schema())
|
209
212
|
|
210
|
-
init_file = os.path.join(self.schema_path,
|
213
|
+
init_file = os.path.join(self.schema_path, INIT_FILE)
|
211
214
|
with open(init_file, "a") as file:
|
212
215
|
file.write(
|
213
216
|
f"from .{self.prefix}{table_name} import {class_name_one}, "
|
@@ -432,7 +435,7 @@ class APIGenerator:
|
|
432
435
|
:return: str: the type in format "<type:idx>"
|
433
436
|
"""
|
434
437
|
schema_table = self.schema["properties"][table_name]["items"]["properties"]
|
435
|
-
id_type=None
|
438
|
+
id_type = None
|
436
439
|
if "id" in schema_table.keys():
|
437
440
|
id_type = schema_table["id"]["type"]
|
438
441
|
if id_type == "string" or isinstance(id_type, list):
|