Skip to content

Commit

Permalink
Fill gaps with IoT Central REST apis (#390)
Browse files Browse the repository at this point in the history
* add device groups and roles commands

* include role_id in help

* add device group tests

* add central roles unit tests

* update version

* fix formatting

* remove unused

* Update mock import.

* add preview tag

* add int tests for new commands

Co-authored-by: Paymaun Heidari <[email protected]>
Co-authored-by: Paymaun <[email protected]>
  • Loading branch information
3 people authored Jul 21, 2021
1 parent dfe4d72 commit 87a4b79
Show file tree
Hide file tree
Showing 21 changed files with 613 additions and 3 deletions.
8 changes: 8 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
Release History
===============

0.10.15
+++++++++++++++

**IoT Central updates**

* Adds support for listing device groups
* Adds support for listing roles and get role by id

0.10.14
+++++++++++++++

Expand Down
59 changes: 59 additions & 0 deletions azext_iot/central/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ def load_central_help():
_load_central_users_help()
_load_central_api_token_help()
_load_central_device_templates_help()
_load_central_device_groups_help()
_load_central_roles_help()
_load_central_monitors_help()
_load_central_command_help()
_load_central_compute_device_key()
Expand Down Expand Up @@ -429,6 +431,63 @@ def _load_central_device_templates_help():
"""


def _load_central_device_groups_help():
helps[
"iot central device-group"
] = """
type: group
short-summary: Manage and configure IoT Central device groups
"""

helps[
"iot central device-group list"
] = """
type: command
short-summary: Get the list of device groups for an IoT Central application.
examples:
- name: List device groups in an application
text: >
az iot central device-group list
--app-id {appid}
"""


def _load_central_roles_help():
helps[
"iot central role"
] = """
type: group
short-summary: Manage and configure IoT Central roles
"""

helps[
"iot central role list"
] = """
type: command
short-summary: Get the list of roles for an IoT Central application.
examples:
- name: List roles in an application
text: >
az iot central role list
--app-id {appid}
"""

helps[
"iot central role show"
] = """
type: command
short-summary: Get the details of a role by ID
examples:
- name: Get details of role
text: >
az iot central role show
--app-id {appid}
--role-id {roleId}
"""


def _load_central_monitors_help():

helps[
Expand Down
19 changes: 19 additions & 0 deletions azext_iot/central/command_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@
operations_tmpl="azext_iot.central.commands_device_template#{}"
)

central_device_groups_ops = CliCommandType(
operations_tmpl="azext_iot.central.commands_device_group#{}"
)

central_roles_ops = CliCommandType(
operations_tmpl="azext_iot.central.commands_role#{}"
)

central_device_twin_ops = CliCommandType(
operations_tmpl="azext_iot.central.commands_device_twin#{}"
)
Expand Down Expand Up @@ -103,6 +111,17 @@ def load_central_commands(self, _):
cmd_group.command("create", "create_device_template")
cmd_group.command("delete", "delete_device_template")

with self.command_group(
"iot central device-group", command_type=central_device_groups_ops, is_preview=True
) as cmd_group:
cmd_group.command("list", "list_device_groups")

with self.command_group(
"iot central role", command_type=central_roles_ops, is_preview=True
) as cmd_group:
cmd_group.show_command("show", "get_role")
cmd_group.command("list", "list_roles")

with self.command_group(
"iot central device twin", command_type=central_device_twin_ops,
) as cmd_group:
Expand Down
21 changes: 21 additions & 0 deletions azext_iot/central/commands_device_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# 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.
# --------------------------------------------------------------------------------------------
# Dev note - think of this as a controller

from azext_iot.constants import CENTRAL_ENDPOINT
from azext_iot.central.providers.preview import CentralDeviceGroupProviderPreview
from azext_iot.central.models.enum import ApiVersion


def list_device_groups(
cmd,
app_id: str,
token=None,
central_dns_suffix=CENTRAL_ENDPOINT,
api_version=ApiVersion.preview.value,
):
provider = CentralDeviceGroupProviderPreview(cmd=cmd, app_id=app_id, token=token)
return provider.list_device_groups(central_dns_suffix=central_dns_suffix)
35 changes: 35 additions & 0 deletions azext_iot/central/commands_role.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# 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.
# --------------------------------------------------------------------------------------------
# Dev note - think of this as a controller

from azext_iot.constants import CENTRAL_ENDPOINT
from azext_iot.central.providers.preview import CentralRoleProviderPreview
from azext_iot.central.models.enum import ApiVersion


def get_role(
cmd,
app_id: str,
role_id: str,
token=None,
central_dns_suffix=CENTRAL_ENDPOINT,
api_version=ApiVersion.preview.value,
):
provider = CentralRoleProviderPreview(cmd=cmd, app_id=app_id, token=token)

return provider.get_role(role_id=role_id, central_dns_suffix=central_dns_suffix)


def list_roles(
cmd,
app_id: str,
token=None,
central_dns_suffix=CENTRAL_ENDPOINT,
api_version=ApiVersion.preview.value,
):
provider = CentralRoleProviderPreview(cmd=cmd, app_id=app_id, token=token)

return provider.list_roles(central_dns_suffix=central_dns_suffix)
4 changes: 4 additions & 0 deletions azext_iot/central/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
from azext_iot.central.models.devicetwin import DeviceTwin
from azext_iot.central.models.templatepreview import TemplatePreview
from azext_iot.central.models.templatev1 import TemplateV1
from azext_iot.central.models.deviceGroupPreview import DeviceGroupPreview
from azext_iot.central.models.rolePreview import RolePreview


__all__ = [
"DevicePreview",
"DeviceGroupPreview",
"DeviceV1",
"DeviceTwin",
"TemplatePreview",
"TemplateV1",
"RolePreview"
]
11 changes: 11 additions & 0 deletions azext_iot/central/models/deviceGroupPreview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 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.
# --------------------------------------------------------------------------------------------

class DeviceGroupPreview:
def __init__(self, group: dict):
self.display_name = group.get("displayName")
self.id = group.get("id")
pass
11 changes: 11 additions & 0 deletions azext_iot/central/models/rolePreview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 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.
# --------------------------------------------------------------------------------------------

class RolePreview:
def __init__(self, device: dict):
self.display_name = device.get("displayName")
self.id = device.get("id")
pass
7 changes: 7 additions & 0 deletions azext_iot/central/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,10 @@ def load_central_arguments(self, _):
options_list=["--module-id", "-m"],
help="Provide IoT Edge Module ID if the device type is IoT Edge.",
)

with self.argument_context("iot central role") as context:
context.argument(
"role_id",
options_list=["--role-id", "-r"],
help="Provide a unique identifier for the role"
)
9 changes: 9 additions & 0 deletions azext_iot/central/providers/preview/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,19 @@
from azext_iot.central.providers.preview.api_token_provider_preview import (
CentralApiTokenProviderPreview,
)
from azext_iot.central.providers.preview.device_group_provider_preview import (
CentralDeviceGroupProviderPreview
)
from azext_iot.central.providers.preview.role_provider_preview import (
CentralRoleProviderPreview
)

__all__ = [
"CentralDeviceProviderPreview",
"CentralDeviceTemplateProviderPreview",
"CentralUserProviderPreview",
"CentralApiTokenProviderPreview",
"CentralDeviceGroupProviderPreview",
"CentralRoleProviderPreview"

]
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# 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 typing import List
from azext_iot.central.models.deviceGroupPreview import DeviceGroupPreview
from knack.log import get_logger
from azext_iot.constants import CENTRAL_ENDPOINT
from azext_iot.central import services as central_services
from azext_iot.central.models.enum import ApiVersion

logger = get_logger(__name__)


class CentralDeviceGroupProviderPreview:
def __init__(self, cmd, app_id: str, token=None):
"""
Provider for device groups APIs
Args:
cmd: command passed into az
app_id: name of app (used for forming request URL)
token: (OPTIONAL) authorization token to fetch device details from IoTC.
MUST INCLUDE type (e.g. 'SharedAccessToken ...', 'Bearer ...')
Useful in scenarios where user doesn't own the app
therefore AAD token won't work, but a SAS token generated by owner will
"""
self._cmd = cmd
self._app_id = app_id
self._token = token
self._device_groups = {}

def list_device_groups(self, central_dns_suffix=CENTRAL_ENDPOINT) -> List[DeviceGroupPreview]:
device_groups = central_services.device_group.list_device_groups(
cmd=self._cmd,
app_id=self._app_id,
token=self._token,
central_dns_suffix=central_dns_suffix,
api_version=ApiVersion.preview.value,
)

# add to cache
self._device_groups.update({device_group.id: device_group for device_group in device_groups})

return self._device_groups
71 changes: 71 additions & 0 deletions azext_iot/central/providers/preview/role_provider_preview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# 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 typing import List
from azext_iot.central.models.rolePreview import RolePreview
from knack.util import CLIError
from knack.log import get_logger
from azext_iot.constants import CENTRAL_ENDPOINT
from azext_iot.central import services as central_services
from azext_iot.central.models.enum import ApiVersion
from azext_iot.central import models as central_models

logger = get_logger(__name__)


class CentralRoleProviderPreview:
def __init__(self, cmd, app_id: str, token=None):
"""
Provider for roles APIs
Args:
cmd: command passed into az
app_id: name of app (used for forming request URL)
token: (OPTIONAL) authorization token to fetch device details from IoTC.
MUST INCLUDE type (e.g. 'SharedAccessToken ...', 'Bearer ...')
Useful in scenarios where user doesn't own the app
therefore AAD token won't work, but a SAS token generated by owner will
"""
self._cmd = cmd
self._app_id = app_id
self._token = token
self._roles = {}

def list_roles(self, central_dns_suffix=CENTRAL_ENDPOINT) -> List[RolePreview]:
roles = central_services.role.list_roles(
cmd=self._cmd,
app_id=self._app_id,
token=self._token,
central_dns_suffix=central_dns_suffix,
api_version=ApiVersion.preview.value,
)

# add to cache
self._roles.update({role.id: role for role in roles})

return self._roles

def get_role(
self, role_id, central_dns_suffix=CENTRAL_ENDPOINT,
) -> central_models.RolePreview:
# get or add to cache
role = self._roles.get(role_id)
if not role:
role = central_services.role.get_role(
cmd=self._cmd,
app_id=self._app_id,
role_id=role_id,
token=self._token,
central_dns_suffix=central_dns_suffix,
api_version=ApiVersion.preview.value,
)
self._roles[role_id] = role

if not role:
raise CLIError("No role found with id: '{}'.".format(role_id))

return role
4 changes: 2 additions & 2 deletions azext_iot/central/services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from azext_iot.central.services import device, device_template, user, api_token
from azext_iot.central.services import device, device_template, user, api_token, device_group, role


__all__ = ["device", "device_template", "user", "api_token"]
__all__ = ["device", "device_template", "user", "api_token", "device_group", "role"]
Loading

0 comments on commit 87a4b79

Please sign in to comment.