From 0eb2ca6b5044553c11d5f5e0f4859bf65387909b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 25 Mar 2021 13:12:44 -0700 Subject: [PATCH] feat: Added support for Monitoring Query Language (#101) feat: Added support for Monitoring Query Language feat: Added support for units in the `MetricService` feat: Added `total_size` to the response of `ListAlertPolicies`. fix: Un-deprecated `cluster_istio` for service monitoring. feat: Added `IstioCanonicalService` for service monitoring. feat: Added creation and mutation records to notification channels. feat: Added support for querying metrics for folders and organizations. fix: Extended the default deadline for `UpdateGroup` to 180s. feat: Added support for secondary aggregation when querying metrics. fix: use correct retry deadline feat: add `client_cert_source_for_mtls` --- .coveragerc | 22 +- docs/monitoring_v3/alert_policy_service.rst | 11 + docs/monitoring_v3/group_service.rst | 11 + docs/monitoring_v3/metric_service.rst | 11 + .../notification_channel_service.rst | 11 + docs/monitoring_v3/query_service.rst | 11 + .../service_monitoring_service.rst | 11 + docs/monitoring_v3/services.rst | 27 +- docs/monitoring_v3/types.rst | 1 + docs/monitoring_v3/uptime_check_service.rst | 11 + google/cloud/monitoring/__init__.py | 6 + google/cloud/monitoring_v3/__init__.py | 6 +- google/cloud/monitoring_v3/proto/alert.proto | 62 +- .../monitoring_v3/proto/alert_service.proto | 17 +- google/cloud/monitoring_v3/proto/common.proto | 49 +- .../monitoring_v3/proto/dropped_labels.proto | 21 +- google/cloud/monitoring_v3/proto/group.proto | 2 +- .../monitoring_v3/proto/group_service.proto | 2 +- google/cloud/monitoring_v3/proto/metric.proto | 19 +- .../monitoring_v3/proto/metric_service.proto | 43 +- .../monitoring_v3/proto/mutation_record.proto | 2 +- .../monitoring_v3/proto/notification.proto | 14 +- .../proto/notification_service.proto | 6 +- .../monitoring_v3/proto/query_service.proto | 50 + .../cloud/monitoring_v3/proto/service.proto | 39 +- .../monitoring_v3/proto/service_service.proto | 18 +- .../monitoring_v3/proto/span_context.proto | 2 +- google/cloud/monitoring_v3/proto/uptime.proto | 81 +- .../monitoring_v3/proto/uptime_service.proto | 2 +- .../alert_policy_service/async_client.py | 112 +- .../services/alert_policy_service/client.py | 126 +- .../services/alert_policy_service/pagers.py | 27 +- .../alert_policy_service/transports/base.py | 21 +- .../alert_policy_service/transports/grpc.py | 115 +- .../transports/grpc_asyncio.py | 123 +- .../services/group_service/async_client.py | 271 ++-- .../services/group_service/client.py | 285 ++-- .../services/group_service/pagers.py | 43 +- .../services/group_service/transports/base.py | 23 +- .../services/group_service/transports/grpc.py | 112 +- .../group_service/transports/grpc_asyncio.py | 120 +- .../services/metric_service/async_client.py | 125 +- .../services/metric_service/client.py | 164 ++- .../services/metric_service/pagers.py | 59 +- .../metric_service/transports/base.py | 24 +- .../metric_service/transports/grpc.py | 112 +- .../metric_service/transports/grpc_asyncio.py | 120 +- .../async_client.py | 154 ++- .../notification_channel_service/client.py | 176 ++- .../notification_channel_service/pagers.py | 43 +- .../transports/base.py | 25 +- .../transports/grpc.py | 112 +- .../transports/grpc_asyncio.py | 120 +- .../services/query_service/__init__.py | 24 + .../services/query_service/async_client.py | 239 ++++ .../services/query_service/client.py | 403 ++++++ .../services/query_service/pagers.py | 158 +++ .../query_service/transports/__init__.py | 35 + .../services/query_service/transports/base.py | 131 ++ .../services/query_service/transports/grpc.py | 256 ++++ .../query_service/transports/grpc_asyncio.py | 261 ++++ .../async_client.py | 135 +- .../service_monitoring_service/client.py | 154 ++- .../service_monitoring_service/pagers.py | 43 +- .../transports/base.py | 24 +- .../transports/grpc.py | 112 +- .../transports/grpc_asyncio.py | 120 +- .../uptime_check_service/async_client.py | 72 +- .../services/uptime_check_service/client.py | 85 +- .../services/uptime_check_service/pagers.py | 43 +- .../uptime_check_service/transports/base.py | 22 +- .../uptime_check_service/transports/grpc.py | 112 +- .../transports/grpc_asyncio.py | 120 +- google/cloud/monitoring_v3/types/__init__.py | 192 +-- google/cloud/monitoring_v3/types/alert.py | 114 +- .../monitoring_v3/types/alert_service.py | 25 +- google/cloud/monitoring_v3/types/common.py | 60 +- .../monitoring_v3/types/dropped_labels.py | 25 +- .../monitoring_v3/types/group_service.py | 10 +- google/cloud/monitoring_v3/types/metric.py | 60 +- .../monitoring_v3/types/metric_service.py | 62 +- .../monitoring_v3/types/mutation_record.py | 2 +- .../cloud/monitoring_v3/types/notification.py | 34 +- .../types/notification_service.py | 21 +- .../monitoring_v3/types/query_service.py | 22 + google/cloud/monitoring_v3/types/service.py | 95 +- .../monitoring_v3/types/service_service.py | 38 +- google/cloud/monitoring_v3/types/uptime.py | 73 +- .../monitoring_v3/types/uptime_service.py | 10 +- scripts/fixup_monitoring_v3_keywords.py | 3 +- synth.metadata | 25 +- tests/unit/gapic/monitoring_v3/__init__.py | 15 + .../test_alert_policy_service.py | 318 +++-- .../gapic/monitoring_v3/test_group_service.py | 318 +++-- .../monitoring_v3/test_metric_service.py | 418 ++++-- .../test_notification_channel_service.py | 420 ++++-- .../gapic/monitoring_v3/test_query_service.py | 1219 +++++++++++++++++ .../test_service_monitoring_service.py | 393 ++++-- .../test_uptime_check_service.py | 330 +++-- 99 files changed, 7381 insertions(+), 2650 deletions(-) create mode 100644 docs/monitoring_v3/alert_policy_service.rst create mode 100644 docs/monitoring_v3/group_service.rst create mode 100644 docs/monitoring_v3/metric_service.rst create mode 100644 docs/monitoring_v3/notification_channel_service.rst create mode 100644 docs/monitoring_v3/query_service.rst create mode 100644 docs/monitoring_v3/service_monitoring_service.rst create mode 100644 docs/monitoring_v3/uptime_check_service.rst create mode 100644 google/cloud/monitoring_v3/proto/query_service.proto create mode 100644 google/cloud/monitoring_v3/services/query_service/__init__.py create mode 100644 google/cloud/monitoring_v3/services/query_service/async_client.py create mode 100644 google/cloud/monitoring_v3/services/query_service/client.py create mode 100644 google/cloud/monitoring_v3/services/query_service/pagers.py create mode 100644 google/cloud/monitoring_v3/services/query_service/transports/__init__.py create mode 100644 google/cloud/monitoring_v3/services/query_service/transports/base.py create mode 100644 google/cloud/monitoring_v3/services/query_service/transports/grpc.py create mode 100644 google/cloud/monitoring_v3/services/query_service/transports/grpc_asyncio.py create mode 100644 google/cloud/monitoring_v3/types/query_service.py create mode 100644 tests/unit/gapic/monitoring_v3/test_query_service.py diff --git a/.coveragerc b/.coveragerc index ed75c17d..37ebb895 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,29 +1,11 @@ -# -*- 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 -# -# https://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. - -# Generated by synthtool. DO NOT EDIT! [run] branch = True -omit = - google/cloud/__init__.py [report] fail_under = 100 show_missing = True -omit = google/cloud/monitoring/__init__.py +omit = + google/cloud/monitoring/__init__.py exclude_lines = # Re-enable the standard pragma pragma: NO COVER diff --git a/docs/monitoring_v3/alert_policy_service.rst b/docs/monitoring_v3/alert_policy_service.rst new file mode 100644 index 00000000..1a413ef2 --- /dev/null +++ b/docs/monitoring_v3/alert_policy_service.rst @@ -0,0 +1,11 @@ +AlertPolicyService +------------------------------------ + +.. automodule:: google.cloud.monitoring_v3.services.alert_policy_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.monitoring_v3.services.alert_policy_service.pagers + :members: + :inherited-members: diff --git a/docs/monitoring_v3/group_service.rst b/docs/monitoring_v3/group_service.rst new file mode 100644 index 00000000..c191656e --- /dev/null +++ b/docs/monitoring_v3/group_service.rst @@ -0,0 +1,11 @@ +GroupService +------------------------------ + +.. automodule:: google.cloud.monitoring_v3.services.group_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.monitoring_v3.services.group_service.pagers + :members: + :inherited-members: diff --git a/docs/monitoring_v3/metric_service.rst b/docs/monitoring_v3/metric_service.rst new file mode 100644 index 00000000..15e120c3 --- /dev/null +++ b/docs/monitoring_v3/metric_service.rst @@ -0,0 +1,11 @@ +MetricService +------------------------------- + +.. automodule:: google.cloud.monitoring_v3.services.metric_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.monitoring_v3.services.metric_service.pagers + :members: + :inherited-members: diff --git a/docs/monitoring_v3/notification_channel_service.rst b/docs/monitoring_v3/notification_channel_service.rst new file mode 100644 index 00000000..cdcaaf1f --- /dev/null +++ b/docs/monitoring_v3/notification_channel_service.rst @@ -0,0 +1,11 @@ +NotificationChannelService +-------------------------------------------- + +.. automodule:: google.cloud.monitoring_v3.services.notification_channel_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.monitoring_v3.services.notification_channel_service.pagers + :members: + :inherited-members: diff --git a/docs/monitoring_v3/query_service.rst b/docs/monitoring_v3/query_service.rst new file mode 100644 index 00000000..d600d503 --- /dev/null +++ b/docs/monitoring_v3/query_service.rst @@ -0,0 +1,11 @@ +QueryService +------------------------------ + +.. automodule:: google.cloud.monitoring_v3.services.query_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.monitoring_v3.services.query_service.pagers + :members: + :inherited-members: diff --git a/docs/monitoring_v3/service_monitoring_service.rst b/docs/monitoring_v3/service_monitoring_service.rst new file mode 100644 index 00000000..b3781db9 --- /dev/null +++ b/docs/monitoring_v3/service_monitoring_service.rst @@ -0,0 +1,11 @@ +ServiceMonitoringService +------------------------------------------ + +.. automodule:: google.cloud.monitoring_v3.services.service_monitoring_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.monitoring_v3.services.service_monitoring_service.pagers + :members: + :inherited-members: diff --git a/docs/monitoring_v3/services.rst b/docs/monitoring_v3/services.rst index d6930ee6..18a1eb15 100644 --- a/docs/monitoring_v3/services.rst +++ b/docs/monitoring_v3/services.rst @@ -1,21 +1,12 @@ Services for Google Cloud Monitoring v3 API =========================================== +.. toctree:: + :maxdepth: 2 -.. automodule:: google.cloud.monitoring_v3.services.alert_policy_service - :members: - :inherited-members: -.. automodule:: google.cloud.monitoring_v3.services.group_service - :members: - :inherited-members: -.. automodule:: google.cloud.monitoring_v3.services.metric_service - :members: - :inherited-members: -.. automodule:: google.cloud.monitoring_v3.services.notification_channel_service - :members: - :inherited-members: -.. automodule:: google.cloud.monitoring_v3.services.service_monitoring_service - :members: - :inherited-members: -.. automodule:: google.cloud.monitoring_v3.services.uptime_check_service - :members: - :inherited-members: + alert_policy_service + group_service + metric_service + notification_channel_service + query_service + service_monitoring_service + uptime_check_service diff --git a/docs/monitoring_v3/types.rst b/docs/monitoring_v3/types.rst index ae49a858..ed0eeeef 100644 --- a/docs/monitoring_v3/types.rst +++ b/docs/monitoring_v3/types.rst @@ -3,4 +3,5 @@ Types for Google Cloud Monitoring v3 API .. automodule:: google.cloud.monitoring_v3.types :members: + :undoc-members: :show-inheritance: diff --git a/docs/monitoring_v3/uptime_check_service.rst b/docs/monitoring_v3/uptime_check_service.rst new file mode 100644 index 00000000..a433d1b2 --- /dev/null +++ b/docs/monitoring_v3/uptime_check_service.rst @@ -0,0 +1,11 @@ +UptimeCheckService +------------------------------------ + +.. automodule:: google.cloud.monitoring_v3.services.uptime_check_service + :members: + :inherited-members: + + +.. automodule:: google.cloud.monitoring_v3.services.uptime_check_service.pagers + :members: + :inherited-members: diff --git a/google/cloud/monitoring/__init__.py b/google/cloud/monitoring/__init__.py index 9b32a207..1d6a7622 100644 --- a/google/cloud/monitoring/__init__.py +++ b/google/cloud/monitoring/__init__.py @@ -37,6 +37,10 @@ from google.cloud.monitoring_v3.services.notification_channel_service.client import ( NotificationChannelServiceClient, ) +from google.cloud.monitoring_v3.services.query_service.async_client import ( + QueryServiceAsyncClient, +) +from google.cloud.monitoring_v3.services.query_service.client import QueryServiceClient from google.cloud.monitoring_v3.services.service_monitoring_service.async_client import ( ServiceMonitoringServiceAsyncClient, ) @@ -283,6 +287,8 @@ "Point", "QueryError", "QueryErrorList", + "QueryServiceAsyncClient", + "QueryServiceClient", "QueryTimeSeriesRequest", "QueryTimeSeriesResponse", "Range", diff --git a/google/cloud/monitoring_v3/__init__.py b/google/cloud/monitoring_v3/__init__.py index 215d3e83..1bd5d669 100644 --- a/google/cloud/monitoring_v3/__init__.py +++ b/google/cloud/monitoring_v3/__init__.py @@ -19,6 +19,7 @@ from .services.group_service import GroupServiceClient from .services.metric_service import MetricServiceClient from .services.notification_channel_service import NotificationChannelServiceClient +from .services.query_service import QueryServiceClient from .services.service_monitoring_service import ServiceMonitoringServiceClient from .services.uptime_check_service import UptimeCheckServiceClient from .types.alert import AlertPolicy @@ -122,6 +123,7 @@ __all__ = ( "Aggregation", "AlertPolicy", + "AlertPolicyServiceClient", "BasicSli", "ComparisonType", "CreateAlertPolicyRequest", @@ -183,7 +185,6 @@ "ListUptimeCheckConfigsResponse", "ListUptimeCheckIpsRequest", "ListUptimeCheckIpsResponse", - "MetricServiceClient", "MutationRecord", "NotificationChannel", "NotificationChannelDescriptor", @@ -191,6 +192,7 @@ "Point", "QueryError", "QueryErrorList", + "QueryServiceClient", "QueryTimeSeriesRequest", "QueryTimeSeriesResponse", "Range", @@ -221,5 +223,5 @@ "UptimeCheckServiceClient", "VerifyNotificationChannelRequest", "WindowsBasedSli", - "AlertPolicyServiceClient", + "MetricServiceClient", ) diff --git a/google/cloud/monitoring_v3/proto/alert.proto b/google/cloud/monitoring_v3/proto/alert.proto index 6662304d..8d1cbf2e 100644 --- a/google/cloud/monitoring_v3/proto/alert.proto +++ b/google/cloud/monitoring_v3/proto/alert.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ syntax = "proto3"; package google.monitoring.v3; +import "google/api/field_behavior.proto"; import "google/api/resource.proto"; import "google/monitoring/v3/common.proto"; import "google/monitoring/v3/mutation_record.proto"; @@ -89,17 +90,17 @@ message AlertPolicy { // A condition type that compares a collection of time series // against a threshold. message MetricThreshold { - // A [filter](https://cloud.google.com/monitoring/api/v3/filters) that + // Required. A [filter](https://cloud.google.com/monitoring/api/v3/filters) that // identifies which time series should be compared with the threshold. // // The filter is similar to the one that is specified in the // [`ListTimeSeries` // request](https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.timeSeries/list) // (that call is useful to verify the time series that will be retrieved / - // processed) and must specify the metric type and optionally may contain - // restrictions on resource type, resource labels, and metric labels. - // This field may not exceed 2048 Unicode characters in length. - string filter = 2; + // processed). The filter must specify the metric type and the resource + // type. Optionally, it can specify resource labels and metric labels. + // This field must not exceed 2048 Unicode characters in length. + string filter = 2 [(google.api.field_behavior) = REQUIRED]; // Specifies the alignment of data points in individual time series as // well as how to combine the retrieved time series together (such as @@ -175,17 +176,17 @@ message AlertPolicy { // when a time series for the specified metric of a monitored // resource does not include any data in the specified `duration`. message MetricAbsence { - // A [filter](https://cloud.google.com/monitoring/api/v3/filters) that + // Required. A [filter](https://cloud.google.com/monitoring/api/v3/filters) that // identifies which time series should be compared with the threshold. // // The filter is similar to the one that is specified in the // [`ListTimeSeries` // request](https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.timeSeries/list) // (that call is useful to verify the time series that will be retrieved / - // processed) and must specify the metric type and optionally may contain - // restrictions on resource type, resource labels, and metric labels. - // This field may not exceed 2048 Unicode characters in length. - string filter = 1; + // processed). The filter must specify the metric type and the resource + // type. Optionally, it can specify resource labels and metric labels. + // This field must not exceed 2048 Unicode characters in length. + string filter = 1 [(google.api.field_behavior) = REQUIRED]; // Specifies the alignment of data points in individual time series as // well as how to combine the retrieved time series together (such as @@ -201,9 +202,10 @@ message AlertPolicy { repeated Aggregation aggregations = 5; // The amount of time that a time series must fail to report new - // data to be considered failing. Currently, only values that - // are a multiple of a minute--e.g. 60, 120, or 300 - // seconds--are supported. If an invalid value is given, an + // data to be considered failing. The minimum value of this field + // is 120 seconds. Larger values that are a multiple of a + // minute--for example, 240 or 300 seconds--are supported. + // If an invalid value is given, an // error will be returned. The `Duration.nanos` field is // ignored. google.protobuf.Duration duration = 2; @@ -215,6 +217,34 @@ message AlertPolicy { Trigger trigger = 3; } + // A condition type that allows alert policies to be defined using + // [Monitoring Query Language](https://cloud.google.com/monitoring/mql). + message MonitoringQueryLanguageCondition { + // [Monitoring Query Language](https://cloud.google.com/monitoring/mql) + // query that outputs a boolean stream. + string query = 1; + + // The amount of time that a time series must violate the + // threshold to be considered failing. Currently, only values + // that are a multiple of a minute--e.g., 0, 60, 120, or 300 + // seconds--are supported. If an invalid value is given, an + // error will be returned. When choosing a duration, it is useful to + // keep in mind the frequency of the underlying time series data + // (which may also be affected by any alignments specified in the + // `aggregations` field); a good duration is long enough so that a single + // outlier does not generate spurious alerts, but short enough that + // unhealthy states are detected and alerted on quickly. + google.protobuf.Duration duration = 2; + + // The number/percent of time series for which the comparison must hold + // in order for the condition to trigger. If unspecified, then the + // condition will trigger if the comparison is true for any of the + // time series that have been identified by `filter` and `aggregations`, + // or by the ratio, if `denominator_filter` and `denominator_aggregations` + // are specified. + Trigger trigger = 3; + } + // Required if the condition exists. The unique resource name for this // condition. Its format is: // @@ -255,6 +285,10 @@ message AlertPolicy { // A condition that checks that a time series continues to // receive new data points. MetricAbsence condition_absent = 2; + + // A condition that uses the Monitoring Query Language to define + // alerts. + MonitoringQueryLanguageCondition condition_monitoring_query_language = 19; } } diff --git a/google/cloud/monitoring_v3/proto/alert_service.proto b/google/cloud/monitoring_v3/proto/alert_service.proto index ea0c5ada..4017b16e 100644 --- a/google/cloud/monitoring_v3/proto/alert_service.proto +++ b/google/cloud/monitoring_v3/proto/alert_service.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -48,7 +48,7 @@ service AlertPolicyService { "https://www.googleapis.com/auth/monitoring," "https://www.googleapis.com/auth/monitoring.read"; - // Lists the existing alerting policies for the project. + // Lists the existing alerting policies for the workspace. rpc ListAlertPolicies(ListAlertPoliciesRequest) returns (ListAlertPoliciesResponse) { option (google.api.http) = { get: "/v3/{name=projects/*}/alertPolicies" @@ -101,10 +101,11 @@ message CreateAlertPolicyRequest { // projects/[PROJECT_ID_OR_NUMBER] // // Note that this field names the parent container in which the alerting - // policy will be written, not the name of the created policy. The alerting - // policy that is returned will have a name that contains a normalized - // representation of this name as a prefix but adds a suffix of the form - // `/alertPolicies/[ALERT_POLICY_ID]`, identifying the policy in the + // policy will be written, not the name of the created policy. |name| must be + // a host project of a workspace, otherwise INVALID_ARGUMENT error will + // return. The alerting policy that is returned will have a name that contains + // a normalized representation of this name as a prefix but adds a suffix of + // the form `/alertPolicies/[ALERT_POLICY_ID]`, identifying the policy in the // container. string name = 3 [ (google.api.field_behavior) = REQUIRED, @@ -183,6 +184,10 @@ message ListAlertPoliciesResponse { // to a non-empty value. To see the additional results, // use that value as `page_token` in the next call to this method. string next_page_token = 2; + + // The total number of alert policies in all pages. This number is only an + // estimate, and may change in subsequent pages. https://aip.dev/158 + int32 total_size = 4; } // The protocol for the `UpdateAlertPolicy` request. diff --git a/google/cloud/monitoring_v3/proto/common.proto b/google/cloud/monitoring_v3/proto/common.proto index 26242225..77a28ea3 100644 --- a/google/cloud/monitoring_v3/proto/common.proto +++ b/google/cloud/monitoring_v3/proto/common.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -51,28 +51,34 @@ message TypedValue { } } -// A closed time interval. It extends from the start time to the end time, and -// includes both: `[startTime, endTime]`. Valid time intervals depend on the -// [`MetricKind`](https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.metricDescriptors#MetricKind) -// of the metric value. In no case can the end time be earlier than the start -// time. +// A closed time interval. It extends from the start time to the end time, and includes both: `[startTime, endTime]`. Valid time intervals depend on the [`MetricKind`](/monitoring/api/ref_v3/rest/v3/projects.metricDescriptors#MetricKind) of the metric value. The end time must not be earlier than the start time. When writing data points, the start time must not be more than 25 hours in the past and the end time must not be more than five minutes in the future. // -// * For a `GAUGE` metric, the `startTime` value is technically optional; if +// * For `GAUGE` metrics, the `startTime` value is technically optional; if // no value is specified, the start time defaults to the value of the // end time, and the interval represents a single point in time. If both // start and end times are specified, they must be identical. Such an // interval is valid only for `GAUGE` metrics, which are point-in-time -// measurements. +// measurements. The end time of a new interval must be at least a +// millisecond after the end time of the previous interval. // -// * For `DELTA` and `CUMULATIVE` metrics, the start time must be earlier -// than the end time. +// * For `DELTA` metrics, the start time and end time must specify a +// non-zero interval, with subsequent points specifying contiguous and +// non-overlapping intervals. For `DELTA` metrics, the start time of +// the next interval must be at least a millisecond after the end time +// of the previous interval. // -// * In all cases, the start time of the next interval must be -// at least a millisecond after the end time of the previous interval. -// Because the interval is closed, if the start time of a new interval -// is the same as the end time of the previous interval, data written -// at the new start time could overwrite data written at the previous -// end time. +// * For `CUMULATIVE` metrics, the start time and end time must specify a +// a non-zero interval, with subsequent points specifying the same +// start time and increasing end times, until an event resets the +// cumulative value to zero and sets a new start time for the following +// points. The new start time must be at least a millisecond after the +// end time of the previous interval. +// +// * The start time of a new interval must be at least a millisecond after the +// end time of the previous interval because intervals are closed. If the +// start time of a new interval is the same as the end time of the previous +// interval, then data written at the new start time could overwrite data +// written at the previous end time. message TimeInterval { // Required. The end of the time interval. google.protobuf.Timestamp end_time = 2; @@ -370,10 +376,13 @@ message Aggregation { // time. This will be done before the per-series aligner can be applied to // the data. // - // The value must be at least 60 seconds. If a per-series aligner other than - // `ALIGN_NONE` is specified, this field is required or an error is returned. - // If no per-series aligner is specified, or the aligner `ALIGN_NONE` is - // specified, then this field is ignored. + // The value must be at least 60 seconds. If a per-series + // aligner other than `ALIGN_NONE` is specified, this field is required or an + // error is returned. If no per-series aligner is specified, or the aligner + // `ALIGN_NONE` is specified, then this field is ignored. + // + // The maximum value of the `alignment_period` is 104 weeks (2 years) for + // charts, and 90,000 seconds (25 hours) for alerting policies. google.protobuf.Duration alignment_period = 1; // An `Aligner` describes how to bring the data points in a single diff --git a/google/cloud/monitoring_v3/proto/dropped_labels.proto b/google/cloud/monitoring_v3/proto/dropped_labels.proto index ce6e46e1..16e213c4 100644 --- a/google/cloud/monitoring_v3/proto/dropped_labels.proto +++ b/google/cloud/monitoring_v3/proto/dropped_labels.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,16 +24,17 @@ option java_package = "com.google.monitoring.v3"; option php_namespace = "Google\\Cloud\\Monitoring\\V3"; option ruby_package = "Google::Cloud::Monitoring::V3"; -// A set of (label, value) pairs which were dropped during aggregation, attached -// to google.api.Distribution.Exemplars in google.api.Distribution values during -// aggregation. +// A set of (label, value) pairs that were removed from a Distribution +// time series during aggregation and then added as an attachment to a +// Distribution.Exemplar. // -// These values are used in combination with the label values that remain on the -// aggregated Distribution timeseries to construct the full label set for the -// exemplar values. The resulting full label set may be used to identify the -// specific task/job/instance (for example) which may be contributing to a -// long-tail, while allowing the storage savings of only storing aggregated -// distribution values for a large group. +// The full label set for the exemplars is constructed by using the dropped +// pairs in combination with the label values that remain on the aggregated +// Distribution time series. The constructed full label set can be used to +// identify the specific entity, such as the instance or job, which might be +// contributing to a long-tail. However, with dropped labels, the storage +// requirements are reduced because only the aggregated distribution values for +// a large group of time series are stored. // // Note that there are no guarantees on ordering of the labels from // exemplar-to-exemplar and from distribution-to-distribution in the same diff --git a/google/cloud/monitoring_v3/proto/group.proto b/google/cloud/monitoring_v3/proto/group.proto index 2d1ffbb6..a414cc85 100644 --- a/google/cloud/monitoring_v3/proto/group.proto +++ b/google/cloud/monitoring_v3/proto/group.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/google/cloud/monitoring_v3/proto/group_service.proto b/google/cloud/monitoring_v3/proto/group_service.proto index 0163ab36..6385c8bb 100644 --- a/google/cloud/monitoring_v3/proto/group_service.proto +++ b/google/cloud/monitoring_v3/proto/group_service.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/google/cloud/monitoring_v3/proto/metric.proto b/google/cloud/monitoring_v3/proto/metric.proto index 5a4833b1..c0c23a39 100644 --- a/google/cloud/monitoring_v3/proto/metric.proto +++ b/google/cloud/monitoring_v3/proto/metric.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -62,8 +62,8 @@ message TimeSeries { google.api.MonitoredResource resource = 2; // Output only. The associated monitored resource metadata. When reading a - // a timeseries, this field will include metadata labels that are explicitly - // named in the reduction. When creating a timeseries, this field is ignored. + // time series, this field will include metadata labels that are explicitly + // named in the reduction. When creating a time series, this field is ignored. google.api.MonitoredResourceMetadata metadata = 7; // The metric kind of the time series. When listing time series, this metric @@ -94,9 +94,14 @@ message TimeSeries { // the value type of the descriptor is determined by the point's type, which // must be `BOOL`, `INT64`, `DOUBLE`, or `DISTRIBUTION`. repeated Point points = 5; + + // The units in which the metric value is reported. It is only applicable + // if the `value_type` is `INT64`, `DOUBLE`, or `DISTRIBUTION`. The `unit` + // defines the representation of the stored metric values. + string unit = 8; } -// A descriptor for the labels and points in a timeseries. +// A descriptor for the labels and points in a time series. message TimeSeriesDescriptor { // A descriptor for the value columns in a data point. message ValueDescriptor { @@ -108,6 +113,12 @@ message TimeSeriesDescriptor { // The value stream kind. google.api.MetricDescriptor.MetricKind metric_kind = 3; + + // The unit in which `time_series` point values are reported. `unit` + // follows the UCUM format for units as seen in + // https://unitsofmeasure.org/ucum.html. + // `unit` is only valid if `value_type` is INTEGER, DOUBLE, DISTRIBUTION. + string unit = 4; } // Descriptors for the labels. diff --git a/google/cloud/monitoring_v3/proto/metric_service.proto b/google/cloud/monitoring_v3/proto/metric_service.proto index 11999035..ab30e285 100644 --- a/google/cloud/monitoring_v3/proto/metric_service.proto +++ b/google/cloud/monitoring_v3/proto/metric_service.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -52,6 +52,17 @@ option (google.api.resource_definition) = { pattern: "*" history: ORIGINALLY_SINGLE_PATTERN }; +option (google.api.resource_definition) = { + type: "monitoring.googleapis.com/Workspace" + pattern: "projects/{project}" + pattern: "workspaces/{workspace}" +}; +option (google.api.resource_definition) = { + type: "monitoring.googleapis.com/TimeSeries" + pattern: "projects/{project}/timeSeries/{time_series}" + pattern: "organizations/{organization}/timeSeries/{time_series}" + pattern: "folders/{folder}/timeSeries/{time_series}" +}; // Manages metric descriptors, monitored resource descriptors, and // time series data. @@ -120,6 +131,12 @@ service MetricService { rpc ListTimeSeries(ListTimeSeriesRequest) returns (ListTimeSeriesResponse) { option (google.api.http) = { get: "/v3/{name=projects/*}/timeSeries" + additional_bindings { + get: "/v3/{name=organizations/*}/timeSeries" + } + additional_bindings { + get: "/v3/{name=folders/*}/timeSeries" + } }; option (google.api.method_signature) = "name,filter,interval,view"; } @@ -299,13 +316,16 @@ message ListTimeSeriesRequest { HEADERS = 1; } - // Required. The project on which to execute the request. The format is: + // Required. The project, organization or folder on which to execute the request. The + // format is: // // projects/[PROJECT_ID_OR_NUMBER] + // organizations/[ORGANIZATION_ID] + // folders/[FOLDER_ID] string name = 10 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { - type: "cloudresourcemanager.googleapis.com/Project" + child_type: "monitoring.googleapis.com/TimeSeries" } ]; @@ -330,6 +350,10 @@ message ListTimeSeriesRequest { // series data is returned. Aggregation aggregation = 5; + // Apply a second aggregation after `aggregation` is applied. May only be + // specified if `aggregation` is specified. + Aggregation secondary_aggregation = 11; + // Unsupported: must be left blank. The points in each time series are // currently returned in reverse time order (most recent to oldest). string order_by = 6; @@ -363,6 +387,14 @@ message ListTimeSeriesResponse { // Query execution errors that may have caused the time series data returned // to be incomplete. repeated google.rpc.Status execution_errors = 3; + + // The unit in which all `time_series` point values are reported. `unit` + // follows the UCUM format for units as seen in + // https://unitsofmeasure.org/ucum.html. + // If different `time_series` have different units (for example, because they + // come from different metric types, or a unit is absent), then `unit` will be + // "{not_a_unit}". + string unit = 5; } // The `CreateTimeSeries` request. @@ -424,8 +456,9 @@ message QueryTimeSeriesRequest { // projects/[PROJECT_ID_OR_NUMBER] string name = 1; - // Required. The query in the monitoring query language format. The default - // time zone is in UTC. + // Required. The query in the [Monitoring Query + // Language](https://cloud.google.com/monitoring/mql/reference) format. + // The default time zone is in UTC. string query = 7; // A positive number that is the maximum number of time_series_data to return. diff --git a/google/cloud/monitoring_v3/proto/mutation_record.proto b/google/cloud/monitoring_v3/proto/mutation_record.proto index b830eb62..77c2d5c2 100644 --- a/google/cloud/monitoring_v3/proto/mutation_record.proto +++ b/google/cloud/monitoring_v3/proto/mutation_record.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/google/cloud/monitoring_v3/proto/notification.proto b/google/cloud/monitoring_v3/proto/notification.proto index 897a14c0..74ea3a15 100644 --- a/google/cloud/monitoring_v3/proto/notification.proto +++ b/google/cloud/monitoring_v3/proto/notification.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import "google/api/label.proto"; import "google/api/launch_stage.proto"; import "google/api/resource.proto"; import "google/monitoring/v3/common.proto"; +import "google/monitoring/v3/mutation_record.proto"; import "google/protobuf/wrappers.proto"; option csharp_namespace = "Google.Cloud.Monitoring.V3"; @@ -49,7 +50,10 @@ message NotificationChannelDescriptor { // In the above, `[TYPE]` is the value of the `type` field. string name = 6; - // The type of notification channel, such as "email", "sms", etc. + // The type of notification channel, such as "email" and "sms". To view the + // full list of channels, see + // [Channel + // descriptors](https://cloud.google.com/monitoring/alerts/using-channels-api#ncd). // Notification channel types are globally unique. string type = 1; @@ -180,4 +184,10 @@ message NotificationChannel { // temporary and you want to receive notifications from the same set // of alerting policies on the channel at some point in the future. google.protobuf.BoolValue enabled = 11; + + // Record of the creation of this channel. + MutationRecord creation_record = 12; + + // Records of the modification of this channel. + repeated MutationRecord mutation_records = 13; } diff --git a/google/cloud/monitoring_v3/proto/notification_service.proto b/google/cloud/monitoring_v3/proto/notification_service.proto index 20c9a8e9..0039ce15 100644 --- a/google/cloud/monitoring_v3/proto/notification_service.proto +++ b/google/cloud/monitoring_v3/proto/notification_service.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -291,6 +291,10 @@ message ListNotificationChannelsResponse { // subsequent request to fetch the next set of results. If empty, // all results have been returned. string next_page_token = 2; + + // The total number of notification channels in all pages. This number is only + // an estimate, and may change in subsequent pages. https://aip.dev/158 + int32 total_size = 4; } // The `GetNotificationChannel` request. diff --git a/google/cloud/monitoring_v3/proto/query_service.proto b/google/cloud/monitoring_v3/proto/query_service.proto new file mode 100644 index 00000000..80bb4126 --- /dev/null +++ b/google/cloud/monitoring_v3/proto/query_service.proto @@ -0,0 +1,50 @@ +// Copyright 2021 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. + +syntax = "proto3"; + +package google.monitoring.v3; + +import "google/api/annotations.proto"; +import "google/api/label.proto"; +import "google/monitoring/v3/metric.proto"; +import "google/monitoring/v3/metric_service.proto"; +import "google/api/client.proto"; + +option csharp_namespace = "Google.Cloud.Monitoring.V3"; +option go_package = "google.golang.org/genproto/googleapis/monitoring/v3;monitoring"; +option java_multiple_files = true; +option java_outer_classname = "QueryServiceProto"; +option java_package = "com.google.monitoring.v3"; +option php_namespace = "Google\\Cloud\\Monitoring\\V3"; +option ruby_package = "Google::Cloud::Monitoring::V3"; + +// The QueryService API is used to manage time series data in Stackdriver +// Monitoring. Time series data is a collection of data points that describes +// the time-varying values of a metric. +service QueryService { + option (google.api.default_host) = "monitoring.googleapis.com"; + option (google.api.oauth_scopes) = + "https://www.googleapis.com/auth/cloud-platform," + "https://www.googleapis.com/auth/monitoring," + "https://www.googleapis.com/auth/monitoring.read"; + + // Queries time series using Monitoring Query Language. This method does not require a Workspace. + rpc QueryTimeSeries(QueryTimeSeriesRequest) returns (QueryTimeSeriesResponse) { + option (google.api.http) = { + post: "/v3/{name=projects/*}/timeSeries:query" + body: "*" + }; + } +} diff --git a/google/cloud/monitoring_v3/proto/service.proto b/google/cloud/monitoring_v3/proto/service.proto index a89c007c..a0156e9e 100644 --- a/google/cloud/monitoring_v3/proto/service.proto +++ b/google/cloud/monitoring_v3/proto/service.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ syntax = "proto3"; package google.monitoring.v3; -import "google/api/monitored_resource.proto"; import "google/api/resource.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; @@ -67,10 +66,9 @@ message Service { } // Istio service scoped to a single Kubernetes cluster. Learn more at - // http://istio.io. + // https://istio.io. Clusters running OSS Istio will have their services + // ingested as this type. message ClusterIstio { - option deprecated = true; - // The location of the Kubernetes cluster in which this Istio service is // defined. Corresponds to the `location` resource label in `k8s_cluster` // resources. @@ -90,7 +88,8 @@ message Service { string service_name = 4; } - // Istio service scoped to an Istio mesh + // Istio service scoped to an Istio mesh. Anthos clusters running ASM < 1.6.8 + // will have their services ingested as this type. message MeshIstio { // Identifier for the mesh in which this Istio service is defined. // Corresponds to the `mesh_uid` metric label in Istio metrics. @@ -105,6 +104,27 @@ message Service { string service_name = 4; } + // Canonical service scoped to an Istio mesh. Anthos clusters running ASM >= + // 1.6.8 will have their services ingested as this type. + message IstioCanonicalService { + // Identifier for the Istio mesh in which this canonical service is defined. + // Corresponds to the `mesh_uid` metric label in + // [Istio metrics](https://cloud.google.com/monitoring/api/metrics_istio). + string mesh_uid = 1; + + // The namespace of the canonical service underlying this service. + // Corresponds to the `destination_canonical_service_namespace` metric + // label in [Istio + // metrics](https://cloud.google.com/monitoring/api/metrics_istio). + string canonical_service_namespace = 3; + + // The name of the canonical service underlying this service. + // Corresponds to the `destination_canonical_service_name` metric label in + // label in [Istio + // metrics](https://cloud.google.com/monitoring/api/metrics_istio). + string canonical_service = 4; + } + // Configuration for how to query telemetry on a Service. message Telemetry { // The full name of the resource that defines this service. Formatted as @@ -132,10 +152,15 @@ message Service { CloudEndpoints cloud_endpoints = 8; // Type used for Istio services that live in a Kubernetes cluster. - ClusterIstio cluster_istio = 9 [deprecated = true]; + ClusterIstio cluster_istio = 9; // Type used for Istio services scoped to an Istio mesh. MeshIstio mesh_istio = 10; + + // Type used for canonical services scoped to an Istio mesh. + // Metrics for Istio are + // [documented here](https://istio.io/latest/docs/reference/config/metrics/) + IstioCanonicalService istio_canonical_service = 11; } // Configuration for how to query telemetry on a Service. diff --git a/google/cloud/monitoring_v3/proto/service_service.proto b/google/cloud/monitoring_v3/proto/service_service.proto index cd5f7db6..07916e62 100644 --- a/google/cloud/monitoring_v3/proto/service_service.proto +++ b/google/cloud/monitoring_v3/proto/service_service.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -180,16 +180,20 @@ message ListServicesRequest { // // - `identifier_case` // - `app_engine.module_id` - // - `cloud_endpoints.service` - // - `cluster_istio.location` - // - `cluster_istio.cluster_name` - // - `cluster_istio.service_namespace` - // - `cluster_istio.service_name` + // - `cloud_endpoints.service` (reserved for future use) + // - `mesh_istio.mesh_uid` + // - `mesh_istio.service_namespace` + // - `mesh_istio.service_name` + // - `cluster_istio.location` (deprecated) + // - `cluster_istio.cluster_name` (deprecated) + // - `cluster_istio.service_namespace` (deprecated) + // - `cluster_istio.service_name` (deprecated) // // `identifier_case` refers to which option in the identifier oneof is // populated. For example, the filter `identifier_case = "CUSTOM"` would match // all services with a value for the `custom` field. Valid options are - // "CUSTOM", "APP_ENGINE", "CLOUD_ENDPOINTS", and "CLUSTER_ISTIO". + // "CUSTOM", "APP_ENGINE", "MESH_ISTIO", plus "CLUSTER_ISTIO" (deprecated) + // and "CLOUD_ENDPOINTS" (reserved for future use). string filter = 2; // A non-negative number that is the maximum number of results to return. diff --git a/google/cloud/monitoring_v3/proto/span_context.proto b/google/cloud/monitoring_v3/proto/span_context.proto index 72cce35f..cfb8f267 100644 --- a/google/cloud/monitoring_v3/proto/span_context.proto +++ b/google/cloud/monitoring_v3/proto/span_context.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/google/cloud/monitoring_v3/proto/uptime.proto b/google/cloud/monitoring_v3/proto/uptime.proto index 54a9b11e..1f66ffcc 100644 --- a/google/cloud/monitoring_v3/proto/uptime.proto +++ b/google/cloud/monitoring_v3/proto/uptime.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,6 +28,27 @@ option java_package = "com.google.monitoring.v3"; option php_namespace = "Google\\Cloud\\Monitoring\\V3"; option ruby_package = "Google::Cloud::Monitoring::V3"; +// The regions from which an Uptime check can be run. +enum UptimeCheckRegion { + // Default value if no region is specified. Will result in Uptime checks + // running from all regions. + REGION_UNSPECIFIED = 0; + + // Allows checks to run from locations within the United States of America. + USA = 1; + + // Allows checks to run from locations within the continent of Europe. + EUROPE = 2; + + // Allows checks to run from locations within the continent of South + // America. + SOUTH_AMERICA = 3; + + // Allows checks to run from locations within the Asia Pacific area (ex: + // Singapore). + ASIA_PACIFIC = 4; +} + // An internal checker allows Uptime checks to run on private/internal GCP // resources. message InternalChecker { @@ -84,27 +105,6 @@ message InternalChecker { State state = 7; } -// The regions from which an Uptime check can be run. -enum UptimeCheckRegion { - // Default value if no region is specified. Will result in Uptime checks - // running from all regions. - REGION_UNSPECIFIED = 0; - - // Allows checks to run from locations within the United States of America. - USA = 1; - - // Allows checks to run from locations within the continent of Europe. - EUROPE = 2; - - // Allows checks to run from locations within the continent of South - // America. - SOUTH_AMERICA = 3; - - // Allows checks to run from locations within the Asia Pacific area (ex: - // Singapore). - ASIA_PACIFIC = 4; -} - // This message configures which resources and services to monitor for // availability. message UptimeCheckConfig { @@ -154,12 +154,9 @@ message UptimeCheckConfig { POST = 2; } - // Header options corresponding to the Content-Type of the body in HTTP - // requests. Note that a `Content-Type` header cannot be present in the - // `headers` field if this field is specified. + // Header options corresponding to the content type of a HTTP request body. enum ContentType { - // No content type specified. If the request method is POST, an - // unspecified content type results in a check creation rejection. + // No content type specified. TYPE_UNSPECIFIED = 0; // `body` is in URL-encoded form. Equivalent to setting the `Content-Type` @@ -167,7 +164,8 @@ message UptimeCheckConfig { URL_ENCODED = 1; } - // The HTTP request method to use for the check. + // The HTTP request method to use for the check. If set to + // `METHOD_UNSPECIFIED` then `request_method` defaults to `GET`. RequestMethod request_method = 8; // If `true`, use HTTPS instead of HTTP to run the check. @@ -190,7 +188,7 @@ message UptimeCheckConfig { // defaults to empty. BasicAuthentication auth_info = 4; - // Boolean specifiying whether to encrypt the header information. + // Boolean specifying whether to encrypt the header information. // Encryption should be specified for any headers related to authentication // that you do not wish to be seen when retrieving the configuration. The // server will be responsible for encrypting the headers. @@ -208,7 +206,14 @@ message UptimeCheckConfig { // The maximum number of headers allowed is 100. map headers = 6; - // The content type to use for the check. + // The content type header to use for the check. The following + // configurations result in errors: + // 1. Content type is specified in both the `headers` field and the + // `content_type` field. + // 2. Request method is `GET` and `content_type` is not `TYPE_UNSPECIFIED` + // 3. Request method is `POST` and `content_type` is `TYPE_UNSPECIFIED`. + // 4. Request method is `POST` and a "Content-Type" header is provided via + // `headers` field. The `content_type` field should be used instead. ContentType content_type = 9; // Boolean specifying whether to include SSL certificate validation as a @@ -217,11 +222,14 @@ message UptimeCheckConfig { // setting `validate_ssl` to `true` has no effect. bool validate_ssl = 7; - // The request body associated with the HTTP request. If `content_type` is - // `URL_ENCODED`, the body passed in must be URL-encoded. Users can provide - // a `Content-Length` header via the `headers` field or the API will do - // so. The maximum byte size is 1 megabyte. Note: As with all `bytes` fields - // JSON representations are base64 encoded. + // The request body associated with the HTTP POST request. If `content_type` + // is `URL_ENCODED`, the body passed in must be URL-encoded. Users can + // provide a `Content-Length` header via the `headers` field or the API will + // do so. If the `request_method` is `GET` and `body` is not empty, the API + // will return an error. The maximum byte size is 1 megabyte. Note: As with + // all `bytes` fields, JSON representations are base64 encoded. e.g.: + // "foo=bar" in URL-encoded form is "foo%3Dbar" and in base64 encoding is + // "Zm9vJTI1M0RiYXI=". bytes body = 10; } @@ -279,6 +287,9 @@ message UptimeCheckConfig { // // projects/[PROJECT_ID_OR_NUMBER]/uptimeCheckConfigs/[UPTIME_CHECK_ID] // + // `[PROJECT_ID_OR_NUMBER]` is the Workspace host project associated with the + // Uptime check. + // // This field should be omitted when creating the Uptime check configuration; // on create, the resource name is assigned by the server and included in the // response. diff --git a/google/cloud/monitoring_v3/proto/uptime_service.proto b/google/cloud/monitoring_v3/proto/uptime_service.proto index 5e53934e..78ad6697 100644 --- a/google/cloud/monitoring_v3/proto/uptime_service.proto +++ b/google/cloud/monitoring_v3/proto/uptime_service.proto @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/google/cloud/monitoring_v3/services/alert_policy_service/async_client.py b/google/cloud/monitoring_v3/services/alert_policy_service/async_client.py index e853baab..841cedd0 100644 --- a/google/cloud/monitoring_v3/services/alert_policy_service/async_client.py +++ b/google/cloud/monitoring_v3/services/alert_policy_service/async_client.py @@ -98,7 +98,36 @@ class AlertPolicyServiceAsyncClient: AlertPolicyServiceClient.parse_common_location_path ) - from_service_account_file = AlertPolicyServiceClient.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: + AlertPolicyServiceAsyncClient: The constructed client. + """ + return AlertPolicyServiceClient.from_service_account_info.__func__(AlertPolicyServiceAsyncClient, 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: + AlertPolicyServiceAsyncClient: The constructed client. + """ + return AlertPolicyServiceClient.from_service_account_file.__func__(AlertPolicyServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -172,10 +201,11 @@ async def list_alert_policies( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListAlertPoliciesAsyncPager: - r"""Lists the existing alerting policies for the project. + r"""Lists the existing alerting policies for the + workspace. Args: - request (:class:`~.alert_service.ListAlertPoliciesRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListAlertPoliciesRequest`): The request object. The protocol for the `ListAlertPolicies` request. name (:class:`str`): @@ -191,6 +221,7 @@ async def list_alert_policies( retrieve a single alerting policy by name, use the [GetAlertPolicy][google.monitoring.v3.AlertPolicyService.GetAlertPolicy] operation, instead. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -202,8 +233,8 @@ async def list_alert_policies( sent along with the request as metadata. Returns: - ~.pagers.ListAlertPoliciesAsyncPager: - The protocol for the ``ListAlertPolicies`` response. + google.cloud.monitoring_v3.services.alert_policy_service.pagers.ListAlertPoliciesAsyncPager: + The protocol for the ListAlertPolicies response. Iterating over this object will yield results and resolve additional pages automatically. @@ -238,6 +269,7 @@ async def list_alert_policies( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -273,7 +305,7 @@ async def get_alert_policy( r"""Gets a single alerting policy. Args: - request (:class:`~.alert_service.GetAlertPolicyRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetAlertPolicyRequest`): The request object. The protocol for the `GetAlertPolicy` request. name (:class:`str`): @@ -283,6 +315,7 @@ async def get_alert_policy( :: projects/[PROJECT_ID_OR_NUMBER]/alertPolicies/[ALERT_POLICY_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -294,12 +327,12 @@ async def get_alert_policy( sent along with the request as metadata. Returns: - ~.alert.AlertPolicy: - A description of the conditions under which some aspect - of your system is considered to be "unhealthy" and the - ways to notify people or services about this state. For - an overview of alert policies, see `Introduction to - Alerting `__. + google.cloud.monitoring_v3.types.AlertPolicy: + A description of the conditions under which some aspect of your system is + considered to be "unhealthy" and the ways to notify + people or services about this state. For an overview + of alert policies, see [Introduction to + Alerting](\ https://cloud.google.com/monitoring/alerts/). """ # Create or coerce a protobuf request object. @@ -331,6 +364,7 @@ async def get_alert_policy( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -361,7 +395,7 @@ async def create_alert_policy( r"""Creates a new alerting policy. Args: - request (:class:`~.alert_service.CreateAlertPolicyRequest`): + request (:class:`google.cloud.monitoring_v3.types.CreateAlertPolicyRequest`): The request object. The protocol for the `CreateAlertPolicy` request. name (:class:`str`): @@ -374,19 +408,23 @@ async def create_alert_policy( Note that this field names the parent container in which the alerting policy will be written, not the name of the - created policy. The alerting policy that is returned - will have a name that contains a normalized - representation of this name as a prefix but adds a - suffix of the form ``/alertPolicies/[ALERT_POLICY_ID]``, - identifying the policy in the container. + created policy. \|name\| must be a host project of a + workspace, otherwise INVALID_ARGUMENT error will return. + The alerting policy that is returned will have a name + that contains a normalized representation of this name + as a prefix but adds a suffix of the form + ``/alertPolicies/[ALERT_POLICY_ID]``, identifying the + policy in the container. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - alert_policy (:class:`~.alert.AlertPolicy`): + alert_policy (:class:`google.cloud.monitoring_v3.types.AlertPolicy`): Required. The requested alerting policy. You should omit the ``name`` field in this policy. The name will be returned in the new policy, including a new ``[ALERT_POLICY_ID]`` value. + This corresponds to the ``alert_policy`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -398,12 +436,12 @@ async def create_alert_policy( sent along with the request as metadata. Returns: - ~.alert.AlertPolicy: - A description of the conditions under which some aspect - of your system is considered to be "unhealthy" and the - ways to notify people or services about this state. For - an overview of alert policies, see `Introduction to - Alerting `__. + google.cloud.monitoring_v3.types.AlertPolicy: + A description of the conditions under which some aspect of your system is + considered to be "unhealthy" and the ways to notify + people or services about this state. For an overview + of alert policies, see [Introduction to + Alerting](\ https://cloud.google.com/monitoring/alerts/). """ # Create or coerce a protobuf request object. @@ -458,7 +496,7 @@ async def delete_alert_policy( r"""Deletes an alerting policy. Args: - request (:class:`~.alert_service.DeleteAlertPolicyRequest`): + request (:class:`google.cloud.monitoring_v3.types.DeleteAlertPolicyRequest`): The request object. The protocol for the `DeleteAlertPolicy` request. name (:class:`str`): @@ -470,6 +508,7 @@ async def delete_alert_policy( For more information, see [AlertPolicy][google.monitoring.v3.AlertPolicy]. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -509,6 +548,7 @@ async def delete_alert_policy( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -541,10 +581,10 @@ async def update_alert_policy( via ``updateMask``. Returns the updated alerting policy. Args: - request (:class:`~.alert_service.UpdateAlertPolicyRequest`): + request (:class:`google.cloud.monitoring_v3.types.UpdateAlertPolicyRequest`): The request object. The protocol for the `UpdateAlertPolicy` request. - update_mask (:class:`~.field_mask.FieldMask`): + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): Optional. A list of alerting policy field names. If this field is not empty, each listed field in the existing alerting policy is set to the value of the corresponding @@ -573,14 +613,16 @@ async def update_alert_policy( the ``name`` field with that ``[CONDITION_ID]``. If the supplied condition omits the ``name`` field, then a new ``[CONDITION_ID]`` is created. + This corresponds to the ``update_mask`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - alert_policy (:class:`~.alert.AlertPolicy`): + alert_policy (:class:`google.cloud.monitoring_v3.types.AlertPolicy`): Required. The updated alerting policy or the updated values for the fields listed in ``update_mask``. If ``update_mask`` is not empty, any fields in this policy that are not in ``update_mask`` are ignored. + This corresponds to the ``alert_policy`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -592,12 +634,12 @@ async def update_alert_policy( sent along with the request as metadata. Returns: - ~.alert.AlertPolicy: - A description of the conditions under which some aspect - of your system is considered to be "unhealthy" and the - ways to notify people or services about this state. For - an overview of alert policies, see `Introduction to - Alerting `__. + google.cloud.monitoring_v3.types.AlertPolicy: + A description of the conditions under which some aspect of your system is + considered to be "unhealthy" and the ways to notify + people or services about this state. For an overview + of alert policies, see [Introduction to + Alerting](\ https://cloud.google.com/monitoring/alerts/). """ # Create or coerce a protobuf request object. diff --git a/google/cloud/monitoring_v3/services/alert_policy_service/client.py b/google/cloud/monitoring_v3/services/alert_policy_service/client.py index bea0a5fb..5f32a4a8 100644 --- a/google/cloud/monitoring_v3/services/alert_policy_service/client.py +++ b/google/cloud/monitoring_v3/services/alert_policy_service/client.py @@ -126,6 +126,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: + AlertPolicyServiceClient: 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 @@ -138,7 +154,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. + AlertPolicyServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -263,10 +279,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, ~.AlertPolicyServiceTransport]): The + transport (Union[str, AlertPolicyServiceTransport]): 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 @@ -302,21 +318,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: @@ -359,7 +371,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, ) @@ -373,13 +385,14 @@ def list_alert_policies( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> pagers.ListAlertPoliciesPager: - r"""Lists the existing alerting policies for the project. + r"""Lists the existing alerting policies for the + workspace. Args: - request (:class:`~.alert_service.ListAlertPoliciesRequest`): + request (google.cloud.monitoring_v3.types.ListAlertPoliciesRequest): The request object. The protocol for the `ListAlertPolicies` request. - name (:class:`str`): + name (str): Required. The project whose alert policies are to be listed. The format is: @@ -392,6 +405,7 @@ def list_alert_policies( retrieve a single alerting policy by name, use the [GetAlertPolicy][google.monitoring.v3.AlertPolicyService.GetAlertPolicy] operation, instead. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -403,8 +417,8 @@ def list_alert_policies( sent along with the request as metadata. Returns: - ~.pagers.ListAlertPoliciesPager: - The protocol for the ``ListAlertPolicies`` response. + google.cloud.monitoring_v3.services.alert_policy_service.pagers.ListAlertPoliciesPager: + The protocol for the ListAlertPolicies response. Iterating over this object will yield results and resolve additional pages automatically. @@ -467,16 +481,17 @@ def get_alert_policy( r"""Gets a single alerting policy. Args: - request (:class:`~.alert_service.GetAlertPolicyRequest`): + request (google.cloud.monitoring_v3.types.GetAlertPolicyRequest): The request object. The protocol for the `GetAlertPolicy` request. - name (:class:`str`): + name (str): Required. The alerting policy to retrieve. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/alertPolicies/[ALERT_POLICY_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -488,12 +503,12 @@ def get_alert_policy( sent along with the request as metadata. Returns: - ~.alert.AlertPolicy: - A description of the conditions under which some aspect - of your system is considered to be "unhealthy" and the - ways to notify people or services about this state. For - an overview of alert policies, see `Introduction to - Alerting `__. + google.cloud.monitoring_v3.types.AlertPolicy: + A description of the conditions under which some aspect of your system is + considered to be "unhealthy" and the ways to notify + people or services about this state. For an overview + of alert policies, see [Introduction to + Alerting](\ https://cloud.google.com/monitoring/alerts/). """ # Create or coerce a protobuf request object. @@ -548,10 +563,10 @@ def create_alert_policy( r"""Creates a new alerting policy. Args: - request (:class:`~.alert_service.CreateAlertPolicyRequest`): + request (google.cloud.monitoring_v3.types.CreateAlertPolicyRequest): The request object. The protocol for the `CreateAlertPolicy` request. - name (:class:`str`): + name (str): Required. The project in which to create the alerting policy. The format is: @@ -561,19 +576,23 @@ def create_alert_policy( Note that this field names the parent container in which the alerting policy will be written, not the name of the - created policy. The alerting policy that is returned - will have a name that contains a normalized - representation of this name as a prefix but adds a - suffix of the form ``/alertPolicies/[ALERT_POLICY_ID]``, - identifying the policy in the container. + created policy. \|name\| must be a host project of a + workspace, otherwise INVALID_ARGUMENT error will return. + The alerting policy that is returned will have a name + that contains a normalized representation of this name + as a prefix but adds a suffix of the form + ``/alertPolicies/[ALERT_POLICY_ID]``, identifying the + policy in the container. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - alert_policy (:class:`~.alert.AlertPolicy`): + alert_policy (google.cloud.monitoring_v3.types.AlertPolicy): Required. The requested alerting policy. You should omit the ``name`` field in this policy. The name will be returned in the new policy, including a new ``[ALERT_POLICY_ID]`` value. + This corresponds to the ``alert_policy`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -585,12 +604,12 @@ def create_alert_policy( sent along with the request as metadata. Returns: - ~.alert.AlertPolicy: - A description of the conditions under which some aspect - of your system is considered to be "unhealthy" and the - ways to notify people or services about this state. For - an overview of alert policies, see `Introduction to - Alerting `__. + google.cloud.monitoring_v3.types.AlertPolicy: + A description of the conditions under which some aspect of your system is + considered to be "unhealthy" and the ways to notify + people or services about this state. For an overview + of alert policies, see [Introduction to + Alerting](\ https://cloud.google.com/monitoring/alerts/). """ # Create or coerce a protobuf request object. @@ -646,10 +665,10 @@ def delete_alert_policy( r"""Deletes an alerting policy. Args: - request (:class:`~.alert_service.DeleteAlertPolicyRequest`): + request (google.cloud.monitoring_v3.types.DeleteAlertPolicyRequest): The request object. The protocol for the `DeleteAlertPolicy` request. - name (:class:`str`): + name (str): Required. The alerting policy to delete. The format is: :: @@ -658,6 +677,7 @@ def delete_alert_policy( For more information, see [AlertPolicy][google.monitoring.v3.AlertPolicy]. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -722,10 +742,10 @@ def update_alert_policy( via ``updateMask``. Returns the updated alerting policy. Args: - request (:class:`~.alert_service.UpdateAlertPolicyRequest`): + request (google.cloud.monitoring_v3.types.UpdateAlertPolicyRequest): The request object. The protocol for the `UpdateAlertPolicy` request. - update_mask (:class:`~.field_mask.FieldMask`): + update_mask (google.protobuf.field_mask_pb2.FieldMask): Optional. A list of alerting policy field names. If this field is not empty, each listed field in the existing alerting policy is set to the value of the corresponding @@ -754,14 +774,16 @@ def update_alert_policy( the ``name`` field with that ``[CONDITION_ID]``. If the supplied condition omits the ``name`` field, then a new ``[CONDITION_ID]`` is created. + This corresponds to the ``update_mask`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - alert_policy (:class:`~.alert.AlertPolicy`): + alert_policy (google.cloud.monitoring_v3.types.AlertPolicy): Required. The updated alerting policy or the updated values for the fields listed in ``update_mask``. If ``update_mask`` is not empty, any fields in this policy that are not in ``update_mask`` are ignored. + This corresponds to the ``alert_policy`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -773,12 +795,12 @@ def update_alert_policy( sent along with the request as metadata. Returns: - ~.alert.AlertPolicy: - A description of the conditions under which some aspect - of your system is considered to be "unhealthy" and the - ways to notify people or services about this state. For - an overview of alert policies, see `Introduction to - Alerting `__. + google.cloud.monitoring_v3.types.AlertPolicy: + A description of the conditions under which some aspect of your system is + considered to be "unhealthy" and the ways to notify + people or services about this state. For an overview + of alert policies, see [Introduction to + Alerting](\ https://cloud.google.com/monitoring/alerts/). """ # Create or coerce a protobuf request object. diff --git a/google/cloud/monitoring_v3/services/alert_policy_service/pagers.py b/google/cloud/monitoring_v3/services/alert_policy_service/pagers.py index 4c486cb7..4a5e61c2 100644 --- a/google/cloud/monitoring_v3/services/alert_policy_service/pagers.py +++ b/google/cloud/monitoring_v3/services/alert_policy_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.monitoring_v3.types import alert from google.cloud.monitoring_v3.types import alert_service @@ -25,7 +34,7 @@ class ListAlertPoliciesPager: """A pager for iterating through ``list_alert_policies`` requests. This class thinly wraps an initial - :class:`~.alert_service.ListAlertPoliciesResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListAlertPoliciesResponse` object, and provides an ``__iter__`` method to iterate through its ``alert_policies`` field. @@ -34,7 +43,7 @@ class ListAlertPoliciesPager: through the ``alert_policies`` field on the corresponding responses. - All the usual :class:`~.alert_service.ListAlertPoliciesResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListAlertPoliciesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -52,9 +61,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.alert_service.ListAlertPoliciesRequest`): + request (google.cloud.monitoring_v3.types.ListAlertPoliciesRequest): The initial request object. - response (:class:`~.alert_service.ListAlertPoliciesResponse`): + response (google.cloud.monitoring_v3.types.ListAlertPoliciesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -87,7 +96,7 @@ class ListAlertPoliciesAsyncPager: """A pager for iterating through ``list_alert_policies`` requests. This class thinly wraps an initial - :class:`~.alert_service.ListAlertPoliciesResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListAlertPoliciesResponse` object, and provides an ``__aiter__`` method to iterate through its ``alert_policies`` field. @@ -96,7 +105,7 @@ class ListAlertPoliciesAsyncPager: through the ``alert_policies`` field on the corresponding responses. - All the usual :class:`~.alert_service.ListAlertPoliciesResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListAlertPoliciesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -114,9 +123,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.alert_service.ListAlertPoliciesRequest`): + request (google.cloud.monitoring_v3.types.ListAlertPoliciesRequest): The initial request object. - response (:class:`~.alert_service.ListAlertPoliciesResponse`): + response (google.cloud.monitoring_v3.types.ListAlertPoliciesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/monitoring_v3/services/alert_policy_service/transports/base.py b/google/cloud/monitoring_v3/services/alert_policy_service/transports/base.py index d79536e7..4da7980d 100644 --- a/google/cloud/monitoring_v3/services/alert_policy_service/transports/base.py +++ b/google/cloud/monitoring_v3/services/alert_policy_service/transports/base.py @@ -75,10 +75,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -86,6 +86,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -95,20 +98,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -121,6 +121,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -134,6 +135,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -150,6 +152,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, diff --git a/google/cloud/monitoring_v3/services/alert_policy_service/transports/grpc.py b/google/cloud/monitoring_v3/services/alert_policy_service/transports/grpc.py index aa6fa157..2de02cda 100644 --- a/google/cloud/monitoring_v3/services/alert_policy_service/transports/grpc.py +++ b/google/cloud/monitoring_v3/services/alert_policy_service/transports/grpc.py @@ -67,6 +67,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: @@ -97,6 +98,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): @@ -111,72 +116,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -184,17 +177,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -208,7 +192,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -256,7 +240,8 @@ def list_alert_policies( ]: r"""Return a callable for the list alert policies method over gRPC. - Lists the existing alerting policies for the project. + Lists the existing alerting policies for the + workspace. Returns: Callable[[~.ListAlertPoliciesRequest], diff --git a/google/cloud/monitoring_v3/services/alert_policy_service/transports/grpc_asyncio.py b/google/cloud/monitoring_v3/services/alert_policy_service/transports/grpc_asyncio.py index e17d9242..11b5c4d7 100644 --- a/google/cloud/monitoring_v3/services/alert_policy_service/transports/grpc_asyncio.py +++ b/google/cloud/monitoring_v3/services/alert_policy_service/transports/grpc_asyncio.py @@ -71,7 +71,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -111,6 +111,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: @@ -142,12 +143,16 @@ 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): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -156,72 +161,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -229,17 +222,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: @@ -260,7 +244,8 @@ def list_alert_policies( ]: r"""Return a callable for the list alert policies method over gRPC. - Lists the existing alerting policies for the project. + Lists the existing alerting policies for the + workspace. Returns: Callable[[~.ListAlertPoliciesRequest], diff --git a/google/cloud/monitoring_v3/services/group_service/async_client.py b/google/cloud/monitoring_v3/services/group_service/async_client.py index 50e2f97f..433e9371 100644 --- a/google/cloud/monitoring_v3/services/group_service/async_client.py +++ b/google/cloud/monitoring_v3/services/group_service/async_client.py @@ -87,7 +87,36 @@ class GroupServiceAsyncClient: GroupServiceClient.parse_common_location_path ) - from_service_account_file = GroupServiceClient.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: + GroupServiceAsyncClient: The constructed client. + """ + return GroupServiceClient.from_service_account_info.__func__(GroupServiceAsyncClient, 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: + GroupServiceAsyncClient: The constructed client. + """ + return GroupServiceClient.from_service_account_file.__func__(GroupServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -163,7 +192,7 @@ async def list_groups( r"""Lists the existing groups. Args: - request (:class:`~.group_service.ListGroupsRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListGroupsRequest`): The request object. The `ListGroup` request. name (:class:`str`): Required. The project whose groups are to be listed. The @@ -172,6 +201,7 @@ async def list_groups( :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -183,8 +213,8 @@ async def list_groups( sent along with the request as metadata. Returns: - ~.pagers.ListGroupsAsyncPager: - The ``ListGroups`` response. + google.cloud.monitoring_v3.services.group_service.pagers.ListGroupsAsyncPager: + The ListGroups response. Iterating over this object will yield results and resolve additional pages automatically. @@ -219,6 +249,7 @@ async def list_groups( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -254,7 +285,7 @@ async def get_group( r"""Gets a single group. Args: - request (:class:`~.group_service.GetGroupRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetGroupRequest`): The request object. The `GetGroup` request. name (:class:`str`): Required. The group to retrieve. The format is: @@ -262,6 +293,7 @@ async def get_group( :: projects/[PROJECT_ID_OR_NUMBER]/groups/[GROUP_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -273,40 +305,40 @@ async def get_group( sent along with the request as metadata. Returns: - ~.group.Group: - The description of a dynamic collection of monitored - resources. Each group has a filter that is matched - against monitored resources and their associated - metadata. If a group's filter matches an available - monitored resource, then that resource is a member of - that group. Groups can contain any number of monitored - resources, and each monitored resource can be a member - of any number of groups. - - Groups can be nested in parent-child hierarchies. The - ``parentName`` field identifies an optional parent for - each group. If a group has a parent, then the only - monitored resources available to be matched by the - group's filter are the resources contained in the parent - group. In other words, a group contains the monitored - resources that match its filter and the filters of all - the group's ancestors. A group without a parent can - contain any monitored resource. - - For example, consider an infrastructure running a set of - instances with two user-defined tags: ``"environment"`` - and ``"role"``. A parent group has a filter, - ``environment="production"``. A child of that parent - group has a filter, ``role="transcoder"``. The parent - group contains all instances in the production - environment, regardless of their roles. The child group - contains instances that have the transcoder role *and* - are in the production environment. - - The monitored resources contained in a group can change - at any moment, depending on what resources exist and - what filters are associated with the group and its - ancestors. + google.cloud.monitoring_v3.types.Group: + The description of a dynamic collection of monitored resources. Each group + has a filter that is matched against monitored + resources and their associated metadata. If a group's + filter matches an available monitored resource, then + that resource is a member of that group. Groups can + contain any number of monitored resources, and each + monitored resource can be a member of any number of + groups. + + Groups can be nested in parent-child hierarchies. The + parentName field identifies an optional parent for + each group. If a group has a parent, then the only + monitored resources available to be matched by the + group's filter are the resources contained in the + parent group. In other words, a group contains the + monitored resources that match its filter and the + filters of all the group's ancestors. A group without + a parent can contain any monitored resource. + + For example, consider an infrastructure running a set + of instances with two user-defined tags: + "environment" and "role". A parent group has a + filter, environment="production". A child of that + parent group has a filter, role="transcoder". The + parent group contains all instances in the production + environment, regardless of their roles. The child + group contains instances that have the transcoder + role *and* are in the production environment. + + The monitored resources contained in a group can + change at any moment, depending on what resources + exist and what filters are associated with the group + and its ancestors. """ # Create or coerce a protobuf request object. @@ -338,6 +370,7 @@ async def get_group( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -368,7 +401,7 @@ async def create_group( r"""Creates a new group. Args: - request (:class:`~.group_service.CreateGroupRequest`): + request (:class:`google.cloud.monitoring_v3.types.CreateGroupRequest`): The request object. The `CreateGroup` request. name (:class:`str`): Required. The project in which to create the group. The @@ -377,12 +410,14 @@ async def create_group( :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - group (:class:`~.gm_group.Group`): + group (:class:`google.cloud.monitoring_v3.types.Group`): Required. A group definition. It is an error to define the ``name`` field because the system assigns the name. + This corresponds to the ``group`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -394,40 +429,40 @@ async def create_group( sent along with the request as metadata. Returns: - ~.gm_group.Group: - The description of a dynamic collection of monitored - resources. Each group has a filter that is matched - against monitored resources and their associated - metadata. If a group's filter matches an available - monitored resource, then that resource is a member of - that group. Groups can contain any number of monitored - resources, and each monitored resource can be a member - of any number of groups. - - Groups can be nested in parent-child hierarchies. The - ``parentName`` field identifies an optional parent for - each group. If a group has a parent, then the only - monitored resources available to be matched by the - group's filter are the resources contained in the parent - group. In other words, a group contains the monitored - resources that match its filter and the filters of all - the group's ancestors. A group without a parent can - contain any monitored resource. - - For example, consider an infrastructure running a set of - instances with two user-defined tags: ``"environment"`` - and ``"role"``. A parent group has a filter, - ``environment="production"``. A child of that parent - group has a filter, ``role="transcoder"``. The parent - group contains all instances in the production - environment, regardless of their roles. The child group - contains instances that have the transcoder role *and* - are in the production environment. - - The monitored resources contained in a group can change - at any moment, depending on what resources exist and - what filters are associated with the group and its - ancestors. + google.cloud.monitoring_v3.types.Group: + The description of a dynamic collection of monitored resources. Each group + has a filter that is matched against monitored + resources and their associated metadata. If a group's + filter matches an available monitored resource, then + that resource is a member of that group. Groups can + contain any number of monitored resources, and each + monitored resource can be a member of any number of + groups. + + Groups can be nested in parent-child hierarchies. The + parentName field identifies an optional parent for + each group. If a group has a parent, then the only + monitored resources available to be matched by the + group's filter are the resources contained in the + parent group. In other words, a group contains the + monitored resources that match its filter and the + filters of all the group's ancestors. A group without + a parent can contain any monitored resource. + + For example, consider an infrastructure running a set + of instances with two user-defined tags: + "environment" and "role". A parent group has a + filter, environment="production". A child of that + parent group has a filter, role="transcoder". The + parent group contains all instances in the production + environment, regardless of their roles. The child + group contains instances that have the transcoder + role *and* are in the production environment. + + The monitored resources contained in a group can + change at any moment, depending on what resources + exist and what filters are associated with the group + and its ancestors. """ # Create or coerce a protobuf request object. @@ -483,12 +518,13 @@ async def update_group( except ``name``. Args: - request (:class:`~.group_service.UpdateGroupRequest`): + request (:class:`google.cloud.monitoring_v3.types.UpdateGroupRequest`): The request object. The `UpdateGroup` request. - group (:class:`~.gm_group.Group`): + group (:class:`google.cloud.monitoring_v3.types.Group`): Required. The new definition of the group. All fields of the existing group, excepting ``name``, are replaced with the corresponding fields of this group. + This corresponds to the ``group`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -500,40 +536,40 @@ async def update_group( sent along with the request as metadata. Returns: - ~.gm_group.Group: - The description of a dynamic collection of monitored - resources. Each group has a filter that is matched - against monitored resources and their associated - metadata. If a group's filter matches an available - monitored resource, then that resource is a member of - that group. Groups can contain any number of monitored - resources, and each monitored resource can be a member - of any number of groups. - - Groups can be nested in parent-child hierarchies. The - ``parentName`` field identifies an optional parent for - each group. If a group has a parent, then the only - monitored resources available to be matched by the - group's filter are the resources contained in the parent - group. In other words, a group contains the monitored - resources that match its filter and the filters of all - the group's ancestors. A group without a parent can - contain any monitored resource. - - For example, consider an infrastructure running a set of - instances with two user-defined tags: ``"environment"`` - and ``"role"``. A parent group has a filter, - ``environment="production"``. A child of that parent - group has a filter, ``role="transcoder"``. The parent - group contains all instances in the production - environment, regardless of their roles. The child group - contains instances that have the transcoder role *and* - are in the production environment. - - The monitored resources contained in a group can change - at any moment, depending on what resources exist and - what filters are associated with the group and its - ancestors. + google.cloud.monitoring_v3.types.Group: + The description of a dynamic collection of monitored resources. Each group + has a filter that is matched against monitored + resources and their associated metadata. If a group's + filter matches an available monitored resource, then + that resource is a member of that group. Groups can + contain any number of monitored resources, and each + monitored resource can be a member of any number of + groups. + + Groups can be nested in parent-child hierarchies. The + parentName field identifies an optional parent for + each group. If a group has a parent, then the only + monitored resources available to be matched by the + group's filter are the resources contained in the + parent group. In other words, a group contains the + monitored resources that match its filter and the + filters of all the group's ancestors. A group without + a parent can contain any monitored resource. + + For example, consider an infrastructure running a set + of instances with two user-defined tags: + "environment" and "role". A parent group has a + filter, environment="production". A child of that + parent group has a filter, role="transcoder". The + parent group contains all instances in the production + environment, regardless of their roles. The child + group contains instances that have the transcoder + role *and* are in the production environment. + + The monitored resources contained in a group can + change at any moment, depending on what resources + exist and what filters are associated with the group + and its ancestors. """ # Create or coerce a protobuf request object. @@ -565,6 +601,7 @@ async def update_group( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -596,7 +633,7 @@ async def delete_group( r"""Deletes an existing group. Args: - request (:class:`~.group_service.DeleteGroupRequest`): + request (:class:`google.cloud.monitoring_v3.types.DeleteGroupRequest`): The request object. The `DeleteGroup` request. The default behavior is to be able to delete a single group without any descendants. @@ -606,6 +643,7 @@ async def delete_group( :: projects/[PROJECT_ID_OR_NUMBER]/groups/[GROUP_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -645,6 +683,7 @@ async def delete_group( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -674,7 +713,7 @@ async def list_group_members( group. Args: - request (:class:`~.group_service.ListGroupMembersRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListGroupMembersRequest`): The request object. The `ListGroupMembers` request. name (:class:`str`): Required. The group whose members are listed. The format @@ -683,6 +722,7 @@ async def list_group_members( :: projects/[PROJECT_ID_OR_NUMBER]/groups/[GROUP_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -694,8 +734,8 @@ async def list_group_members( sent along with the request as metadata. Returns: - ~.pagers.ListGroupMembersAsyncPager: - The ``ListGroupMembers`` response. + google.cloud.monitoring_v3.services.group_service.pagers.ListGroupMembersAsyncPager: + The ListGroupMembers response. Iterating over this object will yield results and resolve additional pages automatically. @@ -730,6 +770,7 @@ async def list_group_members( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/monitoring_v3/services/group_service/client.py b/google/cloud/monitoring_v3/services/group_service/client.py index 18017fee..813bc0a7 100644 --- a/google/cloud/monitoring_v3/services/group_service/client.py +++ b/google/cloud/monitoring_v3/services/group_service/client.py @@ -123,6 +123,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: + GroupServiceClient: 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 @@ -135,7 +151,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. + GroupServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -238,10 +254,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, ~.GroupServiceTransport]): The + transport (Union[str, GroupServiceTransport]): 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 @@ -277,21 +293,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: @@ -334,7 +346,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,15 +363,16 @@ def list_groups( r"""Lists the existing groups. Args: - request (:class:`~.group_service.ListGroupsRequest`): + request (google.cloud.monitoring_v3.types.ListGroupsRequest): The request object. The `ListGroup` request. - name (:class:`str`): + name (str): Required. The project whose groups are to be listed. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -371,8 +384,8 @@ def list_groups( sent along with the request as metadata. Returns: - ~.pagers.ListGroupsPager: - The ``ListGroups`` response. + google.cloud.monitoring_v3.services.group_service.pagers.ListGroupsPager: + The ListGroups response. Iterating over this object will yield results and resolve additional pages automatically. @@ -435,14 +448,15 @@ def get_group( r"""Gets a single group. Args: - request (:class:`~.group_service.GetGroupRequest`): + request (google.cloud.monitoring_v3.types.GetGroupRequest): The request object. The `GetGroup` request. - name (:class:`str`): + name (str): Required. The group to retrieve. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/groups/[GROUP_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -454,40 +468,40 @@ def get_group( sent along with the request as metadata. Returns: - ~.group.Group: - The description of a dynamic collection of monitored - resources. Each group has a filter that is matched - against monitored resources and their associated - metadata. If a group's filter matches an available - monitored resource, then that resource is a member of - that group. Groups can contain any number of monitored - resources, and each monitored resource can be a member - of any number of groups. - - Groups can be nested in parent-child hierarchies. The - ``parentName`` field identifies an optional parent for - each group. If a group has a parent, then the only - monitored resources available to be matched by the - group's filter are the resources contained in the parent - group. In other words, a group contains the monitored - resources that match its filter and the filters of all - the group's ancestors. A group without a parent can - contain any monitored resource. - - For example, consider an infrastructure running a set of - instances with two user-defined tags: ``"environment"`` - and ``"role"``. A parent group has a filter, - ``environment="production"``. A child of that parent - group has a filter, ``role="transcoder"``. The parent - group contains all instances in the production - environment, regardless of their roles. The child group - contains instances that have the transcoder role *and* - are in the production environment. - - The monitored resources contained in a group can change - at any moment, depending on what resources exist and - what filters are associated with the group and its - ancestors. + google.cloud.monitoring_v3.types.Group: + The description of a dynamic collection of monitored resources. Each group + has a filter that is matched against monitored + resources and their associated metadata. If a group's + filter matches an available monitored resource, then + that resource is a member of that group. Groups can + contain any number of monitored resources, and each + monitored resource can be a member of any number of + groups. + + Groups can be nested in parent-child hierarchies. The + parentName field identifies an optional parent for + each group. If a group has a parent, then the only + monitored resources available to be matched by the + group's filter are the resources contained in the + parent group. In other words, a group contains the + monitored resources that match its filter and the + filters of all the group's ancestors. A group without + a parent can contain any monitored resource. + + For example, consider an infrastructure running a set + of instances with two user-defined tags: + "environment" and "role". A parent group has a + filter, environment="production". A child of that + parent group has a filter, role="transcoder". The + parent group contains all instances in the production + environment, regardless of their roles. The child + group contains instances that have the transcoder + role *and* are in the production environment. + + The monitored resources contained in a group can + change at any moment, depending on what resources + exist and what filters are associated with the group + and its ancestors. """ # Create or coerce a protobuf request object. @@ -542,21 +556,23 @@ def create_group( r"""Creates a new group. Args: - request (:class:`~.group_service.CreateGroupRequest`): + request (google.cloud.monitoring_v3.types.CreateGroupRequest): The request object. The `CreateGroup` request. - name (:class:`str`): + name (str): Required. The project in which to create the group. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - group (:class:`~.gm_group.Group`): + group (google.cloud.monitoring_v3.types.Group): Required. A group definition. It is an error to define the ``name`` field because the system assigns the name. + This corresponds to the ``group`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -568,40 +584,40 @@ def create_group( sent along with the request as metadata. Returns: - ~.gm_group.Group: - The description of a dynamic collection of monitored - resources. Each group has a filter that is matched - against monitored resources and their associated - metadata. If a group's filter matches an available - monitored resource, then that resource is a member of - that group. Groups can contain any number of monitored - resources, and each monitored resource can be a member - of any number of groups. - - Groups can be nested in parent-child hierarchies. The - ``parentName`` field identifies an optional parent for - each group. If a group has a parent, then the only - monitored resources available to be matched by the - group's filter are the resources contained in the parent - group. In other words, a group contains the monitored - resources that match its filter and the filters of all - the group's ancestors. A group without a parent can - contain any monitored resource. - - For example, consider an infrastructure running a set of - instances with two user-defined tags: ``"environment"`` - and ``"role"``. A parent group has a filter, - ``environment="production"``. A child of that parent - group has a filter, ``role="transcoder"``. The parent - group contains all instances in the production - environment, regardless of their roles. The child group - contains instances that have the transcoder role *and* - are in the production environment. - - The monitored resources contained in a group can change - at any moment, depending on what resources exist and - what filters are associated with the group and its - ancestors. + google.cloud.monitoring_v3.types.Group: + The description of a dynamic collection of monitored resources. Each group + has a filter that is matched against monitored + resources and their associated metadata. If a group's + filter matches an available monitored resource, then + that resource is a member of that group. Groups can + contain any number of monitored resources, and each + monitored resource can be a member of any number of + groups. + + Groups can be nested in parent-child hierarchies. The + parentName field identifies an optional parent for + each group. If a group has a parent, then the only + monitored resources available to be matched by the + group's filter are the resources contained in the + parent group. In other words, a group contains the + monitored resources that match its filter and the + filters of all the group's ancestors. A group without + a parent can contain any monitored resource. + + For example, consider an infrastructure running a set + of instances with two user-defined tags: + "environment" and "role". A parent group has a + filter, environment="production". A child of that + parent group has a filter, role="transcoder". The + parent group contains all instances in the production + environment, regardless of their roles. The child + group contains instances that have the transcoder + role *and* are in the production environment. + + The monitored resources contained in a group can + change at any moment, depending on what resources + exist and what filters are associated with the group + and its ancestors. """ # Create or coerce a protobuf request object. @@ -658,12 +674,13 @@ def update_group( except ``name``. Args: - request (:class:`~.group_service.UpdateGroupRequest`): + request (google.cloud.monitoring_v3.types.UpdateGroupRequest): The request object. The `UpdateGroup` request. - group (:class:`~.gm_group.Group`): + group (google.cloud.monitoring_v3.types.Group): Required. The new definition of the group. All fields of the existing group, excepting ``name``, are replaced with the corresponding fields of this group. + This corresponds to the ``group`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -675,40 +692,40 @@ def update_group( sent along with the request as metadata. Returns: - ~.gm_group.Group: - The description of a dynamic collection of monitored - resources. Each group has a filter that is matched - against monitored resources and their associated - metadata. If a group's filter matches an available - monitored resource, then that resource is a member of - that group. Groups can contain any number of monitored - resources, and each monitored resource can be a member - of any number of groups. - - Groups can be nested in parent-child hierarchies. The - ``parentName`` field identifies an optional parent for - each group. If a group has a parent, then the only - monitored resources available to be matched by the - group's filter are the resources contained in the parent - group. In other words, a group contains the monitored - resources that match its filter and the filters of all - the group's ancestors. A group without a parent can - contain any monitored resource. - - For example, consider an infrastructure running a set of - instances with two user-defined tags: ``"environment"`` - and ``"role"``. A parent group has a filter, - ``environment="production"``. A child of that parent - group has a filter, ``role="transcoder"``. The parent - group contains all instances in the production - environment, regardless of their roles. The child group - contains instances that have the transcoder role *and* - are in the production environment. - - The monitored resources contained in a group can change - at any moment, depending on what resources exist and - what filters are associated with the group and its - ancestors. + google.cloud.monitoring_v3.types.Group: + The description of a dynamic collection of monitored resources. Each group + has a filter that is matched against monitored + resources and their associated metadata. If a group's + filter matches an available monitored resource, then + that resource is a member of that group. Groups can + contain any number of monitored resources, and each + monitored resource can be a member of any number of + groups. + + Groups can be nested in parent-child hierarchies. The + parentName field identifies an optional parent for + each group. If a group has a parent, then the only + monitored resources available to be matched by the + group's filter are the resources contained in the + parent group. In other words, a group contains the + monitored resources that match its filter and the + filters of all the group's ancestors. A group without + a parent can contain any monitored resource. + + For example, consider an infrastructure running a set + of instances with two user-defined tags: + "environment" and "role". A parent group has a + filter, environment="production". A child of that + parent group has a filter, role="transcoder". The + parent group contains all instances in the production + environment, regardless of their roles. The child + group contains instances that have the transcoder + role *and* are in the production environment. + + The monitored resources contained in a group can + change at any moment, depending on what resources + exist and what filters are associated with the group + and its ancestors. """ # Create or coerce a protobuf request object. @@ -764,16 +781,17 @@ def delete_group( r"""Deletes an existing group. Args: - request (:class:`~.group_service.DeleteGroupRequest`): + request (google.cloud.monitoring_v3.types.DeleteGroupRequest): The request object. The `DeleteGroup` request. The default behavior is to be able to delete a single group without any descendants. - name (:class:`str`): + name (str): Required. The group to delete. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/groups/[GROUP_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -835,15 +853,16 @@ def list_group_members( group. Args: - request (:class:`~.group_service.ListGroupMembersRequest`): + request (google.cloud.monitoring_v3.types.ListGroupMembersRequest): The request object. The `ListGroupMembers` request. - name (:class:`str`): + name (str): Required. The group whose members are listed. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/groups/[GROUP_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -855,8 +874,8 @@ def list_group_members( sent along with the request as metadata. Returns: - ~.pagers.ListGroupMembersPager: - The ``ListGroupMembers`` response. + google.cloud.monitoring_v3.services.group_service.pagers.ListGroupMembersPager: + The ListGroupMembers response. Iterating over this object will yield results and resolve additional pages automatically. diff --git a/google/cloud/monitoring_v3/services/group_service/pagers.py b/google/cloud/monitoring_v3/services/group_service/pagers.py index 712775f0..c2ff3904 100644 --- a/google/cloud/monitoring_v3/services/group_service/pagers.py +++ b/google/cloud/monitoring_v3/services/group_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.api import monitored_resource_pb2 as monitored_resource # type: ignore from google.cloud.monitoring_v3.types import group @@ -26,7 +35,7 @@ class ListGroupsPager: """A pager for iterating through ``list_groups`` requests. This class thinly wraps an initial - :class:`~.group_service.ListGroupsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListGroupsResponse` object, and provides an ``__iter__`` method to iterate through its ``group`` field. @@ -35,7 +44,7 @@ class ListGroupsPager: through the ``group`` field on the corresponding responses. - All the usual :class:`~.group_service.ListGroupsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListGroupsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -53,9 +62,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.group_service.ListGroupsRequest`): + request (google.cloud.monitoring_v3.types.ListGroupsRequest): The initial request object. - response (:class:`~.group_service.ListGroupsResponse`): + response (google.cloud.monitoring_v3.types.ListGroupsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -88,7 +97,7 @@ class ListGroupsAsyncPager: """A pager for iterating through ``list_groups`` requests. This class thinly wraps an initial - :class:`~.group_service.ListGroupsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListGroupsResponse` object, and provides an ``__aiter__`` method to iterate through its ``group`` field. @@ -97,7 +106,7 @@ class ListGroupsAsyncPager: through the ``group`` field on the corresponding responses. - All the usual :class:`~.group_service.ListGroupsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListGroupsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -115,9 +124,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.group_service.ListGroupsRequest`): + request (google.cloud.monitoring_v3.types.ListGroupsRequest): The initial request object. - response (:class:`~.group_service.ListGroupsResponse`): + response (google.cloud.monitoring_v3.types.ListGroupsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -154,7 +163,7 @@ class ListGroupMembersPager: """A pager for iterating through ``list_group_members`` requests. This class thinly wraps an initial - :class:`~.group_service.ListGroupMembersResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListGroupMembersResponse` object, and provides an ``__iter__`` method to iterate through its ``members`` field. @@ -163,7 +172,7 @@ class ListGroupMembersPager: through the ``members`` field on the corresponding responses. - All the usual :class:`~.group_service.ListGroupMembersResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListGroupMembersResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -181,9 +190,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.group_service.ListGroupMembersRequest`): + request (google.cloud.monitoring_v3.types.ListGroupMembersRequest): The initial request object. - response (:class:`~.group_service.ListGroupMembersResponse`): + response (google.cloud.monitoring_v3.types.ListGroupMembersResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -216,7 +225,7 @@ class ListGroupMembersAsyncPager: """A pager for iterating through ``list_group_members`` requests. This class thinly wraps an initial - :class:`~.group_service.ListGroupMembersResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListGroupMembersResponse` object, and provides an ``__aiter__`` method to iterate through its ``members`` field. @@ -225,7 +234,7 @@ class ListGroupMembersAsyncPager: through the ``members`` field on the corresponding responses. - All the usual :class:`~.group_service.ListGroupMembersResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListGroupMembersResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -243,9 +252,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.group_service.ListGroupMembersRequest`): + request (google.cloud.monitoring_v3.types.ListGroupMembersRequest): The initial request object. - response (:class:`~.group_service.ListGroupMembersResponse`): + response (google.cloud.monitoring_v3.types.ListGroupMembersResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/monitoring_v3/services/group_service/transports/base.py b/google/cloud/monitoring_v3/services/group_service/transports/base.py index 1b2d543b..905f2150 100644 --- a/google/cloud/monitoring_v3/services/group_service/transports/base.py +++ b/google/cloud/monitoring_v3/services/group_service/transports/base.py @@ -76,10 +76,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -87,6 +87,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -96,20 +99,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -122,6 +122,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -135,6 +136,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -151,6 +153,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -164,6 +167,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -177,6 +181,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, diff --git a/google/cloud/monitoring_v3/services/group_service/transports/grpc.py b/google/cloud/monitoring_v3/services/group_service/transports/grpc.py index a61c89e5..4e360876 100644 --- a/google/cloud/monitoring_v3/services/group_service/transports/grpc.py +++ b/google/cloud/monitoring_v3/services/group_service/transports/grpc.py @@ -71,6 +71,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: @@ -101,6 +102,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): @@ -115,72 +120,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -188,17 +181,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -212,7 +196,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If diff --git a/google/cloud/monitoring_v3/services/group_service/transports/grpc_asyncio.py b/google/cloud/monitoring_v3/services/group_service/transports/grpc_asyncio.py index ffda52bb..f4bd5a30 100644 --- a/google/cloud/monitoring_v3/services/group_service/transports/grpc_asyncio.py +++ b/google/cloud/monitoring_v3/services/group_service/transports/grpc_asyncio.py @@ -75,7 +75,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -115,6 +115,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: @@ -146,12 +147,16 @@ 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): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -160,72 +165,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -233,17 +226,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/monitoring_v3/services/metric_service/async_client.py b/google/cloud/monitoring_v3/services/metric_service/async_client.py index bb8c9da4..495cb02c 100644 --- a/google/cloud/monitoring_v3/services/metric_service/async_client.py +++ b/google/cloud/monitoring_v3/services/metric_service/async_client.py @@ -60,6 +60,8 @@ class MetricServiceAsyncClient: parse_monitored_resource_descriptor_path = staticmethod( MetricServiceClient.parse_monitored_resource_descriptor_path ) + time_series_path = staticmethod(MetricServiceClient.time_series_path) + parse_time_series_path = staticmethod(MetricServiceClient.parse_time_series_path) common_billing_account_path = staticmethod( MetricServiceClient.common_billing_account_path @@ -90,7 +92,36 @@ class MetricServiceAsyncClient: MetricServiceClient.parse_common_location_path ) - from_service_account_file = MetricServiceClient.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: + MetricServiceAsyncClient: The constructed client. + """ + return MetricServiceClient.from_service_account_info.__func__(MetricServiceAsyncClient, 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: + MetricServiceAsyncClient: The constructed client. + """ + return MetricServiceClient.from_service_account_file.__func__(MetricServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -167,7 +198,7 @@ async def list_monitored_resource_descriptors( filter. This method does not require a Workspace. Args: - request (:class:`~.metric_service.ListMonitoredResourceDescriptorsRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsRequest`): The request object. The `ListMonitoredResourceDescriptors` request. name (:class:`str`): @@ -177,6 +208,7 @@ async def list_monitored_resource_descriptors( :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -188,8 +220,8 @@ async def list_monitored_resource_descriptors( sent along with the request as metadata. Returns: - ~.pagers.ListMonitoredResourceDescriptorsAsyncPager: - The ``ListMonitoredResourceDescriptors`` response. + google.cloud.monitoring_v3.services.metric_service.pagers.ListMonitoredResourceDescriptorsAsyncPager: + The ListMonitoredResourceDescriptors response. Iterating over this object will yield results and resolve additional pages automatically. @@ -224,6 +256,7 @@ async def list_monitored_resource_descriptors( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -260,7 +293,7 @@ async def get_monitored_resource_descriptor( method does not require a Workspace. Args: - request (:class:`~.metric_service.GetMonitoredResourceDescriptorRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetMonitoredResourceDescriptorRequest`): The request object. The `GetMonitoredResourceDescriptor` request. name (:class:`str`): @@ -273,6 +306,7 @@ async def get_monitored_resource_descriptor( The ``[RESOURCE_TYPE]`` is a predefined type, such as ``cloudsql_database``. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -284,19 +318,18 @@ async def get_monitored_resource_descriptor( sent along with the request as metadata. Returns: - ~.monitored_resource.MonitoredResourceDescriptor: - An object that describes the schema of a - [MonitoredResource][google.api.MonitoredResource] object - using a type name and a set of labels. For example, the - monitored resource descriptor for Google Compute Engine - VM instances has a type of ``"gce_instance"`` and - specifies the use of the labels ``"instance_id"`` and - ``"zone"`` to identify particular VM instances. - - Different APIs can support different monitored resource - types. APIs generally provide a ``list`` method that - returns the monitored resource descriptors used by the - API. + google.api.monitored_resource_pb2.MonitoredResourceDescriptor: + An object that describes the schema of a [MonitoredResource][google.api.MonitoredResource] object using a + type name and a set of labels. For example, the + monitored resource descriptor for Google Compute + Engine VM instances has a type of "gce_instance" and + specifies the use of the labels "instance_id" and + "zone" to identify particular VM instances. + + Different APIs can support different monitored + resource types. APIs generally provide a list method + that returns the monitored resource descriptors used + by the API. """ # Create or coerce a protobuf request object. @@ -328,6 +361,7 @@ async def get_monitored_resource_descriptor( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -358,7 +392,7 @@ async def list_metric_descriptors( method does not require a Workspace. Args: - request (:class:`~.metric_service.ListMetricDescriptorsRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListMetricDescriptorsRequest`): The request object. The `ListMetricDescriptors` request. name (:class:`str`): Required. The project on which to execute the request. @@ -367,6 +401,7 @@ async def list_metric_descriptors( :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -378,8 +413,8 @@ async def list_metric_descriptors( sent along with the request as metadata. Returns: - ~.pagers.ListMetricDescriptorsAsyncPager: - The ``ListMetricDescriptors`` response. + google.cloud.monitoring_v3.services.metric_service.pagers.ListMetricDescriptorsAsyncPager: + The ListMetricDescriptors response. Iterating over this object will yield results and resolve additional pages automatically. @@ -414,6 +449,7 @@ async def list_metric_descriptors( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -450,7 +486,7 @@ async def get_metric_descriptor( require a Workspace. Args: - request (:class:`~.metric_service.GetMetricDescriptorRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetMetricDescriptorRequest`): The request object. The `GetMetricDescriptor` request. name (:class:`str`): Required. The metric descriptor on which to execute the @@ -462,6 +498,7 @@ async def get_metric_descriptor( An example value of ``[METRIC_ID]`` is ``"compute.googleapis.com/instance/disk/read_bytes_count"``. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -473,7 +510,7 @@ async def get_metric_descriptor( sent along with the request as metadata. Returns: - ~.ga_metric.MetricDescriptor: + google.api.metric_pb2.MetricDescriptor: Defines a metric type and its schema. Once a metric descriptor is created, deleting or altering it stops data @@ -510,6 +547,7 @@ async def get_metric_descriptor( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -542,7 +580,7 @@ async def create_metric_descriptor( metrics `__. Args: - request (:class:`~.metric_service.CreateMetricDescriptorRequest`): + request (:class:`google.cloud.monitoring_v3.types.CreateMetricDescriptorRequest`): The request object. The `CreateMetricDescriptor` request. name (:class:`str`): @@ -552,13 +590,15 @@ async def create_metric_descriptor( :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - metric_descriptor (:class:`~.ga_metric.MetricDescriptor`): + metric_descriptor (:class:`google.api.metric_pb2.MetricDescriptor`): Required. The new `custom metric `__ descriptor. + This corresponds to the ``metric_descriptor`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -570,7 +610,7 @@ async def create_metric_descriptor( sent along with the request as metadata. Returns: - ~.ga_metric.MetricDescriptor: + google.api.metric_pb2.MetricDescriptor: Defines a metric type and its schema. Once a metric descriptor is created, deleting or altering it stops data @@ -632,7 +672,7 @@ async def delete_metric_descriptor( can be deleted. Args: - request (:class:`~.metric_service.DeleteMetricDescriptorRequest`): + request (:class:`google.cloud.monitoring_v3.types.DeleteMetricDescriptorRequest`): The request object. The `DeleteMetricDescriptor` request. name (:class:`str`): @@ -645,6 +685,7 @@ async def delete_metric_descriptor( An example of ``[METRIC_ID]`` is: ``"custom.googleapis.com/my_test_metric"``. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -684,6 +725,7 @@ async def delete_metric_descriptor( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -716,15 +758,18 @@ async def list_time_series( does not require a Workspace. Args: - request (:class:`~.metric_service.ListTimeSeriesRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListTimeSeriesRequest`): The request object. The `ListTimeSeries` request. name (:class:`str`): - Required. The project on which to execute the request. - The format is: + Required. The project, organization or folder on which + to execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + organizations/[ORGANIZATION_ID] + folders/[FOLDER_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -739,22 +784,25 @@ async def list_time_series( :: metric.type = "compute.googleapis.com/instance/cpu/usage_time" AND - metric.labels.instance_name = "my-instance-name". + metric.labels.instance_name = "my-instance-name" + This corresponds to the ``filter`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - interval (:class:`~.common.TimeInterval`): + interval (:class:`google.cloud.monitoring_v3.types.TimeInterval`): Required. The time interval for which results should be returned. Only time series that contain data points in the specified interval are included in the response. + This corresponds to the ``interval`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - view (:class:`~.metric_service.ListTimeSeriesRequest.TimeSeriesView`): + view (:class:`google.cloud.monitoring_v3.types.ListTimeSeriesRequest.TimeSeriesView`): Required. Specifies which information is returned about the time series. + This corresponds to the ``view`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -766,8 +814,8 @@ async def list_time_series( sent along with the request as metadata. Returns: - ~.pagers.ListTimeSeriesAsyncPager: - The ``ListTimeSeries`` response. + google.cloud.monitoring_v3.services.metric_service.pagers.ListTimeSeriesAsyncPager: + The ListTimeSeries response. Iterating over this object will yield results and resolve additional pages automatically. @@ -808,6 +856,7 @@ async def list_time_series( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -848,7 +897,7 @@ async def create_time_series( response. Args: - request (:class:`~.metric_service.CreateTimeSeriesRequest`): + request (:class:`google.cloud.monitoring_v3.types.CreateTimeSeriesRequest`): The request object. The `CreateTimeSeries` request. name (:class:`str`): Required. The project on which to execute the request. @@ -857,10 +906,11 @@ async def create_time_series( :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - time_series (:class:`Sequence[~.gm_metric.TimeSeries]`): + time_series (:class:`Sequence[google.cloud.monitoring_v3.types.TimeSeries]`): Required. The new data to be added to a list of time series. Adds at most one data point to each of several time series. The new data point must be more recent than @@ -871,6 +921,7 @@ async def create_time_series( The maximum number of ``TimeSeries`` objects per ``Create`` request is 200. + This corresponds to the ``time_series`` field on the ``request`` instance; if ``request`` is provided, this should not be set. diff --git a/google/cloud/monitoring_v3/services/metric_service/client.py b/google/cloud/monitoring_v3/services/metric_service/client.py index 3cdacc94..ec267304 100644 --- a/google/cloud/monitoring_v3/services/metric_service/client.py +++ b/google/cloud/monitoring_v3/services/metric_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: + MetricServiceClient: 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. + MetricServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -175,6 +191,21 @@ def parse_monitored_resource_descriptor_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def time_series_path(project: str, time_series: str,) -> str: + """Return a fully-qualified time_series string.""" + return "projects/{project}/timeSeries/{time_series}".format( + project=project, time_series=time_series, + ) + + @staticmethod + def parse_time_series_path(path: str) -> Dict[str, str]: + """Parse a time_series path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/timeSeries/(?P.+?)$", path + ) + return m.groupdict() if m else {} + @staticmethod def common_billing_account_path(billing_account: str,) -> str: """Return a fully-qualified billing_account string.""" @@ -250,10 +281,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, ~.MetricServiceTransport]): The + transport (Union[str, MetricServiceTransport]): 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 @@ -289,21 +320,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: @@ -346,7 +373,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, ) @@ -364,16 +391,17 @@ def list_monitored_resource_descriptors( filter. This method does not require a Workspace. Args: - request (:class:`~.metric_service.ListMonitoredResourceDescriptorsRequest`): + request (google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsRequest): The request object. The `ListMonitoredResourceDescriptors` request. - name (:class:`str`): + name (str): Required. The project on which to execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -385,8 +413,8 @@ def list_monitored_resource_descriptors( sent along with the request as metadata. Returns: - ~.pagers.ListMonitoredResourceDescriptorsPager: - The ``ListMonitoredResourceDescriptors`` response. + google.cloud.monitoring_v3.services.metric_service.pagers.ListMonitoredResourceDescriptorsPager: + The ListMonitoredResourceDescriptors response. Iterating over this object will yield results and resolve additional pages automatically. @@ -454,10 +482,10 @@ def get_monitored_resource_descriptor( method does not require a Workspace. Args: - request (:class:`~.metric_service.GetMonitoredResourceDescriptorRequest`): + request (google.cloud.monitoring_v3.types.GetMonitoredResourceDescriptorRequest): The request object. The `GetMonitoredResourceDescriptor` request. - name (:class:`str`): + name (str): Required. The monitored resource descriptor to get. The format is: @@ -467,6 +495,7 @@ def get_monitored_resource_descriptor( The ``[RESOURCE_TYPE]`` is a predefined type, such as ``cloudsql_database``. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -478,19 +507,18 @@ def get_monitored_resource_descriptor( sent along with the request as metadata. Returns: - ~.monitored_resource.MonitoredResourceDescriptor: - An object that describes the schema of a - [MonitoredResource][google.api.MonitoredResource] object - using a type name and a set of labels. For example, the - monitored resource descriptor for Google Compute Engine - VM instances has a type of ``"gce_instance"`` and - specifies the use of the labels ``"instance_id"`` and - ``"zone"`` to identify particular VM instances. - - Different APIs can support different monitored resource - types. APIs generally provide a ``list`` method that - returns the monitored resource descriptors used by the - API. + google.api.monitored_resource_pb2.MonitoredResourceDescriptor: + An object that describes the schema of a [MonitoredResource][google.api.MonitoredResource] object using a + type name and a set of labels. For example, the + monitored resource descriptor for Google Compute + Engine VM instances has a type of "gce_instance" and + specifies the use of the labels "instance_id" and + "zone" to identify particular VM instances. + + Different APIs can support different monitored + resource types. APIs generally provide a list method + that returns the monitored resource descriptors used + by the API. """ # Create or coerce a protobuf request object. @@ -549,15 +577,16 @@ def list_metric_descriptors( method does not require a Workspace. Args: - request (:class:`~.metric_service.ListMetricDescriptorsRequest`): + request (google.cloud.monitoring_v3.types.ListMetricDescriptorsRequest): The request object. The `ListMetricDescriptors` request. - name (:class:`str`): + name (str): Required. The project on which to execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -569,8 +598,8 @@ def list_metric_descriptors( sent along with the request as metadata. Returns: - ~.pagers.ListMetricDescriptorsPager: - The ``ListMetricDescriptors`` response. + google.cloud.monitoring_v3.services.metric_service.pagers.ListMetricDescriptorsPager: + The ListMetricDescriptors response. Iterating over this object will yield results and resolve additional pages automatically. @@ -634,9 +663,9 @@ def get_metric_descriptor( require a Workspace. Args: - request (:class:`~.metric_service.GetMetricDescriptorRequest`): + request (google.cloud.monitoring_v3.types.GetMetricDescriptorRequest): The request object. The `GetMetricDescriptor` request. - name (:class:`str`): + name (str): Required. The metric descriptor on which to execute the request. The format is: @@ -646,6 +675,7 @@ def get_metric_descriptor( An example value of ``[METRIC_ID]`` is ``"compute.googleapis.com/instance/disk/read_bytes_count"``. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -657,7 +687,7 @@ def get_metric_descriptor( sent along with the request as metadata. Returns: - ~.ga_metric.MetricDescriptor: + google.api.metric_pb2.MetricDescriptor: Defines a metric type and its schema. Once a metric descriptor is created, deleting or altering it stops data @@ -719,23 +749,25 @@ def create_metric_descriptor( metrics `__. Args: - request (:class:`~.metric_service.CreateMetricDescriptorRequest`): + request (google.cloud.monitoring_v3.types.CreateMetricDescriptorRequest): The request object. The `CreateMetricDescriptor` request. - name (:class:`str`): + name (str): Required. The project on which to execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - metric_descriptor (:class:`~.ga_metric.MetricDescriptor`): + metric_descriptor (google.api.metric_pb2.MetricDescriptor): Required. The new `custom metric `__ descriptor. + This corresponds to the ``metric_descriptor`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -747,7 +779,7 @@ def create_metric_descriptor( sent along with the request as metadata. Returns: - ~.ga_metric.MetricDescriptor: + google.api.metric_pb2.MetricDescriptor: Defines a metric type and its schema. Once a metric descriptor is created, deleting or altering it stops data @@ -810,10 +842,10 @@ def delete_metric_descriptor( can be deleted. Args: - request (:class:`~.metric_service.DeleteMetricDescriptorRequest`): + request (google.cloud.monitoring_v3.types.DeleteMetricDescriptorRequest): The request object. The `DeleteMetricDescriptor` request. - name (:class:`str`): + name (str): Required. The metric descriptor on which to execute the request. The format is: @@ -823,6 +855,7 @@ def delete_metric_descriptor( An example of ``[METRIC_ID]`` is: ``"custom.googleapis.com/my_test_metric"``. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -887,19 +920,22 @@ def list_time_series( does not require a Workspace. Args: - request (:class:`~.metric_service.ListTimeSeriesRequest`): + request (google.cloud.monitoring_v3.types.ListTimeSeriesRequest): The request object. The `ListTimeSeries` request. - name (:class:`str`): - Required. The project on which to execute the request. - The format is: + name (str): + Required. The project, organization or folder on which + to execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + organizations/[ORGANIZATION_ID] + folders/[FOLDER_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - filter (:class:`str`): + filter (str): Required. A `monitoring filter `__ that specifies which time series should be returned. The @@ -910,22 +946,25 @@ def list_time_series( :: metric.type = "compute.googleapis.com/instance/cpu/usage_time" AND - metric.labels.instance_name = "my-instance-name". + metric.labels.instance_name = "my-instance-name" + This corresponds to the ``filter`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - interval (:class:`~.common.TimeInterval`): + interval (google.cloud.monitoring_v3.types.TimeInterval): Required. The time interval for which results should be returned. Only time series that contain data points in the specified interval are included in the response. + This corresponds to the ``interval`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - view (:class:`~.metric_service.ListTimeSeriesRequest.TimeSeriesView`): + view (google.cloud.monitoring_v3.types.ListTimeSeriesRequest.TimeSeriesView): Required. Specifies which information is returned about the time series. + This corresponds to the ``view`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -937,8 +976,8 @@ def list_time_series( sent along with the request as metadata. Returns: - ~.pagers.ListTimeSeriesPager: - The ``ListTimeSeries`` response. + google.cloud.monitoring_v3.services.metric_service.pagers.ListTimeSeriesPager: + The ListTimeSeries response. Iterating over this object will yield results and resolve additional pages automatically. @@ -1012,19 +1051,20 @@ def create_time_series( response. Args: - request (:class:`~.metric_service.CreateTimeSeriesRequest`): + request (google.cloud.monitoring_v3.types.CreateTimeSeriesRequest): The request object. The `CreateTimeSeries` request. - name (:class:`str`): + name (str): Required. The project on which to execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - time_series (:class:`Sequence[~.gm_metric.TimeSeries]`): + time_series (Sequence[google.cloud.monitoring_v3.types.TimeSeries]): Required. The new data to be added to a list of time series. Adds at most one data point to each of several time series. The new data point must be more recent than @@ -1035,6 +1075,7 @@ def create_time_series( The maximum number of ``TimeSeries`` objects per ``Create`` request is 200. + This corresponds to the ``time_series`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1067,9 +1108,8 @@ def create_time_series( if name is not None: request.name = name - - if time_series: - request.time_series.extend(time_series) + if time_series is not None: + request.time_series = time_series # Wrap the RPC method; this adds retry and timeout information, # and friendly error handling. diff --git a/google/cloud/monitoring_v3/services/metric_service/pagers.py b/google/cloud/monitoring_v3/services/metric_service/pagers.py index d93703ec..825bae02 100644 --- a/google/cloud/monitoring_v3/services/metric_service/pagers.py +++ b/google/cloud/monitoring_v3/services/metric_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.api import metric_pb2 as ga_metric # type: ignore from google.api import monitored_resource_pb2 as monitored_resource # type: ignore @@ -27,7 +36,7 @@ class ListMonitoredResourceDescriptorsPager: """A pager for iterating through ``list_monitored_resource_descriptors`` requests. This class thinly wraps an initial - :class:`~.metric_service.ListMonitoredResourceDescriptorsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsResponse` object, and provides an ``__iter__`` method to iterate through its ``resource_descriptors`` field. @@ -36,7 +45,7 @@ class ListMonitoredResourceDescriptorsPager: through the ``resource_descriptors`` field on the corresponding responses. - All the usual :class:`~.metric_service.ListMonitoredResourceDescriptorsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -54,9 +63,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.metric_service.ListMonitoredResourceDescriptorsRequest`): + request (google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsRequest): The initial request object. - response (:class:`~.metric_service.ListMonitoredResourceDescriptorsResponse`): + response (google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -91,7 +100,7 @@ class ListMonitoredResourceDescriptorsAsyncPager: """A pager for iterating through ``list_monitored_resource_descriptors`` requests. This class thinly wraps an initial - :class:`~.metric_service.ListMonitoredResourceDescriptorsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsResponse` object, and provides an ``__aiter__`` method to iterate through its ``resource_descriptors`` field. @@ -100,7 +109,7 @@ class ListMonitoredResourceDescriptorsAsyncPager: through the ``resource_descriptors`` field on the corresponding responses. - All the usual :class:`~.metric_service.ListMonitoredResourceDescriptorsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -120,9 +129,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.metric_service.ListMonitoredResourceDescriptorsRequest`): + request (google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsRequest): The initial request object. - response (:class:`~.metric_service.ListMonitoredResourceDescriptorsResponse`): + response (google.cloud.monitoring_v3.types.ListMonitoredResourceDescriptorsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -163,7 +172,7 @@ class ListMetricDescriptorsPager: """A pager for iterating through ``list_metric_descriptors`` requests. This class thinly wraps an initial - :class:`~.metric_service.ListMetricDescriptorsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListMetricDescriptorsResponse` object, and provides an ``__iter__`` method to iterate through its ``metric_descriptors`` field. @@ -172,7 +181,7 @@ class ListMetricDescriptorsPager: through the ``metric_descriptors`` field on the corresponding responses. - All the usual :class:`~.metric_service.ListMetricDescriptorsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListMetricDescriptorsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -190,9 +199,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.metric_service.ListMetricDescriptorsRequest`): + request (google.cloud.monitoring_v3.types.ListMetricDescriptorsRequest): The initial request object. - response (:class:`~.metric_service.ListMetricDescriptorsResponse`): + response (google.cloud.monitoring_v3.types.ListMetricDescriptorsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -225,7 +234,7 @@ class ListMetricDescriptorsAsyncPager: """A pager for iterating through ``list_metric_descriptors`` requests. This class thinly wraps an initial - :class:`~.metric_service.ListMetricDescriptorsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListMetricDescriptorsResponse` object, and provides an ``__aiter__`` method to iterate through its ``metric_descriptors`` field. @@ -234,7 +243,7 @@ class ListMetricDescriptorsAsyncPager: through the ``metric_descriptors`` field on the corresponding responses. - All the usual :class:`~.metric_service.ListMetricDescriptorsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListMetricDescriptorsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -252,9 +261,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.metric_service.ListMetricDescriptorsRequest`): + request (google.cloud.monitoring_v3.types.ListMetricDescriptorsRequest): The initial request object. - response (:class:`~.metric_service.ListMetricDescriptorsResponse`): + response (google.cloud.monitoring_v3.types.ListMetricDescriptorsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -293,7 +302,7 @@ class ListTimeSeriesPager: """A pager for iterating through ``list_time_series`` requests. This class thinly wraps an initial - :class:`~.metric_service.ListTimeSeriesResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListTimeSeriesResponse` object, and provides an ``__iter__`` method to iterate through its ``time_series`` field. @@ -302,7 +311,7 @@ class ListTimeSeriesPager: through the ``time_series`` field on the corresponding responses. - All the usual :class:`~.metric_service.ListTimeSeriesResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListTimeSeriesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -320,9 +329,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.metric_service.ListTimeSeriesRequest`): + request (google.cloud.monitoring_v3.types.ListTimeSeriesRequest): The initial request object. - response (:class:`~.metric_service.ListTimeSeriesResponse`): + response (google.cloud.monitoring_v3.types.ListTimeSeriesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -355,7 +364,7 @@ class ListTimeSeriesAsyncPager: """A pager for iterating through ``list_time_series`` requests. This class thinly wraps an initial - :class:`~.metric_service.ListTimeSeriesResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListTimeSeriesResponse` object, and provides an ``__aiter__`` method to iterate through its ``time_series`` field. @@ -364,7 +373,7 @@ class ListTimeSeriesAsyncPager: through the ``time_series`` field on the corresponding responses. - All the usual :class:`~.metric_service.ListTimeSeriesResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListTimeSeriesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -382,9 +391,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.metric_service.ListTimeSeriesRequest`): + request (google.cloud.monitoring_v3.types.ListTimeSeriesRequest): The initial request object. - response (:class:`~.metric_service.ListTimeSeriesResponse`): + response (google.cloud.monitoring_v3.types.ListTimeSeriesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/monitoring_v3/services/metric_service/transports/base.py b/google/cloud/monitoring_v3/services/metric_service/transports/base.py index 8d058bc6..a708c2f5 100644 --- a/google/cloud/monitoring_v3/services/metric_service/transports/base.py +++ b/google/cloud/monitoring_v3/services/metric_service/transports/base.py @@ -77,10 +77,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -88,6 +88,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -97,20 +100,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -123,6 +123,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -136,6 +137,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -149,6 +151,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -162,6 +165,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -180,6 +184,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -193,6 +198,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, diff --git a/google/cloud/monitoring_v3/services/metric_service/transports/grpc.py b/google/cloud/monitoring_v3/services/metric_service/transports/grpc.py index 5df95042..0c6f78b0 100644 --- a/google/cloud/monitoring_v3/services/metric_service/transports/grpc.py +++ b/google/cloud/monitoring_v3/services/metric_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): @@ -105,72 +110,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -178,17 +171,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -202,7 +186,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If diff --git a/google/cloud/monitoring_v3/services/metric_service/transports/grpc_asyncio.py b/google/cloud/monitoring_v3/services/metric_service/transports/grpc_asyncio.py index e5a2df2e..3f682d92 100644 --- a/google/cloud/monitoring_v3/services/metric_service/transports/grpc_asyncio.py +++ b/google/cloud/monitoring_v3/services/metric_service/transports/grpc_asyncio.py @@ -65,7 +65,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -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,12 +137,16 @@ 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): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -150,72 +155,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -223,17 +216,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/monitoring_v3/services/notification_channel_service/async_client.py b/google/cloud/monitoring_v3/services/notification_channel_service/async_client.py index 1f15c4cb..26a14a54 100644 --- a/google/cloud/monitoring_v3/services/notification_channel_service/async_client.py +++ b/google/cloud/monitoring_v3/services/notification_channel_service/async_client.py @@ -32,6 +32,7 @@ from google.api import launch_stage_pb2 as launch_stage # type: ignore from google.cloud.monitoring_v3.services.notification_channel_service import pagers from google.cloud.monitoring_v3.types import common +from google.cloud.monitoring_v3.types import mutation_record from google.cloud.monitoring_v3.types import notification from google.cloud.monitoring_v3.types import notification_service from google.protobuf import field_mask_pb2 as field_mask # type: ignore @@ -101,9 +102,36 @@ class NotificationChannelServiceAsyncClient: NotificationChannelServiceClient.parse_common_location_path ) - from_service_account_file = ( - NotificationChannelServiceClient.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: + NotificationChannelServiceAsyncClient: The constructed client. + """ + return NotificationChannelServiceClient.from_service_account_info.__func__(NotificationChannelServiceAsyncClient, 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: + NotificationChannelServiceAsyncClient: The constructed client. + """ + return NotificationChannelServiceClient.from_service_account_file.__func__(NotificationChannelServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -182,7 +210,7 @@ async def list_notification_channel_descriptors( types to be dynamically added. Args: - request (:class:`~.notification_service.ListNotificationChannelDescriptorsRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsRequest`): The request object. The `ListNotificationChannelDescriptors` request. name (:class:`str`): @@ -199,6 +227,7 @@ async def list_notification_channel_descriptors( descriptor by name, use the [GetNotificationChannelDescriptor][google.monitoring.v3.NotificationChannelService.GetNotificationChannelDescriptor] operation, instead. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -210,8 +239,8 @@ async def list_notification_channel_descriptors( sent along with the request as metadata. Returns: - ~.pagers.ListNotificationChannelDescriptorsAsyncPager: - The ``ListNotificationChannelDescriptors`` response. + google.cloud.monitoring_v3.services.notification_channel_service.pagers.ListNotificationChannelDescriptorsAsyncPager: + The ListNotificationChannelDescriptors response. Iterating over this object will yield results and resolve additional pages automatically. @@ -248,6 +277,7 @@ async def list_notification_channel_descriptors( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -285,7 +315,7 @@ async def get_notification_channel_descriptor( notification channel of the given type. Args: - request (:class:`~.notification_service.GetNotificationChannelDescriptorRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetNotificationChannelDescriptorRequest`): The request object. The `GetNotificationChannelDescriptor` response. name (:class:`str`): @@ -295,6 +325,7 @@ async def get_notification_channel_descriptor( :: projects/[PROJECT_ID_OR_NUMBER]/notificationChannelDescriptors/[CHANNEL_TYPE] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -306,7 +337,7 @@ async def get_notification_channel_descriptor( sent along with the request as metadata. Returns: - ~.notification.NotificationChannelDescriptor: + google.cloud.monitoring_v3.types.NotificationChannelDescriptor: A description of a notification channel. The descriptor includes the properties of the channel and the set of @@ -343,6 +374,7 @@ async def get_notification_channel_descriptor( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -373,7 +405,7 @@ async def list_notification_channels( created for the project. Args: - request (:class:`~.notification_service.ListNotificationChannelsRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListNotificationChannelsRequest`): The request object. The `ListNotificationChannels` request. name (:class:`str`): @@ -390,6 +422,7 @@ async def list_notification_channels( name, use the [``GetNotificationChannel``][google.monitoring.v3.NotificationChannelService.GetNotificationChannel] operation. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -401,8 +434,8 @@ async def list_notification_channels( sent along with the request as metadata. Returns: - ~.pagers.ListNotificationChannelsAsyncPager: - The ``ListNotificationChannels`` response. + google.cloud.monitoring_v3.services.notification_channel_service.pagers.ListNotificationChannelsAsyncPager: + The ListNotificationChannels response. Iterating over this object will yield results and resolve additional pages automatically. @@ -437,6 +470,7 @@ async def list_notification_channels( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -478,7 +512,7 @@ async def get_notification_channel( call to the create method. Args: - request (:class:`~.notification_service.GetNotificationChannelRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetNotificationChannelRequest`): The request object. The `GetNotificationChannel` request. name (:class:`str`): @@ -488,6 +522,7 @@ async def get_notification_channel( :: projects/[PROJECT_ID_OR_NUMBER]/notificationChannels/[CHANNEL_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -499,13 +534,14 @@ async def get_notification_channel( sent along with the request as metadata. Returns: - ~.notification.NotificationChannel: - A ``NotificationChannel`` is a medium through which an - alert is delivered when a policy violation is detected. - Examples of channels include email, SMS, and third-party - messaging applications. Fields containing sensitive - information like authentication tokens or contact info - are only partially populated on retrieval. + google.cloud.monitoring_v3.types.NotificationChannel: + A NotificationChannel is a medium through which an alert is + delivered when a policy violation is detected. + Examples of channels include email, SMS, and + third-party messaging applications. Fields containing + sensitive information like authentication tokens or + contact info are only partially populated on + retrieval. """ # Create or coerce a protobuf request object. @@ -537,6 +573,7 @@ async def get_notification_channel( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -569,7 +606,7 @@ async def create_notification_channel( SMS number, or PagerDuty service. Args: - request (:class:`~.notification_service.CreateNotificationChannelRequest`): + request (:class:`google.cloud.monitoring_v3.types.CreateNotificationChannelRequest`): The request object. The `CreateNotificationChannel` request. name (:class:`str`): @@ -586,12 +623,14 @@ async def create_notification_channel( version of this field as a prefix, but will add ``/notificationChannels/[CHANNEL_ID]`` to identify the channel. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - notification_channel (:class:`~.notification.NotificationChannel`): + notification_channel (:class:`google.cloud.monitoring_v3.types.NotificationChannel`): Required. The definition of the ``NotificationChannel`` to create. + This corresponds to the ``notification_channel`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -603,13 +642,14 @@ async def create_notification_channel( sent along with the request as metadata. Returns: - ~.notification.NotificationChannel: - A ``NotificationChannel`` is a medium through which an - alert is delivered when a policy violation is detected. - Examples of channels include email, SMS, and third-party - messaging applications. Fields containing sensitive - information like authentication tokens or contact info - are only partially populated on retrieval. + google.cloud.monitoring_v3.types.NotificationChannel: + A NotificationChannel is a medium through which an alert is + delivered when a policy violation is detected. + Examples of channels include email, SMS, and + third-party messaging applications. Fields containing + sensitive information like authentication tokens or + contact info are only partially populated on + retrieval. """ # Create or coerce a protobuf request object. @@ -666,20 +706,21 @@ async def update_notification_channel( in the field mask remain unchanged. Args: - request (:class:`~.notification_service.UpdateNotificationChannelRequest`): + request (:class:`google.cloud.monitoring_v3.types.UpdateNotificationChannelRequest`): The request object. The `UpdateNotificationChannel` request. - update_mask (:class:`~.field_mask.FieldMask`): + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): The fields to update. This corresponds to the ``update_mask`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - notification_channel (:class:`~.notification.NotificationChannel`): + notification_channel (:class:`google.cloud.monitoring_v3.types.NotificationChannel`): Required. A description of the changes to be applied to the specified notification channel. The description must provide a definition for fields to be updated; the names of these fields should also be included in the ``update_mask``. + This corresponds to the ``notification_channel`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -691,13 +732,14 @@ async def update_notification_channel( sent along with the request as metadata. Returns: - ~.notification.NotificationChannel: - A ``NotificationChannel`` is a medium through which an - alert is delivered when a policy violation is detected. - Examples of channels include email, SMS, and third-party - messaging applications. Fields containing sensitive - information like authentication tokens or contact info - are only partially populated on retrieval. + google.cloud.monitoring_v3.types.NotificationChannel: + A NotificationChannel is a medium through which an alert is + delivered when a policy violation is detected. + Examples of channels include email, SMS, and + third-party messaging applications. Fields containing + sensitive information like authentication tokens or + contact info are only partially populated on + retrieval. """ # Create or coerce a protobuf request object. @@ -755,7 +797,7 @@ async def delete_notification_channel( r"""Deletes a notification channel. Args: - request (:class:`~.notification_service.DeleteNotificationChannelRequest`): + request (:class:`google.cloud.monitoring_v3.types.DeleteNotificationChannelRequest`): The request object. The `DeleteNotificationChannel` request. name (:class:`str`): @@ -765,6 +807,7 @@ async def delete_notification_channel( :: projects/[PROJECT_ID_OR_NUMBER]/notificationChannels/[CHANNEL_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -777,6 +820,7 @@ async def delete_notification_channel( referenced by an existing alerting policy will fail to be deleted in a delete operation. + This corresponds to the ``force`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -818,6 +862,7 @@ async def delete_notification_channel( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -848,12 +893,13 @@ async def send_notification_channel_verification_code( verify the channel. Args: - request (:class:`~.notification_service.SendNotificationChannelVerificationCodeRequest`): + request (:class:`google.cloud.monitoring_v3.types.SendNotificationChannelVerificationCodeRequest`): The request object. The `SendNotificationChannelVerificationCode` request. name (:class:`str`): Required. The notification channel to which to send a verification code. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -942,7 +988,7 @@ async def get_notification_channel_verification_code( string that has a longer expiration time. Args: - request (:class:`~.notification_service.GetNotificationChannelVerificationCodeRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetNotificationChannelVerificationCodeRequest`): The request object. The `GetNotificationChannelVerificationCode` request. name (:class:`str`): @@ -952,6 +998,7 @@ async def get_notification_channel_verification_code( a channel that is already verified; if the specified channel is not verified, the request will fail. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -963,8 +1010,8 @@ async def get_notification_channel_verification_code( sent along with the request as metadata. Returns: - ~.notification_service.GetNotificationChannelVerificationCodeResponse: - The ``GetNotificationChannelVerificationCode`` request. + google.cloud.monitoring_v3.types.GetNotificationChannelVerificationCodeResponse: + The GetNotificationChannelVerificationCode request. """ # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have @@ -997,6 +1044,7 @@ async def get_notification_channel_verification_code( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -1029,12 +1077,13 @@ async def verify_notification_channel( ``SendNotificationChannelVerificationCode``. Args: - request (:class:`~.notification_service.VerifyNotificationChannelRequest`): + request (:class:`google.cloud.monitoring_v3.types.VerifyNotificationChannelRequest`): The request object. The `VerifyNotificationChannel` request. name (:class:`str`): Required. The notification channel to verify. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1048,6 +1097,7 @@ async def verify_notification_channel( (in general, one is only guaranteed that the code is valid UTF-8; one should not make any assumptions regarding the structure or format of the code). + This corresponds to the ``code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1059,13 +1109,14 @@ async def verify_notification_channel( sent along with the request as metadata. Returns: - ~.notification.NotificationChannel: - A ``NotificationChannel`` is a medium through which an - alert is delivered when a policy violation is detected. - Examples of channels include email, SMS, and third-party - messaging applications. Fields containing sensitive - information like authentication tokens or contact info - are only partially populated on retrieval. + google.cloud.monitoring_v3.types.NotificationChannel: + A NotificationChannel is a medium through which an alert is + delivered when a policy violation is detected. + Examples of channels include email, SMS, and + third-party messaging applications. Fields containing + sensitive information like authentication tokens or + contact info are only partially populated on + retrieval. """ # Create or coerce a protobuf request object. @@ -1099,6 +1150,7 @@ async def verify_notification_channel( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/monitoring_v3/services/notification_channel_service/client.py b/google/cloud/monitoring_v3/services/notification_channel_service/client.py index 3b1ffe37..fae66469 100644 --- a/google/cloud/monitoring_v3/services/notification_channel_service/client.py +++ b/google/cloud/monitoring_v3/services/notification_channel_service/client.py @@ -36,6 +36,7 @@ from google.api import launch_stage_pb2 as launch_stage # type: ignore from google.cloud.monitoring_v3.services.notification_channel_service import pagers from google.cloud.monitoring_v3.types import common +from google.cloud.monitoring_v3.types import mutation_record from google.cloud.monitoring_v3.types import notification from google.cloud.monitoring_v3.types import notification_service from google.protobuf import field_mask_pb2 as field_mask # type: ignore @@ -121,6 +122,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: + NotificationChannelServiceClient: 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 @@ -133,7 +150,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. + NotificationChannelServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -259,10 +276,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, ~.NotificationChannelServiceTransport]): The + transport (Union[str, NotificationChannelServiceTransport]): 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 @@ -298,21 +315,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: @@ -355,7 +368,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, ) @@ -374,10 +387,10 @@ def list_notification_channel_descriptors( types to be dynamically added. Args: - request (:class:`~.notification_service.ListNotificationChannelDescriptorsRequest`): + request (google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsRequest): The request object. The `ListNotificationChannelDescriptors` request. - name (:class:`str`): + name (str): Required. The REST resource name of the parent from which to retrieve the notification channel descriptors. The expected syntax is: @@ -391,6 +404,7 @@ def list_notification_channel_descriptors( descriptor by name, use the [GetNotificationChannelDescriptor][google.monitoring.v3.NotificationChannelService.GetNotificationChannelDescriptor] operation, instead. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -402,8 +416,8 @@ def list_notification_channel_descriptors( sent along with the request as metadata. Returns: - ~.pagers.ListNotificationChannelDescriptorsPager: - The ``ListNotificationChannelDescriptors`` response. + google.cloud.monitoring_v3.services.notification_channel_service.pagers.ListNotificationChannelDescriptorsPager: + The ListNotificationChannelDescriptors response. Iterating over this object will yield results and resolve additional pages automatically. @@ -474,16 +488,17 @@ def get_notification_channel_descriptor( notification channel of the given type. Args: - request (:class:`~.notification_service.GetNotificationChannelDescriptorRequest`): + request (google.cloud.monitoring_v3.types.GetNotificationChannelDescriptorRequest): The request object. The `GetNotificationChannelDescriptor` response. - name (:class:`str`): + name (str): Required. The channel type for which to execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/notificationChannelDescriptors/[CHANNEL_TYPE] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -495,7 +510,7 @@ def get_notification_channel_descriptor( sent along with the request as metadata. Returns: - ~.notification.NotificationChannelDescriptor: + google.cloud.monitoring_v3.types.NotificationChannelDescriptor: A description of a notification channel. The descriptor includes the properties of the channel and the set of @@ -561,10 +576,10 @@ def list_notification_channels( created for the project. Args: - request (:class:`~.notification_service.ListNotificationChannelsRequest`): + request (google.cloud.monitoring_v3.types.ListNotificationChannelsRequest): The request object. The `ListNotificationChannels` request. - name (:class:`str`): + name (str): Required. The project on which to execute the request. The format is: @@ -578,6 +593,7 @@ def list_notification_channels( name, use the [``GetNotificationChannel``][google.monitoring.v3.NotificationChannelService.GetNotificationChannel] operation. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -589,8 +605,8 @@ def list_notification_channels( sent along with the request as metadata. Returns: - ~.pagers.ListNotificationChannelsPager: - The ``ListNotificationChannels`` response. + google.cloud.monitoring_v3.services.notification_channel_service.pagers.ListNotificationChannelsPager: + The ListNotificationChannels response. Iterating over this object will yield results and resolve additional pages automatically. @@ -663,16 +679,17 @@ def get_notification_channel( call to the create method. Args: - request (:class:`~.notification_service.GetNotificationChannelRequest`): + request (google.cloud.monitoring_v3.types.GetNotificationChannelRequest): The request object. The `GetNotificationChannel` request. - name (:class:`str`): + name (str): Required. The channel for which to execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/notificationChannels/[CHANNEL_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -684,13 +701,14 @@ def get_notification_channel( sent along with the request as metadata. Returns: - ~.notification.NotificationChannel: - A ``NotificationChannel`` is a medium through which an - alert is delivered when a policy violation is detected. - Examples of channels include email, SMS, and third-party - messaging applications. Fields containing sensitive - information like authentication tokens or contact info - are only partially populated on retrieval. + google.cloud.monitoring_v3.types.NotificationChannel: + A NotificationChannel is a medium through which an alert is + delivered when a policy violation is detected. + Examples of channels include email, SMS, and + third-party messaging applications. Fields containing + sensitive information like authentication tokens or + contact info are only partially populated on + retrieval. """ # Create or coerce a protobuf request object. @@ -747,10 +765,10 @@ def create_notification_channel( SMS number, or PagerDuty service. Args: - request (:class:`~.notification_service.CreateNotificationChannelRequest`): + request (google.cloud.monitoring_v3.types.CreateNotificationChannelRequest): The request object. The `CreateNotificationChannel` request. - name (:class:`str`): + name (str): Required. The project on which to execute the request. The format is: @@ -764,12 +782,14 @@ def create_notification_channel( version of this field as a prefix, but will add ``/notificationChannels/[CHANNEL_ID]`` to identify the channel. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - notification_channel (:class:`~.notification.NotificationChannel`): + notification_channel (google.cloud.monitoring_v3.types.NotificationChannel): Required. The definition of the ``NotificationChannel`` to create. + This corresponds to the ``notification_channel`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -781,13 +801,14 @@ def create_notification_channel( sent along with the request as metadata. Returns: - ~.notification.NotificationChannel: - A ``NotificationChannel`` is a medium through which an - alert is delivered when a policy violation is detected. - Examples of channels include email, SMS, and third-party - messaging applications. Fields containing sensitive - information like authentication tokens or contact info - are only partially populated on retrieval. + google.cloud.monitoring_v3.types.NotificationChannel: + A NotificationChannel is a medium through which an alert is + delivered when a policy violation is detected. + Examples of channels include email, SMS, and + third-party messaging applications. Fields containing + sensitive information like authentication tokens or + contact info are only partially populated on + retrieval. """ # Create or coerce a protobuf request object. @@ -849,20 +870,21 @@ def update_notification_channel( in the field mask remain unchanged. Args: - request (:class:`~.notification_service.UpdateNotificationChannelRequest`): + request (google.cloud.monitoring_v3.types.UpdateNotificationChannelRequest): The request object. The `UpdateNotificationChannel` request. - update_mask (:class:`~.field_mask.FieldMask`): + update_mask (google.protobuf.field_mask_pb2.FieldMask): The fields to update. This corresponds to the ``update_mask`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - notification_channel (:class:`~.notification.NotificationChannel`): + notification_channel (google.cloud.monitoring_v3.types.NotificationChannel): Required. A description of the changes to be applied to the specified notification channel. The description must provide a definition for fields to be updated; the names of these fields should also be included in the ``update_mask``. + This corresponds to the ``notification_channel`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -874,13 +896,14 @@ def update_notification_channel( sent along with the request as metadata. Returns: - ~.notification.NotificationChannel: - A ``NotificationChannel`` is a medium through which an - alert is delivered when a policy violation is detected. - Examples of channels include email, SMS, and third-party - messaging applications. Fields containing sensitive - information like authentication tokens or contact info - are only partially populated on retrieval. + google.cloud.monitoring_v3.types.NotificationChannel: + A NotificationChannel is a medium through which an alert is + delivered when a policy violation is detected. + Examples of channels include email, SMS, and + third-party messaging applications. Fields containing + sensitive information like authentication tokens or + contact info are only partially populated on + retrieval. """ # Create or coerce a protobuf request object. @@ -943,20 +966,21 @@ def delete_notification_channel( r"""Deletes a notification channel. Args: - request (:class:`~.notification_service.DeleteNotificationChannelRequest`): + request (google.cloud.monitoring_v3.types.DeleteNotificationChannelRequest): The request object. The `DeleteNotificationChannel` request. - name (:class:`str`): + name (str): Required. The channel for which to execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/notificationChannels/[CHANNEL_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - force (:class:`bool`): + force (bool): If true, the notification channel will be deleted regardless of its use in alert policies (the policies will be @@ -965,6 +989,7 @@ def delete_notification_channel( referenced by an existing alerting policy will fail to be deleted in a delete operation. + This corresponds to the ``force`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1033,12 +1058,13 @@ def send_notification_channel_verification_code( verify the channel. Args: - request (:class:`~.notification_service.SendNotificationChannelVerificationCodeRequest`): + request (google.cloud.monitoring_v3.types.SendNotificationChannelVerificationCodeRequest): The request object. The `SendNotificationChannelVerificationCode` request. - name (:class:`str`): + name (str): Required. The notification channel to which to send a verification code. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1132,16 +1158,17 @@ def get_notification_channel_verification_code( string that has a longer expiration time. Args: - request (:class:`~.notification_service.GetNotificationChannelVerificationCodeRequest`): + request (google.cloud.monitoring_v3.types.GetNotificationChannelVerificationCodeRequest): The request object. The `GetNotificationChannelVerificationCode` request. - name (:class:`str`): + name (str): Required. The notification channel for which a verification code is to be generated and retrieved. This must name a channel that is already verified; if the specified channel is not verified, the request will fail. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1153,8 +1180,8 @@ def get_notification_channel_verification_code( sent along with the request as metadata. Returns: - ~.notification_service.GetNotificationChannelVerificationCodeResponse: - The ``GetNotificationChannelVerificationCode`` request. + google.cloud.monitoring_v3.types.GetNotificationChannelVerificationCodeResponse: + The GetNotificationChannelVerificationCode request. """ # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have @@ -1216,16 +1243,17 @@ def verify_notification_channel( ``SendNotificationChannelVerificationCode``. Args: - request (:class:`~.notification_service.VerifyNotificationChannelRequest`): + request (google.cloud.monitoring_v3.types.VerifyNotificationChannelRequest): The request object. The `VerifyNotificationChannel` request. - name (:class:`str`): + name (str): Required. The notification channel to verify. + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - code (:class:`str`): + code (str): Required. The verification code that was delivered to the channel as a result of invoking the ``SendNotificationChannelVerificationCode`` API method @@ -1235,6 +1263,7 @@ def verify_notification_channel( (in general, one is only guaranteed that the code is valid UTF-8; one should not make any assumptions regarding the structure or format of the code). + This corresponds to the ``code`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1246,13 +1275,14 @@ def verify_notification_channel( sent along with the request as metadata. Returns: - ~.notification.NotificationChannel: - A ``NotificationChannel`` is a medium through which an - alert is delivered when a policy violation is detected. - Examples of channels include email, SMS, and third-party - messaging applications. Fields containing sensitive - information like authentication tokens or contact info - are only partially populated on retrieval. + google.cloud.monitoring_v3.types.NotificationChannel: + A NotificationChannel is a medium through which an alert is + delivered when a policy violation is detected. + Examples of channels include email, SMS, and + third-party messaging applications. Fields containing + sensitive information like authentication tokens or + contact info are only partially populated on + retrieval. """ # Create or coerce a protobuf request object. diff --git a/google/cloud/monitoring_v3/services/notification_channel_service/pagers.py b/google/cloud/monitoring_v3/services/notification_channel_service/pagers.py index 3e7e6387..01dc3879 100644 --- a/google/cloud/monitoring_v3/services/notification_channel_service/pagers.py +++ b/google/cloud/monitoring_v3/services/notification_channel_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.monitoring_v3.types import notification from google.cloud.monitoring_v3.types import notification_service @@ -25,7 +34,7 @@ class ListNotificationChannelDescriptorsPager: """A pager for iterating through ``list_notification_channel_descriptors`` requests. This class thinly wraps an initial - :class:`~.notification_service.ListNotificationChannelDescriptorsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsResponse` object, and provides an ``__iter__`` method to iterate through its ``channel_descriptors`` field. @@ -34,7 +43,7 @@ class ListNotificationChannelDescriptorsPager: through the ``channel_descriptors`` field on the corresponding responses. - All the usual :class:`~.notification_service.ListNotificationChannelDescriptorsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -54,9 +63,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.notification_service.ListNotificationChannelDescriptorsRequest`): + request (google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsRequest): The initial request object. - response (:class:`~.notification_service.ListNotificationChannelDescriptorsResponse`): + response (google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -93,7 +102,7 @@ class ListNotificationChannelDescriptorsAsyncPager: """A pager for iterating through ``list_notification_channel_descriptors`` requests. This class thinly wraps an initial - :class:`~.notification_service.ListNotificationChannelDescriptorsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsResponse` object, and provides an ``__aiter__`` method to iterate through its ``channel_descriptors`` field. @@ -102,7 +111,7 @@ class ListNotificationChannelDescriptorsAsyncPager: through the ``channel_descriptors`` field on the corresponding responses. - All the usual :class:`~.notification_service.ListNotificationChannelDescriptorsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -123,9 +132,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.notification_service.ListNotificationChannelDescriptorsRequest`): + request (google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsRequest): The initial request object. - response (:class:`~.notification_service.ListNotificationChannelDescriptorsResponse`): + response (google.cloud.monitoring_v3.types.ListNotificationChannelDescriptorsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -166,7 +175,7 @@ class ListNotificationChannelsPager: """A pager for iterating through ``list_notification_channels`` requests. This class thinly wraps an initial - :class:`~.notification_service.ListNotificationChannelsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListNotificationChannelsResponse` object, and provides an ``__iter__`` method to iterate through its ``notification_channels`` field. @@ -175,7 +184,7 @@ class ListNotificationChannelsPager: through the ``notification_channels`` field on the corresponding responses. - All the usual :class:`~.notification_service.ListNotificationChannelsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListNotificationChannelsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -193,9 +202,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.notification_service.ListNotificationChannelsRequest`): + request (google.cloud.monitoring_v3.types.ListNotificationChannelsRequest): The initial request object. - response (:class:`~.notification_service.ListNotificationChannelsResponse`): + response (google.cloud.monitoring_v3.types.ListNotificationChannelsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -228,7 +237,7 @@ class ListNotificationChannelsAsyncPager: """A pager for iterating through ``list_notification_channels`` requests. This class thinly wraps an initial - :class:`~.notification_service.ListNotificationChannelsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListNotificationChannelsResponse` object, and provides an ``__aiter__`` method to iterate through its ``notification_channels`` field. @@ -237,7 +246,7 @@ class ListNotificationChannelsAsyncPager: through the ``notification_channels`` field on the corresponding responses. - All the usual :class:`~.notification_service.ListNotificationChannelsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListNotificationChannelsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -257,9 +266,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.notification_service.ListNotificationChannelsRequest`): + request (google.cloud.monitoring_v3.types.ListNotificationChannelsRequest): The initial request object. - response (:class:`~.notification_service.ListNotificationChannelsResponse`): + response (google.cloud.monitoring_v3.types.ListNotificationChannelsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/monitoring_v3/services/notification_channel_service/transports/base.py b/google/cloud/monitoring_v3/services/notification_channel_service/transports/base.py index 5c688215..a856407e 100644 --- a/google/cloud/monitoring_v3/services/notification_channel_service/transports/base.py +++ b/google/cloud/monitoring_v3/services/notification_channel_service/transports/base.py @@ -75,10 +75,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -86,6 +86,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -95,20 +98,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -121,6 +121,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -134,6 +135,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -147,6 +149,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -160,6 +163,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -183,6 +187,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -201,6 +206,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -214,6 +220,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, diff --git a/google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc.py b/google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc.py index 808434bb..6c84eced 100644 --- a/google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc.py +++ b/google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc.py @@ -60,6 +60,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: @@ -90,6 +91,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): @@ -104,72 +109,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -177,17 +170,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -201,7 +185,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If diff --git a/google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc_asyncio.py b/google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc_asyncio.py index 14eb7a95..5d7d4d53 100644 --- a/google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc_asyncio.py +++ b/google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc_asyncio.py @@ -66,7 +66,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -106,6 +106,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: @@ -137,12 +138,16 @@ 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): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -151,72 +156,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -224,17 +217,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/monitoring_v3/services/query_service/__init__.py b/google/cloud/monitoring_v3/services/query_service/__init__.py new file mode 100644 index 00000000..4d7b09e5 --- /dev/null +++ b/google/cloud/monitoring_v3/services/query_service/__init__.py @@ -0,0 +1,24 @@ +# -*- 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. +# + +from .client import QueryServiceClient +from .async_client import QueryServiceAsyncClient + +__all__ = ( + "QueryServiceClient", + "QueryServiceAsyncClient", +) diff --git a/google/cloud/monitoring_v3/services/query_service/async_client.py b/google/cloud/monitoring_v3/services/query_service/async_client.py new file mode 100644 index 00000000..1b320eb0 --- /dev/null +++ b/google/cloud/monitoring_v3/services/query_service/async_client.py @@ -0,0 +1,239 @@ +# -*- 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. +# + +from collections import OrderedDict +import functools +import re +from typing import Dict, Sequence, Tuple, Type, Union +import pkg_resources + +import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.monitoring_v3.services.query_service import pagers +from google.cloud.monitoring_v3.types import metric +from google.cloud.monitoring_v3.types import metric_service + +from .transports.base import QueryServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc_asyncio import QueryServiceGrpcAsyncIOTransport +from .client import QueryServiceClient + + +class QueryServiceAsyncClient: + """The QueryService API is used to manage time series data in + Stackdriver Monitoring. Time series data is a collection of data + points that describes the time-varying values of a metric. + """ + + _client: QueryServiceClient + + DEFAULT_ENDPOINT = QueryServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = QueryServiceClient.DEFAULT_MTLS_ENDPOINT + + common_billing_account_path = staticmethod( + QueryServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + QueryServiceClient.parse_common_billing_account_path + ) + + common_folder_path = staticmethod(QueryServiceClient.common_folder_path) + parse_common_folder_path = staticmethod(QueryServiceClient.parse_common_folder_path) + + common_organization_path = staticmethod(QueryServiceClient.common_organization_path) + parse_common_organization_path = staticmethod( + QueryServiceClient.parse_common_organization_path + ) + + common_project_path = staticmethod(QueryServiceClient.common_project_path) + parse_common_project_path = staticmethod( + QueryServiceClient.parse_common_project_path + ) + + common_location_path = staticmethod(QueryServiceClient.common_location_path) + parse_common_location_path = staticmethod( + QueryServiceClient.parse_common_location_path + ) + + @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: + QueryServiceAsyncClient: The constructed client. + """ + return QueryServiceClient.from_service_account_info.__func__(QueryServiceAsyncClient, 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: + QueryServiceAsyncClient: The constructed client. + """ + return QueryServiceClient.from_service_account_file.__func__(QueryServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> QueryServiceTransport: + """Return the transport used by the client instance. + + Returns: + QueryServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + get_transport_class = functools.partial( + type(QueryServiceClient).get_transport_class, type(QueryServiceClient) + ) + + def __init__( + self, + *, + credentials: credentials.Credentials = None, + transport: Union[str, QueryServiceTransport] = "grpc_asyncio", + client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiate the query service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + 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, ~.QueryServiceTransport]): The + transport to use. If set to None, a transport is chosen + automatically. + 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 + environment variable can also be used to override the endpoint: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + + self._client = QueryServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def query_time_series( + self, + request: metric_service.QueryTimeSeriesRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.QueryTimeSeriesAsyncPager: + r"""Queries time series using Monitoring Query Language. + This method does not require a Workspace. + + Args: + request (:class:`google.cloud.monitoring_v3.types.QueryTimeSeriesRequest`): + The request object. The `QueryTimeSeries` request. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.monitoring_v3.services.query_service.pagers.QueryTimeSeriesAsyncPager: + The QueryTimeSeries response. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # Create or coerce a protobuf request object. + + request = metric_service.QueryTimeSeriesRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.query_time_series, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # This method is paged; wrap the response in a pager, which provides + # an `__aiter__` convenience method. + response = pagers.QueryTimeSeriesAsyncPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-cloud-monitoring", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("QueryServiceAsyncClient",) diff --git a/google/cloud/monitoring_v3/services/query_service/client.py b/google/cloud/monitoring_v3/services/query_service/client.py new file mode 100644 index 00000000..583c1934 --- /dev/null +++ b/google/cloud/monitoring_v3/services/query_service/client.py @@ -0,0 +1,403 @@ +# -*- 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. +# + +from collections import OrderedDict +from distutils import util +import os +import re +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union +import pkg_resources + +from google.api_core import client_options as client_options_lib # type: ignore +from google.api_core import exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.monitoring_v3.services.query_service import pagers +from google.cloud.monitoring_v3.types import metric +from google.cloud.monitoring_v3.types import metric_service + +from .transports.base import QueryServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import QueryServiceGrpcTransport +from .transports.grpc_asyncio import QueryServiceGrpcAsyncIOTransport + + +class QueryServiceClientMeta(type): + """Metaclass for the QueryService client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = OrderedDict() # type: Dict[str, Type[QueryServiceTransport]] + _transport_registry["grpc"] = QueryServiceGrpcTransport + _transport_registry["grpc_asyncio"] = QueryServiceGrpcAsyncIOTransport + + def get_transport_class(cls, label: str = None,) -> Type[QueryServiceTransport]: + """Return an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class QueryServiceClient(metaclass=QueryServiceClientMeta): + """The QueryService API is used to manage time series data in + Stackdriver Monitoring. Time series data is a collection of data + points that describes the time-varying values of a metric. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Convert api endpoint to mTLS endpoint. + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + DEFAULT_ENDPOINT = "monitoring.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + 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: + QueryServiceClient: 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 + 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: + QueryServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> QueryServiceTransport: + """Return the transport used by the client instance. + + Returns: + QueryServiceTransport: The transport used by the client instance. + """ + return self._transport + + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Return a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path(folder: str,) -> str: + """Return a fully-qualified folder string.""" + return "folders/{folder}".format(folder=folder,) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path(organization: str,) -> str: + """Return a fully-qualified organization string.""" + return "organizations/{organization}".format(organization=organization,) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path(project: str,) -> str: + """Return a fully-qualified project string.""" + return "projects/{project}".format(project=project,) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path(project: str, location: str,) -> str: + """Return a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + + def __init__( + self, + *, + credentials: Optional[credentials.Credentials] = None, + transport: Union[str, QueryServiceTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiate the query service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + 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, QueryServiceTransport]): The + transport to use. If set to None, a transport is chosen + automatically. + 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 + environment variable can also be used to override the endpoint: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + + # Create SSL credentials for mutual TLS if needed. + use_client_cert = bool( + util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + 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: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, QueryServiceTransport): + # transport is a QueryServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, " + "provide its scopes directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + ) + + def query_time_series( + self, + request: metric_service.QueryTimeSeriesRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.QueryTimeSeriesPager: + r"""Queries time series using Monitoring Query Language. + This method does not require a Workspace. + + Args: + request (google.cloud.monitoring_v3.types.QueryTimeSeriesRequest): + The request object. The `QueryTimeSeries` request. + + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.monitoring_v3.services.query_service.pagers.QueryTimeSeriesPager: + The QueryTimeSeries response. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # Create or coerce a protobuf request object. + + # Minor optimization to avoid making a copy if the user passes + # in a metric_service.QueryTimeSeriesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, metric_service.QueryTimeSeriesRequest): + request = metric_service.QueryTimeSeriesRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.query_time_series] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # This method is paged; wrap the response in a pager, which provides + # an `__iter__` convenience method. + response = pagers.QueryTimeSeriesPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-cloud-monitoring", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("QueryServiceClient",) diff --git a/google/cloud/monitoring_v3/services/query_service/pagers.py b/google/cloud/monitoring_v3/services/query_service/pagers.py new file mode 100644 index 00000000..0c8a5059 --- /dev/null +++ b/google/cloud/monitoring_v3/services/query_service/pagers.py @@ -0,0 +1,158 @@ +# -*- 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. +# + +from typing import ( + Any, + AsyncIterable, + Awaitable, + Callable, + Iterable, + Sequence, + Tuple, + Optional, +) + +from google.cloud.monitoring_v3.types import metric +from google.cloud.monitoring_v3.types import metric_service + + +class QueryTimeSeriesPager: + """A pager for iterating through ``query_time_series`` requests. + + This class thinly wraps an initial + :class:`google.cloud.monitoring_v3.types.QueryTimeSeriesResponse` object, and + provides an ``__iter__`` method to iterate through its + ``time_series_data`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``QueryTimeSeries`` requests and continue to iterate + through the ``time_series_data`` field on the + corresponding responses. + + All the usual :class:`google.cloud.monitoring_v3.types.QueryTimeSeriesResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., metric_service.QueryTimeSeriesResponse], + request: metric_service.QueryTimeSeriesRequest, + response: metric_service.QueryTimeSeriesResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.monitoring_v3.types.QueryTimeSeriesRequest): + The initial request object. + response (google.cloud.monitoring_v3.types.QueryTimeSeriesResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = metric_service.QueryTimeSeriesRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterable[metric_service.QueryTimeSeriesResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method(self._request, metadata=self._metadata) + yield self._response + + def __iter__(self) -> Iterable[metric.TimeSeriesData]: + for page in self.pages: + yield from page.time_series_data + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class QueryTimeSeriesAsyncPager: + """A pager for iterating through ``query_time_series`` requests. + + This class thinly wraps an initial + :class:`google.cloud.monitoring_v3.types.QueryTimeSeriesResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``time_series_data`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``QueryTimeSeries`` requests and continue to iterate + through the ``time_series_data`` field on the + corresponding responses. + + All the usual :class:`google.cloud.monitoring_v3.types.QueryTimeSeriesResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., Awaitable[metric_service.QueryTimeSeriesResponse]], + request: metric_service.QueryTimeSeriesRequest, + response: metric_service.QueryTimeSeriesResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.monitoring_v3.types.QueryTimeSeriesRequest): + The initial request object. + response (google.cloud.monitoring_v3.types.QueryTimeSeriesResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = metric_service.QueryTimeSeriesRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages(self) -> AsyncIterable[metric_service.QueryTimeSeriesResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = await self._method(self._request, metadata=self._metadata) + yield self._response + + def __aiter__(self) -> AsyncIterable[metric.TimeSeriesData]: + async def async_generator(): + async for page in self.pages: + for response in page.time_series_data: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/cloud/monitoring_v3/services/query_service/transports/__init__.py b/google/cloud/monitoring_v3/services/query_service/transports/__init__.py new file mode 100644 index 00000000..cdf23933 --- /dev/null +++ b/google/cloud/monitoring_v3/services/query_service/transports/__init__.py @@ -0,0 +1,35 @@ +# -*- 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. +# + +from collections import OrderedDict +from typing import Dict, Type + +from .base import QueryServiceTransport +from .grpc import QueryServiceGrpcTransport +from .grpc_asyncio import QueryServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[QueryServiceTransport]] +_transport_registry["grpc"] = QueryServiceGrpcTransport +_transport_registry["grpc_asyncio"] = QueryServiceGrpcAsyncIOTransport + +__all__ = ( + "QueryServiceTransport", + "QueryServiceGrpcTransport", + "QueryServiceGrpcAsyncIOTransport", +) diff --git a/google/cloud/monitoring_v3/services/query_service/transports/base.py b/google/cloud/monitoring_v3/services/query_service/transports/base.py new file mode 100644 index 00000000..b43f052c --- /dev/null +++ b/google/cloud/monitoring_v3/services/query_service/transports/base.py @@ -0,0 +1,131 @@ +# -*- 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. +# + +import abc +import typing +import pkg_resources + +from google import auth # type: ignore +from google.api_core import exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials # type: ignore + +from google.cloud.monitoring_v3.types import metric_service + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-cloud-monitoring", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class QueryServiceTransport(abc.ABC): + """Abstract transport class for QueryService.""" + + AUTH_SCOPES = ( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ) + + def __init__( + self, + *, + host: str = "monitoring.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: typing.Optional[str] = None, + scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, + quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scope (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = auth.load_credentials_from_file( + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id + ) + + elif credentials is None: + credentials, _ = auth.default( + scopes=self._scopes, quota_project_id=quota_project_id + ) + + # Save the credentials. + self._credentials = credentials + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.query_time_series: gapic_v1.method.wrap_method( + self.query_time_series, default_timeout=None, client_info=client_info, + ), + } + + @property + def query_time_series( + self, + ) -> typing.Callable[ + [metric_service.QueryTimeSeriesRequest], + typing.Union[ + metric_service.QueryTimeSeriesResponse, + typing.Awaitable[metric_service.QueryTimeSeriesResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("QueryServiceTransport",) diff --git a/google/cloud/monitoring_v3/services/query_service/transports/grpc.py b/google/cloud/monitoring_v3/services/query_service/transports/grpc.py new file mode 100644 index 00000000..83b5dbc8 --- /dev/null +++ b/google/cloud/monitoring_v3/services/query_service/transports/grpc.py @@ -0,0 +1,256 @@ +# -*- 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. +# + +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +from google.api_core import grpc_helpers # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google import auth # type: ignore +from google.auth import credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore + +import grpc # type: ignore + +from google.cloud.monitoring_v3.types import metric_service + +from .base import QueryServiceTransport, DEFAULT_CLIENT_INFO + + +class QueryServiceGrpcTransport(QueryServiceTransport): + """gRPC backend transport for QueryService. + + The QueryService API is used to manage time series data in + Stackdriver Monitoring. Time series data is a collection of data + points that describes the time-varying values of a metric. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "monitoring.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: str = None, + scopes: Sequence[str] = None, + channel: grpc.Channel = None, + 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: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or applicatin default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + 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 + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + credentials=self._credentials, + credentials_file=credentials_file, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "monitoring.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: str = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + scopes = scopes or cls.AUTH_SCOPES + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service. + """ + return self._grpc_channel + + @property + def query_time_series( + self, + ) -> Callable[ + [metric_service.QueryTimeSeriesRequest], metric_service.QueryTimeSeriesResponse + ]: + r"""Return a callable for the query time series method over gRPC. + + Queries time series using Monitoring Query Language. + This method does not require a Workspace. + + Returns: + Callable[[~.QueryTimeSeriesRequest], + ~.QueryTimeSeriesResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "query_time_series" not in self._stubs: + self._stubs["query_time_series"] = self.grpc_channel.unary_unary( + "/google.monitoring.v3.QueryService/QueryTimeSeries", + request_serializer=metric_service.QueryTimeSeriesRequest.serialize, + response_deserializer=metric_service.QueryTimeSeriesResponse.deserialize, + ) + return self._stubs["query_time_series"] + + +__all__ = ("QueryServiceGrpcTransport",) diff --git a/google/cloud/monitoring_v3/services/query_service/transports/grpc_asyncio.py b/google/cloud/monitoring_v3/services/query_service/transports/grpc_asyncio.py new file mode 100644 index 00000000..eaaa49b1 --- /dev/null +++ b/google/cloud/monitoring_v3/services/query_service/transports/grpc_asyncio.py @@ -0,0 +1,261 @@ +# -*- 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. +# + +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple + +from google.api_core import gapic_v1 # type: ignore +from google.api_core import grpc_helpers_async # type: ignore +from google import auth # type: ignore +from google.auth import credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore + +import grpc # type: ignore +from grpc.experimental import aio # type: ignore + +from google.cloud.monitoring_v3.types import metric_service + +from .base import QueryServiceTransport, DEFAULT_CLIENT_INFO +from .grpc import QueryServiceGrpcTransport + + +class QueryServiceGrpcAsyncIOTransport(QueryServiceTransport): + """gRPC AsyncIO backend transport for QueryService. + + The QueryService API is used to manage time series data in + Stackdriver Monitoring. Time series data is a collection of data + points that describes the time-varying values of a metric. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "monitoring.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> aio.Channel: + """Create and return a gRPC AsyncIO channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + aio.Channel: A gRPC AsyncIO channel object. + """ + scopes = scopes or cls.AUTH_SCOPES + return grpc_helpers_async.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + **kwargs, + ) + + def __init__( + self, + *, + host: str = "monitoring.googleapis.com", + credentials: credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: aio.Channel = None, + 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: + """Instantiate the transport. + + Args: + host (Optional[str]): The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[aio.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or applicatin default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + 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 + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + credentials=self._credentials, + credentials_file=credentials_file, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @property + def grpc_channel(self) -> aio.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Return the channel from cache. + return self._grpc_channel + + @property + def query_time_series( + self, + ) -> Callable[ + [metric_service.QueryTimeSeriesRequest], + Awaitable[metric_service.QueryTimeSeriesResponse], + ]: + r"""Return a callable for the query time series method over gRPC. + + Queries time series using Monitoring Query Language. + This method does not require a Workspace. + + Returns: + Callable[[~.QueryTimeSeriesRequest], + Awaitable[~.QueryTimeSeriesResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "query_time_series" not in self._stubs: + self._stubs["query_time_series"] = self.grpc_channel.unary_unary( + "/google.monitoring.v3.QueryService/QueryTimeSeries", + request_serializer=metric_service.QueryTimeSeriesRequest.serialize, + response_deserializer=metric_service.QueryTimeSeriesResponse.deserialize, + ) + return self._stubs["query_time_series"] + + +__all__ = ("QueryServiceGrpcAsyncIOTransport",) diff --git a/google/cloud/monitoring_v3/services/service_monitoring_service/async_client.py b/google/cloud/monitoring_v3/services/service_monitoring_service/async_client.py index 839e9f16..9e2e7519 100644 --- a/google/cloud/monitoring_v3/services/service_monitoring_service/async_client.py +++ b/google/cloud/monitoring_v3/services/service_monitoring_service/async_client.py @@ -94,7 +94,36 @@ class ServiceMonitoringServiceAsyncClient: ServiceMonitoringServiceClient.parse_common_location_path ) - from_service_account_file = ServiceMonitoringServiceClient.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: + ServiceMonitoringServiceAsyncClient: The constructed client. + """ + return ServiceMonitoringServiceClient.from_service_account_info.__func__(ServiceMonitoringServiceAsyncClient, 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: + ServiceMonitoringServiceAsyncClient: The constructed client. + """ + return ServiceMonitoringServiceClient.from_service_account_file.__func__(ServiceMonitoringServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -172,7 +201,7 @@ async def create_service( r"""Create a ``Service``. Args: - request (:class:`~.service_service.CreateServiceRequest`): + request (:class:`google.cloud.monitoring_v3.types.CreateServiceRequest`): The request object. The `CreateService` request. parent (:class:`str`): Required. Resource name of the parent workspace. The @@ -181,10 +210,11 @@ async def create_service( :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - service (:class:`~.gm_service.Service`): + service (:class:`google.cloud.monitoring_v3.types.Service`): Required. The ``Service`` to create. This corresponds to the ``service`` field on the ``request`` instance; if ``request`` is provided, this @@ -197,14 +227,13 @@ async def create_service( sent along with the request as metadata. Returns: - ~.gm_service.Service: - A ``Service`` is a discrete, autonomous, and - network-accessible unit, designed to solve an individual - concern - (`Wikipedia `__). - In Cloud Monitoring, a ``Service`` acts as the root - resource under which operational aspects of the service - are accessible. + google.cloud.monitoring_v3.types.Service: + A Service is a discrete, autonomous, and network-accessible unit, designed + to solve an individual concern + ([Wikipedia](https://en.wikipedia.org/wiki/Service-orientation)). + In Cloud Monitoring, a Service acts as the root + resource under which operational aspects of the + service are accessible. """ # Create or coerce a protobuf request object. @@ -259,7 +288,7 @@ async def get_service( r"""Get the named ``Service``. Args: - request (:class:`~.service_service.GetServiceRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetServiceRequest`): The request object. The `GetService` request. name (:class:`str`): Required. Resource name of the ``Service``. The format @@ -268,6 +297,7 @@ async def get_service( :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -279,14 +309,13 @@ async def get_service( sent along with the request as metadata. Returns: - ~.service.Service: - A ``Service`` is a discrete, autonomous, and - network-accessible unit, designed to solve an individual - concern - (`Wikipedia `__). - In Cloud Monitoring, a ``Service`` acts as the root - resource under which operational aspects of the service - are accessible. + google.cloud.monitoring_v3.types.Service: + A Service is a discrete, autonomous, and network-accessible unit, designed + to solve an individual concern + ([Wikipedia](https://en.wikipedia.org/wiki/Service-orientation)). + In Cloud Monitoring, a Service acts as the root + resource under which operational aspects of the + service are accessible. """ # Create or coerce a protobuf request object. @@ -318,6 +347,7 @@ async def get_service( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -347,7 +377,7 @@ async def list_services( r"""List ``Service``\ s for this workspace. Args: - request (:class:`~.service_service.ListServicesRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListServicesRequest`): The request object. The `ListServices` request. parent (:class:`str`): Required. Resource name of the parent containing the @@ -358,6 +388,7 @@ async def list_services( projects/[PROJECT_ID_OR_NUMBER] workspaces/[HOST_PROJECT_ID_OR_NUMBER] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -369,8 +400,8 @@ async def list_services( sent along with the request as metadata. Returns: - ~.pagers.ListServicesAsyncPager: - The ``ListServices`` response. + google.cloud.monitoring_v3.services.service_monitoring_service.pagers.ListServicesAsyncPager: + The ListServices response. Iterating over this object will yield results and resolve additional pages automatically. @@ -405,6 +436,7 @@ async def list_services( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -440,11 +472,12 @@ async def update_service( r"""Update this ``Service``. Args: - request (:class:`~.service_service.UpdateServiceRequest`): + request (:class:`google.cloud.monitoring_v3.types.UpdateServiceRequest`): The request object. The `UpdateService` request. - service (:class:`~.gm_service.Service`): + service (:class:`google.cloud.monitoring_v3.types.Service`): Required. The ``Service`` to draw updates from. The given ``name`` specifies the resource to update. + This corresponds to the ``service`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -456,14 +489,13 @@ async def update_service( sent along with the request as metadata. Returns: - ~.gm_service.Service: - A ``Service`` is a discrete, autonomous, and - network-accessible unit, designed to solve an individual - concern - (`Wikipedia `__). - In Cloud Monitoring, a ``Service`` acts as the root - resource under which operational aspects of the service - are accessible. + google.cloud.monitoring_v3.types.Service: + A Service is a discrete, autonomous, and network-accessible unit, designed + to solve an individual concern + ([Wikipedia](https://en.wikipedia.org/wiki/Service-orientation)). + In Cloud Monitoring, a Service acts as the root + resource under which operational aspects of the + service are accessible. """ # Create or coerce a protobuf request object. @@ -518,7 +550,7 @@ async def delete_service( r"""Soft delete this ``Service``. Args: - request (:class:`~.service_service.DeleteServiceRequest`): + request (:class:`google.cloud.monitoring_v3.types.DeleteServiceRequest`): The request object. The `DeleteService` request. name (:class:`str`): Required. Resource name of the ``Service`` to delete. @@ -527,6 +559,7 @@ async def delete_service( :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -566,6 +599,7 @@ async def delete_service( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -595,7 +629,7 @@ async def create_service_level_objective( r"""Create a ``ServiceLevelObjective`` for the given ``Service``. Args: - request (:class:`~.service_service.CreateServiceLevelObjectiveRequest`): + request (:class:`google.cloud.monitoring_v3.types.CreateServiceLevelObjectiveRequest`): The request object. The `CreateServiceLevelObjective` request. parent (:class:`str`): @@ -605,13 +639,15 @@ async def create_service_level_objective( :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - service_level_objective (:class:`~.service.ServiceLevelObjective`): + service_level_objective (:class:`google.cloud.monitoring_v3.types.ServiceLevelObjective`): Required. The ``ServiceLevelObjective`` to create. The provided ``name`` will be respected if no ``ServiceLevelObjective`` exists with this name. + This corresponds to the ``service_level_objective`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -623,7 +659,7 @@ async def create_service_level_objective( sent along with the request as metadata. Returns: - ~.service.ServiceLevelObjective: + google.cloud.monitoring_v3.types.ServiceLevelObjective: A Service-Level Objective (SLO) describes a level of desired good service. It consists of a service-level @@ -691,7 +727,7 @@ async def get_service_level_objective( r"""Get a ``ServiceLevelObjective`` by name. Args: - request (:class:`~.service_service.GetServiceLevelObjectiveRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetServiceLevelObjectiveRequest`): The request object. The `GetServiceLevelObjective` request. name (:class:`str`): @@ -701,6 +737,7 @@ async def get_service_level_objective( :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID]/serviceLevelObjectives/[SLO_NAME] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -712,7 +749,7 @@ async def get_service_level_objective( sent along with the request as metadata. Returns: - ~.service.ServiceLevelObjective: + google.cloud.monitoring_v3.types.ServiceLevelObjective: A Service-Level Objective (SLO) describes a level of desired good service. It consists of a service-level @@ -757,6 +794,7 @@ async def get_service_level_objective( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -786,7 +824,7 @@ async def list_service_level_objectives( r"""List the ``ServiceLevelObjective``\ s for the given ``Service``. Args: - request (:class:`~.service_service.ListServiceLevelObjectivesRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListServiceLevelObjectivesRequest`): The request object. The `ListServiceLevelObjectives` request. parent (:class:`str`): @@ -798,6 +836,7 @@ async def list_service_level_objectives( projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID] workspaces/[HOST_PROJECT_ID_OR_NUMBER]/services/- + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -809,8 +848,8 @@ async def list_service_level_objectives( sent along with the request as metadata. Returns: - ~.pagers.ListServiceLevelObjectivesAsyncPager: - The ``ListServiceLevelObjectives`` response. + google.cloud.monitoring_v3.services.service_monitoring_service.pagers.ListServiceLevelObjectivesAsyncPager: + The ListServiceLevelObjectives response. Iterating over this object will yield results and resolve additional pages automatically. @@ -845,6 +884,7 @@ async def list_service_level_objectives( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -880,13 +920,14 @@ async def update_service_level_objective( r"""Update the given ``ServiceLevelObjective``. Args: - request (:class:`~.service_service.UpdateServiceLevelObjectiveRequest`): + request (:class:`google.cloud.monitoring_v3.types.UpdateServiceLevelObjectiveRequest`): The request object. The `UpdateServiceLevelObjective` request. - service_level_objective (:class:`~.service.ServiceLevelObjective`): + service_level_objective (:class:`google.cloud.monitoring_v3.types.ServiceLevelObjective`): Required. The ``ServiceLevelObjective`` to draw updates from. The given ``name`` specifies the resource to update. + This corresponds to the ``service_level_objective`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -898,7 +939,7 @@ async def update_service_level_objective( sent along with the request as metadata. Returns: - ~.service.ServiceLevelObjective: + google.cloud.monitoring_v3.types.ServiceLevelObjective: A Service-Level Objective (SLO) describes a level of desired good service. It consists of a service-level @@ -971,7 +1012,7 @@ async def delete_service_level_objective( r"""Delete the given ``ServiceLevelObjective``. Args: - request (:class:`~.service_service.DeleteServiceLevelObjectiveRequest`): + request (:class:`google.cloud.monitoring_v3.types.DeleteServiceLevelObjectiveRequest`): The request object. The `DeleteServiceLevelObjective` request. name (:class:`str`): @@ -981,6 +1022,7 @@ async def delete_service_level_objective( :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID]/serviceLevelObjectives/[SLO_NAME] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1020,6 +1062,7 @@ async def delete_service_level_objective( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/monitoring_v3/services/service_monitoring_service/client.py b/google/cloud/monitoring_v3/services/service_monitoring_service/client.py index e5837ba6..3078d125 100644 --- a/google/cloud/monitoring_v3/services/service_monitoring_service/client.py +++ b/google/cloud/monitoring_v3/services/service_monitoring_service/client.py @@ -120,6 +120,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: + ServiceMonitoringServiceClient: 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 @@ -132,7 +148,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. + ServiceMonitoringServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -257,10 +273,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, ~.ServiceMonitoringServiceTransport]): The + transport (Union[str, ServiceMonitoringServiceTransport]): 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 @@ -296,21 +312,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: @@ -353,7 +365,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, ) @@ -371,19 +383,20 @@ def create_service( r"""Create a ``Service``. Args: - request (:class:`~.service_service.CreateServiceRequest`): + request (google.cloud.monitoring_v3.types.CreateServiceRequest): The request object. The `CreateService` request. - parent (:class:`str`): + parent (str): Required. Resource name of the parent workspace. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - service (:class:`~.gm_service.Service`): + service (google.cloud.monitoring_v3.types.Service): Required. The ``Service`` to create. This corresponds to the ``service`` field on the ``request`` instance; if ``request`` is provided, this @@ -396,14 +409,13 @@ def create_service( sent along with the request as metadata. Returns: - ~.gm_service.Service: - A ``Service`` is a discrete, autonomous, and - network-accessible unit, designed to solve an individual - concern - (`Wikipedia `__). - In Cloud Monitoring, a ``Service`` acts as the root - resource under which operational aspects of the service - are accessible. + google.cloud.monitoring_v3.types.Service: + A Service is a discrete, autonomous, and network-accessible unit, designed + to solve an individual concern + ([Wikipedia](https://en.wikipedia.org/wiki/Service-orientation)). + In Cloud Monitoring, a Service acts as the root + resource under which operational aspects of the + service are accessible. """ # Create or coerce a protobuf request object. @@ -459,15 +471,16 @@ def get_service( r"""Get the named ``Service``. Args: - request (:class:`~.service_service.GetServiceRequest`): + request (google.cloud.monitoring_v3.types.GetServiceRequest): The request object. The `GetService` request. - name (:class:`str`): + name (str): Required. Resource name of the ``Service``. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -479,14 +492,13 @@ def get_service( sent along with the request as metadata. Returns: - ~.service.Service: - A ``Service`` is a discrete, autonomous, and - network-accessible unit, designed to solve an individual - concern - (`Wikipedia `__). - In Cloud Monitoring, a ``Service`` acts as the root - resource under which operational aspects of the service - are accessible. + google.cloud.monitoring_v3.types.Service: + A Service is a discrete, autonomous, and network-accessible unit, designed + to solve an individual concern + ([Wikipedia](https://en.wikipedia.org/wiki/Service-orientation)). + In Cloud Monitoring, a Service acts as the root + resource under which operational aspects of the + service are accessible. """ # Create or coerce a protobuf request object. @@ -540,9 +552,9 @@ def list_services( r"""List ``Service``\ s for this workspace. Args: - request (:class:`~.service_service.ListServicesRequest`): + request (google.cloud.monitoring_v3.types.ListServicesRequest): The request object. The `ListServices` request. - parent (:class:`str`): + parent (str): Required. Resource name of the parent containing the listed services, either a project or a Monitoring Workspace. The formats are: @@ -551,6 +563,7 @@ def list_services( projects/[PROJECT_ID_OR_NUMBER] workspaces/[HOST_PROJECT_ID_OR_NUMBER] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -562,8 +575,8 @@ def list_services( sent along with the request as metadata. Returns: - ~.pagers.ListServicesPager: - The ``ListServices`` response. + google.cloud.monitoring_v3.services.service_monitoring_service.pagers.ListServicesPager: + The ListServices response. Iterating over this object will yield results and resolve additional pages automatically. @@ -626,11 +639,12 @@ def update_service( r"""Update this ``Service``. Args: - request (:class:`~.service_service.UpdateServiceRequest`): + request (google.cloud.monitoring_v3.types.UpdateServiceRequest): The request object. The `UpdateService` request. - service (:class:`~.gm_service.Service`): + service (google.cloud.monitoring_v3.types.Service): Required. The ``Service`` to draw updates from. The given ``name`` specifies the resource to update. + This corresponds to the ``service`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -642,14 +656,13 @@ def update_service( sent along with the request as metadata. Returns: - ~.gm_service.Service: - A ``Service`` is a discrete, autonomous, and - network-accessible unit, designed to solve an individual - concern - (`Wikipedia `__). - In Cloud Monitoring, a ``Service`` acts as the root - resource under which operational aspects of the service - are accessible. + google.cloud.monitoring_v3.types.Service: + A Service is a discrete, autonomous, and network-accessible unit, designed + to solve an individual concern + ([Wikipedia](https://en.wikipedia.org/wiki/Service-orientation)). + In Cloud Monitoring, a Service acts as the root + resource under which operational aspects of the + service are accessible. """ # Create or coerce a protobuf request object. @@ -705,15 +718,16 @@ def delete_service( r"""Soft delete this ``Service``. Args: - request (:class:`~.service_service.DeleteServiceRequest`): + request (google.cloud.monitoring_v3.types.DeleteServiceRequest): The request object. The `DeleteService` request. - name (:class:`str`): + name (str): Required. Resource name of the ``Service`` to delete. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -775,23 +789,25 @@ def create_service_level_objective( r"""Create a ``ServiceLevelObjective`` for the given ``Service``. Args: - request (:class:`~.service_service.CreateServiceLevelObjectiveRequest`): + request (google.cloud.monitoring_v3.types.CreateServiceLevelObjectiveRequest): The request object. The `CreateServiceLevelObjective` request. - parent (:class:`str`): + parent (str): Required. Resource name of the parent ``Service``. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - service_level_objective (:class:`~.service.ServiceLevelObjective`): + service_level_objective (google.cloud.monitoring_v3.types.ServiceLevelObjective): Required. The ``ServiceLevelObjective`` to create. The provided ``name`` will be respected if no ``ServiceLevelObjective`` exists with this name. + This corresponds to the ``service_level_objective`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -803,7 +819,7 @@ def create_service_level_objective( sent along with the request as metadata. Returns: - ~.service.ServiceLevelObjective: + google.cloud.monitoring_v3.types.ServiceLevelObjective: A Service-Level Objective (SLO) describes a level of desired good service. It consists of a service-level @@ -874,16 +890,17 @@ def get_service_level_objective( r"""Get a ``ServiceLevelObjective`` by name. Args: - request (:class:`~.service_service.GetServiceLevelObjectiveRequest`): + request (google.cloud.monitoring_v3.types.GetServiceLevelObjectiveRequest): The request object. The `GetServiceLevelObjective` request. - name (:class:`str`): + name (str): Required. Resource name of the ``ServiceLevelObjective`` to get. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID]/serviceLevelObjectives/[SLO_NAME] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -895,7 +912,7 @@ def get_service_level_objective( sent along with the request as metadata. Returns: - ~.service.ServiceLevelObjective: + google.cloud.monitoring_v3.types.ServiceLevelObjective: A Service-Level Objective (SLO) describes a level of desired good service. It consists of a service-level @@ -964,10 +981,10 @@ def list_service_level_objectives( r"""List the ``ServiceLevelObjective``\ s for the given ``Service``. Args: - request (:class:`~.service_service.ListServiceLevelObjectivesRequest`): + request (google.cloud.monitoring_v3.types.ListServiceLevelObjectivesRequest): The request object. The `ListServiceLevelObjectives` request. - parent (:class:`str`): + parent (str): Required. Resource name of the parent containing the listed SLOs, either a project or a Monitoring Workspace. The formats are: @@ -976,6 +993,7 @@ def list_service_level_objectives( projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID] workspaces/[HOST_PROJECT_ID_OR_NUMBER]/services/- + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -987,8 +1005,8 @@ def list_service_level_objectives( sent along with the request as metadata. Returns: - ~.pagers.ListServiceLevelObjectivesPager: - The ``ListServiceLevelObjectives`` response. + google.cloud.monitoring_v3.services.service_monitoring_service.pagers.ListServiceLevelObjectivesPager: + The ListServiceLevelObjectives response. Iterating over this object will yield results and resolve additional pages automatically. @@ -1053,13 +1071,14 @@ def update_service_level_objective( r"""Update the given ``ServiceLevelObjective``. Args: - request (:class:`~.service_service.UpdateServiceLevelObjectiveRequest`): + request (google.cloud.monitoring_v3.types.UpdateServiceLevelObjectiveRequest): The request object. The `UpdateServiceLevelObjective` request. - service_level_objective (:class:`~.service.ServiceLevelObjective`): + service_level_objective (google.cloud.monitoring_v3.types.ServiceLevelObjective): Required. The ``ServiceLevelObjective`` to draw updates from. The given ``name`` specifies the resource to update. + This corresponds to the ``service_level_objective`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -1071,7 +1090,7 @@ def update_service_level_objective( sent along with the request as metadata. Returns: - ~.service.ServiceLevelObjective: + google.cloud.monitoring_v3.types.ServiceLevelObjective: A Service-Level Objective (SLO) describes a level of desired good service. It consists of a service-level @@ -1147,16 +1166,17 @@ def delete_service_level_objective( r"""Delete the given ``ServiceLevelObjective``. Args: - request (:class:`~.service_service.DeleteServiceLevelObjectiveRequest`): + request (google.cloud.monitoring_v3.types.DeleteServiceLevelObjectiveRequest): The request object. The `DeleteServiceLevelObjective` request. - name (:class:`str`): + name (str): Required. Resource name of the ``ServiceLevelObjective`` to delete. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID]/serviceLevelObjectives/[SLO_NAME] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. diff --git a/google/cloud/monitoring_v3/services/service_monitoring_service/pagers.py b/google/cloud/monitoring_v3/services/service_monitoring_service/pagers.py index b31caf95..8af3947c 100644 --- a/google/cloud/monitoring_v3/services/service_monitoring_service/pagers.py +++ b/google/cloud/monitoring_v3/services/service_monitoring_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.monitoring_v3.types import service from google.cloud.monitoring_v3.types import service_service @@ -25,7 +34,7 @@ class ListServicesPager: """A pager for iterating through ``list_services`` requests. This class thinly wraps an initial - :class:`~.service_service.ListServicesResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListServicesResponse` object, and provides an ``__iter__`` method to iterate through its ``services`` field. @@ -34,7 +43,7 @@ class ListServicesPager: through the ``services`` field on the corresponding responses. - All the usual :class:`~.service_service.ListServicesResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListServicesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -52,9 +61,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.service_service.ListServicesRequest`): + request (google.cloud.monitoring_v3.types.ListServicesRequest): The initial request object. - response (:class:`~.service_service.ListServicesResponse`): + response (google.cloud.monitoring_v3.types.ListServicesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -87,7 +96,7 @@ class ListServicesAsyncPager: """A pager for iterating through ``list_services`` requests. This class thinly wraps an initial - :class:`~.service_service.ListServicesResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListServicesResponse` object, and provides an ``__aiter__`` method to iterate through its ``services`` field. @@ -96,7 +105,7 @@ class ListServicesAsyncPager: through the ``services`` field on the corresponding responses. - All the usual :class:`~.service_service.ListServicesResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListServicesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -114,9 +123,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.service_service.ListServicesRequest`): + request (google.cloud.monitoring_v3.types.ListServicesRequest): The initial request object. - response (:class:`~.service_service.ListServicesResponse`): + response (google.cloud.monitoring_v3.types.ListServicesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -153,7 +162,7 @@ class ListServiceLevelObjectivesPager: """A pager for iterating through ``list_service_level_objectives`` requests. This class thinly wraps an initial - :class:`~.service_service.ListServiceLevelObjectivesResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListServiceLevelObjectivesResponse` object, and provides an ``__iter__`` method to iterate through its ``service_level_objectives`` field. @@ -162,7 +171,7 @@ class ListServiceLevelObjectivesPager: through the ``service_level_objectives`` field on the corresponding responses. - All the usual :class:`~.service_service.ListServiceLevelObjectivesResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListServiceLevelObjectivesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -180,9 +189,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.service_service.ListServiceLevelObjectivesRequest`): + request (google.cloud.monitoring_v3.types.ListServiceLevelObjectivesRequest): The initial request object. - response (:class:`~.service_service.ListServiceLevelObjectivesResponse`): + response (google.cloud.monitoring_v3.types.ListServiceLevelObjectivesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -215,7 +224,7 @@ class ListServiceLevelObjectivesAsyncPager: """A pager for iterating through ``list_service_level_objectives`` requests. This class thinly wraps an initial - :class:`~.service_service.ListServiceLevelObjectivesResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListServiceLevelObjectivesResponse` object, and provides an ``__aiter__`` method to iterate through its ``service_level_objectives`` field. @@ -224,7 +233,7 @@ class ListServiceLevelObjectivesAsyncPager: through the ``service_level_objectives`` field on the corresponding responses. - All the usual :class:`~.service_service.ListServiceLevelObjectivesResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListServiceLevelObjectivesResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -244,9 +253,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.service_service.ListServiceLevelObjectivesRequest`): + request (google.cloud.monitoring_v3.types.ListServiceLevelObjectivesRequest): The initial request object. - response (:class:`~.service_service.ListServiceLevelObjectivesResponse`): + response (google.cloud.monitoring_v3.types.ListServiceLevelObjectivesResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/monitoring_v3/services/service_monitoring_service/transports/base.py b/google/cloud/monitoring_v3/services/service_monitoring_service/transports/base.py index 8d2a8b15..39fddfd3 100644 --- a/google/cloud/monitoring_v3/services/service_monitoring_service/transports/base.py +++ b/google/cloud/monitoring_v3/services/service_monitoring_service/transports/base.py @@ -76,10 +76,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -87,6 +87,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -96,20 +99,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -125,6 +125,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -138,6 +139,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -154,6 +156,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -172,6 +175,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -185,6 +189,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -203,6 +208,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, diff --git a/google/cloud/monitoring_v3/services/service_monitoring_service/transports/grpc.py b/google/cloud/monitoring_v3/services/service_monitoring_service/transports/grpc.py index e6a650e1..e08155e7 100644 --- a/google/cloud/monitoring_v3/services/service_monitoring_service/transports/grpc.py +++ b/google/cloud/monitoring_v3/services/service_monitoring_service/transports/grpc.py @@ -63,6 +63,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: @@ -93,6 +94,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,72 +112,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -180,17 +173,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -204,7 +188,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If diff --git a/google/cloud/monitoring_v3/services/service_monitoring_service/transports/grpc_asyncio.py b/google/cloud/monitoring_v3/services/service_monitoring_service/transports/grpc_asyncio.py index 19c95873..3e562dc8 100644 --- a/google/cloud/monitoring_v3/services/service_monitoring_service/transports/grpc_asyncio.py +++ b/google/cloud/monitoring_v3/services/service_monitoring_service/transports/grpc_asyncio.py @@ -67,7 +67,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -107,6 +107,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: @@ -138,12 +139,16 @@ 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): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -152,72 +157,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -225,17 +218,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/monitoring_v3/services/uptime_check_service/async_client.py b/google/cloud/monitoring_v3/services/uptime_check_service/async_client.py index e01a219d..e8fd9937 100644 --- a/google/cloud/monitoring_v3/services/uptime_check_service/async_client.py +++ b/google/cloud/monitoring_v3/services/uptime_check_service/async_client.py @@ -91,7 +91,36 @@ class UptimeCheckServiceAsyncClient: UptimeCheckServiceClient.parse_common_location_path ) - from_service_account_file = UptimeCheckServiceClient.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: + UptimeCheckServiceAsyncClient: The constructed client. + """ + return UptimeCheckServiceClient.from_service_account_info.__func__(UptimeCheckServiceAsyncClient, 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: + UptimeCheckServiceAsyncClient: The constructed client. + """ + return UptimeCheckServiceClient.from_service_account_file.__func__(UptimeCheckServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -170,7 +199,7 @@ async def list_uptime_check_configs( configurations). Args: - request (:class:`~.uptime_service.ListUptimeCheckConfigsRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListUptimeCheckConfigsRequest`): The request object. The protocol for the `ListUptimeCheckConfigs` request. parent (:class:`str`): @@ -180,6 +209,7 @@ async def list_uptime_check_configs( :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -191,9 +221,8 @@ async def list_uptime_check_configs( sent along with the request as metadata. Returns: - ~.pagers.ListUptimeCheckConfigsAsyncPager: - The protocol for the ``ListUptimeCheckConfigs`` - response. + google.cloud.monitoring_v3.services.uptime_check_service.pagers.ListUptimeCheckConfigsAsyncPager: + The protocol for the ListUptimeCheckConfigs response. Iterating over this object will yield results and resolve additional pages automatically. @@ -228,6 +257,7 @@ async def list_uptime_check_configs( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -263,7 +293,7 @@ async def get_uptime_check_config( r"""Gets a single Uptime check configuration. Args: - request (:class:`~.uptime_service.GetUptimeCheckConfigRequest`): + request (:class:`google.cloud.monitoring_v3.types.GetUptimeCheckConfigRequest`): The request object. The protocol for the `GetUptimeCheckConfig` request. name (:class:`str`): @@ -273,6 +303,7 @@ async def get_uptime_check_config( :: projects/[PROJECT_ID_OR_NUMBER]/uptimeCheckConfigs/[UPTIME_CHECK_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -284,7 +315,7 @@ async def get_uptime_check_config( sent along with the request as metadata. Returns: - ~.uptime.UptimeCheckConfig: + google.cloud.monitoring_v3.types.UptimeCheckConfig: This message configures which resources and services to monitor for availability. @@ -319,6 +350,7 @@ async def get_uptime_check_config( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -349,7 +381,7 @@ async def create_uptime_check_config( r"""Creates a new Uptime check configuration. Args: - request (:class:`~.uptime_service.CreateUptimeCheckConfigRequest`): + request (:class:`google.cloud.monitoring_v3.types.CreateUptimeCheckConfigRequest`): The request object. The protocol for the `CreateUptimeCheckConfig` request. parent (:class:`str`): @@ -359,12 +391,14 @@ async def create_uptime_check_config( :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - uptime_check_config (:class:`~.uptime.UptimeCheckConfig`): + uptime_check_config (:class:`google.cloud.monitoring_v3.types.UptimeCheckConfig`): Required. The new Uptime check configuration. + This corresponds to the ``uptime_check_config`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -376,7 +410,7 @@ async def create_uptime_check_config( sent along with the request as metadata. Returns: - ~.uptime.UptimeCheckConfig: + google.cloud.monitoring_v3.types.UptimeCheckConfig: This message configures which resources and services to monitor for availability. @@ -438,10 +472,10 @@ async def update_uptime_check_config( configuration. Args: - request (:class:`~.uptime_service.UpdateUptimeCheckConfigRequest`): + request (:class:`google.cloud.monitoring_v3.types.UpdateUptimeCheckConfigRequest`): The request object. The protocol for the `UpdateUptimeCheckConfig` request. - uptime_check_config (:class:`~.uptime.UptimeCheckConfig`): + uptime_check_config (:class:`google.cloud.monitoring_v3.types.UptimeCheckConfig`): Required. If an ``updateMask`` has been specified, this field gives the values for the set of fields mentioned in the ``updateMask``. If an ``updateMask`` has not been @@ -455,6 +489,7 @@ async def update_uptime_check_config( The following fields can be updated: ``display_name``, ``http_check``, ``tcp_check``, ``timeout``, ``content_matchers``, and ``selected_regions``. + This corresponds to the ``uptime_check_config`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -466,7 +501,7 @@ async def update_uptime_check_config( sent along with the request as metadata. Returns: - ~.uptime.UptimeCheckConfig: + google.cloud.monitoring_v3.types.UptimeCheckConfig: This message configures which resources and services to monitor for availability. @@ -527,7 +562,7 @@ async def delete_uptime_check_config( that would be rendered invalid by the deletion. Args: - request (:class:`~.uptime_service.DeleteUptimeCheckConfigRequest`): + request (:class:`google.cloud.monitoring_v3.types.DeleteUptimeCheckConfigRequest`): The request object. The protocol for the `DeleteUptimeCheckConfig` request. name (:class:`str`): @@ -537,6 +572,7 @@ async def delete_uptime_check_config( :: projects/[PROJECT_ID_OR_NUMBER]/uptimeCheckConfigs/[UPTIME_CHECK_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -576,6 +612,7 @@ async def delete_uptime_check_config( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, @@ -604,7 +641,7 @@ async def list_uptime_check_ips( from Args: - request (:class:`~.uptime_service.ListUptimeCheckIpsRequest`): + request (:class:`google.cloud.monitoring_v3.types.ListUptimeCheckIpsRequest`): The request object. The protocol for the `ListUptimeCheckIps` request. @@ -615,8 +652,8 @@ async def list_uptime_check_ips( sent along with the request as metadata. Returns: - ~.pagers.ListUptimeCheckIpsAsyncPager: - The protocol for the ``ListUptimeCheckIps`` response. + google.cloud.monitoring_v3.services.uptime_check_service.pagers.ListUptimeCheckIpsAsyncPager: + The protocol for the ListUptimeCheckIps response. Iterating over this object will yield results and resolve additional pages automatically. @@ -637,6 +674,7 @@ async def list_uptime_check_ips( predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=DEFAULT_CLIENT_INFO, diff --git a/google/cloud/monitoring_v3/services/uptime_check_service/client.py b/google/cloud/monitoring_v3/services/uptime_check_service/client.py index be375a82..d7d55120 100644 --- a/google/cloud/monitoring_v3/services/uptime_check_service/client.py +++ b/google/cloud/monitoring_v3/services/uptime_check_service/client.py @@ -123,6 +123,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: + UptimeCheckServiceClient: 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 @@ -135,7 +151,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. + UptimeCheckServiceClient: The constructed client. """ credentials = service_account.Credentials.from_service_account_file(filename) kwargs["credentials"] = credentials @@ -243,10 +259,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, ~.UptimeCheckServiceTransport]): The + transport (Union[str, UptimeCheckServiceTransport]): 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 @@ -282,21 +298,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: @@ -339,7 +351,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, ) @@ -358,16 +370,17 @@ def list_uptime_check_configs( configurations). Args: - request (:class:`~.uptime_service.ListUptimeCheckConfigsRequest`): + request (google.cloud.monitoring_v3.types.ListUptimeCheckConfigsRequest): The request object. The protocol for the `ListUptimeCheckConfigs` request. - parent (:class:`str`): + parent (str): Required. The project whose Uptime check configurations are listed. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -379,9 +392,8 @@ def list_uptime_check_configs( sent along with the request as metadata. Returns: - ~.pagers.ListUptimeCheckConfigsPager: - The protocol for the ``ListUptimeCheckConfigs`` - response. + google.cloud.monitoring_v3.services.uptime_check_service.pagers.ListUptimeCheckConfigsPager: + The protocol for the ListUptimeCheckConfigs response. Iterating over this object will yield results and resolve additional pages automatically. @@ -446,16 +458,17 @@ def get_uptime_check_config( r"""Gets a single Uptime check configuration. Args: - request (:class:`~.uptime_service.GetUptimeCheckConfigRequest`): + request (google.cloud.monitoring_v3.types.GetUptimeCheckConfigRequest): The request object. The protocol for the `GetUptimeCheckConfig` request. - name (:class:`str`): + name (str): Required. The Uptime check configuration to retrieve. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/uptimeCheckConfigs/[UPTIME_CHECK_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -467,7 +480,7 @@ def get_uptime_check_config( sent along with the request as metadata. Returns: - ~.uptime.UptimeCheckConfig: + google.cloud.monitoring_v3.types.UptimeCheckConfig: This message configures which resources and services to monitor for availability. @@ -525,22 +538,24 @@ def create_uptime_check_config( r"""Creates a new Uptime check configuration. Args: - request (:class:`~.uptime_service.CreateUptimeCheckConfigRequest`): + request (google.cloud.monitoring_v3.types.CreateUptimeCheckConfigRequest): The request object. The protocol for the `CreateUptimeCheckConfig` request. - parent (:class:`str`): + parent (str): Required. The project in which to create the Uptime check. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + This corresponds to the ``parent`` field on the ``request`` instance; if ``request`` is provided, this should not be set. - uptime_check_config (:class:`~.uptime.UptimeCheckConfig`): + uptime_check_config (google.cloud.monitoring_v3.types.UptimeCheckConfig): Required. The new Uptime check configuration. + This corresponds to the ``uptime_check_config`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -552,7 +567,7 @@ def create_uptime_check_config( sent along with the request as metadata. Returns: - ~.uptime.UptimeCheckConfig: + google.cloud.monitoring_v3.types.UptimeCheckConfig: This message configures which resources and services to monitor for availability. @@ -617,10 +632,10 @@ def update_uptime_check_config( configuration. Args: - request (:class:`~.uptime_service.UpdateUptimeCheckConfigRequest`): + request (google.cloud.monitoring_v3.types.UpdateUptimeCheckConfigRequest): The request object. The protocol for the `UpdateUptimeCheckConfig` request. - uptime_check_config (:class:`~.uptime.UptimeCheckConfig`): + uptime_check_config (google.cloud.monitoring_v3.types.UptimeCheckConfig): Required. If an ``updateMask`` has been specified, this field gives the values for the set of fields mentioned in the ``updateMask``. If an ``updateMask`` has not been @@ -634,6 +649,7 @@ def update_uptime_check_config( The following fields can be updated: ``display_name``, ``http_check``, ``tcp_check``, ``timeout``, ``content_matchers``, and ``selected_regions``. + This corresponds to the ``uptime_check_config`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -645,7 +661,7 @@ def update_uptime_check_config( sent along with the request as metadata. Returns: - ~.uptime.UptimeCheckConfig: + google.cloud.monitoring_v3.types.UptimeCheckConfig: This message configures which resources and services to monitor for availability. @@ -709,16 +725,17 @@ def delete_uptime_check_config( that would be rendered invalid by the deletion. Args: - request (:class:`~.uptime_service.DeleteUptimeCheckConfigRequest`): + request (google.cloud.monitoring_v3.types.DeleteUptimeCheckConfigRequest): The request object. The protocol for the `DeleteUptimeCheckConfig` request. - name (:class:`str`): + name (str): Required. The Uptime check configuration to delete. The format is: :: projects/[PROJECT_ID_OR_NUMBER]/uptimeCheckConfigs/[UPTIME_CHECK_ID] + This corresponds to the ``name`` field on the ``request`` instance; if ``request`` is provided, this should not be set. @@ -781,7 +798,7 @@ def list_uptime_check_ips( from Args: - request (:class:`~.uptime_service.ListUptimeCheckIpsRequest`): + request (google.cloud.monitoring_v3.types.ListUptimeCheckIpsRequest): The request object. The protocol for the `ListUptimeCheckIps` request. @@ -792,8 +809,8 @@ def list_uptime_check_ips( sent along with the request as metadata. Returns: - ~.pagers.ListUptimeCheckIpsPager: - The protocol for the ``ListUptimeCheckIps`` response. + google.cloud.monitoring_v3.services.uptime_check_service.pagers.ListUptimeCheckIpsPager: + The protocol for the ListUptimeCheckIps response. Iterating over this object will yield results and resolve additional pages automatically. diff --git a/google/cloud/monitoring_v3/services/uptime_check_service/pagers.py b/google/cloud/monitoring_v3/services/uptime_check_service/pagers.py index 6d370226..ec69778f 100644 --- a/google/cloud/monitoring_v3/services/uptime_check_service/pagers.py +++ b/google/cloud/monitoring_v3/services/uptime_check_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.monitoring_v3.types import uptime from google.cloud.monitoring_v3.types import uptime_service @@ -25,7 +34,7 @@ class ListUptimeCheckConfigsPager: """A pager for iterating through ``list_uptime_check_configs`` requests. This class thinly wraps an initial - :class:`~.uptime_service.ListUptimeCheckConfigsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListUptimeCheckConfigsResponse` object, and provides an ``__iter__`` method to iterate through its ``uptime_check_configs`` field. @@ -34,7 +43,7 @@ class ListUptimeCheckConfigsPager: through the ``uptime_check_configs`` field on the corresponding responses. - All the usual :class:`~.uptime_service.ListUptimeCheckConfigsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListUptimeCheckConfigsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -52,9 +61,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.uptime_service.ListUptimeCheckConfigsRequest`): + request (google.cloud.monitoring_v3.types.ListUptimeCheckConfigsRequest): The initial request object. - response (:class:`~.uptime_service.ListUptimeCheckConfigsResponse`): + response (google.cloud.monitoring_v3.types.ListUptimeCheckConfigsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -87,7 +96,7 @@ class ListUptimeCheckConfigsAsyncPager: """A pager for iterating through ``list_uptime_check_configs`` requests. This class thinly wraps an initial - :class:`~.uptime_service.ListUptimeCheckConfigsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListUptimeCheckConfigsResponse` object, and provides an ``__aiter__`` method to iterate through its ``uptime_check_configs`` field. @@ -96,7 +105,7 @@ class ListUptimeCheckConfigsAsyncPager: through the ``uptime_check_configs`` field on the corresponding responses. - All the usual :class:`~.uptime_service.ListUptimeCheckConfigsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListUptimeCheckConfigsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -114,9 +123,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.uptime_service.ListUptimeCheckConfigsRequest`): + request (google.cloud.monitoring_v3.types.ListUptimeCheckConfigsRequest): The initial request object. - response (:class:`~.uptime_service.ListUptimeCheckConfigsResponse`): + response (google.cloud.monitoring_v3.types.ListUptimeCheckConfigsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -155,7 +164,7 @@ class ListUptimeCheckIpsPager: """A pager for iterating through ``list_uptime_check_ips`` requests. This class thinly wraps an initial - :class:`~.uptime_service.ListUptimeCheckIpsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListUptimeCheckIpsResponse` object, and provides an ``__iter__`` method to iterate through its ``uptime_check_ips`` field. @@ -164,7 +173,7 @@ class ListUptimeCheckIpsPager: through the ``uptime_check_ips`` field on the corresponding responses. - All the usual :class:`~.uptime_service.ListUptimeCheckIpsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListUptimeCheckIpsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -182,9 +191,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.uptime_service.ListUptimeCheckIpsRequest`): + request (google.cloud.monitoring_v3.types.ListUptimeCheckIpsRequest): The initial request object. - response (:class:`~.uptime_service.ListUptimeCheckIpsResponse`): + response (google.cloud.monitoring_v3.types.ListUptimeCheckIpsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. @@ -217,7 +226,7 @@ class ListUptimeCheckIpsAsyncPager: """A pager for iterating through ``list_uptime_check_ips`` requests. This class thinly wraps an initial - :class:`~.uptime_service.ListUptimeCheckIpsResponse` object, and + :class:`google.cloud.monitoring_v3.types.ListUptimeCheckIpsResponse` object, and provides an ``__aiter__`` method to iterate through its ``uptime_check_ips`` field. @@ -226,7 +235,7 @@ class ListUptimeCheckIpsAsyncPager: through the ``uptime_check_ips`` field on the corresponding responses. - All the usual :class:`~.uptime_service.ListUptimeCheckIpsResponse` + All the usual :class:`google.cloud.monitoring_v3.types.ListUptimeCheckIpsResponse` attributes are available on the pager. If multiple requests are made, only the most recent response is retained, and thus used for attribute lookup. """ @@ -244,9 +253,9 @@ def __init__( Args: method (Callable): The method that was originally called, and which instantiated this pager. - request (:class:`~.uptime_service.ListUptimeCheckIpsRequest`): + request (google.cloud.monitoring_v3.types.ListUptimeCheckIpsRequest): The initial request object. - response (:class:`~.uptime_service.ListUptimeCheckIpsResponse`): + response (google.cloud.monitoring_v3.types.ListUptimeCheckIpsResponse): The initial response object. metadata (Sequence[Tuple[str, str]]): Strings which should be sent along with the request as metadata. diff --git a/google/cloud/monitoring_v3/services/uptime_check_service/transports/base.py b/google/cloud/monitoring_v3/services/uptime_check_service/transports/base.py index 4ab62743..7864e472 100644 --- a/google/cloud/monitoring_v3/services/uptime_check_service/transports/base.py +++ b/google/cloud/monitoring_v3/services/uptime_check_service/transports/base.py @@ -75,10 +75,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. @@ -86,6 +86,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -95,20 +98,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._scopes, quota_project_id=quota_project_id ) # Save the credentials. self._credentials = credentials - # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { @@ -121,6 +121,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -134,6 +135,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -157,6 +159,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, @@ -170,6 +173,7 @@ def _prep_wrapped_messages(self, client_info): predicate=retries.if_exception_type( exceptions.DeadlineExceeded, exceptions.ServiceUnavailable, ), + deadline=30.0, ), default_timeout=30.0, client_info=client_info, diff --git a/google/cloud/monitoring_v3/services/uptime_check_service/transports/grpc.py b/google/cloud/monitoring_v3/services/uptime_check_service/transports/grpc.py index 8143b5b7..43813c1e 100644 --- a/google/cloud/monitoring_v3/services/uptime_check_service/transports/grpc.py +++ b/google/cloud/monitoring_v3/services/uptime_check_service/transports/grpc.py @@ -66,6 +66,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: @@ -96,6 +97,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): @@ -110,72 +115,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -183,17 +176,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -207,7 +191,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If diff --git a/google/cloud/monitoring_v3/services/uptime_check_service/transports/grpc_asyncio.py b/google/cloud/monitoring_v3/services/uptime_check_service/transports/grpc_asyncio.py index 06aa444d..3f9ff388 100644 --- a/google/cloud/monitoring_v3/services/uptime_check_service/transports/grpc_asyncio.py +++ b/google/cloud/monitoring_v3/services/uptime_check_service/transports/grpc_asyncio.py @@ -70,7 +70,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -110,6 +110,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: @@ -141,12 +142,16 @@ 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): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing your own client library. Raises: @@ -155,72 +160,60 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + 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. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. 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 - else api_mtls_endpoint + ":443" - ) + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) - - # Create SSL credentials with client_cert_source or application - # default SSL credentials. - if client_cert_source: - cert, key = client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) else: - ssl_credentials = SslCredentials().ssl_credentials - - # 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_credentials, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials - else: - host = host if ":" in host else host + ":443" + 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 + ) - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -228,17 +221,8 @@ def __init__( ], ) - # Run the base constructor. - super().__init__( - host=host, - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes or self.AUTH_SCOPES, - quota_project_id=quota_project_id, - client_info=client_info, - ) - - self._stubs = {} + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: diff --git a/google/cloud/monitoring_v3/types/__init__.py b/google/cloud/monitoring_v3/types/__init__.py index 6ee5ca44..11955c00 100644 --- a/google/cloud/monitoring_v3/types/__init__.py +++ b/google/cloud/monitoring_v3/types/__init__.py @@ -15,220 +15,220 @@ # limitations under the License. # -from .common import ( - TypedValue, - TimeInterval, - Aggregation, - ComparisonType, - ServiceTier, -) -from .mutation_record import MutationRecord from .alert import AlertPolicy from .alert_service import ( CreateAlertPolicyRequest, + DeleteAlertPolicyRequest, GetAlertPolicyRequest, ListAlertPoliciesRequest, ListAlertPoliciesResponse, UpdateAlertPolicyRequest, - DeleteAlertPolicyRequest, +) +from .common import ( + Aggregation, + TimeInterval, + TypedValue, + ComparisonType, + ServiceTier, ) from .dropped_labels import DroppedLabels from .group import Group from .group_service import ( - ListGroupsRequest, - ListGroupsResponse, - GetGroupRequest, CreateGroupRequest, - UpdateGroupRequest, DeleteGroupRequest, + GetGroupRequest, ListGroupMembersRequest, ListGroupMembersResponse, + ListGroupsRequest, + ListGroupsResponse, + UpdateGroupRequest, ) from .metric import ( - Point, - TimeSeries, - TimeSeriesDescriptor, - TimeSeriesData, LabelValue, + Point, QueryError, TextLocator, + TimeSeries, + TimeSeriesData, + TimeSeriesDescriptor, ) from .metric_service import ( - ListMonitoredResourceDescriptorsRequest, - ListMonitoredResourceDescriptorsResponse, + CreateMetricDescriptorRequest, + CreateTimeSeriesError, + CreateTimeSeriesRequest, + CreateTimeSeriesSummary, + DeleteMetricDescriptorRequest, + GetMetricDescriptorRequest, GetMonitoredResourceDescriptorRequest, ListMetricDescriptorsRequest, ListMetricDescriptorsResponse, - GetMetricDescriptorRequest, - CreateMetricDescriptorRequest, - DeleteMetricDescriptorRequest, + ListMonitoredResourceDescriptorsRequest, + ListMonitoredResourceDescriptorsResponse, ListTimeSeriesRequest, ListTimeSeriesResponse, - CreateTimeSeriesRequest, - CreateTimeSeriesError, - CreateTimeSeriesSummary, + QueryErrorList, QueryTimeSeriesRequest, QueryTimeSeriesResponse, - QueryErrorList, ) +from .mutation_record import MutationRecord from .notification import ( - NotificationChannelDescriptor, NotificationChannel, + NotificationChannelDescriptor, ) from .notification_service import ( + CreateNotificationChannelRequest, + DeleteNotificationChannelRequest, + GetNotificationChannelDescriptorRequest, + GetNotificationChannelRequest, + GetNotificationChannelVerificationCodeRequest, + GetNotificationChannelVerificationCodeResponse, ListNotificationChannelDescriptorsRequest, ListNotificationChannelDescriptorsResponse, - GetNotificationChannelDescriptorRequest, - CreateNotificationChannelRequest, ListNotificationChannelsRequest, ListNotificationChannelsResponse, - GetNotificationChannelRequest, - UpdateNotificationChannelRequest, - DeleteNotificationChannelRequest, SendNotificationChannelVerificationCodeRequest, - GetNotificationChannelVerificationCodeRequest, - GetNotificationChannelVerificationCodeResponse, + UpdateNotificationChannelRequest, VerifyNotificationChannelRequest, ) from .service import ( - Service, - ServiceLevelObjective, - ServiceLevelIndicator, BasicSli, + DistributionCut, Range, RequestBasedSli, + Service, + ServiceLevelIndicator, + ServiceLevelObjective, TimeSeriesRatio, - DistributionCut, WindowsBasedSli, ) from .service_service import ( + CreateServiceLevelObjectiveRequest, CreateServiceRequest, - GetServiceRequest, - ListServicesRequest, - ListServicesResponse, - UpdateServiceRequest, + DeleteServiceLevelObjectiveRequest, DeleteServiceRequest, - CreateServiceLevelObjectiveRequest, GetServiceLevelObjectiveRequest, + GetServiceRequest, ListServiceLevelObjectivesRequest, ListServiceLevelObjectivesResponse, + ListServicesRequest, + ListServicesResponse, UpdateServiceLevelObjectiveRequest, - DeleteServiceLevelObjectiveRequest, + UpdateServiceRequest, ) from .span_context import SpanContext from .uptime import ( InternalChecker, UptimeCheckConfig, UptimeCheckIp, - UptimeCheckRegion, GroupResourceType, + UptimeCheckRegion, ) from .uptime_service import ( - ListUptimeCheckConfigsRequest, - ListUptimeCheckConfigsResponse, - GetUptimeCheckConfigRequest, CreateUptimeCheckConfigRequest, - UpdateUptimeCheckConfigRequest, DeleteUptimeCheckConfigRequest, + GetUptimeCheckConfigRequest, + ListUptimeCheckConfigsRequest, + ListUptimeCheckConfigsResponse, ListUptimeCheckIpsRequest, ListUptimeCheckIpsResponse, + UpdateUptimeCheckConfigRequest, ) __all__ = ( - "TypedValue", - "TimeInterval", - "Aggregation", - "ComparisonType", - "ServiceTier", - "MutationRecord", "AlertPolicy", "CreateAlertPolicyRequest", + "DeleteAlertPolicyRequest", "GetAlertPolicyRequest", "ListAlertPoliciesRequest", "ListAlertPoliciesResponse", "UpdateAlertPolicyRequest", - "DeleteAlertPolicyRequest", + "Aggregation", + "TimeInterval", + "TypedValue", + "ComparisonType", + "ServiceTier", "DroppedLabels", "Group", - "ListGroupsRequest", - "ListGroupsResponse", - "GetGroupRequest", "CreateGroupRequest", - "UpdateGroupRequest", "DeleteGroupRequest", + "GetGroupRequest", "ListGroupMembersRequest", "ListGroupMembersResponse", - "Point", - "TimeSeries", - "TimeSeriesDescriptor", - "TimeSeriesData", + "ListGroupsRequest", + "ListGroupsResponse", + "UpdateGroupRequest", "LabelValue", + "Point", "QueryError", "TextLocator", - "ListMonitoredResourceDescriptorsRequest", - "ListMonitoredResourceDescriptorsResponse", + "TimeSeries", + "TimeSeriesData", + "TimeSeriesDescriptor", + "CreateMetricDescriptorRequest", + "CreateTimeSeriesError", + "CreateTimeSeriesRequest", + "CreateTimeSeriesSummary", + "DeleteMetricDescriptorRequest", + "GetMetricDescriptorRequest", "GetMonitoredResourceDescriptorRequest", "ListMetricDescriptorsRequest", "ListMetricDescriptorsResponse", - "GetMetricDescriptorRequest", - "CreateMetricDescriptorRequest", - "DeleteMetricDescriptorRequest", + "ListMonitoredResourceDescriptorsRequest", + "ListMonitoredResourceDescriptorsResponse", "ListTimeSeriesRequest", "ListTimeSeriesResponse", - "CreateTimeSeriesRequest", - "CreateTimeSeriesError", - "CreateTimeSeriesSummary", + "QueryErrorList", "QueryTimeSeriesRequest", "QueryTimeSeriesResponse", - "QueryErrorList", - "NotificationChannelDescriptor", + "MutationRecord", "NotificationChannel", + "NotificationChannelDescriptor", + "CreateNotificationChannelRequest", + "DeleteNotificationChannelRequest", + "GetNotificationChannelDescriptorRequest", + "GetNotificationChannelRequest", + "GetNotificationChannelVerificationCodeRequest", + "GetNotificationChannelVerificationCodeResponse", "ListNotificationChannelDescriptorsRequest", "ListNotificationChannelDescriptorsResponse", - "GetNotificationChannelDescriptorRequest", - "CreateNotificationChannelRequest", "ListNotificationChannelsRequest", "ListNotificationChannelsResponse", - "GetNotificationChannelRequest", - "UpdateNotificationChannelRequest", - "DeleteNotificationChannelRequest", "SendNotificationChannelVerificationCodeRequest", - "GetNotificationChannelVerificationCodeRequest", - "GetNotificationChannelVerificationCodeResponse", + "UpdateNotificationChannelRequest", "VerifyNotificationChannelRequest", - "Service", - "ServiceLevelObjective", - "ServiceLevelIndicator", "BasicSli", + "DistributionCut", "Range", "RequestBasedSli", + "Service", + "ServiceLevelIndicator", + "ServiceLevelObjective", "TimeSeriesRatio", - "DistributionCut", "WindowsBasedSli", + "CreateServiceLevelObjectiveRequest", "CreateServiceRequest", - "GetServiceRequest", - "ListServicesRequest", - "ListServicesResponse", - "UpdateServiceRequest", + "DeleteServiceLevelObjectiveRequest", "DeleteServiceRequest", - "CreateServiceLevelObjectiveRequest", "GetServiceLevelObjectiveRequest", + "GetServiceRequest", "ListServiceLevelObjectivesRequest", "ListServiceLevelObjectivesResponse", + "ListServicesRequest", + "ListServicesResponse", "UpdateServiceLevelObjectiveRequest", - "DeleteServiceLevelObjectiveRequest", + "UpdateServiceRequest", "SpanContext", "InternalChecker", "UptimeCheckConfig", "UptimeCheckIp", - "UptimeCheckRegion", "GroupResourceType", - "ListUptimeCheckConfigsRequest", - "ListUptimeCheckConfigsResponse", - "GetUptimeCheckConfigRequest", + "UptimeCheckRegion", "CreateUptimeCheckConfigRequest", - "UpdateUptimeCheckConfigRequest", "DeleteUptimeCheckConfigRequest", + "GetUptimeCheckConfigRequest", + "ListUptimeCheckConfigsRequest", + "ListUptimeCheckConfigsResponse", "ListUptimeCheckIpsRequest", "ListUptimeCheckIpsResponse", + "UpdateUptimeCheckConfigRequest", ) diff --git a/google/cloud/monitoring_v3/types/alert.py b/google/cloud/monitoring_v3/types/alert.py index e9a2093e..0d1cd807 100644 --- a/google/cloud/monitoring_v3/types/alert.py +++ b/google/cloud/monitoring_v3/types/alert.py @@ -56,7 +56,7 @@ class AlertPolicy(proto.Message): same display name for multiple policies in the same project. The name is limited to 512 Unicode characters. - documentation (~.alert.AlertPolicy.Documentation): + documentation (google.cloud.monitoring_v3.types.AlertPolicy.Documentation): Documentation that is included with notifications and incidents related to this policy. Best practice is for the documentation @@ -65,7 +65,7 @@ class AlertPolicy(proto.Message): underlying problems detected by the alerting policy. Notification channels that have limited capacity might not show this documentation. - user_labels (Sequence[~.alert.AlertPolicy.UserLabelsEntry]): + user_labels (Sequence[google.cloud.monitoring_v3.types.AlertPolicy.UserLabelsEntry]): User-supplied key/value data to be used for organizing and identifying the ``AlertPolicy`` objects. @@ -74,19 +74,19 @@ class AlertPolicy(proto.Message): is smaller. Labels and values can contain only lowercase letters, numerals, underscores, and dashes. Keys must begin with a letter. - conditions (Sequence[~.alert.AlertPolicy.Condition]): + conditions (Sequence[google.cloud.monitoring_v3.types.AlertPolicy.Condition]): A list of conditions for the policy. The conditions are combined by AND or OR according to the ``combiner`` field. If the combined conditions evaluate to true, then an incident is created. A policy can have from one to six conditions. If ``condition_time_series_query_language`` is present, it must be the only ``condition``. - combiner (~.alert.AlertPolicy.ConditionCombinerType): + combiner (google.cloud.monitoring_v3.types.AlertPolicy.ConditionCombinerType): How to combine the results of multiple conditions to determine if an incident should be opened. If ``condition_time_series_query_language`` is present, this must be ``COMBINE_UNSPECIFIED``. - enabled (~.wrappers.BoolValue): + enabled (google.protobuf.wrappers_pb2.BoolValue): Whether or not the policy is enabled. On write, the default interpretation if unset is that the policy is enabled. On read, clients @@ -95,7 +95,7 @@ class AlertPolicy(proto.Message): always be populated on List and Get operations, unless a field projection has been specified that strips it out. - validity (~.status.Status): + validity (google.rpc.status_pb2.Status): Read-only description of how the alert policy is invalid. OK if the alert policy is valid. If not OK, the alert policy will not generate @@ -115,11 +115,11 @@ class AlertPolicy(proto.Message): :: projects/[PROJECT_ID_OR_NUMBER]/notificationChannels/[CHANNEL_ID] - creation_record (~.gm_mutation_record.MutationRecord): + creation_record (google.cloud.monitoring_v3.types.MutationRecord): A read-only record of the creation of the alerting policy. If provided in a call to create or update, this field will be ignored. - mutation_record (~.gm_mutation_record.MutationRecord): + mutation_record (google.cloud.monitoring_v3.types.MutationRecord): A read-only record of the most recent change to the alerting policy. If provided in a call to create or update, this field will be ignored. @@ -195,12 +195,15 @@ class Condition(proto.Message): incidents. To avoid confusion, don't use the same display name for multiple conditions in the same policy. - condition_threshold (~.alert.AlertPolicy.Condition.MetricThreshold): + condition_threshold (google.cloud.monitoring_v3.types.AlertPolicy.Condition.MetricThreshold): A condition that compares a time series against a threshold. - condition_absent (~.alert.AlertPolicy.Condition.MetricAbsence): + condition_absent (google.cloud.monitoring_v3.types.AlertPolicy.Condition.MetricAbsence): A condition that checks that a time series continues to receive new data points. + condition_monitoring_query_language (google.cloud.monitoring_v3.types.AlertPolicy.Condition.MonitoringQueryLanguageCondition): + A condition that uses the Monitoring Query + Language to define alerts. """ class Trigger(proto.Message): @@ -227,7 +230,7 @@ class MetricThreshold(proto.Message): Attributes: filter (str): - A + Required. A `filter `__ that identifies which time series should be compared with the threshold. @@ -236,11 +239,11 @@ class MetricThreshold(proto.Message): ```ListTimeSeries`` request `__ (that call is useful to verify the time series that will be - retrieved / processed) and must specify the metric type and - optionally may contain restrictions on resource type, - resource labels, and metric labels. This field may not + retrieved / processed). The filter must specify the metric + type and the resource type. Optionally, it can specify + resource labels and metric labels. This field must not exceed 2048 Unicode characters in length. - aggregations (Sequence[~.common.Aggregation]): + aggregations (Sequence[google.cloud.monitoring_v3.types.Aggregation]): Specifies the alignment of data points in individual time series as well as how to combine the retrieved time series together (such as when aggregating multiple streams on each @@ -266,7 +269,7 @@ class MetricThreshold(proto.Message): contain restrictions on resource type, resource labels, and metric labels. This field may not exceed 2048 Unicode characters in length. - denominator_aggregations (Sequence[~.common.Aggregation]): + denominator_aggregations (Sequence[google.cloud.monitoring_v3.types.Aggregation]): Specifies the alignment of data points in individual time series selected by ``denominatorFilter`` as well as how to combine the retrieved time series together (such as when @@ -278,7 +281,7 @@ class MetricThreshold(proto.Message): ``denominator_aggregations`` fields must use the same alignment period and produce time series that have the same periodicity and labels. - comparison (~.common.ComparisonType): + comparison (google.cloud.monitoring_v3.types.ComparisonType): The comparison to apply between the time series (indicated by ``filter`` and ``aggregation``) and the threshold (indicated by ``threshold_value``). The comparison is @@ -290,7 +293,7 @@ class MetricThreshold(proto.Message): threshold_value (float): A value against which to compare the time series. - duration (~.gp_duration.Duration): + duration (google.protobuf.duration_pb2.Duration): The amount of time that a time series must violate the threshold to be considered failing. Currently, only values that are a multiple of a minute--e.g., 0, 60, 120, or 300 @@ -302,7 +305,7 @@ class MetricThreshold(proto.Message): long enough so that a single outlier does not generate spurious alerts, but short enough that unhealthy states are detected and alerted on quickly. - trigger (~.alert.AlertPolicy.Condition.Trigger): + trigger (google.cloud.monitoring_v3.types.AlertPolicy.Condition.Trigger): The number/percent of time series for which the comparison must hold in order for the condition to trigger. If unspecified, then the condition will trigger if the @@ -345,7 +348,7 @@ class MetricAbsence(proto.Message): Attributes: filter (str): - A + Required. A `filter `__ that identifies which time series should be compared with the threshold. @@ -354,11 +357,11 @@ class MetricAbsence(proto.Message): ```ListTimeSeries`` request `__ (that call is useful to verify the time series that will be - retrieved / processed) and must specify the metric type and - optionally may contain restrictions on resource type, - resource labels, and metric labels. This field may not + retrieved / processed). The filter must specify the metric + type and the resource type. Optionally, it can specify + resource labels and metric labels. This field must not exceed 2048 Unicode characters in length. - aggregations (Sequence[~.common.Aggregation]): + aggregations (Sequence[google.cloud.monitoring_v3.types.Aggregation]): Specifies the alignment of data points in individual time series as well as how to combine the retrieved time series together (such as when aggregating multiple streams on each @@ -371,14 +374,14 @@ class MetricAbsence(proto.Message): request `__. It is advisable to use the ``ListTimeSeries`` method when debugging this field. - duration (~.gp_duration.Duration): + duration (google.protobuf.duration_pb2.Duration): The amount of time that a time series must fail to report - new data to be considered failing. Currently, only values - that are a multiple of a minute--e.g. 60, 120, or 300 - seconds--are supported. If an invalid value is given, an - error will be returned. The ``Duration.nanos`` field is - ignored. - trigger (~.alert.AlertPolicy.Condition.Trigger): + new data to be considered failing. The minimum value of this + field is 120 seconds. Larger values that are a multiple of a + minute--for example, 240 or 300 seconds--are supported. If + an invalid value is given, an error will be returned. The + ``Duration.nanos`` field is ignored. + trigger (google.cloud.monitoring_v3.types.AlertPolicy.Condition.Trigger): The number/percent of time series for which the comparison must hold in order for the condition to trigger. If unspecified, then the condition will trigger if the @@ -400,6 +403,48 @@ class MetricAbsence(proto.Message): proto.MESSAGE, number=3, message="AlertPolicy.Condition.Trigger", ) + class MonitoringQueryLanguageCondition(proto.Message): + r"""A condition type that allows alert policies to be defined using + `Monitoring Query + Language `__. + + Attributes: + query (str): + `Monitoring Query + Language `__ query + that outputs a boolean stream. + duration (google.protobuf.duration_pb2.Duration): + The amount of time that a time series must violate the + threshold to be considered failing. Currently, only values + that are a multiple of a minute--e.g., 0, 60, 120, or 300 + seconds--are supported. If an invalid value is given, an + error will be returned. When choosing a duration, it is + useful to keep in mind the frequency of the underlying time + series data (which may also be affected by any alignments + specified in the ``aggregations`` field); a good duration is + long enough so that a single outlier does not generate + spurious alerts, but short enough that unhealthy states are + detected and alerted on quickly. + trigger (google.cloud.monitoring_v3.types.AlertPolicy.Condition.Trigger): + The number/percent of time series for which the comparison + must hold in order for the condition to trigger. If + unspecified, then the condition will trigger if the + comparison is true for any of the time series that have been + identified by ``filter`` and ``aggregations``, or by the + ratio, if ``denominator_filter`` and + ``denominator_aggregations`` are specified. + """ + + query = proto.Field(proto.STRING, number=1) + + duration = proto.Field( + proto.MESSAGE, number=2, message=gp_duration.Duration, + ) + + trigger = proto.Field( + proto.MESSAGE, number=3, message="AlertPolicy.Condition.Trigger", + ) + name = proto.Field(proto.STRING, number=12) display_name = proto.Field(proto.STRING, number=6) @@ -418,6 +463,13 @@ class MetricAbsence(proto.Message): message="AlertPolicy.Condition.MetricAbsence", ) + condition_monitoring_query_language = proto.Field( + proto.MESSAGE, + number=19, + oneof="condition", + message="AlertPolicy.Condition.MonitoringQueryLanguageCondition", + ) + name = proto.Field(proto.STRING, number=1) display_name = proto.Field(proto.STRING, number=2) diff --git a/google/cloud/monitoring_v3/types/alert_service.py b/google/cloud/monitoring_v3/types/alert_service.py index 38e5f65e..ede64c59 100644 --- a/google/cloud/monitoring_v3/types/alert_service.py +++ b/google/cloud/monitoring_v3/types/alert_service.py @@ -49,12 +49,13 @@ class CreateAlertPolicyRequest(proto.Message): Note that this field names the parent container in which the alerting policy will be written, not the name of the created - policy. The alerting policy that is returned will have a - name that contains a normalized representation of this name - as a prefix but adds a suffix of the form - ``/alertPolicies/[ALERT_POLICY_ID]``, identifying the policy - in the container. - alert_policy (~.alert.AlertPolicy): + policy. \|name\| must be a host project of a workspace, + otherwise INVALID_ARGUMENT error will return. The alerting + policy that is returned will have a name that contains a + normalized representation of this name as a prefix but adds + a suffix of the form ``/alertPolicies/[ALERT_POLICY_ID]``, + identifying the policy in the container. + alert_policy (google.cloud.monitoring_v3.types.AlertPolicy): Required. The requested alerting policy. You should omit the ``name`` field in this policy. The name will be returned in the new policy, including a new ``[ALERT_POLICY_ID]`` value. @@ -136,13 +137,17 @@ class ListAlertPoliciesResponse(proto.Message): r"""The protocol for the ``ListAlertPolicies`` response. Attributes: - alert_policies (Sequence[~.alert.AlertPolicy]): + alert_policies (Sequence[google.cloud.monitoring_v3.types.AlertPolicy]): The returned alert policies. next_page_token (str): If there might be more results than were returned, then this field is set to a non-empty value. To see the additional results, use that value as ``page_token`` in the next call to this method. + total_size (int): + The total number of alert policies in all + pages. This number is only an estimate, and may + change in subsequent pages. https://aip.dev/158 """ @property @@ -155,12 +160,14 @@ def raw_page(self): next_page_token = proto.Field(proto.STRING, number=2) + total_size = proto.Field(proto.INT32, number=4) + class UpdateAlertPolicyRequest(proto.Message): r"""The protocol for the ``UpdateAlertPolicy`` request. Attributes: - update_mask (~.field_mask.FieldMask): + update_mask (google.protobuf.field_mask_pb2.FieldMask): Optional. A list of alerting policy field names. If this field is not empty, each listed field in the existing alerting policy is set to the value of the corresponding @@ -188,7 +195,7 @@ class UpdateAlertPolicyRequest(proto.Message): ``name`` field with that ``[CONDITION_ID]``. If the supplied condition omits the ``name`` field, then a new ``[CONDITION_ID]`` is created. - alert_policy (~.alert.AlertPolicy): + alert_policy (google.cloud.monitoring_v3.types.AlertPolicy): Required. The updated alerting policy or the updated values for the fields listed in ``update_mask``. If ``update_mask`` is not empty, any fields in this policy that are not in diff --git a/google/cloud/monitoring_v3/types/common.py b/google/cloud/monitoring_v3/types/common.py index a7da61e6..3a8a4770 100644 --- a/google/cloud/monitoring_v3/types/common.py +++ b/google/cloud/monitoring_v3/types/common.py @@ -53,6 +53,7 @@ class ServiceTier(proto.Enum): documentation `__ for more details. """ + _pb_options = {"deprecated": True} SERVICE_TIER_UNSPECIFIED = 0 SERVICE_TIER_BASIC = 1 SERVICE_TIER_PREMIUM = 2 @@ -74,7 +75,7 @@ class TypedValue(proto.Message): significant digits of precision. string_value (str): A variable-length string value. - distribution_value (~.distribution.Distribution): + distribution_value (google.api.distribution_pb2.Distribution): A distribution value. """ @@ -95,31 +96,44 @@ class TimeInterval(proto.Message): r"""A closed time interval. It extends from the start time to the end time, and includes both: ``[startTime, endTime]``. Valid time intervals depend on the - ```MetricKind`` `__ - of the metric value. In no case can the end time be earlier than the - start time. + ```MetricKind`` `__ + of the metric value. The end time must not be earlier than the start + time. When writing data points, the start time must not be more than + 25 hours in the past and the end time must not be more than five + minutes in the future. - - For a ``GAUGE`` metric, the ``startTime`` value is technically + - For ``GAUGE`` metrics, the ``startTime`` value is technically optional; if no value is specified, the start time defaults to the value of the end time, and the interval represents a single point in time. If both start and end times are specified, they must be identical. Such an interval is valid only for ``GAUGE`` - metrics, which are point-in-time measurements. - - - For ``DELTA`` and ``CUMULATIVE`` metrics, the start time must be - earlier than the end time. - - - In all cases, the start time of the next interval must be at - least a millisecond after the end time of the previous interval. - Because the interval is closed, if the start time of a new - interval is the same as the end time of the previous interval, - data written at the new start time could overwrite data written - at the previous end time. + metrics, which are point-in-time measurements. The end time of a + new interval must be at least a millisecond after the end time of + the previous interval. + + - For ``DELTA`` metrics, the start time and end time must specify a + non-zero interval, with subsequent points specifying contiguous + and non-overlapping intervals. For ``DELTA`` metrics, the start + time of the next interval must be at least a millisecond after + the end time of the previous interval. + + - For ``CUMULATIVE`` metrics, the start time and end time must + specify a a non-zero interval, with subsequent points specifying + the same start time and increasing end times, until an event + resets the cumulative value to zero and sets a new start time for + the following points. The new start time must be at least a + millisecond after the end time of the previous interval. + + - The start time of a new interval must be at least a millisecond + after the end time of the previous interval because intervals are + closed. If the start time of a new interval is the same as the + end time of the previous interval, then data written at the new + start time could overwrite data written at the previous end time. Attributes: - end_time (~.timestamp.Timestamp): + end_time (google.protobuf.timestamp_pb2.Timestamp): Required. The end of the time interval. - start_time (~.timestamp.Timestamp): + start_time (google.protobuf.timestamp_pb2.Timestamp): Optional. The beginning of the time interval. The default value for the start time is the end time. The start time must not be later than the @@ -162,7 +176,7 @@ class Aggregation(proto.Message): aggregation `__. Attributes: - alignment_period (~.duration.Duration): + alignment_period (google.protobuf.duration_pb2.Duration): The ``alignment_period`` specifies a time interval, in seconds, that is used to divide the data in all the [time series][google.monitoring.v3.TimeSeries] into consistent @@ -174,7 +188,11 @@ class Aggregation(proto.Message): is required or an error is returned. If no per-series aligner is specified, or the aligner ``ALIGN_NONE`` is specified, then this field is ignored. - per_series_aligner (~.common.Aggregation.Aligner): + + The maximum value of the ``alignment_period`` is 104 weeks + (2 years) for charts, and 90,000 seconds (25 hours) for + alerting policies. + per_series_aligner (google.cloud.monitoring_v3.types.Aggregation.Aligner): An ``Aligner`` describes how to bring the data points in a single time series into temporal alignment. Except for ``ALIGN_NONE``, all alignments cause all the data points in @@ -194,7 +212,7 @@ class Aggregation(proto.Message): specified, then ``per_series_aligner`` must be specified and not equal to ``ALIGN_NONE`` and ``alignment_period`` must be specified; otherwise, an error is returned. - cross_series_reducer (~.common.Aggregation.Reducer): + cross_series_reducer (google.cloud.monitoring_v3.types.Aggregation.Reducer): The reduction operation to be used to combine time series into a single time series, where the value of each data point in the resulting series is a function of all the diff --git a/google/cloud/monitoring_v3/types/dropped_labels.py b/google/cloud/monitoring_v3/types/dropped_labels.py index c1e4b258..d49a1783 100644 --- a/google/cloud/monitoring_v3/types/dropped_labels.py +++ b/google/cloud/monitoring_v3/types/dropped_labels.py @@ -24,17 +24,18 @@ class DroppedLabels(proto.Message): - r"""A set of (label, value) pairs which were dropped during - aggregation, attached to google.api.Distribution.Exemplars in - google.api.Distribution values during aggregation. - - These values are used in combination with the label values that - remain on the aggregated Distribution timeseries to construct - the full label set for the exemplar values. The resulting full - label set may be used to identify the specific task/job/instance - (for example) which may be contributing to a long-tail, while - allowing the storage savings of only storing aggregated - distribution values for a large group. + r"""A set of (label, value) pairs that were removed from a + Distribution time series during aggregation and then added as an + attachment to a Distribution.Exemplar. + + The full label set for the exemplars is constructed by using the + dropped pairs in combination with the label values that remain + on the aggregated Distribution time series. The constructed full + label set can be used to identify the specific entity, such as + the instance or job, which might be contributing to a long-tail. + However, with dropped labels, the storage requirements are + reduced because only the aggregated distribution values for a + large group of time series are stored. Note that there are no guarantees on ordering of the labels from exemplar-to-exemplar and from distribution-to-distribution in @@ -42,7 +43,7 @@ class DroppedLabels(proto.Message): clients to resolve any ambiguities. Attributes: - label (Sequence[~.dropped_labels.DroppedLabels.LabelEntry]): + label (Sequence[google.cloud.monitoring_v3.types.DroppedLabels.LabelEntry]): Map from label to its value, for all labels dropped in any aggregation. """ diff --git a/google/cloud/monitoring_v3/types/group_service.py b/google/cloud/monitoring_v3/types/group_service.py index 5ee90f1e..b1bd4573 100644 --- a/google/cloud/monitoring_v3/types/group_service.py +++ b/google/cloud/monitoring_v3/types/group_service.py @@ -109,7 +109,7 @@ class ListGroupsResponse(proto.Message): r"""The ``ListGroups`` response. Attributes: - group (Sequence[~.gm_group.Group]): + group (Sequence[google.cloud.monitoring_v3.types.Group]): The groups that match the specified filters. next_page_token (str): If there are more results than have been returned, then this @@ -153,7 +153,7 @@ class CreateGroupRequest(proto.Message): :: projects/[PROJECT_ID_OR_NUMBER] - group (~.gm_group.Group): + group (google.cloud.monitoring_v3.types.Group): Required. A group definition. It is an error to define the ``name`` field because the system assigns the name. validate_only (bool): @@ -172,7 +172,7 @@ class UpdateGroupRequest(proto.Message): r"""The ``UpdateGroup`` request. Attributes: - group (~.gm_group.Group): + group (google.cloud.monitoring_v3.types.Group): Required. The new definition of the group. All fields of the existing group, excepting ``name``, are replaced with the corresponding fields of this group. @@ -240,7 +240,7 @@ class ListGroupMembersRequest(proto.Message): :: `resource.type = "gce_instance"` - interval (~.common.TimeInterval): + interval (google.cloud.monitoring_v3.types.TimeInterval): An optional time interval for which results should be returned. Only members that were part of the group during the specified interval are @@ -264,7 +264,7 @@ class ListGroupMembersResponse(proto.Message): r"""The ``ListGroupMembers`` response. Attributes: - members (Sequence[~.monitored_resource.MonitoredResource]): + members (Sequence[google.api.monitored_resource_pb2.MonitoredResource]): A set of monitored resources in the group. next_page_token (str): If there are more results than have been returned, then this diff --git a/google/cloud/monitoring_v3/types/metric.py b/google/cloud/monitoring_v3/types/metric.py index 1c4b8494..dda03299 100644 --- a/google/cloud/monitoring_v3/types/metric.py +++ b/google/cloud/monitoring_v3/types/metric.py @@ -42,7 +42,7 @@ class Point(proto.Message): r"""A single data point in a time series. Attributes: - interval (~.common.TimeInterval): + interval (google.cloud.monitoring_v3.types.TimeInterval): The time interval to which the data point applies. For ``GAUGE`` metrics, the start time is optional, but if it is supplied, it must equal the end time. For ``DELTA`` metrics, @@ -54,7 +54,7 @@ class Point(proto.Message): increasing end times, until an event resets the cumulative value to zero and sets a new start time for the following points. - value (~.common.TypedValue): + value (google.cloud.monitoring_v3.types.TypedValue): The value of the data point. """ @@ -71,20 +71,20 @@ class TimeSeries(proto.Message): series. Attributes: - metric (~.ga_metric.Metric): + metric (google.api.metric_pb2.Metric): The associated metric. A fully-specified metric used to identify the time series. - resource (~.monitored_resource.MonitoredResource): + resource (google.api.monitored_resource_pb2.MonitoredResource): The associated monitored resource. Custom metrics can use only certain monitored resource types in their time series data. - metadata (~.monitored_resource.MonitoredResourceMetadata): + metadata (google.api.monitored_resource_pb2.MonitoredResourceMetadata): Output only. The associated monitored - resource metadata. When reading a a timeseries, + resource metadata. When reading a time series, this field will include metadata labels that are explicitly named in the reduction. When creating - a timeseries, this field is ignored. - metric_kind (~.ga_metric.MetricDescriptor.MetricKind): + a time series, this field is ignored. + metric_kind (google.api.metric_pb2.MetricKind): The metric kind of the time series. When listing time series, this metric kind might be different from the metric kind of the associated metric if this time series is an @@ -96,7 +96,7 @@ class TimeSeries(proto.Message): must be auto-created, then this field specifies the metric kind of the new descriptor and must be either ``GAUGE`` (the default) or ``CUMULATIVE``. - value_type (~.ga_metric.MetricDescriptor.ValueType): + value_type (google.api.metric_pb2.ValueType): The value type of the time series. When listing time series, this value type might be different from the value type of the associated metric if this time series is an alignment or @@ -105,7 +105,7 @@ class TimeSeries(proto.Message): When creating a time series, this field is optional. If present, it must be the same as the type of the data in the ``points`` field. - points (Sequence[~.gm_metric.Point]): + points (Sequence[google.cloud.monitoring_v3.types.Point]): The data points of this time series. When listing time series, points are returned in reverse time order. @@ -115,6 +115,11 @@ class TimeSeries(proto.Message): descriptor must be auto-created, then the value type of the descriptor is determined by the point's type, which must be ``BOOL``, ``INT64``, ``DOUBLE``, or ``DISTRIBUTION``. + unit (str): + The units in which the metric value is reported. It is only + applicable if the ``value_type`` is ``INT64``, ``DOUBLE``, + or ``DISTRIBUTION``. The ``unit`` defines the representation + of the stored metric values. """ metric = proto.Field(proto.MESSAGE, number=1, message=ga_metric.Metric,) @@ -137,14 +142,16 @@ class TimeSeries(proto.Message): points = proto.RepeatedField(proto.MESSAGE, number=5, message="Point",) + unit = proto.Field(proto.STRING, number=8) + class TimeSeriesDescriptor(proto.Message): - r"""A descriptor for the labels and points in a timeseries. + r"""A descriptor for the labels and points in a time series. Attributes: - label_descriptors (Sequence[~.label.LabelDescriptor]): + label_descriptors (Sequence[google.api.label_pb2.LabelDescriptor]): Descriptors for the labels. - point_descriptors (Sequence[~.gm_metric.TimeSeriesDescriptor.ValueDescriptor]): + point_descriptors (Sequence[google.cloud.monitoring_v3.types.TimeSeriesDescriptor.ValueDescriptor]): Descriptors for the point data value columns. """ @@ -154,10 +161,15 @@ class ValueDescriptor(proto.Message): Attributes: key (str): The value key. - value_type (~.ga_metric.MetricDescriptor.ValueType): + value_type (google.api.metric_pb2.ValueType): The value type. - metric_kind (~.ga_metric.MetricDescriptor.MetricKind): + metric_kind (google.api.metric_pb2.MetricKind): The value stream kind. + unit (str): + The unit in which ``time_series`` point values are reported. + ``unit`` follows the UCUM format for units as seen in + https://unitsofmeasure.org/ucum.html. ``unit`` is only valid + if ``value_type`` is INTEGER, DOUBLE, DISTRIBUTION. """ key = proto.Field(proto.STRING, number=1) @@ -170,6 +182,8 @@ class ValueDescriptor(proto.Message): proto.ENUM, number=3, enum=ga_metric.MetricDescriptor.MetricKind, ) + unit = proto.Field(proto.STRING, number=4) + label_descriptors = proto.RepeatedField( proto.MESSAGE, number=1, message=label.LabelDescriptor, ) @@ -184,13 +198,13 @@ class TimeSeriesData(proto.Message): TimeSeriesDescriptor. Attributes: - label_values (Sequence[~.gm_metric.LabelValue]): + label_values (Sequence[google.cloud.monitoring_v3.types.LabelValue]): The values of the labels in the time series identifier, given in the same order as the ``label_descriptors`` field of the TimeSeriesDescriptor associated with this object. Each value must have a value of the type given in the corresponding entry of ``label_descriptors``. - point_data (Sequence[~.gm_metric.TimeSeriesData.PointData]): + point_data (Sequence[google.cloud.monitoring_v3.types.TimeSeriesData.PointData]): The points in the time series. """ @@ -201,9 +215,9 @@ class PointData(proto.Message): with this object. Attributes: - values (Sequence[~.common.TypedValue]): + values (Sequence[google.cloud.monitoring_v3.types.TypedValue]): The values that make up the point. - time_interval (~.common.TimeInterval): + time_interval (google.cloud.monitoring_v3.types.TimeInterval): The time interval associated with the point. """ @@ -244,7 +258,7 @@ class QueryError(proto.Message): language format. Attributes: - locator (~.gm_metric.TextLocator): + locator (google.cloud.monitoring_v3.types.TextLocator): The location of the time series query language text that this error applies to. message (str): @@ -281,13 +295,13 @@ class TextLocator(proto.Message): (e.g. a macro definition referenced in the text of the query), in which case this is the name of the source (e.g. the macro name). - start_position (~.gm_metric.TextLocator.Position): + start_position (google.cloud.monitoring_v3.types.TextLocator.Position): The position of the first byte within the text. - end_position (~.gm_metric.TextLocator.Position): + end_position (google.cloud.monitoring_v3.types.TextLocator.Position): The position of the last byte within the text. - nested_locator (~.gm_metric.TextLocator): + nested_locator (google.cloud.monitoring_v3.types.TextLocator): If ``source``, ``start_position``, and ``end_position`` describe a call on some object (e.g. a macro in the time series query language text) and a location is to be diff --git a/google/cloud/monitoring_v3/types/metric_service.py b/google/cloud/monitoring_v3/types/metric_service.py index f2d05b03..64ddf330 100644 --- a/google/cloud/monitoring_v3/types/metric_service.py +++ b/google/cloud/monitoring_v3/types/metric_service.py @@ -93,7 +93,7 @@ class ListMonitoredResourceDescriptorsResponse(proto.Message): r"""The ``ListMonitoredResourceDescriptors`` response. Attributes: - resource_descriptors (Sequence[~.monitored_resource.MonitoredResourceDescriptor]): + resource_descriptors (Sequence[google.api.monitored_resource_pb2.MonitoredResourceDescriptor]): The monitored resource descriptors that are available to this project and that match ``filter``, if present. next_page_token (str): @@ -178,7 +178,7 @@ class ListMetricDescriptorsResponse(proto.Message): r"""The ``ListMetricDescriptors`` response. Attributes: - metric_descriptors (Sequence[~.ga_metric.MetricDescriptor]): + metric_descriptors (Sequence[google.api.metric_pb2.MetricDescriptor]): The metric descriptors that are available to the project and that match the value of ``filter``, if present. next_page_token (str): @@ -229,7 +229,7 @@ class CreateMetricDescriptorRequest(proto.Message): :: projects/[PROJECT_ID_OR_NUMBER] - metric_descriptor (~.ga_metric.MetricDescriptor): + metric_descriptor (google.api.metric_pb2.MetricDescriptor): Required. The new `custom metric `__ descriptor. @@ -266,12 +266,14 @@ class ListTimeSeriesRequest(proto.Message): Attributes: name (str): - Required. The project on which to execute the request. The - format is: + Required. The project, organization or folder on which to + execute the request. The format is: :: projects/[PROJECT_ID_OR_NUMBER] + organizations/[ORGANIZATION_ID] + folders/[FOLDER_ID] filter (str): Required. A `monitoring filter `__ @@ -284,23 +286,26 @@ class ListTimeSeriesRequest(proto.Message): metric.type = "compute.googleapis.com/instance/cpu/usage_time" AND metric.labels.instance_name = "my-instance-name". - interval (~.common.TimeInterval): + interval (google.cloud.monitoring_v3.types.TimeInterval): Required. The time interval for which results should be returned. Only time series that contain data points in the specified interval are included in the response. - aggregation (~.common.Aggregation): + aggregation (google.cloud.monitoring_v3.types.Aggregation): Specifies the alignment of data points in individual time series as well as how to combine the retrieved time series across specified labels. By default (if no ``aggregation`` is explicitly specified), the raw time series data is returned. + secondary_aggregation (google.cloud.monitoring_v3.types.Aggregation): + Apply a second aggregation after ``aggregation`` is applied. + May only be specified if ``aggregation`` is specified. order_by (str): Unsupported: must be left blank. The points in each time series are currently returned in reverse time order (most recent to oldest). - view (~.metric_service.ListTimeSeriesRequest.TimeSeriesView): + view (google.cloud.monitoring_v3.types.ListTimeSeriesRequest.TimeSeriesView): Required. Specifies which information is returned about the time series. page_size (int): @@ -330,6 +335,10 @@ class TimeSeriesView(proto.Enum): aggregation = proto.Field(proto.MESSAGE, number=5, message=common.Aggregation,) + secondary_aggregation = proto.Field( + proto.MESSAGE, number=11, message=common.Aggregation, + ) + order_by = proto.Field(proto.STRING, number=6) view = proto.Field(proto.ENUM, number=7, enum=TimeSeriesView,) @@ -343,7 +352,7 @@ class ListTimeSeriesResponse(proto.Message): r"""The ``ListTimeSeries`` response. Attributes: - time_series (Sequence[~.gm_metric.TimeSeries]): + time_series (Sequence[google.cloud.monitoring_v3.types.TimeSeries]): One or more time series that match the filter included in the request. next_page_token (str): @@ -351,9 +360,16 @@ class ListTimeSeriesResponse(proto.Message): field is set to a non-empty value. To see the additional results, use that value as ``page_token`` in the next call to this method. - execution_errors (Sequence[~.gr_status.Status]): + execution_errors (Sequence[google.rpc.status_pb2.Status]): Query execution errors that may have caused the time series data returned to be incomplete. + unit (str): + The unit in which all ``time_series`` point values are + reported. ``unit`` follows the UCUM format for units as seen + in https://unitsofmeasure.org/ucum.html. If different + ``time_series`` have different units (for example, because + they come from different metric types, or a unit is absent), + then ``unit`` will be "{not_a_unit}". """ @property @@ -370,6 +386,8 @@ def raw_page(self): proto.MESSAGE, number=3, message=gr_status.Status, ) + unit = proto.Field(proto.STRING, number=5) + class CreateTimeSeriesRequest(proto.Message): r"""The ``CreateTimeSeries`` request. @@ -382,7 +400,7 @@ class CreateTimeSeriesRequest(proto.Message): :: projects/[PROJECT_ID_OR_NUMBER] - time_series (Sequence[~.gm_metric.TimeSeries]): + time_series (Sequence[google.cloud.monitoring_v3.types.TimeSeries]): Required. The new data to be added to a list of time series. Adds at most one data point to each of several time series. The new data point must be more recent than any other point @@ -405,10 +423,10 @@ class CreateTimeSeriesError(proto.Message): r"""DEPRECATED. Used to hold per-time-series error status. Attributes: - time_series (~.gm_metric.TimeSeries): + time_series (google.cloud.monitoring_v3.types.TimeSeries): DEPRECATED. Time series ID that resulted in the ``status`` error. - status (~.gr_status.Status): + status (google.rpc.status_pb2.Status): DEPRECATED. The status of the requested write operation for ``time_series``. """ @@ -428,7 +446,7 @@ class CreateTimeSeriesSummary(proto.Message): success_point_count (int): The number of points that were successfully written. - errors (Sequence[~.metric_service.CreateTimeSeriesSummary.Error]): + errors (Sequence[google.cloud.monitoring_v3.types.CreateTimeSeriesSummary.Error]): The number of points that failed to be written. Order is not guaranteed. """ @@ -437,7 +455,7 @@ class Error(proto.Message): r"""Detailed information about an error category. Attributes: - status (~.gr_status.Status): + status (google.rpc.status_pb2.Status): The status of the requested write operation. point_count (int): The number of points that couldn't be written because of @@ -467,9 +485,9 @@ class QueryTimeSeriesRequest(proto.Message): projects/[PROJECT_ID_OR_NUMBER] query (str): - Required. The query in the monitoring query - language format. The default time zone is in - UTC. + Required. The query in the `Monitoring Query + Language `__ + format. The default time zone is in UTC. page_size (int): A positive number that is the maximum number of time_series_data to return. @@ -493,16 +511,16 @@ class QueryTimeSeriesResponse(proto.Message): r"""The ``QueryTimeSeries`` response. Attributes: - time_series_descriptor (~.gm_metric.TimeSeriesDescriptor): + time_series_descriptor (google.cloud.monitoring_v3.types.TimeSeriesDescriptor): The descriptor for the time series data. - time_series_data (Sequence[~.gm_metric.TimeSeriesData]): + time_series_data (Sequence[google.cloud.monitoring_v3.types.TimeSeriesData]): The time series data. next_page_token (str): If there are more results than have been returned, then this field is set to a non-empty value. To see the additional results, use that value as ``page_token`` in the next call to this method. - partial_errors (Sequence[~.gr_status.Status]): + partial_errors (Sequence[google.rpc.status_pb2.Status]): Query execution errors that may have caused the time series data returned to be incomplete. The available data will be available in the @@ -533,7 +551,7 @@ class QueryErrorList(proto.Message): errors. Attributes: - errors (Sequence[~.gm_metric.QueryError]): + errors (Sequence[google.cloud.monitoring_v3.types.QueryError]): Errors in parsing the time series query language text. The number of errors in the response may be limited. diff --git a/google/cloud/monitoring_v3/types/mutation_record.py b/google/cloud/monitoring_v3/types/mutation_record.py index 0c3140e8..053a2a0c 100644 --- a/google/cloud/monitoring_v3/types/mutation_record.py +++ b/google/cloud/monitoring_v3/types/mutation_record.py @@ -30,7 +30,7 @@ class MutationRecord(proto.Message): r"""Describes a change made to a configuration. Attributes: - mutate_time (~.timestamp.Timestamp): + mutate_time (google.protobuf.timestamp_pb2.Timestamp): When the change occurred. mutated_by (str): The email address of the user making the diff --git a/google/cloud/monitoring_v3/types/notification.py b/google/cloud/monitoring_v3/types/notification.py index 02c0663c..97ee957e 100644 --- a/google/cloud/monitoring_v3/types/notification.py +++ b/google/cloud/monitoring_v3/types/notification.py @@ -21,6 +21,7 @@ from google.api import label_pb2 as label # type: ignore from google.api import launch_stage_pb2 as ga_launch_stage # type: ignore from google.cloud.monitoring_v3.types import common +from google.cloud.monitoring_v3.types import mutation_record from google.protobuf import wrappers_pb2 as wrappers # type: ignore @@ -47,9 +48,10 @@ class NotificationChannelDescriptor(proto.Message): In the above, ``[TYPE]`` is the value of the ``type`` field. type_ (str): - The type of notification channel, such as - "email", "sms", etc. Notification channel types - are globally unique. + The type of notification channel, such as "email" and "sms". + To view the full list of channels, see `Channel + descriptors `__. + Notification channel types are globally unique. display_name (str): A human-readable name for the notification channel type. This form of the name is suitable @@ -59,16 +61,16 @@ class NotificationChannelDescriptor(proto.Message): notification channel type. The description may include a description of the properties of the channel and pointers to external documentation. - labels (Sequence[~.label.LabelDescriptor]): + labels (Sequence[google.api.label_pb2.LabelDescriptor]): The set of labels that must be defined to identify a particular channel of the corresponding type. Each label includes a description for how that field should be populated. - supported_tiers (Sequence[~.common.ServiceTier]): + supported_tiers (Sequence[google.cloud.monitoring_v3.types.ServiceTier]): The tiers that support this notification channel; the project service tier must be one of the supported_tiers. - launch_stage (~.ga_launch_stage.LaunchStage): + launch_stage (google.api.launch_stage_pb2.LaunchStage): The product launch stage for channels of this type. """ @@ -128,14 +130,14 @@ class NotificationChannel(proto.Message): provide additional details, beyond the display name, for the channel. This may not exceed 1024 Unicode characters. - labels (Sequence[~.notification.NotificationChannel.LabelsEntry]): + labels (Sequence[google.cloud.monitoring_v3.types.NotificationChannel.LabelsEntry]): Configuration fields that define the channel and its behavior. The permissible and required labels are specified in the [NotificationChannelDescriptor.labels][google.monitoring.v3.NotificationChannelDescriptor.labels] of the ``NotificationChannelDescriptor`` corresponding to the ``type`` field. - user_labels (Sequence[~.notification.NotificationChannel.UserLabelsEntry]): + user_labels (Sequence[google.cloud.monitoring_v3.types.NotificationChannel.UserLabelsEntry]): User-supplied key/value data that does not need to conform to the corresponding ``NotificationChannelDescriptor``'s schema, unlike the ``labels`` field. This field is intended @@ -147,7 +149,7 @@ class NotificationChannel(proto.Message): is smaller. Labels and values can contain only lowercase letters, numerals, underscores, and dashes. Keys must begin with a letter. - verification_status (~.notification.NotificationChannel.VerificationStatus): + verification_status (google.cloud.monitoring_v3.types.NotificationChannel.VerificationStatus): Indicates whether this channel has been verified or not. On a [``ListNotificationChannels``][google.monitoring.v3.NotificationChannelService.ListNotificationChannels] @@ -170,7 +172,7 @@ class NotificationChannel(proto.Message): [``UpdateNotificationChannel``][google.monitoring.v3.NotificationChannelService.UpdateNotificationChannel] operation. To change the value of this field, you must call [``VerifyNotificationChannel``][google.monitoring.v3.NotificationChannelService.VerifyNotificationChannel]. - enabled (~.wrappers.BoolValue): + enabled (google.protobuf.wrappers_pb2.BoolValue): Whether notifications are forwarded to the described channel. This makes it possible to disable delivery of notifications to a @@ -181,6 +183,10 @@ class NotificationChannel(proto.Message): notifications from the same set of alerting policies on the channel at some point in the future. + creation_record (google.cloud.monitoring_v3.types.MutationRecord): + Record of the creation of this channel. + mutation_records (Sequence[google.cloud.monitoring_v3.types.MutationRecord]): + Records of the modification of this channel. """ class VerificationStatus(proto.Enum): @@ -211,5 +217,13 @@ class VerificationStatus(proto.Enum): enabled = proto.Field(proto.MESSAGE, number=11, message=wrappers.BoolValue,) + creation_record = proto.Field( + proto.MESSAGE, number=12, message=mutation_record.MutationRecord, + ) + + mutation_records = proto.RepeatedField( + proto.MESSAGE, number=13, message=mutation_record.MutationRecord, + ) + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/monitoring_v3/types/notification_service.py b/google/cloud/monitoring_v3/types/notification_service.py index 6e73dd6d..e34ccab0 100644 --- a/google/cloud/monitoring_v3/types/notification_service.py +++ b/google/cloud/monitoring_v3/types/notification_service.py @@ -83,7 +83,7 @@ class ListNotificationChannelDescriptorsResponse(proto.Message): r"""The ``ListNotificationChannelDescriptors`` response. Attributes: - channel_descriptors (Sequence[~.notification.NotificationChannelDescriptor]): + channel_descriptors (Sequence[google.cloud.monitoring_v3.types.NotificationChannelDescriptor]): The monitored resource descriptors supported for the specified project, optionally filtered. next_page_token (str): @@ -138,7 +138,7 @@ class CreateNotificationChannelRequest(proto.Message): this field as a prefix, but will add ``/notificationChannels/[CHANNEL_ID]`` to identify the channel. - notification_channel (~.notification.NotificationChannel): + notification_channel (google.cloud.monitoring_v3.types.NotificationChannel): Required. The definition of the ``NotificationChannel`` to create. """ @@ -207,7 +207,7 @@ class ListNotificationChannelsResponse(proto.Message): r"""The ``ListNotificationChannels`` response. Attributes: - notification_channels (Sequence[~.notification.NotificationChannel]): + notification_channels (Sequence[google.cloud.monitoring_v3.types.NotificationChannel]): The notification channels defined for the specified project. next_page_token (str): @@ -215,6 +215,11 @@ class ListNotificationChannelsResponse(proto.Message): match the request. Use the value in the ``page_token`` field in a subsequent request to fetch the next set of results. If empty, all results have been returned. + total_size (int): + The total number of notification channels in + all pages. This number is only an estimate, and + may change in subsequent pages. + https://aip.dev/158 """ @property @@ -227,6 +232,8 @@ def raw_page(self): next_page_token = proto.Field(proto.STRING, number=2) + total_size = proto.Field(proto.INT32, number=4) + class GetNotificationChannelRequest(proto.Message): r"""The ``GetNotificationChannel`` request. @@ -248,9 +255,9 @@ class UpdateNotificationChannelRequest(proto.Message): r"""The ``UpdateNotificationChannel`` request. Attributes: - update_mask (~.field_mask.FieldMask): + update_mask (google.protobuf.field_mask_pb2.FieldMask): The fields to update. - notification_channel (~.notification.NotificationChannel): + notification_channel (google.cloud.monitoring_v3.types.NotificationChannel): Required. A description of the changes to be applied to the specified notification channel. The description must provide a definition for fields to be updated; the names of these @@ -311,7 +318,7 @@ class GetNotificationChannelVerificationCodeRequest(proto.Message): retrieved. This must name a channel that is already verified; if the specified channel is not verified, the request will fail. - expire_time (~.timestamp.Timestamp): + expire_time (google.protobuf.timestamp_pb2.Timestamp): The desired expiration time. If specified, the API will guarantee that the returned code will not be valid after the specified timestamp; @@ -344,7 +351,7 @@ class GetNotificationChannelVerificationCodeResponse(proto.Message): with the same fingerprint such as other email channels with the same email address or other sms channels with the same number). - expire_time (~.timestamp.Timestamp): + expire_time (google.protobuf.timestamp_pb2.Timestamp): The expiration time associated with the code that was returned. If an expiration was provided in the request, this is the minimum of the diff --git a/google/cloud/monitoring_v3/types/query_service.py b/google/cloud/monitoring_v3/types/query_service.py new file mode 100644 index 00000000..15c9849d --- /dev/null +++ b/google/cloud/monitoring_v3/types/query_service.py @@ -0,0 +1,22 @@ +# -*- 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. +# + + +__protobuf__ = proto.module(package="google.monitoring.v3", manifest={},) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/monitoring_v3/types/service.py b/google/cloud/monitoring_v3/types/service.py index 728cacd4..88b892e0 100644 --- a/google/cloud/monitoring_v3/types/service.py +++ b/google/cloud/monitoring_v3/types/service.py @@ -55,19 +55,23 @@ class Service(proto.Message): display_name (str): Name used for UI elements listing this Service. - custom (~.gm_service.Service.Custom): + custom (google.cloud.monitoring_v3.types.Service.Custom): Custom service type. - app_engine (~.gm_service.Service.AppEngine): + app_engine (google.cloud.monitoring_v3.types.Service.AppEngine): Type used for App Engine services. - cloud_endpoints (~.gm_service.Service.CloudEndpoints): + cloud_endpoints (google.cloud.monitoring_v3.types.Service.CloudEndpoints): Type used for Cloud Endpoints services. - cluster_istio (~.gm_service.Service.ClusterIstio): + cluster_istio (google.cloud.monitoring_v3.types.Service.ClusterIstio): Type used for Istio services that live in a Kubernetes cluster. - mesh_istio (~.gm_service.Service.MeshIstio): + mesh_istio (google.cloud.monitoring_v3.types.Service.MeshIstio): Type used for Istio services scoped to an Istio mesh. - telemetry (~.gm_service.Service.Telemetry): + istio_canonical_service (google.cloud.monitoring_v3.types.Service.IstioCanonicalService): + Type used for canonical services scoped to an Istio mesh. + Metrics for Istio are `documented + here `__ + telemetry (google.cloud.monitoring_v3.types.Service.Telemetry): Configuration for how to query telemetry on a Service. """ @@ -107,7 +111,8 @@ class CloudEndpoints(proto.Message): class ClusterIstio(proto.Message): r"""Istio service scoped to a single Kubernetes cluster. Learn - more at http://istio.io. + more at https://istio.io. Clusters running OSS Istio will have + their services ingested as this type. Attributes: location (str): @@ -137,7 +142,9 @@ class ClusterIstio(proto.Message): service_name = proto.Field(proto.STRING, number=4) class MeshIstio(proto.Message): - r"""Istio service scoped to an Istio mesh + r"""Istio service scoped to an Istio mesh. Anthos clusters + running ASM < 1.6.8 will have their services ingested as this + type. Attributes: mesh_uid (str): @@ -160,6 +167,36 @@ class MeshIstio(proto.Message): service_name = proto.Field(proto.STRING, number=4) + class IstioCanonicalService(proto.Message): + r"""Canonical service scoped to an Istio mesh. Anthos clusters + running ASM >= 1.6.8 will have their services ingested as this + type. + + Attributes: + mesh_uid (str): + Identifier for the Istio mesh in which this canonical + service is defined. Corresponds to the ``mesh_uid`` metric + label in `Istio + metrics `__. + canonical_service_namespace (str): + The namespace of the canonical service underlying this + service. Corresponds to the + ``destination_canonical_service_namespace`` metric label in + `Istio + metrics `__. + canonical_service (str): + The name of the canonical service underlying this service. + Corresponds to the ``destination_canonical_service_name`` + metric label in label in `Istio + metrics `__. + """ + + mesh_uid = proto.Field(proto.STRING, number=1) + + canonical_service_namespace = proto.Field(proto.STRING, number=3) + + canonical_service = proto.Field(proto.STRING, number=4) + class Telemetry(proto.Message): r"""Configuration for how to query telemetry on a Service. @@ -194,6 +231,10 @@ class Telemetry(proto.Message): proto.MESSAGE, number=10, oneof="identifier", message=MeshIstio, ) + istio_canonical_service = proto.Field( + proto.MESSAGE, number=11, oneof="identifier", message=IstioCanonicalService, + ) + telemetry = proto.Field(proto.MESSAGE, number=13, message=Telemetry,) @@ -217,18 +258,18 @@ class ServiceLevelObjective(proto.Message): projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID]/serviceLevelObjectives/[SLO_NAME] display_name (str): Name used for UI elements listing this SLO. - service_level_indicator (~.gm_service.ServiceLevelIndicator): + service_level_indicator (google.cloud.monitoring_v3.types.ServiceLevelIndicator): The definition of good service, used to measure and calculate the quality of the ``Service``'s performance with respect to a single aspect of service quality. goal (float): The fraction of service that must be good in order for this objective to be met. ``0 < goal <= 0.999``. - rolling_period (~.duration.Duration): + rolling_period (google.protobuf.duration_pb2.Duration): A rolling time period, semantically "in the past ````". Must be an integer multiple of 1 day no larger than 30 days. - calendar_period (~.gt_calendar_period.CalendarPeriod): + calendar_period (google.type.calendar_period_pb2.CalendarPeriod): A calendar period, semantically "since the start of the current ````". At this time, only ``DAY``, ``WEEK``, ``FORTNIGHT``, and ``MONTH`` are supported. @@ -281,11 +322,11 @@ class ServiceLevelIndicator(proto.Message): queries. Attributes: - basic_sli (~.gm_service.BasicSli): + basic_sli (google.cloud.monitoring_v3.types.BasicSli): Basic SLI on a well-known service type. - request_based (~.gm_service.RequestBasedSli): + request_based (google.cloud.monitoring_v3.types.RequestBasedSli): Request-based SLIs - windows_based (~.gm_service.WindowsBasedSli): + windows_based (google.cloud.monitoring_v3.types.WindowsBasedSli): Windows-based SLIs """ @@ -334,11 +375,11 @@ class BasicSli(proto.Message): applies to all API versions. For service types that don't support breaking down by version, setting this field will result in an error. - availability (~.gm_service.BasicSli.AvailabilityCriteria): + availability (google.cloud.monitoring_v3.types.BasicSli.AvailabilityCriteria): Good service is defined to be the count of requests made to this service that return successfully. - latency (~.gm_service.BasicSli.LatencyCriteria): + latency (google.cloud.monitoring_v3.types.BasicSli.LatencyCriteria): Good service is defined to be the count of requests made to this service that are fast enough with respect to ``latency.threshold``. @@ -351,7 +392,7 @@ class LatencyCriteria(proto.Message): r"""Parameters for a latency threshold SLI. Attributes: - threshold (~.duration.Duration): + threshold (google.protobuf.duration_pb2.Duration): Good service is defined to be the count of requests made to this service that return in no more than ``threshold``. """ @@ -396,11 +437,11 @@ class RequestBasedSli(proto.Message): are counted directly. Attributes: - good_total_ratio (~.gm_service.TimeSeriesRatio): + good_total_ratio (google.cloud.monitoring_v3.types.TimeSeriesRatio): ``good_total_ratio`` is used when the ratio of ``good_service`` to ``total_service`` is computed from two ``TimeSeries``. - distribution_cut (~.gm_service.DistributionCut): + distribution_cut (google.cloud.monitoring_v3.types.DistributionCut): ``distribution_cut`` is used when ``good_service`` is a count of values aggregated in a ``Distribution`` that fall into a good range. The ``total_service`` is the total count @@ -472,7 +513,7 @@ class DistributionCut(proto.Message): specifying a ``TimeSeries`` aggregating values. Must have ``ValueType = DISTRIBUTION`` and ``MetricKind = DELTA`` or ``MetricKind = CUMULATIVE``. - range_ (~.gm_service.Range): + range_ (google.cloud.monitoring_v3.types.Range): Range of values considered "good." For a one- ided range, set one bound to an infinite value. """ @@ -494,15 +535,15 @@ class WindowsBasedSli(proto.Message): filter `__ specifying a ``TimeSeries`` with ``ValueType = BOOL``. The window is good if any ``true`` values appear in the window. - good_total_ratio_threshold (~.gm_service.WindowsBasedSli.PerformanceThreshold): + good_total_ratio_threshold (google.cloud.monitoring_v3.types.WindowsBasedSli.PerformanceThreshold): A window is good if its ``performance`` is high enough. - metric_mean_in_range (~.gm_service.WindowsBasedSli.MetricRange): + metric_mean_in_range (google.cloud.monitoring_v3.types.WindowsBasedSli.MetricRange): A window is good if the metric's value is in a good range, averaged across returned streams. - metric_sum_in_range (~.gm_service.WindowsBasedSli.MetricRange): + metric_sum_in_range (google.cloud.monitoring_v3.types.WindowsBasedSli.MetricRange): A window is good if the metric's value is in a good range, summed across returned streams. - window_period (~.duration.Duration): + window_period (google.protobuf.duration_pb2.Duration): Duration over which window quality is evaluated. Must be an integer fraction of a day and at least ``60s``. """ @@ -512,9 +553,9 @@ class PerformanceThreshold(proto.Message): that window has a sufficiently high ``performance``. Attributes: - performance (~.gm_service.RequestBasedSli): + performance (google.cloud.monitoring_v3.types.RequestBasedSli): ``RequestBasedSli`` to evaluate to judge window quality. - basic_sli_performance (~.gm_service.BasicSli): + basic_sli_performance (google.cloud.monitoring_v3.types.BasicSli): ``BasicSli`` to evaluate to judge window quality. threshold (float): If window ``performance >= threshold``, the window is @@ -543,7 +584,7 @@ class MetricRange(proto.Message): filter `__ specifying the ``TimeSeries`` to use for evaluating window quality. - range_ (~.gm_service.Range): + range_ (google.cloud.monitoring_v3.types.Range): Range of values considered "good." For a one- ided range, set one bound to an infinite value. """ diff --git a/google/cloud/monitoring_v3/types/service_service.py b/google/cloud/monitoring_v3/types/service_service.py index 78696748..c747744d 100644 --- a/google/cloud/monitoring_v3/types/service_service.py +++ b/google/cloud/monitoring_v3/types/service_service.py @@ -56,7 +56,7 @@ class CreateServiceRequest(proto.Message): Optional. The Service id to use for this Service. If omitted, an id will be generated instead. Must match the pattern ``[a-z0-9\-]+`` - service (~.gm_service.Service): + service (google.cloud.monitoring_v3.types.Service): Required. The ``Service`` to create. """ @@ -103,18 +103,22 @@ class ListServicesRequest(proto.Message): - `identifier_case` - `app_engine.module_id` - - `cloud_endpoints.service` - - `cluster_istio.location` - - `cluster_istio.cluster_name` - - `cluster_istio.service_namespace` - - `cluster_istio.service_name` + - `cloud_endpoints.service` (reserved for future use) + - `mesh_istio.mesh_uid` + - `mesh_istio.service_namespace` + - `mesh_istio.service_name` + - `cluster_istio.location` (deprecated) + - `cluster_istio.cluster_name` (deprecated) + - `cluster_istio.service_namespace` (deprecated) + - `cluster_istio.service_name` (deprecated) ``identifier_case`` refers to which option in the identifier oneof is populated. For example, the filter ``identifier_case = "CUSTOM"`` would match all services with a value for the ``custom`` field. Valid options are - "CUSTOM", "APP_ENGINE", "CLOUD_ENDPOINTS", and - "CLUSTER_ISTIO". + "CUSTOM", "APP_ENGINE", "MESH_ISTIO", plus "CLUSTER_ISTIO" + (deprecated) and "CLOUD_ENDPOINTS" (reserved for future + use). page_size (int): A non-negative number that is the maximum number of results to return. When 0, use default @@ -139,7 +143,7 @@ class ListServicesResponse(proto.Message): r"""The ``ListServices`` response. Attributes: - services (Sequence[~.gm_service.Service]): + services (Sequence[google.cloud.monitoring_v3.types.Service]): The ``Service``\ s matching the specified filter. next_page_token (str): If there are more results than have been returned, then this @@ -161,10 +165,10 @@ class UpdateServiceRequest(proto.Message): r"""The ``UpdateService`` request. Attributes: - service (~.gm_service.Service): + service (google.cloud.monitoring_v3.types.Service): Required. The ``Service`` to draw updates from. The given ``name`` specifies the resource to update. - update_mask (~.field_mask.FieldMask): + update_mask (google.protobuf.field_mask_pb2.FieldMask): A set of field paths defining which fields to use for the update. """ @@ -205,7 +209,7 @@ class CreateServiceLevelObjectiveRequest(proto.Message): Optional. The ServiceLevelObjective id to use for this ServiceLevelObjective. If omitted, an id will be generated instead. Must match the pattern ``[a-z0-9\-]+`` - service_level_objective (~.gm_service.ServiceLevelObjective): + service_level_objective (google.cloud.monitoring_v3.types.ServiceLevelObjective): Required. The ``ServiceLevelObjective`` to create. The provided ``name`` will be respected if no ``ServiceLevelObjective`` exists with this name. @@ -231,7 +235,7 @@ class GetServiceLevelObjectiveRequest(proto.Message): :: projects/[PROJECT_ID_OR_NUMBER]/services/[SERVICE_ID]/serviceLevelObjectives/[SLO_NAME] - view (~.gm_service.ServiceLevelObjective.View): + view (google.cloud.monitoring_v3.types.ServiceLevelObjective.View): View of the ``ServiceLevelObjective`` to return. If ``DEFAULT``, return the ``ServiceLevelObjective`` as originally defined. If ``EXPLICIT`` and the @@ -272,7 +276,7 @@ class ListServiceLevelObjectivesRequest(proto.Message): ``nextPageToken`` value returned by a previous call to this method. Using this field causes the method to return additional results from the previous method call. - view (~.gm_service.ServiceLevelObjective.View): + view (google.cloud.monitoring_v3.types.ServiceLevelObjective.View): View of the ``ServiceLevelObjective``\ s to return. If ``DEFAULT``, return each ``ServiceLevelObjective`` as originally defined. If ``EXPLICIT`` and the @@ -298,7 +302,7 @@ class ListServiceLevelObjectivesResponse(proto.Message): r"""The ``ListServiceLevelObjectives`` response. Attributes: - service_level_objectives (Sequence[~.gm_service.ServiceLevelObjective]): + service_level_objectives (Sequence[google.cloud.monitoring_v3.types.ServiceLevelObjective]): The ``ServiceLevelObjective``\ s matching the specified filter. next_page_token (str): @@ -323,10 +327,10 @@ class UpdateServiceLevelObjectiveRequest(proto.Message): r"""The ``UpdateServiceLevelObjective`` request. Attributes: - service_level_objective (~.gm_service.ServiceLevelObjective): + service_level_objective (google.cloud.monitoring_v3.types.ServiceLevelObjective): Required. The ``ServiceLevelObjective`` to draw updates from. The given ``name`` specifies the resource to update. - update_mask (~.field_mask.FieldMask): + update_mask (google.protobuf.field_mask_pb2.FieldMask): A set of field paths defining which fields to use for the update. """ diff --git a/google/cloud/monitoring_v3/types/uptime.py b/google/cloud/monitoring_v3/types/uptime.py index f77dd2b8..9576dff4 100644 --- a/google/cloud/monitoring_v3/types/uptime.py +++ b/google/cloud/monitoring_v3/types/uptime.py @@ -89,7 +89,7 @@ class InternalChecker(proto.Message): The GCP project ID where the internal checker lives. Not necessary the same as the Workspace project. - state (~.uptime.InternalChecker.State): + state (google.cloud.monitoring_v3.types.InternalChecker.State): The current operational state of the internal checker. """ @@ -126,6 +126,9 @@ class UptimeCheckConfig(proto.Message): projects/[PROJECT_ID_OR_NUMBER]/uptimeCheckConfigs/[UPTIME_CHECK_ID] + ``[PROJECT_ID_OR_NUMBER]`` is the Workspace host project + associated with the Uptime check. + This field should be omitted when creating the Uptime check configuration; on create, the resource name is assigned by the server and included in the response. @@ -135,39 +138,39 @@ class UptimeCheckConfig(proto.Message): within a Stackdriver Workspace in order to make it easier to identify; however, uniqueness is not enforced. Required. - monitored_resource (~.ga_monitored_resource.MonitoredResource): + monitored_resource (google.api.monitored_resource_pb2.MonitoredResource): The `monitored resource `__ associated with the configuration. The following monitored resource types are supported for Uptime checks: ``uptime_url``, ``gce_instance``, ``gae_app``, ``aws_ec2_instance``, ``aws_elb_load_balancer`` - resource_group (~.uptime.UptimeCheckConfig.ResourceGroup): + resource_group (google.cloud.monitoring_v3.types.UptimeCheckConfig.ResourceGroup): The group resource associated with the configuration. - http_check (~.uptime.UptimeCheckConfig.HttpCheck): + http_check (google.cloud.monitoring_v3.types.UptimeCheckConfig.HttpCheck): Contains information needed to make an HTTP or HTTPS check. - tcp_check (~.uptime.UptimeCheckConfig.TcpCheck): + tcp_check (google.cloud.monitoring_v3.types.UptimeCheckConfig.TcpCheck): Contains information needed to make a TCP check. - period (~.duration.Duration): + period (google.protobuf.duration_pb2.Duration): How often, in seconds, the Uptime check is performed. Currently, the only supported values are ``60s`` (1 minute), ``300s`` (5 minutes), ``600s`` (10 minutes), and ``900s`` (15 minutes). Optional, defaults to ``60s``. - timeout (~.duration.Duration): + timeout (google.protobuf.duration_pb2.Duration): The maximum amount of time to wait for the request to complete (must be between 1 and 60 seconds). Required. - content_matchers (Sequence[~.uptime.UptimeCheckConfig.ContentMatcher]): + content_matchers (Sequence[google.cloud.monitoring_v3.types.UptimeCheckConfig.ContentMatcher]): The content that is expected to appear in the data returned by the target server against which the check is run. Currently, only the first entry in the ``content_matchers`` list is supported, and additional entries will be ignored. This field is optional and should only be specified if a content match is required as part of the/ Uptime check. - selected_regions (Sequence[~.uptime.UptimeCheckRegion]): + selected_regions (Sequence[google.cloud.monitoring_v3.types.UptimeCheckRegion]): The list of regions from which the check will be run. Some regions contain one location, and others contain more than one. If this field is @@ -182,7 +185,7 @@ class UptimeCheckConfig(proto.Message): provide 'selected_regions' when is_internal is ``true``, or to provide 'internal_checkers' when is_internal is ``false``. - internal_checkers (Sequence[~.uptime.InternalChecker]): + internal_checkers (Sequence[google.cloud.monitoring_v3.types.InternalChecker]): The internal checkers that this check will egress from. If ``is_internal`` is ``true`` and this list is empty, the check will egress from all the InternalCheckers configured @@ -199,7 +202,7 @@ class ResourceGroup(proto.Message): The group of resources being monitored. Should be only the ``[GROUP_ID]``, and not the full-path ``projects/[PROJECT_ID_OR_NUMBER]/groups/[GROUP_ID]``. - resource_type (~.uptime.GroupResourceType): + resource_type (google.cloud.monitoring_v3.types.GroupResourceType): The resource type of the group members. """ @@ -211,8 +214,10 @@ class HttpCheck(proto.Message): r"""Information involved in an HTTP/HTTPS Uptime check request. Attributes: - request_method (~.uptime.UptimeCheckConfig.HttpCheck.RequestMethod): - The HTTP request method to use for the check. + request_method (google.cloud.monitoring_v3.types.UptimeCheckConfig.HttpCheck.RequestMethod): + The HTTP request method to use for the check. If set to + ``METHOD_UNSPECIFIED`` then ``request_method`` defaults to + ``GET``. use_ssl (bool): If ``true``, use HTTPS instead of HTTP to run the check. path (str): @@ -227,18 +232,18 @@ class HttpCheck(proto.Message): server against which to run the check. Will be combined with host (specified within the ``monitored_resource``) and ``path`` to construct the full URL. - auth_info (~.uptime.UptimeCheckConfig.HttpCheck.BasicAuthentication): + auth_info (google.cloud.monitoring_v3.types.UptimeCheckConfig.HttpCheck.BasicAuthentication): The authentication information. Optional when creating an HTTP check; defaults to empty. mask_headers (bool): - Boolean specifiying whether to encrypt the header + Boolean specifying whether to encrypt the header information. Encryption should be specified for any headers related to authentication that you do not wish to be seen when retrieving the configuration. The server will be responsible for encrypting the headers. On Get/List calls, if ``mask_headers`` is set to ``true`` then the headers will be obscured with ``******.`` - headers (Sequence[~.uptime.UptimeCheckConfig.HttpCheck.HeadersEntry]): + headers (Sequence[google.cloud.monitoring_v3.types.UptimeCheckConfig.HttpCheck.HeadersEntry]): The list of headers to send as part of the Uptime check request. If two headers have the same key and different values, they should be @@ -250,8 +255,19 @@ class HttpCheck(proto.Message): the same key in a Create call will cause the first to be overwritten by the second. The maximum number of headers allowed is 100. - content_type (~.uptime.UptimeCheckConfig.HttpCheck.ContentType): - The content type to use for the check. + content_type (google.cloud.monitoring_v3.types.UptimeCheckConfig.HttpCheck.ContentType): + The content type header to use for the check. The following + configurations result in errors: + + 1. Content type is specified in both the ``headers`` field + and the ``content_type`` field. + 2. Request method is ``GET`` and ``content_type`` is not + ``TYPE_UNSPECIFIED`` + 3. Request method is ``POST`` and ``content_type`` is + ``TYPE_UNSPECIFIED``. + 4. Request method is ``POST`` and a "Content-Type" header is + provided via ``headers`` field. The ``content_type`` + field should be used instead. validate_ssl (bool): Boolean specifying whether to include SSL certificate validation as a part of the Uptime check. Only applies to @@ -259,12 +275,16 @@ class HttpCheck(proto.Message): ``uptime_url``. If ``use_ssl`` is ``false``, setting ``validate_ssl`` to ``true`` has no effect. body (bytes): - The request body associated with the HTTP request. If + The request body associated with the HTTP POST request. If ``content_type`` is ``URL_ENCODED``, the body passed in must be URL-encoded. Users can provide a ``Content-Length`` - header via the ``headers`` field or the API will do so. The - maximum byte size is 1 megabyte. Note: As with all ``bytes`` - fields JSON representations are base64 encoded. + header via the ``headers`` field or the API will do so. If + the ``request_method`` is ``GET`` and ``body`` is not empty, + the API will return an error. The maximum byte size is 1 + megabyte. Note: As with all ``bytes`` fields, JSON + representations are base64 encoded. e.g.: "foo=bar" in + URL-encoded form is "foo%3Dbar" and in base64 encoding is + "Zm9vJTI1M0RiYXI=". """ class RequestMethod(proto.Enum): @@ -274,9 +294,8 @@ class RequestMethod(proto.Enum): POST = 2 class ContentType(proto.Enum): - r"""Header options corresponding to the Content-Type of the body in HTTP - requests. Note that a ``Content-Type`` header cannot be present in - the ``headers`` field if this field is specified. + r"""Header options corresponding to the content type of a HTTP + request body. """ TYPE_UNSPECIFIED = 0 URL_ENCODED = 1 @@ -352,7 +371,7 @@ class ContentMatcher(proto.Message): String or regex content to match. Maximum 1024 bytes. An empty ``content`` string indicates no content matching is to be performed. - matcher (~.uptime.UptimeCheckConfig.ContentMatcher.ContentMatcherOption): + matcher (google.cloud.monitoring_v3.types.UptimeCheckConfig.ContentMatcher.ContentMatcherOption): The type of content matcher that will be applied to the server output, compared to the ``content`` string when the check is run. @@ -421,7 +440,7 @@ class UptimeCheckIp(proto.Message): addresses where checkers in the location run from. Attributes: - region (~.uptime.UptimeCheckRegion): + region (google.cloud.monitoring_v3.types.UptimeCheckRegion): A broad region category in which the IP address is located. location (str): diff --git a/google/cloud/monitoring_v3/types/uptime_service.py b/google/cloud/monitoring_v3/types/uptime_service.py index 405bf976..c5b53b1d 100644 --- a/google/cloud/monitoring_v3/types/uptime_service.py +++ b/google/cloud/monitoring_v3/types/uptime_service.py @@ -72,7 +72,7 @@ class ListUptimeCheckConfigsResponse(proto.Message): r"""The protocol for the ``ListUptimeCheckConfigs`` response. Attributes: - uptime_check_configs (Sequence[~.uptime.UptimeCheckConfig]): + uptime_check_configs (Sequence[google.cloud.monitoring_v3.types.UptimeCheckConfig]): The returned Uptime check configurations. next_page_token (str): This field represents the pagination token to retrieve the @@ -127,7 +127,7 @@ class CreateUptimeCheckConfigRequest(proto.Message): :: projects/[PROJECT_ID_OR_NUMBER] - uptime_check_config (~.uptime.UptimeCheckConfig): + uptime_check_config (google.cloud.monitoring_v3.types.UptimeCheckConfig): Required. The new Uptime check configuration. """ @@ -142,14 +142,14 @@ class UpdateUptimeCheckConfigRequest(proto.Message): r"""The protocol for the ``UpdateUptimeCheckConfig`` request. Attributes: - update_mask (~.field_mask.FieldMask): + update_mask (google.protobuf.field_mask_pb2.FieldMask): Optional. If present, only the listed fields in the current Uptime check configuration are updated with values from the new configuration. If this field is empty, then the current configuration is completely replaced with the new configuration. - uptime_check_config (~.uptime.UptimeCheckConfig): + uptime_check_config (google.cloud.monitoring_v3.types.UptimeCheckConfig): Required. If an ``updateMask`` has been specified, this field gives the values for the set of fields mentioned in the ``updateMask``. If an ``updateMask`` has not been given, @@ -215,7 +215,7 @@ class ListUptimeCheckIpsResponse(proto.Message): r"""The protocol for the ``ListUptimeCheckIps`` response. Attributes: - uptime_check_ips (Sequence[~.uptime.UptimeCheckIp]): + uptime_check_ips (Sequence[google.cloud.monitoring_v3.types.UptimeCheckIp]): The returned list of IP addresses (including region and location) that the checkers run from. next_page_token (str): diff --git a/scripts/fixup_monitoring_v3_keywords.py b/scripts/fixup_monitoring_v3_keywords.py index 5527d130..3ed5bc4a 100644 --- a/scripts/fixup_monitoring_v3_keywords.py +++ b/scripts/fixup_monitoring_v3_keywords.py @@ -75,9 +75,10 @@ class monitoringCallTransformer(cst.CSTTransformer): 'list_notification_channels': ('name', 'filter', 'order_by', 'page_size', 'page_token', ), 'list_service_level_objectives': ('parent', 'filter', 'page_size', 'page_token', 'view', ), 'list_services': ('parent', 'filter', 'page_size', 'page_token', ), - 'list_time_series': ('name', 'filter', 'interval', 'view', 'aggregation', 'order_by', 'page_size', 'page_token', ), + 'list_time_series': ('name', 'filter', 'interval', 'view', 'aggregation', 'secondary_aggregation', 'order_by', 'page_size', 'page_token', ), 'list_uptime_check_configs': ('parent', 'page_size', 'page_token', ), 'list_uptime_check_ips': ('page_size', 'page_token', ), + 'query_time_series': ('name', 'query', 'page_size', 'page_token', ), 'send_notification_channel_verification_code': ('name', ), 'update_alert_policy': ('alert_policy', 'update_mask', ), 'update_group': ('group', 'validate_only', ), diff --git a/synth.metadata b/synth.metadata index 6da94df5..edcb86d3 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,15 +4,15 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-monitoring.git", - "sha": "9f74808af641ce63787b64f2e3de713a50977a71" + "sha": "f716011b74c5f7b2ce59b432dfef585050cfd9d8" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "69697504d9eba1d064820c3085b4750767be6d08", - "internalRef": "348952930" + "sha": "a1af63efb82f54428ab35ea76869d9cd57ca52b8", + "internalRef": "364635275" } }, { @@ -42,6 +42,7 @@ } ], "generatedFiles": [ + ".coveragerc", ".flake8", ".github/CONTRIBUTING.md", ".github/ISSUE_TEMPLATE/bug_report.md", @@ -95,8 +96,15 @@ "docs/_static/custom.css", "docs/_templates/layout.html", "docs/conf.py", + "docs/monitoring_v3/alert_policy_service.rst", + "docs/monitoring_v3/group_service.rst", + "docs/monitoring_v3/metric_service.rst", + "docs/monitoring_v3/notification_channel_service.rst", + "docs/monitoring_v3/query_service.rst", + "docs/monitoring_v3/service_monitoring_service.rst", "docs/monitoring_v3/services.rst", "docs/monitoring_v3/types.rst", + "docs/monitoring_v3/uptime_check_service.rst", "docs/multiprocessing.rst", "google/cloud/monitoring/__init__.py", "google/cloud/monitoring/py.typed", @@ -112,6 +120,7 @@ "google/cloud/monitoring_v3/proto/mutation_record.proto", "google/cloud/monitoring_v3/proto/notification.proto", "google/cloud/monitoring_v3/proto/notification_service.proto", + "google/cloud/monitoring_v3/proto/query_service.proto", "google/cloud/monitoring_v3/proto/service.proto", "google/cloud/monitoring_v3/proto/service_service.proto", "google/cloud/monitoring_v3/proto/span_context.proto", @@ -151,6 +160,14 @@ "google/cloud/monitoring_v3/services/notification_channel_service/transports/base.py", "google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc.py", "google/cloud/monitoring_v3/services/notification_channel_service/transports/grpc_asyncio.py", + "google/cloud/monitoring_v3/services/query_service/__init__.py", + "google/cloud/monitoring_v3/services/query_service/async_client.py", + "google/cloud/monitoring_v3/services/query_service/client.py", + "google/cloud/monitoring_v3/services/query_service/pagers.py", + "google/cloud/monitoring_v3/services/query_service/transports/__init__.py", + "google/cloud/monitoring_v3/services/query_service/transports/base.py", + "google/cloud/monitoring_v3/services/query_service/transports/grpc.py", + "google/cloud/monitoring_v3/services/query_service/transports/grpc_asyncio.py", "google/cloud/monitoring_v3/services/service_monitoring_service/__init__.py", "google/cloud/monitoring_v3/services/service_monitoring_service/async_client.py", "google/cloud/monitoring_v3/services/service_monitoring_service/client.py", @@ -179,6 +196,7 @@ "google/cloud/monitoring_v3/types/mutation_record.py", "google/cloud/monitoring_v3/types/notification.py", "google/cloud/monitoring_v3/types/notification_service.py", + "google/cloud/monitoring_v3/types/query_service.py", "google/cloud/monitoring_v3/types/service.py", "google/cloud/monitoring_v3/types/service_service.py", "google/cloud/monitoring_v3/types/span_context.py", @@ -207,6 +225,7 @@ "tests/unit/gapic/monitoring_v3/test_group_service.py", "tests/unit/gapic/monitoring_v3/test_metric_service.py", "tests/unit/gapic/monitoring_v3/test_notification_channel_service.py", + "tests/unit/gapic/monitoring_v3/test_query_service.py", "tests/unit/gapic/monitoring_v3/test_service_monitoring_service.py", "tests/unit/gapic/monitoring_v3/test_uptime_check_service.py" ] diff --git a/tests/unit/gapic/monitoring_v3/__init__.py b/tests/unit/gapic/monitoring_v3/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/monitoring_v3/__init__.py +++ b/tests/unit/gapic/monitoring_v3/__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/tests/unit/gapic/monitoring_v3/test_alert_policy_service.py b/tests/unit/gapic/monitoring_v3/test_alert_policy_service.py index 1011908a..6a273388 100644 --- a/tests/unit/gapic/monitoring_v3/test_alert_policy_service.py +++ b/tests/unit/gapic/monitoring_v3/test_alert_policy_service.py @@ -99,7 +99,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [AlertPolicyServiceClient, AlertPolicyServiceAsyncClient] + "client_class", [AlertPolicyServiceClient, AlertPolicyServiceAsyncClient,] +) +def test_alert_policy_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 == "monitoring.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [AlertPolicyServiceClient, AlertPolicyServiceAsyncClient,] ) def test_alert_policy_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -109,16 +126,21 @@ def test_alert_policy_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 == "monitoring.googleapis.com:443" def test_alert_policy_service_client_get_transport_class(): transport = AlertPolicyServiceClient.get_transport_class() - assert transport == transports.AlertPolicyServiceGrpcTransport + available_transports = [ + transports.AlertPolicyServiceGrpcTransport, + ] + assert transport in available_transports transport = AlertPolicyServiceClient.get_transport_class("grpc") assert transport == transports.AlertPolicyServiceGrpcTransport @@ -169,7 +191,7 @@ def test_alert_policy_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, ) @@ -185,7 +207,7 @@ def test_alert_policy_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, ) @@ -201,7 +223,7 @@ def test_alert_policy_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, ) @@ -229,7 +251,7 @@ def test_alert_policy_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, ) @@ -290,29 +312,25 @@ def test_alert_policy_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. @@ -321,66 +339,53 @@ def test_alert_policy_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", @@ -406,7 +411,7 @@ def test_alert_policy_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, ) @@ -436,7 +441,7 @@ def test_alert_policy_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, ) @@ -455,7 +460,7 @@ def test_alert_policy_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, ) @@ -478,7 +483,7 @@ def test_list_alert_policies( ) as call: # Designate an appropriate return value for the call. call.return_value = alert_service.ListAlertPoliciesResponse( - next_page_token="next_page_token_value", + next_page_token="next_page_token_value", total_size=1086, ) response = client.list_alert_policies(request) @@ -495,11 +500,31 @@ def test_list_alert_policies( assert response.next_page_token == "next_page_token_value" + assert response.total_size == 1086 + def test_list_alert_policies_from_dict(): test_list_alert_policies(request_type=dict) +def test_list_alert_policies_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 = AlertPolicyServiceClient( + 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_alert_policies), "__call__" + ) as call: + client.list_alert_policies() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == alert_service.ListAlertPoliciesRequest() + + @pytest.mark.asyncio async def test_list_alert_policies_async( transport: str = "grpc_asyncio", request_type=alert_service.ListAlertPoliciesRequest @@ -519,7 +544,7 @@ async def test_list_alert_policies_async( # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( alert_service.ListAlertPoliciesResponse( - next_page_token="next_page_token_value", + next_page_token="next_page_token_value", total_size=1086, ) ) @@ -536,6 +561,8 @@ async def test_list_alert_policies_async( assert response.next_page_token == "next_page_token_value" + assert response.total_size == 1086 + @pytest.mark.asyncio async def test_list_alert_policies_async_from_dict(): @@ -878,6 +905,22 @@ def test_get_alert_policy_from_dict(): test_get_alert_policy(request_type=dict) +def test_get_alert_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 = AlertPolicyServiceClient( + 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_alert_policy), "__call__") as call: + client.get_alert_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == alert_service.GetAlertPolicyRequest() + + @pytest.mark.asyncio async def test_get_alert_policy_async( transport: str = "grpc_asyncio", request_type=alert_service.GetAlertPolicyRequest @@ -1095,6 +1138,24 @@ def test_create_alert_policy_from_dict(): test_create_alert_policy(request_type=dict) +def test_create_alert_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 = AlertPolicyServiceClient( + 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_alert_policy), "__call__" + ) as call: + client.create_alert_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == alert_service.CreateAlertPolicyRequest() + + @pytest.mark.asyncio async def test_create_alert_policy_async( transport: str = "grpc_asyncio", request_type=alert_service.CreateAlertPolicyRequest @@ -1320,6 +1381,24 @@ def test_delete_alert_policy_from_dict(): test_delete_alert_policy(request_type=dict) +def test_delete_alert_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 = AlertPolicyServiceClient( + 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_alert_policy), "__call__" + ) as call: + client.delete_alert_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == alert_service.DeleteAlertPolicyRequest() + + @pytest.mark.asyncio async def test_delete_alert_policy_async( transport: str = "grpc_asyncio", request_type=alert_service.DeleteAlertPolicyRequest @@ -1532,6 +1611,24 @@ def test_update_alert_policy_from_dict(): test_update_alert_policy(request_type=dict) +def test_update_alert_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 = AlertPolicyServiceClient( + 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_alert_policy), "__call__" + ) as call: + client.update_alert_policy() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == alert_service.UpdateAlertPolicyRequest() + + @pytest.mark.asyncio async def test_update_alert_policy_async( transport: str = "grpc_asyncio", request_type=alert_service.UpdateAlertPolicyRequest @@ -1906,6 +2003,57 @@ def test_alert_policy_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.AlertPolicyServiceGrpcTransport, + transports.AlertPolicyServiceGrpcAsyncIOTransport, + ], +) +def test_alert_policy_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/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + 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_alert_policy_service_host_no_port(): client = AlertPolicyServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1927,7 +2075,7 @@ def test_alert_policy_service_host_with_port(): def test_alert_policy_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.AlertPolicyServiceGrpcTransport( @@ -1939,7 +2087,7 @@ def test_alert_policy_service_grpc_transport_channel(): def test_alert_policy_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.AlertPolicyServiceGrpcAsyncIOTransport( @@ -1950,6 +2098,8 @@ def test_alert_policy_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", [ @@ -1964,7 +2114,7 @@ def test_alert_policy_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 @@ -2006,6 +2156,8 @@ def test_alert_policy_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", [ @@ -2021,7 +2173,7 @@ def test_alert_policy_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 diff --git a/tests/unit/gapic/monitoring_v3/test_group_service.py b/tests/unit/gapic/monitoring_v3/test_group_service.py index 8efea06a..b4025200 100644 --- a/tests/unit/gapic/monitoring_v3/test_group_service.py +++ b/tests/unit/gapic/monitoring_v3/test_group_service.py @@ -86,7 +86,22 @@ def test__get_default_mtls_endpoint(): assert GroupServiceClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi -@pytest.mark.parametrize("client_class", [GroupServiceClient, GroupServiceAsyncClient]) +@pytest.mark.parametrize("client_class", [GroupServiceClient, GroupServiceAsyncClient,]) +def test_group_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 == "monitoring.googleapis.com:443" + + +@pytest.mark.parametrize("client_class", [GroupServiceClient, GroupServiceAsyncClient,]) def test_group_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() with mock.patch.object( @@ -95,16 +110,21 @@ def test_group_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 == "monitoring.googleapis.com:443" def test_group_service_client_get_transport_class(): transport = GroupServiceClient.get_transport_class() - assert transport == transports.GroupServiceGrpcTransport + available_transports = [ + transports.GroupServiceGrpcTransport, + ] + assert transport in available_transports transport = GroupServiceClient.get_transport_class("grpc") assert transport == transports.GroupServiceGrpcTransport @@ -153,7 +173,7 @@ def test_group_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, ) @@ -169,7 +189,7 @@ def test_group_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, ) @@ -185,7 +205,7 @@ def test_group_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, ) @@ -213,7 +233,7 @@ def test_group_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, ) @@ -262,29 +282,25 @@ def test_group_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. @@ -293,66 +309,53 @@ def test_group_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", @@ -378,7 +381,7 @@ def test_group_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, ) @@ -408,7 +411,7 @@ def test_group_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, ) @@ -425,7 +428,7 @@ def test_group_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, ) @@ -468,6 +471,22 @@ def test_list_groups_from_dict(): test_list_groups(request_type=dict) +def test_list_groups_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 = GroupServiceClient( + 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_groups), "__call__") as call: + client.list_groups() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == group_service.ListGroupsRequest() + + @pytest.mark.asyncio async def test_list_groups_async( transport: str = "grpc_asyncio", request_type=group_service.ListGroupsRequest @@ -785,6 +804,22 @@ def test_get_group_from_dict(): test_get_group(request_type=dict) +def test_get_group_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 = GroupServiceClient( + 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_group), "__call__") as call: + client.get_group() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == group_service.GetGroupRequest() + + @pytest.mark.asyncio async def test_get_group_async( transport: str = "grpc_asyncio", request_type=group_service.GetGroupRequest @@ -1000,6 +1035,22 @@ def test_create_group_from_dict(): test_create_group(request_type=dict) +def test_create_group_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 = GroupServiceClient( + 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_group), "__call__") as call: + client.create_group() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == group_service.CreateGroupRequest() + + @pytest.mark.asyncio async def test_create_group_async( transport: str = "grpc_asyncio", request_type=group_service.CreateGroupRequest @@ -1227,6 +1278,22 @@ def test_update_group_from_dict(): test_update_group(request_type=dict) +def test_update_group_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 = GroupServiceClient( + 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_group), "__call__") as call: + client.update_group() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == group_service.UpdateGroupRequest() + + @pytest.mark.asyncio async def test_update_group_async( transport: str = "grpc_asyncio", request_type=group_service.UpdateGroupRequest @@ -1425,6 +1492,22 @@ def test_delete_group_from_dict(): test_delete_group(request_type=dict) +def test_delete_group_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 = GroupServiceClient( + 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_group), "__call__") as call: + client.delete_group() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == group_service.DeleteGroupRequest() + + @pytest.mark.asyncio async def test_delete_group_async( transport: str = "grpc_asyncio", request_type=group_service.DeleteGroupRequest @@ -1614,6 +1697,24 @@ def test_list_group_members_from_dict(): test_list_group_members(request_type=dict) +def test_list_group_members_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 = GroupServiceClient( + 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_group_members), "__call__" + ) as call: + client.list_group_members() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == group_service.ListGroupMembersRequest() + + @pytest.mark.asyncio async def test_list_group_members_async( transport: str = "grpc_asyncio", request_type=group_service.ListGroupMembersRequest @@ -2004,7 +2105,10 @@ def test_transport_get_channel(): @pytest.mark.parametrize( "transport_class", - [transports.GroupServiceGrpcTransport, transports.GroupServiceGrpcAsyncIOTransport], + [ + transports.GroupServiceGrpcTransport, + transports.GroupServiceGrpcAsyncIOTransport, + ], ) def test_transport_adc(transport_class): # Test default credentials are used if not provided. @@ -2121,6 +2225,52 @@ def test_group_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [transports.GroupServiceGrpcTransport, transports.GroupServiceGrpcAsyncIOTransport], +) +def test_group_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/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + 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_group_service_host_no_port(): client = GroupServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2142,7 +2292,7 @@ def test_group_service_host_with_port(): def test_group_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.GroupServiceGrpcTransport( @@ -2154,7 +2304,7 @@ def test_group_service_grpc_transport_channel(): def test_group_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.GroupServiceGrpcAsyncIOTransport( @@ -2165,6 +2315,8 @@ def test_group_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", [transports.GroupServiceGrpcTransport, transports.GroupServiceGrpcAsyncIOTransport], @@ -2174,7 +2326,7 @@ def test_group_service_transport_channel_mtls_with_client_cert_source(transport_ "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 @@ -2216,6 +2368,8 @@ def test_group_service_transport_channel_mtls_with_client_cert_source(transport_ 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", [transports.GroupServiceGrpcTransport, transports.GroupServiceGrpcAsyncIOTransport], @@ -2228,7 +2382,7 @@ def test_group_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 diff --git a/tests/unit/gapic/monitoring_v3/test_metric_service.py b/tests/unit/gapic/monitoring_v3/test_metric_service.py index a88ac1af..4ed4f946 100644 --- a/tests/unit/gapic/monitoring_v3/test_metric_service.py +++ b/tests/unit/gapic/monitoring_v3/test_metric_service.py @@ -96,7 +96,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [MetricServiceClient, MetricServiceAsyncClient] + "client_class", [MetricServiceClient, MetricServiceAsyncClient,] +) +def test_metric_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 == "monitoring.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [MetricServiceClient, MetricServiceAsyncClient,] ) def test_metric_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -106,16 +123,21 @@ def test_metric_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 == "monitoring.googleapis.com:443" def test_metric_service_client_get_transport_class(): transport = MetricServiceClient.get_transport_class() - assert transport == transports.MetricServiceGrpcTransport + available_transports = [ + transports.MetricServiceGrpcTransport, + ] + assert transport in available_transports transport = MetricServiceClient.get_transport_class("grpc") assert transport == transports.MetricServiceGrpcTransport @@ -166,7 +188,7 @@ def test_metric_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_metric_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_metric_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_metric_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, ) @@ -277,29 +299,25 @@ def test_metric_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. @@ -308,66 +326,53 @@ def test_metric_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", @@ -393,7 +398,7 @@ def test_metric_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, ) @@ -423,7 +428,7 @@ def test_metric_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, ) @@ -442,7 +447,7 @@ def test_metric_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, ) @@ -488,6 +493,24 @@ def test_list_monitored_resource_descriptors_from_dict(): test_list_monitored_resource_descriptors(request_type=dict) +def test_list_monitored_resource_descriptors_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 = MetricServiceClient( + 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_monitored_resource_descriptors), "__call__" + ) as call: + client.list_monitored_resource_descriptors() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.ListMonitoredResourceDescriptorsRequest() + + @pytest.mark.asyncio async def test_list_monitored_resource_descriptors_async( transport: str = "grpc_asyncio", @@ -892,6 +915,24 @@ def test_get_monitored_resource_descriptor_from_dict(): test_get_monitored_resource_descriptor(request_type=dict) +def test_get_monitored_resource_descriptor_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 = MetricServiceClient( + 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_monitored_resource_descriptor), "__call__" + ) as call: + client.get_monitored_resource_descriptor() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.GetMonitoredResourceDescriptorRequest() + + @pytest.mark.asyncio async def test_get_monitored_resource_descriptor_async( transport: str = "grpc_asyncio", @@ -1109,6 +1150,24 @@ def test_list_metric_descriptors_from_dict(): test_list_metric_descriptors(request_type=dict) +def test_list_metric_descriptors_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 = MetricServiceClient( + 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_metric_descriptors), "__call__" + ) as call: + client.list_metric_descriptors() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.ListMetricDescriptorsRequest() + + @pytest.mark.asyncio async def test_list_metric_descriptors_async( transport: str = "grpc_asyncio", @@ -1505,6 +1564,24 @@ def test_get_metric_descriptor_from_dict(): test_get_metric_descriptor(request_type=dict) +def test_get_metric_descriptor_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 = MetricServiceClient( + 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_metric_descriptor), "__call__" + ) as call: + client.get_metric_descriptor() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.GetMetricDescriptorRequest() + + @pytest.mark.asyncio async def test_get_metric_descriptor_async( transport: str = "grpc_asyncio", @@ -1749,6 +1826,24 @@ def test_create_metric_descriptor_from_dict(): test_create_metric_descriptor(request_type=dict) +def test_create_metric_descriptor_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 = MetricServiceClient( + 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_metric_descriptor), "__call__" + ) as call: + client.create_metric_descriptor() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.CreateMetricDescriptorRequest() + + @pytest.mark.asyncio async def test_create_metric_descriptor_async( transport: str = "grpc_asyncio", @@ -1988,6 +2083,24 @@ def test_delete_metric_descriptor_from_dict(): test_delete_metric_descriptor(request_type=dict) +def test_delete_metric_descriptor_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 = MetricServiceClient( + 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_metric_descriptor), "__call__" + ) as call: + client.delete_metric_descriptor() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.DeleteMetricDescriptorRequest() + + @pytest.mark.asyncio async def test_delete_metric_descriptor_async( transport: str = "grpc_asyncio", @@ -2162,7 +2275,7 @@ def test_list_time_series( with mock.patch.object(type(client.transport.list_time_series), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = metric_service.ListTimeSeriesResponse( - next_page_token="next_page_token_value", + next_page_token="next_page_token_value", unit="unit_value", ) response = client.list_time_series(request) @@ -2179,11 +2292,29 @@ def test_list_time_series( assert response.next_page_token == "next_page_token_value" + assert response.unit == "unit_value" + def test_list_time_series_from_dict(): test_list_time_series(request_type=dict) +def test_list_time_series_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 = MetricServiceClient( + 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_time_series), "__call__") as call: + client.list_time_series() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.ListTimeSeriesRequest() + + @pytest.mark.asyncio async def test_list_time_series_async( transport: str = "grpc_asyncio", request_type=metric_service.ListTimeSeriesRequest @@ -2201,7 +2332,7 @@ async def test_list_time_series_async( # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( metric_service.ListTimeSeriesResponse( - next_page_token="next_page_token_value", + next_page_token="next_page_token_value", unit="unit_value", ) ) @@ -2218,6 +2349,8 @@ async def test_list_time_series_async( assert response.next_page_token == "next_page_token_value" + assert response.unit == "unit_value" + @pytest.mark.asyncio async def test_list_time_series_async_from_dict(): @@ -2560,6 +2693,24 @@ def test_create_time_series_from_dict(): test_create_time_series(request_type=dict) +def test_create_time_series_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 = MetricServiceClient( + 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_time_series), "__call__" + ) as call: + client.create_time_series() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.CreateTimeSeriesRequest() + + @pytest.mark.asyncio async def test_create_time_series_async( transport: str = "grpc_asyncio", request_type=metric_service.CreateTimeSeriesRequest @@ -2925,6 +3076,56 @@ def test_metric_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.MetricServiceGrpcTransport, + transports.MetricServiceGrpcAsyncIOTransport, + ], +) +def test_metric_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/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + "https://www.googleapis.com/auth/monitoring.write", + ), + 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_metric_service_host_no_port(): client = MetricServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2946,7 +3147,7 @@ def test_metric_service_host_with_port(): def test_metric_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.MetricServiceGrpcTransport( @@ -2958,7 +3159,7 @@ def test_metric_service_grpc_transport_channel(): def test_metric_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.MetricServiceGrpcAsyncIOTransport( @@ -2969,6 +3170,8 @@ def test_metric_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", [ @@ -2981,7 +3184,7 @@ def test_metric_service_transport_channel_mtls_with_client_cert_source(transport "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 @@ -3024,6 +3227,8 @@ def test_metric_service_transport_channel_mtls_with_client_cert_source(transport 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", [ @@ -3039,7 +3244,7 @@ def test_metric_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 @@ -3120,8 +3325,31 @@ def test_parse_monitored_resource_descriptor_path(): assert expected == actual +def test_time_series_path(): + project = "cuttlefish" + time_series = "mussel" + + expected = "projects/{project}/timeSeries/{time_series}".format( + project=project, time_series=time_series, + ) + actual = MetricServiceClient.time_series_path(project, time_series) + assert expected == actual + + +def test_parse_time_series_path(): + expected = { + "project": "winkle", + "time_series": "nautilus", + } + path = MetricServiceClient.time_series_path(**expected) + + # Check that the path construction is reversible. + actual = MetricServiceClient.parse_time_series_path(path) + assert expected == actual + + def test_common_billing_account_path(): - billing_account = "cuttlefish" + billing_account = "scallop" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, @@ -3132,7 +3360,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "mussel", + "billing_account": "abalone", } path = MetricServiceClient.common_billing_account_path(**expected) @@ -3142,7 +3370,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "winkle" + folder = "squid" expected = "folders/{folder}".format(folder=folder,) actual = MetricServiceClient.common_folder_path(folder) @@ -3151,7 +3379,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "nautilus", + "folder": "clam", } path = MetricServiceClient.common_folder_path(**expected) @@ -3161,7 +3389,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "scallop" + organization = "whelk" expected = "organizations/{organization}".format(organization=organization,) actual = MetricServiceClient.common_organization_path(organization) @@ -3170,7 +3398,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "abalone", + "organization": "octopus", } path = MetricServiceClient.common_organization_path(**expected) @@ -3180,7 +3408,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "squid" + project = "oyster" expected = "projects/{project}".format(project=project,) actual = MetricServiceClient.common_project_path(project) @@ -3189,7 +3417,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "clam", + "project": "nudibranch", } path = MetricServiceClient.common_project_path(**expected) @@ -3199,8 +3427,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "whelk" - location = "octopus" + project = "cuttlefish" + location = "mussel" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -3211,8 +3439,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "oyster", - "location": "nudibranch", + "project": "winkle", + "location": "nautilus", } path = MetricServiceClient.common_location_path(**expected) diff --git a/tests/unit/gapic/monitoring_v3/test_notification_channel_service.py b/tests/unit/gapic/monitoring_v3/test_notification_channel_service.py index 7d063d04..a2fd1808 100644 --- a/tests/unit/gapic/monitoring_v3/test_notification_channel_service.py +++ b/tests/unit/gapic/monitoring_v3/test_notification_channel_service.py @@ -43,6 +43,7 @@ from google.cloud.monitoring_v3.services.notification_channel_service import pagers from google.cloud.monitoring_v3.services.notification_channel_service import transports from google.cloud.monitoring_v3.types import common +from google.cloud.monitoring_v3.types import mutation_record from google.cloud.monitoring_v3.types import notification from google.cloud.monitoring_v3.types import notification_service from google.oauth2 import service_account @@ -100,7 +101,25 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( "client_class", - [NotificationChannelServiceClient, NotificationChannelServiceAsyncClient], + [NotificationChannelServiceClient, NotificationChannelServiceAsyncClient,], +) +def test_notification_channel_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 == "monitoring.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", + [NotificationChannelServiceClient, NotificationChannelServiceAsyncClient,], ) def test_notification_channel_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -110,16 +129,21 @@ def test_notification_channel_service_client_from_service_account_file(client_cl 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 == "monitoring.googleapis.com:443" def test_notification_channel_service_client_get_transport_class(): transport = NotificationChannelServiceClient.get_transport_class() - assert transport == transports.NotificationChannelServiceGrpcTransport + available_transports = [ + transports.NotificationChannelServiceGrpcTransport, + ] + assert transport in available_transports transport = NotificationChannelServiceClient.get_transport_class("grpc") assert transport == transports.NotificationChannelServiceGrpcTransport @@ -178,7 +202,7 @@ def test_notification_channel_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, ) @@ -194,7 +218,7 @@ def test_notification_channel_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, ) @@ -210,7 +234,7 @@ def test_notification_channel_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, ) @@ -238,7 +262,7 @@ def test_notification_channel_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, ) @@ -299,29 +323,25 @@ def test_notification_channel_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. @@ -330,66 +350,53 @@ def test_notification_channel_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", @@ -419,7 +426,7 @@ def test_notification_channel_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, ) @@ -453,7 +460,7 @@ def test_notification_channel_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, ) @@ -472,7 +479,7 @@ def test_notification_channel_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, ) @@ -520,6 +527,26 @@ def test_list_notification_channel_descriptors_from_dict(): test_list_notification_channel_descriptors(request_type=dict) +def test_list_notification_channel_descriptors_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 = NotificationChannelServiceClient( + 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_notification_channel_descriptors), "__call__" + ) as call: + client.list_notification_channel_descriptors() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert ( + args[0] == notification_service.ListNotificationChannelDescriptorsRequest() + ) + + @pytest.mark.asyncio async def test_list_notification_channel_descriptors_async( transport: str = "grpc_asyncio", @@ -949,6 +976,24 @@ def test_get_notification_channel_descriptor_from_dict(): test_get_notification_channel_descriptor(request_type=dict) +def test_get_notification_channel_descriptor_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 = NotificationChannelServiceClient( + 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_notification_channel_descriptor), "__call__" + ) as call: + client.get_notification_channel_descriptor() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == notification_service.GetNotificationChannelDescriptorRequest() + + @pytest.mark.asyncio async def test_get_notification_channel_descriptor_async( transport: str = "grpc_asyncio", @@ -1162,7 +1207,7 @@ def test_list_notification_channels( ) as call: # Designate an appropriate return value for the call. call.return_value = notification_service.ListNotificationChannelsResponse( - next_page_token="next_page_token_value", + next_page_token="next_page_token_value", total_size=1086, ) response = client.list_notification_channels(request) @@ -1179,11 +1224,31 @@ def test_list_notification_channels( assert response.next_page_token == "next_page_token_value" + assert response.total_size == 1086 + def test_list_notification_channels_from_dict(): test_list_notification_channels(request_type=dict) +def test_list_notification_channels_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 = NotificationChannelServiceClient( + 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_notification_channels), "__call__" + ) as call: + client.list_notification_channels() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == notification_service.ListNotificationChannelsRequest() + + @pytest.mark.asyncio async def test_list_notification_channels_async( transport: str = "grpc_asyncio", @@ -1204,7 +1269,7 @@ async def test_list_notification_channels_async( # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( notification_service.ListNotificationChannelsResponse( - next_page_token="next_page_token_value", + next_page_token="next_page_token_value", total_size=1086, ) ) @@ -1221,6 +1286,8 @@ async def test_list_notification_channels_async( assert response.next_page_token == "next_page_token_value" + assert response.total_size == 1086 + @pytest.mark.asyncio async def test_list_notification_channels_async_from_dict(): @@ -1598,6 +1665,24 @@ def test_get_notification_channel_from_dict(): test_get_notification_channel(request_type=dict) +def test_get_notification_channel_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 = NotificationChannelServiceClient( + 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_notification_channel), "__call__" + ) as call: + client.get_notification_channel() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == notification_service.GetNotificationChannelRequest() + + @pytest.mark.asyncio async def test_get_notification_channel_async( transport: str = "grpc_asyncio", @@ -1849,6 +1934,24 @@ def test_create_notification_channel_from_dict(): test_create_notification_channel(request_type=dict) +def test_create_notification_channel_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 = NotificationChannelServiceClient( + 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_notification_channel), "__call__" + ) as call: + client.create_notification_channel() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == notification_service.CreateNotificationChannelRequest() + + @pytest.mark.asyncio async def test_create_notification_channel_async( transport: str = "grpc_asyncio", @@ -2118,6 +2221,24 @@ def test_update_notification_channel_from_dict(): test_update_notification_channel(request_type=dict) +def test_update_notification_channel_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 = NotificationChannelServiceClient( + 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_notification_channel), "__call__" + ) as call: + client.update_notification_channel() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == notification_service.UpdateNotificationChannelRequest() + + @pytest.mark.asyncio async def test_update_notification_channel_async( transport: str = "grpc_asyncio", @@ -2373,6 +2494,24 @@ def test_delete_notification_channel_from_dict(): test_delete_notification_channel(request_type=dict) +def test_delete_notification_channel_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 = NotificationChannelServiceClient( + 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_notification_channel), "__call__" + ) as call: + client.delete_notification_channel() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == notification_service.DeleteNotificationChannelRequest() + + @pytest.mark.asyncio async def test_delete_notification_channel_async( transport: str = "grpc_asyncio", @@ -2594,6 +2733,27 @@ def test_send_notification_channel_verification_code_from_dict(): test_send_notification_channel_verification_code(request_type=dict) +def test_send_notification_channel_verification_code_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 = NotificationChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.send_notification_channel_verification_code), "__call__" + ) as call: + client.send_notification_channel_verification_code() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert ( + args[0] + == notification_service.SendNotificationChannelVerificationCodeRequest() + ) + + @pytest.mark.asyncio async def test_send_notification_channel_verification_code_async( transport: str = "grpc_asyncio", @@ -2817,6 +2977,27 @@ def test_get_notification_channel_verification_code_from_dict(): test_get_notification_channel_verification_code(request_type=dict) +def test_get_notification_channel_verification_code_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 = NotificationChannelServiceClient( + 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_notification_channel_verification_code), "__call__" + ) as call: + client.get_notification_channel_verification_code() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert ( + args[0] + == notification_service.GetNotificationChannelVerificationCodeRequest() + ) + + @pytest.mark.asyncio async def test_get_notification_channel_verification_code_async( transport: str = "grpc_asyncio", @@ -3068,6 +3249,24 @@ def test_verify_notification_channel_from_dict(): test_verify_notification_channel(request_type=dict) +def test_verify_notification_channel_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 = NotificationChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.verify_notification_channel), "__call__" + ) as call: + client.verify_notification_channel() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == notification_service.VerifyNotificationChannelRequest() + + @pytest.mark.asyncio async def test_verify_notification_channel_async( transport: str = "grpc_asyncio", @@ -3460,6 +3659,57 @@ def test_notification_channel_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.NotificationChannelServiceGrpcTransport, + transports.NotificationChannelServiceGrpcAsyncIOTransport, + ], +) +def test_notification_channel_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/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + 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_notification_channel_service_host_no_port(): client = NotificationChannelServiceClient( credentials=credentials.AnonymousCredentials(), @@ -3481,7 +3731,7 @@ def test_notification_channel_service_host_with_port(): def test_notification_channel_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.NotificationChannelServiceGrpcTransport( @@ -3493,7 +3743,7 @@ def test_notification_channel_service_grpc_transport_channel(): def test_notification_channel_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.NotificationChannelServiceGrpcAsyncIOTransport( @@ -3504,6 +3754,8 @@ def test_notification_channel_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", [ @@ -3518,7 +3770,7 @@ def test_notification_channel_service_transport_channel_mtls_with_client_cert_so "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 @@ -3560,6 +3812,8 @@ def test_notification_channel_service_transport_channel_mtls_with_client_cert_so 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", [ @@ -3575,7 +3829,7 @@ def test_notification_channel_service_transport_channel_mtls_with_adc(transport_ 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 diff --git a/tests/unit/gapic/monitoring_v3/test_query_service.py b/tests/unit/gapic/monitoring_v3/test_query_service.py new file mode 100644 index 00000000..a7b86044 --- /dev/null +++ b/tests/unit/gapic/monitoring_v3/test_query_service.py @@ -0,0 +1,1219 @@ +# -*- 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. +# + +import os +import mock + +import grpc +from grpc.experimental import aio +import math +import pytest +from proto.marshal.rules.dates import DurationRule, TimestampRule + +from google import auth +from google.api_core import client_options +from google.api_core import exceptions +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers +from google.api_core import grpc_helpers_async +from google.auth import credentials +from google.auth.exceptions import MutualTLSChannelError +from google.cloud.monitoring_v3.services.query_service import QueryServiceAsyncClient +from google.cloud.monitoring_v3.services.query_service import QueryServiceClient +from google.cloud.monitoring_v3.services.query_service import pagers +from google.cloud.monitoring_v3.services.query_service import transports +from google.cloud.monitoring_v3.types import metric +from google.cloud.monitoring_v3.types import metric_service +from google.oauth2 import service_account + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +# If default endpoint is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint(client): + return ( + "foo.googleapis.com" + if ("localhost" in client.DEFAULT_ENDPOINT) + else client.DEFAULT_ENDPOINT + ) + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert QueryServiceClient._get_default_mtls_endpoint(None) is None + assert ( + QueryServiceClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint + ) + assert ( + QueryServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + QueryServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + QueryServiceClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert QueryServiceClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi + + +@pytest.mark.parametrize("client_class", [QueryServiceClient, QueryServiceAsyncClient,]) +def test_query_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 == "monitoring.googleapis.com:443" + + +@pytest.mark.parametrize("client_class", [QueryServiceClient, QueryServiceAsyncClient,]) +def test_query_service_client_from_service_account_file(client_class): + creds = credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + 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 == "monitoring.googleapis.com:443" + + +def test_query_service_client_get_transport_class(): + transport = QueryServiceClient.get_transport_class() + available_transports = [ + transports.QueryServiceGrpcTransport, + ] + assert transport in available_transports + + transport = QueryServiceClient.get_transport_class("grpc") + assert transport == transports.QueryServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (QueryServiceClient, transports.QueryServiceGrpcTransport, "grpc"), + ( + QueryServiceAsyncClient, + transports.QueryServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ], +) +@mock.patch.object( + QueryServiceClient, "DEFAULT_ENDPOINT", modify_default_endpoint(QueryServiceClient) +) +@mock.patch.object( + QueryServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(QueryServiceAsyncClient), +) +def test_query_service_client_client_options( + client_class, transport_class, transport_name +): + # Check that if channel is provided we won't create a new one. + with mock.patch.object(QueryServiceClient, "get_transport_class") as gtc: + transport = transport_class(credentials=credentials.AnonymousCredentials()) + client = client_class(transport=transport) + gtc.assert_not_called() + + # Check that if channel is provided via str we will create a new one. + with mock.patch.object(QueryServiceClient, "get_transport_class") as gtc: + client = client_class(transport=transport_name) + gtc.assert_called() + + # Check the case api_endpoint is provided. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + with mock.patch.object(transport_class, "__init__") as patched: + 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, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError): + client = client_class() + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError): + client = client_class() + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + 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="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + (QueryServiceClient, transports.QueryServiceGrpcTransport, "grpc", "true"), + ( + QueryServiceAsyncClient, + transports.QueryServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + (QueryServiceClient, transports.QueryServiceGrpcTransport, "grpc", "false"), + ( + QueryServiceAsyncClient, + transports.QueryServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + QueryServiceClient, "DEFAULT_ENDPOINT", modify_default_endpoint(QueryServiceClient) +) +@mock.patch.object( + QueryServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(QueryServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_query_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + + 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, + 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. + 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=True, + ): + with mock.patch( + "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 + + patched.return_value = None + client = client_class() + 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 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", + [ + (QueryServiceClient, transports.QueryServiceGrpcTransport, "grpc"), + ( + QueryServiceAsyncClient, + transports.QueryServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ], +) +def test_query_service_client_client_options_scopes( + client_class, transport_class, transport_name +): + # Check the case scopes are provided. + options = client_options.ClientOptions(scopes=["1", "2"],) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=["1", "2"], + 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", + [ + (QueryServiceClient, transports.QueryServiceGrpcTransport, "grpc"), + ( + QueryServiceAsyncClient, + transports.QueryServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ], +) +def test_query_service_client_client_options_credentials_file( + client_class, transport_class, transport_name +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +def test_query_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.monitoring_v3.services.query_service.transports.QueryServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = QueryServiceClient(client_options={"api_endpoint": "squid.clam.whelk"}) + grpc_transport.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +def test_query_time_series( + transport: str = "grpc", request_type=metric_service.QueryTimeSeriesRequest +): + client = QueryServiceClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.query_time_series), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = metric_service.QueryTimeSeriesResponse( + next_page_token="next_page_token_value", + ) + + response = client.query_time_series(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.QueryTimeSeriesRequest() + + # Establish that the response is the type that we expect. + + assert isinstance(response, pagers.QueryTimeSeriesPager) + + assert response.next_page_token == "next_page_token_value" + + +def test_query_time_series_from_dict(): + test_query_time_series(request_type=dict) + + +def test_query_time_series_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 = QueryServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.query_time_series), "__call__" + ) as call: + client.query_time_series() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.QueryTimeSeriesRequest() + + +@pytest.mark.asyncio +async def test_query_time_series_async( + transport: str = "grpc_asyncio", request_type=metric_service.QueryTimeSeriesRequest +): + client = QueryServiceAsyncClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.query_time_series), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + metric_service.QueryTimeSeriesResponse( + next_page_token="next_page_token_value", + ) + ) + + response = await client.query_time_series(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + + assert args[0] == metric_service.QueryTimeSeriesRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.QueryTimeSeriesAsyncPager) + + assert response.next_page_token == "next_page_token_value" + + +@pytest.mark.asyncio +async def test_query_time_series_async_from_dict(): + await test_query_time_series_async(request_type=dict) + + +def test_query_time_series_field_headers(): + client = QueryServiceClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = metric_service.QueryTimeSeriesRequest() + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.query_time_series), "__call__" + ) as call: + call.return_value = metric_service.QueryTimeSeriesResponse() + + client.query_time_series(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_query_time_series_field_headers_async(): + client = QueryServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = metric_service.QueryTimeSeriesRequest() + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.query_time_series), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + metric_service.QueryTimeSeriesResponse() + ) + + await client.query_time_series(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_query_time_series_pager(): + client = QueryServiceClient(credentials=credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.query_time_series), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + metric_service.QueryTimeSeriesResponse( + time_series_data=[ + metric.TimeSeriesData(), + metric.TimeSeriesData(), + metric.TimeSeriesData(), + ], + next_page_token="abc", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[], next_page_token="def", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[metric.TimeSeriesData(),], next_page_token="ghi", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[metric.TimeSeriesData(), metric.TimeSeriesData(),], + ), + RuntimeError, + ) + + metadata = () + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", ""),)), + ) + pager = client.query_time_series(request={}) + + assert pager._metadata == metadata + + results = [i for i in pager] + assert len(results) == 6 + assert all(isinstance(i, metric.TimeSeriesData) for i in results) + + +def test_query_time_series_pages(): + client = QueryServiceClient(credentials=credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.query_time_series), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + metric_service.QueryTimeSeriesResponse( + time_series_data=[ + metric.TimeSeriesData(), + metric.TimeSeriesData(), + metric.TimeSeriesData(), + ], + next_page_token="abc", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[], next_page_token="def", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[metric.TimeSeriesData(),], next_page_token="ghi", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[metric.TimeSeriesData(), metric.TimeSeriesData(),], + ), + RuntimeError, + ) + pages = list(client.query_time_series(request={}).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.asyncio +async def test_query_time_series_async_pager(): + client = QueryServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.query_time_series), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + metric_service.QueryTimeSeriesResponse( + time_series_data=[ + metric.TimeSeriesData(), + metric.TimeSeriesData(), + metric.TimeSeriesData(), + ], + next_page_token="abc", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[], next_page_token="def", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[metric.TimeSeriesData(),], next_page_token="ghi", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[metric.TimeSeriesData(), metric.TimeSeriesData(),], + ), + RuntimeError, + ) + async_pager = await client.query_time_series(request={},) + assert async_pager.next_page_token == "abc" + responses = [] + async for response in async_pager: + responses.append(response) + + assert len(responses) == 6 + assert all(isinstance(i, metric.TimeSeriesData) for i in responses) + + +@pytest.mark.asyncio +async def test_query_time_series_async_pages(): + client = QueryServiceAsyncClient(credentials=credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.query_time_series), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + metric_service.QueryTimeSeriesResponse( + time_series_data=[ + metric.TimeSeriesData(), + metric.TimeSeriesData(), + metric.TimeSeriesData(), + ], + next_page_token="abc", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[], next_page_token="def", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[metric.TimeSeriesData(),], next_page_token="ghi", + ), + metric_service.QueryTimeSeriesResponse( + time_series_data=[metric.TimeSeriesData(), metric.TimeSeriesData(),], + ), + RuntimeError, + ) + pages = [] + async for page_ in (await client.query_time_series(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.QueryServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = QueryServiceClient( + credentials=credentials.AnonymousCredentials(), transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.QueryServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = QueryServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.QueryServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = QueryServiceClient( + client_options={"scopes": ["1", "2"]}, transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.QueryServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + client = QueryServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.QueryServiceGrpcTransport( + credentials=credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.QueryServiceGrpcAsyncIOTransport( + credentials=credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.QueryServiceGrpcTransport, + transports.QueryServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = QueryServiceClient(credentials=credentials.AnonymousCredentials(),) + assert isinstance(client.transport, transports.QueryServiceGrpcTransport,) + + +def test_query_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(exceptions.DuplicateCredentialArgs): + transport = transports.QueryServiceTransport( + credentials=credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_query_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.monitoring_v3.services.query_service.transports.QueryServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.QueryServiceTransport( + credentials=credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ("query_time_series",) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + +def test_query_service_base_transport_with_credentials_file(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + auth, "load_credentials_from_file" + ) as load_creds, mock.patch( + "google.cloud.monitoring_v3.services.query_service.transports.QueryServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.QueryServiceTransport( + credentials_file="credentials.json", quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + quota_project_id="octopus", + ) + + +def test_query_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(auth, "default") as adc, mock.patch( + "google.cloud.monitoring_v3.services.query_service.transports.QueryServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.QueryServiceTransport() + adc.assert_called_once() + + +def test_query_service_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + QueryServiceClient() + adc.assert_called_once_with( + scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + quota_project_id=None, + ) + + +def test_query_service_transport_auth_adc(): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transports.QueryServiceGrpcTransport( + host="squid.clam.whelk", quota_project_id="octopus" + ) + adc.assert_called_once_with( + scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + quota_project_id="octopus", + ) + + +@pytest.mark.parametrize( + "transport_class", + [transports.QueryServiceGrpcTransport, transports.QueryServiceGrpcAsyncIOTransport], +) +def test_query_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/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + 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_query_service_host_no_port(): + client = QueryServiceClient( + credentials=credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="monitoring.googleapis.com" + ), + ) + assert client.transport._host == "monitoring.googleapis.com:443" + + +def test_query_service_host_with_port(): + client = QueryServiceClient( + credentials=credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="monitoring.googleapis.com:8000" + ), + ) + assert client.transport._host == "monitoring.googleapis.com:8000" + + +def test_query_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.QueryServiceGrpcTransport( + host="squid.clam.whelk", channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +def test_query_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.QueryServiceGrpcAsyncIOTransport( + host="squid.clam.whelk", channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + 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", + [transports.QueryServiceGrpcTransport, transports.QueryServiceGrpcAsyncIOTransport], +) +def test_query_service_transport_channel_mtls_with_client_cert_source(transport_class): + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + 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", + [transports.QueryServiceGrpcTransport, transports.QueryServiceGrpcAsyncIOTransport], +) +def test_query_service_transport_channel_mtls_with_adc(transport_class): + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + + +def test_common_billing_account_path(): + billing_account = "squid" + + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = QueryServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "clam", + } + path = QueryServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = QueryServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "whelk" + + expected = "folders/{folder}".format(folder=folder,) + actual = QueryServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "octopus", + } + path = QueryServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = QueryServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "oyster" + + expected = "organizations/{organization}".format(organization=organization,) + actual = QueryServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "nudibranch", + } + path = QueryServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = QueryServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "cuttlefish" + + expected = "projects/{project}".format(project=project,) + actual = QueryServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "mussel", + } + path = QueryServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = QueryServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "winkle" + location = "nautilus" + + expected = "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + actual = QueryServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "scallop", + "location": "abalone", + } + path = QueryServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = QueryServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.QueryServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = QueryServiceClient( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.QueryServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = QueryServiceClient.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/monitoring_v3/test_service_monitoring_service.py b/tests/unit/gapic/monitoring_v3/test_service_monitoring_service.py index 7ced9a3b..74bd82dc 100644 --- a/tests/unit/gapic/monitoring_v3/test_service_monitoring_service.py +++ b/tests/unit/gapic/monitoring_v3/test_service_monitoring_service.py @@ -96,7 +96,25 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( "client_class", - [ServiceMonitoringServiceClient, ServiceMonitoringServiceAsyncClient], + [ServiceMonitoringServiceClient, ServiceMonitoringServiceAsyncClient,], +) +def test_service_monitoring_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 == "monitoring.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", + [ServiceMonitoringServiceClient, ServiceMonitoringServiceAsyncClient,], ) def test_service_monitoring_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -106,16 +124,21 @@ def test_service_monitoring_service_client_from_service_account_file(client_clas 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 == "monitoring.googleapis.com:443" def test_service_monitoring_service_client_get_transport_class(): transport = ServiceMonitoringServiceClient.get_transport_class() - assert transport == transports.ServiceMonitoringServiceGrpcTransport + available_transports = [ + transports.ServiceMonitoringServiceGrpcTransport, + ] + assert transport in available_transports transport = ServiceMonitoringServiceClient.get_transport_class("grpc") assert transport == transports.ServiceMonitoringServiceGrpcTransport @@ -174,7 +197,7 @@ def test_service_monitoring_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, ) @@ -190,7 +213,7 @@ def test_service_monitoring_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, ) @@ -206,7 +229,7 @@ def test_service_monitoring_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, ) @@ -234,7 +257,7 @@ def test_service_monitoring_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, ) @@ -295,29 +318,25 @@ def test_service_monitoring_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. @@ -326,66 +345,53 @@ def test_service_monitoring_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", @@ -415,7 +421,7 @@ def test_service_monitoring_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, ) @@ -449,7 +455,7 @@ def test_service_monitoring_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, ) @@ -468,7 +474,7 @@ def test_service_monitoring_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, ) @@ -513,6 +519,22 @@ def test_create_service_from_dict(): test_create_service(request_type=dict) +def test_create_service_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 = ServiceMonitoringServiceClient( + 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_service), "__call__") as call: + client.create_service() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.CreateServiceRequest() + + @pytest.mark.asyncio async def test_create_service_async( transport: str = "grpc_asyncio", request_type=service_service.CreateServiceRequest @@ -730,6 +752,22 @@ def test_get_service_from_dict(): test_get_service(request_type=dict) +def test_get_service_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 = ServiceMonitoringServiceClient( + 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_service), "__call__") as call: + client.get_service() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.GetServiceRequest() + + @pytest.mark.asyncio async def test_get_service_async( transport: str = "grpc_asyncio", request_type=service_service.GetServiceRequest @@ -933,6 +971,22 @@ def test_list_services_from_dict(): test_list_services(request_type=dict) +def test_list_services_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 = ServiceMonitoringServiceClient( + 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_services), "__call__") as call: + client.list_services() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.ListServicesRequest() + + @pytest.mark.asyncio async def test_list_services_async( transport: str = "grpc_asyncio", request_type=service_service.ListServicesRequest @@ -1272,6 +1326,22 @@ def test_update_service_from_dict(): test_update_service(request_type=dict) +def test_update_service_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 = ServiceMonitoringServiceClient( + 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_service), "__call__") as call: + client.update_service() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.UpdateServiceRequest() + + @pytest.mark.asyncio async def test_update_service_async( transport: str = "grpc_asyncio", request_type=service_service.UpdateServiceRequest @@ -1478,6 +1548,22 @@ def test_delete_service_from_dict(): test_delete_service(request_type=dict) +def test_delete_service_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 = ServiceMonitoringServiceClient( + 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_service), "__call__") as call: + client.delete_service() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.DeleteServiceRequest() + + @pytest.mark.asyncio async def test_delete_service_async( transport: str = "grpc_asyncio", request_type=service_service.DeleteServiceRequest @@ -1685,6 +1771,24 @@ def test_create_service_level_objective_from_dict(): test_create_service_level_objective(request_type=dict) +def test_create_service_level_objective_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 = ServiceMonitoringServiceClient( + 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_service_level_objective), "__call__" + ) as call: + client.create_service_level_objective() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.CreateServiceLevelObjectiveRequest() + + @pytest.mark.asyncio async def test_create_service_level_objective_async( transport: str = "grpc_asyncio", @@ -1935,6 +2039,24 @@ def test_get_service_level_objective_from_dict(): test_get_service_level_objective(request_type=dict) +def test_get_service_level_objective_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 = ServiceMonitoringServiceClient( + 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_service_level_objective), "__call__" + ) as call: + client.get_service_level_objective() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.GetServiceLevelObjectiveRequest() + + @pytest.mark.asyncio async def test_get_service_level_objective_async( transport: str = "grpc_asyncio", @@ -2160,6 +2282,24 @@ def test_list_service_level_objectives_from_dict(): test_list_service_level_objectives(request_type=dict) +def test_list_service_level_objectives_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 = ServiceMonitoringServiceClient( + 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_service_level_objectives), "__call__" + ) as call: + client.list_service_level_objectives() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.ListServiceLevelObjectivesRequest() + + @pytest.mark.asyncio async def test_list_service_level_objectives_async( transport: str = "grpc_asyncio", @@ -2568,6 +2708,24 @@ def test_update_service_level_objective_from_dict(): test_update_service_level_objective(request_type=dict) +def test_update_service_level_objective_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 = ServiceMonitoringServiceClient( + 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_service_level_objective), "__call__" + ) as call: + client.update_service_level_objective() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.UpdateServiceLevelObjectiveRequest() + + @pytest.mark.asyncio async def test_update_service_level_objective_async( transport: str = "grpc_asyncio", @@ -2804,6 +2962,24 @@ def test_delete_service_level_objective_from_dict(): test_delete_service_level_objective(request_type=dict) +def test_delete_service_level_objective_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 = ServiceMonitoringServiceClient( + 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_service_level_objective), "__call__" + ) as call: + client.delete_service_level_objective() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service_service.DeleteServiceLevelObjectiveRequest() + + @pytest.mark.asyncio async def test_delete_service_level_objective_async( transport: str = "grpc_asyncio", @@ -3159,6 +3335,57 @@ def test_service_monitoring_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.ServiceMonitoringServiceGrpcTransport, + transports.ServiceMonitoringServiceGrpcAsyncIOTransport, + ], +) +def test_service_monitoring_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/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + 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_service_monitoring_service_host_no_port(): client = ServiceMonitoringServiceClient( credentials=credentials.AnonymousCredentials(), @@ -3180,7 +3407,7 @@ def test_service_monitoring_service_host_with_port(): def test_service_monitoring_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.ServiceMonitoringServiceGrpcTransport( @@ -3192,7 +3419,7 @@ def test_service_monitoring_service_grpc_transport_channel(): def test_service_monitoring_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.ServiceMonitoringServiceGrpcAsyncIOTransport( @@ -3203,6 +3430,8 @@ def test_service_monitoring_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", [ @@ -3217,7 +3446,7 @@ def test_service_monitoring_service_transport_channel_mtls_with_client_cert_sour "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 @@ -3259,6 +3488,8 @@ def test_service_monitoring_service_transport_channel_mtls_with_client_cert_sour 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", [ @@ -3274,7 +3505,7 @@ def test_service_monitoring_service_transport_channel_mtls_with_adc(transport_cl 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 diff --git a/tests/unit/gapic/monitoring_v3/test_uptime_check_service.py b/tests/unit/gapic/monitoring_v3/test_uptime_check_service.py index c6274dfb..2d757678 100644 --- a/tests/unit/gapic/monitoring_v3/test_uptime_check_service.py +++ b/tests/unit/gapic/monitoring_v3/test_uptime_check_service.py @@ -94,7 +94,24 @@ def test__get_default_mtls_endpoint(): @pytest.mark.parametrize( - "client_class", [UptimeCheckServiceClient, UptimeCheckServiceAsyncClient] + "client_class", [UptimeCheckServiceClient, UptimeCheckServiceAsyncClient,] +) +def test_uptime_check_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 == "monitoring.googleapis.com:443" + + +@pytest.mark.parametrize( + "client_class", [UptimeCheckServiceClient, UptimeCheckServiceAsyncClient,] ) def test_uptime_check_service_client_from_service_account_file(client_class): creds = credentials.AnonymousCredentials() @@ -104,16 +121,21 @@ def test_uptime_check_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 == "monitoring.googleapis.com:443" def test_uptime_check_service_client_get_transport_class(): transport = UptimeCheckServiceClient.get_transport_class() - assert transport == transports.UptimeCheckServiceGrpcTransport + available_transports = [ + transports.UptimeCheckServiceGrpcTransport, + ] + assert transport in available_transports transport = UptimeCheckServiceClient.get_transport_class("grpc") assert transport == transports.UptimeCheckServiceGrpcTransport @@ -164,7 +186,7 @@ def test_uptime_check_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, ) @@ -180,7 +202,7 @@ def test_uptime_check_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, ) @@ -196,7 +218,7 @@ def test_uptime_check_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, ) @@ -224,7 +246,7 @@ def test_uptime_check_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, ) @@ -285,29 +307,25 @@ def test_uptime_check_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. @@ -316,66 +334,53 @@ def test_uptime_check_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", @@ -401,7 +406,7 @@ def test_uptime_check_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, ) @@ -431,7 +436,7 @@ def test_uptime_check_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, ) @@ -450,7 +455,7 @@ def test_uptime_check_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, ) @@ -497,6 +502,24 @@ def test_list_uptime_check_configs_from_dict(): test_list_uptime_check_configs(request_type=dict) +def test_list_uptime_check_configs_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 = UptimeCheckServiceClient( + 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_uptime_check_configs), "__call__" + ) as call: + client.list_uptime_check_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == uptime_service.ListUptimeCheckConfigsRequest() + + @pytest.mark.asyncio async def test_list_uptime_check_configs_async( transport: str = "grpc_asyncio", @@ -900,6 +923,24 @@ def test_get_uptime_check_config_from_dict(): test_get_uptime_check_config(request_type=dict) +def test_get_uptime_check_config_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 = UptimeCheckServiceClient( + 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_uptime_check_config), "__call__" + ) as call: + client.get_uptime_check_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == uptime_service.GetUptimeCheckConfigRequest() + + @pytest.mark.asyncio async def test_get_uptime_check_config_async( transport: str = "grpc_asyncio", @@ -1136,6 +1177,24 @@ def test_create_uptime_check_config_from_dict(): test_create_uptime_check_config(request_type=dict) +def test_create_uptime_check_config_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 = UptimeCheckServiceClient( + 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_uptime_check_config), "__call__" + ) as call: + client.create_uptime_check_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == uptime_service.CreateUptimeCheckConfigRequest() + + @pytest.mark.asyncio async def test_create_uptime_check_config_async( transport: str = "grpc_asyncio", @@ -1390,6 +1449,24 @@ def test_update_uptime_check_config_from_dict(): test_update_uptime_check_config(request_type=dict) +def test_update_uptime_check_config_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 = UptimeCheckServiceClient( + 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_uptime_check_config), "__call__" + ) as call: + client.update_uptime_check_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == uptime_service.UpdateUptimeCheckConfigRequest() + + @pytest.mark.asyncio async def test_update_uptime_check_config_async( transport: str = "grpc_asyncio", @@ -1624,6 +1701,24 @@ def test_delete_uptime_check_config_from_dict(): test_delete_uptime_check_config(request_type=dict) +def test_delete_uptime_check_config_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 = UptimeCheckServiceClient( + 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_uptime_check_config), "__call__" + ) as call: + client.delete_uptime_check_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == uptime_service.DeleteUptimeCheckConfigRequest() + + @pytest.mark.asyncio async def test_delete_uptime_check_config_async( transport: str = "grpc_asyncio", @@ -1828,6 +1923,24 @@ def test_list_uptime_check_ips_from_dict(): test_list_uptime_check_ips(request_type=dict) +def test_list_uptime_check_ips_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 = UptimeCheckServiceClient( + 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_uptime_check_ips), "__call__" + ) as call: + client.list_uptime_check_ips() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == uptime_service.ListUptimeCheckIpsRequest() + + @pytest.mark.asyncio async def test_list_uptime_check_ips_async( transport: str = "grpc_asyncio", @@ -2202,6 +2315,57 @@ def test_uptime_check_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.UptimeCheckServiceGrpcTransport, + transports.UptimeCheckServiceGrpcAsyncIOTransport, + ], +) +def test_uptime_check_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/cloud-platform", + "https://www.googleapis.com/auth/monitoring", + "https://www.googleapis.com/auth/monitoring.read", + ), + 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_uptime_check_service_host_no_port(): client = UptimeCheckServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2223,7 +2387,7 @@ def test_uptime_check_service_host_with_port(): def test_uptime_check_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.UptimeCheckServiceGrpcTransport( @@ -2235,7 +2399,7 @@ def test_uptime_check_service_grpc_transport_channel(): def test_uptime_check_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.UptimeCheckServiceGrpcAsyncIOTransport( @@ -2246,6 +2410,8 @@ def test_uptime_check_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", [ @@ -2260,7 +2426,7 @@ def test_uptime_check_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 @@ -2302,6 +2468,8 @@ def test_uptime_check_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", [ @@ -2317,7 +2485,7 @@ def test_uptime_check_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