Создайте Adwords BigQuery Transfer с помощью Python bigquery_datatransfer: ошибка 400 Запрос содержит недопустимый аргумент

Мой шаг:

  1. Получить код авторизации: я использую этот URL для получения кода авторизации

    https://www.gstatic.com/bigquerydatatransfer/oauthz/auth?clientId=<id from list data sources>&scope=https://www.googleapis.com/auth/adwords%20https://www.googleapis.com/auth/bigquery

  2. Создайте учетную запись службы с владельцем проекта

  3. Выполнить пример кода:
def run_quickstart():
    from google.cloud import bigquery_datatransfer_v1
    from google.protobuf.struct_pb2 import Struct

    client = bigquery_datatransfer_v1.DataTransferServiceClient()

    project = <project-id>
    parent = client.location_path(project, 'us')
    params = Struct()
    params.update({
        "customer_id": <customer-id>
    })

    transfer_config = {
        "destination_dataset_id": "test",
        "display_name": "test",
        "data_source_id": "adwords",
        "params": params
    }

    authorization_code = <authorization_code from step 1>
    response = client.create_transfer_config(parent, transfer_config, authorization_code)
    print(response)

if __name__ == '__main__':
    run_quickstart()

Ожидание: создание передачи данных. Но я получил сообщение об ошибке:

Traceback (most recent call last):
  File "/project/lib/python3.7/site-packages/google/api_core/grpc_helpers.py", line 57, in error_remapped_callable
    return callable_(*args, **kwargs)
  File "/project/lib/python3.7/site-packages/grpc/_channel.py", line 826, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File "/project/lib/python3.7/site-packages/grpc/_channel.py", line 729, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
    status = StatusCode.INVALID_ARGUMENT
    details = "Request contains an invalid argument."
    debug_error_string = "{"created":"@1581747953.387292000","description":"Error received from peer ipv6:[2404:6800:4012:1::200a]:443","file":"src/core/lib/surface/call.cc","file_line":1056,"grpc_message":"Request contains an invalid argument.","grpc_status":3}"
>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "app.py", line 49, in <module>
    run_quickstart()
  File "app.py", line 40, in run_quickstart
    parent, transfer_config, authorization_code)
  File "/project/lib/python3.7/site-packages/google/cloud/bigquery_datatransfer_v1/gapic/data_transfer_service_client.py", line 563, in create_transfer_config
    request, retry=retry, timeout=timeout, metadata=metadata
  File "/project/lib/python3.7/site-packages/google/api_core/gapic_v1/method.py", line 143, in __call__
    return wrapped_func(*args, **kwargs)
  File "/project/lib/python3.7/site-packages/google/api_core/retry.py", line 286, in retry_wrapped_func
    on_error=on_error,
  File "/project/lib/python3.7/site-packages/google/api_core/retry.py", line 184, in retry_target
    return target()
  File "/project/lib/python3.7/site-packages/google/api_core/timeout.py", line 214, in func_with_timeout
    return func(*args, **kwargs)
  File "/project/lib/python3.7/site-packages/google/api_core/grpc_helpers.py", line 59, in error_remapped_callable
    six.raise_from(exceptions.from_grpc_error(exc), exc)
  File "<string>", line 3, in raise_from
google.api_core.exceptions.InvalidArgument: 400 Request contains an invalid argument.

Я не мог найти, какой шаг неправильный. Пожалуйста, помогите мне разобраться.

--- Обновление 02-19

@mk_sta

Я удаляю authorization_code, тогда API может создать передачу, но передача не работает. Он получит ошибку, подобную этому снимку экрана.

введите здесь описание изображения

Я думал, что ошибка вызвана тем, что authorization_code используется для подключения к объявлениям Google. У вас нормально работает передача?

Справка:


comment
Пробовали ли вы изменить метод аутентификации в API передачи данных BigQuery, т. е. установить переменную среды GOOGLE_APPLICATION_CREDENTIALS вместо использования кода авторизации OAuth2? Это остается той же проблемой?   -  person Nick_Kh    schedule 18.02.2020
comment
@mk_sta Да, я уже установил среду GOOGLE_APPLICATION_CREDENTIALS   -  person Rukeith    schedule 21.02.2020


Ответы (1)


После пересмотра вашего фрагмента кода я заметил несколько моментов, о которых следует упомянуть:

  1. Согласно документации страницы службы передачи данных BigQuery. требуется, чтобы исходный сервисный аккаунт владел ролью bigquery.admin, чтобы наследовать разрешение bigquery.datasets.update:

Всем пользователям, которые будут создавать переносы, должна быть предоставлена ​​предварительно определенная роль Cloud IAM bigquery.admin. Роль bigquery.admin включает следующие разрешения службы передачи данных BigQuery:

bigquery.transfers.update

bigquery.transfers.get

  1. Всякий раз, когда вы вызываете функцию create_transfer_config, authorization_code является необязательным параметром, который можно пропустить, запуская другую аутентификацию модель для конфигурации транспорта, в зависимости от конкретного случая пользователя.

Я попытался выполнить приведенный выше код, используя ключ служебной учетной записи, связанный с моим проектом GCP:

export GOOGLE_APPLICATION_CREDENTIALS="<some_path>/[FILE_NAME].json"

Я внес несколько изменений в исходный код, чтобы избавиться от authorization_code в конфигурации передачи:

def run_quickstart():
    from google.cloud import bigquery_datatransfer_v1
    from google.protobuf.struct_pb2 import Struct

    client = bigquery_datatransfer_v1.DataTransferServiceClient()

    project = <project-id>
    parent = client.location_path(project, 'us')
    params = Struct()
    params.update({
        "customer_id": <customer-id>
    })

    transfer_config = {
        "destination_dataset_id": "test",
        "display_name": "test",
        "data_source_id": "adwords",
        "params": params
    }

    response = client.create_transfer_config(parent, transfer_config)
    print(response)

if __name__ == '__main__':
    run_quickstart()

И это сработало для меня, и я успешно получил тело ответа:

name: "projects/.../..."
destination_dataset_id: "test"
display_name: "test"
update_time {
  seconds: 1582044242
  nanos: 441442000
}
data_source_id: "adwords"
next_run_time {
  seconds: 1581897600
}
params {
  fields {
    key: "customer_id"
    value {
      string_value: "XXXX"
    }
  }
}
user_id: <user_id>
dataset_region: "us"
person Nick_Kh    schedule 18.02.2020
comment
У меня был немного другой сценарий (у меня не было учетной записи Google Ads), там я использовал один и тот же метод аутентификации как для Bigquery API, так и для исходного программного обеспечения, но теперь я понимаю вашу точку зрения, я попытаюсь получить время, чтобы проверить это и вернуться сюда. - person Nick_Kh; 19.02.2020
comment
Можете ли вы проверить учетные данные в checkValidCreds метод? - person Nick_Kh; 19.02.2020
comment
Я использовал этот метод, и он возвращает true. - person Rukeith; 21.02.2020
comment
Хотя я не использовал рекламный аккаунт Google для получения каких-либо результатов исследований, я предлагаю вам изменить authorization code метод, как описано в этом руководство или поднять вопрос tracker группам разработчиков, так как, по моему предположению, проблема возникла с проверкой OAuth authorization code. - person Nick_Kh; 25.02.2020