Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ensure "name" is prioritized for asset events and data-points #389

Merged
merged 3 commits into from
Sep 28, 2024
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
30 changes: 16 additions & 14 deletions azext_edge/edge/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ def load_iotops_help():
] = """
type: group
short-summary: Manage datasets in an asset.
long-summary: A dataset will be created once a point is created. See `az iot ops asset dataset point add` for more details.
"""

helps[
Expand All @@ -842,7 +843,7 @@ def load_iotops_help():
examples:
- name: Show the details of a dataset in an asset.
text: >
az iot ops asset dataset show -g myresourcegroup --asset myasset -n dataset1
az iot ops asset dataset show -g myresourcegroup --asset myasset -n default
"""

helps[
Expand All @@ -857,16 +858,17 @@ def load_iotops_help():
] = """
type: command
short-summary: Add a data point to an asset dataset.
long-summary: If no datasets exist yet, this will create a new dataset. Currently, only one dataset is supported with the name "default".

examples:
- name: Add a data point to an asset.
text: >
az iot ops asset dataset point add --asset myasset -g myresourcegroup --dataset dataset1 --data-source mydatasource --name data1
az iot ops asset dataset point add --asset myasset -g myresourcegroup --dataset default --data-source mydatasource --name data1

- name: Add a data point to an asset with data point name, observability mode, custom queue size,
and custom sampling interval.
text: >
az iot ops asset dataset point add --asset myasset -g myresourcegroup --dataset dataset1 --data-source mydatasource --name data1
az iot ops asset dataset point add --asset myasset -g myresourcegroup --dataset default --data-source mydatasource --name data1
--observability-mode log --queue-size 5 --sampling-interval 200
"""

Expand All @@ -879,13 +881,13 @@ def load_iotops_help():
examples:
- name: Export all data-points in an asset in JSON format.
text: >
az iot ops asset dataset point export --asset myasset -g myresourcegroup --dataset dataset1
az iot ops asset dataset point export --asset myasset -g myresourcegroup --dataset default
- name: Export all data-points in an asset in CSV format in a specific output directory that can be uploaded via the Digital Operations Experience.
text: >
az iot ops asset dataset point export --asset myasset -g myresourcegroup --dataset dataset1 --format csv --output-dir myAssetsFiles
az iot ops asset dataset point export --asset myasset -g myresourcegroup --dataset default --format csv --output-dir myAssetsFiles
- name: Export all data-points in an asset in YAML format. Replace the file if one is present already.
text: >
az iot ops asset dataset point export --asset myasset -g myresourcegroup --dataset dataset1 --format yaml --replace
az iot ops asset dataset point export --asset myasset -g myresourcegroup --dataset default --format yaml --replace
"""

helps[
Expand All @@ -895,12 +897,12 @@ def load_iotops_help():
short-summary: Import data-points in an asset dataset.
long-summary: For examples of file formats, please see aka.ms/aziotops-assets
examples:
- name: Import all data-points from a file. These data-points will be appended to the asset dataset's current data-points. Data-points with duplicate dataSources will be ignored.
- name: Import all data-points from a file. These data-points will be appended to the asset dataset's current data-points. Data-points with duplicate names will be ignored.
text: >
az iot ops asset dataset point import --asset myasset -g myresourcegroup --dataset dataset1 --input-file myasset_dataset1_dataPoints.csv
- name: Import all data-points from a file. These data-points will be appended to the asset dataset's current data-points. Data-points with duplicate dataSources will be replaced.
az iot ops asset dataset point import --asset myasset -g myresourcegroup --dataset default --input-file myasset_default_dataPoints.csv
- name: Import all data-points from a file. These data-points will be appended to the asset dataset's current data-points. Data-points with duplicate names will replace the current asset data-points.
text: >
az iot ops asset dataset point import --asset myasset -g myresourcegroup --dataset dataset1 --input-file myasset_dataset1_dataPoints.json --replace
az iot ops asset dataset point import --asset myasset -g myresourcegroup --dataset default --input-file myasset_default_dataPoints.json --replace
"""

helps[
Expand All @@ -911,7 +913,7 @@ def load_iotops_help():
examples:
- name: List all points in an asset dataset.
text: >
az iot ops asset dataset point list --asset myasset -g myresourcegroup --dataset dataset1
az iot ops asset dataset point list --asset myasset -g myresourcegroup --dataset default
"""

helps[
Expand All @@ -923,7 +925,7 @@ def load_iotops_help():
examples:
- name: Remove a data point from an asset via the data point name.
text: >
az iot ops asset dataset point remove --asset myasset -g myresourcegroup --dataset dataset1 --name data1
az iot ops asset dataset point remove --asset myasset -g myresourcegroup --dataset default --name data1
"""

helps[
Expand Down Expand Up @@ -976,10 +978,10 @@ def load_iotops_help():
short-summary: Import events in an asset.
long-summary: For examples of file formats, please see aka.ms/aziotops-assets
examples:
- name: Import all events from a file. These events will be appended to the asset's current events.
- name: Import all events from a file. These events will be appended to the asset's current events. Events with duplicate names will be ignored.
text: >
az iot ops asset event import --asset myasset -g myresourcegroup --input-file myasset_events.yaml
- name: Import all events from a file. These events will replace the asset's current events.
- name: Import all events from a file. These events will appended the asset's current events. Events with duplicate names will replace the current asset events.
text: >
az iot ops asset event import --asset myasset -g myresourcegroup --input-file myasset_events.csv --replace
"""
Expand Down
81 changes: 4 additions & 77 deletions azext_edge/edge/commands_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,66 +212,6 @@ def update_asset(


# Dataset commands
# TODO: multi dataset support
# def add_asset_dataset(
# cmd,
# asset_name: str,
# dataset_name: str,
# resource_group_name: str,
# data_points: Optional[List[str]] = None,
# data_point_file_path: Optional[str] = None,
# queue_size: Optional[int] = None,
# sampling_interval: Optional[int] = None,
# publishing_interval: Optional[int] = None,
# topic_path: Optional[str] = None,
# topic_retain: Optional[str] = None
# ):
# return Assets(cmd).add_dataset(
# asset_name=asset_name,
# dataset_name=dataset_name,
# resource_group_name=resource_group_name,
# data_points=data_points,
# data_point_file_path=data_point_file_path,
# queue_size=queue_size,
# sampling_interval=sampling_interval,
# publishing_interval=publishing_interval,
# topic_path=topic_path,
# topic_retain=topic_retain,
# )


# def export_asset_datasets(
# cmd,
# asset_name: str,
# resource_group_name: str,
# extension: str = "json",
# output_dir: str = ".",
# replace: bool = False
# ):
# return Assets(cmd).export_datasets(
# asset_name=asset_name,
# resource_group_name=resource_group_name,
# extension=extension,
# output_dir=output_dir,
# replace=replace
# )


# def import_asset_datasets(
# cmd,
# asset_name: str,
# file_path: str,
# resource_group_name: str,
# replace: bool = False
# ):
# return Assets(cmd).import_datasets(
# asset_name=asset_name,
# file_path=file_path,
# resource_group_name=resource_group_name,
# replace=replace
# )


def list_asset_datasets(
cmd,
asset_name: str,
Expand All @@ -296,19 +236,6 @@ def show_asset_dataset(
)


# def remove_asset_dataset(
# cmd,
# asset_name: str,
# dataset_name: str,
# resource_group_name: str
# ):
# return Assets(cmd).remove_dataset(
# asset_name=asset_name,
# dataset_name=dataset_name,
# resource_group_name=resource_group_name
# )


# Data Point sub commands
def add_asset_data_point(
cmd,
Expand All @@ -320,6 +247,7 @@ def add_asset_data_point(
observability_mode: Optional[str] = None,
queue_size: Optional[int] = None,
sampling_interval: Optional[int] = None,
replace: Optional[bool] = None
):
return Assets(cmd).add_dataset_data_point(
asset_name=asset_name,
Expand All @@ -330,6 +258,7 @@ def add_asset_data_point(
queue_size=queue_size,
sampling_interval=sampling_interval,
resource_group_name=resource_group_name,
replace=replace
)


Expand Down Expand Up @@ -407,8 +336,7 @@ def add_asset_event(
observability_mode: Optional[str] = None,
queue_size: Optional[int] = None,
sampling_interval: Optional[int] = None, # Note: not in DOE
# topic_path: Optional[str] = None, # TODO: expose once supported
# topic_retain: Optional[str] = None
replace: Optional[bool] = None
):
return Assets(cmd).add_event(
asset_name=asset_name,
Expand All @@ -418,8 +346,7 @@ def add_asset_event(
queue_size=queue_size,
sampling_interval=sampling_interval,
resource_group_name=resource_group_name,
# topic_path=topic_path,
# topic_retain=topic_retain
replace=replace,
)


Expand Down
31 changes: 24 additions & 7 deletions azext_edge/edge/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ def load_iotops_arguments(self, _):
options_list=["--data"],
nargs="+",
action="append",
help="Space-separated key=value pairs corresponding to properties of the data point to create. "
help="Space-separated key=value pairs corresponding to properties of the data-point to create. "
"The following key values are supported: `data_source` (required), `name` (required), "
"`observability_mode` (None, Gauge, Counter, Histogram, or Log), `sampling_interval` (int), "
"`queue_size` (int). "
Expand All @@ -619,7 +619,7 @@ def load_iotops_arguments(self, _):
context.argument(
"data_points_file_path",
options_list=["--data-file", "--df"],
help="File path for the file containing the data points. The following file types are supported: "
help="File path for the file containing the data-points. The following file types are supported: "
f"{', '.join(FileType.list())}.",
arg_group="Data-point",
)
Expand Down Expand Up @@ -843,7 +843,7 @@ def load_iotops_arguments(self, _):
context.argument(
"capability_id",
options_list=["--capability-id", "--ci"],
help="Capability Id. If not provided, data point name will be used.",
help="Capability Id. If not provided, data-point name will be used.",
)
context.argument(
"dataset_name",
Expand All @@ -866,6 +866,14 @@ def load_iotops_arguments(self, _):
help="Observability mode. Must be none, gauge, counter, histogram, or log.",
)

with self.argument_context("iot ops asset dataset point add") as context:
context.argument(
"replace",
options_list=["--replace"],
help="Replace the data-point if another data-point with the same name is present already.",
arg_type=get_three_state_flag(),
)

with self.argument_context("iot ops asset dataset point export") as context:
context.argument(
"replace",
Expand All @@ -878,14 +886,14 @@ def load_iotops_arguments(self, _):
context.argument(
"replace",
options_list=["--replace"],
help="Replace all asset data points with those from the file. If false, the file data points "
"will be appended.",
help="Replace duplicate asset data-points with those from the file. If false, the file data-points "
"will be ignored. Duplicate asset data-points will be determined by name.",
arg_type=get_three_state_flag(),
)
context.argument(
"file_path",
options_list=["--input-file", "--if"],
help="File path for the file containing the data points. The following file types are supported: "
help="File path for the file containing the data-points. The following file types are supported: "
f"{', '.join(FileType.list())}.",
)

Expand Down Expand Up @@ -916,6 +924,14 @@ def load_iotops_arguments(self, _):
help="Observability mode. Must be none or log.",
)

with self.argument_context("iot ops asset event add") as context:
context.argument(
"replace",
options_list=["--replace"],
help="Replace the event if another event with the same name is already present.",
arg_type=get_three_state_flag(),
)

with self.argument_context("iot ops asset event export") as context:
context.argument(
"replace",
Expand All @@ -928,7 +944,8 @@ def load_iotops_arguments(self, _):
context.argument(
"replace",
options_list=["--replace"],
help="Replace all asset events with those from the file. If false, the file events will be appended.",
help="Replace duplicate asset events with those from the file. If false, the file events "
"will be ignored. Duplicate asset events will be determined by name.",
arg_type=get_three_state_flag(),
)
context.argument(
Expand Down
26 changes: 18 additions & 8 deletions azext_edge/edge/providers/rpsaas/adr/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
)
# from azure.core.exceptions import ResourceNotFoundError

from .user_strings import INVALID_OBSERVABILITY_MODE_ERROR
from .user_strings import DUPLICATE_EVENT_ERROR, DUPLICATE_POINT_ERROR, INVALID_OBSERVABILITY_MODE_ERROR
from ....util import assemble_nargs_to_dict
from ....common import FileType
from ....util.az_client import get_registry_mgmt_client, wait_for_terminal_state
Expand Down Expand Up @@ -368,16 +368,20 @@ def add_dataset_data_point(
observability_mode: Optional[str] = None,
queue_size: Optional[int] = None,
sampling_interval: Optional[int] = None,
replace: bool = False
):
asset = self.show(
asset_name=asset_name,
resource_group_name=resource_group_name,
check_cluster=True
)
dataset = _get_dataset(asset, dataset_name, create_if_none=True)
if not dataset.get("dataPoints"):
dataset["dataPoints"] = []

dataset["dataPoints"] = dataset.get("dataPoints", [])
point_names = [point["name"] for point in dataset["dataPoints"]]
if not replace and data_point_name in point_names:
raise InvalidArgumentValueError(
DUPLICATE_POINT_ERROR.format(data_point_name)
)
sub_point = _build_asset_sub_point(
data_source=data_source,
name=data_point_name,
Expand Down Expand Up @@ -455,7 +459,7 @@ def import_dataset_data_points(
dataset["dataPoints"] = _process_asset_sub_points_file_path(
file_path=file_path,
original_items=dataset.get("dataPoints", []),
point_key="dataSource",
point_key="name",
replace=replace
)

Expand Down Expand Up @@ -524,14 +528,21 @@ def add_event(
queue_size: Optional[int] = None,
sampling_interval: Optional[int] = None,
topic_path: Optional[str] = None,
topic_retain: Optional[str] = None
topic_retain: Optional[str] = None,
replace: bool = False
):
asset = self.show(
asset_name=asset_name,
resource_group_name=resource_group_name,
check_cluster=True
)

asset["properties"]["events"] = asset["properties"].get("events", [])
event_names = [event["name"] for event in asset["properties"]["events"]]
if not replace and event_name in event_names:
raise InvalidArgumentValueError(
DUPLICATE_EVENT_ERROR.format(event_name)
)
sub_point = _build_asset_sub_point(
event_notifier=event_notifier,
name=event_name,
Expand All @@ -544,7 +555,6 @@ def add_event(
"path": topic_path,
"retain": topic_retain or "Never"
}
asset["properties"]["events"] = asset["properties"].get("events", [])
asset["properties"]["events"].append(sub_point)

# note that update does not return the properties
Expand Down Expand Up @@ -607,7 +617,7 @@ def import_events(
asset["properties"]["events"] = _process_asset_sub_points_file_path(
file_path=file_path,
original_items=asset["properties"].get("events", []),
point_key="eventNotifier",
point_key="name",
replace=replace
)

Expand Down
Loading