From 3a6ee2aaabfcd6f3eb7843b8a426beb1899edb45 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Wed, 14 Jan 2026 11:36:21 -0800 Subject: [PATCH 1/6] add "azure-asyncoperation" header into mgmt-core --- .../azure/mgmt/core/polling/_utils.py | 47 +++++++++++++++++++ .../azure/mgmt/core/polling/arm_polling.py | 16 ++++++- .../mgmt/core/polling/async_arm_polling.py | 15 +++++- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 sdk/core/azure-mgmt-core/azure/mgmt/core/polling/_utils.py diff --git a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/_utils.py b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/_utils.py new file mode 100644 index 000000000000..0435aa0f5b38 --- /dev/null +++ b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/_utils.py @@ -0,0 +1,47 @@ +# -------------------------------------------------------------------------- +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the ""Software""), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# -------------------------------------------------------------------------- +"""ARM-specific utilities for polling continuation token serialization.""" + +from typing import Dict, Mapping + +from azure.core.polling._utils import _LRO_HEADERS + +# ARM-specific LRO headers - includes azure-asyncoperation which is ARM-specific +_ARM_LRO_HEADERS = _LRO_HEADERS | frozenset(["azure-asyncoperation"]) + + +def _filter_arm_headers(headers: Mapping[str, str]) -> Dict[str, str]: + """Filter headers to only include those needed for ARM LRO rehydration. + + Uses an allowlist approach - only headers required for polling are included. + This includes the azure-asyncoperation header which is ARM-specific. + + :param headers: The headers to filter. + :type headers: Mapping[str, str] + :return: A new dictionary with only allowed headers. + :rtype: dict[str, str] + """ + return {k: v for k, v in headers.items() if k.lower() in _ARM_LRO_HEADERS} diff --git a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/arm_polling.py b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/arm_polling.py index a17844612a04..b27491808016 100644 --- a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/arm_polling.py +++ b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/arm_polling.py @@ -24,7 +24,7 @@ # # -------------------------------------------------------------------------- from enum import Enum -from typing import Optional, Union, TypeVar, Dict, Any, Sequence +from typing import Optional, Union, TypeVar, Dict, Any, Sequence, Mapping from azure.core import CaseInsensitiveEnumMeta from azure.core.polling.base_polling import ( @@ -47,6 +47,8 @@ ) from azure.core.rest import HttpRequest, HttpResponse, AsyncHttpResponse +from ._utils import _filter_arm_headers + ResponseType = Union[HttpResponse, AsyncHttpResponse] PipelineResponseType = PipelineResponse[HttpRequest, ResponseType] HttpRequestType = Union[LegacyHttpRequest, HttpRequest] @@ -208,6 +210,18 @@ def __init__( **operation_config ) + def _filter_headers_for_continuation_token(self, headers: Mapping[str, str]) -> Dict[str, str]: + """Filter headers to include in the continuation token. + + ARM-specific override that includes the azure-asyncoperation header. + + :param headers: The response headers to filter. + :type headers: Mapping[str, str] + :return: A filtered dictionary of headers to include in the continuation token. + :rtype: dict[str, str] + """ + return _filter_arm_headers(headers) + __all__ = [ "AzureAsyncOperationPolling", diff --git a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py index 38c123871807..2e60bd70b84b 100644 --- a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py +++ b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py @@ -23,12 +23,13 @@ # IN THE SOFTWARE. # # -------------------------------------------------------------------------- -from typing import Optional, Dict, Any, Sequence +from typing import Optional, Dict, Any, Sequence, Mapping from azure.core.polling.base_polling import LocationPolling, StatusCheckPolling, LongRunningOperation from azure.core.polling.async_base_polling import AsyncLROBasePolling from .arm_polling import AzureAsyncOperationPolling, BodyContentPolling, HttpRequestTypeVar, AllHttpResponseTypeVar +from ._utils import _filter_arm_headers class AsyncARMPolling(AsyncLROBasePolling): @@ -54,5 +55,17 @@ def __init__( **operation_config ) + def _filter_headers_for_continuation_token(self, headers: Mapping[str, str]) -> Dict[str, str]: + """Filter headers to include in the continuation token. + + ARM-specific override that includes the azure-asyncoperation header. + + :param headers: The response headers to filter. + :type headers: Mapping[str, str] + :return: A filtered dictionary of headers to include in the continuation token. + :rtype: dict[str, str] + """ + return _filter_arm_headers(headers) + __all__ = ["AsyncARMPolling"] From 45ee71804ac7faeda102536d648e067eeed7e2ba Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Wed, 14 Jan 2026 11:36:59 -0800 Subject: [PATCH 2/6] bump azure-core dep version --- sdk/core/azure-mgmt-core/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-mgmt-core/setup.py b/sdk/core/azure-mgmt-core/setup.py index 98ebd33128e2..2d738fb2299a 100644 --- a/sdk/core/azure-mgmt-core/setup.py +++ b/sdk/core/azure-mgmt-core/setup.py @@ -69,7 +69,7 @@ "pytyped": ["py.typed"], }, install_requires=[ - "azure-core>=1.32.0", + "azure-core>=1.38.0", ], python_requires=">=3.9", ) From 9cf98310d9024c419bb28e6eb08f1536370a0f95 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Thu, 15 Jan 2026 10:26:09 -0800 Subject: [PATCH 3/6] udpate changelog --- sdk/core/azure-mgmt-core/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sdk/core/azure-mgmt-core/CHANGELOG.md b/sdk/core/azure-mgmt-core/CHANGELOG.md index c5ae2fbe9c09..c748a72f89c9 100644 --- a/sdk/core/azure-mgmt-core/CHANGELOG.md +++ b/sdk/core/azure-mgmt-core/CHANGELOG.md @@ -1,5 +1,11 @@ # Release History +## 1.6.1 (Unreleased) + +### Bugs Fixed + +- `ARMPolling` now includes the `azure-asyncoperation` header in the continuation token to ensure proper LRO rehydration. + ## 1.6.0 (2025-07-02) ### Other Changes From 3c9ee74af5a219d1740faaaf5813bbefb0c99198 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Thu, 15 Jan 2026 17:16:01 -0800 Subject: [PATCH 4/6] update version --- sdk/core/azure-mgmt-core/azure/mgmt/core/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-mgmt-core/azure/mgmt/core/_version.py b/sdk/core/azure-mgmt-core/azure/mgmt/core/_version.py index f83b79240838..63b396f7f785 100644 --- a/sdk/core/azure-mgmt-core/azure/mgmt/core/_version.py +++ b/sdk/core/azure-mgmt-core/azure/mgmt/core/_version.py @@ -9,4 +9,4 @@ # regenerated. # -------------------------------------------------------------------------- -VERSION = "1.6.0" +VERSION = "1.6.1" From 4dacc03b5ddd397a67cc65de1d24a4ae30c1e88b Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Fri, 16 Jan 2026 17:01:47 -0800 Subject: [PATCH 5/6] update --- .../azure/mgmt/core/polling/_utils.py | 47 ------------------- .../azure/mgmt/core/polling/arm_polling.py | 20 +++++++- .../mgmt/core/polling/async_arm_polling.py | 5 +- 3 files changed, 20 insertions(+), 52 deletions(-) delete mode 100644 sdk/core/azure-mgmt-core/azure/mgmt/core/polling/_utils.py diff --git a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/_utils.py b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/_utils.py deleted file mode 100644 index 0435aa0f5b38..000000000000 --- a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/_utils.py +++ /dev/null @@ -1,47 +0,0 @@ -# -------------------------------------------------------------------------- -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# -------------------------------------------------------------------------- -"""ARM-specific utilities for polling continuation token serialization.""" - -from typing import Dict, Mapping - -from azure.core.polling._utils import _LRO_HEADERS - -# ARM-specific LRO headers - includes azure-asyncoperation which is ARM-specific -_ARM_LRO_HEADERS = _LRO_HEADERS | frozenset(["azure-asyncoperation"]) - - -def _filter_arm_headers(headers: Mapping[str, str]) -> Dict[str, str]: - """Filter headers to only include those needed for ARM LRO rehydration. - - Uses an allowlist approach - only headers required for polling are included. - This includes the azure-asyncoperation header which is ARM-specific. - - :param headers: The headers to filter. - :type headers: Mapping[str, str] - :return: A new dictionary with only allowed headers. - :rtype: dict[str, str] - """ - return {k: v for k, v in headers.items() if k.lower() in _ARM_LRO_HEADERS} diff --git a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/arm_polling.py b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/arm_polling.py index b27491808016..24c3027e95e4 100644 --- a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/arm_polling.py +++ b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/arm_polling.py @@ -47,7 +47,23 @@ ) from azure.core.rest import HttpRequest, HttpResponse, AsyncHttpResponse -from ._utils import _filter_arm_headers +# ARM-specific LRO headers - azure-asyncoperation is ARM-specific +_ARM_LRO_HEADERS = frozenset(["azure-asyncoperation"]) + + +def _add_arm_headers(filtered: Dict[str, str], headers: Mapping[str, str]) -> Dict[str, str]: + """Add ARM-specific headers to the filtered headers dict. + + :param filtered: The base filtered headers from parent class. + :type filtered: dict[str, str] + :param headers: The original response headers. + :type headers: Mapping[str, str] + :return: Updated filtered dictionary with ARM headers included. + :rtype: dict[str, str] + """ + filtered.update({k: v for k, v in headers.items() if k.lower() in _ARM_LRO_HEADERS}) + return filtered + ResponseType = Union[HttpResponse, AsyncHttpResponse] PipelineResponseType = PipelineResponse[HttpRequest, ResponseType] @@ -220,7 +236,7 @@ def _filter_headers_for_continuation_token(self, headers: Mapping[str, str]) -> :return: A filtered dictionary of headers to include in the continuation token. :rtype: dict[str, str] """ - return _filter_arm_headers(headers) + return _add_arm_headers(super()._filter_headers_for_continuation_token(headers), headers) __all__ = [ diff --git a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py index 2e60bd70b84b..74f501461c74 100644 --- a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py +++ b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py @@ -28,8 +28,7 @@ from azure.core.polling.base_polling import LocationPolling, StatusCheckPolling, LongRunningOperation from azure.core.polling.async_base_polling import AsyncLROBasePolling -from .arm_polling import AzureAsyncOperationPolling, BodyContentPolling, HttpRequestTypeVar, AllHttpResponseTypeVar -from ._utils import _filter_arm_headers +from .arm_polling import AzureAsyncOperationPolling, BodyContentPolling, HttpRequestTypeVar, AllHttpResponseTypeVar, _add_arm_headers class AsyncARMPolling(AsyncLROBasePolling): @@ -65,7 +64,7 @@ def _filter_headers_for_continuation_token(self, headers: Mapping[str, str]) -> :return: A filtered dictionary of headers to include in the continuation token. :rtype: dict[str, str] """ - return _filter_arm_headers(headers) + return _add_arm_headers(super()._filter_headers_for_continuation_token(headers), headers) __all__ = ["AsyncARMPolling"] From a082d5d164a25726804094e557c5180f08828fb5 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Tue, 20 Jan 2026 12:24:54 -0800 Subject: [PATCH 6/6] update --- .../azure/mgmt/core/polling/async_arm_polling.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py index 74f501461c74..a8b3a5a657c0 100644 --- a/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py +++ b/sdk/core/azure-mgmt-core/azure/mgmt/core/polling/async_arm_polling.py @@ -28,7 +28,13 @@ from azure.core.polling.base_polling import LocationPolling, StatusCheckPolling, LongRunningOperation from azure.core.polling.async_base_polling import AsyncLROBasePolling -from .arm_polling import AzureAsyncOperationPolling, BodyContentPolling, HttpRequestTypeVar, AllHttpResponseTypeVar, _add_arm_headers +from .arm_polling import ( + AzureAsyncOperationPolling, + BodyContentPolling, + HttpRequestTypeVar, + AllHttpResponseTypeVar, + _add_arm_headers, +) class AsyncARMPolling(AsyncLROBasePolling):