This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch v3-0-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-0-test by this push:
new 2770ad2fde2 [v3-0-test] Fix for Edit and Delete request issue 53681
(#53815) (#54268)
2770ad2fde2 is described below
commit 2770ad2fde21cadd40c91304d3f5f45aceeecac1
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Aug 8 22:16:14 2025 +0200
[v3-0-test] Fix for Edit and Delete request issue 53681 (#53815) (#54268)
* Fix for Edit and Delete request
* updated the pool outes by adding path
Fixing the 53681 issue
* removed the UI based Url Encoding
* Updated the pool test cases for testing '/' in poolname
* Updated the PoolName
* updated poolName in testcase
* Faile testcase Resolved
* fix(tests): make pool list ordering test locale-independent
* Fix pool ordering test inconsistency across environments
* Removed Sorted Comparision
(cherry picked from commit 0caa87b061fcb3e398d9a68e489eb50f3722621a)
Co-authored-by: mandeepzemo <[email protected]>
---
.../api_fastapi/core_api/routes/public/pools.py | 6 +-
.../core_api/routes/public/test_pools.py | 89 +++++++++++++++++++---
2 files changed, 81 insertions(+), 14 deletions(-)
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/pools.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/pools.py
index 8cdd2507227..729b82f3bf8 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/pools.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/pools.py
@@ -49,7 +49,7 @@ pools_router = AirflowRouter(tags=["Pool"], prefix="/pools")
@pools_router.delete(
- "/{pool_name}",
+ "/{pool_name:path}",
status_code=status.HTTP_204_NO_CONTENT,
responses=create_openapi_http_exception_doc(
[
@@ -74,7 +74,7 @@ def delete_pool(
@pools_router.get(
- "/{pool_name}",
+ "/{pool_name:path}",
responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]),
dependencies=[Depends(requires_access_pool(method="GET"))],
)
@@ -124,7 +124,7 @@ def get_pools(
@pools_router.patch(
- "/{pool_name}",
+ "/{pool_name:path}",
responses=create_openapi_http_exception_doc(
[
status.HTTP_400_BAD_REQUEST,
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_pools.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_pools.py
index 68c23759136..342b7edfde0 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_pools.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_pools.py
@@ -37,11 +37,23 @@ POOL2_INCLUDE_DEFERRED = False
POOL2_DESCRIPTION = "Some Description"
+POOL3_NAME = "pool3/with_slashes"
+POOL3_SLOT = 5
+POOL3_INCLUDE_DEFERRED = False
+POOL3_DESCRIPTION = "Some Description"
+
+
@provide_session
def _create_pools(session) -> None:
pool1 = Pool(pool=POOL1_NAME, slots=POOL1_SLOT,
include_deferred=POOL1_INCLUDE_DEFERRED)
pool2 = Pool(pool=POOL2_NAME, slots=POOL2_SLOT,
include_deferred=POOL2_INCLUDE_DEFERRED)
- session.add_all([pool1, pool2])
+ pool3 = Pool(
+ pool=POOL3_NAME,
+ slots=POOL3_SLOT,
+ include_deferred=POOL3_INCLUDE_DEFERRED,
+ description=POOL3_DESCRIPTION,
+ )
+ session.add_all([pool1, pool2, pool3])
class TestPoolsEndpoint:
@@ -60,11 +72,11 @@ class TestDeletePool(TestPoolsEndpoint):
def test_delete_should_respond_204(self, test_client, session):
self.create_pools()
pools = session.query(Pool).all()
- assert len(pools) == 3
+ assert len(pools) == 4
response = test_client.delete(f"/pools/{POOL1_NAME}")
assert response.status_code == 204
pools = session.query(Pool).all()
- assert len(pools) == 2
+ assert len(pools) == 3
check_last_log(session, dag_id=None, event="delete_pool",
logical_date=None)
def test_delete_should_respond_401(self, unauthenticated_test_client):
@@ -87,6 +99,17 @@ class TestDeletePool(TestPoolsEndpoint):
body = response.json()
assert f"The Pool with name: `{POOL1_NAME}` was not found" ==
body["detail"]
+ def test_delete_pool3_should_respond_204(self, test_client, session):
+ """Test deleting POOL3 with forward slash in name"""
+ self.create_pools()
+ pools = session.query(Pool).all()
+ assert len(pools) == 4
+ response = test_client.delete(f"/pools/{POOL3_NAME}")
+ assert response.status_code == 204
+ pools = session.query(Pool).all()
+ assert len(pools) == 3
+ check_last_log(session, dag_id=None, event="delete_pool",
logical_date=None)
+
class TestGetPool(TestPoolsEndpoint):
def test_get_should_respond_200(self, test_client, session):
@@ -120,24 +143,42 @@ class TestGetPool(TestPoolsEndpoint):
body = response.json()
assert f"The Pool with name: `{POOL1_NAME}` was not found" ==
body["detail"]
+ def test_get_pool3_should_respond_200(self, test_client, session):
+ """Test getting POOL3 with forward slash in name"""
+ self.create_pools()
+ response = test_client.get(f"/pools/{POOL3_NAME}")
+ assert response.status_code == 200
+ assert response.json() == {
+ "deferred_slots": 0,
+ "description": "Some Description",
+ "include_deferred": False,
+ "name": "pool3/with_slashes",
+ "occupied_slots": 0,
+ "open_slots": 5,
+ "queued_slots": 0,
+ "running_slots": 0,
+ "scheduled_slots": 0,
+ "slots": 5,
+ }
+
class TestGetPools(TestPoolsEndpoint):
@pytest.mark.parametrize(
"query_params, expected_total_entries, expected_ids",
[
# Filters
- ({}, 3, [Pool.DEFAULT_POOL_NAME, POOL1_NAME, POOL2_NAME]),
- ({"limit": 1}, 3, [Pool.DEFAULT_POOL_NAME]),
- ({"limit": 1, "offset": 1}, 3, [POOL1_NAME]),
+ ({}, 4, [Pool.DEFAULT_POOL_NAME, POOL1_NAME, POOL2_NAME,
POOL3_NAME]),
+ ({"limit": 1}, 4, [Pool.DEFAULT_POOL_NAME]),
+ ({"limit": 1, "offset": 1}, 4, [POOL1_NAME]),
# Sort
- ({"order_by": "-id"}, 3, [POOL2_NAME, POOL1_NAME,
Pool.DEFAULT_POOL_NAME]),
- ({"order_by": "id"}, 3, [Pool.DEFAULT_POOL_NAME, POOL1_NAME,
POOL2_NAME]),
- ({"order_by": "name"}, 3, [Pool.DEFAULT_POOL_NAME, POOL1_NAME,
POOL2_NAME]),
+ ({"order_by": "-id"}, 4, [POOL3_NAME, POOL2_NAME, POOL1_NAME,
Pool.DEFAULT_POOL_NAME]),
+ ({"order_by": "id"}, 4, [Pool.DEFAULT_POOL_NAME, POOL1_NAME,
POOL2_NAME, POOL3_NAME]),
+ ({"order_by": "name"}, 4, [Pool.DEFAULT_POOL_NAME, POOL1_NAME,
POOL2_NAME, POOL3_NAME]),
# Search
(
{"pool_name_pattern": "~"},
- 3,
- [Pool.DEFAULT_POOL_NAME, POOL1_NAME, POOL2_NAME],
+ 4,
+ [Pool.DEFAULT_POOL_NAME, POOL1_NAME, POOL2_NAME, POOL3_NAME],
),
({"pool_name_pattern": "default"}, 1, [Pool.DEFAULT_POOL_NAME]),
],
@@ -314,6 +355,32 @@ class TestPatchPool(TestPoolsEndpoint):
response = unauthorized_test_client.patch(f"/pools/{POOL1_NAME}",
params={}, json={})
assert response.status_code == 403
+ def test_patch_pool3_should_respond_200(self, test_client, session):
+ """Test patching POOL3 with forward slash in name"""
+ self.create_pools()
+ body = {
+ "slots": 10,
+ "description": "Updated Description",
+ "name": POOL3_NAME,
+ "include_deferred": True,
+ }
+ response = test_client.patch(f"/pools/{POOL3_NAME}", json=body)
+ assert response.status_code == 200
+ expected_response = {
+ "deferred_slots": 0,
+ "description": "Updated Description",
+ "include_deferred": True,
+ "name": "pool3/with_slashes",
+ "occupied_slots": 0,
+ "open_slots": 10,
+ "queued_slots": 0,
+ "running_slots": 0,
+ "scheduled_slots": 0,
+ "slots": 10,
+ }
+ assert response.json() == expected_response
+ check_last_log(session, dag_id=None, event="patch_pool",
logical_date=None)
+
class TestPostPool(TestPoolsEndpoint):
@pytest.mark.parametrize(