diff --git a/packages/google-cloud-bigquery-connection/.coveragerc b/packages/google-cloud-bigquery-connection/.coveragerc index d4489baf6153..b547419b01eb 100644 --- a/packages/google-cloud-bigquery-connection/.coveragerc +++ b/packages/google-cloud-bigquery-connection/.coveragerc @@ -5,7 +5,7 @@ branch = True fail_under = 100 show_missing = True omit = - google/cloud/bigquery/connection/__init__.py + google/cloud/bigquery_connection/__init__.py exclude_lines = # Re-enable the standard pragma pragma: NO COVER diff --git a/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/connection_service.rst b/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/connection_service.rst new file mode 100644 index 000000000000..e4a4b8d7871a --- /dev/null +++ b/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/connection_service.rst @@ -0,0 +1,11 @@ +ConnectionService +----------------------------------- + +.. automodule:: google.cloud.bigquery_connection_v1.services.connection_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.bigquery_connection_v1.services.connection_service.pagers + :members: + :inherited-members: diff --git a/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/services.rst b/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/services.rst index 8ae7bc5c7dfa..317815a9deef 100644 --- a/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/services.rst +++ b/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/services.rst @@ -1,6 +1,6 @@ Services for Google Cloud Bigquery Connection v1 API ==================================================== +.. toctree:: + :maxdepth: 2 -.. automodule:: google.cloud.bigquery_connection_v1.services.connection_service - :members: - :inherited-members: + connection_service diff --git a/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/types.rst b/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/types.rst index 9c90aa6e8782..76dbc70da6ee 100644 --- a/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/types.rst +++ b/packages/google-cloud-bigquery-connection/docs/bigquery_connection_v1/types.rst @@ -3,4 +3,5 @@ Types for Google Cloud Bigquery Connection v1 API .. automodule:: google.cloud.bigquery_connection_v1.types :members: + :undoc-members: :show-inheritance: diff --git a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/async_client.py b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/async_client.py index 933c75979ec7..7b774c47b803 100644 --- a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/async_client.py +++ b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/async_client.py @@ -80,7 +80,36 @@ class ConnectionServiceAsyncClient: ConnectionServiceClient.parse_common_location_path ) - from_service_account_file = ConnectionServiceClient.from_service_account_file + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConnectionServiceAsyncClient: The constructed client. + """ + return ConnectionServiceClient.from_service_account_info.__func__(ConnectionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConnectionServiceAsyncClient: The constructed client. + """ + return ConnectionServiceClient.from_service_account_file.__func__(ConnectionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -158,16 +187,17 @@ async def create_connection( r"""Creates a new connection. Args: - request (:class:`~.gcbc_connection.CreateConnectionRequest`): + request (:class:`google.cloud.bigquery_connection_v1.types.CreateConnectionRequest`): The request object. The request for [ConnectionService.CreateConnection][google.cloud.bigquery.connection.v1.ConnectionService.CreateConnection]. parent (:class:`str`): Required. Parent resource name. Must be in the format ``projects/{project_id}/locations/{location_id}`` + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - connection (:class:`~.gcbc_connection.Connection`): + connection (:class:`google.cloud.bigquery_connection_v1.types.Connection`): Required. Connection to create. This corresponds to the ``connection`` field on the ``request`` instance; if ``request`` is provided, this @@ -175,6 +205,7 @@ async def create_connection( connection_id (:class:`str`): Optional. Connection id that should be assigned to the created connection. + This corresponds to the ``connection_id`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -186,7 +217,7 @@ async def create_connection( sent along with the request as metadata. Returns: - ~.gcbc_connection.Connection: + google.cloud.bigquery_connection_v1.types.Connection: Configuration parameters to establish connection with an external data source, except the credential attributes. @@ -246,12 +277,13 @@ async def get_connection( r"""Returns specified connection. Args: - request (:class:`~.connection.GetConnectionRequest`): + request (:class:`google.cloud.bigquery_connection_v1.types.GetConnectionRequest`): The request object. The request for [ConnectionService.GetConnection][google.cloud.bigquery.connection.v1.ConnectionService.GetConnection]. name (:class:`str`): Required. Name of the requested connection, for example: ``projects/{project_id}/locations/{location_id}/connections/{connection_id}`` + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -263,7 +295,7 @@ async def get_connection( sent along with the request as metadata. Returns: - ~.connection.Connection: + google.cloud.bigquery_connection_v1.types.Connection: Configuration parameters to establish connection with an external data source, except the credential attributes. @@ -327,12 +359,13 @@ async def list_connections( r"""Returns a list of connections in the given project. Args: - request (:class:`~.connection.ListConnectionsRequest`): + request (:class:`google.cloud.bigquery_connection_v1.types.ListConnectionsRequest`): The request object. The request for [ConnectionService.ListConnections][google.cloud.bigquery.connection.v1.ConnectionService.ListConnections]. parent (:class:`str`): Required. Parent resource name. Must be in the form: ``projects/{project_id}/locations/{location_id}`` + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -344,7 +377,7 @@ async def list_connections( sent along with the request as metadata. Returns: - ~.pagers.ListConnectionsAsyncPager: + google.cloud.bigquery_connection_v1.services.connection_service.pagers.ListConnectionsAsyncPager: The response for [ConnectionService.ListConnections][google.cloud.bigquery.connection.v1.ConnectionService.ListConnections]. @@ -420,24 +453,27 @@ async def update_connection( are in the update field mask. Args: - request (:class:`~.gcbc_connection.UpdateConnectionRequest`): + request (:class:`google.cloud.bigquery_connection_v1.types.UpdateConnectionRequest`): The request object. The request for [ConnectionService.UpdateConnection][google.cloud.bigquery.connection.v1.ConnectionService.UpdateConnection]. name (:class:`str`): Required. Name of the connection to update, for example: ``projects/{project_id}/locations/{location_id}/connections/{connection_id}`` + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - connection (:class:`~.gcbc_connection.Connection`): + connection (:class:`google.cloud.bigquery_connection_v1.types.Connection`): Required. Connection containing the updated fields. + This corresponds to the ``connection`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - update_mask (:class:`~.field_mask.FieldMask`): + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): Required. Update mask for the connection fields to be updated. + This corresponds to the ``update_mask`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -449,7 +485,7 @@ async def update_connection( sent along with the request as metadata. Returns: - ~.gcbc_connection.Connection: + google.cloud.bigquery_connection_v1.types.Connection: Configuration parameters to establish connection with an external data source, except the credential attributes. @@ -509,12 +545,13 @@ async def delete_connection( r"""Deletes connection and associated credential. Args: - request (:class:`~.connection.DeleteConnectionRequest`): + request (:class:`google.cloud.bigquery_connection_v1.types.DeleteConnectionRequest`): The request object. The request for [ConnectionService.DeleteConnectionRequest][]. name (:class:`str`): Required. Name of the deleted connection, for example: ``projects/{project_id}/locations/{location_id}/connections/{connection_id}`` + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -584,7 +621,7 @@ async def get_iam_policy( not have a policy set. Args: - request (:class:`~.iam_policy.GetIamPolicyRequest`): + request (:class:`google.iam.v1.iam_policy_pb2.GetIamPolicyRequest`): The request object. Request message for `GetIamPolicy` method. resource (:class:`str`): @@ -592,6 +629,7 @@ async def get_iam_policy( policy is being requested. See the operation documentation for the appropriate value for this field. + This corresponds to the ``resource`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -603,72 +641,62 @@ async def get_iam_policy( sent along with the request as metadata. Returns: - ~.policy.Policy: - Defines an Identity and Access Management (IAM) policy. - It is used to specify access control policies for Cloud - Platform resources. - - A ``Policy`` is a collection of ``bindings``. A - ``binding`` binds one or more ``members`` to a single - ``role``. Members can be user accounts, service - accounts, Google groups, and domains (such as G Suite). - A ``role`` is a named list of permissions (defined by - IAM or configured by users). A ``binding`` can - optionally specify a ``condition``, which is a logic - expression that further constrains the role binding - based on attributes about the request and/or target - resource. - - **JSON Example** - - :: - - { - "bindings": [ - { - "role": "roles/resourcemanager.organizationAdmin", - "members": [ - "user:mike@example.com", - "group:admins@example.com", - "domain:google.com", - "serviceAccount:my-project-id@appspot.gserviceaccount.com" - ] - }, - { - "role": "roles/resourcemanager.organizationViewer", - "members": ["user:eve@example.com"], - "condition": { - "title": "expirable access", - "description": "Does not grant access after Sep 2020", - "expression": "request.time < - timestamp('2020-10-01T00:00:00.000Z')", - } - } - ] - } - - **YAML Example** - - :: - - bindings: - - members: - - user:mike@example.com - - group:admins@example.com - - domain:google.com - - serviceAccount:my-project-id@appspot.gserviceaccount.com - role: roles/resourcemanager.organizationAdmin - - members: - - user:eve@example.com - role: roles/resourcemanager.organizationViewer - condition: - title: expirable access - description: Does not grant access after Sep 2020 - expression: request.time < timestamp('2020-10-01T00:00:00.000Z') - - For a description of IAM and its features, see the `IAM - developer's - guide `__. + google.iam.v1.policy_pb2.Policy: + Defines an Identity and Access Management (IAM) policy. It is used to + specify access control policies for Cloud Platform + resources. + + A Policy is a collection of bindings. A binding binds + one or more members to a single role. Members can be + user accounts, service accounts, Google groups, and + domains (such as G Suite). A role is a named list of + permissions (defined by IAM or configured by users). + A binding can optionally specify a condition, which + is a logic expression that further constrains the + role binding based on attributes about the request + and/or target resource. + + **JSON Example** + + { + "bindings": [ + { + "role": + "roles/resourcemanager.organizationAdmin", + "members": [ "user:mike@example.com", + "group:admins@example.com", + "domain:google.com", + "serviceAccount:my-project-id@appspot.gserviceaccount.com" + ] + + }, { "role": + "roles/resourcemanager.organizationViewer", + "members": ["user:eve@example.com"], + "condition": { "title": "expirable access", + "description": "Does not grant access after + Sep 2020", "expression": "request.time < + timestamp('2020-10-01T00:00:00.000Z')", } } + + ] + + } + + **YAML Example** + + bindings: - members: - user:\ mike@example.com - + group:\ admins@example.com - domain:google.com - + serviceAccount:\ my-project-id@appspot.gserviceaccount.com + role: roles/resourcemanager.organizationAdmin - + members: - user:\ eve@example.com role: + roles/resourcemanager.organizationViewer + condition: title: expirable access description: + Does not grant access after Sep 2020 expression: + request.time < + timestamp('2020-10-01T00:00:00.000Z') + + For a description of IAM and its features, see the + [IAM developer's + guide](\ https://cloud.google.com/iam/docs). """ # Create or coerce a protobuf request object. @@ -725,7 +753,7 @@ async def set_iam_policy( ``PERMISSION_DENIED`` errors. Args: - request (:class:`~.iam_policy.SetIamPolicyRequest`): + request (:class:`google.iam.v1.iam_policy_pb2.SetIamPolicyRequest`): The request object. Request message for `SetIamPolicy` method. resource (:class:`str`): @@ -733,6 +761,7 @@ async def set_iam_policy( policy is being specified. See the operation documentation for the appropriate value for this field. + This corresponds to the ``resource`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -744,72 +773,62 @@ async def set_iam_policy( sent along with the request as metadata. Returns: - ~.policy.Policy: - Defines an Identity and Access Management (IAM) policy. - It is used to specify access control policies for Cloud - Platform resources. - - A ``Policy`` is a collection of ``bindings``. A - ``binding`` binds one or more ``members`` to a single - ``role``. Members can be user accounts, service - accounts, Google groups, and domains (such as G Suite). - A ``role`` is a named list of permissions (defined by - IAM or configured by users). A ``binding`` can - optionally specify a ``condition``, which is a logic - expression that further constrains the role binding - based on attributes about the request and/or target - resource. - - **JSON Example** - - :: - - { - "bindings": [ - { - "role": "roles/resourcemanager.organizationAdmin", - "members": [ - "user:mike@example.com", - "group:admins@example.com", - "domain:google.com", - "serviceAccount:my-project-id@appspot.gserviceaccount.com" - ] - }, - { - "role": "roles/resourcemanager.organizationViewer", - "members": ["user:eve@example.com"], - "condition": { - "title": "expirable access", - "description": "Does not grant access after Sep 2020", - "expression": "request.time < - timestamp('2020-10-01T00:00:00.000Z')", - } - } - ] - } - - **YAML Example** - - :: - - bindings: - - members: - - user:mike@example.com - - group:admins@example.com - - domain:google.com - - serviceAccount:my-project-id@appspot.gserviceaccount.com - role: roles/resourcemanager.organizationAdmin - - members: - - user:eve@example.com - role: roles/resourcemanager.organizationViewer - condition: - title: expirable access - description: Does not grant access after Sep 2020 - expression: request.time < timestamp('2020-10-01T00:00:00.000Z') - - For a description of IAM and its features, see the `IAM - developer's - guide `__. + google.iam.v1.policy_pb2.Policy: + Defines an Identity and Access Management (IAM) policy. It is used to + specify access control policies for Cloud Platform + resources. + + A Policy is a collection of bindings. A binding binds + one or more members to a single role. Members can be + user accounts, service accounts, Google groups, and + domains (such as G Suite). A role is a named list of + permissions (defined by IAM or configured by users). + A binding can optionally specify a condition, which + is a logic expression that further constrains the + role binding based on attributes about the request + and/or target resource. + + **JSON Example** + + { + "bindings": [ + { + "role": + "roles/resourcemanager.organizationAdmin", + "members": [ "user:mike@example.com", + "group:admins@example.com", + "domain:google.com", + "serviceAccount:my-project-id@appspot.gserviceaccount.com" + ] + + }, { "role": + "roles/resourcemanager.organizationViewer", + "members": ["user:eve@example.com"], + "condition": { "title": "expirable access", + "description": "Does not grant access after + Sep 2020", "expression": "request.time < + timestamp('2020-10-01T00:00:00.000Z')", } } + + ] + + } + + **YAML Example** + + bindings: - members: - user:\ mike@example.com - + group:\ admins@example.com - domain:google.com - + serviceAccount:\ my-project-id@appspot.gserviceaccount.com + role: roles/resourcemanager.organizationAdmin - + members: - user:\ eve@example.com role: + roles/resourcemanager.organizationViewer + condition: title: expirable access description: + Does not grant access after Sep 2020 expression: + request.time < + timestamp('2020-10-01T00:00:00.000Z') + + For a description of IAM and its features, see the + [IAM developer's + guide](\ https://cloud.google.com/iam/docs). """ # Create or coerce a protobuf request object. @@ -870,7 +889,7 @@ async def test_iam_permissions( warning. Args: - request (:class:`~.iam_policy.TestIamPermissionsRequest`): + request (:class:`google.iam.v1.iam_policy_pb2.TestIamPermissionsRequest`): The request object. Request message for `TestIamPermissions` method. resource (:class:`str`): @@ -878,6 +897,7 @@ async def test_iam_permissions( policy detail is being requested. See the operation documentation for the appropriate value for this field. + This corresponds to the ``resource`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -886,6 +906,7 @@ async def test_iam_permissions( Permissions with wildcards (such as '*' or 'storage.*') are not allowed. For more information see `IAM Overview `__. + This corresponds to the ``permissions`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -897,8 +918,8 @@ async def test_iam_permissions( sent along with the request as metadata. Returns: - ~.iam_policy.TestIamPermissionsResponse: - Response message for ``TestIamPermissions`` method. + google.iam.v1.iam_policy_pb2.TestIamPermissionsResponse: + Response message for TestIamPermissions method. """ # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have diff --git a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/client.py b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/client.py index c25aef2d413e..ec7047432c4f 100644 --- a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/client.py +++ b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/client.py @@ -116,6 +116,22 @@ def _get_default_mtls_endpoint(api_endpoint): DEFAULT_ENDPOINT ) + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConnectionServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + @classmethod def from_service_account_file(cls, filename: str, *args, **kwargs): """Creates an instance of this client using the provided credentials @@ -128,7 +144,7 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): kwargs: Additional arguments to pass to the constructor. Returns: - {@api.name}: The constructed client. + ConnectionServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -236,10 +252,10 @@ def __init__( credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. - transport (Union[str, ~.ConnectionServiceTransport]): The + transport (Union[str, ConnectionServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (client_options_lib.ClientOptions): Custom options for the + client_options (google.api_core.client_options.ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT @@ -275,21 +291,17 @@ def __init__( util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) ) - ssl_credentials = None + client_cert_source_func = None is_mtls = False if use_client_cert: if client_options.client_cert_source: - import grpc # type: ignore - - cert, key = client_options.client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) is_mtls = True + client_cert_source_func = client_options.client_cert_source else: - creds = SslCredentials() - is_mtls = creds.is_mtls - ssl_credentials = creds.ssl_credentials if is_mtls else None + is_mtls = mtls.has_default_client_cert_source() + client_cert_source_func = ( + mtls.default_client_cert_source() if is_mtls else None + ) # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -332,7 +344,7 @@ def __init__( credentials_file=client_options.credentials_file, host=api_endpoint, scopes=client_options.scopes, - ssl_channel_credentials=ssl_credentials, + client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, ) @@ -351,23 +363,25 @@ def create_connection( r"""Creates a new connection. Args: - request (:class:`~.gcbc_connection.CreateConnectionRequest`): + request (google.cloud.bigquery_connection_v1.types.CreateConnectionRequest): The request object. The request for [ConnectionService.CreateConnection][google.cloud.bigquery.connection.v1.ConnectionService.CreateConnection]. - parent (:class:`str`): + parent (str): Required. Parent resource name. Must be in the format ``projects/{project_id}/locations/{location_id}`` + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - connection (:class:`~.gcbc_connection.Connection`): + connection (google.cloud.bigquery_connection_v1.types.Connection): Required. Connection to create. This corresponds to the ``connection`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - connection_id (:class:`str`): + connection_id (str): Optional. Connection id that should be assigned to the created connection. + This corresponds to the ``connection_id`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -379,7 +393,7 @@ def create_connection( sent along with the request as metadata. Returns: - ~.gcbc_connection.Connection: + google.cloud.bigquery_connection_v1.types.Connection: Configuration parameters to establish connection with an external data source, except the credential attributes. @@ -440,12 +454,13 @@ def get_connection( r"""Returns specified connection. Args: - request (:class:`~.connection.GetConnectionRequest`): + request (google.cloud.bigquery_connection_v1.types.GetConnectionRequest): The request object. The request for [ConnectionService.GetConnection][google.cloud.bigquery.connection.v1.ConnectionService.GetConnection]. - name (:class:`str`): + name (str): Required. Name of the requested connection, for example: ``projects/{project_id}/locations/{location_id}/connections/{connection_id}`` + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -457,7 +472,7 @@ def get_connection( sent along with the request as metadata. Returns: - ~.connection.Connection: + google.cloud.bigquery_connection_v1.types.Connection: Configuration parameters to establish connection with an external data source, except the credential attributes. @@ -514,12 +529,13 @@ def list_connections( r"""Returns a list of connections in the given project. Args: - request (:class:`~.connection.ListConnectionsRequest`): + request (google.cloud.bigquery_connection_v1.types.ListConnectionsRequest): The request object. The request for [ConnectionService.ListConnections][google.cloud.bigquery.connection.v1.ConnectionService.ListConnections]. - parent (:class:`str`): + parent (str): Required. Parent resource name. Must be in the form: ``projects/{project_id}/locations/{location_id}`` + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -531,7 +547,7 @@ def list_connections( sent along with the request as metadata. Returns: - ~.pagers.ListConnectionsPager: + google.cloud.bigquery_connection_v1.services.connection_service.pagers.ListConnectionsPager: The response for [ConnectionService.ListConnections][google.cloud.bigquery.connection.v1.ConnectionService.ListConnections]. @@ -600,24 +616,27 @@ def update_connection( are in the update field mask. Args: - request (:class:`~.gcbc_connection.UpdateConnectionRequest`): + request (google.cloud.bigquery_connection_v1.types.UpdateConnectionRequest): The request object. The request for [ConnectionService.UpdateConnection][google.cloud.bigquery.connection.v1.ConnectionService.UpdateConnection]. - name (:class:`str`): + name (str): Required. Name of the connection to update, for example: ``projects/{project_id}/locations/{location_id}/connections/{connection_id}`` + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - connection (:class:`~.gcbc_connection.Connection`): + connection (google.cloud.bigquery_connection_v1.types.Connection): Required. Connection containing the updated fields. + This corresponds to the ``connection`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - update_mask (:class:`~.field_mask.FieldMask`): + update_mask (google.protobuf.field_mask_pb2.FieldMask): Required. Update mask for the connection fields to be updated. + This corresponds to the ``update_mask`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -629,7 +648,7 @@ def update_connection( sent along with the request as metadata. Returns: - ~.gcbc_connection.Connection: + google.cloud.bigquery_connection_v1.types.Connection: Configuration parameters to establish connection with an external data source, except the credential attributes. @@ -690,12 +709,13 @@ def delete_connection( r"""Deletes connection and associated credential. Args: - request (:class:`~.connection.DeleteConnectionRequest`): + request (google.cloud.bigquery_connection_v1.types.DeleteConnectionRequest): The request object. The request for [ConnectionService.DeleteConnectionRequest][]. - name (:class:`str`): + name (str): Required. Name of the deleted connection, for example: ``projects/{project_id}/locations/{location_id}/connections/{connection_id}`` + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -758,14 +778,15 @@ def get_iam_policy( not have a policy set. Args: - request (:class:`~.iam_policy.GetIamPolicyRequest`): + request (google.iam.v1.iam_policy_pb2.GetIamPolicyRequest): The request object. Request message for `GetIamPolicy` method. - resource (:class:`str`): + resource (str): REQUIRED: The resource for which the policy is being requested. See the operation documentation for the appropriate value for this field. + This corresponds to the ``resource`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -777,72 +798,62 @@ def get_iam_policy( sent along with the request as metadata. Returns: - ~.policy.Policy: - Defines an Identity and Access Management (IAM) policy. - It is used to specify access control policies for Cloud - Platform resources. - - A ``Policy`` is a collection of ``bindings``. A - ``binding`` binds one or more ``members`` to a single - ``role``. Members can be user accounts, service - accounts, Google groups, and domains (such as G Suite). - A ``role`` is a named list of permissions (defined by - IAM or configured by users). A ``binding`` can - optionally specify a ``condition``, which is a logic - expression that further constrains the role binding - based on attributes about the request and/or target - resource. - - **JSON Example** - - :: - - { - "bindings": [ - { - "role": "roles/resourcemanager.organizationAdmin", - "members": [ - "user:mike@example.com", - "group:admins@example.com", - "domain:google.com", - "serviceAccount:my-project-id@appspot.gserviceaccount.com" - ] - }, - { - "role": "roles/resourcemanager.organizationViewer", - "members": ["user:eve@example.com"], - "condition": { - "title": "expirable access", - "description": "Does not grant access after Sep 2020", - "expression": "request.time < - timestamp('2020-10-01T00:00:00.000Z')", - } - } - ] - } - - **YAML Example** - - :: - - bindings: - - members: - - user:mike@example.com - - group:admins@example.com - - domain:google.com - - serviceAccount:my-project-id@appspot.gserviceaccount.com - role: roles/resourcemanager.organizationAdmin - - members: - - user:eve@example.com - role: roles/resourcemanager.organizationViewer - condition: - title: expirable access - description: Does not grant access after Sep 2020 - expression: request.time < timestamp('2020-10-01T00:00:00.000Z') - - For a description of IAM and its features, see the `IAM - developer's - guide `__. + google.iam.v1.policy_pb2.Policy: + Defines an Identity and Access Management (IAM) policy. It is used to + specify access control policies for Cloud Platform + resources. + + A Policy is a collection of bindings. A binding binds + one or more members to a single role. Members can be + user accounts, service accounts, Google groups, and + domains (such as G Suite). A role is a named list of + permissions (defined by IAM or configured by users). + A binding can optionally specify a condition, which + is a logic expression that further constrains the + role binding based on attributes about the request + and/or target resource. + + **JSON Example** + + { + "bindings": [ + { + "role": + "roles/resourcemanager.organizationAdmin", + "members": [ "user:mike@example.com", + "group:admins@example.com", + "domain:google.com", + "serviceAccount:my-project-id@appspot.gserviceaccount.com" + ] + + }, { "role": + "roles/resourcemanager.organizationViewer", + "members": ["user:eve@example.com"], + "condition": { "title": "expirable access", + "description": "Does not grant access after + Sep 2020", "expression": "request.time < + timestamp('2020-10-01T00:00:00.000Z')", } } + + ] + + } + + **YAML Example** + + bindings: - members: - user:\ mike@example.com - + group:\ admins@example.com - domain:google.com - + serviceAccount:\ my-project-id@appspot.gserviceaccount.com + role: roles/resourcemanager.organizationAdmin - + members: - user:\ eve@example.com role: + roles/resourcemanager.organizationViewer + condition: title: expirable access description: + Does not grant access after Sep 2020 expression: + request.time < + timestamp('2020-10-01T00:00:00.000Z') + + For a description of IAM and its features, see the + [IAM developer's + guide](\ https://cloud.google.com/iam/docs). """ # Create or coerce a protobuf request object. @@ -855,13 +866,16 @@ def get_iam_policy( "the individual field arguments should be set." ) - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. if isinstance(request, dict): + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. request = iam_policy.GetIamPolicyRequest(**request) - elif not request: - request = iam_policy.GetIamPolicyRequest(resource=resource,) + # Null request, just make one. + request = iam_policy.GetIamPolicyRequest() + + if resource is not None: + request.resource = resource # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. @@ -895,14 +909,15 @@ def set_iam_policy( ``PERMISSION_DENIED`` errors. Args: - request (:class:`~.iam_policy.SetIamPolicyRequest`): + request (google.iam.v1.iam_policy_pb2.SetIamPolicyRequest): The request object. Request message for `SetIamPolicy` method. - resource (:class:`str`): + resource (str): REQUIRED: The resource for which the policy is being specified. See the operation documentation for the appropriate value for this field. + This corresponds to the ``resource`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -914,72 +929,62 @@ def set_iam_policy( sent along with the request as metadata. Returns: - ~.policy.Policy: - Defines an Identity and Access Management (IAM) policy. - It is used to specify access control policies for Cloud - Platform resources. - - A ``Policy`` is a collection of ``bindings``. A - ``binding`` binds one or more ``members`` to a single - ``role``. Members can be user accounts, service - accounts, Google groups, and domains (such as G Suite). - A ``role`` is a named list of permissions (defined by - IAM or configured by users). A ``binding`` can - optionally specify a ``condition``, which is a logic - expression that further constrains the role binding - based on attributes about the request and/or target - resource. - - **JSON Example** - - :: - - { - "bindings": [ - { - "role": "roles/resourcemanager.organizationAdmin", - "members": [ - "user:mike@example.com", - "group:admins@example.com", - "domain:google.com", - "serviceAccount:my-project-id@appspot.gserviceaccount.com" - ] - }, - { - "role": "roles/resourcemanager.organizationViewer", - "members": ["user:eve@example.com"], - "condition": { - "title": "expirable access", - "description": "Does not grant access after Sep 2020", - "expression": "request.time < - timestamp('2020-10-01T00:00:00.000Z')", - } - } - ] - } - - **YAML Example** - - :: - - bindings: - - members: - - user:mike@example.com - - group:admins@example.com - - domain:google.com - - serviceAccount:my-project-id@appspot.gserviceaccount.com - role: roles/resourcemanager.organizationAdmin - - members: - - user:eve@example.com - role: roles/resourcemanager.organizationViewer - condition: - title: expirable access - description: Does not grant access after Sep 2020 - expression: request.time < timestamp('2020-10-01T00:00:00.000Z') - - For a description of IAM and its features, see the `IAM - developer's - guide `__. + google.iam.v1.policy_pb2.Policy: + Defines an Identity and Access Management (IAM) policy. It is used to + specify access control policies for Cloud Platform + resources. + + A Policy is a collection of bindings. A binding binds + one or more members to a single role. Members can be + user accounts, service accounts, Google groups, and + domains (such as G Suite). A role is a named list of + permissions (defined by IAM or configured by users). + A binding can optionally specify a condition, which + is a logic expression that further constrains the + role binding based on attributes about the request + and/or target resource. + + **JSON Example** + + { + "bindings": [ + { + "role": + "roles/resourcemanager.organizationAdmin", + "members": [ "user:mike@example.com", + "group:admins@example.com", + "domain:google.com", + "serviceAccount:my-project-id@appspot.gserviceaccount.com" + ] + + }, { "role": + "roles/resourcemanager.organizationViewer", + "members": ["user:eve@example.com"], + "condition": { "title": "expirable access", + "description": "Does not grant access after + Sep 2020", "expression": "request.time < + timestamp('2020-10-01T00:00:00.000Z')", } } + + ] + + } + + **YAML Example** + + bindings: - members: - user:\ mike@example.com - + group:\ admins@example.com - domain:google.com - + serviceAccount:\ my-project-id@appspot.gserviceaccount.com + role: roles/resourcemanager.organizationAdmin - + members: - user:\ eve@example.com role: + roles/resourcemanager.organizationViewer + condition: title: expirable access description: + Does not grant access after Sep 2020 expression: + request.time < + timestamp('2020-10-01T00:00:00.000Z') + + For a description of IAM and its features, see the + [IAM developer's + guide](\ https://cloud.google.com/iam/docs). """ # Create or coerce a protobuf request object. @@ -992,13 +997,16 @@ def set_iam_policy( "the individual field arguments should be set." ) - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. if isinstance(request, dict): + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. request = iam_policy.SetIamPolicyRequest(**request) - elif not request: - request = iam_policy.SetIamPolicyRequest(resource=resource,) + # Null request, just make one. + request = iam_policy.SetIamPolicyRequest() + + if resource is not None: + request.resource = resource # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. @@ -1036,22 +1044,24 @@ def test_iam_permissions( warning. Args: - request (:class:`~.iam_policy.TestIamPermissionsRequest`): + request (google.iam.v1.iam_policy_pb2.TestIamPermissionsRequest): The request object. Request message for `TestIamPermissions` method. - resource (:class:`str`): + resource (str): REQUIRED: The resource for which the policy detail is being requested. See the operation documentation for the appropriate value for this field. + This corresponds to the ``resource`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - permissions (:class:`Sequence[str]`): + permissions (Sequence[str]): The set of permissions to check for the ``resource``. Permissions with wildcards (such as '*' or 'storage.*') are not allowed. For more information see `IAM Overview `__. + This corresponds to the ``permissions`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1063,8 +1073,8 @@ def test_iam_permissions( sent along with the request as metadata. Returns: - ~.iam_policy.TestIamPermissionsResponse: - Response message for ``TestIamPermissions`` method. + google.iam.v1.iam_policy_pb2.TestIamPermissionsResponse: + Response message for TestIamPermissions method. """ # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have @@ -1076,15 +1086,19 @@ def test_iam_permissions( "the individual field arguments should be set." ) - # The request isn't a proto-plus wrapped type, - # so it must be constructed via keyword expansion. if isinstance(request, dict): + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. request = iam_policy.TestIamPermissionsRequest(**request) - elif not request: - request = iam_policy.TestIamPermissionsRequest( - resource=resource, permissions=permissions, - ) + # Null request, just make one. + request = iam_policy.TestIamPermissionsRequest() + + if resource is not None: + request.resource = resource + + if permissions: + request.permissions.extend(permissions) # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. diff --git a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/pagers.py b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/pagers.py index b9537fcd1a2c..ddb40fd9ccfb 100644 --- a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/pagers.py +++ b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/pagers.py @@ -15,7 +15,16 @@ # limitations under the License. # -from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple +from typing import ( + Any, + AsyncIterable, + Awaitable, + Callable, + Iterable, + Sequence, + Tuple, + Optional, +) from google.cloud.bigquery_connection_v1.types import connection @@ -24,7 +33,7 @@ class ListConnectionsPager: """A pager for iterating through ``list_connections`` requests. This class thinly wraps an initial - :class:`~.connection.ListConnectionsResponse` object, and + :class:`google.cloud.bigquery_connection_v1.types.ListConnectionsResponse` object, and provides an ``__iter__`` method to iterate through its ``connections`` field. @@ -33,7 +42,7 @@ class ListConnectionsPager: through the ``connections`` field on the corresponding responses. - All the usual :class:`~.connection.ListConnectionsResponse` + All the usual :class:`google.cloud.bigquery_connection_v1.types.ListConnectionsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -51,9 +60,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.connection.ListConnectionsRequest`): + request (google.cloud.bigquery_connection_v1.types.ListConnectionsRequest): The initial request object. - response (:class:`~.connection.ListConnectionsResponse`): + response (google.cloud.bigquery_connection_v1.types.ListConnectionsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -86,7 +95,7 @@ class ListConnectionsAsyncPager: """A pager for iterating through ``list_connections`` requests. This class thinly wraps an initial - :class:`~.connection.ListConnectionsResponse` object, and + :class:`google.cloud.bigquery_connection_v1.types.ListConnectionsResponse` object, and provides an ``__aiter__`` method to iterate through its ``connections`` field. @@ -95,7 +104,7 @@ class ListConnectionsAsyncPager: through the ``connections`` field on the corresponding responses. - All the usual :class:`~.connection.ListConnectionsResponse` + All the usual :class:`google.cloud.bigquery_connection_v1.types.ListConnectionsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -113,9 +122,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.connection.ListConnectionsRequest`): + request (google.cloud.bigquery_connection_v1.types.ListConnectionsRequest): The initial request object. - response (:class:`~.connection.ListConnectionsResponse`): + response (google.cloud.bigquery_connection_v1.types.ListConnectionsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/transports/grpc.py b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/transports/grpc.py index d9a04e1d457b..acf8a25aba14 100644 --- a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/transports/grpc.py +++ b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/transports/grpc.py @@ -61,6 +61,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -91,6 +92,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -107,6 +112,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -116,11 +126,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -164,12 +169,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ diff --git a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/transports/grpc_asyncio.py b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/transports/grpc_asyncio.py index 673a50b69d38..e76d07eb1d0c 100644 --- a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/services/connection_service/transports/grpc_asyncio.py @@ -105,6 +105,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -136,6 +137,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -152,6 +157,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -161,11 +171,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -209,12 +214,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ diff --git a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/types/__init__.py b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/types/__init__.py index fa8107a3a531..75cf0ec832ae 100644 --- a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/types/__init__.py +++ b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/types/__init__.py @@ -16,29 +16,29 @@ # from .connection import ( + AwsCrossAccountRole, + AwsProperties, + CloudSqlCredential, + CloudSqlProperties, + Connection, CreateConnectionRequest, + DeleteConnectionRequest, GetConnectionRequest, ListConnectionsRequest, ListConnectionsResponse, UpdateConnectionRequest, - DeleteConnectionRequest, - Connection, - CloudSqlProperties, - CloudSqlCredential, - AwsProperties, - AwsCrossAccountRole, ) __all__ = ( + "AwsCrossAccountRole", + "AwsProperties", + "CloudSqlCredential", + "CloudSqlProperties", + "Connection", "CreateConnectionRequest", + "DeleteConnectionRequest", "GetConnectionRequest", "ListConnectionsRequest", "ListConnectionsResponse", "UpdateConnectionRequest", - "DeleteConnectionRequest", - "Connection", - "CloudSqlProperties", - "CloudSqlCredential", - "AwsProperties", - "AwsCrossAccountRole", ) diff --git a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/types/connection.py b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/types/connection.py index a964123d1fa0..0d92807ce0ab 100644 --- a/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/types/connection.py +++ b/packages/google-cloud-bigquery-connection/google/cloud/bigquery_connection_v1/types/connection.py @@ -50,7 +50,7 @@ class CreateConnectionRequest(proto.Message): connection_id (str): Optional. Connection id that should be assigned to the created connection. - connection (~.gcbc_connection.Connection): + connection (google.cloud.bigquery_connection_v1.types.Connection): Required. Connection to create. """ @@ -102,7 +102,7 @@ class ListConnectionsResponse(proto.Message): Attributes: next_page_token (str): Next page token. - connections (Sequence[~.gcbc_connection.Connection]): + connections (Sequence[google.cloud.bigquery_connection_v1.types.Connection]): List of connections. """ @@ -123,10 +123,10 @@ class UpdateConnectionRequest(proto.Message): name (str): Required. Name of the connection to update, for example: ``projects/{project_id}/locations/{location_id}/connections/{connection_id}`` - connection (~.gcbc_connection.Connection): + connection (google.cloud.bigquery_connection_v1.types.Connection): Required. Connection containing the updated fields. - update_mask (~.field_mask.FieldMask): + update_mask (google.protobuf.field_mask_pb2.FieldMask): Required. Update mask for the connection fields to be updated. """ @@ -163,9 +163,9 @@ class Connection(proto.Message): connection. description (str): User provided description. - cloud_sql (~.gcbc_connection.CloudSqlProperties): + cloud_sql (google.cloud.bigquery_connection_v1.types.CloudSqlProperties): Cloud SQL properties. - aws (~.gcbc_connection.AwsProperties): + aws (google.cloud.bigquery_connection_v1.types.AwsProperties): Amazon Web Services (AWS) properties. creation_time (int): Output only. The creation timestamp of the @@ -208,9 +208,9 @@ class CloudSqlProperties(proto.Message): ``project:location:instance``. database (str): Database name. - type_ (~.gcbc_connection.CloudSqlProperties.DatabaseType): + type_ (google.cloud.bigquery_connection_v1.types.CloudSqlProperties.DatabaseType): Type of the Cloud SQL database. - credential (~.gcbc_connection.CloudSqlCredential): + credential (google.cloud.bigquery_connection_v1.types.CloudSqlCredential): Input only. Cloud SQL credential. """ @@ -248,7 +248,7 @@ class AwsProperties(proto.Message): r"""Connection properties specific to Amazon Web Services (AWS). Attributes: - cross_account_role (~.gcbc_connection.AwsCrossAccountRole): + cross_account_role (google.cloud.bigquery_connection_v1.types.AwsCrossAccountRole): Authentication using Google owned AWS IAM user's access key to assume into customer's AWS IAM Role. diff --git a/packages/google-cloud-bigquery-connection/synth.metadata b/packages/google-cloud-bigquery-connection/synth.metadata index 14ae09f8ef41..09147308e553 100644 --- a/packages/google-cloud-bigquery-connection/synth.metadata +++ b/packages/google-cloud-bigquery-connection/synth.metadata @@ -4,15 +4,15 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-bigquery-connection.git", - "sha": "414af1d702e7dc736c8996084a2e2e58d7819a99" + "sha": "7eeb516191cf2878788dd4f62d59a1c7f5c983b1" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "dd372aa22ded7a8ba6f0e03a80e06358a3fa0907", - "internalRef": "347055288" + "sha": "28a591963253d52ce3a25a918cafbdd9928de8cf", + "internalRef": "361662015" } }, { @@ -42,6 +42,7 @@ } ], "generatedFiles": [ + ".coveragerc", ".flake8", ".github/CONTRIBUTING.md", ".github/ISSUE_TEMPLATE/bug_report.md", @@ -94,6 +95,7 @@ "MANIFEST.in", "docs/_static/custom.css", "docs/_templates/layout.html", + "docs/bigquery_connection_v1/connection_service.rst", "docs/bigquery_connection_v1/services.rst", "docs/bigquery_connection_v1/types.rst", "docs/conf.py", diff --git a/packages/google-cloud-bigquery-connection/tests/unit/gapic/bigquery_connection_v1/__init__.py b/packages/google-cloud-bigquery-connection/tests/unit/gapic/bigquery_connection_v1/__init__.py index 8b137891791f..42ffdf2bc43d 100644 --- a/packages/google-cloud-bigquery-connection/tests/unit/gapic/bigquery_connection_v1/__init__.py +++ b/packages/google-cloud-bigquery-connection/tests/unit/gapic/bigquery_connection_v1/__init__.py @@ -1 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/packages/google-cloud-bigquery-connection/tests/unit/gapic/bigquery_connection_v1/test_connection_service.py b/packages/google-cloud-bigquery-connection/tests/unit/gapic/bigquery_connection_v1/test_connection_service.py index 846fd59271ac..ebffef9b9a93 100644 --- a/packages/google-cloud-bigquery-connection/tests/unit/gapic/bigquery_connection_v1/test_connection_service.py +++ b/packages/google-cloud-bigquery-connection/tests/unit/gapic/bigquery_connection_v1/test_connection_service.py @@ -96,7 +96,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [ConnectionServiceClient, ConnectionServiceAsyncClient] + "client_class", [ConnectionServiceClient, ConnectionServiceAsyncClient,] +) +def test_connection_service_client_from_service_account_info(client_class): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == "bigqueryconnection.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [ConnectionServiceClient, ConnectionServiceAsyncClient,] ) def test_connection_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -106,16 +123,21 @@ def test_connection_service_client_from_service_account_file(client_class): factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) client = client_class.from_service_account_json("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "bigqueryconnection.googleapis.com:443" def test_connection_service_client_get_transport_class(): transport = ConnectionServiceClient.get_transport_class() - assert transport == transports.ConnectionServiceGrpcTransport + available_transports = [ + transports.ConnectionServiceGrpcTransport, + ] + assert transport in available_transports transport = ConnectionServiceClient.get_transport_class("grpc") assert transport == transports.ConnectionServiceGrpcTransport @@ -166,7 +188,7 @@ def test_connection_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -182,7 +204,7 @@ def test_connection_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -198,7 +220,7 @@ def test_connection_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -226,7 +248,7 @@ def test_connection_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id="octopus", client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -287,29 +309,25 @@ def test_connection_service_client_mtls_env_auto( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - ssl_channel_creds = mock.Mock() - with mock.patch( - "grpc.ssl_channel_credentials", return_value=ssl_channel_creds - ): - patched.return_value = None - client = client_class(client_options=options) + patched.return_value = None + client = client_class(client_options=options) - if use_client_cert_env == "false": - expected_ssl_channel_creds = None - expected_host = client.DEFAULT_ENDPOINT - else: - expected_ssl_channel_creds = ssl_channel_creds - expected_host = client.DEFAULT_MTLS_ENDPOINT + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client.DEFAULT_ENDPOINT + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) # Check the case ADC client cert is provided. Whether client cert is used depends on # GOOGLE_API_USE_CLIENT_CERTIFICATE value. @@ -318,66 +336,53 @@ def test_connection_service_client_mtls_env_auto( ): with mock.patch.object(transport_class, "__init__") as patched: with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, ): with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.ssl_credentials", - new_callable=mock.PropertyMock, - ) as ssl_credentials_mock: - if use_client_cert_env == "false": - is_mtls_mock.return_value = False - ssl_credentials_mock.return_value = None - expected_host = client.DEFAULT_ENDPOINT - expected_ssl_channel_creds = None - else: - is_mtls_mock.return_value = True - ssl_credentials_mock.return_value = mock.Mock() - expected_host = client.DEFAULT_MTLS_ENDPOINT - expected_ssl_channel_creds = ( - ssl_credentials_mock.return_value - ) - - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client.DEFAULT_ENDPOINT + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback - # Check the case client_cert_source and ADC client cert are not provided. - with mock.patch.dict( - os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} - ): - with mock.patch.object(transport_class, "__init__") as patched: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None - ): - with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - is_mtls_mock.return_value = False patched.return_value = None client = client_class() patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=expected_host, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -403,7 +408,7 @@ def test_connection_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -433,7 +438,7 @@ def test_connection_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -452,7 +457,7 @@ def test_connection_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -515,6 +520,24 @@ def test_create_connection_from_dict(): test_create_connection(request_type=dict) +def test_create_connection_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ConnectionServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_connection), "__call__" + ) as call: + client.create_connection() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == gcbc_connection.CreateConnectionRequest() + + @pytest.mark.asyncio async def test_create_connection_async( transport: str = "grpc_asyncio", @@ -780,6 +803,22 @@ def test_get_connection_from_dict(): test_get_connection(request_type=dict) +def test_get_connection_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ConnectionServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_connection), "__call__") as call: + client.get_connection() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == connection.GetConnectionRequest() + + @pytest.mark.asyncio async def test_get_connection_async( transport: str = "grpc_asyncio", request_type=connection.GetConnectionRequest @@ -996,6 +1035,22 @@ def test_list_connections_from_dict(): test_list_connections(request_type=dict) +def test_list_connections_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ConnectionServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_connections), "__call__") as call: + client.list_connections() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == connection.ListConnectionsRequest() + + @pytest.mark.asyncio async def test_list_connections_async( transport: str = "grpc_asyncio", request_type=connection.ListConnectionsRequest @@ -1353,6 +1408,24 @@ def test_update_connection_from_dict(): test_update_connection(request_type=dict) +def test_update_connection_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ConnectionServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_connection), "__call__" + ) as call: + client.update_connection() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == gcbc_connection.UpdateConnectionRequest() + + @pytest.mark.asyncio async def test_update_connection_async( transport: str = "grpc_asyncio", @@ -1599,6 +1672,24 @@ def test_delete_connection_from_dict(): test_delete_connection(request_type=dict) +def test_delete_connection_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ConnectionServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_connection), "__call__" + ) as call: + client.delete_connection() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == connection.DeleteConnectionRequest() + + @pytest.mark.asyncio async def test_delete_connection_async( transport: str = "grpc_asyncio", request_type=connection.DeleteConnectionRequest @@ -1800,6 +1891,22 @@ def test_get_iam_policy_from_dict(): test_get_iam_policy(request_type=dict) +def test_get_iam_policy_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ConnectionServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: + client.get_iam_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == iam_policy.GetIamPolicyRequest() + + @pytest.mark.asyncio async def test_get_iam_policy_async( transport: str = "grpc_asyncio", request_type=iam_policy.GetIamPolicyRequest @@ -2013,6 +2120,22 @@ def test_set_iam_policy_from_dict(): test_set_iam_policy(request_type=dict) +def test_set_iam_policy_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ConnectionServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: + client.set_iam_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == iam_policy.SetIamPolicyRequest() + + @pytest.mark.asyncio async def test_set_iam_policy_async( transport: str = "grpc_asyncio", request_type=iam_policy.SetIamPolicyRequest @@ -2228,6 +2351,24 @@ def test_test_iam_permissions_from_dict(): test_test_iam_permissions(request_type=dict) +def test_test_iam_permissions_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ConnectionServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.test_iam_permissions), "__call__" + ) as call: + client.test_iam_permissions() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == iam_policy.TestIamPermissionsRequest() + + @pytest.mark.asyncio async def test_test_iam_permissions_async( transport: str = "grpc_asyncio", request_type=iam_policy.TestIamPermissionsRequest @@ -2605,6 +2746,54 @@ def test_connection_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.ConnectionServiceGrpcTransport, + transports.ConnectionServiceGrpcAsyncIOTransport, + ], +) +def test_connection_service_grpc_transport_client_cert_source_for_mtls(transport_class): + cred = credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=( + "https://www.googleapis.com/auth/bigquery", + "https://www.googleapis.com/auth/cloud-platform", + ), + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + def test_connection_service_host_no_port(): client = ConnectionServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2626,7 +2815,7 @@ def test_connection_service_host_with_port(): def test_connection_service_grpc_transport_channel(): - channel = grpc.insecure_channel("http://localhost/") + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.ConnectionServiceGrpcTransport( @@ -2638,7 +2827,7 @@ def test_connection_service_grpc_transport_channel(): def test_connection_service_grpc_asyncio_transport_channel(): - channel = aio.insecure_channel("http://localhost/") + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) # Check that channel is used if provided. transport = transports.ConnectionServiceGrpcAsyncIOTransport( @@ -2649,6 +2838,8 @@ def test_connection_service_grpc_asyncio_transport_channel(): assert transport._ssl_channel_credentials == None +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -2663,7 +2854,7 @@ def test_connection_service_transport_channel_mtls_with_client_cert_source( "grpc.ssl_channel_credentials", autospec=True ) as grpc_ssl_channel_cred: with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_ssl_cred = mock.Mock() grpc_ssl_channel_cred.return_value = mock_ssl_cred @@ -2704,6 +2895,8 @@ def test_connection_service_transport_channel_mtls_with_client_cert_source( assert transport._ssl_channel_credentials == mock_ssl_cred +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -2719,7 +2912,7 @@ def test_connection_service_transport_channel_mtls_with_adc(transport_class): ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): with mock.patch.object( - transport_class, "create_channel", autospec=True + transport_class, "create_channel" ) as grpc_create_channel: mock_grpc_channel = mock.Mock() grpc_create_channel.return_value = mock_grpc_channel