azext_iot/dps/providers/discovery.py (70 lines of code) (raw):
# coding=utf-8
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
from knack.log import get_logger
from azure.cli.core.commands.client_factory import get_subscription_id
from azext_iot.common._azure import IOT_SERVICE_CS_TEMPLATE
from azext_iot.common.base_discovery import BaseDiscovery
from azext_iot.common.shared import DiscoveryResourceType, AuthenticationTypeDataplane
from azext_iot.dps.models.dps_target import DPSTarget
from azext_iot._factory import iot_service_provisioning_factory
from typing import Any, Dict
logger = get_logger(__name__)
PRIVILEDGED_ACCESS_RIGHTS_SET = set(
["ServiceConfig", "EnrollmentWrite"]
)
class DPSDiscovery(BaseDiscovery):
def __init__(self, cmd):
super().__init__(
cmd=cmd,
necessary_rights_set=PRIVILEDGED_ACCESS_RIGHTS_SET,
resource_type=DiscoveryResourceType.DPS.value
)
def _initialize_client(self):
if not self.client:
if getattr(self.cmd, "cli_ctx", None):
# The client we want to use is an attribute of the client returned
# from the factory. This will have to be revisted if the DPS sdk changes.
self.client = iot_service_provisioning_factory(self.cmd.cli_ctx).iot_dps_resource
self.sub_id = get_subscription_id(self.cmd.cli_ctx)
else:
self.client = self.cmd
# Method get_keys_for_key_name needed for policy discovery (see
# BaseDiscovery.find_policy for usage) and is defined as
# list)keys_for_key_name in the DPS Sdk.
self.client.get_keys_for_key_name = self.client.list_keys_for_key_name
def _make_kwargs(self, **kwargs) -> Dict[str, Any]:
# The DPS client needs the provisioning_service_name argument
kwargs["provisioning_service_name"] = kwargs.pop("resource_name")
return kwargs
@classmethod
def get_target_by_cstring(cls, connection_string: str) -> Dict[str, str]:
return DPSTarget.from_connection_string(cstring=connection_string).as_dict()
def _build_target_from_hostname(self, resource_hostname: str) -> Dict[str, str]:
login = AuthenticationTypeDataplane.login.value
target = {}
target["cs"] = IOT_SERVICE_CS_TEMPLATE.format(
resource_hostname,
login,
login,
)
target["entity"] = resource_hostname
target["name"] = resource_hostname.split(".")[0]
target["policy"] = login
target["primarykey"] = login
target["secondarykey"] = login
target["subscription"] = self.sub_id
target["cmd"] = self.cmd
return target
def _build_target(
self, resource, policy, key_type: str = None, **kwargs
) -> Dict[str, str]:
# This is more or less a compatibility function which produces the
# same result as _azure.get_iot_dps_connection_string()
# In future iteration we will return a 'Target' object rather than dict
# but that will be better served aligning with vNext pattern for DPS
result = {}
result["cs"] = IOT_SERVICE_CS_TEMPLATE.format(
resource.properties.service_operations_host_name,
policy.key_name,
policy.primary_key if key_type == "primary" else policy.secondary_key,
)
result["entity"] = resource.properties.service_operations_host_name
result["policy"] = policy.key_name
result["primarykey"] = policy.primary_key
result["secondarykey"] = policy.secondary_key
result["subscription"] = self.sub_id
result["cmd"] = self.cmd
result["idscope"] = resource.properties.id_scope
return result
def get_id_scope(self, resource_name: str, rg: str = None) -> str:
"""Get the ID scope. Only needed for certain DPS operations."""
return self.find_resource(
resource_name=resource_name, rg=rg
).properties.id_scope