def test_create_host_with_empty_tags_facts_display_name_then_update(self): # Create a host with empty tags, facts, and display_name # then update those fields host_data = HostWrapper(test_data(facts=None)) del host_data.tags del host_data.display_name del host_data.facts expected_tags = [] # initial create results = self.post(HOST_URL, host_data.data(), 201) self.assertIsNotNone(results["id"]) original_id = results["id"] host_data.tags = ["aws/new_tag_1:new_value_1", "aws/k:v"] host_data.facts = FACTS host_data.display_name = "expected_display_name" self.post(HOST_URL, host_data.data(), 200) data = self.get("%s/%s" % (HOST_URL, original_id), 200) results = HostWrapper(data["results"][0]) self.assertListEqual(results.tags, expected_tags) self.assertListEqual(results.facts, host_data.facts) self.assertEqual(results.display_name, host_data.display_name)
def test_create_and_update_multiple_hosts_with_account_mismatch(self): """ Attempt to create multiple hosts, one host has the wrong account number. Verify this causes an error response to be returned. """ facts = None host1 = HostWrapper(test_data(display_name="host1", facts=facts)) host1.ip_addresses = ["10.0.0.1"] host1.rhel_machine_id = generate_uuid() host2 = HostWrapper(test_data(display_name="host2", facts=facts)) # Set the account number to the wrong account for this request host2.account = "222222" host2.ip_addresses = ["10.0.0.2"] host2.rhel_machine_id = generate_uuid() host_list = [host1.data(), host2.data()] # Create the host created_host = self.post(HOST_URL, host_list, 207) self.assertEqual(len(host_list), len(created_host["data"])) self.assertEqual(created_host["errors"], 1) self.assertEqual(created_host["data"][0]["status"], 201) self.assertEqual(created_host["data"][1]["status"], 400)
def create_hosts(self): hosts_to_create = [ ("host1", "12345", "host1.domain.test"), ("host2", "54321", "host1.domain.test"), # the same fqdn is intentional ("host3", "56789", "host2.domain.test"), ] host_list = [] for host in hosts_to_create: host_wrapper = HostWrapper() host_wrapper.account = ACCOUNT host_wrapper.tags = copy.deepcopy(TAGS) host_wrapper.display_name = host[0] host_wrapper.insights_id = host[1] host_wrapper.fqdn = host[2] host_wrapper.facts = [{ "namespace": "ns1", "facts": { "key1": "value1" } }] response_data = self.post(HOST_URL, host_wrapper.data(), 201) host_list.append(HostWrapper(response_data)) return host_list
def add_2_hosts(self): # FIXME: make this more generic host_list = [] canonical_facts = {'insights_id': '12345'} display_name = "host1" tags = TAGS host_data = HostWrapper( test_data(display_name=display_name, canonical_facts=canonical_facts, tags=tags)) response_data = self.post(HOST_URL, host_data.data(), 201) host_list.append(HostWrapper(response_data)) canonical_facts = {'insights_id': '54321'} display_name = "host2" tags = TAGS host_data = HostWrapper( test_data(display_name=display_name, canonical_facts=canonical_facts, tags=tags)) response_data = self.post(HOST_URL, host_data.data(), 201) host_list.append(HostWrapper(response_data)) return host_list
def test_update_host_with_tags_doesnt_change_tags(self): create_host_data = HostWrapper( test_data(tags=[{"namespace": "ns", "key": "some_key", "value": "val"}], fqdn="fqdn") ) message = {"operation": "add_host", "data": create_host_data.data()} mock_event_producer = MockEventProducer() with self.app.app_context(): handle_message(json.dumps(message), mock_event_producer) event = json.loads(mock_event_producer.event) host_id = event["host"]["id"] # attempt to update update_host_data = HostWrapper( test_data(tags=[{"namespace": "other_ns", "key": "other_key", "value": "other_val"}], fqdn="fqdn") ) update_response = self.post(HOST_URL, [update_host_data.data()], 207) self._verify_host_status(update_response, 0, 200) tags_response = self.get(f"{HOST_URL}/{host_id}/tags") # check the tags haven't updated self.assertEqual(create_host_data.tags, tags_response["results"][host_id])
def setUp(self): super().setUp() host_wrapper = HostWrapper() host_wrapper.account = ACCOUNT host_wrapper.display_name = "host1" # Same as self.added_hosts[0] host_wrapper.insights_id = generate_uuid() host_wrapper.stale_timestamp = now().isoformat() host_wrapper.reporter = "test" response_data = self.post(HOST_URL, [host_wrapper.data()], 207) self.added_hosts.append(HostWrapper(response_data["data"][0]["host"]))
def test_create_and_update_multiple_hosts_with_different_accounts(self): with test.support.EnvironmentVarGuard() as env: env.set("INVENTORY_SHARED_SECRET", SHARED_SECRET) facts = None host1 = HostWrapper(test_data(display_name="host1", facts=facts)) host1.account = "111111" host1.ip_addresses = ["10.0.0.1"] host1.rhel_machine_id = str(uuid.uuid4()) host2 = HostWrapper(test_data(display_name="host2", facts=facts)) host2.account = "222222" host2.ip_addresses = ["10.0.0.2"] host2.rhel_machine_id = str(uuid.uuid4()) host_list = [host1.data(), host2.data()] # Create the host response = self.post(HOST_URL, host_list, 207) self.assertEqual(len(host_list), len(response["data"])) self.assertEqual(response["total"], len(response["data"])) self.assertEqual(response["errors"], 0) for host in response["data"]: self.assertEqual(host["status"], 201) host_list[0]["id"] = response["data"][0]["host"]["id"] host_list[0]["bios_uuid"] = str(uuid.uuid4()) host_list[0]["display_name"] = "fred" host_list[1]["id"] = response["data"][1]["host"]["id"] host_list[1]["bios_uuid"] = str(uuid.uuid4()) host_list[1]["display_name"] = "barney" # Update the host updated_host = self.post(HOST_URL, host_list, 207) self.assertEqual(updated_host["errors"], 0) i = 0 for host in updated_host["data"]: self.assertEqual(host["status"], 200) expected_host = HostWrapper(host_list[i]) self._validate_host(host["host"], expected_host, expected_id=expected_host.id) i += 1
def _add_hosts(self, data): post = [] for d in data: host = HostWrapper(test_data(insights_id=generate_uuid(), **d)) post.append(host.data()) response = self.post(HOST_URL, post, 207) hosts = [] for i in range(len(data)): self._verify_host_status(response, i, 201) added_host = self._pluck_host_from_response(response, i) hosts.append(HostWrapper(added_host)) return hosts
def test_create_host_with_empty_facts_display_name_then_update(self): # Create a host with empty facts, and display_name # then update those fields host_data = HostWrapper(test_data(facts=None)) del host_data.display_name del host_data.facts # Create the host response = self.post(HOST_URL, [host_data.data()], 207) self._verify_host_status(response, 0, 201) created_host = self._pluck_host_from_response(response, 0) self.assertIsNotNone(created_host["id"]) original_id = created_host["id"] # Update the facts and display name host_data.facts = copy.deepcopy(FACTS) host_data.display_name = "expected_display_name" # Update the hosts self.post(HOST_URL, [host_data.data()], 207) host_lookup_results = self.get(f"{HOST_URL}/{original_id}", 200) self._validate_host(host_lookup_results["results"][0], host_data, expected_id=original_id)
def test_add_facts_to_multiple_hosts(self): facts_to_add = {"newfact1": "newvalue1", "newfact2": "newvalue2"} host_list = self.add_2_hosts() # This test assumes the set of facts are the same across # the hosts in the host_list expected_facts = {**host_list[0].facts[0]["facts"], **facts_to_add} target_namespace = host_list[0].facts[0]["namespace"] url_host_id_list = self._build_host_id_list_for_url(host_list) patch_url = self._build_facts_url(host_list, target_namespace) response = self.patch(patch_url, facts_to_add, 200) response = self.get(f"{HOST_URL}/{url_host_id_list}", 200) self.assertEqual(len(response["results"]), len(host_list)) for response_host in response["results"]: host_to_verify = HostWrapper(response_host) self.assertEqual(host_to_verify.facts[0]["facts"], expected_facts) self.assertEqual(host_to_verify.facts[0]["namespace"], target_namespace)
def test_create_host_with_non_nullable_fields_as_none(self): non_nullable_field_names = ( "display_name", "account", "insights_id", "rhel_machine_id", "subscription_manager_id", "satellite_id", "fqdn", "bios_uuid", "ip_addresses", "mac_addresses", "external_id", "ansible_host", "stale_timestamp", "reporter", ) host_data = HostWrapper(test_data(facts=None)) # Have at least one good canonical fact set host_data.insights_id = generate_uuid() host_data.rhel_machine_id = generate_uuid() host_dict = host_data.data() for field_name in non_nullable_field_names: with self.subTest(field_as_None=field_name): invalid_host_dict = copy.deepcopy(host_dict) invalid_host_dict[field_name] = None response_data = self.post(HOST_URL, [invalid_host_dict], 400) self.verify_error_response(response_data, expected_title="Bad Request")
def test_create_host_update_with_same_insights_id_and_different_canonical_facts( self): original_insights_id = str(uuid.uuid4()) host_data = HostWrapper(test_data(facts=None)) host_data.insights_id = original_insights_id host_data.rhel_machine_id = str(uuid.uuid4()) host_data.subscription_manager_id = "123456" host_data.satellite_id = "123456" host_data.bios_uuid = "123456" host_data.fqdn = "original_fqdn" host_data.mac_addresses = ["aa:bb:cc:dd:ee:ff"] host_data.external_id = "abcdef" # Create the host response = self.post(HOST_URL, [host_data.data()], 207) self._verify_host_status(response, 0, 201) created_host = self._pluck_host_from_response(response, 0) original_id = created_host["id"] self._validate_host(created_host, host_data, expected_id=original_id) # Change the canonical facts except for the insights_id host_data.rhel_machine_id = str(uuid.uuid4()) host_data.ip_addresses = [ "192.168.1.44", "10.0.0.2", ] host_data.subscription_manager_id = "654321" host_data.satellite_id = "654321" host_data.bios_uuid = "654321" host_data.fqdn = "expected_fqdn" host_data.mac_addresses = ["ff:ee:dd:cc:bb:aa"] host_data.external_id = "fedcba" host_data.facts = [{ "namespace": "ns1", "facts": { "newkey": "newvalue" } }] # Update the host response = self.post(HOST_URL, [host_data.data()], 207) self._verify_host_status(response, 0, 200) updated_host = self._pluck_host_from_response(response, 0) # Verify that the id did not change on the update self.assertEqual(updated_host["id"], original_id) # Retrieve the host using the id that we first received data = self.get("%s/%s" % (HOST_URL, original_id), 200) self._validate_host(data["results"][0], host_data, expected_id=original_id)
def test_create_host_without_ansible_host_then_update(self): # Create a host without ansible_host field # then update those fields host_data = HostWrapper(test_data(facts=None)) del host_data.ansible_host # Create the host response = self.post(HOST_URL, [host_data.data()], 207) self._verify_host_status(response, 0, 201) created_host = self._pluck_host_from_response(response, 0) original_id = created_host["id"] ansible_hosts = ["ima_ansible_host_" + generate_uuid(), ""] # Update the ansible_host for ansible_host in ansible_hosts: with self.subTest(ansible_host=ansible_host): host_data.ansible_host = ansible_host # Update the hosts self.post(HOST_URL, [host_data.data()], 207) host_lookup_results = self.get(f"{HOST_URL}/{original_id}", 200) self._validate_host(host_lookup_results["results"][0], host_data, expected_id=original_id)
def _basic_fact_test(self, input_facts, expected_facts, replace_facts): host_list = self.added_hosts # This test assumes the set of facts are the same across # the hosts in the host_list target_namespace = host_list[0].facts[0]["namespace"] url_host_id_list = self._build_host_id_list_for_url(host_list) patch_url = self._build_facts_url(host_list, target_namespace) if replace_facts: response = self.put(patch_url, input_facts, 200) else: response = self.patch(patch_url, input_facts, 200) response = self.get(f"{HOST_URL}/{url_host_id_list}", 200) self.assertEqual(len(response["results"]), len(host_list)) for response_host in response["results"]: host_to_verify = HostWrapper(response_host) self.assertEqual(host_to_verify.facts[0]["facts"], expected_facts) self.assertEqual(host_to_verify.facts[0]["namespace"], target_namespace)
def test_create_host_with_display_name_as_None_with_fqdn(self): """ This test should verify that the display_name is set to the fqdn when a display_name is not passed in but the fqdn is passed in. """ expected_display_name = "fred.flintstone.bedrock.com" host_data = HostWrapper(test_data(facts=None)) # Explicitly set the display name to None host_data.display_name = None host_data.fqdn = expected_display_name # Create the host created_host = self.post(HOST_URL, host_data.data(), 201) original_id = created_host["id"] host_lookup_results = self.get("%s/%s" % (HOST_URL, original_id), 200) # Explicitly set the display_name ...this is expected here host_data.display_name = expected_display_name self._validate_host(host_lookup_results["results"][0], host_data, expected_id=original_id, verify_tags=False)
def test_create_host_without_display_name_and_with_fqdn(self): """ This test should verify that the display_name is set to the fqdn when a display_name is not passed in but the fqdn is passed in. """ expected_display_name = "fred.flintstone.bedrock.com" host_data = HostWrapper(test_data(facts=None)) del host_data.display_name host_data.fqdn = expected_display_name # Create the host response = self.post(HOST_URL, [host_data.data()], 207) self._verify_host_status(response, 0, 201) created_host = self._pluck_host_from_response(response, 0) original_id = created_host["id"] host_lookup_results = self.get(f"{HOST_URL}/{original_id}", 200) # Explicitly set the display_name ...this is expected here host_data.display_name = expected_display_name self._validate_host(host_lookup_results["results"][0], host_data, expected_id=original_id)
def test_create_and_update(self): facts = None host_data = HostWrapper(test_data(facts=facts)) # Create the host response = self.post(HOST_URL, [host_data.data()], 207) self._verify_host_status(response, 0, 201) created_host = self._pluck_host_from_response(response, 0) original_id = created_host["id"] self._validate_host(created_host, host_data, expected_id=original_id) created_time = dateutil.parser.parse(created_host["created"]) current_timestamp = now() self.assertGreater(current_timestamp, created_time) self.assertLess(current_timestamp - timedelta(minutes=15), created_time) host_data.facts = copy.deepcopy(FACTS) # Replace facts under the first namespace host_data.facts[0]["facts"] = {"newkey1": "newvalue1"} # Add a new set of facts under a new namespace host_data.facts.append({"namespace": "ns2", "facts": {"key2": "value2"}}) # Add a new canonical fact host_data.rhel_machine_id = generate_uuid() host_data.ip_addresses = ["10.10.0.1", "10.0.0.2", "fe80::d46b:2807:f258:c319"] host_data.mac_addresses = ["c2:00:d0:c8:61:01"] host_data.external_id = "i-05d2313e6b9a42b16" host_data.insights_id = generate_uuid() # Update the host with the new data response = self.post(HOST_URL, [host_data.data()], 207) self._verify_host_status(response, 0, 200) updated_host = self._pluck_host_from_response(response, 0) # Make sure the id from the update post matches the id from the create self.assertEqual(updated_host["id"], original_id) # Verify the timestamp has been modified self.assertIsNotNone(updated_host["updated"]) modified_time = dateutil.parser.parse(updated_host["updated"]) self.assertGreater(modified_time, created_time) host_lookup_results = self.get(f"{HOST_URL}/{original_id}", 200) # sanity check # host_lookup_results["results"][0]["facts"][0]["facts"]["key2"] = "blah" # host_lookup_results["results"][0]["insights_id"] = "1.2.3.4" self._validate_host(host_lookup_results["results"][0], host_data, expected_id=original_id)
def test_create_host_ignores_tags(self): host_data = HostWrapper(test_data(tags=[{"namespace": "ns", "key": "some_key", "value": "val"}])) create_response = self.post(HOST_URL, [host_data.data()], 207) self._verify_host_status(create_response, 0, 201) host = self._pluck_host_from_response(create_response, 0) host_id = host["id"] tags_response = self.get(f"{HOST_URL}/{host_id}/tags") self.assertEqual(tags_response["results"][host_id], [])
def test_create_host_without_account(self): host_data = HostWrapper(test_data(facts=None)) del host_data.account response_data = self.post(HOST_URL, [host_data.data()], 400) self.verify_error_response( response_data, expected_title="Bad Request", expected_detail="'account' is a required property - '0'" )
def setUp(self): super().setUp() # add a host with no insights id host_wrapper = HostWrapper() host_wrapper.account = ACCOUNT host_wrapper.id = generate_uuid() host_wrapper.satellite_id = generate_uuid() host_wrapper.stale_timestamp = now().isoformat() host_wrapper.reporter = "test" self.post(HOST_URL, [host_wrapper.data()], 207)
def test_create_host_without_required_fields(self): fields = ("account", "stale_timestamp", "reporter") for field in fields: with self.subTest(fields=fields): data = test_data() del data[field] host_data = HostWrapper(data) response_data = self.post(HOST_URL, [host_data.data()], 400) self.verify_error_response(response_data, expected_title="Bad Request")
def test_create_host_with_mismatched_account_numbers(self): host_data = HostWrapper(test_data(facts=None)) host_data.account = ACCOUNT[::-1] response_data = self.post(HOST_URL, host_data.data(), 400) assert "Invalid request" in response_data["title"] assert "status" in response_data assert "detail" in response_data assert "type" in response_data
def test_create_host_without_account(self): host_data = HostWrapper(test_data(facts=None)) del host_data.account response_data = self.post(HOST_URL, host_data.data(), 400) assert "Bad Request" in response_data["title"] assert "status" in response_data assert "detail" in response_data assert "type" in response_data
def test_create_with_branch_id(self): facts = None host_data = HostWrapper(test_data(facts=facts)) post_url = HOST_URL + "?" + "branch_id=1234" # Create the host response = self.post(post_url, [host_data.data()], 207) self._verify_host_status(response, 0, 201)
def minimal_host(**values): data = { "account": ACCOUNT, "display_name": "test" + generate_random_string(), "ip_addresses": ["10.10.0.1"], "stale_timestamp": (now() + timedelta(days=randint(1, 7))).isoformat(), "reporter": "test" + generate_random_string(), **values, } return HostWrapper(data)
def test_create_host_with_invalid_facts_no_facts(self): facts = copy.deepcopy(FACTS) del facts[0]["facts"] host_data = HostWrapper(test_data(facts=facts)) response_data = self.post(HOST_URL, host_data.data(), 400) assert response_data["title"] == "Invalid request" assert "status" in response_data assert "detail" in response_data assert "type" in response_data
def test_create_and_update(self): facts = None tags = [] host_data = HostWrapper(test_data(facts=facts, tags=tags)) # Create the host created_host = self.post(HOST_URL, host_data.data(), 201) original_id = created_host["id"] self._validate_host(created_host, host_data, expected_id=original_id) created_time = dateutil.parser.parse(created_host["created"]) self.assertGreater(datetime.now(timezone.utc), created_time) host_data.facts = copy.deepcopy(FACTS) # Replace facts under the first namespace host_data.facts[0]["facts"] = {"newkey1": "newvalue1"} # Add a new set of facts under a new namespace host_data.facts.append({ "namespace": "ns2", "facts": { "key2": "value2" } }) # Add a new canonical fact host_data.rhel_machine_id = "1234-56-789" host_data.ip_addresses = ["10.10.0.1", "10.0.0.2"] host_data.mac_addresses = ["c2:00:d0:c8:61:01"] host_data.insights_id = "0987-65-4321" # Update the host with the new data updated_host = self.post(HOST_URL, host_data.data(), 200) # Make sure the id from the update post matches the id from the create self.assertEqual(updated_host["id"], original_id) # Verify the timestamp has been modified self.assertIsNotNone(updated_host["updated"]) modified_time = dateutil.parser.parse(updated_host["updated"]) self.assertGreater(modified_time, created_time) host_lookup_results = self.get("%s/%s" % (HOST_URL, original_id), 200) # sanity check # host_lookup_results["results"][0]["facts"][0]["facts"]["key2"] = "blah" # host_lookup_results["results"][0]["insights_id"] = "1.2.3.4" self._validate_host(host_lookup_results["results"][0], host_data, expected_id=original_id)
def _update_host(self, added_host_index, new_id, new_modified_on): old_id = self.added_hosts[added_host_index].id old_host = db.session.query(Host).get(old_id) old_host.id = new_id old_host.modified_on = new_modified_on db.session.add(old_host) staleness_offset = Timestamps.from_config( self.app.config["INVENTORY_CONFIG"]) serialized_old_host = serialize_host(old_host, staleness_offset) self.added_hosts[added_host_index] = HostWrapper(serialized_old_host)
def create_hosts(self): hosts_to_create = [("host1", "12345"), ("host2", "54321")] host_list = [] for host in hosts_to_create: host_wrapper = HostWrapper() host_wrapper.account = ACCOUNT host_wrapper.tags = TAGS host_wrapper.display_name = host[0] host_wrapper.insights_id = host[1] host_wrapper.facts = [{ "namespace": "ns1", "facts": { "key1": "value1" } }] response_data = self.post(HOST_URL, host_wrapper.data(), 201) host_list.append(HostWrapper(response_data)) return host_list
def _mq_create_or_update_host( host_data, platform_metadata=None, return_all_data=False, event_producer=event_producer_mock ): message = wrap_message(host_data.data(), platform_metadata=platform_metadata) handle_message(json.dumps(message), event_producer) event = json.loads(event_producer.event) if return_all_data: return event_producer_mock.key, event, event_producer.headers # add facts object since it's not returned by event message return HostWrapper({**event["host"], **{"facts": host_data.facts}})