Disable experimental REST API by default (#12337)
This commit is contained in:
Родитель
d5589673a9
Коммит
abce78c53b
|
@ -52,6 +52,14 @@ assists users migrating to a new version.
|
|||
|
||||
## Master
|
||||
|
||||
### The experimental REST API is disabled by default
|
||||
|
||||
The experimental REST API is disabled by default. To restore these APIs while migrating to
|
||||
the stable REST API, set `enable_experimental_api` option in `[api]` section to `True`.
|
||||
|
||||
Please note that the experimental REST API do not have access control.
|
||||
The authenticated user has full access.
|
||||
|
||||
### SparkJDBCHook default connection
|
||||
|
||||
For SparkJDBCHook default connection was `spark-default`, and for SparkSubmitHook it was
|
||||
|
|
|
@ -699,6 +699,22 @@
|
|||
- name: api
|
||||
description: ~
|
||||
options:
|
||||
- name: enable_experimental_api
|
||||
description: |
|
||||
Enables the deprecated experimental API. Please note that these APIs do not have access control.
|
||||
The authenticated user has full access.
|
||||
|
||||
.. warning::
|
||||
|
||||
This `Experimental REST API <https://airflow.readthedocs.io/en/latest/rest-api-ref.html>`__ is
|
||||
deprecated since version 2.0. Please consider using
|
||||
`the Stable REST API <https://airflow.readthedocs.io/en/latest/stable-rest-api-ref.html>`__.
|
||||
For more information on migration, see
|
||||
`UPDATING.md <https://github.com/apache/airflow/blob/master/UPDATING.md>`_
|
||||
version_added: 2.0.0
|
||||
type: boolean
|
||||
example: ~
|
||||
default: "False"
|
||||
- name: auth_backend
|
||||
description: |
|
||||
How to authenticate users of the API. See
|
||||
|
|
|
@ -371,6 +371,18 @@ endpoint_url = http://localhost:8080
|
|||
fail_fast = False
|
||||
|
||||
[api]
|
||||
# Enables the deprecated experimental API. Please note that these APIs do not have access control.
|
||||
# The authenticated user has full access.
|
||||
#
|
||||
# .. warning::
|
||||
#
|
||||
# This `Experimental REST API <https://airflow.readthedocs.io/en/latest/rest-api-ref.html>`__ is
|
||||
# deprecated since version 2.0. Please consider using
|
||||
# `the Stable REST API <https://airflow.readthedocs.io/en/latest/stable-rest-api-ref.html>`__.
|
||||
# For more information on migration, see
|
||||
# `UPDATING.md <https://github.com/apache/airflow/blob/master/UPDATING.md>`_
|
||||
enable_experimental_api = False
|
||||
|
||||
# How to authenticate users of the API. See
|
||||
# https://airflow.apache.org/docs/stable/security.html for possible values.
|
||||
# ("airflow.api.auth.backend.default" allows all requests for historic reasons)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
# under the License.
|
||||
|
||||
import logging
|
||||
import warnings
|
||||
from os import path
|
||||
|
||||
import connexion
|
||||
|
@ -23,6 +24,7 @@ from connexion import ProblemException
|
|||
from flask import Flask, request
|
||||
|
||||
from airflow.api_connexion.exceptions import common_error_handler
|
||||
from airflow.configuration import conf
|
||||
from airflow.security import permissions
|
||||
from airflow.www.views import lazy_add_provider_discovered_options_to_connection_form
|
||||
|
||||
|
@ -169,7 +171,15 @@ def init_api_connexion(app: Flask) -> None:
|
|||
|
||||
def init_api_experimental(app):
|
||||
"""Initialize Experimental API"""
|
||||
if not conf.getboolean('api', 'enable_experimental_api', fallback=False):
|
||||
return
|
||||
from airflow.www.api.experimental import endpoints
|
||||
|
||||
warnings.warn(
|
||||
"The experimental REST API is deprecated. Please migrate to the stable REST API. "
|
||||
"Please note that the experimental API do not have access control. "
|
||||
"The authenticated user has full access.",
|
||||
DeprecationWarning,
|
||||
)
|
||||
app.register_blueprint(endpoints.api_experimental, url_prefix='/api/experimental')
|
||||
app.extensions['csrf'].exempt(endpoints.api_experimental)
|
||||
|
|
|
@ -26,6 +26,11 @@ available at ``/api/experimental/``.
|
|||
This REST API is deprecated since version 2.0. Please consider using :doc:`the stable REST API <stable-rest-api-ref>`.
|
||||
For more information on migration, see `UPDATING.md <https://github.com/apache/airflow/blob/master/UPDATING.md>`_
|
||||
|
||||
.. versionchanged:: 2.0
|
||||
|
||||
The experimental REST API is disabled by default. To restore these APIs while migrating to
|
||||
the stable REST API, set ``enable_experimental_api`` option in ``[api]`` section to ``True``.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
|
|
|
@ -323,7 +323,8 @@ function kind::deploy_airflow_with_helm() {
|
|||
--set "images.airflow.repository=${DOCKERHUB_USER}/${DOCKERHUB_REPO}" \
|
||||
--set "images.airflow.tag=${AIRFLOW_PROD_BASE_TAG}-kubernetes" -v 1 \
|
||||
--set "defaultAirflowTag=${AIRFLOW_PROD_BASE_TAG}-kubernetes" -v 1 \
|
||||
--set "config.api.auth_backend=airflow.api.auth.backend.default"
|
||||
--set "config.api.auth_backend=airflow.api.auth.backend.default" \
|
||||
--set "config.api.enable_experimental_api=true"
|
||||
echo
|
||||
popd || exit 1
|
||||
}
|
||||
|
|
|
@ -29,7 +29,12 @@ from tests.test_utils.db import clear_db_pools
|
|||
|
||||
class TestBasicAuth(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
with conf_vars({("api", "auth_backend"): "airflow.api.auth.backend.basic_auth"}):
|
||||
with conf_vars(
|
||||
{
|
||||
("api", "auth_backend"): "airflow.api.auth.backend.basic_auth",
|
||||
('api', 'enable_experimental_api'): 'true',
|
||||
}
|
||||
):
|
||||
self.app = create_app(testing=True)
|
||||
|
||||
self.appbuilder = self.app.appbuilder # pylint: disable=no-member
|
||||
|
@ -104,6 +109,7 @@ class TestBasicAuth(unittest.TestCase):
|
|||
assert response.headers["WWW-Authenticate"] == "Basic"
|
||||
assert_401(response)
|
||||
|
||||
@conf_vars({('api', 'enable_experimental_api'): 'true'})
|
||||
def test_experimental_api(self):
|
||||
with self.app.test_client() as test_client:
|
||||
response = test_client.get("/api/experimental/pools", headers={"Authorization": "Basic"})
|
||||
|
|
|
@ -30,7 +30,10 @@ from tests.test_utils.db import clear_db_pools
|
|||
class TestGoogleOpenID(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
with conf_vars(
|
||||
{("api", "auth_backend"): "airflow.providers.google.common.auth_backend.google_openid"}
|
||||
{
|
||||
("api", "auth_backend"): "airflow.providers.google.common.auth_backend.google_openid",
|
||||
('api', 'enable_experimental_api'): 'true',
|
||||
}
|
||||
):
|
||||
self.app = create_app(testing=True)
|
||||
|
||||
|
|
|
@ -29,7 +29,9 @@ class TestGoogleOpenID(unittest.TestCase):
|
|||
def setUp(self) -> None:
|
||||
with conf_vars(
|
||||
{("api", "auth_backend"): "tests.test_utils.remote_user_api_auth_backend"}
|
||||
), mock.patch.dict('os.environ', SKIP_DAGS_PARSING='True'):
|
||||
), mock.patch.dict('os.environ', SKIP_DAGS_PARSING='True'), conf_vars(
|
||||
{('api', 'enable_experimental_api'): 'true'}
|
||||
):
|
||||
self.app = create_app(testing=True)
|
||||
|
||||
self.appbuilder = self.app.appbuilder # pylint: disable=no-member
|
||||
|
|
|
@ -23,6 +23,7 @@ from airflow.models import DagBag, DagRun
|
|||
from airflow.models.serialized_dag import SerializedDagModel
|
||||
from airflow.settings import Session
|
||||
from airflow.www import app as application
|
||||
from tests.test_utils.config import conf_vars
|
||||
|
||||
|
||||
class TestDagRunsEndpoint(unittest.TestCase):
|
||||
|
@ -40,7 +41,12 @@ class TestDagRunsEndpoint(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
app = application.create_app(testing=True)
|
||||
with conf_vars(
|
||||
{
|
||||
('api', 'enable_experimental_api'): 'true',
|
||||
}
|
||||
):
|
||||
app = application.create_app(testing=True)
|
||||
self.app = app.test_client()
|
||||
|
||||
def tearDown(self):
|
||||
|
|
|
@ -30,6 +30,7 @@ from airflow.settings import Session
|
|||
from airflow.utils.timezone import datetime, parse as parse_datetime, utcnow
|
||||
from airflow.version import version
|
||||
from airflow.www import app as application
|
||||
from tests.test_utils.config import conf_vars
|
||||
from tests.test_utils.db import clear_db_pools
|
||||
|
||||
ROOT_FOLDER = os.path.realpath(
|
||||
|
@ -38,6 +39,7 @@ ROOT_FOLDER = os.path.realpath(
|
|||
|
||||
|
||||
class TestBase(unittest.TestCase):
|
||||
@conf_vars({('api', 'enable_experimental_api'): 'true'})
|
||||
def setUp(self):
|
||||
self.app = application.create_app(testing=True)
|
||||
self.appbuilder = self.app.appbuilder # pylint: disable=no-member
|
||||
|
|
|
@ -46,6 +46,7 @@ class TestApiKerberos(unittest.TestCase):
|
|||
{
|
||||
("api", "auth_backend"): "airflow.api.auth.backend.kerberos_auth",
|
||||
("kerberos", "keytab"): KRB5_KTNAME,
|
||||
('api', 'enable_experimental_api'): 'true',
|
||||
}
|
||||
)
|
||||
def setUp(self):
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import re
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from airflow.www.extensions import init_views
|
||||
from tests.test_utils.config import conf_vars
|
||||
|
||||
|
||||
class TestInitApiExperimental(unittest.TestCase):
|
||||
@conf_vars({('api', 'enable_experimental_api'): 'true'})
|
||||
def test_should_raise_deprecation_warning_when_enabled(self):
|
||||
app = mock.MagicMock()
|
||||
with self.assertWarnsRegex(DeprecationWarning, re.escape("The experimental REST API is deprecated.")):
|
||||
init_views.init_api_experimental(app)
|
||||
|
||||
@conf_vars({('api', 'enable_experimental_api'): 'false'})
|
||||
def test_should_not_raise_deprecation_warning_when_disabled(self):
|
||||
app = mock.MagicMock()
|
||||
with self.assertRaises(AssertionError), self.assertWarnsRegex(
|
||||
DeprecationWarning, re.escape("The experimental REST API is deprecated.")
|
||||
):
|
||||
init_views.init_api_experimental(app)
|
Загрузка…
Ссылка в новой задаче