def setUp(self):
        change_dir()
        if self._testMethodName == "test_interface_life_cycle":
            interface = str(read_file_content(_interface_payload))
            _interface_id = "{}{}".format(
                json.loads(interface)["@id"], TestPnPModel.rand_val)
            self.kwargs.update({"interface_id": _interface_id})
            interface_newContent = interface.replace(
                json.loads(interface)["@id"], self.kwargs["interface_id"])
            interface_newContent = interface_newContent.replace("\n", "")

            fo = open(self.kwargs["interface"], "w+", encoding="utf-8")
            fo.write(interface_newContent)
            fo.close()

        if self._testMethodName == "test_model_life_cycle":
            model = str(read_file_content(_capability_model_payload))
            _model_id = "{}{}".format(
                json.loads(model)["@id"], TestPnPModel.rand_val)
            self.kwargs.update({"model_id": _model_id})
            model_newContent = model.replace(
                json.loads(model)["@id"], self.kwargs["model_id"])
            model_newContent = model_newContent.replace("\n", "")

            fo = open(self.kwargs["model"], "w+", encoding="utf-8")
            fo.write(model_newContent)
            fo.close()
예제 #2
0
def sample_config_metrics(set_cwd, request):
    path = "test_config_generic_metrics.json"

    payload = None
    if request.param == "inlineA":
        payload = json.dumps(json.loads(read_file_content(path)))
    elif request.param == "inlineB":
        payload = json.dumps(json.loads(read_file_content(path))["metrics"])
    elif request.param == "file":
        payload = get_context_path(__file__, path)

    return (request.param, payload)
예제 #3
0
def sample_config_adm(set_cwd, request):
    path_device = "test_adm_device_content.json"
    path_module = "test_adm_module_content.json"

    payload = None
    if request.param == "moduleFile":
        payload = get_context_path(__file__, path_module)
    elif request.param == "moduleInline":
        payload = json.dumps(json.loads(read_file_content(path_module)))
    elif request.param == "deviceFile":
        payload = get_context_path(__file__, path_device)
    elif request.param == "deviceInline":
        payload = json.dumps(json.loads(read_file_content(path_device)))

    return (request.param, payload)
예제 #4
0
    def test_iot_digitaltwin_invoke_command(self, fixture_cmd, serviceclient,
                                            command_payload):

        payload = None
        interface = "environmentalSensor"
        command = "blink"

        # If file path provided
        if not command_payload[0]:
            payload = command_payload[1]
        else:
            payload = str(
                read_file_content(_device_digitaltwin_invoke_command_payload))

        subject.iot_digitaltwin_invoke_command(
            fixture_cmd,
            device_id=device_id,
            interface=interface,
            command_name=command,
            command_payload=payload,
            login=mock_target["cs"],
        )
        args = serviceclient.call_args
        url = args[0][0].url
        method = args[0][0].method

        assert method == "POST"
        assert ("{}/digitalTwins/{}/interfaces/{}/commands/{}?".format(
            mock_target["entity"], device_id, interface, command) in url)
    def test_interface_create(self, fixture_cmd, serviceclient,
                              payload_scenario):
        payload = None

        # If file path provided
        if not payload_scenario[0]:
            payload = payload_scenario[1]
        else:
            payload = str(
                read_file_content(_pnp_create_interface_payload_file))

        subject.iot_pnp_interface_create(fixture_cmd,
                                         interface_definition=payload,
                                         login=mock_target["cs"])
        args = serviceclient.call_args
        url = args[0][0].url
        method = args[0][0].method
        data = args[0][0].data
        headers = args[0][0].headers

        assert method == "PUT"
        assert ("{}/models/{}?".format(
            _repo_endpoint, url_encode_str(_pnp_generic_interface_id,
                                           plus=True)) in url)
        assert "repositoryId={}".format(_repo_id) in url
        assert json.dumps(data)
        assert headers.get("Authorization")
def iot_digitaltwin_property_update(
    cmd,
    interface_payload,
    device_id,
    hub_name=None,
    resource_group_name=None,
    login=None,
):
    if exists(interface_payload):
        interface_payload = str(read_file_content(interface_payload))

    target_json = None
    try:
        target_json = shell_safe_json_parse(interface_payload)
    except ValueError:
        pass

    if target_json:
        interface_payload = target_json

    target = get_iot_hub_connection_string(cmd,
                                           hub_name,
                                           resource_group_name,
                                           login=login)
    service_sdk, errors = _bind_sdk(target, SdkType.service_sdk)
    try:
        result = service_sdk.update_interfaces(device_id,
                                               interfaces=interface_payload)
        return result
    except errors.CloudError as e:
        raise CLIError(unpack_msrest_error(e))
예제 #7
0
    def test_config_create_adm(
        self,
        fixture_cmd,
        serviceclient,
        sample_config_adm,
        sample_config_metrics,
        config_id,
        hub_name,
        target_condition,
        priority,
        labels,
    ):

        contentKey = (
            "moduleContent"
            if sample_config_adm[0].startswith("module")
            else "deviceContent"
        )

        if contentKey == "moduleContent":
            # Enforce the query prefix for success the case
            target_condition = "FROM devices.modules WHERE {}".format(target_condition)

        subject.iot_hub_configuration_create(
            cmd=fixture_cmd,
            config_id=config_id,
            hub_name=hub_name,
            content=sample_config_adm[1],
            target_condition=target_condition,
            priority=priority,
            labels=labels,
            metrics=sample_config_metrics[1],
        )

        args = serviceclient.call_args
        url = args[0][0].url
        method = args[0][0].method
        body = json.loads(args[0][0].body)

        assert "{}/configurations/{}?".format(hub_name, config_id.lower()) in url
        assert method == "PUT"
        assert body["id"] == config_id.lower()
        assert body.get("targetCondition") == target_condition
        assert body.get("priority") == priority
        assert body.get("labels") == evaluate_literal(labels, dict)

        if sample_config_adm[0].endswith("Inline"):
            assert (
                body["content"][contentKey]
                == json.loads(sample_config_adm[1])["content"][contentKey]
            )
        elif sample_config_adm[0].endswith("File"):
            assert (
                body["content"][contentKey]
                == json.loads(read_file_content(sample_config_adm[1]))["content"][
                    contentKey
                ]
            )

        self._assert_config_metrics_request(sample_config_metrics, body)
예제 #8
0
    def test_config_create_edge(
        self,
        fixture_cmd,
        serviceclient,
        sample_config_edge,
        sample_config_metrics,
        config_id,
        hub_name,
        target_condition,
        priority,
        labels,
    ):
        subject.iot_edge_deployment_create(
            cmd=fixture_cmd,
            config_id=config_id,
            hub_name=hub_name,
            content=sample_config_edge[1],
            target_condition=target_condition,
            priority=priority,
            labels=labels,
            metrics=sample_config_metrics[1],
            layered=(sample_config_edge[0] == "layered"),
        )

        args = serviceclient.call_args
        url = args[0][0].url
        method = args[0][0].method
        body = json.loads(args[0][0].body)

        assert "{}/configurations/{}?".format(hub_name, config_id.lower()) in url
        assert method == "PUT"
        assert body["id"] == config_id.lower()
        assert body.get("targetCondition") == target_condition
        assert body.get("priority") == priority
        assert body.get("labels") == evaluate_literal(labels, dict)

        if sample_config_edge[0] == "inlineB":
            assert (
                body["content"]["modulesContent"]
                == json.loads(sample_config_edge[1])["modulesContent"]
            )
        elif sample_config_edge[0] == "file":
            assert (
                body["content"]["modulesContent"]
                == json.loads(read_file_content(sample_config_edge[1]))["content"][
                    "modulesContent"
                ]
            )
        elif sample_config_edge[0] == "v1":
            assert (
                body["content"]["modulesContent"]
                == json.loads(sample_config_edge[1])["content"]["moduleContent"]
            )
        else:
            assert (
                body["content"]["modulesContent"]
                == json.loads(sample_config_edge[1])["content"]["modulesContent"]
            )

        self._assert_config_metrics_request(sample_config_metrics, body)
예제 #9
0
def iot_digitaltwin_invoke_command(cmd, interface, device_id, command_name, command_payload=None,
                                   timeout=10, hub_name=None, resource_group_name=None, login=None):
    device_interfaces = _iot_digitaltwin_interface_list(cmd, device_id, hub_name, resource_group_name, login)
    interface_list = _get_device_default_interface_dict(device_interfaces)

    target_interface = next((item for item in interface_list if item['name'] == interface), None)

    if not target_interface:
        raise CLIError('Target interface is not implemented by the device!')

    if command_payload:
        if exists(command_payload):
            command_payload = str(read_file_content(command_payload))

        target_json = None
        try:
            target_json = shell_safe_json_parse(command_payload)
        except ValueError:
            pass

        if target_json or isinstance(target_json, bool):
            command_payload = target_json

    target = get_iot_hub_connection_string(cmd, hub_name, resource_group_name, login=login)
    service_sdk, errors = _bind_sdk(target, SdkType.service_sdk)
    try:
        result = service_sdk.invoke_interface_command(device_id,
                                                      interface,
                                                      command_name,
                                                      command_payload,
                                                      connect_timeout_in_seconds=timeout,
                                                      response_timeout_in_seconds=timeout)
        return result
    except errors.CloudError as e:
        raise CLIError(unpack_msrest_error(e))
예제 #10
0
    def test_iot_digitaltwin_property_update(self, fixture_cmd, serviceclient,
                                             payload_scenario):

        payload = None

        # If file path provided
        if not payload_scenario[0]:
            payload = payload_scenario[1]
        else:
            payload = str(
                read_file_content(
                    _device_digitaltwin_property_update_payload_file))

        subject.iot_digitaltwin_property_update(
            fixture_cmd,
            device_id=device_id,
            interface_payload=payload,
            login=mock_target["cs"],
        )
        args = serviceclient.call_args
        url = args[0][0].url
        method = args[0][0].method

        assert method == "PATCH"
        assert ("{}/digitalTwins/{}/interfaces?".format(
            mock_target["entity"], device_id) in url)
예제 #11
0
    def test_config_apply_edge(
        self, fixture_cmd, serviceclient, device_id, hub_name, sample_config_edge
    ):
        # Not yet supporting layered deployments
        if sample_config_edge[0] == "layered":
            return

        result = subject.iot_edge_set_modules(
            cmd=fixture_cmd,
            device_id=device_id,
            hub_name=mock_target["entity"],
            content=sample_config_edge[1],
        )

        # For the actual apply configuration call
        args = serviceclient.call_args_list[0]
        url = args[0][0].url
        method = args[0][0].method
        body = json.loads(args[0][0].body)

        assert method == "POST"
        assert (
            "{}/devices/{}/applyConfigurationContent?".format(
                mock_target["entity"], device_id
            )
            in url
        )

        if sample_config_edge[0] == "inlineB":
            assert (
                body["modulesContent"]
                == json.loads(sample_config_edge[1])["modulesContent"]
            )
        elif sample_config_edge[0] == "file":
            assert (
                body["modulesContent"]
                == json.loads(read_file_content(sample_config_edge[1]))["content"][
                    "modulesContent"
                ]
            )
        elif sample_config_edge[0] == "v1":
            assert (
                body["modulesContent"]
                == json.loads(sample_config_edge[1])["content"]["moduleContent"]
            )
        else:
            assert (
                body["modulesContent"]
                == json.loads(sample_config_edge[1])["content"]["modulesContent"]
            )

        # For returning the set of module identities applied to the device
        args = serviceclient.call_args_list[1]
        url = args[0][0].url
        method = args[0][0].method

        assert method == "GET"
        assert "{}/devices/{}/modules?".format(mock_target["entity"], device_id) in url
        assert result is not None
    def test_model_create_invalid_payload(self, serviceclient):

        payload = str(read_file_content(_pnp_create_model_payload_file))
        payload = json.loads(payload)
        del payload["@id"]
        payload = json.dumps(payload)
        with pytest.raises(CLIError):
            dataplane.iot_pnp_model_create(fixture_cmd, model=payload)
def generate_pnp_model_create_payload(content_from_file=False):
    if content_from_file:
        return (None, _pnp_create_model_payload_file)

    return (
        str(read_file_content(_pnp_create_model_payload_file)),
        _pnp_create_model_payload_file,
    )
예제 #14
0
def sample_config_edge(set_cwd, request):
    path = "test_edge_deployment.json"
    layered_path = "test_edge_deployment_layered.json"
    v1_path = "test_edge_deployment_v1.json"
    v11_path = "test_edge_deployment_v11.json"
    ea_v11_eh_v12_path = "test_edge_deployment_ea_v11_eh_v12.json"
    ea_v90_eh_v91_path = "test_edge_deployment_ea_v90_eh_v91.json"

    payload = None
    if request.param == "inlineA":
        payload = json.dumps(json.loads(read_file_content(path)))
    elif request.param == "inlineB":
        payload = json.dumps(json.loads(read_file_content(path))["content"])
    elif request.param == "file":
        payload = get_context_path(__file__, path)
    elif request.param == "layered":
        payload = json.dumps(json.loads(read_file_content(layered_path)))
    elif request.param == "v1":
        payload = json.dumps(json.loads(read_file_content(v1_path)))
    elif request.param == "v11":
        payload = json.dumps(json.loads(read_file_content(v11_path)))
    elif request.param == "ea_v11_eh_v12":
        payload = json.dumps(json.loads(read_file_content(ea_v11_eh_v12_path)))
    elif request.param == "ea_v90_eh_v91":
        payload = json.dumps(json.loads(read_file_content(ea_v90_eh_v91_path)))

    return (request.param, payload)
예제 #15
0
def generate_device_digitaltwin_invoke_command_payload(content_from_file=False):
    change_dir()
    if content_from_file:
        return (None, _device_digitaltwin_invoke_command_payload)

    return (
        str(read_file_content(_device_digitaltwin_invoke_command_payload)),
        _device_digitaltwin_invoke_command_payload,
    )
예제 #16
0
def generate_device_digitaltwin_property_update_payload(content_from_file=False):
    change_dir()
    if content_from_file:
        return (None, _device_digitaltwin_property_update_payload_file)

    return (
        str(read_file_content(_device_digitaltwin_property_update_payload_file)),
        _device_digitaltwin_property_update_payload_file,
    )
def generate_pnp_interface_create_payload(content_from_file=False):
    change_dir()
    if content_from_file:
        return (None, _pnp_create_interface_payload_file)

    return (
        str(read_file_content(_pnp_create_interface_payload_file)),
        _pnp_create_interface_payload_file,
    )
    def test_model_create_invalid_payload(self, serviceclient):

        payload = str(read_file_content(_pnp_create_model_payload_file))
        payload = json.loads(payload)
        del payload["@id"]
        payload = json.dumps(payload)
        with pytest.raises(CLIError):
            subject.iot_pnp_model_create(fixture_cmd,
                                         login=mock_target["cs"],
                                         model_definition=payload)
예제 #19
0
 def _assert_config_metrics_request(self, sample_config_metrics, body):
     if sample_config_metrics[0]:
         if sample_config_metrics[0] == "inlineA":
             assert (body["metrics"] == json.loads(
                 sample_config_metrics[1])["metrics"])
         elif sample_config_metrics[0] == "inlineB":
             assert body["metrics"] == json.loads(sample_config_metrics[1])
         else:
             assert (body["metrics"] == json.loads(
                 read_file_content(sample_config_metrics[1]))["metrics"])
     else:
         assert body["metrics"] == {}
    def test_model_update_invalid_payload(self, serviceclient):

        payload = str(read_file_content(_pnp_create_model_payload_file))
        payload = json.loads(payload)
        payload["@id"] = "fake_invalid_id"
        payload = json.dumps(payload)
        with pytest.raises(CLIError):
            subject.iot_pnp_model_update(
                fixture_cmd,
                model_definition=payload,
                repo_endpoint=mock_target["entity"],
                repo_id=mock_target["repository_id"],
            )
 def test_model_update_error(self, fixture_cmd, serviceclient_generic_error,
                             payload_scenario):
     if not payload_scenario[0]:
         payload = payload_scenario[1]
     else:
         payload = str(read_file_content(_pnp_create_model_payload_file))
     with pytest.raises(CLIError):
         subject.iot_pnp_model_update(
             fixture_cmd,
             model_definition=payload,
             repo_endpoint=mock_target["entity"],
             repo_id=mock_target["repository_id"],
         )
    def test_model_create_error(self, fixture_cmd, serviceclient_generic_error,
                                content_from_file):
        payload = None
        payload_scenario = generate_pnp_model_create_payload(content_from_file)
        if not payload_scenario[0]:
            payload = payload_scenario[1]
        payload = str(read_file_content(_pnp_create_model_payload_file))

        payload = json.loads(payload)
        del payload["@id"]
        payload = json.dumps(payload)
        with pytest.raises(CLIError):
            dataplane.iot_pnp_model_create(
                fixture_cmd,
                model=payload,
            )
예제 #23
0
 def test_iot_digitaltwin_property_update_error(
     self, fixture_cmd, serviceclient_error, command_payload, interface, command
 ):
     payload = None
     if not command_payload[0]:
         payload = command_payload[1]
     else:
         payload = str(read_file_content(_device_digitaltwin_invoke_command_payload))
     with pytest.raises(CLIError):
         subject.iot_digitaltwin_invoke_command(
             fixture_cmd,
             device_id=device_id,
             interface=interface,
             command_name=command,
             command_payload=payload,
             login=mock_target["cs"],
         )
예제 #24
0
def _validate_model_definition(model_def):
    if exists(model_def):
        model_def = str(read_file_content(model_def))
    else:
        logger.info('Definition not from file path or incorrect path given.')

    try:
        return shell_safe_json_parse(model_def)
    except ValueError as e:
        logger.debug('Received definition: %s', model_def)
        if looks_like_file(model_def):
            raise CLIError(
                'The definition content looks like its from a file. Please ensure the path is correct.'
            )
        raise CLIError(
            'Malformed capability model definition. '
            'Use --debug to see what was received. Error details: {}'.format(
                e))
예제 #25
0
    def test_edge_set_modules(self):
        edge_device_count = 1
        edge_device_ids = self.generate_device_names(edge_device_count, True)

        self.cmd(
            "iot hub device-identity create -d {} -n {} -g {} --ee".format(
                edge_device_ids[0], LIVE_HUB, LIVE_RG
            )
        )

        self.kwargs["edge_content"] = read_file_content(edge_content_path)

        # Content from file
        self.cmd(
            "iot edge set-modules -d {} -n {} -g {} -k '{}'".format(
                edge_device_ids[0], LIVE_HUB, LIVE_RG, edge_content_path
            ),
            checks=[self.check("length([*])", 3)],
        )

        # Content inline
        self.cmd(
            "iot edge set-modules -d {} -n {} -g {} --content '{}'".format(
                edge_device_ids[0], LIVE_HUB, LIVE_RG, "{edge_content}"
            ),
            self.check("length([*])", 3),
        )

        # Using connection string - content from file
        self.cmd(
            "iot edge set-modules -d {} --login {} -k '{}'".format(
                edge_device_ids[0], self.connection_string, edge_content_v1_path
            ),
            checks=[self.check("length([*])", 4)],
        )

        # Error schema validation - Malformed deployment
        self.cmd(
            "iot edge set-modules -d {} -n {} -g {} -k '{}'".format(
                edge_device_ids[0], LIVE_HUB, LIVE_RG, edge_content_malformed_path
            ),
            expect_failure=True,
        )
def _process_models_directory(from_directory):
    from azext_iot.common.utility import scantree, process_json_arg, read_file_content
    # we need to double-encode the JSON string
    from json import dumps

    models = []
    if os.path.isfile(from_directory) and (from_directory.endswith(".json") or from_directory.endswith(".dtdl")):
        models.append(dumps(read_file_content(file_path=from_directory)))
        return models
    for entry in scantree(from_directory):
        if not any([entry.name.endswith(".json"), entry.name.endswith(".dtdl")]):
            logger.debug(
                "Skipping {} - model file must end with .json or .dtdl".format(
                    entry.path
                )
            )
            continue
        entry_json = process_json_arg(content=entry.path, argument_name=entry.name)

        models.append(dumps(entry_json))
    return models
    def setUp(self):
        if self._testMethodName == "test_model_lifecycle":

            roles = self.cmd(
                "iot pnp role-assignment list --resource-id {repo_id} --resource-type Tenant --subject-id {user_id} "
                "--pnp-dns-suffix {pnp_dns_suffix}")
            # check for TenantAdministrator
            try:
                roles = roles.get_output_in_json()
                role_assignments = list(
                    map(lambda role: role["subject"]["role"], roles))
                if RoleIdentifier.tenantAdmin.value not in role_assignments:
                    self.skipTest("Need TenantAdmin role to perform tests")
            except CLIError as e:
                self.skipTest(e)

            # Assign roles for model test

            self.cmd(
                "iot pnp role-assignment create --resource-id {repo_id} --resource-type Tenant --subject-id {user_id} "
                "--subject-type {user_type} --role ModelsCreator --pnp-dns-suffix {pnp_dns_suffix}"
            )

            self.cmd(
                "iot pnp role-assignment create --resource-id {repo_id} --resource-type Tenant --subject-id {user_id} "
                "--subject-type {user_type} --role ModelsPublisher --pnp-dns-suffix {pnp_dns_suffix}"
            )

            # Generate model ID

            model = str(read_file_content(_capability_model_payload))
            _model_id = self._generate_model_id(json.loads(model)["@id"])
            self.kwargs.update({"model_id": _model_id})
            model_newContent = model.replace(
                json.loads(model)["@id"], self.kwargs["model_id"])
            model_newContent = model_newContent.replace("\n", "")

            fo = open(self.kwargs["model"], "w+", encoding="utf-8")
            fo.write(model_newContent)
            fo.close()
    def test_model_create(self, fixture_cmd, serviceclient, content_from_file,
                          set_cwd):

        payload = None
        payload_scenario = generate_pnp_model_create_payload(content_from_file)
        # If file path provided
        if not payload_scenario[0]:
            payload = payload_scenario[1]
        payload = str(read_file_content(_pnp_create_model_payload_file))

        model_id = json.loads(payload)["@id"]
        dataplane.iot_pnp_model_create(
            cmd=fixture_cmd,
            model=payload,
        )
        args = serviceclient.call_args
        url = args[0][0].url
        method = args[0][0].method
        data = args[0][0].data

        assert method == "PUT"
        assert "/models/{}?".format(url_encode_str(model_id, plus=True)) in url
        assert json.dumps(data)
예제 #29
0
 def test_file_json(self, content, argname, set_cwd):
     result = process_json_arg(content, argument_name=argname)
     assert result == json.loads(read_file_content(content))
예제 #30
0
    def test_edge_deployments(self):
        config_count = 5
        config_ids = self.generate_config_names(config_count)

        self.kwargs["generic_metrics"] = read_file_content(generic_metrics_path)
        self.kwargs["edge_content"] = read_file_content(edge_content_path)
        self.kwargs["edge_content_layered"] = read_file_content(
            edge_content_layered_path
        )
        self.kwargs["edge_content_v1"] = read_file_content(edge_content_v1_path)
        self.kwargs["edge_content_malformed"] = read_file_content(
            edge_content_malformed_path
        )
        self.kwargs["labels"] = '{"key0": "value0"}'

        priority = random.randint(1, 10)
        condition = "tags.building=9 and tags.environment='test'"

        # Content inline
        # Note: $schema is included as a nested property in the sample content.
        self.cmd(
            """iot edge deployment create --deployment-id {} --hub-name {} --resource-group {} --priority {}
            --target-condition \"{}\" --labels '{}' --content '{}'""".format(
                config_ids[0],
                LIVE_HUB,
                LIVE_RG,
                priority,
                condition,
                "{labels}",
                "{edge_content}",
            ),
            checks=[
                self.check("id", config_ids[0]),
                self.check("priority", priority),
                self.check("targetCondition", condition),
                self.check("labels", json.loads(self.kwargs["labels"])),
                self.check(
                    "content.modulesContent",
                    json.loads(self.kwargs["edge_content"])["content"][
                        "modulesContent"
                    ],
                ),
                self.check("metrics.queries", {}),
            ],
        )

        # Using connection string - content + metrics from file. Configurations must be lowercase and will be lower()'ed.
        # Note: $schema is included as a nested property in the sample content.
        self.cmd(
            "iot edge deployment create -d {} --login {} --pri {} --tc \"{}\" --lab '{}' -k '{}' --metrics '{}'".format(
                config_ids[1].upper(),
                self.connection_string,
                priority,
                condition,
                "{labels}",
                edge_content_path,
                edge_content_path,
            ),
            checks=[
                self.check("id", config_ids[1].lower()),
                self.check("priority", priority),
                self.check("targetCondition", condition),
                self.check("labels", json.loads(self.kwargs["labels"])),
                self.check(
                    "content.modulesContent",
                    json.loads(self.kwargs["edge_content"])["content"][
                        "modulesContent"
                    ],
                ),
                self.check(
                    "metrics.queries",
                    json.loads(self.kwargs["edge_content"])["metrics"]["queries"],
                ),
            ],
        )

        # Using connection string - layered deployment with content + metrics from file.
        # No labels, target-condition or priority
        self.cmd(
            "iot edge deployment create -d {} --login {} -k '{}' --metrics '{}' --layered".format(
                config_ids[2].upper(),
                self.connection_string,
                edge_content_layered_path,
                generic_metrics_path,
            ),
            checks=[
                self.check("id", config_ids[2].lower()),
                self.check("priority", 0),
                self.check("targetCondition", ""),
                self.check("labels", None),
                self.check(
                    "content.modulesContent",
                    json.loads(self.kwargs["edge_content_layered"])["content"][
                        "modulesContent"
                    ],
                ),
                self.check(
                    "metrics.queries",
                    json.loads(self.kwargs["generic_metrics"])["metrics"]["queries"],
                ),
            ],
        )

        # Content inline - Edge v1 format
        self.cmd(
            """iot edge deployment create --deployment-id {} --hub-name {} --resource-group {} --priority {}
            --target-condition \"{}\" --labels '{}' --content '{}' --metrics '{}'""".format(
                config_ids[3],
                LIVE_HUB,
                LIVE_RG,
                priority,
                condition,
                "{labels}",
                "{edge_content_v1}",
                "{generic_metrics}",
            ),
            checks=[
                self.check("id", config_ids[3]),
                self.check("priority", priority),
                self.check("targetCondition", condition),
                self.check("labels", json.loads(self.kwargs["labels"])),
                self.check(
                    "content.modulesContent",
                    json.loads(self.kwargs["edge_content_v1"])["content"][
                        "moduleContent"
                    ],
                ),
                self.check(
                    "metrics.queries",
                    json.loads(self.kwargs["generic_metrics"])["metrics"]["queries"],
                ),
            ],
        )

        # Error schema validation - Malformed deployment content causes validation error
        self.cmd(
            """iot edge deployment create --deployment-id {} --hub-name {} --resource-group {} --priority {}
            --target-condition \"{}\" --labels '{}' --content '{}'""".format(
                config_ids[1],
                LIVE_HUB,
                LIVE_RG,
                priority,
                condition,
                "{labels}",
                "{edge_content_malformed}",
            ),
            expect_failure=True,
        )

        # Error schema validation - Layered deployment without flag causes validation error
        self.cmd(
            """iot edge deployment create --deployment-id {} --hub-name {} --resource-group {} --priority {}
            --target-condition \"{}\" --labels '{}' --content '{}'""".format(
                config_ids[1],
                LIVE_HUB,
                LIVE_RG,
                priority,
                condition,
                "{labels}",
                "{edge_content_layered}",
            ),
            expect_failure=True,
        )

        # Uses IoT Edge hub schema version 1.1
        self.cmd(
            """iot edge deployment create --deployment-id {} --hub-name {} --resource-group {} --priority {}
            --target-condition \"{}\" --labels '{}' --content '{}'""".format(
                config_ids[4],
                LIVE_HUB,
                LIVE_RG,
                priority,
                condition,
                "{labels}",
                edge_content_v11_path,
            ),
            checks=[
                self.check("id", config_ids[4]),
                self.check("priority", priority),
                self.check("targetCondition", condition),
                self.check("labels", json.loads(self.kwargs["labels"])),
                self.check(
                    "content.modulesContent",
                    json.loads(read_file_content(edge_content_v11_path))["modulesContent"],
                ),
                self.check("metrics.queries", {}),
            ],
        )

        # Show deployment
        self.cmd(
            "iot edge deployment show --deployment-id {} --hub-name {} --resource-group {}".format(
                config_ids[0], LIVE_HUB, LIVE_RG
            ),
            checks=[
                self.check("id", config_ids[0]),
                self.check("priority", priority),
                self.check("targetCondition", condition),
                self.check("labels", json.loads(self.kwargs["labels"])),
            ],
        )

        # Show deployment - using connection string
        self.cmd(
            "iot edge deployment show -d {} --login {}".format(
                config_ids[1], self.connection_string
            ),
            checks=[
                self.check("id", config_ids[1]),
                self.check("priority", priority),
                self.check("targetCondition", condition),
                self.check("labels", json.loads(self.kwargs["labels"])),
            ],
        )

        # Update deployment
        new_priority = random.randint(1, 10)
        new_condition = "tags.building=43 and tags.environment='dev'"
        self.kwargs["new_labels"] = '{"key": "super_value"}'
        self.cmd(
            "iot edge deployment update -d {} -n {} -g {} --set priority={} targetCondition=\"{}\" labels='{}'".format(
                config_ids[0],
                LIVE_HUB,
                LIVE_RG,
                new_priority,
                new_condition,
                "{new_labels}",
            ),
            checks=[
                self.check("id", config_ids[0]),
                self.check("priority", new_priority),
                self.check("targetCondition", new_condition),
                self.check("labels", json.loads(self.kwargs["new_labels"])),
            ],
        )

        # Update deployment - using connection string
        new_priority = random.randint(1, 10)
        new_condition = "tags.building=40 and tags.environment='kindaprod'"
        self.kwargs["new_labels"] = '{"key": "legit_value"}'
        self.cmd(
            "iot edge deployment update -d {} -n {} -g {} --set priority={} targetCondition=\"{}\" labels='{}'".format(
                config_ids[0],
                LIVE_HUB,
                LIVE_RG,
                new_priority,
                new_condition,
                "{new_labels}",
            ),
            checks=[
                self.check("id", config_ids[0]),
                self.check("priority", new_priority),
                self.check("targetCondition", new_condition),
                self.check("labels", json.loads(self.kwargs["new_labels"])),
            ],
        )

        # Evaluate metrics of a deployment
        user_metric_name = "mymetric"
        system_metric_name = "appliedCount"
        config_output = self.cmd(
            "iot edge deployment show --login {} --deployment-id {}".format(
                self.connection_string, config_ids[1]
            )
        ).get_output_in_json()

        # Default metric type is user
        self.cmd(
            "iot edge deployment show-metric --metric-id {} --deployment-id {} --hub-name {}".format(
                user_metric_name, config_ids[1], LIVE_HUB
            ),
            checks=[
                self.check("metric", user_metric_name),
                self.check(
                    "query", config_output["metrics"]["queries"][user_metric_name]
                ),
            ],
        )

        # System metric - using connection string
        self.cmd(
            "iot edge deployment show-metric --metric-id {} --login '{}' --deployment-id {} --metric-type {}".format(
                system_metric_name, self.connection_string, config_ids[1], "system"
            ),
            checks=[
                self.check("metric", system_metric_name),
                self.check(
                    "query",
                    config_output["systemMetrics"]["queries"][system_metric_name],
                ),
            ],
        )

        # Error - metric does not exist, using connection string
        self.cmd(
            "iot edge deployment show-metric -m {} --login {} -d {}".format(
                "doesnotexist", self.connection_string, config_ids[0]
            ),
            expect_failure=True,
        )

        config_list_check = [
            self.check("length([*])", config_count),
            self.exists("[?id=='{}']".format(config_ids[0])),
            self.exists("[?id=='{}']".format(config_ids[1])),
            self.exists("[?id=='{}']".format(config_ids[2])),
            self.exists("[?id=='{}']".format(config_ids[3]))
        ]

        # List all edge deployments
        self.cmd(
            "iot edge deployment list -n {} -g {}".format(LIVE_HUB, LIVE_RG),
            checks=config_list_check,
        )

        # List all edge deployments - using connection string
        self.cmd(
            "iot edge deployment list --login {}".format(self.connection_string),
            checks=config_list_check,
        )

        # Explicitly delete an edge deployment
        self.cmd(
            "iot edge deployment delete -d {} -n {} -g {}".format(
                config_ids[0], LIVE_HUB, LIVE_RG
            )
        )
        del self.config_ids[0]

        # Explicitly delete an edge deployment - using connection string
        self.cmd(
            "iot edge deployment delete -d {} --login {}".format(
                config_ids[1], self.connection_string
            )
        )
        del self.config_ids[0]