Beispiel #1
0
    def test_missing_hsp_in_list(self):
        # get a 404 if one out of two records is missing
        with self.test_flask_app.app_context():
            db_interface.create_profile("eca1c5c4-ab27-11ea-958a-98fa9b07d419",
                                        {}, "1234", "5678")

        self.addInventoryRecord("eca1c5c4-ab27-11ea-958a-98fa9b07d419",
                                "test_name")
        response = self.client.get(
            "/api/historical-system-profiles/v1/systems/eca1c5c4-ab27-11ea-958a-98fa9b07d419",
            headers=fixtures.AUTH_HEADER,
        )
        data = json.loads(response.data)
        valid_profile_id = data["data"][0]["profiles"][0]["id"]

        # NB: we are fetching individual profiles now, not the list of profiles for the system
        response = self.client.get(
            f"/api/historical-system-profiles/v1/profiles/{valid_profile_id}",
            headers=fixtures.AUTH_HEADER,
        )
        self.assertEqual(response.status_code, 200)

        response = self.client.get(
            f"/api/historical-system-profiles/v1/profiles/{valid_profile_id}"
            ",9db484bc-ab2a-11ea-9a15-98fa9b07d419",
            headers=fixtures.AUTH_HEADER,
        )
        self.assertEqual(response.status_code, 404)
        self.assertEqual(
            response.json["message"],
            "ids [9db484bc-ab2a-11ea-9a15-98fa9b07d419] not available to display",
        )
Beispiel #2
0
    def test_save_model(self):
        # confirm there are zero records associated with an inventory ID
        response = self.client.get(
            "/api/historical-system-profiles/v1/systems/29dbe6ce-897f-11ea-8f75-98fa9b07d419",
            headers=fixtures.AUTH_HEADER,
        )
        data = json.loads(response.data)
        self.assertEqual(response.status_code, 404)

        # add one record, confirm count
        with self.test_flask_app.app_context():
            # NB: this is an INVENTORY id, not HSP id! HSP ids are generated at creation time.
            db_interface.create_profile("29dbe6ce-897f-11ea-8f75-98fa9b07d419",
                                        {}, "1234", "5678")

        response = self.client.get(
            "/api/historical-system-profiles/v1/systems/29dbe6ce-897f-11ea-8f75-98fa9b07d419",
            headers=fixtures.AUTH_HEADER,
        )
        data = json.loads(response.data)
        self.assertEquals(1, len(data["data"][0]["profiles"]))

        # delete all records, confirm count
        with self.test_flask_app.app_context():
            # inventory ID is the only way to reference records to delete
            db_interface.delete_hsps_by_inventory_id(
                "29dbe6ce-897f-11ea-8f75-98fa9b07d419")

        response = self.client.get(
            "/api/historical-system-profiles/v1/systems/29dbe6ce-897f-11ea-8f75-98fa9b07d419",
            headers=fixtures.AUTH_HEADER,
        )
        data = json.loads(response.data)
        self.assertEqual(response.status_code, 404)
Beispiel #3
0
    def test_create_delete_hsp(self):
        # this test requires accessing some data via the DB interface. We don't
        # expose create or delete via the API.

        # confirm there are zero records to start
        response = self.client.get(
            "/api/historical-system-profiles/v1/systems/6887d404-ab27-11ea-b3ae-98fa9b07d419",
            headers=fixtures.AUTH_HEADER,
        )
        data = json.loads(response.data)
        self.assertEqual(response.status_code, 404)

        # add one record, confirm count
        with self.test_flask_app.app_context():
            db_interface.create_profile("6887d404-ab27-11ea-b3ae-98fa9b07d419",
                                        {}, "1234", "5678")

        response = self.client.get(
            "/api/historical-system-profiles/v1/systems/6887d404-ab27-11ea-b3ae-98fa9b07d419",
            headers=fixtures.AUTH_HEADER,
        )
        data = json.loads(response.data)
        self.assertEquals(1, len(data["data"][0]["profiles"]))

        # delete all records, confirm count
        with self.test_flask_app.app_context():
            db_interface.delete_hsps_by_inventory_id(
                "6887d404-ab27-11ea-b3ae-98fa9b07d419")

        response = self.client.get(
            "/api/historical-system-profiles/v1/systems/6887d404-ab27-11ea-b3ae-98fa9b07d419",
            headers=fixtures.AUTH_HEADER,
        )
        data = json.loads(response.data)
        self.assertEqual(response.status_code, 404)
Beispiel #4
0
    def test_pagination(self):
        # create inventory record
        self.addInventoryRecord(
            "16c1b34a-bf78-494e-ba3d-fe7dc1b18459",
            "pagination_test_system_display_name",
        )

        # create four profiles, iterating "some_fact" to simulate check-ins for this host
        # 1234 is the account number
        # 5678 is the org id
        with self.test_flask_app.app_context():
            for i in range(4):
                db_interface.create_profile(
                    "16c1b34a-bf78-494e-ba3d-fe7dc1b18459",
                    {"some_fact": f"some_value_{i}"},
                    "1234",
                    "5678",
                )

        # fetch the system profiles providing limit and offset
        response = self.client.get(
            "/api/historical-system-profiles/v1/systems/16c1b34a-bf78-494e-ba3d-fe7dc1b18459"
            "?limit=2&offset=1",
            headers=fixtures.AUTH_HEADER,
        )

        returned_profiles = response.json["data"][0]["profiles"]

        # assert that the limit works
        self.assertEqual(len(returned_profiles), 2)

        # get the fact from a particular profile
        profile_id = returned_profiles[1]["id"]
        profile_response = self.client.get(
            f"/api/historical-system-profiles/v1/profiles/{profile_id}",
            headers=fixtures.AUTH_HEADER,
        )
        some_value = profile_response.json["data"][0]["system_profile"][
            "some_fact"]

        # assert that the offset works by comparing the fact for the profile in that position
        self.assertEqual(some_value, "some_value_1")
Beispiel #5
0
def archiver_event_loop(flask_app, logger):
    consumer = init_consumer("platform.inventory.host-egress")
    with flask_app.app_context():
        while True:
            for data in consumer:
                try:
                    host = data.value["host"]
                    profile = host["system_profile"]
                    # fqdn is on the host but we need it in the profile as well
                    profile["fqdn"] = host["fqdn"]
                    db_interface.create_profile(
                        inventory_id=host["id"],
                        profile=profile,
                        account_number=host["account"],
                    )
                    logger.info(
                        "wrote inventory_id %s's profile to historical database"
                        % host["id"]
                    )
                except Exception:
                    logger.exception("An error occurred during message processing")
Beispiel #6
0
def _archive_profile(data, ptc, logger):
    """
    given an event, archive a profile and emit a success message
    """
    if data.value["type"] not in ("created", "updated"):
        logger.info("skipping message that is not created or updated type")
        return

    host = data.value["host"]
    request_id = _get_request_id(data)
    _record_recv_message(host, request_id, ptc)

    profile = host["system_profile"]
    # fqdn is on the host but we need it in the profile as well
    profile["fqdn"] = host["fqdn"]

    # tags is on the host but we need it in the profile as well
    profile["tags"] = host["tags"]

    captured_date = profile.get("captured_date")
    account = host["account"]

    # Historical profiles have a "captured_date" which is when the data was
    # taken from the system by insights-client. However, some reporters to
    # inventory service run in a batch mode and do not update the
    # captured_date. The logic below will only save a profile if the
    # captured_date is one that we don't already have for the system in
    # question.  This works for our purposes since users differentiate between
    # profiles in the app via captured_date.

    if captured_date and db_interface.is_profile_recorded(
        captured_date, host["id"], account
    ):
        logger.info(
            "profile with date %s is already recorded for %s"
            % (captured_date, host["id"])
        )
        _record_duplicate_message(host, request_id, ptc)
    else:
        hsp = db_interface.create_profile(
            inventory_id=host["id"], profile=profile, account_number=host["account"],
        )
        _record_success_message(hsp.id, host, request_id, ptc)
        logger.info(
            "wrote %s to historical database (inv id: %s, captured_on: %s)"
            % (hsp.id, hsp.inventory_id, hsp.captured_on)
        )
Beispiel #7
0
def _archive_profile(data, ptc, logger, notification_service):
    """
    given an event, archive a profile and emit a success message
    """

    if not data.value or not isinstance(data.value, dict):
        logger.info("skipping message where data.value is empty or not a dict")
        return

    if "type" not in data.value:
        logger.info("skipping message that does not have a type")
        return

    if data.value["type"] not in ("created", "updated"):
        logger.info("skipping message that is not created or updated type")
        return

    service_auth_key = None
    if "platform_metadata" in data.value and isinstance(data.value["platform_metadata"], dict):
        service_auth_key = data.value["platform_metadata"].get("b64_identity", None)

    host = data.value["host"]
    request_id = _get_request_id(data)
    _record_recv_message(host, request_id, ptc)

    profile = host["system_profile"]
    # fqdn is on the host but we need it in the profile as well
    profile["fqdn"] = host["fqdn"]

    # tags is on the host but we need it in the profile as well
    profile["tags"] = host["tags"]

    captured_date = profile.get("captured_date")
    account = host["account"]
    org_id = host["org_id"]

    # Historical profiles have a "captured_date" which is when the data was
    # taken from the system by insights-client. However, some reporters to
    # inventory service run in a batch mode and do not update the
    # captured_date. The logic below will only save a profile if the
    # captured_date is one that we don't already have for the system in
    # question.  This works for our purposes since users differentiate between
    # profiles in the app via captured_date.

    if captured_date and db_interface.is_profile_recorded(
        captured_date, host["id"], account, org_id
    ):
        logger.info(
            "profile with date %s is already recorded for %s, using account id: %s, org_id: %s"
            % (captured_date, host["id"], account, org_id)
        )
        _record_duplicate_message(host, request_id, ptc)
    else:
        hsp = db_interface.create_profile(
            inventory_id=host["id"],
            profile=profile,
            account_number=host["account"],
            org_id=org_id,
        )
        _record_success_message(hsp.id, host, request_id, ptc)
        logger.info(
            "wrote %s to historical database (inv id: %s, captured_on: %s, account id: %s,"
            " org_id: %s)" % (hsp.id, hsp.inventory_id, hsp.captured_on, account, org_id)
        )
        # After the new hsp is saved, we need to check for any reason to alert via
        # triggering a notification, i.e. if drift from any associated baselines has
        # occurred.
        _check_and_send_notifications(
            host["id"],
            host["account"],
            host["org_id"],
            host["updated"],
            host["display_name"],
            host["tags"],
            notification_service,
            service_auth_key,
            logger,
        )