Запрос API сервиса сейчас не возвращает размер запроса - PullRequest
0 голосов
/ 25 февраля 2020

Я пытаюсь получить все элементы конфигурации из нашей CMDB для конкретного запроса, используя API REST Service Now и библиотеку запросов Python. Когда я использую веб-интерфейс, общее количество элементов соответствует тому, что REST API возвращает для заголовка 'X-Total-Count. Однако, когда я разбиваю результаты на страницы, используя al oop и их REST API, мое общее количество возвращаемых элементов меньше, чем это.

Я написал тестовый скрипт (ниже), чтобы попробовать и отладить это. Скрипт распечатает количество элементов, возвращаемых каждым запросом, и я заметил, что некоторые страницы возвращают число в соответствии с установленным пределом.

Например, страница 2 вернет 4730 результатов вместо 5000, затем несколько других страниц вернут 5000 результатов, а затем другая случайная страница вернет некоторое число ниже предела. Когда я снова запускаю запрос, одна и та же страница каждый раз возвращает одинаковое количество результатов (или отсутствие результатов).

Что здесь происходит? Почему бы не вернуть максимальное количество результатов, если оно далеко от последней страницы? Это услуга сейчас? У кого-нибудь есть опыт с этим? Я довольно много пытался поиграть со своим запросом и размером лимита, и до сих пор сталкиваюсь с той же проблемой. У меня не было этой проблемы на прошлой неделе, и теперь я не могу исправить это для моей жизни.

import json
import requests


def get_ci() -> list:
    """
    Returns a list of all configuration items in Service Now CMDB.

    :return: configuration item list
    """

    config_items = []  # The configuration items
    limit = 5000  # REST API call limit

    # Build the url for the API call
    url = 'https://company.com/' 
    url += 'api/now/table/cmdb_ci?'              # REST API call to cmdb_ci table (configuration items table).
    url += 'sysparm_query='                      # Query parameters begin, parameters are on the following lines.
    url += 'ip_addressISNOTEMPTY'                # IP Address can't be empty
    url += '^install_statusIN7,9,10013,10015,10016'  # State is either Deployed, Disposed, Build, Live, or Retired
    url += '^u_business_segmentNOT INEnterprise,Federal'  # Business Segment is neither Enterprise or Federal
    url += '^ORu_business_segment='  # OR Business Segment is None

    total_count = __get_total_count(url)  # Get the total number of results to our query (# of ci's)

    url += '&sysparm_limit=' + str(limit)  # Convert the limit to string and use it.

    print("Collecting items from REST API.")
    print("This may take quite a while ( > 30 minutes...)")
    print("")

    # Debug counter
    counter = 0

    # Enter a loop to gather paginated results from the Service Now API
    while True:
        # Do the HTTP request
        response = requests.get(url, auth=(username, password),
                                headers={"Content-Type": "application/json", "Accept": "application/json"})
        # Check for HTTP codes other than 200
        if response.status_code != 200:
            print('Status:', response.status_code, 'Headers:', response.headers, 'Error Response:',
                  response.content)
            exit(1)

        print("\nAdding " + str(len(json.loads(response.content)['result'])) + " items to list.")
        print(url)
        config_items.extend(json.loads(response.content)['result'])

        counter += 1

        percentage = ((limit*counter)/total_count)*100

        print("Total Done: " + str(percentage) + "%")

        # If there's another page of results, continue.
        if 'next' in response.links:
            url = response.links['next']['url']
        # Exit the loop if there's no more pages to go through.
        else:
            break

    print("Loops done: " + str(counter))
    print("List length: " + str(len(config_items)))

    # Build a new list that only contains the columns we're looking for.

    # Function returns the list containing IP, OS Patch Owner, Tech Group Owner, and Status.
    return config_items

def __get_total_count(url) -> int:
    """
    Returns the total number of items for a given query

    :param url: query url
    :return: total number of items
    """
    print("Counting the number of items for your query...")

    url += '&sysparm_limit=1'  # Set a limit of one so it's a faster return.

    # Do the HTTP request
    response = requests.get(url, auth=(user, password),
                            headers={"Content-Type": "application/json", "Accept": "application/json"})
    # Check for HTTP codes other than 200
    if response.status_code != 200:
        print('Status:', response.status_code, 'Headers:', response.headers, 'Error Response:',
              response.content)
        exit(1)
    total = int(response.headers['X-Total-Count'])
    print("Total count: " + str(total))
    return total
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...