From 27dfdcab82c091d77f40542e6393a0a3f466bcb0 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 9 Nov 2021 11:16:15 +0000 Subject: [PATCH] feat(v1): Support Multiple Read Replicas when creating Instance (#135) - [ ] Regenerate this pull request now. PiperOrigin-RevId: 408360267 Source-Link: https://github.com/googleapis/googleapis/commit/8625cf0cf87fa4778a6ad48256d1fa98b45c0ca9 Source-Link: https://github.com/googleapis/googleapis-gen/commit/d84247808680a19dec0d3f3b52a28e2d3050beaf Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiZDg0MjQ3ODA4NjgwYTE5ZGVjMGQzZjNiNTJhMjhlMmQzMDUwYmVhZiJ9 --- google/cloud/redis/__init__.py | 2 + google/cloud/redis_v1/__init__.py | 2 + .../services/cloud_redis/async_client.py | 3 +- .../redis_v1/services/cloud_redis/client.py | 3 +- .../services/cloud_redis/transports/grpc.py | 2 +- .../cloud_redis/transports/grpc_asyncio.py | 2 +- google/cloud/redis_v1/types/__init__.py | 2 + google/cloud/redis_v1/types/cloud_redis.py | 109 +++++++++++++----- tests/unit/gapic/redis_v1/test_cloud_redis.py | 22 ++++ 9 files changed, 112 insertions(+), 35 deletions(-) diff --git a/google/cloud/redis/__init__.py b/google/cloud/redis/__init__.py index 08024c0..505605d 100644 --- a/google/cloud/redis/__init__.py +++ b/google/cloud/redis/__init__.py @@ -32,6 +32,7 @@ from google.cloud.redis_v1.types.cloud_redis import ListInstancesRequest from google.cloud.redis_v1.types.cloud_redis import ListInstancesResponse from google.cloud.redis_v1.types.cloud_redis import LocationMetadata +from google.cloud.redis_v1.types.cloud_redis import NodeInfo from google.cloud.redis_v1.types.cloud_redis import OperationMetadata from google.cloud.redis_v1.types.cloud_redis import OutputConfig from google.cloud.redis_v1.types.cloud_redis import UpdateInstanceRequest @@ -54,6 +55,7 @@ "ListInstancesRequest", "ListInstancesResponse", "LocationMetadata", + "NodeInfo", "OperationMetadata", "OutputConfig", "UpdateInstanceRequest", diff --git a/google/cloud/redis_v1/__init__.py b/google/cloud/redis_v1/__init__.py index ce7087f..5dbea84 100644 --- a/google/cloud/redis_v1/__init__.py +++ b/google/cloud/redis_v1/__init__.py @@ -30,6 +30,7 @@ from .types.cloud_redis import ListInstancesRequest from .types.cloud_redis import ListInstancesResponse from .types.cloud_redis import LocationMetadata +from .types.cloud_redis import NodeInfo from .types.cloud_redis import OperationMetadata from .types.cloud_redis import OutputConfig from .types.cloud_redis import UpdateInstanceRequest @@ -52,6 +53,7 @@ "ListInstancesRequest", "ListInstancesResponse", "LocationMetadata", + "NodeInfo", "OperationMetadata", "OutputConfig", "UpdateInstanceRequest", diff --git a/google/cloud/redis_v1/services/cloud_redis/async_client.py b/google/cloud/redis_v1/services/cloud_redis/async_client.py index 51808bd..b6d31c7 100644 --- a/google/cloud/redis_v1/services/cloud_redis/async_client.py +++ b/google/cloud/redis_v1/services/cloud_redis/async_client.py @@ -497,6 +497,7 @@ async def update_instance( - ``labels`` - ``memorySizeGb`` - ``redisConfig`` + - ``replica_count`` This corresponds to the ``update_mask`` field on the ``request`` instance; if ``request`` is provided, this @@ -874,7 +875,7 @@ async def failover_instance( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation_async.AsyncOperation: - r"""Initiates a failover of the master node to current + r"""Initiates a failover of the primary node to current replica node for a specific STANDARD tier Cloud Memorystore for Redis instance. diff --git a/google/cloud/redis_v1/services/cloud_redis/client.py b/google/cloud/redis_v1/services/cloud_redis/client.py index 1d9e188..a69af50 100644 --- a/google/cloud/redis_v1/services/cloud_redis/client.py +++ b/google/cloud/redis_v1/services/cloud_redis/client.py @@ -687,6 +687,7 @@ def update_instance( - ``labels`` - ``memorySizeGb`` - ``redisConfig`` + - ``replica_count`` This corresponds to the ``update_mask`` field on the ``request`` instance; if ``request`` is provided, this @@ -1064,7 +1065,7 @@ def failover_instance( timeout: float = None, metadata: Sequence[Tuple[str, str]] = (), ) -> operation.Operation: - r"""Initiates a failover of the master node to current + r"""Initiates a failover of the primary node to current replica node for a specific STANDARD tier Cloud Memorystore for Redis instance. diff --git a/google/cloud/redis_v1/services/cloud_redis/transports/grpc.py b/google/cloud/redis_v1/services/cloud_redis/transports/grpc.py index 0ed3e50..3c69418 100644 --- a/google/cloud/redis_v1/services/cloud_redis/transports/grpc.py +++ b/google/cloud/redis_v1/services/cloud_redis/transports/grpc.py @@ -492,7 +492,7 @@ def failover_instance( ) -> Callable[[cloud_redis.FailoverInstanceRequest], operations_pb2.Operation]: r"""Return a callable for the failover instance method over gRPC. - Initiates a failover of the master node to current + Initiates a failover of the primary node to current replica node for a specific STANDARD tier Cloud Memorystore for Redis instance. diff --git a/google/cloud/redis_v1/services/cloud_redis/transports/grpc_asyncio.py b/google/cloud/redis_v1/services/cloud_redis/transports/grpc_asyncio.py index 4e5aad3..daac696 100644 --- a/google/cloud/redis_v1/services/cloud_redis/transports/grpc_asyncio.py +++ b/google/cloud/redis_v1/services/cloud_redis/transports/grpc_asyncio.py @@ -508,7 +508,7 @@ def failover_instance( ]: r"""Return a callable for the failover instance method over gRPC. - Initiates a failover of the master node to current + Initiates a failover of the primary node to current replica node for a specific STANDARD tier Cloud Memorystore for Redis instance. diff --git a/google/cloud/redis_v1/types/__init__.py b/google/cloud/redis_v1/types/__init__.py index 909344d..68fdb3d 100644 --- a/google/cloud/redis_v1/types/__init__.py +++ b/google/cloud/redis_v1/types/__init__.py @@ -27,6 +27,7 @@ ListInstancesRequest, ListInstancesResponse, LocationMetadata, + NodeInfo, OperationMetadata, OutputConfig, UpdateInstanceRequest, @@ -48,6 +49,7 @@ "ListInstancesRequest", "ListInstancesResponse", "LocationMetadata", + "NodeInfo", "OperationMetadata", "OutputConfig", "UpdateInstanceRequest", diff --git a/google/cloud/redis_v1/types/cloud_redis.py b/google/cloud/redis_v1/types/cloud_redis.py index 8c865f0..cd3325c 100644 --- a/google/cloud/redis_v1/types/cloud_redis.py +++ b/google/cloud/redis_v1/types/cloud_redis.py @@ -22,6 +22,7 @@ __protobuf__ = proto.module( package="google.cloud.redis.v1", manifest={ + "NodeInfo", "Instance", "ListInstancesRequest", "ListInstancesResponse", @@ -44,6 +45,21 @@ ) +class NodeInfo(proto.Message): + r"""Node specific properties. + + Attributes: + id (str): + Output only. Node identifying string. e.g. + 'node-0', 'node-1' + zone (str): + Output only. Location of the node. + """ + + id = proto.Field(proto.STRING, number=1,) + zone = proto.Field(proto.STRING, number=2,) + + class Instance(proto.Message): r"""A Google Cloud Redis instance. @@ -69,19 +85,21 @@ class Instance(proto.Message): Resource labels to represent user provided metadata location_id (str): - Optional. The zone where the instance will be provisioned. - If not provided, the service will choose a zone for the - instance. For STANDARD_HA tier, instances will be created - across two zones for protection against zonal failures. If - [alternative_location_id][google.cloud.redis.v1.Instance.alternative_location_id] - is also provided, it must be different from - [location_id][google.cloud.redis.v1.Instance.location_id]. + Optional. The zone where the instance will be + provisioned. If not provided, the service will + choose a zone from the specified region for the + instance. For standard tier, additional nodes + will be added across multiple zones for + protection against zonal failures. If specified, + at least one node will be provisioned in this + zone. alternative_location_id (str): - Optional. Only applicable to STANDARD_HA tier which protects - the instance against zonal failures by provisioning it - across two zones. If provided, it must be a different zone - from the one provided in - [location_id][google.cloud.redis.v1.Instance.location_id]. + Optional. If specified, at least one node will be + provisioned in this zone in addition to the zone specified + in location_id. Only applicable to standard tier. If + provided, it must be a different zone from the one provided + in [location_id]. Additional nodes beyond the first 2 will + be placed in zones selected by the service. redis_version (str): Optional. The version of Redis software. If not provided, latest supported version will be used. Currently, the @@ -90,14 +108,17 @@ class Instance(proto.Message): - ``REDIS_3_2`` for Redis 3.2 compatibility - ``REDIS_4_0`` for Redis 4.0 compatibility (default) - ``REDIS_5_0`` for Redis 5.0 compatibility + - ``REDIS_6_X`` for Redis 6.x compatibility reserved_ip_range (str): - Optional. The CIDR range of internal - addresses that are reserved for this instance. - If not provided, the service will choose an - unused /29 block, for example, 10.0.0.0/29 or - 192.168.0.0/29. Ranges must be unique and non- - overlapping with existing subnets in an - authorized network. + Optional. For DIRECT_PEERING mode, the CIDR range of + internal addresses that are reserved for this instance. + Range must be unique and non-overlapping with existing + subnets in an authorized network. For PRIVATE_SERVICE_ACCESS + mode, the name of one allocated IP address ranges associated + with this private service access connection. If not + provided, the service will choose an unused /29 block, for + example, 10.0.0.0/29 or 192.168.0.0/29. For + READ_REPLICAS_ENABLED the default block size is /28. host (str): Output only. Hostname or IP address of the exposed Redis endpoint used by clients to @@ -106,15 +127,10 @@ class Instance(proto.Message): Output only. The port number of the exposed Redis endpoint. current_location_id (str): - Output only. The current zone where the Redis endpoint is - placed. For Basic Tier instances, this will always be the - same as the - [location_id][google.cloud.redis.v1.Instance.location_id] - provided by the user at creation time. For Standard Tier - instances, this can be either - [location_id][google.cloud.redis.v1.Instance.location_id] or - [alternative_location_id][google.cloud.redis.v1.Instance.alternative_location_id] - and can change after a failover event. + Output only. The current zone where the Redis primary node + is located. In basic tier, this will always be the same as + [location_id]. In standard tier, this can be the zone of any + node in the instance. create_time (google.protobuf.timestamp_pb2.Timestamp): Output only. The time the instance was created. @@ -163,6 +179,25 @@ class Instance(proto.Message): connect_mode (google.cloud.redis_v1.types.Instance.ConnectMode): Optional. The network connect mode of the Redis instance. If not provided, the connect mode defaults to DIRECT_PEERING. + replica_count (int): + Optional. The number of replica nodes. Valid range for + standard tier is [1-5] and defaults to 1. Valid value for + basic tier is 0 and defaults to 0. + nodes (Sequence[google.cloud.redis_v1.types.NodeInfo]): + Output only. Info per node. + read_endpoint (str): + Output only. Hostname or IP address of the + exposed readonly Redis endpoint. Standard tier + only. Targets all healthy replica nodes in + instance. Replication is asynchronous and + replica nodes will exhibit some lag behind the + primary. Write requests must target 'host'. + read_endpoint_port (int): + Output only. The port number of the exposed + readonly redis endpoint. Standard tier only. + Write requests should target 'port'. + read_replicas_mode (google.cloud.redis_v1.types.Instance.ReadReplicasMode): + Optional. Read replica mode. """ class State(proto.Enum): @@ -189,6 +224,12 @@ class ConnectMode(proto.Enum): DIRECT_PEERING = 1 PRIVATE_SERVICE_ACCESS = 2 + class ReadReplicasMode(proto.Enum): + r"""Read replicas mode.""" + READ_REPLICAS_MODE_UNSPECIFIED = 0 + READ_REPLICAS_DISABLED = 1 + READ_REPLICAS_ENABLED = 2 + name = proto.Field(proto.STRING, number=1,) display_name = proto.Field(proto.STRING, number=2,) labels = proto.MapField(proto.STRING, proto.STRING, number=3,) @@ -210,6 +251,11 @@ class ConnectMode(proto.Enum): authorized_network = proto.Field(proto.STRING, number=20,) persistence_iam_identity = proto.Field(proto.STRING, number=21,) connect_mode = proto.Field(proto.ENUM, number=22, enum=ConnectMode,) + replica_count = proto.Field(proto.INT32, number=31,) + nodes = proto.RepeatedField(proto.MESSAGE, number=32, message="NodeInfo",) + read_endpoint = proto.Field(proto.STRING, number=33,) + read_endpoint_port = proto.Field(proto.INT32, number=34,) + read_replicas_mode = proto.Field(proto.ENUM, number=35, enum=ReadReplicasMode,) class ListInstancesRequest(proto.Message): @@ -253,9 +299,9 @@ class ListInstancesResponse(proto.Message): If the ``location_id`` in the parent field of the request is "-", all regions available to the project are queried, and the results aggregated. If in such an aggregated query a - location is unavailable, a dummy Redis entry is included in - the response with the ``name`` field set to a value of the - form + location is unavailable, a placeholder Redis entry is + included in the response with the ``name`` field set to a + value of the form ``projects/{project_id}/locations/{location_id}/instances/``- and the ``status`` field set to ERROR and ``status_message`` field set to "location not available for ListInstances". @@ -333,6 +379,7 @@ class UpdateInstanceRequest(proto.Message): - ``labels`` - ``memorySizeGb`` - ``redisConfig`` + - ``replica_count`` instance (google.cloud.redis_v1.types.Instance): Required. Update description. Only fields specified in update_mask are updated. diff --git a/tests/unit/gapic/redis_v1/test_cloud_redis.py b/tests/unit/gapic/redis_v1/test_cloud_redis.py index 006e110..c00c1a2 100644 --- a/tests/unit/gapic/redis_v1/test_cloud_redis.py +++ b/tests/unit/gapic/redis_v1/test_cloud_redis.py @@ -842,6 +842,10 @@ def test_get_instance( authorized_network="authorized_network_value", persistence_iam_identity="persistence_iam_identity_value", connect_mode=cloud_redis.Instance.ConnectMode.DIRECT_PEERING, + replica_count=1384, + read_endpoint="read_endpoint_value", + read_endpoint_port=1920, + read_replicas_mode=cloud_redis.Instance.ReadReplicasMode.READ_REPLICAS_DISABLED, ) response = client.get_instance(request) @@ -868,6 +872,13 @@ def test_get_instance( assert response.authorized_network == "authorized_network_value" assert response.persistence_iam_identity == "persistence_iam_identity_value" assert response.connect_mode == cloud_redis.Instance.ConnectMode.DIRECT_PEERING + assert response.replica_count == 1384 + assert response.read_endpoint == "read_endpoint_value" + assert response.read_endpoint_port == 1920 + assert ( + response.read_replicas_mode + == cloud_redis.Instance.ReadReplicasMode.READ_REPLICAS_DISABLED + ) def test_get_instance_from_dict(): @@ -922,6 +933,10 @@ async def test_get_instance_async( authorized_network="authorized_network_value", persistence_iam_identity="persistence_iam_identity_value", connect_mode=cloud_redis.Instance.ConnectMode.DIRECT_PEERING, + replica_count=1384, + read_endpoint="read_endpoint_value", + read_endpoint_port=1920, + read_replicas_mode=cloud_redis.Instance.ReadReplicasMode.READ_REPLICAS_DISABLED, ) ) response = await client.get_instance(request) @@ -949,6 +964,13 @@ async def test_get_instance_async( assert response.authorized_network == "authorized_network_value" assert response.persistence_iam_identity == "persistence_iam_identity_value" assert response.connect_mode == cloud_redis.Instance.ConnectMode.DIRECT_PEERING + assert response.replica_count == 1384 + assert response.read_endpoint == "read_endpoint_value" + assert response.read_endpoint_port == 1920 + assert ( + response.read_replicas_mode + == cloud_redis.Instance.ReadReplicasMode.READ_REPLICAS_DISABLED + ) @pytest.mark.asyncio