File: //lib/google-cloud-sdk/lib/googlecloudsdk/command_lib/compute/backend_services/backend_flags.py
# pylint: disable=E1305
# -*- coding: utf-8 -*- #
# Copyright 2014 Google LLC. All Rights Reserved.
#
# 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.
"""Flags and helpers for the compute backend-services backend commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import textwrap
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.command_lib.compute import flags
from googlecloudsdk.core import log
def AddDescription(parser):
parser.add_argument(
'--description',
help='An optional, textual description for the backend.')
def AddInstanceGroup(parser, operation_type, with_deprecated_zone=False):
"""Adds arguments to define instance group."""
parser.add_argument(
'--instance-group',
required=True,
help='The name or URI of a Google Cloud Instance Group.')
scope_parser = parser.add_mutually_exclusive_group()
flags.AddRegionFlag(
scope_parser,
resource_type='instance group',
operation_type='{0} the backend service'.format(operation_type),
flag_prefix='instance-group',
explanation=flags.REGION_PROPERTY_EXPLANATION_NO_DEFAULT)
if with_deprecated_zone:
flags.AddZoneFlag(
scope_parser,
resource_type='instance group',
operation_type='{0} the backend service'.format(operation_type),
explanation='DEPRECATED, use --instance-group-zone flag instead.')
flags.AddZoneFlag(
scope_parser,
resource_type='instance group',
operation_type='{0} the backend service'.format(operation_type),
flag_prefix='instance-group',
explanation=flags.ZONE_PROPERTY_EXPLANATION_NO_DEFAULT)
def WarnOnDeprecatedFlags(args):
if getattr(args, 'zone', None): # TODO(b/28518663).
log.warning(
'The --zone flag is deprecated, please use --instance-group-zone'
' instead. It will be removed in a future release.')
def _GetBalancingModes():
"""Returns the --balancing-modes flag value choices name:description dict."""
per_rate_flags = '*--max-rate-per-instance*'
per_connection_flags = '*--max-connections-per-instance*'
per_rate_flags += '/*--max-rate-per-endpoint*'
per_connection_flags += '*--max-max-per-endpoint*'
utilization_extra_help = (
'This is incompatible with --network-endpoint-group.')
balancing_modes = {
'CONNECTION': textwrap.dedent("""
Available if the backend service's load balancing scheme is either
`INTERNAL` or `EXTERNAL`.
Available if the backend service's protocol is one of `SSL`, `TCP`,
or `UDP`.
Spreads load based on how many concurrent connections the backend
can handle.
For backend services with --load-balancing-scheme `EXTERNAL`, you
must specify exactly one of these additional parameters:
`--max-connections`, `--max-connections-per-instance`, or
`--max-connections-per-endpoint`.
For backend services where `--load-balancing-scheme` is `INTERNAL`,
you must omit all of these parameters.
""").format(per_rate_flags),
'RATE': textwrap.dedent("""
Available if the backend service's load balancing scheme is
`INTERNAL_MANAGED`, `INTERNAL_SELF_MANAGED`, or `EXTERNAL`. Available
if the backend service's protocol is one of HTTP, HTTPS, or HTTP/2.
Spreads load based on how many HTTP requests per second (RPS) the
backend can handle.
You must specify exactly one of these additional parameters:
`--max-rate`, `--max-rate-per-instance`, or `--max-rate-per-endpoint`.
""").format(utilization_extra_help),
'UTILIZATION': textwrap.dedent("""
Available if the backend service's load balancing scheme is
`INTERNAL_MANAGED`, `INTERNAL_SELF_MANAGED`, or `EXTERNAL`. Available only
for managed or unmanaged instance group backends.
Spreads load based on the backend utilization of instances in a backend
instance group.
The following additional parameters may be specified:
`--max-utilization`, `--max-rate`, `--max-rate-per-instance`,
`--max-connections`, `--max-connections-per-instance`.
For valid combinations, see `--max-utilization`.
""").format(per_connection_flags),
}
return balancing_modes
def AddBalancingMode(parser,
support_global_neg=False,
support_region_neg=False):
"""Adds balancing mode argument to the argparse."""
help_text = """\
Defines how to measure whether a backend can handle additional traffic or is
fully loaded. For more information, see
https://cloud.google.com/load-balancing/docs/backend-service#balancing-mode.
"""
incompatible_types = []
if support_global_neg:
incompatible_types.extend(['INTERNET_IP_PORT', 'INTERNET_FQDN_PORT'])
if support_region_neg:
incompatible_types.append('SERVERLESS')
if incompatible_types:
help_text += """\
This cannot be used when the endpoint type of an attached network endpoint
group is {0}.
""".format(_JoinTypes(incompatible_types))
parser.add_argument(
'--balancing-mode',
choices=_GetBalancingModes(),
type=lambda x: x.upper(),
help=help_text)
def AddCapacityLimits(parser,
support_global_neg=False,
support_region_neg=False):
"""Adds capacity thresholds arguments to the argparse."""
AddMaxUtilization(parser)
capacity_group = parser.add_group(mutex=True)
capacity_incompatible_types = []
if support_global_neg:
capacity_incompatible_types.extend(
['INTERNET_IP_PORT', 'INTERNET_FQDN_PORT'])
if support_region_neg:
capacity_incompatible_types.append('SERVERLESS')
append_help_text = """\
This cannot be used when the endpoint type of an attached network endpoint
group is {0}.
""".format(_JoinTypes(
capacity_incompatible_types)) if capacity_incompatible_types else ''
capacity_group.add_argument(
'--max-rate-per-endpoint',
type=float,
help="""\
Only valid for network endpoint group backends. Defines a maximum
number of HTTP requests per second (RPS) per endpoint if all endpoints
are healthy. When one or more endpoints are unhealthy, an effective
maximum rate per healthy endpoint is calculated by multiplying
`MAX_RATE_PER_ENDPOINT` by the number of endpoints in the network
endpoint group, then dividing by the number of healthy endpoints.
""" + append_help_text)
capacity_group.add_argument(
'--max-connections-per-endpoint',
type=int,
help="""\
Only valid for network endpoint group backends. Defines a maximum
number of connections per endpoint if all endpoints are healthy. When
one or more endpoints are unhealthy, an effective maximum number of
connections per healthy endpoint is calculated by multiplying
`MAX_CONNECTIONS_PER_ENDPOINT` by the number of endpoints in the network
endpoint group, then dividing by the number of healthy endpoints.
""" + append_help_text)
capacity_group.add_argument(
'--max-rate',
type=int,
help="""\
Maximum number of HTTP requests per second (RPS) that the backend can
handle. Valid for network endpoint group and instance group backends
(except for regional managed instance groups). Must not be defined if the
backend is a managed instance group using load balancing-based autoscaling.
""" + append_help_text)
capacity_group.add_argument(
'--max-rate-per-instance',
type=float,
help="""\
Only valid for instance group backends. Defines a maximum number of
HTTP requests per second (RPS) per instance if all instances in the
instance group are healthy. When one or more instances are unhealthy,
an effective maximum RPS per healthy instance is calculated by
multiplying `MAX_RATE_PER_INSTANCE` by the number of instances in the
instance group, then dividing by the number of healthy instances. This
parameter is compatible with managed instance group backends that use
autoscaling based on load balancing.
""")
capacity_group.add_argument(
'--max-connections',
type=int,
help="""\
Maximum concurrent connections that the backend can handle. Valid for
network endpoint group and instance group backends (except for regional
managed instance groups).
""" + append_help_text)
capacity_group.add_argument(
'--max-connections-per-instance',
type=int,
help="""\
Only valid for instance group backends. Defines a maximum number
of concurrent connections per instance if all instances in the
instance group are healthy. When one or more instances are
unhealthy, an effective maximum number of connections per healthy
instance is calculated by multiplying `MAX_CONNECTIONS_PER_INSTANCE`
by the number of instances in the instance group, then dividing by
the number of healthy instances.
""")
def AddMaxUtilization(parser):
"""Adds max utilization argument to the argparse."""
parser.add_argument(
'--max-utilization',
type=arg_parsers.BoundedFloat(lower_bound=0.0, upper_bound=1.0),
help="""\
Defines the maximum target for average utilization of the backend instance
in the backend instance group. Acceptable values are `0.0` (0%) through
`1.0`(100%). Available for all backend service protocols, with
`--balancing-mode=UTILIZATION`.
For backend services that use SSL, TCP, or UDP protocols, the following
configuration options are supported:
* no additional parameter
* only `--max-utilization`
* only `--max-connections` (except for regional managed instance groups)
* only `--max-connections-per-instance`
* both `--max-utilization` and `--max-connections` (except for regional
managed instance groups)
* both `--max-utilization` and `--max-connections-per-instance`
The meanings for `-max-connections` and `--max-connections-per-instance`
are the same as for --balancing-mode=CONNECTION. If one is used with
`--max-utilization`, instances are considered at capacity
when either maximum utilization or maximum connections is reached.
For backend services that use HTTP, HTTPS, or HTTP/2 protocols, the
following configuration options are supported:
* no additional parameter
* only `--max-utilization`
* only `--max-rate` (except for regional managed instance groups)
* only `--max-rate-per-instance`
* both `--max-utilization` and `--max-rate` (except for regional managed
instance groups)
* both `--max-utilization` and `--max-rate-per-instance`
The meanings for `--max-rate` and `--max-rate-per-instance` are the same
as for --balancing-mode=RATE. If one is used in conjunction with
`--max-utilization`, instances are considered at capacity when *either*
maximum utilization or the maximum rate is reached.""")
def AddCapacityScalar(parser,
support_global_neg=False,
support_region_neg=False):
"""Adds capacity thresholds argument to the argparse."""
help_text = """\
A setting that applies to all balancing modes. This value is multiplied
by the balancing mode value to set the current max usage of the instance
group. You can set the capacity scaler to `0.0` or from `0.1` (10%) to
`1.0` (100%). You cannot configure a setting that is larger than `0.0` and
smaller than `0.1`. A scale factor of zero (`0.0`) prevents all new
connections. You cannot configure a setting of
`0.0` when there is only one backend attached to the backend service. Note
that draining a backend service only prevents new connections to instances
in the group. All existing connections are allowed to continue until they
close by normal means. This cannot be used for internal load balancing.
"""
incompatible_types = []
if support_global_neg:
incompatible_types.extend(['INTERNET_IP_PORT', 'INTERNET_FQDN_PORT'])
if support_region_neg:
incompatible_types.append('SERVERLESS')
if incompatible_types:
help_text += """\
This cannot be used when the endpoint type of an attached network endpoint
group is {0}.
""".format(_JoinTypes(incompatible_types))
parser.add_argument(
'--capacity-scaler',
type=arg_parsers.BoundedFloat(lower_bound=0.0, upper_bound=1.0),
help=help_text)
def AddFailover(parser, default):
"""Adds the failover argument to the argparse."""
parser.add_argument(
'--failover',
action='store_true',
default=default,
help="""\
Designates whether this is a failover backend. More than one
failover backend can be configured for a given BackendService.
Not compatible with the --global flag""")
def _JoinTypes(types):
return ', or '.join([', '.join(types[:-1]), types[-1]
]) if len(types) > 2 else ' or '.join(types)