diff --git a/eng/pipelines/templates/steps/analyze.yml b/eng/pipelines/templates/steps/analyze.yml index 7368cddf3fa5..55461845c5fe 100644 --- a/eng/pipelines/templates/steps/analyze.yml +++ b/eng/pipelines/templates/steps/analyze.yml @@ -91,8 +91,8 @@ steps: BuildTargetingString: ${{ parameters.BuildTargetingString }} TestMarkArgument: ${{ parameters.TestMarkArgument }} - - template: ../steps/run_apistub.yml - parameters: - ServiceDirectory: ${{ parameters.ServiceDirectory }} - BuildTargetingString: ${{ parameters.BuildTargetingString }} - TestMarkArgument: ${{ parameters.TestMarkArgument }} \ No newline at end of file + # - template: ../steps/run_apistub.yml + # parameters: + # ServiceDirectory: ${{ parameters.ServiceDirectory }} + # BuildTargetingString: ${{ parameters.BuildTargetingString }} + # TestMarkArgument: ${{ parameters.TestMarkArgument }} diff --git a/eng/tox/install_dev_build_dependency.py b/eng/tox/install_dev_build_dependency.py index df9eb28b9686..3f5c22670348 100644 --- a/eng/tox/install_dev_build_dependency.py +++ b/eng/tox/install_dev_build_dependency.py @@ -13,13 +13,11 @@ from os import path from subprocess import check_call -from pip._internal.operations import freeze - # import common_task module root_dir = path.abspath(path.join(path.abspath(__file__), "..", "..", "..")) common_task_path = path.abspath(path.join(root_dir, "scripts", "devops_tasks")) sys.path.append(common_task_path) -from common_tasks import process_glob_string +from common_tasks import process_glob_string, get_installed_packages from tox_helper_tasks import get_package_details EXCLUDED_PKGS = [ @@ -34,10 +32,10 @@ # This script verifies installed package version and ensure all installed pacakges are dev build version -def get_installed_packages(pkg_name_to_exclude): +def get_installed_azure_packages(pkg_name_to_exclude): # This method returns a list of installed azure sdk packages installed_pkgs = [ - p.split("==")[0] for p in freeze.freeze() if p.startswith("azure-") + p.split("==")[0] for p in get_installed_packages() if p.startswith("azure-") ] # Get valid list of Azure SDK packages in repo @@ -100,7 +98,7 @@ def install_packages(packages): def install_dev_build_packages(pkg_name_to_exclude): # Uninstall GA version and reinstall dev build version of dependent packages - azure_pkgs = get_installed_packages(pkg_name_to_exclude) + azure_pkgs = get_installed_azure_packages(pkg_name_to_exclude) uninstall_packages(azure_pkgs) install_packages(azure_pkgs) diff --git a/eng/tox/verify_installed_packages.py b/eng/tox/verify_installed_packages.py index fa7b1b7f8958..cee12559c01d 100644 --- a/eng/tox/verify_installed_packages.py +++ b/eng/tox/verify_installed_packages.py @@ -9,8 +9,13 @@ import os import sys import logging -from pip._internal.operations import freeze +from os import path +# import common_task module +root_dir = path.abspath(path.join(path.abspath(__file__), "..", "..", "..")) +common_task_path = path.abspath(path.join(root_dir, "scripts", "devops_tasks")) +sys.path.append(common_task_path) +from common_tasks import get_installed_packages def verify_packages(package_file_path): # this method verifies packages installed on machine is matching the expected package version @@ -29,7 +34,7 @@ def verify_packages(package_file_path): sys.exit(1) # find installed and expected packages - installed = dict(p.split('==') for p in freeze.freeze() if p.startswith('azure') and "==" in p) + installed = dict(p.split('==') for p in get_installed_packages() if p.startswith('azure') and "==" in p) expected = dict(p.split('==') for p in packages) missing_packages = [pkg for pkg in expected.keys() if installed.get(pkg) != expected.get(pkg)] diff --git a/scripts/devops_tasks/common_tasks.py b/scripts/devops_tasks/common_tasks.py index f8a8473b5cdf..1c41506e1f1f 100644 --- a/scripts/devops_tasks/common_tasks.py +++ b/scripts/devops_tasks/common_tasks.py @@ -22,7 +22,7 @@ import pdb # Assumes the presence of setuptools -from pkg_resources import parse_version, parse_requirements, Requirement +from pkg_resources import parse_version, parse_requirements, Requirement, WorkingSet, working_set # this assumes the presence of "packaging" from packaging.specifiers import SpecifierSet @@ -420,4 +420,15 @@ def find_tools_packages(root_path): glob_string = os.path.join(root_path, "tools", "*", "setup.py") pkgs = [os.path.basename(os.path.dirname(p)) for p in glob.glob(glob_string)] logging.info("Packages in tools: {}".format(pkgs)) - return pkgs \ No newline at end of file + return pkgs + + +def get_installed_packages(paths = None): + """Find packages in default or given lib paths + """ + # WorkingSet returns installed packages in given path + # working_set returns installed packages in default path + # if paths is set then find installed packages from given paths + ws = WorkingSet(paths) if paths else working_set + return ["{0}=={1}".format(p.project_name, p.version) for p in ws] + diff --git a/scripts/devops_tasks/test_regression.py b/scripts/devops_tasks/test_regression.py index c1193aea1876..b0722ea39db4 100644 --- a/scripts/devops_tasks/test_regression.py +++ b/scripts/devops_tasks/test_regression.py @@ -22,10 +22,10 @@ filter_dev_requirements, find_packages_missing_on_pypi, find_whl, - find_tools_packages + find_tools_packages, + get_installed_packages ) from git_helper import get_release_tag, git_checkout_tag, git_checkout_branch, clone_repo -from pip._internal.operations import freeze AZURE_GLOB_STRING = "azure*" @@ -222,7 +222,7 @@ def _install_packages(self, dependent_pkg_path, pkg_to_exclude): temp_dir = self.context.temp_path list_to_exclude = [pkg_to_exclude,] - installed_pkgs = [p.split('==')[0] for p in list(freeze.freeze(paths=self.context.venv.lib_paths)) if p.startswith('azure-')] + installed_pkgs = [p.split('==')[0] for p in get_installed_packages(self.context.venv.lib_paths) if p.startswith('azure-')] logging.info("Installed azure sdk packages:{}".format(installed_pkgs)) # Do not exclude list of packages in tools directory and so these tools packages will be reinstalled from repo branch we are testing @@ -257,7 +257,7 @@ def _is_package_installed(self, package, version): venv_root = self.context.venv.path site_packages = self.context.venv.lib_paths logging.info("Searching for packages in :{}".format(site_packages)) - installed_pkgs = list(freeze.freeze(paths=site_packages)) + installed_pkgs = get_installed_packages(site_packages) logging.info("Installed packages: {}".format(installed_pkgs)) # Verify installed package version # Search for exact version or dev build version of current version. diff --git a/sdk/cosmos/azure-cosmos/CHANGELOG.md b/sdk/cosmos/azure-cosmos/CHANGELOG.md index 54618cdbf4fe..ef0df15f6fce 100644 --- a/sdk/cosmos/azure-cosmos/CHANGELOG.md +++ b/sdk/cosmos/azure-cosmos/CHANGELOG.md @@ -1,13 +1,16 @@ ## 4.0.1 (Unreleased) - Added deprecation warning for "lazy" indexing mode. The backend no longer allows creating containers with this mode and will set them to consistent instead. -- Fix for bug where options headers were not added to upsert_item function. Issue #11791 - thank you @aalapatirvbd. -- Fixed error raised when a non string ID is used in an item. It now raises TypeError rather than AttributeError. Issue #11793 - thank you @Rabbit994. + +**New features** - Added the ability to set the analytical storage TTL when creating a new container. -** Bug fixes ** +**Bug fixes** - Fixed support for dicts as inputs for get_client APIs. - Fixed Python 2/3 compatibility in query iterators. +- Fixed type hint error. Issue #12570 - Thanks @sl-sandy. +- Fixed bug where options headers were not added to upsert_item function. Issue #11791 - thank you @aalapatirvbd. +- Fixed error raised when a non string ID is used in an item. It now raises TypeError rather than AttributeError. Issue #11793 - thank you @Rabbit994. ## 4.0.0 (2020-05-20) diff --git a/sdk/cosmos/azure-cosmos/azure/cosmos/container.py b/sdk/cosmos/azure-cosmos/azure/cosmos/container.py index f5883c860091..9e1d86f24dca 100644 --- a/sdk/cosmos/azure-cosmos/azure/cosmos/container.py +++ b/sdk/cosmos/azure-cosmos/azure/cosmos/container.py @@ -282,7 +282,7 @@ def query_items_change_feed( def query_items( self, query, # type: str - parameters=None, # type: Optional[List[str]] + parameters=None, # type: Optional[List[Dict[str, object]]] partition_key=None, # type: Optional[Any] enable_cross_partition_query=None, # type: Optional[bool] max_item_count=None, # type: Optional[int] @@ -299,7 +299,9 @@ def query_items( the WHERE clause. :param query: The Azure Cosmos DB SQL query to execute. - :param parameters: Optional array of parameters to the query. Ignored if no query is provided. + :param parameters: Optional array of parameters to the query. + Each parameter is a dict() with 'name' and 'value' keys. + Ignored if no query is provided. :param partition_key: Specifies the partition key value for the item. :param enable_cross_partition_query: Allows sending of more than one request to execute the query in the Azure Cosmos DB service. diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/README.md b/sdk/formrecognizer/azure-ai-formrecognizer/README.md index be8d1fc27afa..aa98db81f8cb 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/README.md +++ b/sdk/formrecognizer/azure-ai-formrecognizer/README.md @@ -193,7 +193,7 @@ all the recognize methods. ``` -form_url_jpg = "" +form_url = "" poller = form_recognizer_client.begin_recognize_custom_forms_from_url(model_id=model_id, form_url=form_url) result = poller.result() ``` diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/azure/ai/formrecognizer/_form_recognizer_client.py b/sdk/formrecognizer/azure-ai-formrecognizer/azure/ai/formrecognizer/_form_recognizer_client.py index e4bc9786023f..3962901aba96 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/azure/ai/formrecognizer/_form_recognizer_client.py +++ b/sdk/formrecognizer/azure-ai-formrecognizer/azure/ai/formrecognizer/_form_recognizer_client.py @@ -94,7 +94,7 @@ def begin_recognize_receipts(self, receipt, **kwargs): 'image/jpeg', 'image/png' or 'image/tiff'. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields :param receipt: JPEG, PNG, PDF and TIFF type file stream or bytes. Currently only supports US sales receipts. @@ -152,7 +152,7 @@ def begin_recognize_receipts_from_url(self, receipt_url, **kwargs): The input document must be the location (URL) of the receipt to be analyzed. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields :param str receipt_url: The URL of the receipt to analyze. The input must be a valid, encoded URL of one of the supported formats: JPEG, PNG, PDF and TIFF. Currently only supports diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/azure/ai/formrecognizer/aio/_form_recognizer_client_async.py b/sdk/formrecognizer/azure-ai-formrecognizer/azure/ai/formrecognizer/aio/_form_recognizer_client_async.py index c4cc7aa1798a..6a54d5752812 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/azure/ai/formrecognizer/aio/_form_recognizer_client_async.py +++ b/sdk/formrecognizer/azure-ai-formrecognizer/azure/ai/formrecognizer/aio/_form_recognizer_client_async.py @@ -102,7 +102,7 @@ async def begin_recognize_receipts( 'image/jpeg', 'image/png' or 'image/tiff'. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields :param receipt: JPEG, PNG, PDF and TIFF type file stream or bytes. Currently only supports US sales receipts. @@ -166,7 +166,7 @@ async def begin_recognize_receipts_from_url( The input document must be the location (URL) of the receipt to be analyzed. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields :param str receipt_url: The URL of the receipt to analyze. The input must be a valid, encoded URL of one of the supported formats: JPEG, PNG, PDF and TIFF. Currently only supports diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_recognize_receipts_async.py b/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_recognize_receipts_async.py index c9caa01b8903..dbc363ea71ea 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_recognize_receipts_async.py +++ b/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_recognize_receipts_async.py @@ -15,7 +15,7 @@ from receipts, see sample_strongly_typed_recognized_form_async.py. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields USAGE: python sample_recognize_receipts_async.py diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_recognize_receipts_from_url_async.py b/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_recognize_receipts_from_url_async.py index a7732c34121e..737920bd8527 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_recognize_receipts_from_url_async.py +++ b/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_recognize_receipts_from_url_async.py @@ -15,7 +15,7 @@ from receipts, see sample_strongly_typed_recognized_form_async.py. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields USAGE: python sample_recognize_receipts_from_url_async.py diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_strongly_typing_recognized_form_async.py b/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_strongly_typing_recognized_form_async.py index 7bcd77c0320e..c33cc856c059 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_strongly_typing_recognized_form_async.py +++ b/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_strongly_typing_recognized_form_async.py @@ -16,7 +16,7 @@ fields' names and types. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields USAGE: python sample_strongly_typed_recognized_form_async.py @@ -36,7 +36,7 @@ class Receipt(object): If a specific field is not found on the receipt, it will return None. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields """ def __init__(self, form): diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_recognize_receipts.py b/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_recognize_receipts.py index c2061ce14da9..3a699e8ee765 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_recognize_receipts.py +++ b/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_recognize_receipts.py @@ -15,7 +15,7 @@ from receipts, see sample_strongly_typed_recognized_form.py. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields USAGE: python sample_recognize_receipts.py diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_recognize_receipts_from_url.py b/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_recognize_receipts_from_url.py index 3ee25b4dd4ae..c0d9c6d8cbb3 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_recognize_receipts_from_url.py +++ b/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_recognize_receipts_from_url.py @@ -15,7 +15,7 @@ from receipts, see sample_strongly_typed_recognized_form.py. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields USAGE: python sample_recognize_receipts_from_url.py diff --git a/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_strongly_typing_recognized_form.py b/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_strongly_typing_recognized_form.py index a552b8b75420..4069402af13d 100644 --- a/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_strongly_typing_recognized_form.py +++ b/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_strongly_typing_recognized_form.py @@ -16,7 +16,7 @@ fields' names and types. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields USAGE: python sample_strongly_typed_recognized_form.py @@ -35,7 +35,7 @@ class Receipt(object): If a specific field is not found on the receipt, it will return None. See fields found on a receipt here: - https://aka.ms/azsdk/python/formrecognizer/receiptfields + https://aka.ms/formrecognizer/receiptfields """ def __init__(self, form): diff --git a/sdk/identity/azure-identity/MANIFEST.in b/sdk/identity/azure-identity/MANIFEST.in index fcca83563a8c..07b576fc0eb3 100644 --- a/sdk/identity/azure-identity/MANIFEST.in +++ b/sdk/identity/azure-identity/MANIFEST.in @@ -1,3 +1,4 @@ +recursive-include samples *.py recursive-include tests *.py include *.md -include azure/__init__.py \ No newline at end of file +include azure/__init__.py diff --git a/sdk/identity/azure-identity/azure/identity/_authn_client.py b/sdk/identity/azure-identity/azure/identity/_authn_client.py index 2b165d0a0a52..e29a48854e68 100644 --- a/sdk/identity/azure-identity/azure/identity/_authn_client.py +++ b/sdk/identity/azure-identity/azure/identity/_authn_client.py @@ -22,7 +22,7 @@ UserAgentPolicy, ) from azure.core.pipeline.transport import RequestsTransport, HttpRequest -from ._constants import AZURE_CLI_CLIENT_ID +from ._constants import AZURE_CLI_CLIENT_ID, DEFAULT_REFRESH_OFFSET, DEFAULT_TOKEN_REFRESH_RETRY_DELAY from ._internal import get_default_authority, normalize_authority from ._internal.user_agent import USER_AGENT @@ -65,17 +65,32 @@ def __init__(self, endpoint=None, authority=None, tenant=None, **kwargs): # pyl authority = normalize_authority(authority) if authority else get_default_authority() self._auth_url = "/".join((authority, tenant.strip("/"), "oauth2/v2.0/token")) self._cache = kwargs.get("cache") or TokenCache() # type: TokenCache + self._token_refresh_retry_delay = DEFAULT_TOKEN_REFRESH_RETRY_DELAY + self._token_refresh_offset = DEFAULT_REFRESH_OFFSET + self._last_refresh_time = 0 @property def auth_url(self): return self._auth_url + def should_refresh(self, token): + # type: (AccessToken) -> bool + """ check if the token needs refresh or not + """ + expires_on = int(token.expires_on) + now = int(time.time()) + if expires_on - now > self._token_refresh_offset: + return False + if now - self._last_refresh_time < self._token_refresh_retry_delay: + return False + return True + def get_cached_token(self, scopes): # type: (Iterable[str]) -> Optional[AccessToken] tokens = self._cache.find(TokenCache.CredentialType.ACCESS_TOKEN, target=list(scopes)) for token in tokens: expires_on = int(token["expires_on"]) - if expires_on - 300 > int(time.time()): + if expires_on > int(time.time()): return AccessToken(token["secret"], expires_on) return None @@ -217,6 +232,7 @@ def request_token( # type: (...) -> AccessToken request = self._prepare_request(method, headers=headers, form_data=form_data, params=params) request_time = int(time.time()) + self._last_refresh_time = request_time # no matter succeed or not, update the last refresh time response = self._pipeline.run(request, stream=False, **kwargs) token = self._deserialize_and_cache_token(response=response, scopes=scopes, request_time=request_time) return token diff --git a/sdk/identity/azure-identity/azure/identity/_constants.py b/sdk/identity/azure-identity/azure/identity/_constants.py index a47ebdeb9920..4d217d7dc716 100644 --- a/sdk/identity/azure-identity/azure/identity/_constants.py +++ b/sdk/identity/azure-identity/azure/identity/_constants.py @@ -7,6 +7,8 @@ AZURE_CLI_CLIENT_ID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46" AZURE_VSCODE_CLIENT_ID = "aebc6443-996d-45c2-90f0-388ff96faa56" VSCODE_CREDENTIALS_SECTION = "VS Code Azure" +DEFAULT_REFRESH_OFFSET = 300 +DEFAULT_TOKEN_REFRESH_RETRY_DELAY = 30 class KnownAuthorities: diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/authorization_code.py b/sdk/identity/azure-identity/azure/identity/_credentials/authorization_code.py index 3568f8c921ce..c535d0371f13 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/authorization_code.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/authorization_code.py @@ -6,10 +6,11 @@ from azure.core.exceptions import ClientAuthenticationError from .._internal.aad_client import AadClient +from .._internal.decorators import log_get_token if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports - from typing import Any, Optional, Sequence + from typing import Any, Iterable, Optional from azure.core.credentials import AccessToken @@ -38,6 +39,7 @@ def __init__(self, tenant_id, client_id, authorization_code, redirect_uri, **kwa self._client = kwargs.pop("client", None) or AadClient(tenant_id, client_id, **kwargs) self._redirect_uri = redirect_uri + @log_get_token("AuthorizationCodeCredential") def get_token(self, *scopes, **kwargs): # type: (*str, **Any) -> AccessToken """Request an access token for `scopes`. @@ -64,7 +66,15 @@ def get_token(self, *scopes, **kwargs): self._authorization_code = None # auth codes are single-use return token - token = self._client.get_cached_access_token(scopes) or self._redeem_refresh_token(scopes, **kwargs) + token = self._client.get_cached_access_token(scopes) + if not token: + token = self._redeem_refresh_token(scopes, **kwargs) + elif self._client.should_refresh(token): + try: + self._redeem_refresh_token(scopes, **kwargs) + except Exception: # pylint: disable=broad-except + pass + if not token: raise ClientAuthenticationError( message="No authorization code, cached access token, or refresh token available." @@ -73,7 +83,7 @@ def get_token(self, *scopes, **kwargs): return token def _redeem_refresh_token(self, scopes, **kwargs): - # type: (Sequence[str], **Any) -> Optional[AccessToken] + # type: (Iterable[str], **Any) -> Optional[AccessToken] for refresh_token in self._client.get_cached_refresh_tokens(scopes): if "secret" not in refresh_token: continue diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/azure_cli.py b/sdk/identity/azure-identity/azure/identity/_credentials/azure_cli.py index c5fe99a1119c..8e609d83ff05 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/azure_cli.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/azure_cli.py @@ -17,11 +17,13 @@ from .. import CredentialUnavailableError from .._internal import _scopes_to_resource +from .._internal.decorators import log_get_token if TYPE_CHECKING: # pylint:disable=ungrouped-imports from typing import Any + CLI_NOT_FOUND = "Azure CLI not found on path" COMMAND_LINE = "az account get-access-token --output json --resource {}" NOT_LOGGED_IN = "Please run 'az login' to set up an account" @@ -33,6 +35,7 @@ class AzureCliCredential(object): This requires previously logging in to Azure via "az login", and will use the CLI's currently logged in identity. """ + @log_get_token("AzureCliCredential") def get_token(self, *scopes, **kwargs): # pylint:disable=no-self-use,unused-argument # type: (*str, **Any) -> AccessToken """Request an access token for `scopes`. diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/certificate.py b/sdk/identity/azure-identity/azure/identity/_credentials/certificate.py index 81adb2621a96..f0f032d49c9a 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/certificate.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/certificate.py @@ -5,6 +5,7 @@ from typing import TYPE_CHECKING from .._internal import AadClient, CertificateCredentialBase +from .._internal.decorators import log_get_token if TYPE_CHECKING: from azure.core.credentials import AccessToken @@ -30,6 +31,7 @@ class CertificateCredential(CertificateCredentialBase): is unavailable. Default to False. Has no effect when `enable_persistent_cache` is False. """ + @log_get_token("CertificateCredential") def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument # type: (*str, **Any) -> AccessToken """Request an access token for `scopes`. @@ -48,6 +50,11 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument token = self._client.get_cached_access_token(scopes, query={"client_id": self._client_id}) if not token: token = self._client.obtain_token_by_client_certificate(scopes, self._certificate, **kwargs) + elif self._client.should_refresh(token): + try: + self._client.obtain_token_by_client_certificate(scopes, self._certificate, **kwargs) + except Exception: # pylint: disable=broad-except + pass return token def _get_auth_client(self, tenant_id, client_id, **kwargs): diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/chained.py b/sdk/identity/azure-identity/azure/identity/_credentials/chained.py index b40c373afa1d..752e16cf1f7d 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/chained.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/chained.py @@ -2,6 +2,8 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +import logging + from azure.core.exceptions import ClientAuthenticationError from .. import CredentialUnavailableError @@ -16,6 +18,8 @@ from typing import Any, Optional from azure.core.credentials import AccessToken, TokenCredential +_LOGGER = logging.getLogger(__name__) + def _get_error_message(history): attempts = [] @@ -61,16 +65,26 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument for credential in self.credentials: try: token = credential.get_token(*scopes, **kwargs) + _LOGGER.info("%s acquired a token from %s", self.__class__.__name__, credential.__class__.__name__) self._successful_credential = credential return token except CredentialUnavailableError as ex: # credential didn't attempt authentication because it lacks required data or state -> continue history.append((credential, ex.message)) + _LOGGER.info("%s - %s is unavailable", self.__class__.__name__, credential.__class__.__name__) except Exception as ex: # pylint: disable=broad-except # credential failed to authenticate, or something unexpectedly raised -> break history.append((credential, str(ex))) + _LOGGER.warning( + '%s.get_token failed: %s raised unexpected error "%s"', + self.__class__.__name__, + credential.__class__.__name__, + ex, + exc_info=_LOGGER.isEnabledFor(logging.DEBUG), + ) break attempts = _get_error_message(history) message = self.__class__.__name__ + " failed to retrieve a token from the included credentials." + attempts + _LOGGER.warning(message) raise ClientAuthenticationError(message=message) diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/client_secret.py b/sdk/identity/azure-identity/azure/identity/_credentials/client_secret.py index 4e20c2bd900b..94da7b0655a9 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/client_secret.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/client_secret.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. # ------------------------------------ from .._internal import AadClient, ClientSecretCredentialBase +from .._internal.decorators import log_get_token try: from typing import TYPE_CHECKING @@ -31,6 +32,7 @@ class ClientSecretCredential(ClientSecretCredentialBase): is unavailable. Default to False. Has no effect when `enable_persistent_cache` is False. """ + @log_get_token("ClientSecretCredential") def get_token(self, *scopes, **kwargs): # type: (*str, **Any) -> AccessToken """Request an access token for `scopes`. @@ -49,6 +51,11 @@ def get_token(self, *scopes, **kwargs): token = self._client.get_cached_access_token(scopes, query={"client_id": self._client_id}) if not token: token = self._client.obtain_token_by_client_secret(scopes, self._secret, **kwargs) + elif self._client.should_refresh(token): + try: + self._client.obtain_token_by_client_secret(scopes, self._secret, **kwargs) + except Exception: # pylint: disable=broad-except + pass return token def _get_auth_client(self, tenant_id, client_id, **kwargs): diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/default.py b/sdk/identity/azure-identity/azure/identity/_credentials/default.py index 44a802ee27c9..7282630aa80f 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/default.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/default.py @@ -102,7 +102,6 @@ def __init__(self, **kwargs): ) credentials.append(shared_cache) except Exception as ex: # pylint:disable=broad-except - # transitive dependency pywin32 doesn't support 3.8 (https://github.com/mhammond/pywin32/issues/1431) _LOGGER.info("Shared token cache is unavailable: '%s'", ex) if not exclude_visual_studio_code_credential: credentials.append(VSCodeCredential()) @@ -124,6 +123,10 @@ def get_token(self, *scopes, **kwargs): `message` attribute listing each authentication attempt and its error message. """ if self._successful_credential: - return self._successful_credential.get_token(*scopes, **kwargs) + token = self._successful_credential.get_token(*scopes, **kwargs) + _LOGGER.info( + "%s acquired a token from %s", self.__class__.__name__, self._successful_credential.__class__.__name__ + ) + return token return super(DefaultAzureCredential, self).get_token(*scopes, **kwargs) diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/environment.py b/sdk/identity/azure-identity/azure/identity/_credentials/environment.py index dc37abca83c1..565a8006b324 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/environment.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/environment.py @@ -2,10 +2,13 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +import logging import os + from .. import CredentialUnavailableError from .._constants import EnvironmentVariables +from .._internal.decorators import log_get_token from .certificate import CertificateCredential from .client_secret import ClientSecretCredential from .user_password import UsernamePasswordCredential @@ -22,6 +25,8 @@ EnvironmentCredentialTypes = Union["CertificateCredential", "ClientSecretCredential", "UsernamePasswordCredential"] +_LOGGER = logging.getLogger(__name__) + class EnvironmentCredential(object): """A credential configured by environment variables. @@ -76,6 +81,21 @@ def __init__(self, **kwargs): **kwargs ) + if self._credential: + _LOGGER.info("Environment is configured for %s", self._credential.__class__.__name__) + else: + expected_variables = set( + EnvironmentVariables.CERT_VARS + + EnvironmentVariables.CLIENT_SECRET_VARS + + EnvironmentVariables.USERNAME_PASSWORD_VARS + ) + set_variables = [v for v in expected_variables if v in os.environ] + if set_variables: + _LOGGER.warning("Incomplete environment configuration. Set variables: %s", ", ".join(set_variables)) + else: + _LOGGER.info("No environment configuration found.") + + @log_get_token("EnvironmentCredential") def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument # type: (*str, **Any) -> AccessToken """Request an access token for `scopes`. diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/managed_identity.py b/sdk/identity/azure-identity/azure/identity/_credentials/managed_identity.py index 8d29f0aae70c..8bdd46f5cba9 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/managed_identity.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/managed_identity.py @@ -2,6 +2,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +import logging import os import six @@ -21,6 +22,7 @@ from .. import CredentialUnavailableError from .._authn_client import AuthnClient from .._constants import Endpoints, EnvironmentVariables +from .._internal.decorators import log_get_token from .._internal.user_agent import USER_AGENT try: @@ -32,6 +34,8 @@ # pylint:disable=unused-import from typing import Any, Optional, Type +_LOGGER = logging.getLogger(__name__) + class ManagedIdentityCredential(object): """Authenticates with an Azure managed identity in any hosting environment which supports managed identities. @@ -50,10 +54,13 @@ def __init__(self, **kwargs): # type: (**Any) -> None self._credential = None if os.environ.get(EnvironmentVariables.MSI_ENDPOINT): + _LOGGER.info("%s will use MSI", self.__class__.__name__) self._credential = MsiCredential(**kwargs) else: + _LOGGER.info("%s will use IMDS", self.__class__.__name__) self._credential = ImdsCredential(**kwargs) + @log_get_token("ManagedIdentityCredential") def get_token(self, *scopes, **kwargs): # type: (*str, **Any) -> AccessToken """Request an access token for `scopes`. @@ -160,6 +167,7 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument except Exception: # pylint:disable=broad-except # if anything else was raised, assume the endpoint is unavailable self._endpoint_available = False + _LOGGER.info("No response from the IMDS endpoint.") if not self._endpoint_available: message = "ManagedIdentityCredential authentication unavailable, no managed identity endpoint found." @@ -170,30 +178,39 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument token = self._client.get_cached_token(scopes) if not token: - resource = scopes[0] - if resource.endswith("/.default"): - resource = resource[: -len("/.default")] - params = dict({"api-version": "2018-02-01", "resource": resource}, **self._identity_config) - + token = self._refresh_token(*scopes) + elif self._client.should_refresh(token): try: - token = self._client.request_token(scopes, method="GET", params=params) - except HttpResponseError as ex: - # 400 in response to a token request indicates managed identity is disabled, - # or the identity with the specified client_id is not available - if ex.status_code == 400: - self._endpoint_available = False - message = "ManagedIdentityCredential authentication unavailable. " - if self._identity_config: - message += "The requested identity has not been assigned to this resource." - else: - message += "No identity has been assigned to this resource." - six.raise_from(CredentialUnavailableError(message=message), ex) - - # any other error is unexpected - six.raise_from(ClientAuthenticationError(message=ex.message, response=ex.response), None) + token = self._refresh_token(*scopes) + except Exception: # pylint: disable=broad-except + pass return token + def _refresh_token(self, *scopes): + resource = scopes[0] + if resource.endswith("/.default"): + resource = resource[: -len("/.default")] + params = dict({"api-version": "2018-02-01", "resource": resource}, **self._identity_config) + + try: + token = self._client.request_token(scopes, method="GET", params=params) + except HttpResponseError as ex: + # 400 in response to a token request indicates managed identity is disabled, + # or the identity with the specified client_id is not available + if ex.status_code == 400: + self._endpoint_available = False + message = "ManagedIdentityCredential authentication unavailable. " + if self._identity_config: + message += "The requested identity has not been assigned to this resource." + else: + message += "No identity has been assigned to this resource." + six.raise_from(CredentialUnavailableError(message=message), ex) + + # any other error is unexpected + six.raise_from(ClientAuthenticationError(message=ex.message, response=ex.response), None) + return token + class MsiCredential(_ManagedIdentityBase): """Authenticates via the MSI endpoint in an App Service or Cloud Shell environment. @@ -227,16 +244,25 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument token = self._client.get_cached_token(scopes) if not token: - resource = scopes[0] - if resource.endswith("/.default"): - resource = resource[: -len("/.default")] - secret = os.environ.get(EnvironmentVariables.MSI_SECRET) - if secret: - # MSI_ENDPOINT and MSI_SECRET set -> App Service - token = self._request_app_service_token(scopes=scopes, resource=resource, secret=secret) - else: - # only MSI_ENDPOINT set -> legacy-style MSI (Cloud Shell) - token = self._request_legacy_token(scopes=scopes, resource=resource) + token = self._refresh_token(*scopes) + elif self._client.should_refresh(token): + try: + token = self._refresh_token(*scopes) + except Exception: # pylint: disable=broad-except + pass + return token + + def _refresh_token(self, *scopes): + resource = scopes[0] + if resource.endswith("/.default"): + resource = resource[: -len("/.default")] + secret = os.environ.get(EnvironmentVariables.MSI_SECRET) + if secret: + # MSI_ENDPOINT and MSI_SECRET set -> App Service + token = self._request_app_service_token(scopes=scopes, resource=resource, secret=secret) + else: + # only MSI_ENDPOINT set -> legacy-style MSI (Cloud Shell) + token = self._request_legacy_token(scopes=scopes, resource=resource) return token def _request_app_service_token(self, scopes, resource, secret): diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/shared_cache.py b/sdk/identity/azure-identity/azure/identity/_credentials/shared_cache.py index 2c6e84be8782..27b7ef30d074 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/shared_cache.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/shared_cache.py @@ -5,6 +5,7 @@ from .. import CredentialUnavailableError from .._constants import AZURE_CLI_CLIENT_ID from .._internal import AadClient +from .._internal.decorators import log_get_token from .._internal.shared_token_cache import NO_TOKEN, SharedTokenCacheBase try: @@ -36,6 +37,7 @@ class SharedTokenCacheCredential(SharedTokenCacheBase): is unavailable. Defaults to False. """ + @log_get_token("SharedTokenCacheCredential") def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument # type (*str, **Any) -> AccessToken """Get an access token for `scopes` from the shared cache. diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/vscode_credential.py b/sdk/identity/azure-identity/azure/identity/_credentials/vscode_credential.py index d2c5e4ee6f6e..76273368a5ab 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/vscode_credential.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/vscode_credential.py @@ -4,16 +4,18 @@ # ------------------------------------ import sys from typing import TYPE_CHECKING + from .._exceptions import CredentialUnavailableError from .._constants import AZURE_VSCODE_CLIENT_ID from .._internal.aad_client import AadClient +from .._internal.decorators import log_get_token if sys.platform.startswith("win"): - from .win_vscode_adapter import get_credentials + from .._internal.win_vscode_adapter import get_credentials elif sys.platform.startswith("darwin"): - from .macos_vscode_adapter import get_credentials + from .._internal.macos_vscode_adapter import get_credentials else: - from .linux_vscode_adapter import get_credentials + from .._internal.linux_vscode_adapter import get_credentials if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports @@ -29,6 +31,7 @@ def __init__(self, **kwargs): self._client = kwargs.pop("_client", None) or AadClient("organizations", AZURE_VSCODE_CLIENT_ID, **kwargs) self._refresh_token = None + @log_get_token("VSCodeCredential") def get_token(self, *scopes, **kwargs): # type: (*str, **Any) -> AccessToken """Request an access token for `scopes`. @@ -47,9 +50,17 @@ def get_token(self, *scopes, **kwargs): token = self._client.get_cached_access_token(scopes) - if token: - return token + if not token: + token = self._redeem_refresh_token(scopes, **kwargs) + elif self._client.should_refresh(token): + try: + self._redeem_refresh_token(scopes, **kwargs) + except Exception: # pylint: disable=broad-except + pass + return token + def _redeem_refresh_token(self, scopes, **kwargs): + # type: (Sequence[str], **Any) -> Optional[AccessToken] if not self._refresh_token: self._refresh_token = get_credentials() if not self._refresh_token: diff --git a/sdk/identity/azure-identity/azure/identity/_exceptions.py b/sdk/identity/azure-identity/azure/identity/_exceptions.py index ef1199fdf3b9..1012b2ab6667 100644 --- a/sdk/identity/azure-identity/azure/identity/_exceptions.py +++ b/sdk/identity/azure-identity/azure/identity/_exceptions.py @@ -7,7 +7,7 @@ from azure.core.exceptions import ClientAuthenticationError if TYPE_CHECKING: - from typing import Any, Optional, Sequence + from typing import Any, Iterable, Optional class CredentialUnavailableError(ClientAuthenticationError): @@ -18,7 +18,7 @@ class AuthenticationRequiredError(CredentialUnavailableError): """Interactive authentication is required to acquire a token.""" def __init__(self, scopes, message=None, error_details=None, **kwargs): - # type: (Sequence[str], Optional[str], Optional[str], **Any) -> None + # type: (Iterable[str], Optional[str], Optional[str], **Any) -> None self._scopes = scopes self._error_details = error_details if not message: @@ -27,7 +27,7 @@ def __init__(self, scopes, message=None, error_details=None, **kwargs): @property def scopes(self): - # type: () -> Sequence[str] + # type: () -> Iterable[str] """Scopes requested during the failed authentication""" return self._scopes diff --git a/sdk/identity/azure-identity/azure/identity/_internal/__init__.py b/sdk/identity/azure-identity/azure/identity/_internal/__init__.py index 4d4f3f5989a7..60d776175e4f 100644 --- a/sdk/identity/azure-identity/azure/identity/_internal/__init__.py +++ b/sdk/identity/azure-identity/azure/identity/_internal/__init__.py @@ -36,8 +36,8 @@ def get_default_authority(): from .aadclient_certificate import AadClientCertificate from .certificate_credential_base import CertificateCredentialBase from .client_secret_credential_base import ClientSecretCredentialBase -from .exception_wrapper import wrap_exceptions -from .msal_credentials import InteractiveCredential, PublicClientCredential +from .decorators import wrap_exceptions +from .msal_credentials import InteractiveCredential def _scopes_to_resource(*scopes): @@ -64,6 +64,5 @@ def _scopes_to_resource(*scopes): "get_default_authority", "InteractiveCredential", "normalize_authority", - "PublicClientCredential", "wrap_exceptions", ] diff --git a/sdk/identity/azure-identity/azure/identity/_internal/aad_client.py b/sdk/identity/azure-identity/azure/identity/_internal/aad_client.py index ab25736a9407..5681b930e194 100644 --- a/sdk/identity/azure-identity/azure/identity/_internal/aad_client.py +++ b/sdk/identity/azure-identity/azure/identity/_internal/aad_client.py @@ -21,7 +21,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports - from typing import Any, List, Optional, Sequence, Union + from typing import Any, Iterable, List, Optional, Union from azure.core.credentials import AccessToken from azure.core.pipeline.policies import HTTPPolicy, SansIOHTTPPolicy from azure.core.pipeline.transport import HttpTransport @@ -32,7 +32,7 @@ class AadClient(AadClientBase): def obtain_token_by_authorization_code(self, scopes, code, redirect_uri, client_secret=None, **kwargs): - # type: (Sequence[str], str, str, Optional[str], **Any) -> AccessToken + # type: (Iterable[str], str, str, Optional[str], **Any) -> AccessToken request = self._get_auth_code_request( scopes=scopes, code=code, redirect_uri=redirect_uri, client_secret=client_secret ) @@ -41,21 +41,21 @@ def obtain_token_by_authorization_code(self, scopes, code, redirect_uri, client_ return self._process_response(response, now) def obtain_token_by_client_certificate(self, scopes, certificate, **kwargs): - # type: (Sequence[str], AadClientCertificate, **Any) -> AccessToken + # type: (Iterable[str], AadClientCertificate, **Any) -> AccessToken request = self._get_client_certificate_request(scopes, certificate) now = int(time.time()) response = self._pipeline.run(request, stream=False, **kwargs) return self._process_response(response, now) def obtain_token_by_client_secret(self, scopes, secret, **kwargs): - # type: (Sequence[str], str, **Any) -> AccessToken + # type: (Iterable[str], str, **Any) -> AccessToken request = self._get_client_secret_request(scopes, secret) now = int(time.time()) response = self._pipeline.run(request, stream=False, **kwargs) return self._process_response(response, now) def obtain_token_by_refresh_token(self, scopes, refresh_token, **kwargs): - # type: (Sequence[str], str, **Any) -> AccessToken + # type: (Iterable[str], str, **Any) -> AccessToken request = self._get_refresh_token_request(scopes, refresh_token) now = int(time.time()) response = self._pipeline.run(request, stream=False, **kwargs) diff --git a/sdk/identity/azure-identity/azure/identity/_internal/aad_client_base.py b/sdk/identity/azure-identity/azure/identity/_internal/aad_client_base.py index e1af4f949626..cf7d70744a49 100644 --- a/sdk/identity/azure-identity/azure/identity/_internal/aad_client_base.py +++ b/sdk/identity/azure-identity/azure/identity/_internal/aad_client_base.py @@ -16,6 +16,7 @@ from azure.core.credentials import AccessToken from azure.core.exceptions import ClientAuthenticationError from . import get_default_authority, normalize_authority +from .._constants import DEFAULT_TOKEN_REFRESH_RETRY_DELAY, DEFAULT_REFRESH_OFFSET try: from typing import TYPE_CHECKING @@ -29,7 +30,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports - from typing import Any, Optional, Sequence, Union + from typing import Any, Iterable, List, Optional, Union from azure.core.pipeline import AsyncPipeline, Pipeline, PipelineResponse from azure.core.pipeline.policies import AsyncHTTPPolicy, HTTPPolicy, SansIOHTTPPolicy from azure.core.pipeline.transport import AsyncHttpTransport, HttpTransport @@ -48,21 +49,37 @@ def __init__(self, tenant_id, client_id, authority=None, cache=None, **kwargs): self._cache = cache or TokenCache() self._client_id = client_id self._pipeline = self._build_pipeline(**kwargs) + self._token_refresh_retry_delay = DEFAULT_TOKEN_REFRESH_RETRY_DELAY + self._token_refresh_offset = DEFAULT_REFRESH_OFFSET + self._last_refresh_time = 0 def get_cached_access_token(self, scopes, query=None): - # type: (Sequence[str], Optional[dict]) -> Optional[AccessToken] + # type: (Iterable[str], Optional[dict]) -> Optional[AccessToken] tokens = self._cache.find(TokenCache.CredentialType.ACCESS_TOKEN, target=list(scopes), query=query) for token in tokens: expires_on = int(token["expires_on"]) - if expires_on - 300 > int(time.time()): + if expires_on > int(time.time()): return AccessToken(token["secret"], expires_on) return None def get_cached_refresh_tokens(self, scopes): - # type: (Sequence[str]) -> Sequence[dict] + # type: (Iterable[str]) -> List[dict] """Assumes all cached refresh tokens belong to the same user""" return self._cache.find(TokenCache.CredentialType.REFRESH_TOKEN, target=list(scopes)) + def should_refresh(self, token): + # type: (AccessToken) -> bool + """ check if the token needs refresh or not + """ + expires_on = int(token.expires_on) + now = int(time.time()) + if expires_on - now > self._token_refresh_offset: + return False + if now - self._last_refresh_time < self._token_refresh_retry_delay: + return False + return True + + @abc.abstractmethod def obtain_token_by_authorization_code(self, scopes, code, redirect_uri, client_secret=None, **kwargs): pass @@ -85,6 +102,7 @@ def _build_pipeline(self, config=None, policies=None, transport=None, **kwargs): def _process_response(self, response, request_time): # type: (PipelineResponse, int) -> AccessToken + self._last_refresh_time = request_time # no matter succeed or not, update the last refresh time content = ContentDecodePolicy.deserialize_from_http_generics(response.http_response) @@ -136,7 +154,7 @@ def _process_response(self, response, request_time): return token def _get_auth_code_request(self, scopes, code, redirect_uri, client_secret=None): - # type: (Sequence[str], str, str, Optional[str]) -> HttpRequest + # type: (Iterable[str], str, str, Optional[str]) -> HttpRequest data = { "client_id": self._client_id, "code": code, @@ -153,7 +171,7 @@ def _get_auth_code_request(self, scopes, code, redirect_uri, client_secret=None) return request def _get_client_certificate_request(self, scopes, certificate): - # type: (Sequence[str], AadClientCertificate) -> HttpRequest + # type: (Iterable[str], AadClientCertificate) -> HttpRequest assertion = self._get_jwt_assertion(certificate) data = { "client_assertion": assertion, @@ -169,7 +187,7 @@ def _get_client_certificate_request(self, scopes, certificate): return request def _get_client_secret_request(self, scopes, secret): - # type: (Sequence[str], str) -> HttpRequest + # type: (Iterable[str], str) -> HttpRequest data = { "client_id": self._client_id, "client_secret": secret, @@ -207,7 +225,7 @@ def _get_jwt_assertion(self, certificate): return jwt_bytes.decode("utf-8") def _get_refresh_token_request(self, scopes, refresh_token): - # type: (Sequence[str], str) -> HttpRequest + # type: (Iterable[str], str) -> HttpRequest data = { "grant_type": "refresh_token", "refresh_token": refresh_token, diff --git a/sdk/identity/azure-identity/azure/identity/_internal/decorators.py b/sdk/identity/azure-identity/azure/identity/_internal/decorators.py new file mode 100644 index 000000000000..6c00f74bff67 --- /dev/null +++ b/sdk/identity/azure-identity/azure/identity/_internal/decorators.py @@ -0,0 +1,52 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import functools +import logging + +from six import raise_from +from azure.core.exceptions import ClientAuthenticationError + +_LOGGER = logging.getLogger(__name__) + + +def log_get_token(class_name): + """Adds logging around get_token calls. + + :param str class_name: required for the sake of Python 2.7, which lacks an easy way to get the credential's class + name from the decorated function + """ + + def decorator(fn): + qualified_name = class_name + ".get_token" + + @functools.wraps(fn) + def wrapper(*args, **kwargs): + try: + token = fn(*args, **kwargs) + _LOGGER.info("%s succeeded", qualified_name) + return token + except Exception as ex: + _LOGGER.warning("%s failed: %s", qualified_name, ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + raise + + return wrapper + + return decorator + + +def wrap_exceptions(fn): + """Prevents leaking exceptions defined outside azure-core by raising ClientAuthenticationError from them.""" + + @functools.wraps(fn) + def wrapper(*args, **kwargs): + try: + return fn(*args, **kwargs) + except ClientAuthenticationError: + raise + except Exception as ex: # pylint:disable=broad-except + auth_error = ClientAuthenticationError(message="Authentication failed: {}".format(ex)) + raise_from(auth_error, ex) + + return wrapper diff --git a/sdk/identity/azure-identity/azure/identity/_internal/exception_wrapper.py b/sdk/identity/azure-identity/azure/identity/_internal/exception_wrapper.py deleted file mode 100644 index 4d07f54c85a7..000000000000 --- a/sdk/identity/azure-identity/azure/identity/_internal/exception_wrapper.py +++ /dev/null @@ -1,25 +0,0 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -import functools - -from six import raise_from - -from azure.core.exceptions import ClientAuthenticationError - - -def wrap_exceptions(fn): - """Prevents leaking exceptions defined outside azure-core by raising ClientAuthenticationError from them.""" - - @functools.wraps(fn) - def wrapper(*args, **kwargs): - try: - return fn(*args, **kwargs) - except ClientAuthenticationError: - raise - except Exception as ex: # pylint:disable=broad-except - auth_error = ClientAuthenticationError(message="Authentication failed: {}".format(ex)) - raise_from(auth_error, ex) - - return wrapper diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/linux_vscode_adapter.py b/sdk/identity/azure-identity/azure/identity/_internal/linux_vscode_adapter.py similarity index 100% rename from sdk/identity/azure-identity/azure/identity/_credentials/linux_vscode_adapter.py rename to sdk/identity/azure-identity/azure/identity/_internal/linux_vscode_adapter.py diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/macos_vscode_adapter.py b/sdk/identity/azure-identity/azure/identity/_internal/macos_vscode_adapter.py similarity index 100% rename from sdk/identity/azure-identity/azure/identity/_credentials/macos_vscode_adapter.py rename to sdk/identity/azure-identity/azure/identity/_internal/macos_vscode_adapter.py diff --git a/sdk/identity/azure-identity/azure/identity/_internal/msal_credentials.py b/sdk/identity/azure-identity/azure/identity/_internal/msal_credentials.py index 826ed9ef50d2..ac2966c93e1d 100644 --- a/sdk/identity/azure-identity/azure/identity/_internal/msal_credentials.py +++ b/sdk/identity/azure-identity/azure/identity/_internal/msal_credentials.py @@ -13,12 +13,11 @@ from azure.core.credentials import AccessToken from azure.core.exceptions import ClientAuthenticationError -from .exception_wrapper import wrap_exceptions from .msal_client import MsalClient from .persistent_cache import load_user_cache from .._constants import KnownAuthorities from .._exceptions import AuthenticationRequiredError, CredentialUnavailableError -from .._internal import get_default_authority, normalize_authority +from .._internal import get_default_authority, normalize_authority, wrap_exceptions from .._auth_record import AuthenticationRecord try: @@ -35,7 +34,6 @@ # pylint:disable=ungrouped-imports,unused-import from typing import Any, Mapping, Optional, Type, Union - _LOGGER = logging.getLogger(__name__) _DEFAULT_AUTHENTICATE_SCOPES = { @@ -127,22 +125,7 @@ def _create_app(self, cls): return app -class PublicClientCredential(MsalCredential): - """Wraps an MSAL PublicClientApplication with the TokenCredential API""" - - @abc.abstractmethod - def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument - # type: (*str, **Any) -> AccessToken - pass - - def _get_app(self): - # type: () -> msal.PublicClientApplication - if not self._msal_app: - self._msal_app = self._create_app(msal.PublicClientApplication) - return self._msal_app - - -class InteractiveCredential(PublicClientCredential): +class InteractiveCredential(MsalCredential): def __init__(self, **kwargs): self._disable_automatic_authentication = kwargs.pop("disable_automatic_authentication", False) self._auth_record = kwargs.pop("authentication_record", None) # type: Optional[AuthenticationRecord] @@ -174,33 +157,50 @@ def get_token(self, *scopes, **kwargs): configured not to begin this automatically. Call :func:`authenticate` to begin interactive authentication. """ if not scopes: - raise ValueError("'get_token' requires at least one scope") + message = "'get_token' requires at least one scope" + _LOGGER.warning("%s.get_token failed: %s", self.__class__.__name__, message) + raise ValueError(message) allow_prompt = kwargs.pop("_allow_prompt", not self._disable_automatic_authentication) try: - return self._acquire_token_silent(*scopes, **kwargs) - except AuthenticationRequiredError: - if not allow_prompt: + token = self._acquire_token_silent(*scopes, **kwargs) + _LOGGER.info("%s.get_token succeeded", self.__class__.__name__) + return token + except Exception as ex: # pylint:disable=broad-except + if not (isinstance(ex, AuthenticationRequiredError) and allow_prompt): + _LOGGER.warning( + "%s.get_token failed: %s", + self.__class__.__name__, + ex, + exc_info=_LOGGER.isEnabledFor(logging.DEBUG), + ) raise # silent authentication failed -> authenticate interactively now = int(time.time()) - result = self._request_token(*scopes, **kwargs) - if "access_token" not in result: - message = "Authentication failed: {}".format(result.get("error_description") or result.get("error")) - raise ClientAuthenticationError(message=message) - - # this may be the first authentication, or the user may have authenticated a different identity - self._auth_record = _build_auth_record(result) + try: + result = self._request_token(*scopes, **kwargs) + if "access_token" not in result: + message = "Authentication failed: {}".format(result.get("error_description") or result.get("error")) + raise ClientAuthenticationError(message=message) + + # this may be the first authentication, or the user may have authenticated a different identity + self._auth_record = _build_auth_record(result) + except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning( + "%s.get_token failed: %s", self.__class__.__name__, ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG), + ) + raise + _LOGGER.info("%s.get_token succeeded", self.__class__.__name__) return AccessToken(result["access_token"], now + int(result["expires_in"])) def authenticate(self, **kwargs): # type: (**Any) -> AuthenticationRecord """Interactively authenticate a user. - :keyword Sequence[str] scopes: scopes to request during authentication, such as those provided by + :keyword Iterable[str] scopes: scopes to request during authentication, such as those provided by :func:`AuthenticationRequiredError.scopes`. If provided, successful authentication will cache an access token for these scopes. :rtype: ~azure.identity.AuthenticationRecord @@ -246,3 +246,9 @@ def _acquire_token_silent(self, *scopes, **kwargs): def _request_token(self, *scopes, **kwargs): # type: (*str, **Any) -> dict """Request an access token via a non-silent MSAL token acquisition method, returning that method's result""" + + def _get_app(self): + # type: () -> msal.PublicClientApplication + if not self._msal_app: + self._msal_app = self._create_app(msal.PublicClientApplication) + return self._msal_app diff --git a/sdk/identity/azure-identity/azure/identity/_internal/shared_token_cache.py b/sdk/identity/azure-identity/azure/identity/_internal/shared_token_cache.py index 414819cc4ed0..d28a7602fd5e 100644 --- a/sdk/identity/azure-identity/azure/identity/_internal/shared_token_cache.py +++ b/sdk/identity/azure-identity/azure/identity/_internal/shared_token_cache.py @@ -28,7 +28,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports - from typing import Any, Iterable, List, Mapping, Optional, Sequence + from typing import Any, Iterable, List, Mapping, Optional from .._internal import AadClientBase from azure.identity import AuthenticationRecord @@ -203,7 +203,7 @@ def _get_account(self, username=None, tenant_id=None): raise CredentialUnavailableError(message=message) def _get_cached_access_token(self, scopes, account): - # type: (Sequence[str], CacheItem) -> Optional[AccessToken] + # type: (Iterable[str], CacheItem) -> Optional[AccessToken] if "home_account_id" not in account: return None diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/win_vscode_adapter.py b/sdk/identity/azure-identity/azure/identity/_internal/win_vscode_adapter.py similarity index 100% rename from sdk/identity/azure-identity/azure/identity/_credentials/win_vscode_adapter.py rename to sdk/identity/azure-identity/azure/identity/_internal/win_vscode_adapter.py diff --git a/sdk/identity/azure-identity/azure/identity/aio/_authn_client.py b/sdk/identity/azure-identity/azure/identity/aio/_authn_client.py index 53cc9fc32959..42c441b39762 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_authn_client.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_authn_client.py @@ -75,6 +75,7 @@ async def request_token( # pylint:disable=invalid-overridden-method ) -> AccessToken: request = self._prepare_request(method, headers=headers, form_data=form_data, params=params) request_time = int(time.time()) + self._last_refresh_time = request_time # no matter succeed or not, update the last refresh time response = await self._pipeline.run(request, stream=False, **kwargs) token = self._deserialize_and_cache_token(response=response, scopes=scopes, request_time=request_time) return token diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/authorization_code.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/authorization_code.py index 0b5fbb53dc33..7528fbb05516 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/authorization_code.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/authorization_code.py @@ -7,10 +7,11 @@ from azure.core.exceptions import ClientAuthenticationError from .base import AsyncCredentialBase from .._internal import AadClient +from .._internal.decorators import log_get_token_async if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports - from typing import Any, Optional, Sequence + from typing import Any, Iterable, Optional from azure.core.credentials import AccessToken @@ -51,6 +52,7 @@ def __init__( self._client = kwargs.pop("client", None) or AadClient(tenant_id, client_id, **kwargs) self._redirect_uri = redirect_uri + @log_get_token_async async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": """Request an access token for `scopes`. @@ -80,7 +82,11 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": token = self._client.get_cached_access_token(scopes) if not token: token = await self._redeem_refresh_token(scopes, **kwargs) - + elif self._client.should_refresh(token): + try: + await self._redeem_refresh_token(scopes, **kwargs) + except Exception: # pylint: disable=broad-except + pass if not token: raise ClientAuthenticationError( message="No authorization code, cached access token, or refresh token available." @@ -88,7 +94,7 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": return token - async def _redeem_refresh_token(self, scopes: "Sequence[str]", **kwargs: "Any") -> "Optional[AccessToken]": + async def _redeem_refresh_token(self, scopes: "Iterable[str]", **kwargs: "Any") -> "Optional[AccessToken]": for refresh_token in self._client.get_cached_refresh_tokens(scopes): if "secret" not in refresh_token: continue diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_cli.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_cli.py index 56c025680db3..00d348db648e 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_cli.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/azure_cli.py @@ -8,6 +8,7 @@ from azure.core.exceptions import ClientAuthenticationError from .._credentials.base import AsyncCredentialBase +from .._internal.decorators import log_get_token_async from ... import CredentialUnavailableError from ..._credentials.azure_cli import ( AzureCliCredential as _SyncAzureCliCredential, @@ -27,6 +28,7 @@ class AzureCliCredential(AsyncCredentialBase): This requires previously logging in to Azure via "az login", and will use the CLI's currently logged in identity. """ + @log_get_token_async async def get_token(self, *scopes, **kwargs): """Request an access token for `scopes`. diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/certificate.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/certificate.py index a569ea5af8db..180d9cba11e5 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/certificate.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/certificate.py @@ -6,6 +6,7 @@ from .base import AsyncCredentialBase from .._internal import AadClient +from .._internal.decorators import log_get_token_async from ..._internal import CertificateCredentialBase if TYPE_CHECKING: @@ -37,7 +38,8 @@ async def close(self): await self._client.__aexit__() - async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": + @log_get_token_async + async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": # pylint:disable=unused-argument """Asynchronously request an access token for `scopes`. .. note:: This method is called by Azure SDK clients. It isn't intended for use in application code. @@ -54,6 +56,11 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": token = self._client.get_cached_access_token(scopes, query={"client_id": self._client_id}) if not token: token = await self._client.obtain_token_by_client_certificate(scopes, self._certificate, **kwargs) + elif self._client.should_refresh(token): + try: + await self._client.obtain_token_by_client_certificate(scopes, self._certificate, **kwargs) + except Exception: # pylint: disable=broad-except + pass return token def _get_auth_client(self, tenant_id, client_id, **kwargs): diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/chained.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/chained.py index aab679966e15..b20538d53e49 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/chained.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/chained.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. # ------------------------------------ import asyncio +import logging from typing import TYPE_CHECKING from azure.core.exceptions import ClientAuthenticationError @@ -15,6 +16,8 @@ from azure.core.credentials import AccessToken from azure.core.credentials_async import AsyncTokenCredential +_LOGGER = logging.getLogger(__name__) + class ChainedTokenCredential(AsyncCredentialBase): """A sequence of credentials that is itself a credential. @@ -53,14 +56,23 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": for credential in self.credentials: try: token = await credential.get_token(*scopes, **kwargs) + _LOGGER.info("%s acquired a token from %s", self.__class__.__name__, credential.__class__.__name__) self._successful_credential = credential return token except CredentialUnavailableError as ex: # credential didn't attempt authentication because it lacks required data or state -> continue history.append((credential, ex.message)) + _LOGGER.info("%s - %s is unavailable", self.__class__.__name__, credential.__class__.__name__) except Exception as ex: # pylint: disable=broad-except # credential failed to authenticate, or something unexpectedly raised -> break history.append((credential, str(ex))) + _LOGGER.warning( + '%s.get_token failed: %s raised unexpected error "%s"', + self.__class__.__name__, + credential.__class__.__name__, + ex, + exc_info=_LOGGER.isEnabledFor(logging.DEBUG), + ) break attempts = _get_error_message(history) diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/client_secret.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/client_secret.py index 87b5472760e6..f6249dc61ec0 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/client_secret.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/client_secret.py @@ -6,6 +6,7 @@ from .base import AsyncCredentialBase from .._internal import AadClient +from .._internal.decorators import log_get_token_async from ..._internal import ClientSecretCredentialBase if TYPE_CHECKING: @@ -38,6 +39,7 @@ async def close(self): await self._client.__aexit__() + @log_get_token_async async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": """Asynchronously request an access token for `scopes`. @@ -55,6 +57,11 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": token = self._client.get_cached_access_token(scopes, query={"client_id": self._client_id}) if not token: token = await self._client.obtain_token_by_client_secret(scopes, self._secret, **kwargs) + elif self._client.should_refresh(token): + try: + await self._client.obtain_token_by_client_secret(scopes, self._secret, **kwargs) + except Exception: # pylint: disable=broad-except + pass return token def _get_auth_client(self, tenant_id, client_id, **kwargs): diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py index 7e1197d702c2..2599e54ee69a 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py @@ -2,9 +2,12 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +import logging import os from typing import TYPE_CHECKING +from .._internal.decorators import log_get_token_async + from ... import CredentialUnavailableError from ..._constants import EnvironmentVariables from .certificate import CertificateCredential @@ -15,6 +18,8 @@ from typing import Any, Optional, Union from azure.core.credentials import AccessToken +_LOGGER = logging.getLogger(__name__) + class EnvironmentCredential(AsyncCredentialBase): """A credential configured by environment variables. @@ -30,7 +35,7 @@ class EnvironmentCredential(AsyncCredentialBase): Service principal with certificate: - **AZURE_TENANT_ID**: ID of the service principal's tenant. Also called its 'directory' ID. - **AZURE_CLIENT_ID**: the service principal's client ID - - **AZURE_CLIENT_CERTIFICATE_PATH**: path to a PEM-encoded certificate file including the private key The + - **AZURE_CLIENT_CERTIFICATE_PATH**: path to a PEM-encoded certificate file including the private key. The certificate must not be password-protected. """ @@ -52,6 +57,16 @@ def __init__(self, **kwargs: "Any") -> None: **kwargs ) + if self._credential: + _LOGGER.info("Environment is configured for %s", self._credential.__class__.__name__) + else: + expected_variables = set(EnvironmentVariables.CERT_VARS + EnvironmentVariables.CLIENT_SECRET_VARS) + set_variables = [v for v in expected_variables if v in os.environ] + if set_variables: + _LOGGER.warning("Incomplete environment configuration. Set variables: %s", ", ".join(set_variables)) + else: + _LOGGER.info("No environment configuration found.") + async def __aenter__(self): if self._credential: await self._credential.__aenter__() @@ -63,6 +78,7 @@ async def close(self): if self._credential: await self._credential.__aexit__() + @log_get_token_async async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": """Asynchronously request an access token for `scopes`. diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/managed_identity.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/managed_identity.py index 5e5bf172f43e..7def20143526 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/managed_identity.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/managed_identity.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. # ------------------------------------ import abc +import logging import os from typing import TYPE_CHECKING @@ -10,16 +11,19 @@ from azure.core.exceptions import ClientAuthenticationError, HttpResponseError from azure.core.pipeline.policies import AsyncRetryPolicy -from azure.identity._credentials.managed_identity import _ManagedIdentityBase from .base import AsyncCredentialBase from .._authn_client import AsyncAuthnClient +from .._internal.decorators import log_get_token_async from ... import CredentialUnavailableError from ..._constants import Endpoints, EnvironmentVariables +from ..._credentials.managed_identity import _ManagedIdentityBase if TYPE_CHECKING: from typing import Any, Optional from azure.core.configuration import Configuration +_LOGGER = logging.getLogger(__name__) + class ManagedIdentityCredential(AsyncCredentialBase): """Authenticates with an Azure managed identity in any hosting environment which supports managed identities. @@ -37,8 +41,10 @@ class ManagedIdentityCredential(AsyncCredentialBase): def __init__(self, **kwargs: "Any") -> None: self._credential = None if os.environ.get(EnvironmentVariables.MSI_ENDPOINT): + _LOGGER.info("%s will use MSI", self.__class__.__name__) self._credential = MsiCredential(**kwargs) else: + _LOGGER.info("%s will use IMDS", self.__class__.__name__) self._credential = ImdsCredential(**kwargs) async def __aenter__(self): @@ -51,6 +57,7 @@ async def close(self): if self._credential: await self._credential.__aexit__() + @log_get_token_async async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": """Asynchronously request an access token for `scopes`. @@ -120,6 +127,7 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> AccessToken: # pyli except Exception: # pylint:disable=broad-except # if anything else was raised, assume the endpoint is unavailable self._endpoint_available = False + _LOGGER.info("No response from the IMDS endpoint.") if not self._endpoint_available: message = "ManagedIdentityCredential authentication unavailable, no managed identity endpoint found." @@ -130,30 +138,39 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> AccessToken: # pyli token = self._client.get_cached_token(scopes) if not token: - resource = scopes[0] - if resource.endswith("/.default"): - resource = resource[: -len("/.default")] - params = {"api-version": "2018-02-01", "resource": resource, **self._identity_config} - + token = await self._refresh_token(*scopes) + elif self._client.should_refresh(token): try: - token = await self._client.request_token(scopes, method="GET", params=params) - except HttpResponseError as ex: - # 400 in response to a token request indicates managed identity is disabled, - # or the identity with the specified client_id is not available - if ex.status_code == 400: - self._endpoint_available = False - message = "ManagedIdentityCredential authentication unavailable. " - if self._identity_config: - message += "The requested identity has not been assigned to this resource." - else: - message += "No identity has been assigned to this resource." - raise CredentialUnavailableError(message=message) from ex - - # any other error is unexpected - raise ClientAuthenticationError(message=ex.message, response=ex.response) from None + token = await self._refresh_token(*scopes) + except Exception: # pylint: disable=broad-except + pass return token + async def _refresh_token(self, *scopes): + resource = scopes[0] + if resource.endswith("/.default"): + resource = resource[: -len("/.default")] + params = {"api-version": "2018-02-01", "resource": resource, **self._identity_config} + + try: + token = await self._client.request_token(scopes, method="GET", params=params) + except HttpResponseError as ex: + # 400 in response to a token request indicates managed identity is disabled, + # or the identity with the specified client_id is not available + if ex.status_code == 400: + self._endpoint_available = False + message = "ManagedIdentityCredential authentication unavailable. " + if self._identity_config: + message += "The requested identity has not been assigned to this resource." + else: + message += "No identity has been assigned to this resource." + raise CredentialUnavailableError(message=message) from ex + + # any other error is unexpected + raise ClientAuthenticationError(message=ex.message, response=ex.response) from None + return token + class MsiCredential(_AsyncManagedIdentityBase): """Authenticates via the MSI endpoint in an App Service or Cloud Shell environment. @@ -184,17 +201,26 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> AccessToken: # pyli token = self._client.get_cached_token(scopes) if not token: - resource = scopes[0] - if resource.endswith("/.default"): - resource = resource[: -len("/.default")] - - secret = os.environ.get(EnvironmentVariables.MSI_SECRET) - if secret: - # MSI_ENDPOINT and MSI_SECRET set -> App Service - token = await self._request_app_service_token(scopes=scopes, resource=resource, secret=secret) - else: - # only MSI_ENDPOINT set -> legacy-style MSI (Cloud Shell) - token = await self._request_legacy_token(scopes=scopes, resource=resource) + token = await self._refresh_token(*scopes) + elif self._client.should_refresh(token): + try: + token = await self._refresh_token(*scopes) + except Exception: # pylint: disable=broad-except + pass + return token + + async def _refresh_token(self, *scopes): + resource = scopes[0] + if resource.endswith("/.default"): + resource = resource[: -len("/.default")] + + secret = os.environ.get(EnvironmentVariables.MSI_SECRET) + if secret: + # MSI_ENDPOINT and MSI_SECRET set -> App Service + token = await self._request_app_service_token(scopes=scopes, resource=resource, secret=secret) + else: + # only MSI_ENDPOINT set -> legacy-style MSI (Cloud Shell) + token = await self._request_legacy_token(scopes=scopes, resource=resource) return token async def _request_app_service_token(self, scopes, resource, secret): diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/shared_cache.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/shared_cache.py index 66f25038aa6b..7b7ef7c28590 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/shared_cache.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/shared_cache.py @@ -8,6 +8,7 @@ from ..._constants import AZURE_CLI_CLIENT_ID from ..._internal.shared_token_cache import NO_TOKEN, SharedTokenCacheBase from .._internal.aad_client import AadClient +from .._internal.decorators import log_get_token_async from .base import AsyncCredentialBase if TYPE_CHECKING: @@ -45,6 +46,7 @@ async def close(self): if self._client: await self._client.__aexit__() + @log_get_token_async async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": # pylint:disable=unused-argument """Get an access token for `scopes` from the shared cache. diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/vscode_credential.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/vscode_credential.py index 798aefe8c5c2..eb235bb19776 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/vscode_credential.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/vscode_credential.py @@ -3,10 +3,12 @@ # Licensed under the MIT License. # ------------------------------------ from typing import TYPE_CHECKING + from ..._exceptions import CredentialUnavailableError from .._credentials.base import AsyncCredentialBase from ..._constants import AZURE_VSCODE_CLIENT_ID from .._internal.aad_client import AadClient +from .._internal.decorators import log_get_token_async from ..._credentials.vscode_credential import get_credentials if TYPE_CHECKING: @@ -33,6 +35,7 @@ async def close(self): if self._client: await self._client.__aexit__() + @log_get_token_async async def get_token(self, *scopes, **kwargs): # type: (*str, **Any) -> AccessToken """Request an access token for `scopes`. @@ -50,9 +53,16 @@ async def get_token(self, *scopes, **kwargs): raise ValueError("'get_token' requires at least one scope") token = self._client.get_cached_access_token(scopes) - if token: - return token + if not token: + token = await self._redeem_refresh_token(scopes, **kwargs) + elif self._client.should_refresh(token): + try: + await self._redeem_refresh_token(scopes, **kwargs) + except Exception: # pylint: disable=broad-except + pass + return token + async def _redeem_refresh_token(self, scopes: "Sequence[str]", **kwargs: "Any") -> "Optional[AccessToken]": if not self._refresh_token: self._refresh_token = get_credentials() if not self._refresh_token: diff --git a/sdk/identity/azure-identity/azure/identity/aio/_internal/__init__.py b/sdk/identity/azure-identity/azure/identity/aio/_internal/__init__.py index 82f17fb260f8..9653b45acab7 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_internal/__init__.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_internal/__init__.py @@ -3,6 +3,6 @@ # Licensed under the MIT License. # ------------------------------------ from .aad_client import AadClient -from .exception_wrapper import wrap_exceptions +from .decorators import wrap_exceptions __all__ = ["AadClient", "wrap_exceptions"] diff --git a/sdk/identity/azure-identity/azure/identity/aio/_internal/aad_client.py b/sdk/identity/azure-identity/azure/identity/aio/_internal/aad_client.py index db5065412ae8..24322896727c 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_internal/aad_client.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_internal/aad_client.py @@ -20,7 +20,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports - from typing import Any, List, Optional, Sequence, Union + from typing import Any, Iterable, List, Optional, Union from azure.core.credentials import AccessToken from azure.core.pipeline.policies import AsyncHTTPPolicy, SansIOHTTPPolicy from azure.core.pipeline.transport import AsyncHttpTransport @@ -45,7 +45,7 @@ async def close(self) -> None: async def obtain_token_by_authorization_code( self, - scopes: "Sequence[str]", + scopes: "Iterable[str]", code: str, redirect_uri: str, client_secret: "Optional[str]" = None, @@ -59,14 +59,14 @@ async def obtain_token_by_authorization_code( return self._process_response(response, now) async def obtain_token_by_client_certificate(self, scopes, certificate, **kwargs): - # type: (Sequence[str], AadClientCertificate, **Any) -> AccessToken + # type: (Iterable[str], AadClientCertificate, **Any) -> AccessToken request = self._get_client_certificate_request(scopes, certificate) now = int(time.time()) response = await self._pipeline.run(request, stream=False, **kwargs) return self._process_response(response, now) async def obtain_token_by_client_secret( - self, scopes: "Sequence[str]", secret: str, **kwargs: "Any" + self, scopes: "Iterable[str]", secret: str, **kwargs: "Any" ) -> "AccessToken": request = self._get_client_secret_request(scopes, secret) now = int(time.time()) @@ -74,7 +74,7 @@ async def obtain_token_by_client_secret( return self._process_response(response, now) async def obtain_token_by_refresh_token( - self, scopes: "Sequence[str]", refresh_token: str, **kwargs: "Any" + self, scopes: "Iterable[str]", refresh_token: str, **kwargs: "Any" ) -> "AccessToken": request = self._get_refresh_token_request(scopes, refresh_token) now = int(time.time()) diff --git a/sdk/identity/azure-identity/azure/identity/aio/_internal/exception_wrapper.py b/sdk/identity/azure-identity/azure/identity/aio/_internal/decorators.py similarity index 62% rename from sdk/identity/azure-identity/azure/identity/aio/_internal/exception_wrapper.py rename to sdk/identity/azure-identity/azure/identity/aio/_internal/decorators.py index 4d6f40f954cb..10bbd33269d2 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_internal/exception_wrapper.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_internal/decorators.py @@ -3,9 +3,25 @@ # Licensed under the MIT License. # ------------------------------------ import functools +import logging from azure.core.exceptions import ClientAuthenticationError +_LOGGER = logging.getLogger(__name__) + + +def log_get_token_async(fn): + @functools.wraps(fn) + async def wrapper(*args, **kwargs): + try: + token = await fn(*args, **kwargs) + _LOGGER.info("%s succeeded", fn.__qualname__) + return token + except Exception as ex: + _LOGGER.warning("%s failed: %s", fn.__qualname__, ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + raise + return wrapper + def wrap_exceptions(fn): """Prevents leaking exceptions defined outside azure-core by raising ClientAuthenticationError from them.""" diff --git a/sdk/identity/azure-identity/samples/README.md b/sdk/identity/azure-identity/samples/README.md new file mode 100644 index 000000000000..35a9cd502650 --- /dev/null +++ b/sdk/identity/azure-identity/samples/README.md @@ -0,0 +1,37 @@ +--- +page_type: sample +languages: + - python +products: + - azure + - azure-identity +urlFragment: identity-samples +--- + +# Azure Identity Library Python Samples + +## Prerequisites + +You must have an [Azure subscription](https://azure.microsoft.com/free) and an +[Azure Key Vault](https://azure.microsoft.com/en-us/services/key-vault/) to run +these samples. You can create a Key Vault in the +[Azure Portal](https://portal.azure.com/#create/Microsoft.KeyVault) or with the +[Azure CLI](https://docs.microsoft.com/en-us/azure/key-vault/secrets/quick-create-cli). + +Azure Key Vault is used only to demonstrate authentication. Azure Identity has +the same API for all compatible client libraries. + +## Setup + +To run these samples, first install the Azure Identity and Key Vault Secrets +client libraries: + +```commandline +pip install azure-identity azure-keyvault-secrets +``` + +## Contents +| File | Description | +|-------------|-------------| +| control_interactive_prompts.py | demonstrates controlling when interactive credentials prompt for user interaction | +| user_authentication.py | demonstrates user authentication API for applications | diff --git a/sdk/identity/azure-identity/samples/control_interactive_prompts.py b/sdk/identity/azure-identity/samples/control_interactive_prompts.py new file mode 100644 index 000000000000..10dabf65e9d2 --- /dev/null +++ b/sdk/identity/azure-identity/samples/control_interactive_prompts.py @@ -0,0 +1,38 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +"""Demonstrates controlling the timing of interactive authentication using InteractiveBrowserCredential. + +DeviceCodeCredential supports the same API. +""" + +import os +import sys +from azure.identity import AuthenticationRequiredError, InteractiveBrowserCredential +from azure.keyvault.secrets import SecretClient + + +# This sample uses Key Vault only for demonstration. Any client accepting azure-identity credentials will work the same. +VAULT_URL = os.environ.get("VAULT_URL") +if not VAULT_URL: + print("This sample expects environment variable 'VAULT_URL' to be set with the URL of a Key Vault.") + sys.exit(1) + + +# If it's important for your application to prompt for authentication only at certain times, +# create the credential with disable_automatic_authentication=True. This configures the credential to raise +# when interactive authentication is required, instead of immediately beginning that authentication. +credential = InteractiveBrowserCredential(disable_automatic_authentication=True) +client = SecretClient(VAULT_URL, credential) + +try: + secret_names = [s.name for s in client.list_properties_of_secrets()] +except AuthenticationRequiredError as ex: + # Interactive authentication is necessary to authorize the client's request. The exception carries the + # requested authentication scopes. If you pass these to 'authenticate', it will cache an access token + # for those scopes. + credential.authenticate(scopes=ex.scopes) + +# the client operation should now succeed +secret_names = [s.name for s in client.list_properties_of_secrets()] diff --git a/sdk/identity/azure-identity/samples/user_authentication.py b/sdk/identity/azure-identity/samples/user_authentication.py new file mode 100644 index 000000000000..2c21c2a44973 --- /dev/null +++ b/sdk/identity/azure-identity/samples/user_authentication.py @@ -0,0 +1,43 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +"""Demonstrates user authentication using InteractiveBrowserCredential. DeviceCodeCredential supports the same API.""" + +import os +import sys +from azure.identity import AuthenticationRecord, InteractiveBrowserCredential +from azure.keyvault.secrets import SecretClient + + +# This sample uses Key Vault only for demonstration. Any client accepting azure-identity credentials will work the same. +VAULT_URL = os.environ.get("VAULT_URL") +if not VAULT_URL: + print("This sample expects environment variable 'VAULT_URL' to be set with the URL of a Key Vault.") + sys.exit(1) + + +# Persistent caching is optional. By default, interactive credentials cache in memory only. +credential = InteractiveBrowserCredential(enable_persistent_cache=True) + +# The 'authenticate' method begins interactive authentication. Call it whenever it's convenient +# for your application to authenticate a user. It returns a record of the authentication. +record = credential.authenticate() + +# The record contains no authentication secrets. You can serialize it to JSON for storage. +record_json = record.serialize() + +# An authenticated credential is ready for use with a client. This request should succeed +# without prompting for authentication again. +client = SecretClient(VAULT_URL, credential) +secret_names = [s.name for s in client.list_properties_of_secrets()] + +# With persistent caching enabled, an authentication record stored by your application enables +# credentials to access data from past authentications. If the cache contains sufficient data, +# this eliminates the need for your application to prompt for authentication every time it runs. +deserialized_record = AuthenticationRecord.deserialize(record_json) +new_credential = InteractiveBrowserCredential(enable_persistent_cache=True, authentication_record=deserialized_record) + +# This request should also succeed without prompting for authentication. +client = SecretClient(VAULT_URL, new_credential) +secret_names = [s.name for s in client.list_properties_of_secrets()] diff --git a/sdk/identity/azure-identity/tests/test_aad_client.py b/sdk/identity/azure-identity/tests/test_aad_client.py index daa40c3d4659..b878d4bbf5e8 100644 --- a/sdk/identity/azure-identity/tests/test_aad_client.py +++ b/sdk/identity/azure-identity/tests/test_aad_client.py @@ -3,10 +3,11 @@ # Licensed under the MIT License. # ------------------------------------ import functools - +import time from azure.core.exceptions import ClientAuthenticationError -from azure.identity._constants import EnvironmentVariables +from azure.identity._constants import EnvironmentVariables, DEFAULT_REFRESH_OFFSET, DEFAULT_TOKEN_REFRESH_RETRY_DELAY from azure.identity._internal.aad_client import AadClient +from azure.core.credentials import AccessToken import pytest from msal import TokenCache from six.moves.urllib_parse import urlparse @@ -201,3 +202,24 @@ def send(request, **_): assert transport.send.call_count == 1 assert len(cache.find(TokenCache.CredentialType.REFRESH_TOKEN)) == 1 assert len(cache.find(TokenCache.CredentialType.REFRESH_TOKEN, query={"secret": invalid_token})) == 0 + + +def test_should_refresh(): + client = AadClient("test", "test") + now = int(time.time()) + + # do not need refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET + 1) + should_refresh = client.should_refresh(token) + assert not should_refresh + + # need refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET - 1) + should_refresh = client.should_refresh(token) + assert should_refresh + + # not exceed cool down time, do not refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET - 1) + client._last_refresh_time = now - DEFAULT_TOKEN_REFRESH_RETRY_DELAY + 1 + should_refresh = client.should_refresh(token) + assert not should_refresh diff --git a/sdk/identity/azure-identity/tests/test_aad_client_async.py b/sdk/identity/azure-identity/tests/test_aad_client_async.py index e43f70bd4369..ab9cd8208809 100644 --- a/sdk/identity/azure-identity/tests/test_aad_client_async.py +++ b/sdk/identity/azure-identity/tests/test_aad_client_async.py @@ -5,10 +5,11 @@ import functools from unittest.mock import Mock, patch from urllib.parse import urlparse - +import time from azure.core.exceptions import ClientAuthenticationError -from azure.identity._constants import EnvironmentVariables +from azure.identity._constants import EnvironmentVariables, DEFAULT_REFRESH_OFFSET, DEFAULT_TOKEN_REFRESH_RETRY_DELAY from azure.identity.aio._internal.aad_client import AadClient +from azure.core.credentials import AccessToken from msal import TokenCache import pytest @@ -208,3 +209,24 @@ async def send(request, **_): assert transport.send.call_count == 1 assert len(cache.find(TokenCache.CredentialType.REFRESH_TOKEN)) == 1 assert len(cache.find(TokenCache.CredentialType.REFRESH_TOKEN, query={"secret": invalid_token})) == 0 + + +async def test_should_refresh(): + client = AadClient("test", "test") + now = int(time.time()) + + # do not need refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET + 1) + should_refresh = client.should_refresh(token) + assert not should_refresh + + # need refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET - 1) + should_refresh = client.should_refresh(token) + assert should_refresh + + # not exceed cool down time, do not refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET - 1) + client._last_refresh_time = now - DEFAULT_TOKEN_REFRESH_RETRY_DELAY + 1 + should_refresh = client.should_refresh(token) + assert not should_refresh diff --git a/sdk/identity/azure-identity/tests/test_authn_client.py b/sdk/identity/azure-identity/tests/test_authn_client.py index 6732d43cd4dc..c5dbbe41394a 100644 --- a/sdk/identity/azure-identity/tests/test_authn_client.py +++ b/sdk/identity/azure-identity/tests/test_authn_client.py @@ -14,7 +14,7 @@ from azure.core.credentials import AccessToken from azure.identity._authn_client import AuthnClient -from azure.identity._constants import EnvironmentVariables +from azure.identity._constants import EnvironmentVariables, DEFAULT_REFRESH_OFFSET, DEFAULT_TOKEN_REFRESH_RETRY_DELAY import pytest from six.moves.urllib_parse import urlparse from helpers import mock_response @@ -233,3 +233,24 @@ def mock_send(request, **kwargs): client.request_token(("scope",)) request = client.get_refresh_token_grant_request({"secret": "***"}, "scope") validate_url(request.url) + + +def test_should_refresh(): + client = AuthnClient(endpoint="http://foo") + now = int(time.time()) + + # do not need refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET + 1) + should_refresh = client.should_refresh(token) + assert not should_refresh + + # need refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET - 1) + should_refresh = client.should_refresh(token) + assert should_refresh + + # not exceed cool down time, do not refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET - 1) + client._last_refresh_time = now - DEFAULT_TOKEN_REFRESH_RETRY_DELAY + 1 + should_refresh = client.should_refresh(token) + assert not should_refresh diff --git a/sdk/identity/azure-identity/tests/test_authn_client_async.py b/sdk/identity/azure-identity/tests/test_authn_client_async.py index ab94c2c236c4..bd91e0374d95 100644 --- a/sdk/identity/azure-identity/tests/test_authn_client_async.py +++ b/sdk/identity/azure-identity/tests/test_authn_client_async.py @@ -2,12 +2,13 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -import asyncio +import time from unittest.mock import Mock, patch from urllib.parse import urlparse import pytest -from azure.identity._constants import EnvironmentVariables +from azure.core.credentials import AccessToken +from azure.identity._constants import EnvironmentVariables, DEFAULT_REFRESH_OFFSET, DEFAULT_TOKEN_REFRESH_RETRY_DELAY from azure.identity.aio._authn_client import AsyncAuthnClient from helpers import mock_response @@ -35,3 +36,24 @@ def mock_send(request, **kwargs): with patch.dict("os.environ", {EnvironmentVariables.AZURE_AUTHORITY_HOST: authority}, clear=True): client = AsyncAuthnClient(tenant=tenant_id, transport=Mock(send=wrap_in_future(mock_send))) await client.request_token(("scope",)) + + +def test_should_refresh(): + client = AsyncAuthnClient(endpoint="http://foo") + now = int(time.time()) + + # do not need refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET + 1) + should_refresh = client.should_refresh(token) + assert not should_refresh + + # need refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET - 1) + should_refresh = client.should_refresh(token) + assert should_refresh + + # not exceed cool down time, do not refresh + token = AccessToken("token", now + DEFAULT_REFRESH_OFFSET - 1) + client._last_refresh_time = now - DEFAULT_TOKEN_REFRESH_RETRY_DELAY + 1 + should_refresh = client.should_refresh(token) + assert not should_refresh diff --git a/sdk/identity/azure-identity/tests/test_vscode_credential.py b/sdk/identity/azure-identity/tests/test_vscode_credential.py index a0b320410bc8..6f22ad7ad8d6 100644 --- a/sdk/identity/azure-identity/tests/test_vscode_credential.py +++ b/sdk/identity/azure-identity/tests/test_vscode_credential.py @@ -94,7 +94,7 @@ def test_cache_refresh_token(): def test_no_obtain_token_if_cached(): expected_token = AccessToken("token", 42) - mock_client = mock.Mock(spec=object) + mock_client = mock.Mock(should_refresh=lambda _: False) mock_client.obtain_token_by_refresh_token = mock.Mock(return_value=expected_token) mock_client.get_cached_access_token = mock.Mock(return_value="VALUE") @@ -106,7 +106,7 @@ def test_no_obtain_token_if_cached(): @pytest.mark.skipif(not sys.platform.startswith("linux"), reason="This test only runs on Linux") def test_segfault(): - from azure.identity._credentials.linux_vscode_adapter import _get_refresh_token + from azure.identity._internal.linux_vscode_adapter import _get_refresh_token _get_refresh_token("test", "test") diff --git a/sdk/identity/azure-identity/tests/test_vscode_credential_async.py b/sdk/identity/azure-identity/tests/test_vscode_credential_async.py index 1f26651d45d8..5207c73641fe 100644 --- a/sdk/identity/azure-identity/tests/test_vscode_credential_async.py +++ b/sdk/identity/azure-identity/tests/test_vscode_credential_async.py @@ -97,7 +97,7 @@ async def test_cache_refresh_token(): async def test_no_obtain_token_if_cached(): expected_token = AccessToken("token", 42) - mock_client = mock.Mock(spec=object) + mock_client = mock.Mock(should_refresh=lambda _: False) token_by_refresh_token = mock.Mock(return_value=expected_token) mock_client.obtain_token_by_refresh_token = wrap_in_future(token_by_refresh_token) mock_client.get_cached_access_token = mock.Mock(return_value="VALUE") diff --git a/sdk/keyvault/azure-mgmt-keyvault/CHANGELOG.md b/sdk/keyvault/azure-mgmt-keyvault/CHANGELOG.md index 27220b5f5404..a532f1d9e1e5 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/CHANGELOG.md +++ b/sdk/keyvault/azure-mgmt-keyvault/CHANGELOG.md @@ -1,5 +1,10 @@ # Release History +## 7.0.0b2 (2020-07-21) + +**Bugfixes** + - Use service api_version "2015-11-01" instead of "2016-10-01". + ## 7.0.0b1 (2020-06-17) This is beta preview version. diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/_version.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/_version.py index 5c6ad95258f3..eed2e13a835f 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/_version.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/_version.py @@ -5,4 +5,4 @@ # license information. # -------------------------------------------------------------------------- -VERSION = "7.0.0b1" \ No newline at end of file +VERSION = "7.0.0b2" \ No newline at end of file diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/aio/operations_async/_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/aio/operations_async/_operations_async.py index 47ecb3338309..bb39715117fe 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/aio/operations_async/_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/aio/operations_async/_operations_async.py @@ -58,6 +58,10 @@ def list( api_version = "2016-10-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -65,15 +69,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/aio/operations_async/_vaults_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/aio/operations_async/_vaults_operations_async.py index 1f725751d290..93781d220655 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/aio/operations_async/_vaults_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/aio/operations_async/_vaults_operations_async.py @@ -87,7 +87,6 @@ async def create_or_update( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultCreateOrUpdateParameters') body_content_kwargs['content'] = body_content @@ -100,7 +99,6 @@ async def create_or_update( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -157,7 +155,6 @@ async def update( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultPatchParameters') body_content_kwargs['content'] = body_content @@ -170,7 +167,6 @@ async def update( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -221,7 +217,6 @@ async def delete( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -274,7 +269,6 @@ async def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -339,7 +333,6 @@ async def update_access_policy( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultAccessPolicyParameters') body_content_kwargs['content'] = body_content @@ -352,7 +345,6 @@ async def update_access_policy( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('VaultAccessPolicyParameters', pipeline_response) @@ -389,6 +381,10 @@ def list_by_resource_group( api_version = "2016-10-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_resource_group.metadata['url'] # type: ignore @@ -403,15 +399,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -458,6 +450,10 @@ def list_by_subscription( api_version = "2016-10-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_subscription.metadata['url'] # type: ignore @@ -471,15 +467,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -523,6 +515,10 @@ def list_deleted( api_version = "2016-10-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_deleted.metadata['url'] # type: ignore @@ -534,15 +530,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -608,7 +600,6 @@ async def get_deleted( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -652,7 +643,6 @@ async def _purge_deleted_initial( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.post(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -671,7 +661,7 @@ async def begin_purge_deleted( vault_name: str, location: str, **kwargs - ) -> None: + ) -> AsyncLROPoller[None]: """Permanently deletes the specified vault. aka Purges the deleted Azure key vault. :param vault_name: The name of the soft-deleted vault. @@ -684,8 +674,8 @@ async def begin_purge_deleted( polling object for personal polling strategy :paramtype polling: bool or ~azure.core.polling.AsyncPollingMethod :keyword int polling_interval: Default waiting time between two polls for LRO operations if no Retry-After header is present. - :return: None, or the result of cls(response) - :rtype: None + :return: An instance of AsyncLROPoller that returns either None or the result of cls(response) + :rtype: ~azure.core.polling.AsyncLROPoller[None] :raises ~azure.core.exceptions.HttpResponseError: """ polling = kwargs.pop('polling', True) # type: Union[bool, AsyncPollingMethod] @@ -742,9 +732,13 @@ def list( error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) filter = "resourceType eq 'Microsoft.KeyVault/vaults'" - api_version = "2016-10-01" + api_version = "2015-11-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -759,15 +753,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -830,7 +820,6 @@ async def check_name_availability( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(vault_name, 'VaultCheckNameAvailabilityParameters') body_content_kwargs['content'] = body_content diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/operations/_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/operations/_operations.py index dfe858a24401..7836d1e5bdb7 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/operations/_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/operations/_operations.py @@ -63,6 +63,10 @@ def list( api_version = "2016-10-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -70,15 +74,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/operations/_vaults_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/operations/_vaults_operations.py index 74854f5a895e..5aa92d56ad12 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/operations/_vaults_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2016_10_01/operations/_vaults_operations.py @@ -92,7 +92,6 @@ def create_or_update( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultCreateOrUpdateParameters') body_content_kwargs['content'] = body_content @@ -105,7 +104,6 @@ def create_or_update( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -163,7 +161,6 @@ def update( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultPatchParameters') body_content_kwargs['content'] = body_content @@ -176,7 +173,6 @@ def update( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -228,7 +224,6 @@ def delete( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -282,7 +277,6 @@ def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -348,7 +342,6 @@ def update_access_policy( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultAccessPolicyParameters') body_content_kwargs['content'] = body_content @@ -361,7 +354,6 @@ def update_access_policy( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('VaultAccessPolicyParameters', pipeline_response) @@ -399,6 +391,10 @@ def list_by_resource_group( api_version = "2016-10-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_resource_group.metadata['url'] # type: ignore @@ -413,15 +409,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -469,6 +461,10 @@ def list_by_subscription( api_version = "2016-10-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_subscription.metadata['url'] # type: ignore @@ -482,15 +478,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -535,6 +527,10 @@ def list_deleted( api_version = "2016-10-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_deleted.metadata['url'] # type: ignore @@ -546,15 +542,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -621,7 +613,6 @@ def get_deleted( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -666,7 +657,6 @@ def _purge_deleted_initial( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.post(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -686,7 +676,7 @@ def begin_purge_deleted( location, # type: str **kwargs # type: Any ): - # type: (...) -> LROPoller + # type: (...) -> LROPoller[None] """Permanently deletes the specified vault. aka Purges the deleted Azure key vault. :param vault_name: The name of the soft-deleted vault. @@ -758,9 +748,13 @@ def list( error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) filter = "resourceType eq 'Microsoft.KeyVault/vaults'" - api_version = "2016-10-01" + api_version = "2015-11-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -775,15 +769,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -847,7 +837,6 @@ def check_name_availability( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(vault_name, 'VaultCheckNameAvailabilityParameters') body_content_kwargs['content'] = body_content diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_operations_async.py index 6242c4e6289a..9d2336d57340 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_operations_async.py @@ -58,6 +58,10 @@ def list( api_version = "2018-02-14" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -65,15 +69,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_private_endpoint_connections_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_private_endpoint_connections_operations_async.py index 823750d8967c..e091b60e6508 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_private_endpoint_connections_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_private_endpoint_connections_operations_async.py @@ -86,7 +86,6 @@ async def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -152,7 +151,6 @@ async def put( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(properties, 'PrivateEndpointConnection') body_content_kwargs['content'] = body_content @@ -182,8 +180,8 @@ async def _delete_initial( vault_name: str, private_endpoint_connection_name: str, **kwargs - ) -> "models.PrivateEndpointConnection": - cls = kwargs.pop('cls', None) # type: ClsType["models.PrivateEndpointConnection"] + ) -> Optional["models.PrivateEndpointConnection"]: + cls = kwargs.pop('cls', None) # type: ClsType[Optional["models.PrivateEndpointConnection"]] error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) api_version = "2018-02-14" @@ -206,7 +204,6 @@ async def _delete_initial( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -236,7 +233,7 @@ async def begin_delete( vault_name: str, private_endpoint_connection_name: str, **kwargs - ) -> "models.PrivateEndpointConnection": + ) -> AsyncLROPoller["models.PrivateEndpointConnection"]: """Deletes the specified private endpoint connection associated with the key vault. :param resource_group_name: Name of the resource group that contains the key vault. @@ -252,8 +249,8 @@ async def begin_delete( polling object for personal polling strategy :paramtype polling: bool or ~azure.core.polling.AsyncPollingMethod :keyword int polling_interval: Default waiting time between two polls for LRO operations if no Retry-After header is present. - :return: PrivateEndpointConnection, or the result of cls(response) - :rtype: ~azure.mgmt.keyvault.v2018_02_14.models.PrivateEndpointConnection + :return: An instance of AsyncLROPoller that returns either PrivateEndpointConnection or the result of cls(response) + :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.keyvault.v2018_02_14.models.PrivateEndpointConnection] :raises ~azure.core.exceptions.HttpResponseError: """ polling = kwargs.pop('polling', True) # type: Union[bool, AsyncPollingMethod] diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_private_link_resources_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_private_link_resources_operations_async.py index f15e06765d74..9bb76c573251 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_private_link_resources_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_private_link_resources_operations_async.py @@ -79,7 +79,6 @@ async def list_by_vault( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_vaults_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_vaults_operations_async.py index 269f3da6038d..2d26869c6faa 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_vaults_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/aio/operations_async/_vaults_operations_async.py @@ -74,7 +74,6 @@ async def _create_or_update_initial( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultCreateOrUpdateParameters') body_content_kwargs['content'] = body_content @@ -87,7 +86,6 @@ async def _create_or_update_initial( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -106,7 +104,7 @@ async def begin_create_or_update( vault_name: str, parameters: "models.VaultCreateOrUpdateParameters", **kwargs - ) -> "models.Vault": + ) -> AsyncLROPoller["models.Vault"]: """Create or update a key vault in the specified subscription. :param resource_group_name: The name of the Resource Group to which the server belongs. @@ -121,8 +119,8 @@ async def begin_create_or_update( polling object for personal polling strategy :paramtype polling: bool or ~azure.core.polling.AsyncPollingMethod :keyword int polling_interval: Default waiting time between two polls for LRO operations if no Retry-After header is present. - :return: Vault, or the result of cls(response) - :rtype: ~azure.mgmt.keyvault.v2018_02_14.models.Vault + :return: An instance of AsyncLROPoller that returns either Vault or the result of cls(response) + :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.keyvault.v2018_02_14.models.Vault] :raises ~azure.core.exceptions.HttpResponseError: """ polling = kwargs.pop('polling', True) # type: Union[bool, AsyncPollingMethod] @@ -209,7 +207,6 @@ async def update( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultPatchParameters') body_content_kwargs['content'] = body_content @@ -222,7 +219,6 @@ async def update( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -273,7 +269,6 @@ async def delete( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -326,7 +321,6 @@ async def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -391,7 +385,6 @@ async def update_access_policy( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultAccessPolicyParameters') body_content_kwargs['content'] = body_content @@ -404,7 +397,6 @@ async def update_access_policy( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('VaultAccessPolicyParameters', pipeline_response) @@ -441,6 +433,10 @@ def list_by_resource_group( api_version = "2018-02-14" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_resource_group.metadata['url'] # type: ignore @@ -455,15 +451,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -510,6 +502,10 @@ def list_by_subscription( api_version = "2018-02-14" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_subscription.metadata['url'] # type: ignore @@ -523,15 +519,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -575,6 +567,10 @@ def list_deleted( api_version = "2018-02-14" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_deleted.metadata['url'] # type: ignore @@ -586,15 +582,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -660,7 +652,6 @@ async def get_deleted( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -704,7 +695,6 @@ async def _purge_deleted_initial( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.post(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -723,7 +713,7 @@ async def begin_purge_deleted( vault_name: str, location: str, **kwargs - ) -> None: + ) -> AsyncLROPoller[None]: """Permanently deletes the specified vault. aka Purges the deleted Azure key vault. :param vault_name: The name of the soft-deleted vault. @@ -736,8 +726,8 @@ async def begin_purge_deleted( polling object for personal polling strategy :paramtype polling: bool or ~azure.core.polling.AsyncPollingMethod :keyword int polling_interval: Default waiting time between two polls for LRO operations if no Retry-After header is present. - :return: None, or the result of cls(response) - :rtype: None + :return: An instance of AsyncLROPoller that returns either None or the result of cls(response) + :rtype: ~azure.core.polling.AsyncLROPoller[None] :raises ~azure.core.exceptions.HttpResponseError: """ polling = kwargs.pop('polling', True) # type: Union[bool, AsyncPollingMethod] @@ -794,9 +784,13 @@ def list( error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) filter = "resourceType eq 'Microsoft.KeyVault/vaults'" - api_version = "2018-02-14" + api_version = "2015-11-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -811,15 +805,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -882,7 +872,6 @@ async def check_name_availability( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(vault_name, 'VaultCheckNameAvailabilityParameters') body_content_kwargs['content'] = body_content diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_operations.py index e9d5d41a4e46..be8bf406ad45 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_operations.py @@ -63,6 +63,10 @@ def list( api_version = "2018-02-14" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -70,15 +74,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_private_endpoint_connections_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_private_endpoint_connections_operations.py index b9eacb3ba092..fb6c609fba68 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_private_endpoint_connections_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_private_endpoint_connections_operations.py @@ -91,7 +91,6 @@ def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -158,7 +157,6 @@ def put( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(properties, 'PrivateEndpointConnection') body_content_kwargs['content'] = body_content @@ -189,8 +187,8 @@ def _delete_initial( private_endpoint_connection_name, # type: str **kwargs # type: Any ): - # type: (...) -> "models.PrivateEndpointConnection" - cls = kwargs.pop('cls', None) # type: ClsType["models.PrivateEndpointConnection"] + # type: (...) -> Optional["models.PrivateEndpointConnection"] + cls = kwargs.pop('cls', None) # type: ClsType[Optional["models.PrivateEndpointConnection"]] error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) api_version = "2018-02-14" @@ -213,7 +211,6 @@ def _delete_initial( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -244,7 +241,7 @@ def begin_delete( private_endpoint_connection_name, # type: str **kwargs # type: Any ): - # type: (...) -> LROPoller + # type: (...) -> LROPoller["models.PrivateEndpointConnection"] """Deletes the specified private endpoint connection associated with the key vault. :param resource_group_name: Name of the resource group that contains the key vault. diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_private_link_resources_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_private_link_resources_operations.py index 303bace6fdc3..90e8eb527104 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_private_link_resources_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_private_link_resources_operations.py @@ -84,7 +84,6 @@ def list_by_vault( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_vaults_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_vaults_operations.py index df8155ca7ce1..a29a4f688c55 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_vaults_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2018_02_14/operations/_vaults_operations.py @@ -79,7 +79,6 @@ def _create_or_update_initial( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultCreateOrUpdateParameters') body_content_kwargs['content'] = body_content @@ -92,7 +91,6 @@ def _create_or_update_initial( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -112,7 +110,7 @@ def begin_create_or_update( parameters, # type: "models.VaultCreateOrUpdateParameters" **kwargs # type: Any ): - # type: (...) -> LROPoller + # type: (...) -> LROPoller["models.Vault"] """Create or update a key vault in the specified subscription. :param resource_group_name: The name of the Resource Group to which the server belongs. @@ -216,7 +214,6 @@ def update( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultPatchParameters') body_content_kwargs['content'] = body_content @@ -229,7 +226,6 @@ def update( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -281,7 +277,6 @@ def delete( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -335,7 +330,6 @@ def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -401,7 +395,6 @@ def update_access_policy( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultAccessPolicyParameters') body_content_kwargs['content'] = body_content @@ -414,7 +407,6 @@ def update_access_policy( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('VaultAccessPolicyParameters', pipeline_response) @@ -452,6 +444,10 @@ def list_by_resource_group( api_version = "2018-02-14" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_resource_group.metadata['url'] # type: ignore @@ -466,15 +462,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -522,6 +514,10 @@ def list_by_subscription( api_version = "2018-02-14" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_subscription.metadata['url'] # type: ignore @@ -535,15 +531,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -588,6 +580,10 @@ def list_deleted( api_version = "2018-02-14" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_deleted.metadata['url'] # type: ignore @@ -599,15 +595,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -674,7 +666,6 @@ def get_deleted( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -719,7 +710,6 @@ def _purge_deleted_initial( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.post(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -739,7 +729,7 @@ def begin_purge_deleted( location, # type: str **kwargs # type: Any ): - # type: (...) -> LROPoller + # type: (...) -> LROPoller[None] """Permanently deletes the specified vault. aka Purges the deleted Azure key vault. :param vault_name: The name of the soft-deleted vault. @@ -811,9 +801,13 @@ def list( error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) filter = "resourceType eq 'Microsoft.KeyVault/vaults'" - api_version = "2018-02-14" + api_version = "2015-11-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -828,15 +822,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -900,7 +890,6 @@ def check_name_availability( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(vault_name, 'VaultCheckNameAvailabilityParameters') body_content_kwargs['content'] = body_content diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_operations_async.py index a07488230478..2550e07a34f6 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_operations_async.py @@ -58,6 +58,10 @@ def list( api_version = "2019-09-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -65,15 +69,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_private_endpoint_connections_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_private_endpoint_connections_operations_async.py index 5441c5db5659..d178f5229c2f 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_private_endpoint_connections_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_private_endpoint_connections_operations_async.py @@ -86,7 +86,6 @@ async def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -152,7 +151,6 @@ async def put( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(properties, 'PrivateEndpointConnection') body_content_kwargs['content'] = body_content @@ -182,8 +180,8 @@ async def _delete_initial( vault_name: str, private_endpoint_connection_name: str, **kwargs - ) -> "models.PrivateEndpointConnection": - cls = kwargs.pop('cls', None) # type: ClsType["models.PrivateEndpointConnection"] + ) -> Optional["models.PrivateEndpointConnection"]: + cls = kwargs.pop('cls', None) # type: ClsType[Optional["models.PrivateEndpointConnection"]] error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) api_version = "2019-09-01" @@ -206,7 +204,6 @@ async def _delete_initial( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -236,7 +233,7 @@ async def begin_delete( vault_name: str, private_endpoint_connection_name: str, **kwargs - ) -> "models.PrivateEndpointConnection": + ) -> AsyncLROPoller["models.PrivateEndpointConnection"]: """Deletes the specified private endpoint connection associated with the key vault. :param resource_group_name: Name of the resource group that contains the key vault. @@ -252,8 +249,8 @@ async def begin_delete( polling object for personal polling strategy :paramtype polling: bool or ~azure.core.polling.AsyncPollingMethod :keyword int polling_interval: Default waiting time between two polls for LRO operations if no Retry-After header is present. - :return: PrivateEndpointConnection, or the result of cls(response) - :rtype: ~azure.mgmt.keyvault.v2019_09_01.models.PrivateEndpointConnection + :return: An instance of AsyncLROPoller that returns either PrivateEndpointConnection or the result of cls(response) + :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.keyvault.v2019_09_01.models.PrivateEndpointConnection] :raises ~azure.core.exceptions.HttpResponseError: """ polling = kwargs.pop('polling', True) # type: Union[bool, AsyncPollingMethod] diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_private_link_resources_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_private_link_resources_operations_async.py index 74957bed8692..bd21613268b5 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_private_link_resources_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_private_link_resources_operations_async.py @@ -79,7 +79,6 @@ async def list_by_vault( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_vaults_operations_async.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_vaults_operations_async.py index fc82562b634c..eaddd56bf6af 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_vaults_operations_async.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/aio/operations_async/_vaults_operations_async.py @@ -74,7 +74,6 @@ async def _create_or_update_initial( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultCreateOrUpdateParameters') body_content_kwargs['content'] = body_content @@ -87,7 +86,6 @@ async def _create_or_update_initial( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -106,7 +104,7 @@ async def begin_create_or_update( vault_name: str, parameters: "models.VaultCreateOrUpdateParameters", **kwargs - ) -> "models.Vault": + ) -> AsyncLROPoller["models.Vault"]: """Create or update a key vault in the specified subscription. :param resource_group_name: The name of the Resource Group to which the server belongs. @@ -121,8 +119,8 @@ async def begin_create_or_update( polling object for personal polling strategy :paramtype polling: bool or ~azure.core.polling.AsyncPollingMethod :keyword int polling_interval: Default waiting time between two polls for LRO operations if no Retry-After header is present. - :return: Vault, or the result of cls(response) - :rtype: ~azure.mgmt.keyvault.v2019_09_01.models.Vault + :return: An instance of AsyncLROPoller that returns either Vault or the result of cls(response) + :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.keyvault.v2019_09_01.models.Vault] :raises ~azure.core.exceptions.HttpResponseError: """ polling = kwargs.pop('polling', True) # type: Union[bool, AsyncPollingMethod] @@ -209,7 +207,6 @@ async def update( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultPatchParameters') body_content_kwargs['content'] = body_content @@ -222,7 +219,6 @@ async def update( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -273,7 +269,6 @@ async def delete( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -326,7 +321,6 @@ async def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -391,7 +385,6 @@ async def update_access_policy( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultAccessPolicyParameters') body_content_kwargs['content'] = body_content @@ -404,7 +397,6 @@ async def update_access_policy( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('VaultAccessPolicyParameters', pipeline_response) @@ -441,6 +433,10 @@ def list_by_resource_group( api_version = "2019-09-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_resource_group.metadata['url'] # type: ignore @@ -455,15 +451,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -510,6 +502,10 @@ def list_by_subscription( api_version = "2019-09-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_subscription.metadata['url'] # type: ignore @@ -523,15 +519,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -575,6 +567,10 @@ def list_deleted( api_version = "2019-09-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_deleted.metadata['url'] # type: ignore @@ -586,15 +582,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -660,7 +652,6 @@ async def get_deleted( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -704,7 +695,6 @@ async def _purge_deleted_initial( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.post(url, query_parameters, header_parameters) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -723,7 +713,7 @@ async def begin_purge_deleted( vault_name: str, location: str, **kwargs - ) -> None: + ) -> AsyncLROPoller[None]: """Permanently deletes the specified vault. aka Purges the deleted Azure key vault. :param vault_name: The name of the soft-deleted vault. @@ -736,8 +726,8 @@ async def begin_purge_deleted( polling object for personal polling strategy :paramtype polling: bool or ~azure.core.polling.AsyncPollingMethod :keyword int polling_interval: Default waiting time between two polls for LRO operations if no Retry-After header is present. - :return: None, or the result of cls(response) - :rtype: None + :return: An instance of AsyncLROPoller that returns either None or the result of cls(response) + :rtype: ~azure.core.polling.AsyncLROPoller[None] :raises ~azure.core.exceptions.HttpResponseError: """ polling = kwargs.pop('polling', True) # type: Union[bool, AsyncPollingMethod] @@ -794,9 +784,13 @@ def list( error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) filter = "resourceType eq 'Microsoft.KeyVault/vaults'" - api_version = "2019-09-01" + api_version = "2015-11-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -811,15 +805,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request async def extract_data(pipeline_response): @@ -882,7 +872,6 @@ async def check_name_availability( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(vault_name, 'VaultCheckNameAvailabilityParameters') body_content_kwargs['content'] = body_content diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_operations.py index 7f961d399970..78b6b93255ed 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_operations.py @@ -63,6 +63,10 @@ def list( api_version = "2019-09-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -70,15 +74,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_private_endpoint_connections_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_private_endpoint_connections_operations.py index f4a731639511..843ee7f45cd1 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_private_endpoint_connections_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_private_endpoint_connections_operations.py @@ -91,7 +91,6 @@ def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -158,7 +157,6 @@ def put( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(properties, 'PrivateEndpointConnection') body_content_kwargs['content'] = body_content @@ -189,8 +187,8 @@ def _delete_initial( private_endpoint_connection_name, # type: str **kwargs # type: Any ): - # type: (...) -> "models.PrivateEndpointConnection" - cls = kwargs.pop('cls', None) # type: ClsType["models.PrivateEndpointConnection"] + # type: (...) -> Optional["models.PrivateEndpointConnection"] + cls = kwargs.pop('cls', None) # type: ClsType[Optional["models.PrivateEndpointConnection"]] error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) api_version = "2019-09-01" @@ -213,7 +211,6 @@ def _delete_initial( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -244,7 +241,7 @@ def begin_delete( private_endpoint_connection_name, # type: str **kwargs # type: Any ): - # type: (...) -> LROPoller + # type: (...) -> LROPoller["models.PrivateEndpointConnection"] """Deletes the specified private endpoint connection associated with the key vault. :param resource_group_name: Name of the resource group that contains the key vault. diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_private_link_resources_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_private_link_resources_operations.py index f7874435bd23..db08e491b020 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_private_link_resources_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_private_link_resources_operations.py @@ -84,7 +84,6 @@ def list_by_vault( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response diff --git a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_vaults_operations.py b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_vaults_operations.py index f8d4ef58edbf..b71de4d0827f 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_vaults_operations.py +++ b/sdk/keyvault/azure-mgmt-keyvault/azure/mgmt/keyvault/v2019_09_01/operations/_vaults_operations.py @@ -79,7 +79,6 @@ def _create_or_update_initial( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultCreateOrUpdateParameters') body_content_kwargs['content'] = body_content @@ -92,7 +91,6 @@ def _create_or_update_initial( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -112,7 +110,7 @@ def begin_create_or_update( parameters, # type: "models.VaultCreateOrUpdateParameters" **kwargs # type: Any ): - # type: (...) -> LROPoller + # type: (...) -> LROPoller["models.Vault"] """Create or update a key vault in the specified subscription. :param resource_group_name: The name of the Resource Group to which the server belongs. @@ -216,7 +214,6 @@ def update( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultPatchParameters') body_content_kwargs['content'] = body_content @@ -229,7 +226,6 @@ def update( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('Vault', pipeline_response) @@ -281,7 +277,6 @@ def delete( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.delete(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -335,7 +330,6 @@ def get( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -401,7 +395,6 @@ def update_access_policy( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(parameters, 'VaultAccessPolicyParameters') body_content_kwargs['content'] = body_content @@ -414,7 +407,6 @@ def update_access_policy( map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, error_format=ARMErrorFormat) - deserialized = None if response.status_code == 200: deserialized = self._deserialize('VaultAccessPolicyParameters', pipeline_response) @@ -452,6 +444,10 @@ def list_by_resource_group( api_version = "2019-09-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_resource_group.metadata['url'] # type: ignore @@ -466,15 +462,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -522,6 +514,10 @@ def list_by_subscription( api_version = "2019-09-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_by_subscription.metadata['url'] # type: ignore @@ -535,15 +531,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -588,6 +580,10 @@ def list_deleted( api_version = "2019-09-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list_deleted.metadata['url'] # type: ignore @@ -599,15 +595,11 @@ def prepare_request(next_link=None): query_parameters = {} # type: Dict[str, Any] query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -674,7 +666,6 @@ def get_deleted( header_parameters = {} # type: Dict[str, Any] header_parameters['Accept'] = 'application/json' - # Construct and send request request = self._client.get(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -719,7 +710,6 @@ def _purge_deleted_initial( # Construct headers header_parameters = {} # type: Dict[str, Any] - # Construct and send request request = self._client.post(url, query_parameters, header_parameters) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -739,7 +729,7 @@ def begin_purge_deleted( location, # type: str **kwargs # type: Any ): - # type: (...) -> LROPoller + # type: (...) -> LROPoller[None] """Permanently deletes the specified vault. aka Purges the deleted Azure key vault. :param vault_name: The name of the soft-deleted vault. @@ -811,9 +801,13 @@ def list( error_map = {404: ResourceNotFoundError, 409: ResourceExistsError} error_map.update(kwargs.pop('error_map', {})) filter = "resourceType eq 'Microsoft.KeyVault/vaults'" - api_version = "2019-09-01" + api_version = "2015-11-01" def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = 'application/json' + if not next_link: # Construct URL url = self.list.metadata['url'] # type: ignore @@ -828,15 +822,11 @@ def prepare_request(next_link=None): query_parameters['$top'] = self._serialize.query("top", top, 'int') query_parameters['api-version'] = self._serialize.query("api_version", api_version, 'str') + request = self._client.get(url, query_parameters, header_parameters) else: url = next_link query_parameters = {} # type: Dict[str, Any] - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = 'application/json' - - # Construct and send request - request = self._client.get(url, query_parameters, header_parameters) + request = self._client.get(url, query_parameters, header_parameters) return request def extract_data(pipeline_response): @@ -900,7 +890,6 @@ def check_name_availability( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = 'application/json' - # Construct and send request body_content_kwargs = {} # type: Dict[str, Any] body_content = self._serialize.body(vault_name, 'VaultCheckNameAvailabilityParameters') body_content_kwargs['content'] = body_content diff --git a/sdk/keyvault/azure-mgmt-keyvault/tests/recordings/test_cli_mgmt_keyvault.test_keyvault.yaml b/sdk/keyvault/azure-mgmt-keyvault/tests/recordings/test_cli_mgmt_keyvault.test_keyvault.yaml index 9030b82ee416..817530671580 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/tests/recordings/test_cli_mgmt_keyvault.test_keyvault.yaml +++ b/sdk/keyvault/azure-mgmt-keyvault/tests/recordings/test_cli_mgmt_keyvault.test_keyvault.yaml @@ -1,8 +1,8 @@ interactions: - request: - body: 'b''{"location": "eastus", "properties": {"tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47", + body: 'b''{"location": "eastus", "properties": {"tenantId": "00000000-0000-0000-0000-000000000000", "sku": {"family": "A", "name": "standard"}, "accessPolicies": [{"tenantId": - "72f988bf-86f1-41af-91ab-2d7cd011db47", "objectId": "00000000-0000-0000-0000-000000000000", + "00000000-0000-0000-0000-000000000000", "objectId": "00000000-0000-0000-0000-000000000000", "permissions": {"keys": ["encrypt", "decrypt", "wrapKey", "unwrapKey", "sign", "verify", "get", "list", "create", "update", "import", "delete", "backup", "restore", "recover", "purge"], "secrets": ["get", "list", "set", "delete", "backup", "restore", @@ -22,21 +22,21 @@ interactions: Content-Type: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: PUT - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz?api-version=2019-09-01 response: body: - string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy","name":"myValtZikfikxy","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","accessPolicies":[{"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myValtZikfikxy.vault.azure.net","provisioningState":"RegisteringDns"}}' + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz","name":"myValtZikfikxz","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myValtZikfikxz.vault.azure.net","provisioningState":"RegisteringDns"}}' headers: cache-control: - no-cache content-length: - - '1113' + - '1144' content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:44:50 GMT + - Tue, 21 Jul 2020 08:20:57 GMT expires: - '-1' pragma: @@ -54,9 +54,9 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-ms-ratelimit-remaining-subscription-writes: - - '1199' + - '1193' x-powered-by: - ASP.NET status: @@ -72,21 +72,21 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz?api-version=2019-09-01 response: body: - string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy","name":"myValtZikfikxy","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","accessPolicies":[{"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxy.vault.azure.net/","provisioningState":"Succeeded"}}' + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz","name":"myValtZikfikxz","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxz.vault.azure.net/","provisioningState":"Succeeded"}}' headers: cache-control: - no-cache content-length: - - '1109' + - '1140' content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:20 GMT + - Tue, 21 Jul 2020 08:21:30 GMT expires: - '-1' pragma: @@ -104,14 +104,14 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-powered-by: - ASP.NET status: code: 200 message: OK - request: - body: 'b''{"properties": {"accessPolicies": [{"tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47", + body: 'b''{"properties": {"accessPolicies": [{"tenantId": "00000000-0000-0000-0000-000000000000", "objectId": "00000000-0000-0000-0000-000000000000", "permissions": {"keys": ["encrypt"], "secrets": ["get"], "certificates": ["get"]}}]}}''' headers: @@ -126,21 +126,21 @@ interactions: Content-Type: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: PUT - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy/accessPolicies/add?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz/accessPolicies/add?api-version=2019-09-01 response: body: - string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy/accessPolicies/","type":"Microsoft.KeyVault/vaults/accessPolicies","properties":{"accessPolicies":[{"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}]}}' + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz/accessPolicies/","type":"Microsoft.KeyVault/vaults/accessPolicies","properties":{"accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}]}}' headers: cache-control: - no-cache content-length: - - '792' + - '823' content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:21 GMT + - Tue, 21 Jul 2020 08:21:32 GMT expires: - '-1' pragma: @@ -158,9 +158,9 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-ms-ratelimit-remaining-subscription-writes: - - '1198' + - '1192' x-powered-by: - ASP.NET status: @@ -176,21 +176,21 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz?api-version=2019-09-01 response: body: - string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy","name":"myValtZikfikxy","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","accessPolicies":[{"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxy.vault.azure.net/","provisioningState":"Succeeded"}}' + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz","name":"myValtZikfikxz","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxz.vault.azure.net/","provisioningState":"Succeeded"}}' headers: cache-control: - no-cache content-length: - - '1109' + - '1140' content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:21 GMT + - Tue, 21 Jul 2020 08:21:33 GMT expires: - '-1' pragma: @@ -208,7 +208,7 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-powered-by: - ASP.NET status: @@ -228,21 +228,21 @@ interactions: Content-Type: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: PATCH - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz?api-version=2019-09-01 response: body: - string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy","name":"myValtZikfikxy","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","accessPolicies":[{"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxy.vault.azure.net/","provisioningState":"Succeeded"}}' + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz","name":"myValtZikfikxz","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxz.vault.azure.net/","provisioningState":"Succeeded"}}' headers: cache-control: - no-cache content-length: - - '1109' + - '1140' content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:22 GMT + - Tue, 21 Jul 2020 08:21:34 GMT expires: - '-1' pragma: @@ -260,9 +260,9 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-ms-ratelimit-remaining-subscription-writes: - - '1197' + - '1191' x-powered-by: - ASP.NET status: @@ -282,7 +282,7 @@ interactions: Content-Type: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: POST uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/checkNameAvailability?api-version=2019-09-01 response: @@ -297,7 +297,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:22 GMT + - Tue, 21 Jul 2020 08:21:34 GMT expires: - '-1' pragma: @@ -315,7 +315,7 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-powered-by: - ASP.NET status: @@ -333,9 +333,9 @@ interactions: Content-Length: - '0' User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: DELETE - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz?api-version=2019-09-01 response: body: string: '' @@ -345,7 +345,7 @@ interactions: content-length: - '0' date: - - Wed, 29 Apr 2020 10:45:25 GMT + - Tue, 21 Jul 2020 08:21:44 GMT expires: - '-1' pragma: @@ -359,9 +359,9 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-ms-ratelimit-remaining-subscription-deletes: - - '14999' + - '14997' x-powered-by: - ASP.NET status: @@ -377,21 +377,21 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxy?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxz?api-version=2019-09-01 response: body: - string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxy","name":"myValtZikfikxy","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxy","location":"eastus","tags":{},"deletionDate":"2020-04-29T10:45:24Z","scheduledPurgeDate":"2020-07-28T10:45:24Z"}}' + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxz","name":"myValtZikfikxz","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxz","location":"eastus","tags":{},"deletionDate":"2020-07-21T08:21:35Z","scheduledPurgeDate":"2020-10-19T08:21:35Z"}}' headers: cache-control: - no-cache content-length: - - '503' + - '534' content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:25 GMT + - Tue, 21 Jul 2020 08:21:44 GMT expires: - '-1' pragma: @@ -409,7 +409,7 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-powered-by: - ASP.NET status: @@ -427,9 +427,9 @@ interactions: Content-Length: - '0' User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: POST - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxy/purge?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxz/purge?api-version=2019-09-01 response: body: string: '' @@ -439,11 +439,11 @@ interactions: content-length: - '0' date: - - Wed, 29 Apr 2020 10:45:26 GMT + - Tue, 21 Jul 2020 08:21:45 GMT expires: - '-1' location: - - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzIzNzUzOTI3NzYyNzYxOHw0MjIwOTIzNUM4Mzk0Q0RDQTJDQTg0QjkzRTNDQjg3Mg?api-version=2019-09-01 + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 pragma: - no-cache server: @@ -455,9 +455,607 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-ms-ratelimit-remaining-subscription-writes: - - '1199' + - '1198' + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:21:50 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:21:56 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:01 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:06 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:12 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:17 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:22 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:28 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:33 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:38 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:44 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:50 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 + x-powered-by: + - ASP.NET + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' + headers: + cache-control: + - no-cache + content-length: + - '64' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 21 Jul 2020 08:22:55 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 + pragma: + - no-cache + server: + - Microsoft-IIS/10.0 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-aspnet-version: + - 4.0.30319 + x-content-type-options: + - nosniff + x-ms-keyvault-service-version: + - 1.1.0.283 x-powered-by: - ASP.NET status: @@ -473,12 +1071,12 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzIzNzUzOTI3NzYyNzYxOHw0MjIwOTIzNUM4Mzk0Q0RDQTJDQTg0QjkzRTNDQjg3Mg?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 response: body: - string: '{"createdDateTime":"2020-04-29 10:45:26Z","status":"NotStarted"}' + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' headers: cache-control: - no-cache @@ -487,11 +1085,11 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:31 GMT + - Tue, 21 Jul 2020 08:23:01 GMT expires: - '-1' location: - - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzIzNzUzOTI3NzYyNzYxOHw0MjIwOTIzNUM4Mzk0Q0RDQTJDQTg0QjkzRTNDQjg3Mg?api-version=2019-09-01 + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 pragma: - no-cache server: @@ -503,7 +1101,7 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-powered-by: - ASP.NET status: @@ -519,12 +1117,12 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzIzNzUzOTI3NzYyNzYxOHw0MjIwOTIzNUM4Mzk0Q0RDQTJDQTg0QjkzRTNDQjg3Mg?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 response: body: - string: '{"createdDateTime":"2020-04-29 10:45:26Z","status":"NotStarted"}' + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' headers: cache-control: - no-cache @@ -533,11 +1131,11 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:36 GMT + - Tue, 21 Jul 2020 08:23:06 GMT expires: - '-1' location: - - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzIzNzUzOTI3NzYyNzYxOHw0MjIwOTIzNUM4Mzk0Q0RDQTJDQTg0QjkzRTNDQjg3Mg?api-version=2019-09-01 + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 pragma: - no-cache server: @@ -549,7 +1147,7 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-powered-by: - ASP.NET status: @@ -565,12 +1163,12 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzIzNzUzOTI3NzYyNzYxOHw0MjIwOTIzNUM4Mzk0Q0RDQTJDQTg0QjkzRTNDQjg3Mg?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 response: body: - string: '{"createdDateTime":"2020-04-29 10:45:26Z","status":"NotStarted"}' + string: '{"createdDateTime":"2020-07-21 08:21:45Z","status":"NotStarted"}' headers: cache-control: - no-cache @@ -579,11 +1177,11 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:41 GMT + - Tue, 21 Jul 2020 08:23:11 GMT expires: - '-1' location: - - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzIzNzUzOTI3NzYyNzYxOHw0MjIwOTIzNUM4Mzk0Q0RDQTJDQTg0QjkzRTNDQjg3Mg?api-version=2019-09-01 + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 pragma: - no-cache server: @@ -595,7 +1193,7 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-powered-by: - ASP.NET status: @@ -611,13 +1209,13 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzIzNzUzOTI3NzYyNzYxOHw0MjIwOTIzNUM4Mzk0Q0RDQTJDQTg0QjkzRTNDQjg3Mg?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2NTA2NzQwODIwNnwxNTc5OTY3NDQ4QUQ0QTFBQTgwQzlERkVEQTBEMkQxMQ?api-version=2019-09-01 response: body: - string: '{"createdDateTime":"2020-04-29 10:45:26Z","lastActionDateTime":"2020-04-29 - 10:45:42Z","status":"Succeeded"}' + string: '{"createdDateTime":"2020-07-21 08:21:45Z","lastActionDateTime":"2020-07-21 + 08:23:14Z","status":"Succeeded"}' headers: cache-control: - no-cache @@ -626,7 +1224,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 29 Apr 2020 10:45:46 GMT + - Tue, 21 Jul 2020 08:23:17 GMT expires: - '-1' pragma: @@ -644,7 +1242,7 @@ interactions: x-content-type-options: - nosniff x-ms-keyvault-service-version: - - 1.1.0.277 + - 1.1.0.283 x-powered-by: - ASP.NET status: diff --git a/sdk/keyvault/azure-mgmt-keyvault/tests/recordings/test_cli_mgmt_keyvault_async.test_keyvault.yaml b/sdk/keyvault/azure-mgmt-keyvault/tests/recordings/test_cli_mgmt_keyvault_async.test_keyvault.yaml index cfc159997b0e..fa1ef5d73bf3 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/tests/recordings/test_cli_mgmt_keyvault_async.test_keyvault.yaml +++ b/sdk/keyvault/azure-mgmt-keyvault/tests/recordings/test_cli_mgmt_keyvault_async.test_keyvault.yaml @@ -18,7 +18,7 @@ interactions: Content-Type: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: PUT uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 response: @@ -28,7 +28,7 @@ interactions: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:18 GMT + date: Tue, 21 Jul 2020 08:13:18 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -37,18 +37,18 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 - x-ms-ratelimit-remaining-subscription-writes: '1198' + x-ms-keyvault-service-version: 1.1.0.283 + x-ms-ratelimit-remaining-subscription-writes: '1197' x-powered-by: ASP.NET status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/vra53ahg2dkl4ogaogg2spj5iddbgeewhd67uhzbued73tzlvcw3p3x5fb47f3ippwlbykcwo3u/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 - request: body: null headers: User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 response: @@ -58,7 +58,7 @@ interactions: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:51 GMT + date: Tue, 21 Jul 2020 08:13:48 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -67,12 +67,12 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 + x-ms-keyvault-service-version: 1.1.0.283 x-powered-by: ASP.NET status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/vra53ahg2dkl4ogaogg2spj5iddbgeewhd67uhzbued73tzlvcw3p3x5fb47f3ippwlbykcwo3u/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 - request: body: 'b''{"properties": {"accessPolicies": [{"tenantId": "00000000-0000-0000-0000-000000000000", "objectId": "00000000-0000-0000-0000-000000000000", "permissions": {"keys": @@ -85,7 +85,7 @@ interactions: Content-Type: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: PUT uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz/accessPolicies/add?api-version=2019-09-01 response: @@ -95,7 +95,7 @@ interactions: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:51 GMT + date: Tue, 21 Jul 2020 08:13:49 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -104,20 +104,20 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 - x-ms-ratelimit-remaining-subscription-writes: '1198' + x-ms-keyvault-service-version: 1.1.0.283 + x-ms-ratelimit-remaining-subscription-writes: '1196' x-powered-by: ASP.NET status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz/accessPolicies/add?api-version=2019-09-01 + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/vra53ahg2dkl4ogaogg2spj5iddbgeewhd67uhzbued73tzlvcw3p3x5fb47f3ippwlbykcwo3u/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz/accessPolicies/add?api-version=2019-09-01 - request: body: null headers: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 response: @@ -127,7 +127,7 @@ interactions: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:52 GMT + date: Tue, 21 Jul 2020 08:13:49 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -136,19 +136,19 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 + x-ms-keyvault-service-version: 1.1.0.283 x-powered-by: ASP.NET status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/vra53ahg2dkl4ogaogg2spj5iddbgeewhd67uhzbued73tzlvcw3p3x5fb47f3ippwlbykcwo3u/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 - request: body: null headers: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01 response: @@ -158,7 +158,7 @@ interactions: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:52 GMT + date: Tue, 21 Jul 2020 08:13:50 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -167,19 +167,19 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 + x-ms-keyvault-service-version: 1.1.0.283 x-powered-by: ASP.NET status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01 + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/vra53ahg2dkl4ogaogg2spj5iddbgeewhd67uhzbued73tzlvcw3p3x5fb47f3ippwlbykcwo3u/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01 - request: body: null headers: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=bXlWYWx0WmlrZmlreHl6eg== response: @@ -189,7 +189,7 @@ interactions: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:53 GMT + date: Tue, 21 Jul 2020 08:13:50 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -198,36 +198,36 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 + x-ms-keyvault-service-version: 1.1.0.283 x-powered-by: ASP.NET status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=bXlWYWx0WmlrZmlreHl6eg== + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/vra53ahg2dkl4ogaogg2spj5iddbgeewhd67uhzbued73tzlvcw3p3x5fb47f3ippwlbykcwo3u/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=bXlWYWx0WmlrZmlreHl6eg== - request: body: null headers: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/deletedVaults?api-version=2019-09-01 response: body: - string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/keyvaultxyzxxxxx","name":"keyvaultxyzxxxxx","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testgroupx/providers/Microsoft.KeyVault/vaults/keyvaultxyzxxxxx","location":"eastus","tags":{},"deletionDate":"2020-05-12T09:10:06Z","scheduledPurgeDate":"2020-08-10T09:10:06Z"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/keyvaultxyzxxxx","name":"keyvaultxyzxxxx","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testgroupx/providers/Microsoft.KeyVault/vaults/keyvaultxyzxxxx","location":"eastus","tags":{},"deletionDate":"2020-05-12T08:22:10Z","scheduledPurgeDate":"2020-08-10T08:22:10Z"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/westus/deletedVaults/pykvf9870e4e","name":"pykvf9870e4e","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test_vaults_test_vaults_operationsf9870e4e/providers/Microsoft.KeyVault/vaults/pykvf9870e4e","location":"westus","tags":{},"deletionDate":"2020-03-18T09:43:53Z","scheduledPurgeDate":"2020-06-16T09:43:53Z"}}],"nextLink":"https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/deletedVaults?api-version=2019-09-01&%24skiptoken=3ZDtaoMwGIXvJYz9mlWjXbVQhmAK22okaWJh%2f2yMrabVYuxXSu99YZcxOHA4cDgv7%2fMAnbyNq6ZTGswfACVrxtdgDvbjeNJz1z2WXbmTR9mNk9KcBzkR%2fdHV560WQ3Mam77TbgzreFpFtROI95kT%2bjB0Yl%2fMnEjU3kxU2xqGvnsa%2bktTyUG7WSOGXvf1OPmW96I8H0a3kgc5yuov6I%2fy1DgX27TjC%2bj5seNZ%2ba8vWtmLvZLdgqtiQ4svRjldMlTwNY%2fzFT%2fwOv30M7a7ZSa55yyBOeMGGwExwxHx%2bJW0Ksh5BjOW3HCaGGKUh5m6YkOXxHBIPJzmHIE3sEH%2fgYP9PcAtgrjlofU7Nj9RZsjVsgiwlxmaUoRTZGirLIvE2F5A0z2iKZ8SRcDz%2bQs%3d"}' + string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/test-changlong","name":"test-changlong","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-changlong/providers/Microsoft.KeyVault/vaults/test-changlong","location":"eastus","tags":{},"deletionDate":"2020-06-12T07:38:10Z","scheduledPurgeDate":"2020-09-10T07:38:10Z"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/keyvaultxyzxxxxx","name":"keyvaultxyzxxxxx","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testgroupx/providers/Microsoft.KeyVault/vaults/keyvaultxyzxxxxx","location":"eastus","tags":{},"deletionDate":"2020-05-12T09:10:06Z","scheduledPurgeDate":"2020-08-10T09:10:06Z"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/keyvaultxyzxxxx","name":"keyvaultxyzxxxx","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testgroupx/providers/Microsoft.KeyVault/vaults/keyvaultxyzxxxx","location":"eastus","tags":{},"deletionDate":"2020-05-12T08:22:10Z","scheduledPurgeDate":"2020-08-10T08:22:10Z"}}],"nextLink":"https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/deletedVaults?api-version=2019-09-01&%24skiptoken=HY1ba4MwAEb%2fSxh702jq5gXKELSwrUbUxD3bGDsXb5jY2pT%2b98rgezlwON8dDHxVx3YQEgR3EIcFoQUIwK9Skwwg7KuhOvOeD8qs9DJzk409lMtJsrmdVDsOEvqo8d9qrzF27N01HBs5hm8z1%2fBYY7msPjXIseE0j5e25rOEScvmUY6NMr%2f5rayWTsGad1zx%2bh%2fkRzW1xmUzt%2fgeWbZvWNvs1xcptsdR8GFPRfmTl18kp%2fmBxCUtqJ8eaUeb6NNOyHlNdHhLSYhSQjXWDGGCvcyi1%2bxP7FKaoISEK45CnWlhYSKuWOeHTFOUWThKaQwejyc%3d"}' headers: cache-control: no-cache content-encoding: gzip - content-length: '1045' + content-length: '927' content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:55 GMT + date: Tue, 21 Jul 2020 08:13:52 GMT expires: '-1' pragma: no-cache strict-transport-security: max-age=31536000; includeSubDomains vary: Accept-Encoding x-content-type-options: nosniff - x-ms-original-request-ids: 34023f30-fd9c-4561-ab54-ea8250813f02 + x-ms-original-request-ids: 8e68c799-efe4-4a5d-a169-3390eb3f2af9 status: code: 200 message: OK @@ -238,9 +238,9 @@ interactions: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/deletedVaults?api-version=2019-09-01&$skiptoken=3ZDtaoMwGIXvJYz9mlWjXbVQhmAK22okaWJh/2yMrabVYuxXSu99YZcxOHA4cDgv7/MAnbyNq6ZTGswfACVrxtdgDvbjeNJz1z2WXbmTR9mNk9KcBzkR/dHV560WQ3Mam77TbgzreFpFtROI95kT%2BjB0Yl/MnEjU3kxU2xqGvnsa%2BktTyUG7WSOGXvf1OPmW96I8H0a3kgc5yuov6I/y1DgX27TjC%2Bj5seNZ%2Ba8vWtmLvZLdgqtiQ4svRjldMlTwNY/zFT/wOv30M7a7ZSa55yyBOeMGGwExwxHx%2BJW0Ksh5BjOW3HCaGGKUh5m6YkOXxHBIPJzmHIE3sEH/gYP9PcAtgrjlofU7Nj9RZsjVsgiwlxmaUoRTZGirLIvE2F5A0z2iKZ8SRcDz%2BQs%3D + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/deletedVaults?api-version=2019-09-01&$skiptoken=HY1ba4MwAEb/Sxh702jq5gXKELSwrUbUxD3bGDsXb5jY2pT%2B98rgezlwON8dDHxVx3YQEgR3EIcFoQUIwK9Skwwg7KuhOvOeD8qs9DJzk409lMtJsrmdVDsOEvqo8d9qrzF27N01HBs5hm8z1/BYY7msPjXIseE0j5e25rOEScvmUY6NMr/5rayWTsGad1zx%2Bh/kRzW1xmUzt/geWbZvWNvs1xcptsdR8GFPRfmTl18kp/mBxCUtqJ8eaUeb6NNOyHlNdHhLSYhSQjXWDGGCvcyi1%2BxP7FKaoISEK45CnWlhYSKuWOeHTFOUWThKaQwejyc%3D response: body: string: '{"value":[]}' @@ -249,41 +249,41 @@ interactions: content-encoding: gzip content-length: '133' content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:55 GMT + date: Tue, 21 Jul 2020 08:13:53 GMT expires: '-1' pragma: no-cache strict-transport-security: max-age=31536000; includeSubDomains vary: Accept-Encoding x-content-type-options: nosniff - x-ms-original-request-ids: 970fc52b-6668-4c03-968e-87d60145429a + x-ms-original-request-ids: 6b5e9021-1b1a-4cb4-9e57-f1c93c6b0ff3 status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/deletedVaults?api-version=2019-09-01&$skiptoken=3ZDtaoMwGIXvJYz9mlWjXbVQhmAK22okaWJh/2yMrabVYuxXSu99YZcxOHA4cDgv7/MAnbyNq6ZTGswfACVrxtdgDvbjeNJz1z2WXbmTR9mNk9KcBzkR/dHV560WQ3Mam77TbgzreFpFtROI95kT%2BjB0Yl/MnEjU3kxU2xqGvnsa%2BktTyUG7WSOGXvf1OPmW96I8H0a3kgc5yuov6I/y1DgX27TjC%2Bj5seNZ%2Ba8vWtmLvZLdgqtiQ4svRjldMlTwNY/zFT/wOv30M7a7ZSa55yyBOeMGGwExwxHx%2BJW0Ksh5BjOW3HCaGGKUh5m6YkOXxHBIPJzmHIE3sEH/gYP9PcAtgrjlofU7Nj9RZsjVsgiwlxmaUoRTZGirLIvE2F5A0z2iKZ8SRcDz%2BQs%3D + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/deletedVaults?api-version=2019-09-01&$skiptoken=HY1ba4MwAEb/Sxh702jq5gXKELSwrUbUxD3bGDsXb5jY2pT%2B98rgezlwON8dDHxVx3YQEgR3EIcFoQUIwK9Skwwg7KuhOvOeD8qs9DJzk409lMtJsrmdVDsOEvqo8d9qrzF27N01HBs5hm8z1/BYY7msPjXIseE0j5e25rOEScvmUY6NMr/5rayWTsGad1zx%2Bh/kRzW1xmUzt/geWbZvWNvs1xcptsdR8GFPRfmTl18kp/mBxCUtqJ8eaUeb6NNOyHlNdHhLSYhSQjXWDGGCvcyi1%2BxP7FKaoISEK45CnWlhYSKuWOeHTFOUWThKaQwejyc%3D - request: body: null headers: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01 response: body: - string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-changlong/providers/Microsoft.KeyVault/vaults/test-changlong","name":"test-changlong","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"6bedd520-9535-468f-9ab3-79d17bea1b92","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"enableSoftDelete":true,"softDeleteRetentionInDays":90,"enableRbacAuthorization":false,"vaultUri":"https://test-changlong.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz","name":"myValtZikfikxyzz","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxyzz.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/git2gridtesting/providers/Microsoft.KeyVault/vaults/git2gridkv","name":"git2gridkv","type":"Microsoft.KeyVault/vaults","location":"centralus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"7b5d64cb-f02f-4b19-ab5d-60dca4916c54","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"vaultUri":"https://git2gridkv.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azure-sdk-for-node/providers/Microsoft.KeyVault/vaults/node-sdk-kv","name":"node-sdk-kv","type":"Microsoft.KeyVault/vaults","location":"westus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"52bcebf6-9dc1-4a9a-8b3b-6962bb22a6aa","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"vaultUri":"https://node-sdk-kv.vault.azure.net/","provisioningState":"Succeeded"}}],"nextLink":"https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?%24top=1&api-version=2019-09-01&%24skiptoken=1VHRbqMwEPwXVPWpBAwhCZHQqb2jtL1Cr0Aw%2bM3YphBsQNjJEar%2b%2b9H7ilbaWY1Gqx3N7rvWsUk9N10rtf275t8m6SHR9lqt1CD3hiFwh9%2bYYJ1a4fk0shXphSFPpSRjM6im76ThWpXr0F2l22Sz1dfAWusuIFt9RypzS2hZWWtgDGN%2fbigbpRE2ZOxlX6nVb3bJ8Ikr4%2fzZ5Y8r1Q8euMZDo5%2bXyWW5Z5nA1c2lwPWVbBfHvmWdR4NspvfusQx4VUKqFj6inFtFnsmF18TmpwK4JsojM7cUZzmqKZzMaCY2Sv0pstCuzDksFg0KPqIF7IFv2JvnaTfaTz9K49vnr38HZHEzFPSCYfw%2fK4ZOVwV0oL%2beOiJ4i%2b3iMw%2f0v8NTEzaeG8LusGT0JhXuCSVTGwO0QX7hhJwXWRe1ie8I5FPIRBy8pE8I3qMZ%2bfULEo%2fzq5iO5aH4W2TEoTC8wDT7EweRDXmclAF6fD1mdQgGlYK4C03wkKV3%2bJCarvbx8Q8%3d"}' + string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz","name":"myValtZikfikxyzz","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxyzz.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/git2gridtesting/providers/Microsoft.KeyVault/vaults/git2gridkv","name":"git2gridkv","type":"Microsoft.KeyVault/vaults","location":"centralus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"7b5d64cb-f02f-4b19-ab5d-60dca4916c54","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"vaultUri":"https://git2gridkv.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azure-sdk-for-node/providers/Microsoft.KeyVault/vaults/node-sdk-kv","name":"node-sdk-kv","type":"Microsoft.KeyVault/vaults","location":"westus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"52bcebf6-9dc1-4a9a-8b3b-6962bb22a6aa","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"vaultUri":"https://node-sdk-kv.vault.azure.net/","provisioningState":"Succeeded"}}],"nextLink":"https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?%24top=1&api-version=2019-09-01&%24skiptoken=1VLNbqMwGHwXVPVUAnZIEyJFq7LrJLtNiGocHLgZY1pifrzYkJSq777pYR%2bi0qc5jEYzmtH3YTXianZlI7W1%2fLDQU0SOkbW03oxReuk4NWvYq6hFYyZs7Dsx4W3t6D7TvCuVKdtGOz4s%2fFm%2bKOwpf5zbHoCe7QM%2btxe8cOc8zwroAUd17VDmotPOvuRdq9vCTJ7Fe8z6yjjDF%2bofd6ZVK3DPVGkPN%2bXNfAVd4Nvu7cD9nZa3xFaKZhWJbii5CJgW%2bQOp%2fT6NrjKTqiUVPrDNeptMK4aneCSSz7KqOh3ojAmpHhM3H%2fZ0fTrWJs0o1rR6kxlQiJJQxvAVUjqj2VqhZKpktA3GdAMOe9cdX06qwuvUUKrwHqi%2fpAnOEfo9JjJ%2fDil6J%2bewFNK7ppJfwzg1uAklboJLQv4wvkEj%2bxVXWb3wrQfrJwoJftp9z5HZvr5cCAVSfI14DhhF3iWJOcjqdJtuA4mR6hMININopMRd3QpT9B1eKjkpwOuj4RB3O5oOvAR9BnFVbGZDuvnPG2h9fv4D"}' headers: cache-control: no-cache content-encoding: gzip - content-length: '1823' + content-length: '1727' content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:56 GMT + date: Tue, 21 Jul 2020 08:13:53 GMT expires: '-1' pragma: no-cache strict-transport-security: max-age=31536000; includeSubDomains vary: Accept-Encoding x-content-type-options: nosniff - x-ms-original-request-ids: ded3b3c4-1c3c-490d-b98c-0f6cbbdf3f81 + x-ms-original-request-ids: 30ca9ed8-3dd8-4ad3-bf57-a629df4f8280 status: code: 200 message: OK @@ -294,9 +294,9 @@ interactions: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=1VHRbqMwEPwXVPWpBAwhCZHQqb2jtL1Cr0Aw%2BM3YphBsQNjJEar%2B%2B9H7ilbaWY1Gqx3N7rvWsUk9N10rtf275t8m6SHR9lqt1CD3hiFwh9%2BYYJ1a4fk0shXphSFPpSRjM6im76ThWpXr0F2l22Sz1dfAWusuIFt9RypzS2hZWWtgDGN/bigbpRE2ZOxlX6nVb3bJ8Ikr4/zZ5Y8r1Q8euMZDo5%2BXyWW5Z5nA1c2lwPWVbBfHvmWdR4NspvfusQx4VUKqFj6inFtFnsmF18TmpwK4JsojM7cUZzmqKZzMaCY2Sv0pstCuzDksFg0KPqIF7IFv2JvnaTfaTz9K49vnr38HZHEzFPSCYfw/K4ZOVwV0oL%2BeOiJ4i%2B3iMw/0v8NTEzaeG8LusGT0JhXuCSVTGwO0QX7hhJwXWRe1ie8I5FPIRBy8pE8I3qMZ%2BfULEo/zq5iO5aH4W2TEoTC8wDT7EweRDXmclAF6fD1mdQgGlYK4C03wkKV3%2BJCarvbx8Q8%3D + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=1VLNbqMwGHwXVPVUAnZIEyJFq7LrJLtNiGocHLgZY1pifrzYkJSq777pYR%2Bi0qc5jEYzmtH3YTXianZlI7W1/LDQU0SOkbW03oxReuk4NWvYq6hFYyZs7Dsx4W3t6D7TvCuVKdtGOz4s/Fm%2BKOwpf5zbHoCe7QM%2Btxe8cOc8zwroAUd17VDmotPOvuRdq9vCTJ7Fe8z6yjjDF%2Bofd6ZVK3DPVGkPN%2BXNfAVd4Nvu7cD9nZa3xFaKZhWJbii5CJgW%2BQOp/T6NrjKTqiUVPrDNeptMK4aneCSSz7KqOh3ojAmpHhM3H/Z0fTrWJs0o1rR6kxlQiJJQxvAVUjqj2VqhZKpktA3GdAMOe9cdX06qwuvUUKrwHqi/pAnOEfo9JjJ/Dil6J%2BewFNK7ppJfwzg1uAklboJLQv4wvkEj%2BxVXWb3wrQfrJwoJftp9z5HZvr5cCAVSfI14DhhF3iWJOcjqdJtuA4mR6hMININopMRd3QpT9B1eKjkpwOuj4RB3O5oOvAR9BnFVbGZDuvnPG2h9fv4D response: body: string: '{"value":[]}' @@ -305,41 +305,41 @@ interactions: content-encoding: gzip content-length: '133' content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:56 GMT + date: Tue, 21 Jul 2020 08:13:54 GMT expires: '-1' pragma: no-cache strict-transport-security: max-age=31536000; includeSubDomains vary: Accept-Encoding x-content-type-options: nosniff - x-ms-original-request-ids: d23b735f-2642-4dad-9524-a2b042b5332a + x-ms-original-request-ids: 1ec36214-2005-4d58-94a1-3acd9ad7981d status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=1VHRbqMwEPwXVPWpBAwhCZHQqb2jtL1Cr0Aw%2BM3YphBsQNjJEar%2B%2B9H7ilbaWY1Gqx3N7rvWsUk9N10rtf275t8m6SHR9lqt1CD3hiFwh9%2BYYJ1a4fk0shXphSFPpSRjM6im76ThWpXr0F2l22Sz1dfAWusuIFt9RypzS2hZWWtgDGN/bigbpRE2ZOxlX6nVb3bJ8Ikr4/zZ5Y8r1Q8euMZDo5%2BXyWW5Z5nA1c2lwPWVbBfHvmWdR4NspvfusQx4VUKqFj6inFtFnsmF18TmpwK4JsojM7cUZzmqKZzMaCY2Sv0pstCuzDksFg0KPqIF7IFv2JvnaTfaTz9K49vnr38HZHEzFPSCYfw/K4ZOVwV0oL%2BeOiJ4i%2B3iMw/0v8NTEzaeG8LusGT0JhXuCSVTGwO0QX7hhJwXWRe1ie8I5FPIRBy8pE8I3qMZ%2BfULEo/zq5iO5aH4W2TEoTC8wDT7EweRDXmclAF6fD1mdQgGlYK4C03wkKV3%2BJCarvbx8Q8%3D + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=1VLNbqMwGHwXVPVUAnZIEyJFq7LrJLtNiGocHLgZY1pifrzYkJSq777pYR%2Bi0qc5jEYzmtH3YTXianZlI7W1/LDQU0SOkbW03oxReuk4NWvYq6hFYyZs7Dsx4W3t6D7TvCuVKdtGOz4s/Fm%2BKOwpf5zbHoCe7QM%2Btxe8cOc8zwroAUd17VDmotPOvuRdq9vCTJ7Fe8z6yjjDF%2Bofd6ZVK3DPVGkPN%2BXNfAVd4Nvu7cD9nZa3xFaKZhWJbii5CJgW%2BQOp/T6NrjKTqiUVPrDNeptMK4aneCSSz7KqOh3ojAmpHhM3H/Z0fTrWJs0o1rR6kxlQiJJQxvAVUjqj2VqhZKpktA3GdAMOe9cdX06qwuvUUKrwHqi/pAnOEfo9JjJ/Dil6J%2BewFNK7ppJfwzg1uAklboJLQv4wvkEj%2BxVXWb3wrQfrJwoJftp9z5HZvr5cCAVSfI14DhhF3iWJOcjqdJtuA4mR6hMININopMRd3QpT9B1eKjkpwOuj4RB3O5oOvAR9BnFVbGZDuvnPG2h9fv4D - request: body: null headers: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01 response: body: - string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-changlong/providers/Microsoft.KeyVault/vaults/test-changlong","name":"test-changlong","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"6bedd520-9535-468f-9ab3-79d17bea1b92","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"enableSoftDelete":true,"softDeleteRetentionInDays":90,"enableRbacAuthorization":false,"vaultUri":"https://test-changlong.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz","name":"myValtZikfikxyzz","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxyzz.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/git2gridtesting/providers/Microsoft.KeyVault/vaults/git2gridkv","name":"git2gridkv","type":"Microsoft.KeyVault/vaults","location":"centralus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"7b5d64cb-f02f-4b19-ab5d-60dca4916c54","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"vaultUri":"https://git2gridkv.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azure-sdk-for-node/providers/Microsoft.KeyVault/vaults/node-sdk-kv","name":"node-sdk-kv","type":"Microsoft.KeyVault/vaults","location":"westus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"52bcebf6-9dc1-4a9a-8b3b-6962bb22a6aa","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"vaultUri":"https://node-sdk-kv.vault.azure.net/","provisioningState":"Succeeded"}}],"nextLink":"https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?%24top=1&api-version=2019-09-01&%24skiptoken=1VJhb6MwDP0vqNqnUZLQrqUSOpU7WqRbqdbSBvIthNAyEkAktF2n%2fffLdNN%2bw51kW8%2bW9Sz7%2bd1q%2bE0%2fV02trMW7FS73yWFvLayz1p1aOI6kDT1xyRs9pveh52PWSkcNuWJ91emqbZTjodKbFvPSdtnTzJ5ANLE9yGb2nJVgxoq8RBPodH17qQreK2dTsb5VbanHv%2fnbkQ5CO5fPqH6MdNv58IF2lX0xnYbcRwB6NjAGH0aqNhPbmjd%2bsT7ei5X3mq9FmeNCG9yTVKAsPSqDz8wVQwY9QNIYpEgLnpJzgW8gvjOXJOEtRmSepwJnpoal6IlxHoknfvJ969H6GcbJbvn8799hz%2ftLxXhAFS8eE%2bkNZH%2bjG3m9JhjWHK%2fSw2tAcTi5ZkcGc0kiEgX1LuyGDEFFUXjHCfhcGIf%2fkep%2fVY7i8usLvvPcDQSTK0CxNzCUTbe%2f2JUkO1FGwZS6RG6Tk7tZHwB5MSp%2ffPwB"}' + string: '{"value":[{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz","name":"myValtZikfikxyzz","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"00000000-0000-0000-0000-000000000000","permissions":{"keys":["encrypt","decrypt","wrapKey","unwrapKey","sign","verify","get","list","create","update","import","delete","backup","restore","recover","purge"],"secrets":["get","list","set","delete","backup","restore","recover","purge"],"certificates":["get","list","delete","create","import","update","managecontacts","getissuers","listissuers","setissuers","deleteissuers","manageissuers","recover","purge"]}}],"enabledForDeployment":true,"enabledForDiskEncryption":true,"enabledForTemplateDeployment":true,"enableSoftDelete":true,"vaultUri":"https://myvaltzikfikxyzz.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/git2gridtesting/providers/Microsoft.KeyVault/vaults/git2gridkv","name":"git2gridkv","type":"Microsoft.KeyVault/vaults","location":"centralus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"7b5d64cb-f02f-4b19-ab5d-60dca4916c54","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"vaultUri":"https://git2gridkv.vault.azure.net/","provisioningState":"Succeeded"}},{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azure-sdk-for-node/providers/Microsoft.KeyVault/vaults/node-sdk-kv","name":"node-sdk-kv","type":"Microsoft.KeyVault/vaults","location":"westus","tags":{},"properties":{"sku":{"family":"A","name":"Standard"},"tenantId":"00000000-0000-0000-0000-000000000000","accessPolicies":[{"tenantId":"00000000-0000-0000-0000-000000000000","objectId":"52bcebf6-9dc1-4a9a-8b3b-6962bb22a6aa","permissions":{"keys":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore"],"secrets":["Get","List","Set","Delete","Recover","Backup","Restore"],"certificates":["Get","List","Update","Create","Import","Delete","Recover","Backup","Restore","ManageContacts","ManageIssuers","GetIssuers","ListIssuers","SetIssuers","DeleteIssuers"]}}],"enabledForDeployment":false,"enabledForDiskEncryption":false,"enabledForTemplateDeployment":false,"vaultUri":"https://node-sdk-kv.vault.azure.net/","provisioningState":"Succeeded"}}],"nextLink":"https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?%24top=1&api-version=2019-09-01&%24skiptoken=1ZLNbptAFIXfBUVZBeMZ7DhYsiq7xrhuQIqNmTC7YWYoGM%2bPGLCBKO9esuqmD9BKV3dzjs7Vd3Q%2fLMm75rWUlbGWH5a%2fPsXnk7W0iqbRZuk4gkjyiwsumwkZ2ppPqBKOaTND61I3pZLG8WDuzdlLbrv0eWHPAJzZHqAL%2b4Xm0wVlWQ5nwNG1upWM18YJS1oro%2fJm8pP3CWmvjXP72ubbQ6P0CjwSXdq30TmGr%2bAUePZ0HPD4YKrxoqq4XDF5KKI4KkhAexw0Jgo8mSJP4uEw0EABgo5VKtgVvzOFt6nLUPGcyuSKt3Rge22YiNzQXQ98m4j08ubiS6TpfuNmwWFOYORmQwTyAMwTsTNspzWBWBO3mHOpVtaT9d2P4uP69d%2fv6cTrW0n5hhjOnmLhtfjUkVDc7zECFUe79%2fNlQ5A%2fu6cJBZnAe7zfVEdftykEhkB%2fQPH0Cxj5%2f8NX%2fI0Wo%2f26G2kSFoT9WR7CBGiYwqpj6Ed%2fFp04DglEFfuju2%2b99fn5Gw%3d%3d"}' headers: cache-control: no-cache content-encoding: gzip - content-length: '1793' + content-length: '1702' content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:56 GMT + date: Tue, 21 Jul 2020 08:13:54 GMT expires: '-1' pragma: no-cache strict-transport-security: max-age=31536000; includeSubDomains vary: Accept-Encoding x-content-type-options: nosniff - x-ms-original-request-ids: b9c365e5-e09a-4cda-8f62-9912b4a90b9c + x-ms-original-request-ids: 811de193-caae-44a8-bff0-ead6e1beae85 status: code: 200 message: OK @@ -350,9 +350,9 @@ interactions: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=1VJhb6MwDP0vqNqnUZLQrqUSOpU7WqRbqdbSBvIthNAyEkAktF2n/ffLdNN%2Bw51kW8%2BW9Sz7%2Bd1q%2BE0/V02trMW7FS73yWFvLayz1p1aOI6kDT1xyRs9pveh52PWSkcNuWJ91emqbZTjodKbFvPSdtnTzJ5ANLE9yGb2nJVgxoq8RBPodH17qQreK2dTsb5VbanHv/nbkQ5CO5fPqH6MdNv58IF2lX0xnYbcRwB6NjAGH0aqNhPbmjd%2BsT7ei5X3mq9FmeNCG9yTVKAsPSqDz8wVQwY9QNIYpEgLnpJzgW8gvjOXJOEtRmSepwJnpoal6IlxHoknfvJ969H6GcbJbvn8799hz/tLxXhAFS8eE%2BkNZH%2BjG3m9JhjWHK/Sw2tAcTi5ZkcGc0kiEgX1LuyGDEFFUXjHCfhcGIf/kep/VY7i8usLvvPcDQSTK0CxNzCUTbe/2JUkO1FGwZS6RG6Tk7tZHwB5MSp/fPwB + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=1ZLNbptAFIXfBUVZBeMZ7DhYsiq7xrhuQIqNmTC7YWYoGM%2BPGLCBKO9esuqmD9BKV3dzjs7Vd3Q/LMm75rWUlbGWH5a/PsXnk7W0iqbRZuk4gkjyiwsumwkZ2ppPqBKOaTND61I3pZLG8WDuzdlLbrv0eWHPAJzZHqAL%2B4Xm0wVlWQ5nwNG1upWM18YJS1oro/Jm8pP3CWmvjXP72ubbQ6P0CjwSXdq30TmGr%2BAUePZ0HPD4YKrxoqq4XDF5KKI4KkhAexw0Jgo8mSJP4uEw0EABgo5VKtgVvzOFt6nLUPGcyuSKt3Rge22YiNzQXQ98m4j08ubiS6TpfuNmwWFOYORmQwTyAMwTsTNspzWBWBO3mHOpVtaT9d2P4uP69d/v6cTrW0n5hhjOnmLhtfjUkVDc7zECFUe79/NlQ5A/u6cJBZnAe7zfVEdftykEhkB/QPH0Cxj5/8NX/I0Wo/26G2kSFoT9WR7CBGiYwqpj6Ed/Fp04DglEFfuju2%2B99fn5Gw%3D%3D response: body: string: '{"value":[]}' @@ -361,24 +361,24 @@ interactions: content-encoding: gzip content-length: '133' content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:57 GMT + date: Tue, 21 Jul 2020 08:13:55 GMT expires: '-1' pragma: no-cache strict-transport-security: max-age=31536000; includeSubDomains vary: Accept-Encoding x-content-type-options: nosniff - x-ms-original-request-ids: 1be66f9b-a058-41ce-a574-8406643c4ea9 + x-ms-original-request-ids: 954cb531-1a99-4441-bf6d-21bcb09f45d2 status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=1VJhb6MwDP0vqNqnUZLQrqUSOpU7WqRbqdbSBvIthNAyEkAktF2n/ffLdNN%2Bw51kW8%2BW9Sz7%2Bd1q%2BE0/V02trMW7FS73yWFvLayz1p1aOI6kDT1xyRs9pveh52PWSkcNuWJ91emqbZTjodKbFvPSdtnTzJ5ANLE9yGb2nJVgxoq8RBPodH17qQreK2dTsb5VbanHv/nbkQ5CO5fPqH6MdNv58IF2lX0xnYbcRwB6NjAGH0aqNhPbmjd%2BsT7ei5X3mq9FmeNCG9yTVKAsPSqDz8wVQwY9QNIYpEgLnpJzgW8gvjOXJOEtRmSepwJnpoal6IlxHoknfvJ969H6GcbJbvn8799hz/tLxXhAFS8eE%2BkNZH%2BjG3m9JhjWHK/Sw2tAcTi5ZkcGc0kiEgX1LuyGDEFFUXjHCfhcGIf/kep/VY7i8usLvvPcDQSTK0CxNzCUTbe/2JUkO1FGwZS6RG6Tk7tZHwB5MSp/fPwB + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/vaults?$top=1&api-version=2019-09-01&$skiptoken=1ZLNbptAFIXfBUVZBeMZ7DhYsiq7xrhuQIqNmTC7YWYoGM%2BPGLCBKO9esuqmD9BKV3dzjs7Vd3Q/LMm75rWUlbGWH5a/PsXnk7W0iqbRZuk4gkjyiwsumwkZ2ppPqBKOaTND61I3pZLG8WDuzdlLbrv0eWHPAJzZHqAL%2B4Xm0wVlWQ5nwNG1upWM18YJS1oro/Jm8pP3CWmvjXP72ubbQ6P0CjwSXdq30TmGr%2BAUePZ0HPD4YKrxoqq4XDF5KKI4KkhAexw0Jgo8mSJP4uEw0EABgo5VKtgVvzOFt6nLUPGcyuSKt3Rge22YiNzQXQ98m4j08ubiS6TpfuNmwWFOYORmQwTyAMwTsTNspzWBWBO3mHOpVtaT9d2P4uP69d/v6cTrW0n5hhjOnmLhtfjUkVDc7zECFUe79/NlQ5A/u6cJBZnAe7zfVEdftykEhkB/QPH0Cxj5/8NX/I0Wo/26G2kSFoT9WR7CBGiYwqpj6Ed/Fp04DglEFfuju2%2B99fn5Gw%3D%3D - request: body: null headers: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET uri: https://management.azure.com/providers/Microsoft.KeyVault/operations?api-version=2019-09-01 response: @@ -450,12 +450,12 @@ interactions: Key Vault","description":"View the properties of a soft deleted key vault"},"isDataAction":false},{"name":"Microsoft.KeyVault/locations/deletedVaults/purge/action","display":{"provider":"Microsoft Key Vault","resource":"Soft Deleted Key Vault","operation":"Purge Soft Deleted Key Vault","description":"Purge a soft deleted key vault"},"isDataAction":false},{"name":"Microsoft.KeyVault/vaults/certificatecas/delete","display":{"provider":"Microsoft - Key Vault","resource":"Certificate Issuser","operation":"Delete Certificate - Issuser","description":"Delete Certificate Issuser"},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/certificatecas/read","display":{"provider":"Microsoft - Key Vault","resource":"Certificate Issuser","operation":"Read Certificate - Issuser","description":"Read Certificate Issuser"},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/certificatecas/write","display":{"provider":"Microsoft - Key Vault","resource":"Certificate Issuser","operation":"Write Certificate - Issuser","description":"Write Certificate Issuser"},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/certificatecontacts/write","display":{"provider":"Microsoft + Key Vault","resource":"Certificate Issuer","operation":"Delete Certificate + Issuer","description":"Delete Certificate Issuer"},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/certificatecas/read","display":{"provider":"Microsoft + Key Vault","resource":"Certificate Issuer","operation":"Read Certificate Issuer","description":"Read + Certificate Issuer"},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/certificatecas/write","display":{"provider":"Microsoft + Key Vault","resource":"Certificate Issuer","operation":"Write Certificate + Issuer","description":"Write Certificate Issuer"},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/certificatecontacts/write","display":{"provider":"Microsoft Key Vault","resource":"Certificate Contact","operation":"Manage Certificate Contact","description":"Manage Certificate Contact"},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/certificates/delete","display":{"provider":"Microsoft Key Vault","resource":"Certificate","operation":"Delete Certificate","description":"Delete @@ -544,7 +544,37 @@ interactions: Key Vault","resource":"Secret","operation":"Get Secret","description":"Get the value of a secret."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/secrets/setSecret/action","display":{"provider":"Microsoft Key Vault","resource":"Secret","operation":"Create Secret","description":"Create - new secret."},"isDataAction":true},{"name":"Microsoft.KeyVault/hsmPools/read","display":{"provider":"Microsoft + new secret."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/read","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Read Managed + Storage Account","description":"Read definition of managed storage accounts + and SAS."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/set/action","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Set Managed Storage + Account","description":"Create or update the definition of a managed storage + account."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/delete","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Delete Managed + Storage Account","description":"Delete the definition of a managed storage + account."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/backup/action","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Backup Managed + Storage Account","description":"Create a backup of the definition of a managed + storage account and its SAS (Shared Access Signature)."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/purge/action","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Purge Managed + Storage Account or SAS","description":"Purge the soft-deleted definition of + a managed storage account or SAS (Shared Access Signature)."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/regeneratekey/action","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Regenerate Key + of Managed Storage Account","description":"Regenerate the access key of a + managed storage account."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/recover/action","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Recover Managed + Storage Account or SAS","description":"Recover the soft-deleted definition + of a managed storage account or SAS (Shared Access Signature)."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/restore/action","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Restore Managed + Storage Account","description":"Restores the definition of a managed storage + account and its SAS (Shared Access Signature)."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/sas/set/action","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Set SAS Definition + for Managed Storage Account","description":"Create or update the SAS (Shared + Access Signature) definition for a managed storage account."},"isDataAction":true},{"name":"Microsoft.KeyVault/vaults/storageaccounts/sas/delete","display":{"provider":"Microsoft + Key Vault","resource":"Managed Storage Account","operation":"Delete SAS Definition + for Managed Storage Account","description":"Delete the SAS (Shared Access + Signature) definition for a managed storage account."},"isDataAction":true},{"name":"Microsoft.KeyVault/hsmPools/read","display":{"provider":"Microsoft Key Vault","resource":"HSM pool","operation":"View HSM pool","description":"View the properties of an HSM pool"},"isDataAction":false},{"name":"Microsoft.KeyVault/hsmPools/write","display":{"provider":"Microsoft Key Vault","resource":"HSM pool","operation":"Create or Update HSM pool","description":"Create @@ -592,7 +622,7 @@ interactions: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:57 GMT + date: Tue, 21 Jul 2020 08:13:55 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -601,7 +631,7 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 + x-ms-keyvault-service-version: 1.1.0.283 x-powered-by: ASP.NET status: code: 200 @@ -617,7 +647,7 @@ interactions: Content-Type: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: PATCH uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 response: @@ -627,7 +657,7 @@ interactions: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:58 GMT + date: Tue, 21 Jul 2020 08:13:56 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -636,13 +666,13 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 - x-ms-ratelimit-remaining-subscription-writes: '1197' + x-ms-keyvault-service-version: 1.1.0.283 + x-ms-ratelimit-remaining-subscription-writes: '1195' x-powered-by: ASP.NET status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/vra53ahg2dkl4ogaogg2spj5iddbgeewhd67uhzbued73tzlvcw3p3x5fb47f3ippwlbykcwo3u/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 - request: body: '{"name": "sample-vault", "type": "Microsoft.KeyVault/vaults"}' headers: @@ -653,7 +683,7 @@ interactions: Content-Type: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: POST uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/checkNameAvailability?api-version=2019-09-01 response: @@ -664,7 +694,7 @@ interactions: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:21:58 GMT + date: Tue, 21 Jul 2020 08:13:57 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -673,7 +703,7 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 + x-ms-keyvault-service-version: 1.1.0.283 x-powered-by: ASP.NET status: code: 200 @@ -683,7 +713,7 @@ interactions: body: null headers: User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: DELETE uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 response: @@ -692,37 +722,37 @@ interactions: headers: cache-control: no-cache content-length: '0' - date: Tue, 02 Jun 2020 05:22:01 GMT + date: Tue, 21 Jul 2020 08:14:02 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 strict-transport-security: max-age=31536000; includeSubDomains x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 - x-ms-ratelimit-remaining-subscription-deletes: '14999' + x-ms-keyvault-service-version: 1.1.0.283 + x-ms-ratelimit-remaining-subscription-deletes: '14998' x-powered-by: ASP.NET status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/resourceGroups/vra53ahg2dkl4ogaogg2spj5iddbgeewhd67uhzbued73tzlvcw3p3x5fb47f3ippwlbykcwo3u/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz?api-version=2019-09-01 - request: body: null headers: Accept: - application/json User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxyzz?api-version=2019-09-01 response: body: - string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxyzz","name":"myValtZikfikxyzz","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz","location":"eastus","tags":{},"deletionDate":"2020-06-02T05:21:59Z","scheduledPurgeDate":"2020-08-31T05:21:59Z"}}' + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxyzz","name":"myValtZikfikxyzz","type":"Microsoft.KeyVault/deletedVaults","properties":{"vaultId":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/myValtZikfikxyzz","location":"eastus","tags":{},"deletionDate":"2020-07-21T08:13:58Z","scheduledPurgeDate":"2020-10-19T08:13:58Z"}}' headers: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:22:02 GMT + date: Tue, 21 Jul 2020 08:14:03 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -731,7 +761,7 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 + x-ms-keyvault-service-version: 1.1.0.283 x-powered-by: ASP.NET status: code: 200 @@ -741,7 +771,7 @@ interactions: body: null headers: User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: POST uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/deletedVaults/myValtZikfikxyzz/purge?api-version=2019-09-01 response: @@ -750,16 +780,16 @@ interactions: headers: cache-control: no-cache content-length: '0' - date: Tue, 02 Jun 2020 05:22:02 GMT + date: Tue, 21 Jul 2020 08:14:03 GMT expires: '-1' - location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzI2NjcyMTIzNDgxMTM5Mnw3N0FDREY4RUI0QUI0N0E2QTBBQ0RBOUI2NTNCMjYzRA?api-version=2019-09-01 + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 pragma: no-cache server: Microsoft-IIS/10.0 strict-transport-security: max-age=31536000; includeSubDomains x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 - x-ms-ratelimit-remaining-subscription-writes: '1198' + x-ms-keyvault-service-version: 1.1.0.283 + x-ms-ratelimit-remaining-subscription-writes: '1199' x-powered-by: ASP.NET status: code: 202 @@ -769,46 +799,270 @@ interactions: body: null headers: User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:14:04Z","status":"NotStarted"}' + headers: + cache-control: no-cache + content-length: '64' + content-type: application/json; charset=utf-8 + date: Tue, 21 Jul 2020 08:14:10 GMT + expires: '-1' + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + pragma: no-cache + server: Microsoft-IIS/10.0 + strict-transport-security: max-age=31536000; includeSubDomains + x-aspnet-version: 4.0.30319 + x-content-type-options: nosniff + x-ms-keyvault-service-version: 1.1.0.283 + x-powered-by: ASP.NET + status: + code: 202 + message: Accepted + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 +- request: + body: null + headers: + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:14:04Z","status":"NotStarted"}' + headers: + cache-control: no-cache + content-length: '64' + content-type: application/json; charset=utf-8 + date: Tue, 21 Jul 2020 08:14:15 GMT + expires: '-1' + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + pragma: no-cache + server: Microsoft-IIS/10.0 + strict-transport-security: max-age=31536000; includeSubDomains + x-aspnet-version: 4.0.30319 + x-content-type-options: nosniff + x-ms-keyvault-service-version: 1.1.0.283 + x-powered-by: ASP.NET + status: + code: 202 + message: Accepted + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 +- request: + body: null + headers: + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:14:04Z","status":"NotStarted"}' + headers: + cache-control: no-cache + content-length: '64' + content-type: application/json; charset=utf-8 + date: Tue, 21 Jul 2020 08:14:20 GMT + expires: '-1' + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + pragma: no-cache + server: Microsoft-IIS/10.0 + strict-transport-security: max-age=31536000; includeSubDomains + x-aspnet-version: 4.0.30319 + x-content-type-options: nosniff + x-ms-keyvault-service-version: 1.1.0.283 + x-powered-by: ASP.NET + status: + code: 202 + message: Accepted + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 +- request: + body: null + headers: + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:14:04Z","status":"NotStarted"}' + headers: + cache-control: no-cache + content-length: '64' + content-type: application/json; charset=utf-8 + date: Tue, 21 Jul 2020 08:14:25 GMT + expires: '-1' + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + pragma: no-cache + server: Microsoft-IIS/10.0 + strict-transport-security: max-age=31536000; includeSubDomains + x-aspnet-version: 4.0.30319 + x-content-type-options: nosniff + x-ms-keyvault-service-version: 1.1.0.283 + x-powered-by: ASP.NET + status: + code: 202 + message: Accepted + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 +- request: + body: null + headers: + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:14:04Z","status":"NotStarted"}' + headers: + cache-control: no-cache + content-length: '64' + content-type: application/json; charset=utf-8 + date: Tue, 21 Jul 2020 08:14:31 GMT + expires: '-1' + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + pragma: no-cache + server: Microsoft-IIS/10.0 + strict-transport-security: max-age=31536000; includeSubDomains + x-aspnet-version: 4.0.30319 + x-content-type-options: nosniff + x-ms-keyvault-service-version: 1.1.0.283 + x-powered-by: ASP.NET + status: + code: 202 + message: Accepted + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 +- request: + body: null + headers: + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:14:04Z","status":"NotStarted"}' + headers: + cache-control: no-cache + content-length: '64' + content-type: application/json; charset=utf-8 + date: Tue, 21 Jul 2020 08:14:36 GMT + expires: '-1' + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + pragma: no-cache + server: Microsoft-IIS/10.0 + strict-transport-security: max-age=31536000; includeSubDomains + x-aspnet-version: 4.0.30319 + x-content-type-options: nosniff + x-ms-keyvault-service-version: 1.1.0.283 + x-powered-by: ASP.NET + status: + code: 202 + message: Accepted + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 +- request: + body: null + headers: + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:14:04Z","status":"NotStarted"}' + headers: + cache-control: no-cache + content-length: '64' + content-type: application/json; charset=utf-8 + date: Tue, 21 Jul 2020 08:14:41 GMT + expires: '-1' + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + pragma: no-cache + server: Microsoft-IIS/10.0 + strict-transport-security: max-age=31536000; includeSubDomains + x-aspnet-version: 4.0.30319 + x-content-type-options: nosniff + x-ms-keyvault-service-version: 1.1.0.283 + x-powered-by: ASP.NET + status: + code: 202 + message: Accepted + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 +- request: + body: null + headers: + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + response: + body: + string: '{"createdDateTime":"2020-07-21 08:14:04Z","status":"NotStarted"}' + headers: + cache-control: no-cache + content-length: '64' + content-type: application/json; charset=utf-8 + date: Tue, 21 Jul 2020 08:14:47 GMT + expires: '-1' + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 + pragma: no-cache + server: Microsoft-IIS/10.0 + strict-transport-security: max-age=31536000; includeSubDomains + x-aspnet-version: 4.0.30319 + x-content-type-options: nosniff + x-ms-keyvault-service-version: 1.1.0.283 + x-powered-by: ASP.NET + status: + code: 202 + message: Accepted + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 +- request: + body: null + headers: + User-Agent: + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzI2NjcyMTIzNDgxMTM5Mnw3N0FDREY4RUI0QUI0N0E2QTBBQ0RBOUI2NTNCMjYzRA?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 response: body: - string: '{"createdDateTime":"2020-06-02 05:22:02Z","status":"NotStarted"}' + string: '{"createdDateTime":"2020-07-21 08:14:04Z","status":"NotStarted"}' headers: cache-control: no-cache content-length: '64' content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:22:07 GMT + date: Tue, 21 Jul 2020 08:14:52 GMT expires: '-1' - location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzI2NjcyMTIzNDgxMTM5Mnw3N0FDREY4RUI0QUI0N0E2QTBBQ0RBOUI2NTNCMjYzRA?api-version=2019-09-01 + location: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 pragma: no-cache server: Microsoft-IIS/10.0 strict-transport-security: max-age=31536000; includeSubDomains x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 + x-ms-keyvault-service-version: 1.1.0.283 x-powered-by: ASP.NET status: code: 202 message: Accepted - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzI2NjcyMTIzNDgxMTM5Mnw3N0FDREY4RUI0QUI0N0E2QTBBQ0RBOUI2NTNCMjYzRA?api-version=2019-09-01 + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 - request: body: null headers: User-Agent: - - azsdk-python-azure-mgmt-keyvault/3.0.0b1 Python/3.6.9 (Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic) + - azsdk-python-azure-mgmt-keyvault/7.0.0b2 Python/3.8.1 (Windows-10-10.0.18362-SP0) method: GET - uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzI2NjcyMTIzNDgxMTM5Mnw3N0FDREY4RUI0QUI0N0E2QTBBQ0RBOUI2NTNCMjYzRA?api-version=2019-09-01 + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 response: body: - string: '{"createdDateTime":"2020-06-02 05:22:02Z","lastActionDateTime":"2020-06-02 - 05:22:09Z","status":"Succeeded"}' + string: '{"createdDateTime":"2020-07-21 08:14:04Z","lastActionDateTime":"2020-07-21 + 08:14:56Z","status":"Succeeded"}' headers: cache-control: no-cache content-encoding: gzip content-type: application/json; charset=utf-8 - date: Tue, 02 Jun 2020 05:22:12 GMT + date: Tue, 21 Jul 2020 08:14:57 GMT expires: '-1' pragma: no-cache server: Microsoft-IIS/10.0 @@ -817,10 +1071,10 @@ interactions: vary: Accept-Encoding x-aspnet-version: 4.0.30319 x-content-type-options: nosniff - x-ms-keyvault-service-version: 1.1.0.281 + x-ms-keyvault-service-version: 1.1.0.283 x-powered-by: ASP.NET status: code: 200 message: OK - url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzI2NjcyMTIzNDgxMTM5Mnw3N0FDREY4RUI0QUI0N0E2QTBBQ0RBOUI2NTNCMjYzRA?api-version=2019-09-01 + url: https://management.azure.com/subscriptions/92f95d8f-3c67-4124-91c7-8cf07cdbf241/providers/Microsoft.KeyVault/locations/eastus/operationResults/VVR8MDYzNzMwOTE2MDQ1NTI2NDk2MHw4NTExNzM2MzlFQkI0NzY2Qjc1RDA0MzdFNzgyQjRDMw?api-version=2019-09-01 version: 1 diff --git a/sdk/keyvault/azure-mgmt-keyvault/tests/test_cli_mgmt_keyvault.py b/sdk/keyvault/azure-mgmt-keyvault/tests/test_cli_mgmt_keyvault.py index 2436ecf38066..66a5b64eb516 100644 --- a/sdk/keyvault/azure-mgmt-keyvault/tests/test_cli_mgmt_keyvault.py +++ b/sdk/keyvault/azure-mgmt-keyvault/tests/test_cli_mgmt_keyvault.py @@ -37,7 +37,7 @@ def test_keyvault(self, resource_group): SUBSCRIPTION_ID = self.settings.SUBSCRIPTION_ID TENANT_ID = "72f988bf-86f1-41af-91ab-2d7cd011db47" # self.settings.TENANT_ID RESOURCE_GROUP = resource_group.name - VAULT_NAME = "myValtZikfikxy" + VAULT_NAME = "myValtZikfikxz" OPERATION_KIND = "add" LOCATION = "eastus" PRIVATE_ENDPOINT_CONNECTION_NAME = "myPrivateEndpointConnection" diff --git a/sdk/search/azure-search-documents/README.md b/sdk/search/azure-search-documents/README.md index ebd9bbc64f6c..6bce89f6b26b 100644 --- a/sdk/search/azure-search-documents/README.md +++ b/sdk/search/azure-search-documents/README.md @@ -94,7 +94,7 @@ import os from azure.core.credentials import AzureKeyCredential from azure.search.documents import SearchClient -index_name = "nycjobs"; +index_name = "nycjobs" # Get the service endpoint and API key from the environment endpoint = os.environ["SEARCH_ENDPOINT"] key = os.environ["SEARCH_API_KEY"] @@ -293,12 +293,14 @@ key = os.environ["SEARCH_API_KEY"] DOCUMENT = { 'Category': 'Hotel', - 'HotelId': '1000', - 'Rating': 4.0, - 'Rooms': [], - 'HotelName': 'Azure Inn', + 'hotelId': '1000', + 'rating': 4.0, + 'rooms': [], + 'hotelName': 'Azure Inn', } +search_client = SearchClient(endpoint, index_name, AzureKeyCredential(key)) + result = client.upload_documents(documents=[DOCUMENT]) print("Upload of new document succeeded: {}".format(result[0].succeeded)) diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_models.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_models.py index bfdbc1701aa8..7da916d21bdb 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_models.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_models.py @@ -119,7 +119,7 @@ class CustomAnalyzer(LexicalAnalyzer): _validation = { 'odata_type': {'required': True}, 'name': {'required': True}, - 'tokenizer': {'required': True}, + 'tokenizer_name': {'required': True}, } _attribute_map = { diff --git a/sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_utils.py b/sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_utils.py index fe3722a8e75d..9ad43085cd07 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_utils.py +++ b/sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_utils.py @@ -78,6 +78,7 @@ def prep_if_none_match(etag, match_condition): def pack_custom_analyzer(custom_analyzer): # type: (CustomAnalyzer) -> _CustomAnalyzer return _CustomAnalyzer( + name=custom_analyzer.name, odata_type=custom_analyzer.odata_type, tokenizer=custom_analyzer.tokenizer_name, token_filters=custom_analyzer.token_filters, @@ -87,7 +88,8 @@ def pack_custom_analyzer(custom_analyzer): def unpack_custom_analyzer(custom_analyzer): # type: (_CustomAnalyzer) -> CustomAnalyzer - return _CustomAnalyzer( + return CustomAnalyzer( + name=custom_analyzer.name, odata_type=custom_analyzer.odata_type, tokenizer_name=custom_analyzer.tokenizer, token_filters=custom_analyzer.token_filters, diff --git a/sdk/search/azure-search-documents/samples/async_samples/sample_indexers_operations_async.py b/sdk/search/azure-search-documents/samples/async_samples/sample_indexers_operations_async.py index ad3c028fd4fd..2f26c0a00b41 100644 --- a/sdk/search/azure-search-documents/samples/async_samples/sample_indexers_operations_async.py +++ b/sdk/search/azure-search-documents/samples/async_samples/sample_indexers_operations_async.py @@ -40,13 +40,13 @@ async def create_indexer(): # create an index - index_name = "hotels" + index_name = "indexer-hotels" fields = [ SimpleField(name="hotelId", type=SearchFieldDataType.String, key=True), SimpleField(name="baseRate", type=SearchFieldDataType.Double) ] index = SearchIndex(name=index_name, fields=fields) - ind_client = SearchIndexerClient(service_endpoint, AzureKeyCredential(key)) + ind_client = SearchIndexClient(service_endpoint, AzureKeyCredential(key)) async with ind_client: await ind_client.create_index(index) @@ -59,8 +59,8 @@ async def create_indexer(): connection_string=connection_string, container=container ) - async with ind_client: - data_source = await ind_client.create_data_source_connection(data_source_connection) + async with indexers_client: + data_source = await indexers_client.create_data_source_connection(data_source_connection) # create an indexer indexer = SearchIndexer( diff --git a/sdk/search/azure-search-documents/samples/sample_indexer_datasource_skillset.py b/sdk/search/azure-search-documents/samples/sample_indexer_datasource_skillset.py index f0684da68d6b..9b3dac6cccd4 100644 --- a/sdk/search/azure-search-documents/samples/sample_indexer_datasource_skillset.py +++ b/sdk/search/azure-search-documents/samples/sample_indexer_datasource_skillset.py @@ -38,7 +38,7 @@ from azure.search.documents.indexes.models import ( SearchIndexerDataContainer, SearchIndex, SearchIndexer, SimpleField, SearchFieldDataType, EntityRecognitionSkill, InputFieldMappingEntry, OutputFieldMappingEntry, SearchIndexerSkillset, - CorsOptions, IndexingSchedule, SearchableField, IndexingParameters + CorsOptions, IndexingSchedule, SearchableField, IndexingParameters, SearchIndexerDataSourceConnection ) from azure.search.documents.indexes import SearchIndexerClient, SearchIndexClient @@ -75,12 +75,13 @@ def _create_datasource(): # "searchcontainer" ds_client = SearchIndexerClient(service_endpoint, AzureKeyCredential(key)) container = SearchIndexerDataContainer(name='searchcontainer') - data_source = ds_client.create_datasource( + data_source_connection = SearchIndexerDataSourceConnection( name="hotel-datasource", type="azureblob", connection_string=connection_string, container=container ) + data_source = ds_client.create_data_source_connection(data_source_connection) return data_source def _create_skillset(): diff --git a/sdk/servicebus/azure-servicebus/CHANGELOG.md b/sdk/servicebus/azure-servicebus/CHANGELOG.md index 13a9cb2a79e4..f424295345a0 100644 --- a/sdk/servicebus/azure-servicebus/CHANGELOG.md +++ b/sdk/servicebus/azure-servicebus/CHANGELOG.md @@ -2,6 +2,29 @@ ## 7.0.0b5 (Unreleased) +**New Features** + +* Added new properties to Message, PeekMessage and ReceivedMessage: `content_type`, `correlation_id`, `label`, +`message_id`, `reply_to`, `reply_to_session_id` and `to`. Please refer to the docstring for further information. + +* Add new properties to PeekedMessaged and ReceivedMessage: `enqueued_sequence_number`, `dead_letter_error_description`, +`dead_letter_reason`, `dead_letter_source`, `delivery_count` and `expires_at_utc`. Please refer to the docstring for further information. + +**Breaking Changes** + +* Removed/Renamed several properties and instance variables on Message (the changes applied to the inherited Message type PeekMessage and ReceivedMessage). + - Renamed property `user_properties` to `properties` + - The original instance variable `properties` which represents the AMQP properties now becomes an internal instance variable `_amqp_properties`. + - Removed property `enqueue_sequence_number`. + - Removed property `annotations`. + - Removed instance variable `header`. + +* Removed several properties and instance variables on PeekMessage and ReceivedMessage. + - Removed proeprty `partition_id` on both type. + - Removed instance variable `received_timestamp_utc` on both type. + - Removed property `settled` on `PeekMessage`. + - Removed property `expired` on `ReceivedMessage`. + ## 7.0.0b4 (2020-07-06) diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_common/constants.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_common/constants.py index 7b67fe37a32b..00182a290432 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_common/constants.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_common/constants.py @@ -3,10 +3,9 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- - from enum import Enum -from uamqp import constants +from uamqp import constants, types VENDOR = b"com.microsoft" DATETIMEOFFSET_EPOCH = 621355968000000000 @@ -97,6 +96,10 @@ _X_OPT_LOCKED_UNTIL = b'x-opt-locked-until' _X_OPT_LOCK_TOKEN = b'x-opt-lock-token' _X_OPT_SCHEDULED_ENQUEUE_TIME = b'x-opt-scheduled-enqueue-time' +_X_OPT_DEAD_LETTER_SOURCE = b'x-opt-deadletter-source' + +PROPERTIES_DEAD_LETTER_REASON = b'DeadLetterReason' +PROPERTIES_DEAD_LETTER_ERROR_DESCRIPTION = b'DeadLetterErrorDescription' DEAD_LETTER_QUEUE_SUFFIX = '/$DeadLetterQueue' @@ -112,4 +115,15 @@ class SessionFilter(Enum): NextAvailable = 0 +ANNOTATION_SYMBOL_PARTITION_KEY = types.AMQPSymbol(_X_OPT_PARTITION_KEY) +ANNOTATION_SYMBOL_VIA_PARTITION_KEY = types.AMQPSymbol(_X_OPT_VIA_PARTITION_KEY) +ANNOTATION_SYMBOL_SCHEDULED_ENQUEUE_TIME = types.AMQPSymbol(_X_OPT_SCHEDULED_ENQUEUE_TIME) + +ANNOTATION_SYMBOL_KEY_MAP = { + _X_OPT_PARTITION_KEY: ANNOTATION_SYMBOL_PARTITION_KEY, + _X_OPT_VIA_PARTITION_KEY: ANNOTATION_SYMBOL_VIA_PARTITION_KEY, + _X_OPT_SCHEDULED_ENQUEUE_TIME: ANNOTATION_SYMBOL_SCHEDULED_ENQUEUE_TIME +} + + NEXT_AVAILABLE = SessionFilter.NextAvailable diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_common/message.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_common/message.py index 80361f35e506..18c0e6bc7c18 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_common/message.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_common/message.py @@ -1,17 +1,17 @@ -# ------------------------------------------------------------------------ +# ------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +# pylint: disable=too-many-lines import datetime import uuid import functools import logging -from typing import Optional, List, Union, Iterable, TYPE_CHECKING, Callable, Dict, Any +from typing import Optional, List, Union, Iterable, TYPE_CHECKING, Callable import uamqp.message -from uamqp import types from .constants import ( _BATCH_MESSAGE_OVERHEAD_COST, @@ -23,12 +23,12 @@ _X_OPT_ENQUEUED_TIME, _X_OPT_SEQUENCE_NUMBER, _X_OPT_ENQUEUE_SEQUENCE_NUMBER, - _X_OPT_PARTITION_ID, _X_OPT_PARTITION_KEY, _X_OPT_VIA_PARTITION_KEY, _X_OPT_LOCKED_UNTIL, _X_OPT_LOCK_TOKEN, _X_OPT_SCHEDULED_ENQUEUE_TIME, + _X_OPT_DEAD_LETTER_SOURCE, MGMT_RESPONSE_MESSAGE_EXPIRATION, MGMT_REQUEST_DEAD_LETTER_REASON, MGMT_REQUEST_DEAD_LETTER_DESCRIPTION, @@ -39,7 +39,13 @@ MESSAGE_ABANDON, MESSAGE_DEFER, MESSAGE_RENEW_LOCK, - DEADLETTERNAME + DEADLETTERNAME, + PROPERTIES_DEAD_LETTER_REASON, + PROPERTIES_DEAD_LETTER_ERROR_DESCRIPTION, + ANNOTATION_SYMBOL_PARTITION_KEY, + ANNOTATION_SYMBOL_VIA_PARTITION_KEY, + ANNOTATION_SYMBOL_SCHEDULED_ENQUEUE_TIME, + ANNOTATION_SYMBOL_KEY_MAP ) from ..exceptions import ( MessageAlreadySettled, @@ -58,17 +64,24 @@ class Message(object): # pylint: disable=too-many-public-methods,too-many-instance-attributes """A Service Bus Message. - :ivar properties: Properties of the internal AMQP message object. - :vartype properties: ~uamqp.message.MessageProperties - :ivar header: Header of the internal AMQP message object. - :vartype header: ~uamqp.message.MessageHeader - :ivar message: Internal AMQP message object. - :vartype message: ~uamqp.message.Message - :param body: The data to send in a single message. :type body: str or bytes + + :keyword dict properties: The user defined properties on the message. + :keyword str session_id: The session identifier of the message for a sessionful entity. + :keyword str message_id: The id to identify the message. + :keyword datetime.datetime scheduled_enqueue_time_utc: The utc scheduled enqueue time to the message. + :keyword datetime.timedelta time_to_live: The life duration of a message. + :keyword str content_type: The content type descriptor. + :keyword str correlation_id: The correlation identifier. + :keyword str label: The application specific label. + :keyword str partition_key: The partition key for sending a message to a partitioned entity. + :keyword str via_partition_key: The partition key for sending a message into an entity via a partitioned + transfer queue. + :keyword str to: The `to` address used for auto_forward chaining scenarios. + :keyword str reply_to: The address of an entity to send replies to. + :keyword str reply_to_session_id: The session identifier augmenting the `reply_to` address. :keyword str encoding: The encoding for string data. Default is UTF-8. - :keyword str session_id: An optional session ID for the message to be sent. .. admonition:: Example: @@ -82,170 +95,190 @@ class Message(object): # pylint: disable=too-many-public-methods,too-many-insta """ def __init__(self, body, **kwargs): - subject = kwargs.pop('subject', None) # Although we might normally thread through **kwargs this causes # problems as MessageProperties won't absorb spurious args. self._encoding = kwargs.pop("encoding", 'UTF-8') - self.properties = uamqp.message.MessageProperties(encoding=self._encoding, subject=subject) - self.header = uamqp.message.MessageHeader() - self._annotations = {} - self._app_properties = {} + self._amqp_properties = uamqp.message.MessageProperties(encoding=self._encoding) + self._amqp_header = uamqp.message.MessageHeader() - self.session_id = kwargs.get("session_id", None) if 'message' in kwargs: self.message = kwargs['message'] - self._annotations = self.message.annotations - self._app_properties = self.message.application_properties - self.properties = self.message.properties - self.header = self.message.header + self._amqp_properties = self.message.properties + self._amqp_header = self.message.header else: self._build_message(body) + self.properties = kwargs.pop("properties", None) + self.session_id = kwargs.pop("session_id", None) + self.message_id = kwargs.get("message_id", None) + self.content_type = kwargs.pop("content_type", None) + self.correlation_id = kwargs.pop("correlation_id", None) + self.to = kwargs.pop("to", None) + self.reply_to = kwargs.pop("reply_to", None) + self.reply_to_session_id = kwargs.pop("reply_to_session_id", None) + self.label = kwargs.pop("label", None) + self.scheduled_enqueue_time_utc = kwargs.pop("scheduled_enqueue_time_utc", None) + self.time_to_live = kwargs.pop("time_to_live", None) + self.partition_key = kwargs.pop("partition_key", None) + self.via_partition_key = kwargs.pop("via_partition_key", None) def __str__(self): return str(self.message) def _build_message(self, body): if isinstance(body, list) and body: # TODO: This only works for a list of bytes/strings - self.message = uamqp.Message(body[0], properties=self.properties, header=self.header) + self.message = uamqp.Message(body[0], properties=self._amqp_properties, header=self._amqp_header) for more in body[1:]: self.message._body.append(more) # pylint: disable=protected-access elif body is None: raise ValueError("Message body cannot be None.") else: - self.message = uamqp.Message(body, properties=self.properties, header=self.header) + self.message = uamqp.Message(body, properties=self._amqp_properties, header=self._amqp_header) + + def _set_message_annotations(self, key, value): + if not self.message.annotations: + self.message.annotations = {} + + if isinstance(self, ReceivedMessage): + try: + del self.message.annotations[key] + except KeyError: + pass + + if value is None: + try: + del self.message.annotations[ANNOTATION_SYMBOL_KEY_MAP[key]] + except KeyError: + pass + else: + self.message.annotations[ANNOTATION_SYMBOL_KEY_MAP[key]] = value @property def session_id(self): # type: () -> str - """The session id of the message + """The session identifier of the message for a sessionful entity. + + For sessionful entities, this application-defined value specifies the session affiliation of the message. + Messages with the same session identifier are subject to summary locking and enable exact in-order + processing and demultiplexing. For non-sessionful entities, this value is ignored. + + See Message Sessions in `https://docs.microsoft.com/azure/service-bus-messaging/message-sessions`. :rtype: str """ try: - return self.properties.group_id.decode('UTF-8') + return self._amqp_properties.group_id.decode('UTF-8') except (AttributeError, UnicodeDecodeError): - return self.properties.group_id + return self._amqp_properties.group_id @session_id.setter def session_id(self, value): - """Set the session id on the message. - - :param value: The session id for the message. - :type value: str - """ - self.properties.group_id = value - - @property - def annotations(self): - # type: () -> dict - """The annotations of the message. - - :rtype: dict - """ - return self.message.annotations - - @annotations.setter - def annotations(self, value): - """Set the annotations on the message. - - :param value: The annotations for the Message. - :type value: dict - """ - self.message.annotations = value + # type: (str) -> None + self._amqp_properties.group_id = value @property - def user_properties(self): + def properties(self): # type: () -> dict - """User defined properties on the message. + """The user defined properties on the message. :rtype: dict """ return self.message.application_properties - @user_properties.setter - def user_properties(self, value): - """User defined properties on the message. - - :param value: The application properties for the Message. - :type value: dict - """ + @properties.setter + def properties(self, value): + # type: (dict) -> None self.message.application_properties = value - @property - def enqueue_sequence_number(self): - # type: () -> Optional[int] - """ - - :rtype: int - """ - if self.message.annotations: - return self.message.annotations.get(_X_OPT_ENQUEUE_SEQUENCE_NUMBER) - return None - - @enqueue_sequence_number.setter - def enqueue_sequence_number(self, value): - if not self.message.annotations: - self.message.annotations = {} - self.message.annotations[types.AMQPSymbol(_X_OPT_ENQUEUE_SEQUENCE_NUMBER)] = value - @property def partition_key(self): # type: () -> Optional[str] - """ + """ The partition key for sending a message to a partitioned entity. + + Setting this value enables assigning related messages to the same internal partition, so that submission + sequence order is correctly recorded. + The partition is chosen by a hash function over this value and cannot be chosen directly. + + See Partitioned queues and topics in + `https://docs.microsoft.com/azure/service-bus-messaging/service-bus-partitioning`. :rtype: str """ - if self.message.annotations: - return self.message.annotations.get(_X_OPT_PARTITION_KEY) - return None + p_key = None + try: + p_key = self.message.annotations.get(_X_OPT_PARTITION_KEY) or \ + self.message.annotations.get(ANNOTATION_SYMBOL_PARTITION_KEY) + return p_key.decode('UTF-8') + except (AttributeError, UnicodeDecodeError): + return p_key @partition_key.setter def partition_key(self, value): - if not self.message.annotations: - self.message.annotations = {} - self.message.annotations[types.AMQPSymbol(_X_OPT_PARTITION_KEY)] = value + # type: (str) -> None + self._set_message_annotations(_X_OPT_PARTITION_KEY, value) @property def via_partition_key(self): # type: () -> Optional[str] - """ + """ The partition key for sending a message into an entity via a partitioned transfer queue. + + If a message is sent via a transfer queue in the scope of a transaction, this value selects the transfer + queue partition: This is functionally equivalent to `partition_key` and ensures that messages are kept + together and in order as they are transferred. + + See Transfers and Send Via in + `https://docs.microsoft.com/azure/service-bus-messaging/service-bus-transactions#transfers-and-send-via`. :rtype: str """ - if self.message.annotations: - return self.message.annotations.get(_X_OPT_VIA_PARTITION_KEY) - return None + via_p_key = None + try: + via_p_key = self.message.annotations.get(_X_OPT_VIA_PARTITION_KEY) or \ + self.message.annotations.get(ANNOTATION_SYMBOL_VIA_PARTITION_KEY) + return via_p_key.decode('UTF-8') + except (AttributeError, UnicodeDecodeError): + return via_p_key @via_partition_key.setter def via_partition_key(self, value): - if not self.message.annotations: - self.message.annotations = {} - self.message.annotations[types.AMQPSymbol(_X_OPT_VIA_PARTITION_KEY)] = value + # type: (str) -> None + self._set_message_annotations(_X_OPT_VIA_PARTITION_KEY, value) @property def time_to_live(self): # type: () -> Optional[datetime.timedelta] - """ + """The life duration of a message. + + This value is the relative duration after which the message expires, starting from the instant the message + has been accepted and stored by the broker, as captured in `enqueued_time_utc`. + When not set explicitly, the assumed value is the DefaultTimeToLive for the respective queue or topic. + A message-level time-to-live value cannot be longer than the entity's time-to-live setting and it is silently + adjusted if it does. + + See Expiration in `https://docs.microsoft.com/azure/service-bus-messaging/message-expiration` :rtype: ~datetime.timedelta """ - if self.header and self.header.time_to_live: - return datetime.timedelta(milliseconds=self.header.time_to_live) + if self._amqp_header and self._amqp_header.time_to_live: + return datetime.timedelta(milliseconds=self._amqp_header.time_to_live) return None @time_to_live.setter def time_to_live(self, value): - if not self.header: - self.header = uamqp.message.MessageHeader() - if isinstance(value, datetime.timedelta): - self.header.time_to_live = value.seconds * 1000 + # type: (datetime.timedelta) -> None + if not self._amqp_header: + self._amqp_header = uamqp.message.MessageHeader() + if value is None: + self._amqp_header.time_to_live = value + elif isinstance(value, datetime.timedelta): + self._amqp_header.time_to_live = value.seconds * 1000 else: - self.header.time_to_live = int(value) * 1000 + self._amqp_header.time_to_live = int(value) * 1000 @property def scheduled_enqueue_time_utc(self): # type: () -> Optional[datetime.datetime] - """Get or set the utc scheduled enqueue time to the message. + """The utc scheduled enqueue time to the message. + This property can be used for scheduling when sending a message through `ServiceBusSender.send` method. If cancelling scheduled messages is required, you should use the `ServiceBusSender.schedule` method, which returns sequence numbers that can be used for future cancellation. @@ -254,20 +287,22 @@ def scheduled_enqueue_time_utc(self): :rtype: ~datetime.datetime """ if self.message.annotations: - timestamp = self.message.annotations.get(_X_OPT_SCHEDULED_ENQUEUE_TIME) + timestamp = self.message.annotations.get(_X_OPT_SCHEDULED_ENQUEUE_TIME) or \ + self.message.annotations.get(ANNOTATION_SYMBOL_SCHEDULED_ENQUEUE_TIME) if timestamp: - in_seconds = timestamp/1000.0 - return utc_from_timestamp(in_seconds) + try: + in_seconds = timestamp/1000.0 + return utc_from_timestamp(in_seconds) + except TypeError: + return timestamp return None @scheduled_enqueue_time_utc.setter def scheduled_enqueue_time_utc(self, value): # type: (datetime.datetime) -> None - if not self.properties.message_id: - self.properties.message_id = str(uuid.uuid4()) - if not self.message.annotations: - self.message.annotations = {} - self.message.annotations[types.AMQPSymbol(_X_OPT_SCHEDULED_ENQUEUE_TIME)] = value + if not self._amqp_properties.message_id: + self._amqp_properties.message_id = str(uuid.uuid4()) + self._set_message_annotations(_X_OPT_SCHEDULED_ENQUEUE_TIME, value) @property def body(self): @@ -278,6 +313,165 @@ def body(self): """ return self.message.get_data() + @property + def content_type(self): + # type: () -> str + """The content type descriptor. + + Optionally describes the payload of the message, with a descriptor following the format of RFC2045, Section 5, + for example "application/json". + + :rtype: str + """ + try: + return self._amqp_properties.content_type.decode('UTF-8') + except (AttributeError, UnicodeDecodeError): + return self._amqp_properties.content_type + + @content_type.setter + def content_type(self, val): + # type: (str) -> None + self._amqp_properties.content_type = val + + @property + def correlation_id(self): + # type: () -> str + # pylint: disable=line-too-long + """The correlation identifier. + + Allows an application to specify a context for the message for the purposes of correlation, for example + reflecting the MessageId of a message that is being replied to. + + See Message Routing and Correlation in + `https://docs.microsoft.com/azure/service-bus-messaging/service-bus-messages-payloads?#message-routing-and-correlation`. + + :rtype: str + """ + try: + return self._amqp_properties.correlation_id.decode('UTF-8') + except (AttributeError, UnicodeDecodeError): + return self._amqp_properties.correlation_id + + @correlation_id.setter + def correlation_id(self, val): + # type: (str) -> None + self._amqp_properties.correlation_id = val + + @property + def label(self): + # type: () -> str + """The application specific label. + + This property enables the application to indicate the purpose of the message to the receiver in a standardized + fashion, similar to an email subject line. + + :rtype: str + """ + try: + return self._amqp_properties.subject.decode('UTF-8') + except (AttributeError, UnicodeDecodeError): + return self._amqp_properties.subject + + @label.setter + def label(self, val): + # type: (str) -> None + self._amqp_properties.subject = val + + @property + def message_id(self): + # type: () -> str + """The id to identify the message. + + The message identifier is an application-defined value that uniquely identifies the message and its payload. + The identifier is a free-form string and can reflect a GUID or an identifier derived from the + application context. If enabled, the duplicate detection (see + `https://docs.microsoft.com/azure/service-bus-messaging/duplicate-detection`) + feature identifies and removes second and further submissions of messages with the same message id. + + :rtype: str + """ + try: + return self._amqp_properties.message_id.decode('UTF-8') + except (AttributeError, UnicodeDecodeError): + return self._amqp_properties.message_id + + @message_id.setter + def message_id(self, val): + # type: (str) -> None + self._amqp_properties.message_id = val + + @property + def reply_to(self): + # type: () -> str + # pylint: disable=line-too-long + """The address of an entity to send replies to. + + This optional and application-defined value is a standard way to express a reply path to the receiver of + the message. When a sender expects a reply, it sets the value to the absolute or relative path of the queue + or topic it expects the reply to be sent to. + + See Message Routing and Correlation in + `https://docs.microsoft.com/azure/service-bus-messaging/service-bus-messages-payloads?#message-routing-and-correlation`. + + :rtype: str + """ + try: + return self._amqp_properties.reply_to.decode('UTF-8') + except (AttributeError, UnicodeDecodeError): + return self._amqp_properties.reply_to + + @reply_to.setter + def reply_to(self, val): + # type: (str) -> None + self._amqp_properties.reply_to = val + + @property + def reply_to_session_id(self): + # type: () -> str + # pylint: disable=line-too-long + """The session identifier augmenting the `reply_to` address. + + This value augments the `reply_to` information and specifies which session id should be set for the reply + when sent to the reply entity. + + See Message Routing and Correlation in + `https://docs.microsoft.com/azure/service-bus-messaging/service-bus-messages-payloads?#message-routing-and-correlation`. + + :rtype: str + """ + try: + return self._amqp_properties.reply_to_group_id.decode('UTF-8') + except (AttributeError, UnicodeDecodeError): + return self._amqp_properties.reply_to_group_id + + @reply_to_session_id.setter + def reply_to_session_id(self, val): + # type: (str) -> None + self._amqp_properties.reply_to_group_id = val + + @property + def to(self): + # type: () -> str + """The `to` address. + + This property is reserved for future use in routing scenarios and presently ignored by the broker itself. + Applications can use this value in rule-driven auto-forward chaining scenarios to indicate the intended + logical destination of the message. + + See https://docs.microsoft.com/azure/service-bus-messaging/service-bus-auto-forwarding for more details. + + :rtype: str + """ + try: + return self._amqp_properties.to.decode('UTF-8') + except (AttributeError, UnicodeDecodeError): + return self._amqp_properties.to + + @to.setter + def to(self, val): + # type: (str) -> None + self._amqp_properties.to = val + class BatchMessage(object): """A batch of messages. @@ -376,42 +570,89 @@ class PeekMessage(Message): A peeked message cannot be completed, abandoned, dead-lettered or deferred. It has no lock token or expiry. - :ivar received_timestamp_utc: The utc timestamp of when the message is received. - :vartype received_timestamp_utc: datetime.datetime - """ def __init__(self, message): super(PeekMessage, self).__init__(None, message=message) - self.received_timestamp_utc = utc_now() @property - def settled(self): - # type: () -> bool - """Whether the message has been settled. + def dead_letter_error_description(self): + # type: () -> Optional[str] + """ + Dead letter error description, when the message is received from a deadletter subqueue of an entity. - This will aways be `True` for a message received using ReceiveAndDelete mode, - otherwise it will be `False` until the message is completed or otherwise settled. + :rtype: str + """ + if self.message.application_properties: + try: + return self.message.application_properties.get(PROPERTIES_DEAD_LETTER_ERROR_DESCRIPTION).decode('UTF-8') + except AttributeError: + pass + return None - :rtype: bool + @property + def dead_letter_reason(self): + # type: () -> Optional[str] """ - return self.message.settled + Dead letter reason, when the message is received from a deadletter subqueue of an entity. + + :rtype: str + """ + if self.message.application_properties: + try: + return self.message.application_properties.get(PROPERTIES_DEAD_LETTER_REASON).decode('UTF-8') + except AttributeError: + pass + return None @property - def partition_id(self): + def dead_letter_source(self): # type: () -> Optional[str] """ + The name of the queue or subscription that this message was enqueued on, before it was deadlettered. + This property is only set in messages that have been dead-lettered and subsequently auto-forwarded + from the dead-letter queue to another entity. Indicates the entity in which the message was dead-lettered. + + :rtype: str + """ + if self.message.annotations: + try: + return self.message.annotations.get(_X_OPT_DEAD_LETTER_SOURCE).decode('UTF-8') + except AttributeError: + pass + return None + + @property + def delivery_count(self): + # type: () -> Optional[int] + """ + Number of deliveries that have been attempted for this message. The count is incremented + when a message lock expires or the message is explicitly abandoned by the receiver. + + :rtype: int + """ + if self._amqp_header: + return self._amqp_header.delivery_count + return None + + @property + def enqueued_sequence_number(self): + # type: () -> Optional[int] + """ + For messages that have been auto-forwarded, this property reflects the sequence number that had + first been assigned to the message at its original point of submission. :rtype: int """ if self.message.annotations: - return self.message.annotations.get(_X_OPT_PARTITION_ID) + return self.message.annotations.get(_X_OPT_ENQUEUE_SEQUENCE_NUMBER) return None @property def enqueued_time_utc(self): # type: () -> Optional[datetime.datetime] """ + The UTC datetime at which the message has been accepted and stored in the entity. :rtype: ~datetime.datetime """ @@ -422,10 +663,28 @@ def enqueued_time_utc(self): return utc_from_timestamp(in_seconds) return None + @property + def expires_at_utc(self): + # type: () -> Optional[datetime.datetime] + """ + The UTC datetime at which the message is marked for removal and no longer available for retrieval + from the entity due to expiration. Expiry is controlled by the `Message.time_to_live` property. + This property is computed from `Message.enqueued_time_utc` + `Message.time_to_live`. + + :rtype: ~datetime.datetime + """ + if self.enqueued_time_utc and self.time_to_live: + return self.enqueued_time_utc + self.time_to_live + return None + @property def sequence_number(self): # type: () -> Optional[int] """ + The unique number assigned to a message by Service Bus. The sequence number is a unique 64-bit integer + assigned to a message as it is accepted and stored by the broker and functions as its true identifier. + For partitioned entities, the topmost 16 bits reflect the partition identifier. + Sequence numbers monotonically increase. They roll over to 0 when the 48-64 bit range is exhausted. :rtype: int """ @@ -454,89 +713,25 @@ class ReceivedMessageBase(PeekMessage): def __init__(self, message, mode=ReceiveSettleMode.PeekLock, **kwargs): super(ReceivedMessageBase, self).__init__(message=message) self._settled = (mode == ReceiveSettleMode.ReceiveAndDelete) + self._received_timestamp_utc = utc_now() self._is_deferred_message = kwargs.get("is_deferred_message", False) self.auto_renew_error = None self._receiver = None # type: ignore self._expiry = None - @property - def settled(self): - # type: () -> bool - """Whether the message has been settled. - - This will aways be `True` for a message received using ReceiveAndDelete mode, - otherwise it will be `False` until the message is completed or otherwise settled. - - :rtype: bool - """ - return self._settled - - @property - def expired(self): - # type: () -> bool - """ - - :rtype: bool - """ - try: - if self._receiver.session: # pylint: disable=protected-access - raise TypeError("Session messages do not expire. Please use the Session expiry instead.") - except AttributeError: # Is not a session receiver - pass - if self.locked_until_utc and self.locked_until_utc <= utc_now(): - return True - return False - - @property - def locked_until_utc(self): - # type: () -> Optional[datetime.datetime] - """ - - :rtype: datetime.datetime - """ - try: - if self.settled or self._receiver.session: # pylint: disable=protected-access - return None - except AttributeError: # not settled, and isn't session receiver. - pass - if self._expiry: - return self._expiry - if self.message.annotations and _X_OPT_LOCKED_UNTIL in self.message.annotations: - expiry_in_seconds = self.message.annotations[_X_OPT_LOCKED_UNTIL]/1000 - self._expiry = utc_from_timestamp(expiry_in_seconds) - return self._expiry - - @property - def lock_token(self): - # type: () -> Optional[Union[uuid.UUID, str]] - """ - - :rtype: ~uuid.UUID or str - """ - if self.settled: - return None - - if self.message.delivery_tag: - return uuid.UUID(bytes_le=self.message.delivery_tag) - - delivery_annotations = self.message.delivery_annotations - if delivery_annotations: - return delivery_annotations.get(_X_OPT_LOCK_TOKEN) - return None - def _check_live(self, action): # pylint: disable=no-member if not self._receiver or not self._receiver._running: # pylint: disable=protected-access raise MessageSettleFailed(action, "Orphan message had no open connection.") - if self.settled: + if self._settled: raise MessageAlreadySettled(action) try: - if self.expired: + if self._lock_expired: raise MessageLockExpired(inner_exception=self.auto_renew_error) except TypeError: pass try: - if self._receiver.session.expired: + if self._receiver.session._lock_expired: # pylint: disable=protected-access raise SessionLockExpired(inner_exception=self._receiver.session.auto_renew_error) except AttributeError: pass @@ -594,6 +789,75 @@ def _settle_via_receiver_link(self, settle_operation, dead_letter_reason=None, d return functools.partial(self.message.modify, True, True) raise ValueError("Unsupported settle operation type: {}".format(settle_operation)) + @property + def _lock_expired(self): + # type: () -> bool + """ + Whether the lock on the message has expired. + + :rtype: bool + """ + try: + if self._receiver.session: # pylint: disable=protected-access + raise TypeError("Session messages do not expire. Please use the Session expiry instead.") + except AttributeError: # Is not a session receiver + pass + if self.locked_until_utc and self.locked_until_utc <= utc_now(): + return True + return False + + @property + def lock_token(self): + # type: () -> Optional[Union[uuid.UUID, str]] + """ + The lock token for the current message serving as a reference to the lock that + is being held by the broker in PeekLock mode. + + :rtype: ~uuid.UUID or str + """ + if self._settled: + return None + + if self.message.delivery_tag: + return uuid.UUID(bytes_le=self.message.delivery_tag) + + delivery_annotations = self.message.delivery_annotations + if delivery_annotations: + return delivery_annotations.get(_X_OPT_LOCK_TOKEN) + return None + + @property + def locked_until_utc(self): + # type: () -> Optional[datetime.datetime] + """ + The UTC datetime until which the message will be locked in the queue/subscription. + When the lock expires, delivery count of hte message is incremented and the message + is again available for retrieval. + + :rtype: datetime.datetime + """ + try: + if self._settled or self._receiver.session: # pylint: disable=protected-access + return None + except AttributeError: # not settled, and isn't session receiver. + pass + if self._expiry: + return self._expiry + if self.message.annotations and _X_OPT_LOCKED_UNTIL in self.message.annotations: + expiry_in_seconds = self.message.annotations[_X_OPT_LOCKED_UNTIL]/1000 + self._expiry = utc_from_timestamp(expiry_in_seconds) + return self._expiry + + @property + def settled(self): + # type: () -> bool + """Whether the message has been settled. + This will aways be `True` for a message received using ReceiveAndDelete mode, + otherwise it will be `False` until the message is completed or otherwise settled. + :rtype: bool + """ + return self._settled + class ReceivedMessage(ReceivedMessageBase): def _settle_message( diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_common/receiver_mixins.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_common/receiver_mixins.py index 842160c2a79b..f879ac5a8fd4 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_common/receiver_mixins.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_common/receiver_mixins.py @@ -90,7 +90,7 @@ def _on_attach(self, source, target, properties, error): # pylint: disable=unus self._session._session_id = self._session_id def _check_live(self): - if self._session and self._session.expired: + if self._session and self._session._lock_expired: # pylint: disable=protected-access raise SessionLockExpired(inner_exception=self._session.auto_renew_error) def _populate_session_attributes(self, **kwargs): diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_common/utils.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_common/utils.py index 11ee8e0292b9..e6d047e8ad37 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_common/utils.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_common/utils.py @@ -104,7 +104,7 @@ def create_properties(): def renewable_start_time(renewable): try: - return renewable.received_timestamp_utc + return renewable._received_timestamp_utc # pylint: disable=protected-access except AttributeError: pass try: @@ -205,9 +205,9 @@ def __exit__(self, *args): def _renewable(self, renewable): if self._shutdown.is_set(): return False - if hasattr(renewable, 'settled') and renewable.settled: + if hasattr(renewable, '_settled') and renewable._settled: # pylint: disable=protected-access return False - if renewable.expired: + if renewable._lock_expired: # pylint: disable=protected-access return False return True diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_sender.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_sender.py index 96d5442d741b..f5714bd8a1ae 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_sender.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_sender.py @@ -70,9 +70,9 @@ def _build_schedule_request(cls, schedule_time_utc, *messages): " Received instead: {}".format(message.__class__.__name__)) message.scheduled_enqueue_time_utc = schedule_time_utc message_data = {} - message_data[MGMT_REQUEST_MESSAGE_ID] = message.properties.message_id - if message.properties.group_id: - message_data[MGMT_REQUEST_SESSION_ID] = message.properties.group_id + message_data[MGMT_REQUEST_MESSAGE_ID] = message.message_id + if message.session_id: + message_data[MGMT_REQUEST_SESSION_ID] = message.session_id if message.partition_key: message_data[MGMT_REQUEST_PARTITION_KEY] = message.partition_key if message.via_partition_key: diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_session.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_session.py index c8b254eccefe..1e991efcb85b 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_session.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_session.py @@ -37,6 +37,19 @@ def __init__(self, session_id, receiver, encoding="UTF-8"): self._locked_until_utc = None # type: Optional[datetime.datetime] self.auto_renew_error = None + def _check_live(self): + if self._lock_expired: + raise SessionLockExpired(inner_exception=self.auto_renew_error) + + @property + def _lock_expired(self): + # type: () -> bool + """Whether the receivers lock on a particular session has expired. + + :rtype: bool + """ + return bool(self._locked_until_utc and self._locked_until_utc <= utc_now()) + @property def session_id(self): # type: () -> str @@ -47,15 +60,6 @@ def session_id(self): """ return self._session_id - @property - def expired(self): - # type: () -> bool - """Whether the receivers lock on a particular session has expired. - - :rtype: bool - """ - return bool(self._locked_until_utc and self._locked_until_utc <= utc_now()) - @property def locked_until_utc(self): # type: () -> Optional[datetime.datetime] @@ -65,10 +69,6 @@ def locked_until_utc(self): """ return self._locked_until_utc - def _check_live(self): - if self.expired: - raise SessionLockExpired(inner_exception=self.auto_renew_error) - class ServiceBusSession(BaseSession): """ diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_async_utils.py b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_async_utils.py index b1f1050d1754..b963ad2394db 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_async_utils.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_async_utils.py @@ -118,9 +118,9 @@ async def __aexit__(self, *args): def _renewable(self, renewable): if self._shutdown.is_set(): return False - if hasattr(renewable, 'settled') and renewable.settled: + if hasattr(renewable, '_settled') and renewable._settled: # pylint: disable=protected-access return False - if renewable.expired: + if renewable._lock_expired: # pylint: disable=protected-access return False return True diff --git a/sdk/servicebus/azure-servicebus/samples/async_samples/session_pool_receive_async.py b/sdk/servicebus/azure-servicebus/samples/async_samples/session_pool_receive_async.py index 9dca5337a921..043e4ccf9a28 100644 --- a/sdk/servicebus/azure-servicebus/samples/async_samples/session_pool_receive_async.py +++ b/sdk/servicebus/azure-servicebus/samples/async_samples/session_pool_receive_async.py @@ -27,10 +27,9 @@ async def message_processing(servicebus_client, queue_name): await receiver.session.set_session_state("OPEN") async for message in receiver: print("Message: {}".format(message)) - print("Time to live: {}".format(message.header.time_to_live)) + print("Time to live: {}".format(message.time_to_live)) print("Sequence number: {}".format(message.sequence_number)) - print("Enqueue Sequence number: {}".format(message.enqueue_sequence_number)) - print("Partition ID: {}".format(message.partition_id)) + print("Enqueue Sequence number: {}".format(message.enqueued_sequence_number)) print("Partition Key: {}".format(message.partition_key)) print("Locked until: {}".format(message.locked_until_utc)) print("Lock Token: {}".format(message.lock_token)) diff --git a/sdk/servicebus/azure-servicebus/samples/sync_samples/sample_code_servicebus.py b/sdk/servicebus/azure-servicebus/samples/sync_samples/sample_code_servicebus.py index 19df1c3ff818..ffa3a68f7f78 100644 --- a/sdk/servicebus/azure-servicebus/samples/sync_samples/sample_code_servicebus.py +++ b/sdk/servicebus/azure-servicebus/samples/sync_samples/sample_code_servicebus.py @@ -199,11 +199,14 @@ def example_send_and_receive_sync(): # [END create_batch_sync] # [START send_complex_message] - message = Message("Hello World!!") - message.session_id = "MySessionID" - message.partition_key = "UsingSpecificPartition" - message.user_properties = {'data': 'custom_data'} - message.time_to_live = datetime.timedelta(seconds=30) + message = Message( + "Hello World!!", + session_id="MySessionID", + partition_key="UsingSpecificPartition", + user_properties={'data': 'custom_data'}, + time_to_live=datetime.timedelta(seconds=30), + label='MyLabel' + ) # [END send_complex_message] # [START peek_messages_sync] @@ -239,13 +242,11 @@ def example_send_and_receive_sync(): print("Receiving: {}".format(message)) print("Time to live: {}".format(message.time_to_live)) print("Sequence number: {}".format(message.sequence_number)) - print("Enqueue Sequence numger: {}".format(message.enqueue_sequence_number)) - print("Partition ID: {}".format(message.partition_id)) + print("Enqueued Sequence numger: {}".format(message.enqueued_sequence_number)) print("Partition Key: {}".format(message.partition_key)) - print("User Properties: {}".format(message.user_properties)) - print("Annotations: {}".format(message.annotations)) - print("Delivery count: {}".format(message.header.delivery_count)) - print("Message ID: {}".format(message.properties.message_id)) + print("Properties: {}".format(message.properties)) + print("Delivery count: {}".format(message.delivery_count)) + print("Message ID: {}".format(message.message_id)) print("Locked until: {}".format(message.locked_until_utc)) print("Lock Token: {}".format(message.lock_token)) print("Enqueued time: {}".format(message.enqueued_time_utc)) diff --git a/sdk/servicebus/azure-servicebus/samples/sync_samples/session_pool_receive.py b/sdk/servicebus/azure-servicebus/samples/sync_samples/session_pool_receive.py index e64705189aa2..26ddcb75cb72 100644 --- a/sdk/servicebus/azure-servicebus/samples/sync_samples/session_pool_receive.py +++ b/sdk/servicebus/azure-servicebus/samples/sync_samples/session_pool_receive.py @@ -26,10 +26,9 @@ def message_processing(sb_client, queue_name, messages): for message in receiver: messages.append(message) print("Message: {}".format(message)) - print("Time to live: {}".format(message.header.time_to_live)) + print("Time to live: {}".format(message.time_to_live)) print("Sequence number: {}".format(message.sequence_number)) - print("Enqueue Sequence number: {}".format(message.enqueue_sequence_number)) - print("Partition ID: {}".format(message.partition_id)) + print("Enqueue Sequence number: {}".format(message.enqueued_sequence_number)) print("Partition Key: {}".format(message.partition_key)) print("Locked until: {}".format(message.locked_until_utc)) print("Lock Token: {}".format(message.lock_token)) diff --git a/sdk/servicebus/azure-servicebus/tests/async_tests/test_queues_async.py b/sdk/servicebus/azure-servicebus/tests/async_tests/test_queues_async.py index c4e05ea3675a..3a0968ab5368 100644 --- a/sdk/servicebus/azure-servicebus/tests/async_tests/test_queues_async.py +++ b/sdk/servicebus/azure-servicebus/tests/async_tests/test_queues_async.py @@ -51,7 +51,6 @@ async def test_async_queue_by_queue_client_conn_str_receive_handler_peeklock(sel async with sb_client.get_queue_sender(servicebus_queue.name) as sender: for i in range(10): message = Message("Handler message no. {}".format(i)) - message.enqueue_sequence_number = i await sender.send_messages(message) with pytest.raises(ServiceBusConnectionError): @@ -129,7 +128,7 @@ async def test_github_issue_6178_async(self, servicebus_namespace_connection_str _logger.debug(message) _logger.debug(message.sequence_number) _logger.debug(message.enqueued_time_utc) - _logger.debug(message.expired) + _logger.debug(message._lock_expired) await message.complete() await asyncio.sleep(40) @@ -146,7 +145,6 @@ async def test_async_queue_by_queue_client_conn_str_receive_handler_receiveandde async with sb_client.get_queue_sender(servicebus_queue.name) as sender: for i in range(10): message = Message("Handler message no. {}".format(i)) - message.enqueue_sequence_number = i await sender.send_messages(message) messages = [] @@ -252,11 +250,11 @@ async def test_async_queue_by_servicebus_conn_str_client_iter_messages_with_aban count = 0 async for message in receiver: print_message(_logger, message) - if not message.header.delivery_count: + if not message.delivery_count: count += 1 await message.abandon() else: - assert message.header.delivery_count == 1 + assert message.delivery_count == 1 await message.complete() assert count == 10 @@ -407,8 +405,10 @@ async def test_async_queue_by_servicebus_client_iter_messages_with_retrieve_defe async for message in receiver: count += 1 print_message(_logger, message) - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' await message.complete() assert count == 10 @@ -521,8 +521,10 @@ async def test_async_queue_by_servicebus_client_receive_batch_with_deadletter(se async for message in dl_receiver: await message.complete() count += 1 - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' assert count == 10 @pytest.mark.liveTest @@ -560,8 +562,10 @@ async def test_async_queue_by_servicebus_client_receive_batch_with_retrieve_dead count = 0 async for message in receiver: print_message(_logger, message) - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' await message.complete() count += 1 assert count == 10 @@ -665,7 +669,7 @@ async def test_async_queue_by_servicebus_client_renew_message_locks(self, servic try: with pytest.raises(AttributeError): - assert not message.expired + assert not message._lock_expired for m in messages: time.sleep(5) initial_expiry = m.locked_until_utc @@ -698,29 +702,29 @@ async def test_async_queue_by_queue_client_conn_str_receive_handler_with_autoloc async for message in receiver: if not messages: messages.append(message) - assert not message.expired + assert not message._lock_expired renewer.register(message, timeout=60) print("Registered lock renew thread", message.locked_until_utc, utc_now()) await asyncio.sleep(60) print("Finished first sleep", message.locked_until_utc) - assert not message.expired + assert not message._lock_expired await asyncio.sleep(15) #generate autolockrenewtimeout error by going one iteration past. sleep_until_expired(message) print("Finished second sleep", message.locked_until_utc, utc_now()) - assert message.expired + assert message._lock_expired try: await message.complete() raise AssertionError("Didn't raise MessageLockExpired") except MessageLockExpired as e: assert isinstance(e.inner_exception, AutoLockRenewTimeout) else: - if message.expired: + if message._lock_expired: print("Remaining messages", message.locked_until_utc, utc_now()) - assert message.expired + assert message._lock_expired with pytest.raises(MessageLockExpired): await message.complete() else: - assert message.header.delivery_count >= 1 + assert message.delivery_count >= 1 print("Remaining messages", message.locked_until_utc, utc_now()) messages.append(message) await message.complete() @@ -789,14 +793,14 @@ async def test_async_queue_message_duplicate_detection(self, servicebus_namespac async with sb_client.get_queue_sender(servicebus_queue.name) as sender: for i in range(5): message = Message(str(i)) - message.properties.message_id = message_id + message.message_id = message_id await sender.send_messages(message) async with sb_client.get_queue_receiver(servicebus_queue.name, idle_timeout=5) as receiver: count = 0 async for message in receiver: print_message(_logger, message) - assert message.properties.message_id == message_id + assert message.message_id == message_id await message.complete() count += 1 assert count == 1 @@ -840,7 +844,7 @@ async def test_async_queue_message_expiry(self, servicebus_namespace_connection_ messages = await receiver.receive_messages(max_wait_time=10) assert len(messages) == 1 time.sleep(60) - assert messages[0].expired + assert messages[0]._lock_expired with pytest.raises(MessageLockExpired): await messages[0].complete() with pytest.raises(MessageLockExpired): @@ -850,7 +854,7 @@ async def test_async_queue_message_expiry(self, servicebus_namespace_connection_ messages = await receiver.receive_messages(max_wait_time=30) assert len(messages) == 1 print_message(_logger, messages[0]) - assert messages[0].header.delivery_count > 0 + assert messages[0].delivery_count > 0 await messages[0].complete() @pytest.mark.liveTest @@ -875,7 +879,7 @@ async def test_async_queue_message_lock_renew(self, servicebus_namespace_connect time.sleep(15) await messages[0].renew_lock() time.sleep(15) - assert not messages[0].expired + assert not messages[0]._lock_expired await messages[0].complete() async with sb_client.get_queue_receiver(servicebus_queue.name) as receiver: @@ -960,7 +964,7 @@ async def test_async_queue_schedule_message(self, servicebus_namespace_connectio content = str(uuid.uuid4()) message_id = uuid.uuid4() message = Message(content) - message.properties.message_id = message_id + message.message_id = message_id message.scheduled_enqueue_time_utc = enqueue_time await sender.send_messages(message) @@ -969,7 +973,7 @@ async def test_async_queue_schedule_message(self, servicebus_namespace_connectio try: data = str(messages[0]) assert data == content - assert messages[0].properties.message_id == message_id + assert messages[0].message_id == message_id assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 1 @@ -994,10 +998,10 @@ async def test_async_queue_schedule_multiple_messages(self, servicebus_namespace content = str(uuid.uuid4()) message_id_a = uuid.uuid4() message_a = Message(content) - message_a.properties.message_id = message_id_a + message_a.message_id = message_id_a message_id_b = uuid.uuid4() message_b = Message(content) - message_b.properties.message_id = message_id_b + message_b.message_id = message_id_b tokens = await sender.schedule_messages([message_a, message_b], enqueue_time) assert len(tokens) == 2 @@ -1009,7 +1013,7 @@ async def test_async_queue_schedule_multiple_messages(self, servicebus_namespace try: data = str(messages[0]) assert data == content - assert messages[0].properties.message_id in (message_id_a, message_id_b) + assert messages[0].message_id in (message_id_a, message_id_b) assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 2 @@ -1107,8 +1111,8 @@ async def test_queue_message_settle_through_mgmt_link_due_to_broken_receiver_lin async def test_async_queue_mock_no_reusing_auto_lock_renew(self): class MockReceivedMessage: def __init__(self): - self.received_timestamp_utc = utc_now() - self.locked_until_utc = self.received_timestamp_utc + timedelta(seconds=10) + self._received_timestamp_utc = utc_now() + self.locked_until_utc = self._received_timestamp_utc + timedelta(seconds=10) async def renew_lock(self): self.locked_until_utc = self.locked_until_utc + timedelta(seconds=10) diff --git a/sdk/servicebus/azure-servicebus/tests/async_tests/test_sessions_async.py b/sdk/servicebus/azure-servicebus/tests/async_tests/test_sessions_async.py index 5645fa58e5a5..450ec473f338 100644 --- a/sdk/servicebus/azure-servicebus/tests/async_tests/test_sessions_async.py +++ b/sdk/servicebus/azure-servicebus/tests/async_tests/test_sessions_async.py @@ -255,8 +255,10 @@ async def test_async_session_by_servicebus_client_iter_messages_with_retrieve_de async for message in receiver: count += 1 print_message(_logger, message) - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' await message.complete() assert count == 10 @@ -355,8 +357,10 @@ async def test_async_session_by_servicebus_client_fetch_next_with_retrieve_deadl count = 0 async for message in session: print_message(_logger, message) - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' await message.complete() count += 1 assert count == 10 @@ -447,7 +451,7 @@ async def test_async_session_by_servicebus_client_renew_client_locks(self, servi try: for m in messages: with pytest.raises(TypeError): - expired = m.expired + expired = m._lock_expired assert m.locked_until_utc is None assert m.lock_token is not None time.sleep(5) @@ -487,9 +491,9 @@ async def test_async_session_by_conn_str_receive_handler_with_autolockrenew(self if not messages: await asyncio.sleep(45) print("First sleep {}".format(session.session.locked_until_utc - utc_now())) - assert not session.session.expired + assert not session.session._lock_expired with pytest.raises(TypeError): - message.expired + message._lock_expired assert message.locked_until_utc is None with pytest.raises(TypeError): await message.renew_lock() @@ -500,7 +504,7 @@ async def test_async_session_by_conn_str_receive_handler_with_autolockrenew(self elif len(messages) == 1: await asyncio.sleep(45) print("Second sleep {}".format(session.session.locked_until_utc - utc_now())) - assert session.session.expired + assert session.session._lock_expired assert isinstance(session.session.auto_renew_error, AutoLockRenewTimeout) try: await message.complete() @@ -559,10 +563,10 @@ async def test_async_session_message_expiry(self, servicebus_namespace_connectio print_message(_logger, messages[0]) await asyncio.sleep(60) #TODO: Was 30, but then lock isn't expired. with pytest.raises(TypeError): - messages[0].expired + messages[0]._lock_expired with pytest.raises(TypeError): await messages[0].renew_lock() - assert receiver.session.expired + assert receiver.session._lock_expired with pytest.raises(SessionLockExpired): await messages[0].complete() with pytest.raises(SessionLockExpired): @@ -572,7 +576,7 @@ async def test_async_session_message_expiry(self, servicebus_namespace_connectio messages = await receiver.receive_messages(max_wait_time=30) assert len(messages) == 1 print_message(_logger, messages[0]) - #assert messages[0].header.delivery_count # TODO confirm this with service + assert messages[0].delivery_count await messages[0].complete() @@ -591,7 +595,7 @@ async def test_async_session_schedule_message(self, servicebus_namespace_connect content = str(uuid.uuid4()) message_id = uuid.uuid4() message = Message(content, session_id=session_id) - message.properties.message_id = message_id + message.message_id = message_id message.scheduled_enqueue_time_utc = enqueue_time await sender.send_messages(message) @@ -604,7 +608,7 @@ async def test_async_session_schedule_message(self, servicebus_namespace_connect if messages: data = str(messages[0]) assert data == content - assert messages[0].properties.message_id == message_id + assert messages[0].message_id == message_id assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 1 @@ -629,10 +633,10 @@ async def test_async_session_schedule_multiple_messages(self, servicebus_namespa content = str(uuid.uuid4()) message_id_a = uuid.uuid4() message_a = Message(content, session_id=session_id) - message_a.properties.message_id = message_id_a + message_a.message_id = message_id_a message_id_b = uuid.uuid4() message_b = Message(content, session_id=session_id) - message_b.properties.message_id = message_id_b + message_b.message_id = message_id_b tokens = await sender.schedule_messages([message_a, message_b], enqueue_time) assert len(tokens) == 2 @@ -644,7 +648,7 @@ async def test_async_session_schedule_multiple_messages(self, servicebus_namespa if messages: data = str(messages[0]) assert data == content - assert messages[0].properties.message_id in (message_id_a, message_id_b) + assert messages[0].message_id in (message_id_a, message_id_b) assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 2 @@ -707,7 +711,7 @@ async def test_async_session_get_set_state_with_receiver(self, servicebus_namesp await session.session.set_session_state("first_state") count = 0 async for m in session: - assert m.properties.group_id == session_id.encode('utf-8') + assert m.session_id == session_id count += 1 await session.session.get_session_state() assert count == 3 diff --git a/sdk/servicebus/azure-servicebus/tests/async_tests/test_subscriptions_async.py b/sdk/servicebus/azure-servicebus/tests/async_tests/test_subscriptions_async.py index 70bff4a022f6..70dcb43b4e0a 100644 --- a/sdk/servicebus/azure-servicebus/tests/async_tests/test_subscriptions_async.py +++ b/sdk/servicebus/azure-servicebus/tests/async_tests/test_subscriptions_async.py @@ -148,6 +148,8 @@ async def test_topic_by_servicebus_client_receive_batch_with_deadletter(self, se async for message in dl_receiver: await message.complete() count += 1 - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' assert count == 10 diff --git a/sdk/servicebus/azure-servicebus/tests/test_queues.py b/sdk/servicebus/azure-servicebus/tests/test_queues.py index f13062f01c0e..1185bfb5136c 100644 --- a/sdk/servicebus/azure-servicebus/tests/test_queues.py +++ b/sdk/servicebus/azure-servicebus/tests/test_queues.py @@ -11,10 +11,18 @@ import time import uuid from datetime import datetime, timedelta +import calendar +import uamqp from azure.servicebus import ServiceBusClient, AutoLockRenew, TransportType from azure.servicebus._common.message import Message, PeekMessage, ReceivedMessage, BatchMessage -from azure.servicebus._common.constants import ReceiveSettleMode, _X_OPT_LOCK_TOKEN +from azure.servicebus._common.constants import ( + ReceiveSettleMode, + _X_OPT_LOCK_TOKEN, + _X_OPT_PARTITION_KEY, + _X_OPT_VIA_PARTITION_KEY, + _X_OPT_SCHEDULED_ENQUEUE_TIME +) from azure.servicebus._common.utils import utc_now from azure.servicebus.exceptions import ( ServiceBusConnectionError, @@ -82,7 +90,7 @@ def test_github_issue_6178(self, servicebus_namespace_connection_string, service _logger.debug(message) _logger.debug(message.sequence_number) _logger.debug(message.enqueued_time_utc) - _logger.debug(message.expired) + _logger.debug(message._lock_expired) message.complete() time.sleep(40) @@ -99,16 +107,41 @@ def test_queue_by_queue_client_conn_str_receive_handler_peeklock(self, servicebu with sb_client.get_queue_sender(servicebus_queue.name) as sender: for i in range(10): message = Message("Handler message no. {}".format(i)) - message.enqueue_sequence_number = i + message.properties = {'key': 'value'} + message.label = 'label' + message.content_type = 'application/text' + message.correlation_id = 'cid' + message.message_id = str(i) + message.partition_key = 'pk' + message.via_partition_key = 'via_pk' + message.to = 'to' + message.reply_to = 'reply_to' sender.send_messages(message) receiver = sb_client.get_queue_receiver(servicebus_queue.name, idle_timeout=5) count = 0 for message in receiver: print_message(_logger, message) + assert message.delivery_count == 0 + assert message.properties + assert message.properties[b'key'] == b'value' + assert message.label == 'label' + assert message.content_type == 'application/text' + assert message.correlation_id == 'cid' + assert message.message_id == str(count) + assert message.partition_key == 'pk' + assert message.via_partition_key == 'via_pk' + assert message.to == 'to' + assert message.reply_to == 'reply_to' + assert message.sequence_number + assert message.enqueued_time_utc assert message.message.delivery_tag is not None assert message.lock_token == message.message.delivery_annotations.get(_X_OPT_LOCK_TOKEN) assert message.lock_token == uuid.UUID(bytes_le=message.message.delivery_tag) + assert not message.scheduled_enqueue_time_utc + assert not message.time_to_live + assert not message.session_id + assert not message.reply_to_session_id count += 1 message.complete() @@ -127,6 +160,15 @@ def test_queue_by_queue_client_send_multiple_messages(self, servicebus_namespace messages = [] for i in range(10): message = Message("Handler message no. {}".format(i)) + message.partition_key = 'pkey' + message.via_partition_key = 'vpkey' + message.time_to_live = timedelta(seconds=60) + message.scheduled_enqueue_time_utc = utc_now() + timedelta(seconds=60) + message.partition_key = None + message.via_partition_key = None + message.time_to_live = None + message.scheduled_enqueue_time_utc = None + message.session_id = None messages.append(message) sender.send_messages(messages) @@ -134,6 +176,19 @@ def test_queue_by_queue_client_send_multiple_messages(self, servicebus_namespace count = 0 for message in receiver: print_message(_logger, message) + assert message.delivery_count == 0 + assert not message.properties + assert not message.label + assert not message.content_type + assert not message.correlation_id + assert not message.partition_key + assert not message.via_partition_key + assert not message.to + assert not message.reply_to + assert not message.scheduled_enqueue_time_utc + assert not message.time_to_live + assert not message.session_id + assert not message.reply_to_session_id count += 1 message.complete() @@ -152,7 +207,6 @@ def test_queue_by_queue_client_conn_str_receive_handler_receiveanddelete(self, s with sb_client.get_queue_sender(servicebus_queue.name) as sender: for i in range(10): message = Message("Handler message no. {}".format(i)) - message.enqueue_sequence_number = i sender.send_messages(message) messages = [] @@ -160,6 +214,18 @@ def test_queue_by_queue_client_conn_str_receive_handler_receiveanddelete(self, s mode=ReceiveSettleMode.ReceiveAndDelete, idle_timeout=5) as receiver: for message in receiver: + assert not message.properties + assert not message.label + assert not message.content_type + assert not message.correlation_id + assert not message.partition_key + assert not message.via_partition_key + assert not message.to + assert not message.reply_to + assert not message.scheduled_enqueue_time_utc + assert not message.time_to_live + assert not message.session_id + assert not message.reply_to_session_id messages.append(message) with pytest.raises(MessageAlreadySettled): message.complete() @@ -269,11 +335,11 @@ def test_queue_by_servicebus_conn_str_client_iter_messages_with_abandon(self, se count = 0 for message in receiver: print_message(_logger, message) - if not message.header.delivery_count: + if not message.delivery_count: count += 1 message.abandon() else: - assert message.header.delivery_count == 1 + assert message.delivery_count == 1 message.complete() assert count == 10 @@ -446,8 +512,10 @@ def test_queue_by_servicebus_client_iter_messages_with_retrieve_deferred_receive for message in receiver: count += 1 print_message(_logger, message) - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' message.complete() assert count == 10 @@ -570,8 +638,10 @@ def test_queue_by_servicebus_client_receive_batch_with_deadletter(self, serviceb for message in dl_receiver: message.complete() count += 1 - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' assert count == 10 @pytest.mark.liveTest @@ -614,8 +684,10 @@ def test_queue_by_servicebus_client_receive_batch_with_retrieve_deadletter(self, count = 0 for message in dl_receiver: print_message(_logger, message) - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' message.complete() count += 1 assert count == 10 @@ -757,7 +829,7 @@ def test_queue_by_servicebus_client_renew_message_locks(self, servicebus_namespa try: for m in messages: - assert not m.expired + assert not m._lock_expired time.sleep(5) initial_expiry = m.locked_until_utc m.renew_lock() @@ -794,29 +866,29 @@ def test_queue_by_queue_client_conn_str_receive_handler_with_autolockrenew(self, for message in receiver: if not messages: messages.append(message) - assert not message.expired + assert not message._lock_expired renewer.register(message, timeout=60) print("Registered lock renew thread", message.locked_until_utc, utc_now()) time.sleep(60) print("Finished first sleep", message.locked_until_utc) - assert not message.expired + assert not message._lock_expired time.sleep(15) #generate autolockrenewtimeout error by going one iteration past. sleep_until_expired(message) print("Finished second sleep", message.locked_until_utc, utc_now()) - assert message.expired + assert message._lock_expired try: message.complete() raise AssertionError("Didn't raise MessageLockExpired") except MessageLockExpired as e: assert isinstance(e.inner_exception, AutoLockRenewTimeout) else: - if message.expired: + if message._lock_expired: print("Remaining messages", message.locked_until_utc, utc_now()) - assert message.expired + assert message._lock_expired with pytest.raises(MessageLockExpired): message.complete() else: - assert message.header.delivery_count >= 1 + assert message.delivery_count >= 1 print("Remaining messages", message.locked_until_utc, utc_now()) messages.append(message) message.complete() @@ -871,7 +943,7 @@ def test_queue_message_duplicate_detection(self, servicebus_namespace_connection with sb_client.get_queue_sender(servicebus_queue.name) as sender: for i in range(5): message = Message(str(i)) - message.properties.message_id = message_id + message.message_id = message_id sender.send_messages(message) with sb_client.get_queue_receiver(servicebus_queue.name, @@ -879,7 +951,7 @@ def test_queue_message_duplicate_detection(self, servicebus_namespace_connection count = 0 for message in receiver: print_message(_logger, message) - assert message.properties.message_id == message_id + assert message.message_id == message_id message.complete() count += 1 assert count == 1 @@ -927,7 +999,7 @@ def test_queue_message_expiry(self, servicebus_namespace_connection_string, serv messages = receiver.receive_messages(max_wait_time=10) assert len(messages) == 1 time.sleep((messages[0].locked_until_utc - utc_now()).total_seconds()+1) - assert messages[0].expired + assert messages[0]._lock_expired with pytest.raises(MessageLockExpired): messages[0].complete() with pytest.raises(MessageLockExpired): @@ -937,7 +1009,7 @@ def test_queue_message_expiry(self, servicebus_namespace_connection_string, serv messages = receiver.receive_messages(max_wait_time=30) assert len(messages) == 1 print_message(_logger, messages[0]) - assert messages[0].header.delivery_count > 0 + assert messages[0].delivery_count > 0 messages[0].complete() @@ -964,7 +1036,7 @@ def test_queue_message_lock_renew(self, servicebus_namespace_connection_string, time.sleep(15) messages[0].renew_lock() time.sleep(15) - assert not messages[0].expired + assert not messages[0]._lock_expired messages[0].complete() with sb_client.get_queue_receiver(servicebus_queue.name) as receiver: @@ -1024,9 +1096,20 @@ def test_queue_message_batch(self, servicebus_namespace_connection_string, servi def message_content(): for i in range(5): - yield Message("Message no. {}".format(i)) - - + message = Message("Message no. {}".format(i)) + message.properties = {'key': 'value'} + message.label = 'label' + message.content_type = 'application/text' + message.correlation_id = 'cid' + message.message_id = str(i) + message.partition_key = 'pk' + message.via_partition_key = 'via_pk' + message.to = 'to' + message.reply_to = 'reply_to' + message.time_to_live = timedelta(seconds=60) + + yield message + with sb_client.get_queue_sender(servicebus_queue.name) as sender: message = BatchMessage() for each in message_content(): @@ -1041,9 +1124,25 @@ def message_content(): messages.extend(recv) assert len(messages) == 5 - for m in messages: - print_message(_logger, m) - m.complete() + count = 0 + for message in messages: + assert message.delivery_count == 0 + assert message.properties + assert message.properties[b'key'] == b'value' + assert message.label == 'label' + assert message.content_type == 'application/text' + assert message.correlation_id == 'cid' + assert message.message_id == str(count) + assert message.partition_key == 'pk' + assert message.via_partition_key == 'via_pk' + assert message.to == 'to' + assert message.reply_to == 'reply_to' + assert message.sequence_number + assert message.enqueued_time_utc + assert message.expires_at_utc == (message.enqueued_time_utc + timedelta(seconds=60)) + print_message(_logger, message) + message.complete() + count += 1 @pytest.mark.liveTest @@ -1062,7 +1161,7 @@ def test_queue_schedule_message(self, servicebus_namespace_connection_string, se content = str(uuid.uuid4()) message_id = uuid.uuid4() message = Message(content) - message.properties.message_id = message_id + message.message_id = message_id message.scheduled_enqueue_time_utc = enqueue_time sender.send_messages(message) @@ -1071,7 +1170,7 @@ def test_queue_schedule_message(self, servicebus_namespace_connection_string, se try: data = str(messages[0]) assert data == content - assert messages[0].properties.message_id == message_id + assert messages[0].message_id == message_id assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 1 @@ -1099,11 +1198,21 @@ def test_queue_schedule_multiple_messages(self, servicebus_namespace_connection_ content = str(uuid.uuid4()) message_id_a = uuid.uuid4() message_a = Message(content) - message_a.properties.message_id = message_id_a + message_a.message_id = message_id_a message_id_b = uuid.uuid4() message_b = Message(content) - message_b.properties.message_id = message_id_b - tokens = sender.schedule_messages([message_a, message_b], enqueue_time) + message_b.message_id = message_id_b + message_arry = [message_a, message_b] + for message in message_arry: + message.properties = {'key': 'value'} + message.label = 'label' + message.content_type = 'application/text' + message.correlation_id = 'cid' + message.partition_key = 'pk' + message.via_partition_key = 'via_pk' + message.to = 'to' + message.reply_to = 'reply_to' + tokens = sender.schedule_messages(message_arry, enqueue_time) assert len(tokens) == 2 messages = receiver.receive_messages(max_wait_time=120) @@ -1112,9 +1221,22 @@ def test_queue_schedule_multiple_messages(self, servicebus_namespace_connection_ try: data = str(messages[0]) assert data == content - assert messages[0].properties.message_id in (message_id_a, message_id_b) + assert messages[0].message_id in (message_id_a, message_id_b) assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) + assert messages[0].delivery_count == 0 + assert messages[0].properties + assert messages[0].properties[b'key'] == b'value' + assert messages[0].label == 'label' + assert messages[0].content_type == 'application/text' + assert messages[0].correlation_id == 'cid' + assert messages[0].partition_key == 'pk' + assert messages[0].via_partition_key == 'via_pk' + assert messages[0].to == 'to' + assert messages[0].reply_to == 'reply_to' + assert messages[0].sequence_number + assert messages[0].enqueued_time_utc + assert messages[0].message.delivery_tag is not None assert len(messages) == 2 finally: for m in messages: @@ -1218,8 +1340,8 @@ def test_queue_message_settle_through_mgmt_link_due_to_broken_receiver_link(self def test_queue_mock_no_reusing_auto_lock_renew(self): class MockReceivedMessage: def __init__(self): - self.received_timestamp_utc = utc_now() - self.locked_until_utc = self.received_timestamp_utc + timedelta(seconds=10) + self._received_timestamp_utc = utc_now() + self.locked_until_utc = self._received_timestamp_utc + timedelta(seconds=10) def renew_lock(self): self.locked_until_utc = self.locked_until_utc + timedelta(seconds=10) @@ -1251,6 +1373,91 @@ def renew_lock(self): with pytest.raises(ServiceBusError): auto_lock_renew.register(renewable=MockReceivedMessage()) + def test_queue_message_properties(self): + scheduled_enqueue_time = (utc_now() + timedelta(seconds=20)).replace(microsecond=0) + message = Message( + body='data', + properties={'key': 'value'}, + session_id='sid', + label='label', + content_type='application/text', + correlation_id='cid', + message_id='mid', + partition_key='pk', + via_partition_key='via_pk', + to='to', + reply_to='reply_to', + reply_to_session_id='reply_to_sid', + scheduled_enqueue_time_utc=scheduled_enqueue_time + ) + + assert message.properties + assert message.properties['key'] == 'value' + assert message.label == 'label' + assert message.content_type == 'application/text' + assert message.correlation_id == 'cid' + assert message.message_id == 'mid' + assert message.partition_key == 'pk' + assert message.via_partition_key == 'via_pk' + assert message.to == 'to' + assert message.reply_to == 'reply_to' + assert message.session_id == 'sid' + assert message.reply_to_session_id == 'reply_to_sid' + assert message.scheduled_enqueue_time_utc == scheduled_enqueue_time + + message.partition_key = 'updated' + message.via_partition_key = 'updated' + new_scheduled_time = (utc_now() + timedelta(hours=5)).replace(microsecond=0) + message.scheduled_enqueue_time_utc = new_scheduled_time + assert message.partition_key == 'updated' + assert message.via_partition_key == 'updated' + assert message.scheduled_enqueue_time_utc == new_scheduled_time + + message.partition_key = None + message.via_partition_key = None + message.scheduled_enqueue_time_utc = None + + assert message.partition_key is None + assert message.via_partition_key is None + assert message.scheduled_enqueue_time_utc is None + + try: + timestamp = new_scheduled_time.timestamp() * 1000 + except AttributeError: + timestamp = calendar.timegm(new_scheduled_time.timetuple()) * 1000 + + uamqp_received_message = uamqp.message.Message( + body=b'data', + annotations={ + _X_OPT_PARTITION_KEY: b'r_key', + _X_OPT_VIA_PARTITION_KEY: b'r_via_key', + _X_OPT_SCHEDULED_ENQUEUE_TIME: timestamp, + }, + properties=uamqp.message.MessageProperties() + ) + received_message = ReceivedMessage(uamqp_received_message) + assert received_message.partition_key == 'r_key' + assert received_message.via_partition_key == 'r_via_key' + assert received_message.scheduled_enqueue_time_utc == new_scheduled_time + + new_scheduled_time = utc_now() + timedelta(hours=1, minutes=49, seconds=32) + + received_message.partition_key = 'new_r_key' + received_message.via_partition_key = 'new_r_via_key' + received_message.scheduled_enqueue_time_utc = new_scheduled_time + + assert received_message.partition_key == 'new_r_key' + assert received_message.via_partition_key == 'new_r_via_key' + assert received_message.scheduled_enqueue_time_utc == new_scheduled_time + + received_message.partition_key = None + received_message.via_partition_key = None + received_message.scheduled_enqueue_time_utc = None + + assert message.partition_key is None + assert message.via_partition_key is None + assert message.scheduled_enqueue_time_utc is None + @pytest.mark.liveTest @pytest.mark.live_test_only @CachedResourceGroupPreparer(name_prefix='servicebustest') diff --git a/sdk/servicebus/azure-servicebus/tests/test_sessions.py b/sdk/servicebus/azure-servicebus/tests/test_sessions.py index dba7fcb8165a..d72721d8c182 100644 --- a/sdk/servicebus/azure-servicebus/tests/test_sessions.py +++ b/sdk/servicebus/azure-servicebus/tests/test_sessions.py @@ -53,7 +53,18 @@ def test_session_by_session_client_conn_str_receive_handler_peeklock(self, servi session_id = str(uuid.uuid4()) with sb_client.get_queue_sender(servicebus_queue.name) as sender: for i in range(3): - message = Message("Handler message no. {}".format(i), session_id=session_id) + message = Message("Handler message no. {}".format(i)) + message.session_id = session_id + message.properties = {'key': 'value'} + message.label = 'label' + message.content_type = 'application/text' + message.correlation_id = 'cid' + message.message_id = str(i) + message.partition_key = 'pk' + message.via_partition_key = 'via_pk' + message.to = 'to' + message.reply_to = 'reply_to' + message.reply_to_session_id = 'reply_to_session_id' sender.send_messages(message) with pytest.raises(ServiceBusConnectionError): @@ -63,7 +74,21 @@ def test_session_by_session_client_conn_str_receive_handler_peeklock(self, servi count = 0 for message in session: print_message(_logger, message) + assert message.delivery_count == 0 + assert message.properties + assert message.properties[b'key'] == b'value' + assert message.label == 'label' + assert message.content_type == 'application/text' + assert message.correlation_id == 'cid' + assert message.message_id == str(count) + assert message.partition_key == 'pk' + assert message.via_partition_key == 'via_pk' + assert message.to == 'to' + assert message.reply_to == 'reply_to' + assert message.sequence_number + assert message.enqueued_time_utc assert message.session_id == session_id + assert message.reply_to_session_id == 'reply_to_session_id' count += 1 message.complete() @@ -303,8 +328,10 @@ def test_session_by_servicebus_client_iter_messages_with_retrieve_deferred_recei for message in receiver: count += 1 print_message(_logger, message) - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' message.complete() assert count == 10 @@ -415,8 +442,10 @@ def test_session_by_servicebus_client_receive_with_retrieve_deadletter(self, ser for message in session: print_message(_logger, message) message.complete() - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' count += 1 assert count == 10 @@ -510,7 +539,7 @@ def test_session_by_servicebus_client_renew_client_locks(self, servicebus_namesp try: for m in messages: with pytest.raises(TypeError): - expired = m.expired + expired = m._lock_expired assert m.locked_until_utc is None assert m.lock_token is not None time.sleep(5) @@ -557,9 +586,9 @@ def test_session_by_conn_str_receive_handler_with_autolockrenew(self, servicebus print("Starting first sleep") time.sleep(40) print("First sleep {}".format(receiver.session._locked_until_utc - utc_now())) - assert not receiver.session.expired + assert not receiver.session._lock_expired with pytest.raises(TypeError): - message.expired + message._lock_expired assert message.locked_until_utc is None with pytest.raises(TypeError): message.renew_lock() @@ -572,7 +601,7 @@ def test_session_by_conn_str_receive_handler_with_autolockrenew(self, servicebus time.sleep(40) # ensure renewer expires print("Second sleep {}".format(receiver.session._locked_until_utc - utc_now())) sleep_until_expired(receiver.session) # and then ensure it didn't slip a renew under the wire. - assert receiver.session.expired + assert receiver.session._lock_expired assert isinstance(receiver.session.auto_renew_error, AutoLockRenewTimeout) try: message.complete() @@ -632,11 +661,11 @@ def test_session_message_expiry(self, servicebus_namespace_connection_string, se print_message(_logger, messages[0]) time.sleep(60) with pytest.raises(TypeError): - messages[0].expired + messages[0]._lock_expired with pytest.raises(TypeError): messages[0].renew_lock() #TODO: Bug: Why was this 30s sleep before? compare with T1. - assert receiver.session.expired + assert receiver.session._lock_expired with pytest.raises(SessionLockExpired): messages[0].complete() with pytest.raises(SessionLockExpired): @@ -646,7 +675,7 @@ def test_session_message_expiry(self, servicebus_namespace_connection_string, se messages = receiver.receive_messages(max_wait_time=30) assert len(messages) == 1 print_message(_logger, messages[0]) - #assert messages[0].header.delivery_count # TODO confirm this with service + assert messages[0].delivery_count messages[0].complete() @@ -667,7 +696,7 @@ def test_session_schedule_message(self, servicebus_namespace_connection_string, content = str(uuid.uuid4()) message_id = uuid.uuid4() message = Message(content, session_id=session_id) - message.properties.message_id = message_id + message.message_id = message_id message.scheduled_enqueue_time_utc = enqueue_time sender.send_messages(message) @@ -680,7 +709,7 @@ def test_session_schedule_message(self, servicebus_namespace_connection_string, data = str(messages[0]) assert data == content - assert messages[0].properties.message_id == message_id + assert messages[0].message_id == message_id assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 1 @@ -704,10 +733,10 @@ def test_session_schedule_multiple_messages(self, servicebus_namespace_connectio content = str(uuid.uuid4()) message_id_a = uuid.uuid4() message_a = Message(content, session_id=session_id) - message_a.properties.message_id = message_id_a + message_a.message_id = message_id_a message_id_b = uuid.uuid4() message_b = Message(content, session_id=session_id) - message_b.properties.message_id = message_id_b + message_b.message_id = message_id_b tokens = sender.schedule_messages([message_a, message_b], enqueue_time) assert len(tokens) == 2 @@ -721,7 +750,7 @@ def test_session_schedule_multiple_messages(self, servicebus_namespace_connectio data = str(messages[0]) assert data == content - assert messages[0].properties.message_id in (message_id_a, message_id_b) + assert messages[0].message_id in (message_id_a, message_id_b) assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 2 @@ -778,7 +807,7 @@ def test_session_get_set_state_with_receiver(self, servicebus_namespace_connecti session.session.set_session_state("first_state") count = 0 for m in session: - assert m.properties.group_id == session_id.encode('utf-8') + assert m.session_id == session_id count += 1 session.session.get_session_state() assert count == 3 diff --git a/sdk/servicebus/azure-servicebus/tests/test_subscriptions.py b/sdk/servicebus/azure-servicebus/tests/test_subscriptions.py index 980e813b890a..a58aff4422cd 100644 --- a/sdk/servicebus/azure-servicebus/tests/test_subscriptions.py +++ b/sdk/servicebus/azure-servicebus/tests/test_subscriptions.py @@ -168,6 +168,8 @@ def test_subscription_by_servicebus_client_receive_batch_with_deadletter(self, s for message in dl_receiver: message.complete() count += 1 - assert message.user_properties[b'DeadLetterReason'] == b'Testing reason' - assert message.user_properties[b'DeadLetterErrorDescription'] == b'Testing description' + assert message.dead_letter_reason == 'Testing reason' + assert message.dead_letter_error_description == 'Testing description' + assert message.properties[b'DeadLetterReason'] == b'Testing reason' + assert message.properties[b'DeadLetterErrorDescription'] == b'Testing description' assert count == 10 diff --git a/sdk/servicebus/azure-servicebus/tests/utilities.py b/sdk/servicebus/azure-servicebus/tests/utilities.py index b22b4c4249ca..2d46b00daa29 100644 --- a/sdk/servicebus/azure-servicebus/tests/utilities.py +++ b/sdk/servicebus/azure-servicebus/tests/utilities.py @@ -28,12 +28,10 @@ def print_message(_logger, message): _logger.info("Receiving: {}".format(message)) _logger.debug("Time to live: {}".format(message.time_to_live)) _logger.debug("Sequence number: {}".format(message.sequence_number)) - _logger.debug("Enqueue Sequence numger: {}".format(message.enqueue_sequence_number)) - _logger.debug("Partition ID: {}".format(message.partition_id)) + _logger.debug("Enqueue Sequence numger: {}".format(message.enqueued_sequence_number)) _logger.debug("Partition Key: {}".format(message.partition_key)) - _logger.debug("User Properties: {}".format(message.user_properties)) - _logger.debug("Annotations: {}".format(message.annotations)) - _logger.debug("Delivery count: {}".format(message.header.delivery_count)) + _logger.debug("Properties: {}".format(message.properties)) + _logger.debug("Delivery count: {}".format(message.delivery_count)) try: _logger.debug("Locked until: {}".format(message.locked_until_utc)) _logger.debug("Lock Token: {}".format(message.lock_token))