Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions azext_iot/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1472,11 +1472,11 @@
az iot dps connection-string show --resource-group MyResourceGroup
- name: Show all connection strings of the given DPS using primary key.
text: >
az iot dps connection-string show --name MyDPS --all
az iot dps connection-string show -n MyDPS --all
- name: Show the connection string of the given DPS using the default policy and primary key.
text: >
az iot dps connection-string show --name MyDPS
az iot dps connection-string show -n MyDPS
- name: Show the connection string of the given DPS using policy 'service' and secondary key.
text: >
az iot dps connection-string show --name MyDPS --policy-name service --key-type secondary
az iot dps connection-string show -n MyDPS --policy-name service --key-type secondary
"""
16 changes: 7 additions & 9 deletions azext_iot/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -974,14 +974,11 @@ def load_arguments(self, _):
'Use to avoid session login via "az login". '
"If both an entity connection string and name are provided the connection string takes priority. "
"Required if --dps-name is not provided.",
arg_group="Device Provisioning Service Identifier"
)
# TODO - CMS Preview - Hack to quiet the linter
context.argument(
"dps_name",
options_list=["--dps-name", "--name", "-n"],
options_list=["--dps-name", "-n"],
help="Name or hostname of the Azure IoT Hub Device Provisioning Service. Required if --login is not provided.",
arg_group="Device Provisioning Service Identifier"
)
context.argument(
"initial_twin_properties",
Expand Down Expand Up @@ -1074,6 +1071,12 @@ def load_arguments(self, _):
arg_type=dps_auth_type_dataplane_param_type,
)

# Apply arg_group only to dataplane commands
for dps_dataplane_command in ["compute-device-key", "connection-string", "enrollment", "enrollment-group"]:
with self.argument_context(f"iot dps {dps_dataplane_command}") as context:
context.argument("dps_name", arg_group="Device Provisioning Service Identifier")
context.argument("login", arg_group="Device Provisioning Service Identifier")

with self.argument_context("iot dps compute-device-key") as context:
context.argument(
"enrollment_id",
Expand All @@ -1091,11 +1094,6 @@ def load_arguments(self, _):
context.argument("registration_id", help="ID of device registration. ")

with self.argument_context("iot dps connection-string") as context:
context.argument(
"dps_name",
options_list=["--dps-name", "--name", "-n"],
help="IoT Hub Device Provisioning Service name."
)
context.argument(
"show_all",
options_list=["--show-all", "--all"],
Expand Down
34 changes: 25 additions & 9 deletions azext_iot/core/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
help='IoT Hub name.')

dps_name_type = CLIArgumentType(
options_list=['--dps-name', '--name'],
options_list=['--name', '-n'],
completer=get_resource_name_completion_list('Microsoft.Devices/ProvisioningServices'),
help='IoT Hub Device Provisioning Service name')

Expand All @@ -57,9 +57,13 @@
def load_arguments(self, _): # pylint: disable=too-many-statements
# Arguments for IoT DPS
with self.argument_context('iot dps') as c:
c.argument('dps_name', dps_name_type, id_part='name')
c.argument('tags', tags_type)

# Direct DPS resource commands use --name -n
for subgroup in ['create', 'update', 'show', 'delete']:
with self.argument_context('iot dps {}'.format(subgroup)) as c:
c.argument('dps_name', dps_name_type, id_part='name')

with self.argument_context('iot dps create') as c:
c.argument('location', get_location_type(self.cli_ctx),
help='Location of your IoT Hub Device Provisioning Service. '
Expand All @@ -76,12 +80,19 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
# plan to slowly align this with extension naming patterns - n should be aligned with dps_name
for subgroup in ['linked-hub', 'certificate']:
with self.argument_context('iot dps {}'.format(subgroup)) as c:
c.argument('dps_name', options_list=['--dps-name'], id_part=None)
c.argument('dps_name', options_list=['--dps-name'], id_part=None,
help='IoT Hub Device Provisioning Service name.', arg_group=None)

# Identity uses --name like IoT Hub
with self.argument_context('iot dps identity') as c:
c.argument('dps_name', options_list=['--name', '-n'],
help='IoT Hub Device Provisioning Service name.', arg_group=None)

# To replace above
for subgroup in ['policy']:
with self.argument_context('iot dps {}'.format(subgroup)) as c:
c.argument('dps_name', options_list=['--dps-name', '-n'], id_part=None)
c.argument('dps_name', options_list=['--dps-name', '-n'], id_part=None,
help='IoT Hub Device Provisioning Service name.', arg_group=None)

with self.argument_context('iot dps policy') as c:
c.argument('access_policy_name', options_list=['--policy-name', '--pn'],
Expand Down Expand Up @@ -109,6 +120,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements

with self.argument_context('iot dps linked-hub create') as c:
c.argument('connection_string',
options_list=['--connection-string', '--cs'],
help='Connection string of the IoT hub. Required if hub name is not provided using --hub-name.',
arg_group='IoT Hub Identifier')
c.argument('hub_name',
Expand Down Expand Up @@ -136,7 +148,9 @@ def load_arguments(self, _): # pylint: disable=too-many-statements

with self.argument_context('iot dps certificate') as c:
c.argument('certificate_path', options_list=['--path', '-p'], type=file_type,
completer=FilesCompleter([".cer", ".pem"]), help='The path to the file containing the certificate.')
completer=FilesCompleter([".cer", ".pem"]),
help='The path to the file containing the certificate.',
arg_group=None)
c.argument('certificate_name', options_list=['--certificate-name', '--name', '-n'],
help='A friendly name for the certificate.')
c.argument('etag', options_list=['--etag', '-e'], help='Entity Tag (etag) of the object.')
Expand All @@ -148,13 +162,15 @@ def load_arguments(self, _): # pylint: disable=too-many-statements

# Arguments for IoT Hub
with self.argument_context('iot hub') as c:
c.argument('hub_name', hub_name_type, options_list=['--name', '-n'], id_part='name')
c.argument('etag', options_list=['--etag', '-e'], help='Entity Tag (etag) of the object.')
c.argument('hub_name', hub_name_type, options_list=['--name', '-n'], id_part='name', arg_group=None)
c.argument("etag", options_list=["--etag", "-e"],
help="Etag or entity tag corresponding to the last state of the resource."
" If no etag is provided the value '*' is used.")
c.argument('sku', arg_type=get_enum_type(IotHubSku),
help='Pricing tier for Azure IoT Hub. '
'Note that only one free IoT hub instance (F1) is allowed in each '
'subscription. Exception will be thrown if free instances exceed one.')
c.argument('unit', help='Units in your IoT Hub.', type=int)
c.argument('unit', help='Units in your IoT Hub.', type=int, arg_group=None)
c.argument('partition_count',
help='The number of partitions of the backing Event Hub for device-to-cloud messages.', type=int)
c.argument('retention_day', options_list=['--retention-day', '--rd'],
Expand Down Expand Up @@ -250,7 +266,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements
# Tag-type should only be for hub create/update (conflicts with device-twin update twin tags)
for cmd in ["iot hub create", "iot hub update"]:
with self.argument_context(cmd) as c:
c.argument('tags', tags_type)
c.argument('tags', tags_type, arg_group=None)

with self.argument_context('iot hub identity assign') as c:
c.argument('system_identity', options_list=['--system-assigned', '--system'],
Expand Down
4 changes: 2 additions & 2 deletions azext_iot/core/command_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ def load_core_commands(self, _):
with self.command_group(
"iot hub", command_type=core_ops, client_factory=iot_hub_service_factory
) as cmd_group:
cmd_group.command("create", "iot_hub_create")
cmd_group.command("create", "iot_hub_create", supports_no_wait=True)
cmd_group.generic_update_command(
"update",
getter_name="iot_hub_get",
setter_name="iot_hub_update",
custom_func_type=core_ops,
custom_func_name="update_iot_hub_custom",
)
cmd_group.command("delete", "iot_hub_delete")
cmd_group.command("delete", "iot_hub_delete", supports_no_wait=True)
cmd_group.show_command("show", "iot_hub_get")
cmd_group.command("list", "iot_hub_list")
cmd_group.command('list-skus', 'iot_hub_sku_list')
Expand Down
36 changes: 19 additions & 17 deletions azext_iot/core/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

from azext_iot._factory import iot_hub_service_factory, resource_service_factory
from azext_iot.common.certops import open_certificate
from azext_iot.common.shared import AuthenticationType
from azext_iot.sdk.iothub.mgmt.models import AuthenticationType
from azext_iot.core.shared import (
ADR_CONFIGURE_ROLES_ERROR_MSG,
ADR_NS_IDENTITY_ROLES_FOR_HUB,
Expand Down Expand Up @@ -535,7 +535,8 @@ def iot_dps_certificate_update(client, dps_name, certificate_name, certificate_p
provisioning_service_name=dps_name,
certificate_name=certificate_name,
certificate_description=certificate_description,
etag=etag
etag=etag,
match_condition=MatchConditions.IfNotModified
)
raise CLIError("Certificate '{0}' does not exist. Use 'iot dps certificate create' to create a new certificate."
.format(certificate_name))
Expand Down Expand Up @@ -734,7 +735,7 @@ def iot_hub_create(
raise RequiredArgumentMissingError('Please mention storage container name.')
if fileupload_storage_container_name and not fileupload_storage_connectionstring:
raise RequiredArgumentMissingError('Please mention storage connection string.')
identity_based_file_upload = fileupload_storage_authentication_type and fileupload_storage_authentication_type == AuthenticationType.IdentityBased.value
identity_based_file_upload = fileupload_storage_authentication_type and fileupload_storage_authentication_type == AuthenticationType.IDENTITY_BASED.value
if not identity_based_file_upload and fileupload_storage_identity:
raise RequiredArgumentMissingError('In order to set a fileupload storage identity, please set file upload storage authentication (--fsa) to IdentityBased')
if identity_based_file_upload or fileupload_storage_identity:
Expand Down Expand Up @@ -927,7 +928,7 @@ def update_iot_hub_custom(instance,
default_storage_endpoint = StorageEndpointProperties(container_name=fileupload_storage_container_name, connection_string=fileupload_storage_connectionstring)

# if setting a fileupload storage identity or changing fileupload to identity-based
if fileupload_storage_identity or fileupload_storage_authentication_type == AuthenticationType.IdentityBased.value:
if fileupload_storage_identity or fileupload_storage_authentication_type == AuthenticationType.IDENTITY_BASED.value:
_validate_fileupload_identity(instance, fileupload_storage_identity)

instance.properties.storage_endpoints['$default'] = _process_fileupload_args(
Expand Down Expand Up @@ -959,9 +960,10 @@ def update_iot_hub_custom(instance,
f"Cannot change IoT Hub SKU from {existing_sku_name} to {final_sku_name}."
)

adr_namespace_resource_id = instance.device_registry.namespace_resource_id if instance.device_registry else None
device_registry = getattr(instance.properties, "device_registry", None)
adr_namespace_resource_id = device_registry.namespace_resource_id if device_registry else None
_validate_and_set_adr_properties(
instance=instance,
instance=instance.properties,
sku=final_sku_name,
adr_namespace_resource_id=adr_namespace_resource_id,
adr_identity_resource_id=adr_ns_identity_id,
Expand Down Expand Up @@ -1276,7 +1278,7 @@ def iot_hub_get_stats(client, hub_name, resource_group_name=None):


def validate_authentication_type_input(endpoint_type, connection_string=None, authentication_type=None, endpoint_uri=None, entity_path=None):
is_keyBased = (AuthenticationType.KeyBased.value == authentication_type) or (authentication_type is None)
is_keyBased = (AuthenticationType.KEY_BASED.value == authentication_type) or (authentication_type is None)
has_connection_string = connection_string is not None
if is_keyBased and not has_connection_string:
raise CLIError("Please provide a connection string '--connection-string/-c'")
Expand All @@ -1298,7 +1300,7 @@ def iot_hub_routing_endpoint_create(cmd, client, hub_name, endpoint_name, endpoi
identity=None):
resource_group_name = _ensure_hub_resource_group_name(client, resource_group_name, hub_name)
hub = iot_hub_get(cmd, client, hub_name, resource_group_name)
if identity and authentication_type != AuthenticationType.IdentityBased.value:
if identity and authentication_type != AuthenticationType.IDENTITY_BASED.value:
raise ArgumentUsageError("In order to use an identity for authentication, you must select --auth-type as 'identityBased'")

if EndpointType.EventHub.value == endpoint_type.lower():
Expand Down Expand Up @@ -1497,15 +1499,15 @@ def iot_hub_route_test(cmd, client, hub_name, route_name=None, source_type=None,
route=route
)
return client.iot_hub_resource.test_route(
resource_name=hub_name, resource_group_name=resource_group_name, input=test_route_input
iot_hub_name=hub_name, resource_group_name=resource_group_name, input=test_route_input
)
test_all_routes_input = TestAllRoutesInput(
routing_source=source_type,
message=route_message,
twin=None
)
return client.iot_hub_resource.test_all_routes(
resource_name=hub_name, resource_group_name=resource_group_name, input=test_all_routes_input
iot_hub_name=hub_name, resource_group_name=resource_group_name, input=test_all_routes_input
)


Expand Down Expand Up @@ -1559,11 +1561,11 @@ def iot_hub_manual_failover(cmd, client, hub_name, resource_group_name=None, no_
failover_input = FailoverInput(failover_region=failover_region)
if no_wait:
return client.iot_hub.begin_manual_failover(
resource_name=hub_name, resource_group_name=resource_group_name, failover_input=failover_input
iot_hub_name=hub_name, resource_group_name=resource_group_name, failover_input=failover_input
)
LongRunningOperation(cmd.cli_ctx)(
client.iot_hub.begin_manual_failover(
resource_name=hub_name, resource_group_name=resource_group_name, failover_input=failover_input
iot_hub_name=hub_name, resource_group_name=resource_group_name, failover_input=failover_input
)
)
return iot_hub_get(cmd, client, hub_name, resource_group_name)
Expand Down Expand Up @@ -1712,12 +1714,12 @@ def _process_fileupload_args(
fileupload_storage_identity=None,
):
from datetime import timedelta
if fileupload_storage_authentication_type and fileupload_storage_authentication_type == AuthenticationType.IdentityBased.value:
default_storage_endpoint.authentication_type = AuthenticationType.IdentityBased.value
if fileupload_storage_authentication_type and fileupload_storage_authentication_type == AuthenticationType.IDENTITY_BASED.value:
default_storage_endpoint.authentication_type = AuthenticationType.IDENTITY_BASED.value
if fileupload_storage_container_uri:
default_storage_endpoint.container_uri = fileupload_storage_container_uri
elif fileupload_storage_authentication_type and fileupload_storage_authentication_type == AuthenticationType.KeyBased.value:
default_storage_endpoint.authentication_type = AuthenticationType.KeyBased.value
elif fileupload_storage_authentication_type and fileupload_storage_authentication_type == AuthenticationType.KEY_BASED.value:
default_storage_endpoint.authentication_type = AuthenticationType.KEY_BASED.value
default_storage_endpoint.identity = None
elif fileupload_storage_authentication_type is not None:
default_storage_endpoint.authentication_type = None
Expand All @@ -1736,7 +1738,7 @@ def _process_fileupload_args(
# Fix for identity/authentication-type params missing on hybrid profile api
if hasattr(default_storage_endpoint, 'authentication_type'):
# If we are now (or will be) using fsa=identity AND we've set a new identity
if default_storage_endpoint.authentication_type == AuthenticationType.IdentityBased.value and fileupload_storage_identity:
if default_storage_endpoint.authentication_type == AuthenticationType.IDENTITY_BASED.value and fileupload_storage_identity:
# setup new fsi
default_storage_endpoint.identity = ManagedIdentity(
user_assigned_identity=fileupload_storage_identity) if fileupload_storage_identity not in [IdentityType.none.value, SYSTEM_ASSIGNED_IDENTITY] else None
Expand Down
4 changes: 2 additions & 2 deletions azext_iot/core/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def patch_core_help():
- name: Assign a system-assigned identity to an Azure IoT Hub Device Provisioning Service.
text: az iot dps identity assign --name MyDps --resource-group MyResourceGroup --system
- name: Assign both a system-assigned and a user-managed identity to an Azure IoT Hub Device Provisioning Service.
text: az iot dps identity assign --system --user IdentityResourceId
text: az iot dps identity assign --name MyDps --resource-group MyResourceGroup --system --user IdentityResourceId
"""

helps[
Expand All @@ -75,7 +75,7 @@ def patch_core_help():
- name: Remove a system-assigned identity from an Azure IoT Hub Device Provisioning Service.
text: az iot dps identity remove --name MyDps --resource-group MyResourceGroup --system
- name: Remove a user-managed identity from an Azure IoT Hub Device Provisioning Service.
text: az iot dps identity remove --user IdentityResourceId
text: az iot dps identity remove --name MyDps --resource-group MyResourceGroup --user IdentityResourceId
"""

helps[
Expand Down