Skip to content

Commit

Permalink
dt deletion job (#676)
Browse files Browse the repository at this point in the history
  • Loading branch information
vilit1 authored Aug 1, 2023
1 parent 3638bc5 commit 23f65b0
Show file tree
Hide file tree
Showing 24 changed files with 864 additions and 85 deletions.
46 changes: 46 additions & 0 deletions azext_iot/digitaltwins/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,52 @@ def load_digitaltwins_help():
short-summary: Manage and configure jobs for a digital twin instance.
"""

helps["dt job deletion"] = """
type: group
short-summary: Manage and configure jobs for deleting model, twin and relationships data in a digital twin instance.
long-summary: A deletion job cannot be cancelled or deleted.
"""

helps["dt job deletion create"] = """
type: command
short-summary: Create and execute a deletion job on a digital twin instance.
long-summary: |
A deletion job cannot be cancelled or deleted.
The command will delete all models, twins, and relationships in the digital twin instance.
To delete only certain aspects in a digital twin instance, please see
- az dt twin relationship delete-all
- az dt twin delete-all
- az dt model delete-all
These commands will not show up in deletion job history.
examples:
- name: Creates a deletion job with a given job id.
text: >
az dt job deletion create -n {instance_or_hostname} -j {job_id}
- name: Creates a deletion job with a generated job id and no confirmation prompts.
text: >
az dt job deletion create -n {instance_or_hostname} -y
"""

helps["dt job deletion show"] = """
type: command
short-summary: Show details of a deletion job executed on a digital twins instance.
examples:
- name: Show details of a data deletion job by job id.
text: >
az dt job deletion show -n {instance_or_hostname} -j {job_id}
"""

helps["dt job deletion list"] = """
type: command
short-summary: List all deletion jobs executed on a digital twins instance.
examples:
- name: List all deletion jobs on a target digital twins instance.
text: >
az dt job deletion list -n {instance_or_hostname}
"""

helps["dt job import"] = """
type: group
short-summary: Manage and configure jobs for importing model, twin and relationships data to a digital twin instance.
Expand Down
16 changes: 15 additions & 1 deletion azext_iot/digitaltwins/command_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ def load_digitaltwins_commands(self, _):
cmd_group.command("list", "list_instances")
cmd_group.command("delete", "delete_instance", confirmation=True, supports_no_wait=True)
cmd_group.wait_command("wait", "wait_instance")
cmd_group.command("reset", "reset_instance", confirmation=True, is_preview=True)
cmd_group.command(
"reset",
"reset_instance",
confirmation=True,
deprecate_info=self.deprecate(redirect="az dt job delete-all create", hide=True)
)

with self.command_group(
"dt data-history",
Expand Down Expand Up @@ -237,3 +242,12 @@ def load_digitaltwins_commands(self, _):
cmd_group.command("list", "list_import_jobs")
cmd_group.command("delete", "delete_import_job", confirmation=True)
cmd_group.command("cancel", "cancel_import_job", confirmation=True)

with self.command_group(
"dt job deletion",
command_type=digitaltwins_job_ops,
is_preview=True
) as cmd_group:
cmd_group.command("create", "create_delete_job", confirmation=True)
cmd_group.show_command("show", "show_delete_job")
cmd_group.command("list", "list_delete_jobs")
18 changes: 18 additions & 0 deletions azext_iot/digitaltwins/commands_jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# --------------------------------------------------------------------------------------------

from azext_iot.digitaltwins.providers.import_job import ImportJobProvider
from azext_iot.digitaltwins.providers.deletion_job import DeletionJobProvider


def create_import_job(
Expand Down Expand Up @@ -38,3 +39,20 @@ def delete_import_job(cmd, name_or_hostname: str, job_id: str, resource_group_na
def cancel_import_job(cmd, name_or_hostname: str, job_id: str, resource_group_name: str = None):
import_job_provider = ImportJobProvider(cmd=cmd, name=name_or_hostname, rg=resource_group_name)
return import_job_provider.cancel(job_id=job_id)


def create_delete_job(
cmd, name_or_hostname: str, job_id: str = None, resource_group_name: str = None
):
delete_job_provider = DeletionJobProvider(cmd=cmd, name=name_or_hostname, rg=resource_group_name)
return delete_job_provider.create(job_id=job_id)


def show_delete_job(cmd, name_or_hostname: str, job_id: str, resource_group_name: str = None):
delete_job_provider = DeletionJobProvider(cmd=cmd, name=name_or_hostname, rg=resource_group_name)
return delete_job_provider.get(job_id=job_id)


def list_delete_jobs(cmd, name_or_hostname: str, resource_group_name: str = None):
delete_job_provider = DeletionJobProvider(cmd=cmd, name=name_or_hostname, rg=resource_group_name)
return delete_job_provider.list()
7 changes: 4 additions & 3 deletions azext_iot/digitaltwins/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,13 +667,14 @@ def load_digitaltwins_arguments(self, _):
"permissions are not in place. Setting this to 'true' does not delete any recorded data.",
)

with self.argument_context("dt job import") as context:
with self.argument_context("dt job") as context:
context.argument(
"job_id",
options_list=["--job-id", "-j"],
help="Id of bulk import job. A system generated id is assigned when this parameter is ommitted during job creation.",
arg_group="Bulk Import Job",
help="Id of job. A system generated id is assigned when this parameter is ommitted during job creation.",
)

with self.argument_context("dt job import") as context:
context.argument(
"data_file_name",
options_list=["--data-file", "--df"],
Expand Down
47 changes: 47 additions & 0 deletions azext_iot/digitaltwins/providers/deletion_job.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# 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 Optional
from azext_iot.common.utility import handle_service_exception
from azext_iot.digitaltwins.providers.base import DigitalTwinsProvider
from azext_iot.digitaltwins.providers import ErrorResponseException
from azext_iot.common.embedded_cli import EmbeddedCLI
from knack.log import get_logger
from uuid import uuid4

DEFAULT_DELETE_JOB_ID_PREFIX = "delete-job-"
logger = get_logger(__name__)


class DeletionJobProvider(DigitalTwinsProvider):
def __init__(self, cmd, name: str, rg: str = None):
super(DeletionJobProvider, self).__init__(cmd=cmd, name=name, rg=rg)
self.sdk = self.get_sdk().delete_jobs
self.cli = EmbeddedCLI(cli_ctx=cmd.cli_ctx)

def get(self, job_id: str):
try:
return self.sdk.get_by_id(job_id)
except ErrorResponseException as e:
handle_service_exception(e)

def list(self, top: int = None): # top is guarded for int() in arg def
from azext_iot.sdk.digitaltwins.dataplane.models import DeleteJobsListOptions

list_options = DeleteJobsListOptions(max_items_per_page=top)

try:
return self.sdk.list(import_jobs_list_options=list_options,)
except ErrorResponseException as e:
handle_service_exception(e)

def create(self, job_id: Optional[str] = None):
job_id = job_id if job_id else DEFAULT_DELETE_JOB_ID_PREFIX + str(uuid4()).replace("-", "")
self.sdk.config.operation_id = job_id
try:
return self.sdk.add(polling=False)
except ErrorResponseException as e:
handle_service_exception(e)
2 changes: 1 addition & 1 deletion azext_iot/digitaltwins/providers/import_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from knack.log import get_logger
from uuid import uuid4

DEFAULT_IMPORT_JOB_ID_PREFIX = "bulk-import-job-"
DEFAULT_IMPORT_JOB_ID_PREFIX = "import-job-"
logger = get_logger(__name__)


Expand Down
2 changes: 1 addition & 1 deletion azext_iot/monitor/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def _changed_props(self, prop, metadata, property_name):
return diff

def _is_component(self, prop):
return type(prop) == dict and prop.get(PNP_DTDLV2_COMPONENT_MARKER) == "c"
return isinstance(prop, dict) and prop.get(PNP_DTDLV2_COMPONENT_MARKER) == "c"

def _validate_payload(self, changes, minimum_severity):
for value in changes:
Expand Down
20 changes: 16 additions & 4 deletions azext_iot/sdk/digitaltwins/dataplane/azure_digital_twins_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .operations.digital_twins_operations import DigitalTwinsOperations
from .operations.event_routes_operations import EventRoutesOperations
from .operations.import_jobs_operations import ImportJobsOperations
from .operations.delete_jobs_operations import DeleteJobsOperations
from . import models


Expand All @@ -29,11 +30,14 @@ class AzureDigitalTwinsAPIConfiguration(AzureConfiguration):
:param credentials: Credentials needed for the client to connect to Azure.
:type credentials: :mod:`A msrestazure Credentials
object<msrestazure.azure_active_directory>`
:param operation_id: ID for the operation's status monitor. The ID is
generated if header was not passed by the client.
:type operation_id: str
:param str base_url: Service URL
"""

def __init__(
self, credentials, base_url=None):
self, credentials, operation_id=None, base_url=None):

if credentials is None:
raise ValueError("Parameter 'credentials' must not be None.")
Expand All @@ -46,6 +50,7 @@ def __init__(
self.add_user_agent('Azure-SDK-For-Python')

self.credentials = credentials
self.operation_id = operation_id


class AzureDigitalTwinsAPI(SDKClient):
Expand All @@ -64,21 +69,26 @@ class AzureDigitalTwinsAPI(SDKClient):
:vartype event_routes: dataplane.operations.EventRoutesOperations
:ivar import_jobs: ImportJobs operations
:vartype import_jobs: dataplane.operations.ImportJobsOperations
:ivar delete_jobs: DeleteJobs operations
:vartype delete_jobs: dataplane.operations.DeleteJobsOperations
:param credentials: Credentials needed for the client to connect to Azure.
:type credentials: :mod:`A msrestazure Credentials
object<msrestazure.azure_active_directory>`
:param operation_id: ID for the operation's status monitor. The ID is
generated if header was not passed by the client.
:type operation_id: str
:param str base_url: Service URL
"""

def __init__(
self, credentials, base_url=None):
self, credentials, operation_id=None, base_url=None):

self.config = AzureDigitalTwinsAPIConfiguration(credentials, base_url)
self.config = AzureDigitalTwinsAPIConfiguration(credentials, operation_id, base_url)
super(AzureDigitalTwinsAPI, self).__init__(self.config.credentials, self.config)

client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
self.api_version = '2023-06-30'
self.api_version = '2023-07-31-preview'
self._serialize = Serializer(client_models)
self._deserialize = Deserializer(client_models)

Expand All @@ -92,3 +102,5 @@ def __init__(
self._client, self.config, self._serialize, self._deserialize)
self.import_jobs = ImportJobsOperations(
self._client, self.config, self._serialize, self._deserialize)
self.delete_jobs = DeleteJobsOperations(
self._client, self.config, self._serialize, self._deserialize)
12 changes: 12 additions & 0 deletions azext_iot/sdk/digitaltwins/dataplane/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from .inner_error_py3 import InnerError
from .error_py3 import Error
from .import_job_py3 import ImportJob
from .delete_job_py3 import DeleteJob
from .error_response_py3 import ErrorResponse, ErrorResponseException
from .digital_twin_models_add_options_py3 import DigitalTwinModelsAddOptions
from .digital_twin_models_list_options_py3 import DigitalTwinModelsListOptions
Expand Down Expand Up @@ -47,13 +48,18 @@
from .import_jobs_get_by_id_options_py3 import ImportJobsGetByIdOptions
from .import_jobs_delete_options_py3 import ImportJobsDeleteOptions
from .import_jobs_cancel_options_py3 import ImportJobsCancelOptions
from .delete_jobs_add_options_py3 import DeleteJobsAddOptions
from .delete_jobs_list_options_py3 import DeleteJobsListOptions
from .delete_jobs_get_by_id_options_py3 import DeleteJobsGetByIdOptions
from .digital_twins_model_data_paged import DigitalTwinsModelDataPaged
from .object_paged import ObjectPaged
from .incoming_relationship_paged import IncomingRelationshipPaged
from .event_route_paged import EventRoutePaged
from .import_job_paged import ImportJobPaged
from .delete_job_paged import DeleteJobPaged
from .azure_digital_twins_api_enums import (
Status,
DeleteJobStatus,
)

__all__ = [
Expand All @@ -65,6 +71,7 @@
'InnerError',
'Error',
'ImportJob',
'DeleteJob',
'ErrorResponse', 'ErrorResponseException',
'DigitalTwinModelsAddOptions',
'DigitalTwinModelsListOptions',
Expand Down Expand Up @@ -95,10 +102,15 @@
'ImportJobsGetByIdOptions',
'ImportJobsDeleteOptions',
'ImportJobsCancelOptions',
'DeleteJobsAddOptions',
'DeleteJobsListOptions',
'DeleteJobsGetByIdOptions',
'DigitalTwinsModelDataPaged',
'ObjectPaged',
'IncomingRelationshipPaged',
'EventRoutePaged',
'ImportJobPaged',
'DeleteJobPaged',
'Status',
'DeleteJobStatus',
]
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@ class Status(str, Enum):
succeeded = "succeeded"
cancelling = "cancelling"
cancelled = "cancelled"


class DeleteJobStatus(str, Enum):

notstarted = "notstarted"
running = "running"
failed = "failed"
succeeded = "succeeded"
27 changes: 27 additions & 0 deletions azext_iot/sdk/digitaltwins/dataplane/models/delete_job_paged.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# 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.
#
# Code generated by Microsoft (R) AutoRest Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is
# regenerated.
# --------------------------------------------------------------------------

from msrest.paging import Paged


class DeleteJobPaged(Paged):
"""
A paging container for iterating over a list of :class:`DeleteJob <dataplane.models.DeleteJob>` object
"""

_attribute_map = {
'next_link': {'key': 'nextLink', 'type': 'str'},
'current_page': {'key': 'value', 'type': '[DeleteJob]'}
}

def __init__(self, *args, **kwargs):

super(DeleteJobPaged, self).__init__(*args, **kwargs)
Loading

0 comments on commit 23f65b0

Please sign in to comment.