def test_create_and_update_multiple_hosts_with_account_mismatch( api_create_or_update_host): """ Attempt to create multiple hosts, one host has the wrong account number. Verify this causes an error response to be returned. """ host1 = minimal_host(display_name="host1", ip_addresses=["10.0.0.1"], rhel_machine_id=generate_uuid()) host2 = minimal_host(display_name="host2", account="222222", ip_addresses=["10.0.0.2"], rhel_machine_id=generate_uuid()) host_list = [host1, host2] # Create the host multi_response_status, multi_response_data = api_create_or_update_host( host_list) assert_response_status(multi_response_status, 207) assert len(host_list) == len(multi_response_data["data"]) assert multi_response_status, multi_response_data["errors"] == 1 assert_host_response_status(multi_response_data, 201, 0) assert_host_response_status(multi_response_data, 400, 1)
def test_mac_addresses_case_insensitive(mq_create_or_update_host): first_host = mq_create_or_update_host( minimal_host(fqdn="foo.bar.com", mac_addresses=["C2:00:D0:C8:61:01", "aa:bb:cc:dd:ee:ff"])) second_host = mq_create_or_update_host( minimal_host(fqdn="foo.bar.com", mac_addresses=["c2:00:d0:c8:61:01", "AA:BB:CC:DD:EE:FF"])) assert first_host.id == second_host.id
def test_subscription_manager_id_case_insensitive(mq_create_or_update_host): smid = generate_uuid() first_host = mq_create_or_update_host( minimal_host(subscription_manager_id=smid.upper())) second_host = mq_create_or_update_host( minimal_host(subscription_manager_id=smid.lower())) assert first_host.id == second_host.id
def test_update_display_name(mq_create_or_update_host, db_get_host_by_insights_id): insights_id = generate_uuid() host = minimal_host(display_name="test_host", insights_id=insights_id) mq_create_or_update_host(host) host = minimal_host(display_name="better_test_host", insights_id=insights_id) mq_create_or_update_host(host) record = db_get_host_by_insights_id(insights_id) assert record.display_name == "better_test_host"
def test_create_and_update_multiple_hosts_with_different_accounts( api_create_or_update_host, monkeypatch): monkeypatch.setenv("INVENTORY_SHARED_SECRET", SHARED_SECRET) host1 = minimal_host(display_name="host1", account="111111", ip_addresses=["10.0.0.1"], rhel_machine_id=generate_uuid()) host2 = minimal_host(display_name="host2", account="222222", ip_addresses=["10.0.0.2"], rhel_machine_id=generate_uuid()) host_list = [host1, host2] # Create the host multi_response_status, multi_response_data = api_create_or_update_host( host_list, auth_type="token") assert_response_status(multi_response_status, 207) assert len(host_list) == len(multi_response_data["data"]) assert multi_response_data["total"] == len(multi_response_data["data"]) assert multi_response_status, multi_response_data["errors"] == 0 for i, host in enumerate(host_list): create_host_response = get_host_from_multi_response( multi_response_data, host_index=i) assert_host_was_created(create_host_response) host_list[i].id = create_host_response["host"]["id"] host_list[0].bios_uuid = generate_uuid() host_list[0].display_name = "fred" host_list[1].bios_uuid = generate_uuid() host_list[1].display_name = "barney" # Update the host multi_response_status, multi_response_data = api_create_or_update_host( host_list, auth_type="token") assert_response_status(multi_response_status, 207) for i, host in enumerate(host_list): update_host_response = get_host_from_multi_response( multi_response_data, host_index=i) assert_host_response_status(update_host_response, expected_status=200) assert_host_data(actual_host=update_host_response["host"], expected_host=host_list[i], expected_id=host_list[i].id)
def test_no_merge_when_no_match(mq_create_or_update_host): wrapper = minimal_host(fqdn="test_fqdn", insights_id=generate_uuid()) del wrapper.ip_addresses first_host = mq_create_or_update_host(wrapper) second_host = mq_create_or_update_host( minimal_host( bios_uuid=generate_uuid(), satellite_id=generate_uuid(), ansible_host="testhost", display_name="testdisplayname", )) assert first_host.id != second_host.id
def test_match_host_by_elevated_id_performance(mocker, api_create_or_update_host): canonical_fact_host_query_mock = mocker.patch( "lib.host_repository.canonical_fact_host_query", wraps=canonical_fact_host_query) canonical_facts_host_query_mock = mocker.patch( "lib.host_repository.canonical_facts_host_query", wraps=canonical_facts_host_query) subscription_manager_id = generate_uuid() host = minimal_host(subscription_manager_id=subscription_manager_id) multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) create_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(create_host_response) # Create a host with Subscription Manager ID insights_id = generate_uuid() host = minimal_host(insights_id=insights_id, subscription_manager_id=subscription_manager_id) mocker.resetall() # Update a host with Insights ID and Subscription Manager ID multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) update_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_updated(create_host_response, update_host_response) expected_calls = ( mocker.call(ACCOUNT, "insights_id", insights_id), mocker.call(ACCOUNT, "subscription_manager_id", subscription_manager_id), ) canonical_fact_host_query_mock.assert_has_calls(expected_calls) assert canonical_fact_host_query_mock.call_count == len(expected_calls) canonical_facts_host_query_mock.assert_not_called()
def test_validate_sp_for_branch(mocker): # Mock schema fetch get_schema_from_url_mock = mocker.patch( "lib.system_profile_validate._get_schema_from_url") mock_schema = system_profile_specification() get_schema_from_url_mock.return_value = mock_schema # Mock Kafka consumer fake_consumer = mocker.Mock() config = Config(RuntimeEnvironment.SERVICE) tp = TopicPartition(config.host_ingress_topic, 0) fake_consumer.poll.return_value = { tp: [ SimpleNamespace( value=json.dumps(wrap_message(minimal_host().data()))) for _ in range(5) ] } fake_consumer.offsets_for_times.return_value = { tp: SimpleNamespace(offset=0) } validation_results = validate_sp_for_branch(config, fake_consumer, repo_fork="test_repo", repo_branch="test_branch", days=3) assert "test_repo/test_branch" in validation_results for reporter in validation_results["test_repo/test_branch"]: assert validation_results["test_repo/test_branch"][ reporter].pass_count > 0
def test_get_host_with_escaped_special_characters(namespace, key, value, mq_create_or_update_host, api_get): tags = [ { "namespace": ";,/?:@&=+$", "key": "-_.!~*'()", "value": "#" }, { "namespace": " \t\n\r\f\v", "key": " \t\n\r\f\v", "value": " \t\n\r\f\v" }, ] host = minimal_host(tags=tags) created_host = mq_create_or_update_host(host) tags_query = quote( f"{quote_everything(namespace)}/{quote_everything(key)}={quote_everything(value)}" ) url = build_hosts_url(query=f"?tags={tags_query}") response_status, response_data = api_get(url) assert response_status == 200 assert response_data["count"] assert response_data["results"][0]["id"] == created_host.id
def mq_create_four_specific_hosts(mq_create_three_specific_hosts, mq_create_or_update_host): created_hosts = mq_create_three_specific_hosts host = minimal_host(insights_id=generate_uuid(), display_name=created_hosts[0].display_name) created_host = mq_create_or_update_host(host) created_hosts.append(created_host) return created_hosts
def test_add_host_key_filtering_system_profile(mq_create_or_update_host, db_get_host): host_to_create = minimal_host( system_profile={ "number_of_cpus": 1, "number_of_gpus": 2, "disk_devices": [{ "options": { "uid": "0" }, "mount_options": { "ro": True } }], }) created_host_from_event = mq_create_or_update_host(host_to_create) created_host_from_db = db_get_host(created_host_from_event.id) assert created_host_from_db.system_profile_facts == { "number_of_cpus": 1, "disk_devices": [{ "options": { "uid": "0" } }], }
def test_add_host_stale_timestamp(event_datetime_mock, mq_create_or_update_host): """ Tests to see if the host is successfully created with both reporter and stale_timestamp set. """ expected_insights_id = generate_uuid() timestamp_iso = event_datetime_mock.isoformat() stale_timestamp = now() host = minimal_host(insights_id=expected_insights_id, stale_timestamp=stale_timestamp.isoformat()) expected_results = { "host": { **host.data(), "stale_warning_timestamp": (stale_timestamp + timedelta(weeks=1)).isoformat(), "culled_timestamp": (stale_timestamp + timedelta(weeks=2)).isoformat(), }, "platform_metadata": {}, "timestamp": timestamp_iso, "type": "created", } host_keys_to_check = ["reporter", "stale_timestamp", "culled_timestamp"] key, event, headers = mq_create_or_update_host(host, return_all_data=True) assert_mq_host_data(key, event, expected_results, host_keys_to_check)
def test_delete_host_tags(mq_create_or_update_host, db_get_host_by_insights_id, subtests): insights_id = generate_uuid() # Can't use parametrize here due to the data cleanup on each test run for message_tags, expected_tags in ( ({}, {}), ( { "namespace 1": {"key 1": ["value 1"]}, "namespace 2": {"key 2": ["value 2"]}, "namespace 3": {"key 3": ["value 3"]}, "null": {"key 4": ["value 4"]}, }, { "namespace 1": {"key 1": ["value 1"]}, "namespace 2": {"key 2": ["value 2"]}, "namespace 3": {"key 3": ["value 3"]}, "null": {"key 4": ["value 4"]}, }, ), ( {"namespace 2": None, "namespace 3": {}}, {"namespace 1": {"key 1": ["value 1"]}, "null": {"key 4": ["value 4"]}}, ), ({"null": {}}, {"namespace 1": {"key 1": ["value 1"]}}), ({"null": {"key 5": ["value 5"]}}, {"namespace 1": {"key 1": ["value 1"]}, "null": {"key 5": ["value 5"]}}), ({"": {}}, {"namespace 1": {"key 1": ["value 1"]}}), ): with subtests.test(tags=message_tags): host = minimal_host(insights_id=insights_id, tags=message_tags) mq_create_or_update_host(host) record = db_get_host_by_insights_id(insights_id) assert expected_tags == record.tags
def test_create_host_with_system_profile_sap_fact(api_create_or_update_host, api_get): system_profile = valid_system_profile() system_profile["sap_system"] = True host = minimal_host(system_profile=system_profile) # Create the host multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) create_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(create_host_response) created_host = create_host_response["host"] response_status, response_data = api_get( f"{HOST_URL}/{created_host['id']}/system_profile") assert_response_status(response_status, 200) host_response = get_host_from_response(response_data) assert host_response["system_profile"] == host.system_profile assert host_response["system_profile"]["sap_system"] == system_profile[ "sap_system"]
def test_get_system_profile_of_host_that_does_not_have_system_profile( api_create_or_update_host, api_get): host = minimal_host() # Create the host multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) create_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(create_host_response) created_host = create_host_response["host"] # verify system_profile is not included assert "system_profile" not in created_host response_status, response_data = api_get( f"{HOST_URL}/{created_host['id']}/system_profile") assert_response_status(response_status, 200) host_response = get_host_from_response(response_data) assert host_response["id"] == created_host["id"] assert host_response["system_profile"] == {}
def test_create_host_with_system_profile_with_different_cloud_providers( api_create_or_update_host, api_get, cloud_provider): host = minimal_host(system_profile={"cloud_provider": cloud_provider}) # Create the host multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) create_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(create_host_response) created_host = create_host_response["host"] # verify system_profile is not included assert "system_profile" not in created_host response_status, response_data = api_get( f"{HOST_URL}/{created_host['id']}/system_profile") assert_response_status(response_status, 200) host_response = get_host_from_response(response_data) assert host_response["id"] == created_host["id"] assert host_response["system_profile"] == host.system_profile
def test_handle_message_happy_path(mocker, event_datetime_mock, flask_app): expected_insights_id = generate_uuid() host_id = generate_uuid() timestamp_iso = event_datetime_mock.isoformat() mocker.patch( "app.queue.queue.add_host", return_value=( {"id": host_id, "insights_id": expected_insights_id}, host_id, expected_insights_id, AddHostResult.created, ), ) mock_event_producer = mocker.Mock() host = minimal_host(insights_id=expected_insights_id) message = wrap_message(host.data()) handle_message(json.dumps(message), mock_event_producer) mock_event_producer.write_event.assert_called_once() assert json.loads(mock_event_producer.write_event.call_args[0][0]) == { "timestamp": timestamp_iso, "type": "created", "host": {"id": host_id, "insights_id": expected_insights_id}, "platform_metadata": {}, "metadata": {"request_id": "-1"}, }
def test_create_host_with_20_byte_mac_address(api_create_or_update_host, api_get): system_profile = { "network_interfaces": [{ "mac_address": "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33" }] } host = minimal_host(system_profile=system_profile) multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) create_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(create_host_response) created_host_id = create_host_response["host"]["id"] response_status, response_data = api_get(f"{HOST_URL}/{created_host_id}") assert_response_status(response_status, 200) host_response = get_host_from_response(response_data) assert_host_data(actual_host=host_response, expected_host=host, expected_id=created_host_id)
def test_add_host_with_operating_system_incorrect_format( event_datetime_mock, mq_create_or_update_host, db_get_host): """ Tests that operating_system in the system profile is rejected if it's in the wrong format """ operating_system_list = [ { "major": "bananas", "minor": 1, "name": "RHEL" }, { "major": 1, "minor": "oranges", "name": "RHEL" }, { "major": 1, "minor": 1, "name": "UBUNTU" }, ] for operating_system in operating_system_list: host = minimal_host( system_profile={"operating_system": operating_system}) with pytest.raises(ValidationException): mq_create_or_update_host(host)
def test_ignore_culled_host_on_update_by_canonical_facts( api_create_or_update_host): # Culled host host = minimal_host(fqdn="my awesome fqdn", stale_timestamp=(now() - timedelta(weeks=3)).isoformat()) # Create the host multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) create_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(create_host_response) # Update the host multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) update_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(update_host_response) assert create_host_response["host"]["id"] != update_host_response["host"][ "id"]
def test_add_host_type_coercion_system_profile(mq_create_or_update_host, db_get_host): host_to_create = minimal_host(system_profile={"number_of_cpus": "1"}) created_host_from_event = mq_create_or_update_host(host_to_create) created_host_from_db = db_get_host(created_host_from_event.id) assert created_host_from_db.system_profile_facts == {"number_of_cpus": 1}
def test_ignore_culled_host_on_update_by_elevated_id( api_create_or_update_host): # Culled host host = minimal_host(insights_id=generate_uuid(), stale_timestamp=(now() - timedelta(weeks=3)).isoformat()) # Create the host multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) create_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(create_host_response) # Update the host host.ip_addresses = ["10.10.0.2"] multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) update_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(update_host_response) assert create_host_response["host"]["id"] != update_host_response["host"][ "id"]
def test_add_host_with_sap_system(event_datetime_mock, mq_create_or_update_host): expected_insights_id = generate_uuid() timestamp_iso = event_datetime_mock.isoformat() system_profile = valid_system_profile() system_profile["sap_system"] = True host = minimal_host(insights_id=expected_insights_id, system_profile=system_profile) expected_results = { "host": { **host.data() }, "platform_metadata": {}, "timestamp": timestamp_iso, "type": "created", } host_keys_to_check = [ "display_name", "insights_id", "account", "system_profile" ] key, event, headers = mq_create_or_update_host(host, return_all_data=True) assert_mq_host_data(key, event, expected_results, host_keys_to_check)
def test_create_host_without_display_name_and_without_fqdn( api_create_or_update_host, api_get): """ This test should verify that the display_name is set to the id when neither the display name or fqdn is set. """ host = minimal_host() del host.display_name del host.fqdn # Create the host multi_response_status, multi_response_data = api_create_or_update_host( [host]) assert_response_status(multi_response_status, 207) create_host_response = get_host_from_multi_response(multi_response_data) assert_host_was_created(create_host_response) created_host_id = create_host_response["host"]["id"] response_status, response_data = api_get(f"{HOST_URL}/{created_host_id}") assert_response_status(response_status, 200) host_response = get_host_from_response(response_data) assert_host_data(actual_host=host_response, expected_host=host, expected_id=created_host_id)
def test_get_host_with_unescaped_special_characters(tag_query, mq_create_or_update_host, api_get, subtests): tags = [ { "namespace": ";?:@&+$", "key": "-_.!~*'()'", "value": "#" }, { "namespace": " \t\n\r\f\v", "key": " \t\n\r\f\v", "value": " \t\n\r\f\v" }, ] host = minimal_host(tags=tags) created_host = mq_create_or_update_host(host) url = build_hosts_url(query=f"?tags={quote(tag_query)}") response_status, response_data = api_get(url) assert response_status == 200 assert response_data["count"] assert response_data["results"][0]["id"] == created_host.id
def test_events_sent_to_correct_topic(mocker, flask_app, secondary_topic_enabled): host_id = generate_uuid() insights_id = generate_uuid() host = minimal_host(id=host_id, insights_id=insights_id) add_host = mocker.patch( "app.queue.queue.add_host", return_value=({"id": host_id}, host_id, insights_id, AddHostResult.created) ) mock_event_producer = mocker.Mock() message = wrap_message(host.data()) handle_message(json.dumps(message), mock_event_producer) # checking events sent to both egress and events topic assert mock_event_producer.write_event.call_count == 2 assert mock_event_producer.write_event.call_args_list[0][0][3] == Topic.egress assert mock_event_producer.write_event.call_args_list[1][0][3] == Topic.events mock_event_producer.reset_mock() # for host update events add_host.return_value = ({"id": host_id}, host_id, insights_id, AddHostResult.updated) message["data"].update(stale_timestamp=(now() + timedelta(hours=26)).isoformat()) handle_message(json.dumps(message), mock_event_producer) # checking events sent to both egress and events topic assert mock_event_producer.write_event.call_count == 2 assert mock_event_producer.write_event.call_args_list[0][0][3] == Topic.egress assert mock_event_producer.write_event.call_args_list[1][0][3] == Topic.events
def test_system_profile_valid_date_format(mq_create_or_update_host, boot_time): system_profile = valid_system_profile() system_profile["owner_id"] = OWNER_ID system_profile["last_boot_time"] = boot_time host = minimal_host(system_profile=system_profile) mq_create_or_update_host(host)
def test_add_host_with_tags(event_datetime_mock, mq_create_or_update_host): """ Tests adding a host with message containing tags """ expected_insights_id = generate_uuid() expected_tags = [ {"namespace": "NS1", "key": "key3", "value": "val3"}, {"namespace": "NS3", "key": "key2", "value": "val2"}, {"namespace": "Sat", "key": "prod", "value": None}, {"namespace": "Sat", "key": "dev", "value": ""}, {"namespace": "Sat", "key": "test"}, {"namespace": None, "key": "key", "value": "val1"}, {"namespace": "", "key": "key", "value": "val4"}, {"namespace": "null", "key": "key", "value": "val5"}, {"namespace": None, "key": "only_key", "value": None}, {"key": "just_key"}, {"namespace": " \t\n\r\f\v", "key": " \t\n\r\f\v", "value": " \t\n\r\f\v"}, ] timestamp_iso = event_datetime_mock.isoformat() host = minimal_host(insights_id=expected_insights_id, tags=expected_tags) expected_results = { "host": {**host.data()}, "platform_metadata": {}, "timestamp": timestamp_iso, "type": "created", } host_keys_to_check = ["display_name", "insights_id", "account"] key, event, headers = mq_create_or_update_host(host, return_all_data=True) assert_mq_host_data(key, event, expected_results, host_keys_to_check) assert len(event["host"]["tags"]) == len(expected_tags)
def test_validate_sp_for_missing_branch_or_repo(api_post, mocker): # Mock schema fetch get_schema_from_url_mock = mocker.patch( "lib.system_profile_validate._get_schema_from_url") get_schema_from_url_mock.side_effect = ValueError( "Schema not found at URL!") # Mock Kafka consumer fake_consumer = mocker.Mock() config = Config(RuntimeEnvironment.SERVICE) tp = TopicPartition(config.host_ingress_topic, 0) fake_consumer.poll.return_value = { tp: [ SimpleNamespace( value=json.dumps(wrap_message(minimal_host().data()))) for _ in range(5) ] } fake_consumer.offsets_for_times.return_value = { tp: SimpleNamespace(offset=0) } with pytest.raises(expected_exception=ValueError) as excinfo: validate_sp_for_branch(config, fake_consumer, repo_fork="foo", repo_branch="bar", days=3) assert "Schema not found at URL" in str(excinfo.value)
def test_add_host_empty_keys_system_profile(mq_create_or_update_host): insights_id = generate_uuid() system_profile = {"disk_devices": [{"options": {"": "invalid"}}]} host = minimal_host(insights_id=insights_id, system_profile=system_profile) with pytest.raises(ValidationException): mq_create_or_update_host(host)