Skip to content

Commit e2d2006

Browse files
authored
[KeyVault] KV Certificates to test proxy (#24256)
* sync test mods * add in a conftest for certs * sync recordings * minor update to remove method * clean up imports * async recordings * async test to test proxy * clean up imports * PR comments * uncomment out skip * record failing tests * delete old recordings * minor clean up
1 parent de91b99 commit e2d2006

447 files changed

Lines changed: 271233 additions & 221350 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# ------------------------------------
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
# ------------------------------------
5+
6+
import os
7+
8+
from azure.keyvault.certificates import ApiVersion
9+
from azure.keyvault.certificates._shared.client_base import DEFAULT_VERSION
10+
from devtools_testutils import AzureRecordedTestCase, is_live
11+
import pytest
12+
13+
14+
def get_decorator(**kwargs):
15+
"""returns a test decorator for test parameterization"""
16+
versions = kwargs.pop("api_versions", None) or ApiVersion
17+
params = [pytest.param(api_version) for api_version in versions]
18+
return params
19+
20+
21+
class AsyncCertificatesClientPreparer(AzureRecordedTestCase):
22+
def __init__(self, **kwargs) -> None:
23+
self.azure_keyvault_url = "https://vaultname.vault.azure.net"
24+
25+
if is_live():
26+
self.azure_keyvault_url = os.environ["AZURE_KEYVAULT_URL"]
27+
28+
self.is_logging_enabled = kwargs.pop("logging_enable", True)
29+
30+
if is_live():
31+
os.environ["AZURE_TENANT_ID"] = os.environ["KEYVAULT_TENANT_ID"]
32+
os.environ["AZURE_CLIENT_ID"] = os.environ["KEYVAULT_CLIENT_ID"]
33+
os.environ["AZURE_CLIENT_SECRET"] = os.environ["KEYVAULT_CLIENT_SECRET"]
34+
35+
def __call__(self, fn):
36+
async def _preparer(test_class, api_version, **kwargs):
37+
38+
self._skip_if_not_configured(api_version)
39+
if not self.is_logging_enabled:
40+
kwargs.update({"logging_enable": False})
41+
client = self.create_client(self.azure_keyvault_url, api_version=api_version, **kwargs)
42+
43+
async with client:
44+
await fn(test_class, client)
45+
return _preparer
46+
47+
def create_client(self, vault_uri, **kwargs):
48+
from azure.keyvault.certificates.aio import CertificateClient
49+
50+
credential = self.get_credential(CertificateClient, is_async = True)
51+
52+
return self.create_client_from_credential(
53+
CertificateClient, credential=credential, vault_url=vault_uri, **kwargs
54+
)
55+
56+
def _skip_if_not_configured(self, api_version, **kwargs):
57+
if self.is_live and api_version != DEFAULT_VERSION:
58+
pytest.skip("This test only uses the default API version for live tests")

sdk/keyvault/azure-keyvault-certificates/tests/_shared/test_case.py

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,11 @@
33
# Licensed under the MIT License.
44
# ------------------------------------
55
import time
6+
from azure.keyvault.certificates._shared import HttpChallengeCache
7+
from devtools_testutils import AzureRecordedTestCase
68

7-
from azure_devtools.scenario_tests.patches import patch_time_sleep_api
8-
from devtools_testutils import AzureTestCase
9-
10-
11-
class KeyVaultTestCase(AzureTestCase):
12-
def __init__(self, *args, **kwargs):
13-
if "match_body" not in kwargs:
14-
kwargs["match_body"] = True
15-
16-
super(KeyVaultTestCase, self).__init__(*args, **kwargs)
17-
self.replay_patches.append(patch_time_sleep_api)
18-
19-
def setUp(self):
20-
self.list_test_size = 7
21-
super(KeyVaultTestCase, self).setUp()
229

10+
class KeyVaultTestCase(AzureRecordedTestCase):
2311
def get_resource_name(self, name):
2412
"""helper to create resources with a consistent, test-indicative prefix"""
2513
return super(KeyVaultTestCase, self).get_resource_name("livekvtest{}".format(name))
@@ -48,3 +36,7 @@ def _poll_until_exception(self, fn, expected_exception, max_retries=20, retry_de
4836
return
4937

5038
self.fail("expected exception {expected_exception} was not raised")
39+
40+
def tear_down(self):
41+
HttpChallengeCache.clear()
42+
assert len(HttpChallengeCache._cache) == 0

sdk/keyvault/azure-keyvault-certificates/tests/_shared/test_case_async.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import asyncio
66

77
from azure_devtools.scenario_tests.patches import mock_in_unit_test
8-
from devtools_testutils import AzureTestCase
8+
from devtools_testutils import AzureRecordedTestCase
9+
10+
from azure.keyvault.certificates._shared import HttpChallengeCache
911

1012

1113
def skip_sleep(unit_test):
@@ -15,15 +17,7 @@ async def immediate_return(_):
1517
return mock_in_unit_test(unit_test, "asyncio.sleep", immediate_return)
1618

1719

18-
class KeyVaultTestCase(AzureTestCase):
19-
def __init__(self, *args, match_body=True, **kwargs):
20-
super().__init__(*args, match_body=match_body, **kwargs)
21-
self.replay_patches.append(skip_sleep)
22-
23-
def setUp(self):
24-
self.list_test_size = 7
25-
super(KeyVaultTestCase, self).setUp()
26-
20+
class KeyVaultTestCase(AzureRecordedTestCase):
2721
def get_resource_name(self, name):
2822
"""helper to create resources with a consistent, test-indicative prefix"""
2923
return super(KeyVaultTestCase, self).get_resource_name("livekvtest{}".format(name))
@@ -51,3 +45,8 @@ async def _poll_until_exception(self, fn, expected_exception, max_retries=20, re
5145
except expected_exception:
5246
return
5347
self.fail("expected exception {expected_exception} was not raised")
48+
49+
def tear_down(self):
50+
HttpChallengeCache.clear()
51+
assert len(HttpChallengeCache._cache) == 0
52+

sdk/keyvault/azure-keyvault-certificates/tests/_test_case.py

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,51 @@
22
# Copyright (c) Microsoft Corporation.
33
# Licensed under the MIT License.
44
# ------------------------------------
5-
import functools
5+
import os
66

77
from azure.keyvault.certificates import ApiVersion
8-
from azure.keyvault.certificates._shared import HttpChallengeCache
98
from azure.keyvault.certificates._shared.client_base import DEFAULT_VERSION
10-
from devtools_testutils import AzureTestCase, PowerShellPreparer
11-
from parameterized import parameterized, param
9+
from devtools_testutils import AzureRecordedTestCase, is_live
1210
import pytest
1311

1412

15-
def client_setup(testcase_func):
16-
"""decorator that creates a client to be passed in to a test method"""
17-
@PowerShellPreparer("keyvault", azure_keyvault_url="https://vaultname.vault.azure.net")
18-
@functools.wraps(testcase_func)
19-
def wrapper(test_class_instance, azure_keyvault_url, api_version, **kwargs):
20-
test_class_instance._skip_if_not_configured(api_version)
21-
client = test_class_instance.create_client(azure_keyvault_url, api_version=api_version, **kwargs)
22-
23-
if kwargs.get("is_async"):
24-
import asyncio
25-
26-
coroutine = testcase_func(test_class_instance, client)
27-
loop = asyncio.get_event_loop()
28-
loop.run_until_complete(coroutine)
29-
else:
30-
testcase_func(test_class_instance, client)
31-
return wrapper
32-
3313

3414
def get_decorator(**kwargs):
3515
"""returns a test decorator for test parameterization"""
3616
versions = kwargs.pop("api_versions", None) or ApiVersion
37-
params = [param(api_version=api_version, **kwargs) for api_version in versions]
38-
return functools.partial(parameterized.expand, params, name_func=suffixed_test_name)
39-
40-
41-
def suffixed_test_name(testcase_func, param_num, param):
42-
return "{}_{}".format(testcase_func.__name__, parameterized.to_safe_name(param.kwargs.get("api_version")))
43-
44-
45-
class CertificatesTestCase(AzureTestCase):
46-
def tearDown(self):
47-
HttpChallengeCache.clear()
48-
assert len(HttpChallengeCache._cache) == 0
49-
super(CertificatesTestCase, self).tearDown()
50-
17+
params = [pytest.param(api_version) for api_version in versions]
18+
return params
19+
20+
21+
class CertificatesClientPreparer(AzureRecordedTestCase):
22+
def __init__(self, **kwargs) -> None:
23+
self.azure_keyvault_url = "https://vaultname.vault.azure.net"
24+
25+
self.is_logging_enabled = kwargs.pop("logging_enable", True)
26+
27+
if is_live():
28+
self.azure_keyvault_url = os.environ["AZURE_KEYVAULT_URL"]
29+
os.environ["AZURE_TENANT_ID"] = os.environ["KEYVAULT_TENANT_ID"]
30+
os.environ["AZURE_CLIENT_ID"] = os.environ["KEYVAULT_CLIENT_ID"]
31+
os.environ["AZURE_CLIENT_SECRET"] = os.environ["KEYVAULT_CLIENT_SECRET"]
32+
33+
def __call__(self, fn):
34+
def _preparer(test_class, api_version, **kwargs):
35+
36+
self._skip_if_not_configured(api_version)
37+
if not self.is_logging_enabled:
38+
kwargs.update({"logging_enable": False})
39+
client = self.create_client(self.azure_keyvault_url, api_version=api_version, **kwargs)
40+
41+
with client:
42+
fn(test_class, client)
43+
return _preparer
44+
5145
def create_client(self, vault_uri, **kwargs):
52-
if kwargs.pop("is_async", False):
53-
from azure.keyvault.certificates.aio import CertificateClient
54-
credential = self.get_credential(CertificateClient, is_async=True)
55-
else:
56-
from azure.keyvault.certificates import CertificateClient
57-
credential = self.get_credential(CertificateClient)
46+
from azure.keyvault.certificates import CertificateClient
47+
48+
credential = self.get_credential(CertificateClient)
49+
5850
return self.create_client_from_credential(
5951
CertificateClient, credential=credential, vault_url=vault_uri, **kwargs
6052
)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# --------------------------------------------------------------------------
2+
#
3+
# Copyright (c) Microsoft Corporation. All rights reserved.
4+
#
5+
# The MIT License (MIT)
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the ""Software""), to
9+
# deal in the Software without restriction, including without limitation the
10+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11+
# sell copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in
15+
# all copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23+
# IN THE SOFTWARE.
24+
#
25+
# --------------------------------------------------------------------------
26+
import asyncio
27+
import os
28+
import pytest
29+
from unittest import mock
30+
from devtools_testutils import is_live, test_proxy, add_oauth_response_sanitizer, add_general_regex_sanitizer
31+
32+
33+
@pytest.fixture(scope="session", autouse=True)
34+
def add_sanitizers(test_proxy):
35+
azure_keyvault_url = os.getenv("azure_keyvault_url", "https://vaultname.vault.azure.net")
36+
azure_keyvault_url = azure_keyvault_url.rstrip("/")
37+
keyvault_tenant_id = os.getenv("keyvault_tenant_id", "keyvault_tenant_id")
38+
keyvault_subscription_id = os.getenv("keyvault_subscription_id", "keyvault_subscription_id")
39+
40+
add_general_regex_sanitizer(regex=azure_keyvault_url, value="https://vaultname.vault.azure.net")
41+
add_general_regex_sanitizer(regex=keyvault_tenant_id, value="00000000-0000-0000-0000-000000000000")
42+
add_general_regex_sanitizer(regex=keyvault_subscription_id, value="00000000-0000-0000-0000-000000000000")
43+
add_oauth_response_sanitizer()
44+
45+
46+
@pytest.fixture(scope="session", autouse=True)
47+
def patch_async_sleep():
48+
async def immediate_return(_):
49+
return
50+
51+
if not is_live():
52+
with mock.patch("asyncio.sleep", immediate_return):
53+
yield
54+
55+
else:
56+
yield
57+
58+
59+
@pytest.fixture(scope="session", autouse=True)
60+
def patch_sleep():
61+
def immediate_return(_):
62+
return
63+
64+
if not is_live():
65+
with mock.patch("time.sleep", immediate_return):
66+
yield
67+
68+
else:
69+
yield
70+
71+
@pytest.fixture(scope="session")
72+
def event_loop(request):
73+
loop = asyncio.get_event_loop()
74+
yield loop
75+
loop.close()

0 commit comments

Comments
 (0)