Esempio n. 1
0
def delete_by_id(host_id_list):
    current_identity = get_current_identity()
    payload_tracker = get_payload_tracker(
        account=current_identity.account_number,
        request_id=threadctx.request_id)

    with PayloadTrackerContext(payload_tracker,
                               received_status_message="delete operation",
                               current_operation="delete"):
        query = _get_host_list_by_id_list(host_id_list)

        if not query.count():
            flask.abort(status.HTTP_404_NOT_FOUND)

        for host_id, deleted in delete_hosts(
                query, current_app.event_producer,
                inventory_config().host_delete_chunk_size):
            if deleted:
                log_host_delete_succeeded(logger, host_id, get_control_rule())
                tracker_message = "deleted host"
            else:
                log_host_delete_failed(logger, host_id)
                tracker_message = "not deleted host"

            with PayloadTrackerProcessingContext(
                    payload_tracker, processing_status_message=tracker_message
            ) as payload_tracker_processing_ctx:
                payload_tracker_processing_ctx.inventory_id = host_id

    return flask.Response(None, status.HTTP_200_OK)
Esempio n. 2
0
def handle_message(message, event_producer):
    validated_operation_msg = parse_operation_message(message)
    platform_metadata = validated_operation_msg.get("platform_metadata") or {}

    # create a dummy identity for working around the identity requirement for CRUD operations
    identity = Identity(USER_IDENTITY)

    # set account_number in dummy idenity to the actual account_number received in the payload
    identity.account_number = validated_operation_msg["data"]["account"]

    request_id = platform_metadata.get("request_id", "-1")
    initialize_thread_local_storage(request_id)

    payload_tracker = get_payload_tracker(request_id=request_id)

    with PayloadTrackerContext(payload_tracker,
                               received_status_message="message received",
                               current_operation="handle_message"):
        output_host, host_id, insights_id, add_results = add_host(
            validated_operation_msg["data"], identity)
        event_type = add_host_results_to_event_type(add_results)
        event = build_event(event_type,
                            output_host,
                            platform_metadata=platform_metadata)

        headers = message_headers(add_results, insights_id)
        event_producer.write_event(event, str(host_id), headers, Topic.egress)

        # for transition to platform.inventory.events
        if inventory_config().secondary_topic_enabled:
            event_producer.write_event(event, str(host_id), headers,
                                       Topic.events)
Esempio n. 3
0
def delete_by_id(host_id_list):
    payload_tracker = get_payload_tracker(account=current_identity.account_number, request_id=threadctx.request_id)

    with PayloadTrackerContext(
        payload_tracker, received_status_message="delete operation", current_operation="delete"
    ):
        query = _get_host_list_by_id_list(current_identity.account_number, host_id_list)

        if not query.count():
            flask.abort(status.HTTP_404_NOT_FOUND)

        for host_id, deleted in delete_hosts(query, current_app.event_producer):
            if deleted:
                logger.info("Deleted host: %s", host_id)
                tracker_message = "deleted host"
            else:
                logger.info("Host %s already deleted. Delete event not emitted.", host_id)
                tracker_message = "not deleted host"

            with PayloadTrackerProcessingContext(
                payload_tracker, processing_status_message=tracker_message
            ) as payload_tracker_processing_ctx:
                payload_tracker_processing_ctx.inventory_id = host_id

    return flask.Response(None, status.HTTP_200_OK)
Esempio n. 4
0
def add_host_list(host_list):
    response_host_list = []
    number_of_errors = 0

    payload_tracker = get_payload_tracker(
        account=current_identity.account_number,
        payload_id=threadctx.request_id)

    with PayloadTrackerContext(payload_tracker,
                               received_status_message="add host operation"):

        for host in host_list:
            try:
                with PayloadTrackerProcessingContext(
                        payload_tracker,
                        processing_status_message="adding/updating host"
                ) as payload_tracker_processing_ctx:
                    input_host = deserialize_host(host)
                    (output_host, add_result) = _add_host(input_host)
                    status_code = _convert_host_results_to_http_status(
                        add_result)
                    response_host_list.append({
                        "status": status_code,
                        "host": output_host
                    })
                    payload_tracker_processing_ctx.inventory_id = output_host[
                        "id"]
            except ValidationException as e:
                number_of_errors += 1
                logger.exception("Input validation error while adding host",
                                 extra={"host": host})
                response_host_list.append({
                    **e.to_json(), "title": "Bad Request",
                    "host": host
                })
            except InventoryException as e:
                number_of_errors += 1
                logger.exception("Error adding host", extra={"host": host})
                response_host_list.append({**e.to_json(), "host": host})
            except Exception:
                number_of_errors += 1
                logger.exception("Error adding host", extra={"host": host})
                response_host_list.append({
                    "status": 500,
                    "title": "Error",
                    "type": "unknown",
                    "detail": "Could not complete operation",
                    "host": host,
                })

        response = {
            "total": len(response_host_list),
            "errors": number_of_errors,
            "data": response_host_list
        }
        return _build_json_response(response, status=207)
Esempio n. 5
0
def handle_message(message, event_producer):
    validated_operation_msg = parse_operation_message(message)
    platform_metadata = validated_operation_msg.get("platform_metadata") or {}
    initialize_thread_local_storage(platform_metadata)

    payload_tracker = get_payload_tracker(request_id=threadctx.request_id)

    with PayloadTrackerContext(payload_tracker, received_status_message="message received"):
        (output_host, add_results) = add_host(validated_operation_msg["data"])
        event = build_egress_topic_event(add_results.name, output_host, platform_metadata)
        event_producer.write_event(event, output_host["id"], message_headers(add_results.name))
    def test_payload_tracker_context_error(self, datetime_mock):
        expected_request_id = "REQUEST_ID"
        expected_received_status_msg = "ima received msg"

        producer = Mock()

        tracker = self._get_tracker(request_id=expected_request_id,
                                    producer=producer)

        operations = [None, "test operation"]

        for current_operation in operations:
            with self.subTest(current_operation=current_operation):

                with self.assertRaises(ValueError):
                    with PayloadTrackerContext(
                            payload_tracker=tracker,
                            received_status_message=
                            expected_received_status_msg,
                            current_operation=current_operation,
                    ):

                        expected_msg = self._build_expected_message(
                            status="received",
                            status_msg=expected_received_status_msg,
                            request_id=expected_request_id,
                            datetime_mock=datetime_mock,
                        )

                        self._verify_mock_send_call(producer,
                                                    self.DEFAULT_TOPIC,
                                                    expected_msg)
                        producer.reset_mock()
                        method_to_raise_exception()

                expected_msg = self._build_expected_message(
                    status="error",
                    status_msg=self.
                    _build_payload_tracker_context_error_message(
                        "ValueError", current_operation,
                        "something bad happened!"),
                    request_id=expected_request_id,
                    datetime_mock=datetime_mock,
                )

                self._verify_mock_send_call(producer, self.DEFAULT_TOPIC,
                                            expected_msg)

                producer.reset_mock()
    def test_payload_tracker_context_error(self, datetime_mock):
        expected_request_id = "REQUEST_ID"
        expected_received_status_msg = "ima received msg"

        producer = Mock()

        tracker = self._get_tracker(request_id=expected_request_id,
                                    producer=producer)

        error_status_msgs = [None, "ima error status msg"]

        for error_status_msg in error_status_msgs:
            with self.subTest(error_status_msg=error_status_msg):

                with self.assertRaises(ValueError):
                    with PayloadTrackerContext(
                            payload_tracker=tracker,
                            received_status_message=
                            expected_received_status_msg,
                            error_status_message=error_status_msg,
                    ):

                        expected_msg = self._build_expected_message(
                            status="received",
                            status_msg=expected_received_status_msg,
                            request_id=expected_request_id,
                            datetime_mock=datetime_mock,
                        )

                        self._verify_mock_send_call(producer,
                                                    self.DEFAULT_TOPIC,
                                                    expected_msg)
                        producer.reset_mock()
                        method_to_raise_exception()

                expected_msg = self._build_expected_message(
                    status="error",
                    status_msg=error_status_msg,
                    request_id=expected_request_id,
                    datetime_mock=datetime_mock,
                )

                self._verify_mock_send_call(producer, self.DEFAULT_TOPIC,
                                            expected_msg)

                producer.reset_mock()
    def test_payload_tracker_context_success(self, datetime_mock):
        expected_request_id = "REQUEST_ID"
        expected_received_status_msg = "ima received msg"

        producer = Mock()

        tracker = self._get_tracker(request_id=expected_request_id,
                                    producer=producer)

        success_status_msgs = [None, "ima success status msg"]

        for success_status_msg in success_status_msgs:
            with self.subTest(success_status_msg=success_status_msg):

                with PayloadTrackerContext(
                        payload_tracker=tracker,
                        received_status_message=expected_received_status_msg,
                        success_status_message=success_status_msg,
                ):

                    expected_msg = self._build_expected_message(
                        status="received",
                        status_msg=expected_received_status_msg,
                        request_id=expected_request_id,
                        datetime_mock=datetime_mock,
                    )

                    self._verify_mock_send_call(producer, self.DEFAULT_TOPIC,
                                                expected_msg)

                    producer.reset_mock()

                expected_msg = self._build_expected_message(
                    status="success",
                    status_msg=success_status_msg,
                    request_id=expected_request_id,
                    datetime_mock=datetime_mock,
                )

                self._verify_mock_send_call(producer, self.DEFAULT_TOPIC,
                                            expected_msg)

                producer.reset_mock()
def handle_message(message, event_producer):
    validated_operation_msg = parse_operation_message(message)
    platform_metadata = validated_operation_msg.get("platform_metadata") or {}

    request_id = platform_metadata.get("request_id", "-1")
    initialize_thread_local_storage(request_id)

    payload_tracker = get_payload_tracker(request_id=request_id)

    with PayloadTrackerContext(
        payload_tracker, received_status_message="message received", current_operation="handle_message"
    ):
        (output_host, add_results) = add_host(validated_operation_msg["data"])
        event_type = add_host_results_to_event_type(add_results)
        event = build_event(event_type, output_host, platform_metadata=platform_metadata)
        event_producer.write_event(event, output_host["id"], message_headers(add_results), Topic.egress)

        # for transition to platform.inventory.events
        if inventory_config().secondary_topic_enabled:
            event_producer.write_event(event, output_host["id"], message_headers(add_results), Topic.events)
def handle_message(message, event_producer):
    validated_operation_msg = parse_operation_message(message)
    metadata = validated_operation_msg.get("platform_metadata") or {}
    initialize_thread_local_storage(metadata)

    payload_tracker = get_payload_tracker(payload_id=threadctx.request_id)

    with PayloadTrackerContext(payload_tracker,
                               received_status_message="message received"):

        # FIXME: verify operation type
        (output_host, add_results) = add_host(validated_operation_msg["data"])

        if add_results == host_repository.AddHostResults.created:
            event_type = "created"
        else:
            event_type = "updated"

        event = build_event(event_type, output_host, metadata)

        event_producer.write_event(event, output_host["id"])
Esempio n. 11
0
def delete_by_id(host_id_list):
    payload_tracker = get_payload_tracker(
        account=current_identity.account_number,
        payload_id=threadctx.request_id)

    with PayloadTrackerContext(payload_tracker,
                               received_status_message="delete operation"):

        query = _get_host_list_by_id_list(current_identity.account_number,
                                          host_id_list)

        hosts_to_delete = query.all()

        if not hosts_to_delete:
            return flask.abort(status.HTTP_404_NOT_FOUND)

        with metrics.delete_host_processing_time.time():
            query.delete(synchronize_session="fetch")
        db.session.commit()

        metrics.delete_host_count.inc(len(hosts_to_delete))

        # This process of checking for an already deleted host relies
        # on checking the session after it has been updated by the commit()
        # function and marked the deleted hosts as expired.  It is after this
        # change that the host is called by a new query and, if deleted by a
        # different process, triggers the ObjectDeletedError and is not emited.
        for deleted_host in hosts_to_delete:
            # Prevents ObjectDeletedError from being raised.
            if instance_state(deleted_host).expired:
                # Can’t log the Host ID. Accessing an attribute raises ObjectDeletedError.
                logger.info("Host already deleted. Delete event not emitted.")
            else:
                with PayloadTrackerProcessingContext(
                        payload_tracker,
                        processing_status_message="deleted host"
                ) as payload_tracker_processing_ctx:
                    logger.debug("Deleted host: %s", deleted_host)
                    emit_event(events.delete(deleted_host))
                    payload_tracker_processing_ctx.inventory_id = deleted_host.id
Esempio n. 12
0
def handle_message(message, event_producer, message_operation=add_host):
    validated_operation_msg = parse_operation_message(message)
    platform_metadata = validated_operation_msg.get("platform_metadata", {})

    request_id = platform_metadata.get("request_id", UNKNOWN_REQUEST_ID_VALUE)
    initialize_thread_local_storage(request_id)

    payload_tracker = get_payload_tracker(request_id=request_id)

    with PayloadTrackerContext(payload_tracker,
                               received_status_message="message received",
                               current_operation="handle_message"):
        try:
            host = validated_operation_msg["data"]

            output_host, host_id, insights_id, operation_result = message_operation(
                host, platform_metadata)
            event_type = operation_results_to_event_type(operation_result)
            event = build_event(event_type,
                                output_host,
                                platform_metadata=platform_metadata)

            headers = message_headers(operation_result, insights_id)
            event_producer.write_event(event, str(host_id), headers)
        except ValidationException as ve:
            logger.error(
                "Validation error while adding or updating host: %s",
                ve,
                extra={"host": {
                    "reporter": host.get("reporter")
                }},
            )
            raise
        except ValueError as ve:
            logger.error("Value error while adding or updating host: %s",
                         ve,
                         extra={"reporter": host.get("reporter")})
            raise
Esempio n. 13
0
def add_host_list(body):
    if not inventory_config().rest_post_enabled:
        return flask_json_response(
            {
                "detail": "The method is not allowed for the requested URL.",
                "status": 405,
                "title": "Method Not Allowed",
                "type": "about:blank",
            },
            status=405,
        )
    reporter = None

    response_host_list = []
    number_of_errors = 0

    payload_tracker = get_payload_tracker(account=current_identity.account_number, request_id=threadctx.request_id)

    with PayloadTrackerContext(
        payload_tracker, received_status_message="add host operation", current_operation="add host"
    ):

        for host in body:
            try:
                with PayloadTrackerProcessingContext(
                    payload_tracker,
                    processing_status_message="adding/updating host",
                    current_operation="adding/updating host",
                ) as payload_tracker_processing_ctx:
                    if host.get("tags"):
                        tags_ignored_from_http_count.inc()
                        logger.info("Tags from an HTTP request were ignored")

                    input_host = deserialize_host_http(host)
                    output_host, host_id, _, add_result = _add_host(input_host)
                    status_code = _convert_host_results_to_http_status(add_result)
                    response_host_list.append({"status": status_code, "host": output_host})
                    payload_tracker_processing_ctx.inventory_id = host_id

                    reporter = host.get("reporter")
            except ValidationException as e:
                number_of_errors += 1
                logger.exception("Input validation error while adding host", extra={"host": host})
                response_host_list.append({**e.to_json(), "title": "Bad Request", "host": host})
            except InventoryException as e:
                number_of_errors += 1
                logger.exception("Error adding host", extra={"host": host})
                response_host_list.append({**e.to_json(), "host": host})
            except Exception:
                number_of_errors += 1
                logger.exception("Error adding host", extra={"host": host})
                response_host_list.append(
                    {
                        "status": 500,
                        "title": "Error",
                        "type": "unknown",
                        "detail": "Could not complete operation",
                        "host": host,
                    }
                )

        rest_post_request_count.labels(reporter=reporter).inc()

        response = {"total": len(response_host_list), "errors": number_of_errors, "data": response_host_list}
        return flask_json_response(response, status=207)