Disable experimental REST API by default (#12337)

This commit is contained in:
Kamil Breguła 2020-12-08 20:27:27 +01:00 коммит произвёл GitHub
Родитель d5589673a9
Коммит abce78c53b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 116 добавлений и 5 удалений

Просмотреть файл

@ -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)