def test_update_host_with_tags(db_create_host): insights_id = str(uuid.uuid4()) old_tags = Tag("Sat", "env", "prod").to_nested() existing_host = db_create_host( extra_data={ "canonical_facts": { "insights_id": insights_id }, "display_name": "tagged", "tags": old_tags }) assert existing_host.tags == old_tags # On update each namespace in the input host's tags should be updated. new_tags = Tag.create_nested_from_tags( [Tag("Sat", "env", "ci"), Tag("AWS", "env", "prod")]) input_host = db_create_host( extra_data={ "canonical_facts": { "insights_id": insights_id }, "display_name": "tagged", "tags": new_tags }) existing_host.update(input_host) assert existing_host.tags == new_tags
def find_hosts_by_tag(account_number, string_tags, query): tags = [] for string_tag in string_tags: tags.append(Tag().from_string(string_tag)) tags_to_find = Tag.create_nested_from_tags(tags) return query.filter(Host.tags.contains(tags_to_find))
def _find_hosts_by_tag(string_tags, query): logger.debug("_find_hosts_by_tag(%s)", string_tags) tags = [] for string_tag in string_tags: tags.append(Tag.from_string(string_tag)) tags_to_find = Tag.create_nested_from_tags(tags) return query.filter(Host.tags.contains(tags_to_find))
def test_update_host_with_tags(flask_app_fixture): insights_id = str(uuid.uuid4()) old_tags = Tag("Sat", "env", "prod").to_nested() existing_host = _create_host(insights_id=insights_id, display_name="tagged", tags=old_tags) assert existing_host.tags == old_tags # On update each namespace in the input host's tags should be updated. new_tags = Tag.create_nested_from_tags([Tag("Sat", "env", "ci"), Tag("AWS", "env", "prod")]) input_host = _create_host(insights_id=insights_id, display_name="tagged", tags=new_tags) existing_host.update(input_host) assert existing_host.tags == new_tags
def test_tag_deserialization(): tags = [ {"namespace": "Sat", "key": "env", "value": "prod"}, {"namespace": "Sat", "key": "env", "value": "test"}, {"namespace": "Sat", "key": "geo", "value": "somewhere"}, {"namespace": "AWS", "key": "env", "value": "ci"}, {"namespace": "AWS", "key": "env"}, ] expected_tags = {"Sat": {"env": ["prod", "test"], "geo": ["somewhere"]}, "AWS": {"env": ["ci"]}} deserialized_tags = Tag.create_nested_from_tags(Tag.create_structered_tags_from_tag_data_list(tags)) assert sorted(deserialized_tags["Sat"]["env"]) == sorted(expected_tags["Sat"]["env"]) assert sorted(deserialized_tags["Sat"]["geo"]) == sorted(expected_tags["Sat"]["geo"]) assert sorted(deserialized_tags["AWS"]["env"]) == sorted(expected_tags["AWS"]["env"])
def _build_serialized_tags(host_list, search): response_tags = {} for host in host_list: if search is None: tags = Tag.create_tags_from_nested(host.tags) else: tags = Tag.filter_tags(Tag.create_tags_from_nested(host.tags), search) tag_dictionaries = [] for tag in tags: tag_dictionaries.append(tag.data()) response_tags[str(host.id)] = tag_dictionaries return response_tags
def _deserialize_tags_dict(tags): deserialized_tags = {} for namespace, tags_ns in tags.items(): deserialized_namespace = Tag.deserialize_namespace(namespace) if deserialized_namespace not in deserialized_tags: deserialized_tags[deserialized_namespace] = {} deserialized_tags_ns = deserialized_tags[deserialized_namespace] if not tags_ns: continue for key, values in tags_ns.items(): if not key: raise ValueError("Key cannot be empty.") if key not in deserialized_tags_ns: deserialized_tags_ns[key] = [] deserialized_tags_key = deserialized_tags_ns[key] if not values: continue for value in values: if value and value not in deserialized_tags_key: deserialized_tags_key.append(value) return deserialized_tags
def _query_filters(fqdn, display_name, hostname_or_id, insights_id, tags, staleness): if fqdn: query_filters = ({"fqdn": fqdn},) elif display_name: query_filters = ({"display_name": string_contains(display_name)},) elif hostname_or_id: contains = string_contains(hostname_or_id) hostname_or_id_filters = ({"display_name": contains}, {"fqdn": contains}) try: id = UUID(hostname_or_id) except ValueError: # Do not filter using the id logger.debug("The hostname (%s) could not be converted into a UUID", hostname_or_id, exc_info=True) else: logger.debug("Adding id (uuid) to the filter list") hostname_or_id_filters += ({"id": str(id)},) query_filters = ({"OR": hostname_or_id_filters},) elif insights_id: query_filters = ({"insights_id": insights_id},) else: query_filters = () if tags: query_filters += tuple({"tag": Tag().from_string(string_tag).data()} for string_tag in tags) if staleness: staleness_filters = tuple(staleness_filter(staleness)) query_filters += ({"OR": staleness_filters},) return query_filters
def get_tags(search=None, tags=None, order_by=None, order_how=None, page=None, per_page=None, staleness=None): if not xjoin_enabled(): flask.abort(503) limit, offset = pagination_params(page, per_page) variables = { "order_by": order_by, "order_how": order_how, "limit": limit, "offset": offset, "hostFilter": { # we're not indexing null timestamps in ES "OR": list(staleness_filter(staleness)) }, } if search: variables["filter"] = { # Escaped to prevent ReDoS "name": f".*{re.escape(url_quote(search, safe=''))}.*" } if tags: variables["hostFilter"]["AND"] = [{"tag": Tag().from_string(tag).data()} for tag in tags] response = graphql_query(TAGS_QUERY, variables) data = response["hostTags"] check_pagination(offset, data["meta"]["total"]) return flask_json_response(build_collection_response(data["data"], page, per_page, data["meta"]["total"]))
def build_tag_query_dict_tuple(tags): query_tag_tuple = () for string_tag in tags: query_tag_dict = {} tag_dict = Tag.from_string(string_tag).data() for key in tag_dict.keys(): query_tag_dict[key] = {"eq": tag_dict[key]} query_tag_tuple += ({"tag": query_tag_dict}, ) logger.debug("query_tag_tuple: %s", query_tag_tuple) return query_tag_tuple
def test_update_host_with_no_tags(flask_app_fixture): insights_id = str(uuid.uuid4()) old_tags = Tag("Sat", "env", "prod").to_nested() existing_host = _create_host(insights_id=insights_id, display_name="tagged", tags=old_tags) # Updating a host should not remove any existing tags if tags are missing from the input host input_host = _create_host(insights_id=insights_id, display_name="tagged") existing_host.update(input_host) assert existing_host.tags == old_tags
def assert_patch_event_is_valid( host, event_producer, expected_request_id, expected_timestamp, display_name="patch_event_test", stale_timestamp=None, reporter=None, ): stale_timestamp = stale_timestamp or host.stale_timestamp.astimezone(timezone.utc) reporter = reporter or host.reporter event = json.loads(event_producer.event) assert isinstance(event, dict) expected_event = { "type": "updated", "host": { "id": str(host.id), "account": host.account, "display_name": display_name, "ansible_host": host.ansible_host, "fqdn": host.canonical_facts.get("fqdn"), "insights_id": host.canonical_facts.get("insights_id"), "bios_uuid": host.canonical_facts.get("bios_uuid"), "ip_addresses": host.canonical_facts.get("ip_addresses"), "mac_addresses": host.canonical_facts.get("mac_addresses"), "satellite_id": host.canonical_facts.get("satellite_id"), "subscription_manager_id": host.canonical_facts.get("subscription_manager_id"), "system_profile": host.system_profile_facts, "per_reporter_staleness": host.per_reporter_staleness, "tags": [tag.data() for tag in Tag.create_tags_from_nested(host.tags)], "reporter": reporter, "stale_timestamp": stale_timestamp.isoformat(), "stale_warning_timestamp": (stale_timestamp + timedelta(weeks=1)).isoformat(), "culled_timestamp": (stale_timestamp + timedelta(weeks=2)).isoformat(), "created": host.created_on.astimezone(timezone.utc).isoformat(), "provider_id": host.canonical_facts.get("provider_id"), "provider_type": host.canonical_facts.get("provider_type"), }, "platform_metadata": None, "metadata": {"request_id": expected_request_id}, "timestamp": expected_timestamp.isoformat(), } # We don't have this information without retrieving the host after the patch request del event["host"]["updated"] assert event == expected_event assert event_producer.key == str(host.id) assert event_producer.headers == expected_headers( "updated", expected_request_id, host.canonical_facts.get("insights_id") )
def test_update_host_with_no_tags(db_create_host): insights_id = str(uuid.uuid4()) old_tags = Tag("Sat", "env", "prod").to_nested() existing_host = db_create_host( extra_data={"canonical_facts": {"insights_id": insights_id}, "display_name": "tagged", "tags": old_tags} ) # Updating a host should not remove any existing tags if tags are missing from the input host input_host = db_create_host(extra_data={"canonical_facts": {"insights_id": insights_id}, "display_name": "tagged"}) existing_host.update(input_host) assert existing_host.tags == old_tags
def _build_serialized_tags(host_list): response_tags = {} for host in host_list: tags = Tag.create_tags_from_nested(host.tags) tag_dictionaries = [] for tag in tags: tag_dictionaries.append(tag.data()) response_tags[str(host.id)] = tag_dictionaries return response_tags
def _deserialize_tags_list(tags): deserialized = {} for tag_data in tags: namespace = Tag.deserialize_namespace(tag_data.get("namespace")) if namespace not in deserialized: deserialized[namespace] = {} key = tag_data.get("key") if not key: raise ValueError("Key cannot be empty.") if key not in deserialized[namespace]: deserialized[namespace][key] = [] value = tag_data.get("value") if value and value not in deserialized[namespace][key]: deserialized[namespace][key].append(value) return deserialized
def _serialize_tags(tags): return [tag.data() for tag in Tag.create_tags_from_nested(tags)]
def _deserialize_tags(tags): # TODO: Move the deserialization logic to this method. return Tag.create_nested_from_tags( Tag.create_structered_tags_from_tag_data_list(tags))