Skip to content

Commit

Permalink
feat: register required resource providers in `az iot ops schema regi…
Browse files Browse the repository at this point in the history
…stry create` (#405)

* registry movement

* mc changes

* fix unit test

* it is hard to be perfect

* wat
  • Loading branch information
vilit1 authored Oct 8, 2024
1 parent 71bdc00 commit 7005939
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 12 deletions.
3 changes: 3 additions & 0 deletions azext_edge/edge/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,9 @@ def load_iotops_help():
If the indicated storage account container does not exist it will be created with default
settings.
This operation will also register the Microsoft.DeviceRegistry resource provider if it is
not registered.
examples:
- name: Create a schema registry called 'myregistry' with minimum inputs.
text: >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from knack.log import get_logger
from rich.console import Console


from ....util.az_client import (
get_registry_mgmt_client,
get_storage_mgmt_client,
Expand Down Expand Up @@ -66,7 +67,11 @@ def create(
custom_role_id: Optional[str] = None,
**kwargs,
) -> dict:
from ..rp_namespace import register_providers, ADR_PROVIDER
with console.status("Working...") as c:
# Register the schema (ADR) provider
register_providers(self.default_subscription_id, ADR_PROVIDER)

if not location:
location = self.get_resource_group(name=resource_group_name)["location"]

Expand Down
9 changes: 6 additions & 3 deletions azext_edge/edge/providers/orchestration/rp_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,30 @@
# Licensed under the MIT License. See License file in the project root for license information.
# ----------------------------------------------------------------------------------------------

from typing import Optional
from knack.log import get_logger

from ...util.az_client import get_resource_client

logger = get_logger(__name__)


ADR_PROVIDER = "Microsoft.DeviceRegistry"
RP_NAMESPACE_SET = frozenset(
[
"Microsoft.IoTOperations",
"Microsoft.DeviceRegistry",
"Microsoft.SecretSyncController",
ADR_PROVIDER
]
)


def register_providers(subscription_id: str):
def register_providers(subscription_id: str, resource_provider: Optional[str] = None):
resource_client = get_resource_client(subscription_id=subscription_id)
providers_list = resource_client.providers.list()
required_providers = [resource_provider] if resource_provider else RP_NAMESPACE_SET
for provider in providers_list:
if "namespace" in provider and provider["namespace"] in RP_NAMESPACE_SET:
if "namespace" in provider and provider["namespace"] in required_providers:
if provider["registrationState"] == "Registered":
logger.debug("RP %s is already registered.", provider["namespace"])
continue
Expand Down
6 changes: 6 additions & 0 deletions azext_edge/tests/edge/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ def mocked_urlopen(mocker):
yield patched


@pytest.fixture
def mocked_register_providers(mocker):
patched = mocker.patch("azext_edge.edge.providers.orchestration.rp_namespace.register_providers", autospec=True)
yield patched


@pytest.fixture
def mocked_resource_management_client(request, mocker):
request_results = getattr(request, "param", {})
Expand Down
6 changes: 0 additions & 6 deletions azext_edge/tests/edge/init/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ def mocked_verify_cli_client_connections(mocker):
yield patched


@pytest.fixture
def mocked_register_providers(mocker):
patched = mocker.patch("azext_edge.edge.providers.orchestration.rp_namespace.register_providers", autospec=True)
yield patched


@pytest.fixture
def mocked_edge_api_keyvault_api_v1(mocker):
patched = mocker.patch("azext_edge.edge.providers.edge_api.keyvault.KEYVAULT_API_V1", autospec=False)
Expand Down
7 changes: 5 additions & 2 deletions azext_edge/tests/edge/init/test_base_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,8 @@ def test_verify_custom_location_namespace(
"NotRegistered",
],
)
def test_register_providers(mocker, registration_state):
@pytest.mark.parametrize("input_rp", [None, "Microsoft.DeviceRegistry"])
def test_register_providers(mocker, registration_state, input_rp):
mocked_get_resource_client: Mock = mocker.patch(
"azext_edge.edge.providers.orchestration.rp_namespace.get_resource_client"
)
Expand All @@ -338,13 +339,15 @@ def test_register_providers(mocker, registration_state):
"Microsoft.DeviceRegistry",
"Microsoft.SecretSyncController",
]
if input_rp:
iot_ops_rps = [input_rp]
mocked_get_resource_client().providers.list.return_value = [
{"namespace": namespace, "registrationState": registration_state} for namespace in iot_ops_rps
]

for rp in iot_ops_rps:
assert rp in RP_NAMESPACE_SET
assert len(iot_ops_rps) == len(RP_NAMESPACE_SET)
assert len(iot_ops_rps) == (1 if input_rp else len(RP_NAMESPACE_SET))

register_providers(ZEROED_SUB)
mocked_get_resource_client().providers.list.assert_called_once()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
ROLE_DEF_FORMAT_STR,
STORAGE_BLOB_DATA_CONTRIBUTOR_ROLE_ID,
)
from azext_edge.edge.providers.orchestration.rp_namespace import ADR_PROVIDER

from ....generators import generate_random_string
from .conftest import get_base_endpoint, get_mock_resource, get_resource_id, find_request_by_url, ZEROED_SUBSCRIPTION
Expand Down Expand Up @@ -218,8 +219,9 @@ def test_schema_registry_delete(mocked_cmd, mocked_responses: responses):
)
def test_schema_registry_create(
mocked_cmd,
mocked_responses: responses,
mocker,
mocked_register_providers,
mocked_responses: responses,
location: Optional[str],
display_name: Optional[str],
description: Optional[str],
Expand Down Expand Up @@ -343,6 +345,7 @@ def test_schema_registry_create(
== f"{mock_storage_record['properties']['primaryEndpoints']['blob']}{storage_container_name}"
)

mocked_register_providers.assert_called_with(ZEROED_SUBSCRIPTION, ADR_PROVIDER)
mock_permission_manager.assert_called_with(ZEROED_SUBSCRIPTION)
target_role_id = custom_role_id or ROLE_DEF_FORMAT_STR.format(
subscription_id=ZEROED_SUBSCRIPTION, role_id=STORAGE_BLOB_DATA_CONTRIBUTOR_ROLE_ID
Expand Down

0 comments on commit 7005939

Please sign in to comment.