1178 lines
36 KiB
Python
1178 lines
36 KiB
Python
# -*- coding: utf-8 -*- #
|
|
# Copyright 2016 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.
|
|
"""Common flags for some of the DNS commands."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import unicode_literals
|
|
|
|
from googlecloudsdk.calliope import actions
|
|
from googlecloudsdk.calliope import arg_parsers
|
|
from googlecloudsdk.calliope import base
|
|
from googlecloudsdk.calliope.concepts import concepts
|
|
from googlecloudsdk.command_lib.util import completers
|
|
from googlecloudsdk.command_lib.util.apis import arg_utils
|
|
from googlecloudsdk.command_lib.util.concepts import concept_parsers
|
|
|
|
|
|
class BetaKeyCompleter(completers.ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(BetaKeyCompleter, self).__init__(
|
|
collection='dns.dnsKeys',
|
|
api_version='v1beta2',
|
|
list_command='beta dns dns-keys list --format=value(keyTag)',
|
|
parse_output=True,
|
|
flags=['zone'],
|
|
**kwargs,
|
|
)
|
|
|
|
|
|
class KeyCompleter(completers.ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(KeyCompleter, self).__init__(
|
|
collection='dns.dnsKeys',
|
|
api_version='v1',
|
|
list_command='dns dns-keys list --format=value(keyTag)',
|
|
parse_output=True,
|
|
flags=['zone'],
|
|
**kwargs,
|
|
)
|
|
|
|
|
|
class ManagedZoneCompleter(completers.ListCommandCompleter):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(ManagedZoneCompleter, self).__init__(
|
|
collection='dns.managedZones',
|
|
list_command='dns managed-zones list --uri',
|
|
**kwargs,
|
|
)
|
|
|
|
|
|
def GetKeyArg(help_text='The DNS key identifier.', is_beta=False):
|
|
return base.Argument(
|
|
'key_id',
|
|
metavar='KEY-ID',
|
|
completer=BetaKeyCompleter if is_beta else KeyCompleter,
|
|
help=help_text,
|
|
)
|
|
|
|
|
|
def GetDnsZoneArg(help_text):
|
|
return base.Argument(
|
|
'dns_zone',
|
|
metavar='ZONE_NAME',
|
|
completer=ManagedZoneCompleter,
|
|
help=help_text,
|
|
)
|
|
|
|
|
|
def ZoneAttributeConfig():
|
|
return concepts.ResourceParameterAttributeConfig(
|
|
name='zone', help_text='The Cloud DNS zone for the {resource}.'
|
|
)
|
|
|
|
|
|
def GetZoneResourceSpec():
|
|
return concepts.ResourceSpec(
|
|
'dns.managedZones',
|
|
resource_name='zone',
|
|
managedZone=ZoneAttributeConfig(),
|
|
project=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
|
|
disable_auto_completers=False,
|
|
)
|
|
|
|
|
|
def GetZoneResourceArg(help_text, positional=True, plural=False):
|
|
arg_name = 'zones' if plural else 'zone'
|
|
return concept_parsers.ConceptParser.ForResource(
|
|
arg_name if positional else '--{}'.format(arg_name),
|
|
GetZoneResourceSpec(),
|
|
help_text,
|
|
plural=plural,
|
|
required=True,
|
|
)
|
|
|
|
|
|
def GetZoneArg(
|
|
help_text='Name of the managed zone whose record sets you want to manage.',
|
|
hide_short_zone_flag=False,
|
|
):
|
|
"""Returns the managed zone arg."""
|
|
if hide_short_zone_flag:
|
|
zone_group = base.ArgumentGroup(required=True)
|
|
zone_group.AddArgument(
|
|
base.Argument('--zone', completer=ManagedZoneCompleter, help=help_text)
|
|
)
|
|
zone_group.AddArgument(
|
|
base.Argument(
|
|
'-z',
|
|
dest='zone',
|
|
completer=ManagedZoneCompleter,
|
|
help=help_text,
|
|
hidden=True,
|
|
)
|
|
)
|
|
return zone_group
|
|
else:
|
|
return base.Argument(
|
|
'--zone',
|
|
'-z',
|
|
completer=ManagedZoneCompleter,
|
|
help=help_text,
|
|
required=True,
|
|
)
|
|
|
|
|
|
def GetManagedZonesDnsNameArg():
|
|
return base.Argument(
|
|
'--dns-name',
|
|
required=True,
|
|
help='The DNS name suffix that will be managed with the created zone.',
|
|
)
|
|
|
|
|
|
def GetZoneIdArg(
|
|
help_text=(
|
|
'The unique system generated id for the peering zone to deactivate.'
|
|
),
|
|
):
|
|
return base.Argument('--zone-id', required=True, help=help_text)
|
|
|
|
|
|
def GetPeeringZoneListArg():
|
|
return base.Argument(
|
|
'--target-network',
|
|
required=True,
|
|
help=(
|
|
'The network url of the Google Compute Engine private network '
|
|
'to forward queries to.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetManagedZonesDescriptionArg():
|
|
return base.Argument(
|
|
'--description',
|
|
required=False,
|
|
help='Short description for the managed zone.',
|
|
)
|
|
|
|
|
|
def GetDnsSecStateFlagMapper(messages, api_version='v1'):
|
|
"""Returns a ChoiceEnumMapper for the --dnssec-state flag.
|
|
|
|
The v2 DNS API uses uppercase enum values for dnssec-state (e.g. 'ON'),
|
|
while v1 uses lowercase. To maintain a consistent user experience, gcloud
|
|
accepts lowercase values for all API versions. The `ChoiceEnumMapper`
|
|
validates that custom mapping keys are valid API enum values. For v2, this
|
|
requires mapping the uppercase API enum to the lowercase, user-facing
|
|
choice. The mapper then handles translating the user's input to the
|
|
correct value for the API request.
|
|
|
|
Args:
|
|
messages: The messages module for the API version.
|
|
api_version: The API version to use (e.g., 'v1', 'v2').
|
|
|
|
Returns:
|
|
A ChoiceEnumMapper for the --dnssec-state flag.
|
|
"""
|
|
v1_mappings = {
|
|
'off': ('off', 'Disable DNSSEC for the managed zone.'),
|
|
'on': ('on', 'Enable DNSSEC for the managed zone.'),
|
|
'transfer': (
|
|
'transfer',
|
|
'Enable DNSSEC and allow transferring a signed zone in or out.',
|
|
),
|
|
}
|
|
if api_version == 'v2':
|
|
custom_mappings = {k.upper(): v for k, v in v1_mappings.items()}
|
|
else:
|
|
custom_mappings = v1_mappings
|
|
return arg_utils.ChoiceEnumMapper(
|
|
'--dnssec-state',
|
|
messages.ManagedZoneDnsSecConfig.StateValueValuesEnum,
|
|
custom_mappings=custom_mappings,
|
|
help_str='The DNSSEC state for this managed zone.',
|
|
)
|
|
|
|
|
|
def GetDoeFlagMapper(messages):
|
|
return arg_utils.ChoiceEnumMapper(
|
|
'--denial-of-existence',
|
|
messages.ManagedZoneDnsSecConfig.NonExistenceValueValuesEnum,
|
|
help_str='Requires DNSSEC enabled.',
|
|
)
|
|
|
|
|
|
def GetKeyAlgorithmFlagMapper(key_type, messages):
|
|
return arg_utils.ChoiceEnumMapper(
|
|
'--{}-algorithm'.format(key_type),
|
|
messages.DnsKeySpec.AlgorithmValueValuesEnum,
|
|
help_str=(
|
|
'String mnemonic specifying the DNSSEC algorithm of the '
|
|
'key-signing key. Requires DNSSEC enabled'
|
|
),
|
|
)
|
|
|
|
|
|
def AddCommonManagedZonesDnssecArgs(parser, messages, api_version='v1'):
|
|
"""Add Common DNSSEC flags for the managed-zones group."""
|
|
GetDnsSecStateFlagMapper(messages, api_version).choice_arg.AddToParser(parser)
|
|
GetDoeFlagMapper(messages).choice_arg.AddToParser(parser)
|
|
GetKeyAlgorithmFlagMapper('ksk', messages).choice_arg.AddToParser(parser)
|
|
GetKeyAlgorithmFlagMapper('zsk', messages).choice_arg.AddToParser(parser)
|
|
parser.add_argument(
|
|
'--ksk-key-length',
|
|
type=int,
|
|
help='Length of the key-signing key in bits. Requires DNSSEC enabled.',
|
|
)
|
|
parser.add_argument(
|
|
'--zsk-key-length',
|
|
type=int,
|
|
help='Length of the zone-signing key in bits. Requires DNSSEC enabled.',
|
|
)
|
|
|
|
|
|
def GetManagedZoneVisibilityArg():
|
|
return base.Argument(
|
|
'--visibility',
|
|
choices=['public', 'private'],
|
|
default='public',
|
|
help=(
|
|
'Visibility of the zone. Public zones are visible to the public '
|
|
'internet. Private zones are only visible in your internal '
|
|
'networks denoted by the `--networks` flag.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetManagedZoneNetworksArg():
|
|
return base.Argument(
|
|
'--networks',
|
|
metavar='NETWORK',
|
|
type=arg_parsers.ArgList(),
|
|
help=(
|
|
'List of networks that the zone should be visible in if the zone '
|
|
'visibility is [private].'
|
|
),
|
|
)
|
|
|
|
|
|
def GetManagedZoneGkeClustersArg():
|
|
return base.Argument(
|
|
'--gkeclusters',
|
|
metavar='GKECLUSTERS',
|
|
type=arg_parsers.ArgList(),
|
|
help=(
|
|
'List of GKE clusters that the zone should be visible in if the zone '
|
|
'visibility is [private].'
|
|
),
|
|
)
|
|
|
|
|
|
def GetDnsPeeringArgs():
|
|
"""Return arg group for DNS Peering flags."""
|
|
peering_group = base.ArgumentGroup(required=False)
|
|
target_network_help_text = (
|
|
'Network ID of the Google Compute Engine private network to forward'
|
|
' queries to.'
|
|
)
|
|
target_project_help_text = (
|
|
'Project ID of the Google Compute Engine private network to forward'
|
|
' queries to.'
|
|
)
|
|
peering_group.AddArgument(
|
|
base.Argument(
|
|
'--target-network', required=True, help=target_network_help_text
|
|
)
|
|
)
|
|
peering_group.AddArgument(
|
|
base.Argument(
|
|
'--target-project', required=True, help=target_project_help_text
|
|
)
|
|
)
|
|
return peering_group
|
|
|
|
|
|
def GetForwardingTargetsArg():
|
|
return base.Argument(
|
|
'--forwarding-targets',
|
|
type=arg_parsers.ArgList(),
|
|
metavar='IP_ADDRESSES',
|
|
help=(
|
|
'List of IPv4/IPv6 addresses or one domain name of the target name'
|
|
' server that the zone will forward queries to. Ignored for `public`'
|
|
' visibility. Non-RFC1918 addresses will forward to the target'
|
|
' through the Internet. RFC1918 addresses will forward through the'
|
|
' VPC.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetPrivateForwardingTargetsArg():
|
|
return base.Argument(
|
|
'--private-forwarding-targets',
|
|
type=arg_parsers.ArgList(),
|
|
metavar='IP_ADDRESSES',
|
|
help=(
|
|
'List of IPv4/IPv6 addresses or one domain name of the target name'
|
|
' server that the zone will forward queries to. Ignored for `public`'
|
|
' visibility. All addresses specified for this parameter will be'
|
|
' reached through the VPC.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetReverseLookupArg():
|
|
return base.Argument(
|
|
'--managed-reverse-lookup',
|
|
action='store_true',
|
|
default=None,
|
|
help=(
|
|
'Specifies whether this zone is a managed reverse lookup zone, '
|
|
'required for Cloud DNS to correctly resolve Non-RFC1918 PTR records.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetServiceDirectoryArg():
|
|
return base.Argument(
|
|
'--service-directory-namespace',
|
|
required=False,
|
|
help=(
|
|
'The fully qualified URL of the service directory namespace that '
|
|
'should be associated with the zone. Ignored for `public` visibility '
|
|
'zones.'
|
|
),
|
|
)
|
|
|
|
|
|
# Policy Flags
|
|
def GetPolicyDescriptionArg(required=False):
|
|
return base.Argument(
|
|
'--description', required=required, help='A description of the policy.'
|
|
)
|
|
|
|
|
|
def GetPolicyNetworksArg(required=False):
|
|
return base.Argument(
|
|
'--networks',
|
|
type=arg_parsers.ArgList(),
|
|
metavar='NETWORKS',
|
|
required=required,
|
|
help=(
|
|
'The comma separated list of network names to associate with '
|
|
'the policy.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetPolicyInboundForwardingArg():
|
|
return base.Argument(
|
|
'--enable-inbound-forwarding',
|
|
action='store_true',
|
|
help=(
|
|
'Specifies whether to allow networks bound to this policy to '
|
|
'receive DNS queries sent by VMs or applications over VPN '
|
|
'connections. Defaults to False.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetPolicyLoggingArg():
|
|
return base.Argument(
|
|
'--enable-logging',
|
|
action='store_true',
|
|
help='Specifies whether to enable query logging. Defaults to False.',
|
|
)
|
|
|
|
|
|
def GetPolicyAltNameServersArg():
|
|
return base.Argument(
|
|
'--alternative-name-servers',
|
|
type=arg_parsers.ArgList(),
|
|
metavar='NAME_SERVERS',
|
|
help=(
|
|
'List of alternative name servers to forward to. Non-RFC1918 '
|
|
'addresses will forward to the target through the Internet.'
|
|
'RFC1918 addresses will forward through the VPC.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetPolicyPrivateAltNameServersArg():
|
|
return base.Argument(
|
|
'--private-alternative-name-servers',
|
|
type=arg_parsers.ArgList(),
|
|
metavar='NAME_SERVERS',
|
|
help=(
|
|
'List of alternative name servers to forward to. All addresses'
|
|
' specified for this parameter will be reached through the VPC.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetEnableDns64AllQueriesArg(update=False):
|
|
"""Returns the enable dns64 all queries arg for create or update."""
|
|
if not update:
|
|
return base.Argument(
|
|
'--enable-dns64-all-queries',
|
|
action='store_true',
|
|
default=None,
|
|
help=(
|
|
'Specifies whether to allow networks bound to this policy to use '
|
|
'DNS64 for IPv6-only VM instances.'
|
|
),
|
|
)
|
|
else:
|
|
return base.Argument(
|
|
'--enable-dns64-all-queries',
|
|
action=arg_parsers.StoreTrueFalseAction,
|
|
help=(
|
|
'Specifies whether to allow networks bound to this policy to use '
|
|
'DNS64 for IPv6-only VM instances.'
|
|
),
|
|
)
|
|
|
|
|
|
## ResourceRecordSets flags.
|
|
def GetResourceRecordSetsNameArg():
|
|
return base.Argument(
|
|
'name', metavar='DNS_NAME', help='DNS or domain name of the record-set.'
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsTypeArg(required=False):
|
|
return base.Argument(
|
|
'--type',
|
|
required=required,
|
|
help='DNS record type of the record-set (e.g. A, AAAA, MX etc.).',
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsTtlArg(required=False):
|
|
return base.Argument(
|
|
'--ttl',
|
|
type=int,
|
|
required=required,
|
|
help='TTL (time to live) for the record-set.',
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsRrdatasArg(required=False):
|
|
return base.Argument(
|
|
'--rrdatas',
|
|
metavar='RRDATA',
|
|
required=required,
|
|
type=arg_parsers.ArgList(),
|
|
help=(
|
|
'DNS data (Address/CNAME/MX info, etc.) of the record-set. '
|
|
'This is RDATA; the format of this information varies depending '
|
|
'on the type and class of the resource record.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsRrdatasArgGroup(use_deprecated_names=False):
|
|
"""Returns arg group for rrdatas flags.
|
|
|
|
Args:
|
|
use_deprecated_names: If true, uses snake_case names for flags
|
|
--routing-policy-type and --routing-policy-data, --routing_policy_type and
|
|
--routing_policy_data. This group is defined with required=True and
|
|
mutex=True, meaning that exactly one of these two arg configurations must
|
|
be specified: --rrdatas --routing-policy-type AND --routing-policy-data
|
|
"""
|
|
# Group containing the primary backup config.
|
|
routing_policy_backup_data_group = base.ArgumentGroup(
|
|
mutex=True,
|
|
required=True,
|
|
help=(
|
|
'Routing policy backup data arguments for the primary backup routing'
|
|
' policy. Specify either --routing-policy-backup-data or'
|
|
' --routing-policy-backup-item, but not both.'
|
|
),
|
|
)
|
|
routing_policy_backup_data_group.AddArgument(
|
|
GetResourceRecordSetsRoutingPolicyBackupDataArg()
|
|
)
|
|
routing_policy_backup_data_group.AddArgument(GetRoutingPolicyBackupItemArg())
|
|
|
|
primary_backup_data_group = base.ArgumentGroup(
|
|
help='Configuration for primary backup routing policy'
|
|
)
|
|
primary_backup_data_group.AddArgument(
|
|
GetResourceRecordSetsRoutingPolicyPrimaryDataArg(required=True)
|
|
)
|
|
primary_backup_data_group.AddArgument(routing_policy_backup_data_group)
|
|
primary_backup_data_group.AddArgument(
|
|
GetResourceRecordSetsRoutingPolicyBackupDataTypeArg(required=True)
|
|
)
|
|
primary_backup_data_group.AddArgument(
|
|
GetResourceRecordSetsBackupDataTrickleRatio(required=False)
|
|
)
|
|
|
|
# This group dictates that we should either have a primary backup config,
|
|
# or, a wrr or geo config
|
|
policy_data_group = base.ArgumentGroup(
|
|
required=True,
|
|
mutex=True,
|
|
help=(
|
|
'Routing policy data arguments. Allows setting one of'
|
|
' [routing-policy-data, routing-policy-item,'
|
|
' [routing-policy-primary-data, [routing-policy-backup-data,'
|
|
' routing-policy-backup-item]]]'
|
|
),
|
|
)
|
|
policy_data_group.AddArgument(
|
|
GetResourceRecordSetsRoutingPolicyDataArg(
|
|
deprecated_name=use_deprecated_names
|
|
)
|
|
)
|
|
policy_data_group.AddArgument(primary_backup_data_group)
|
|
policy_data_group.AddArgument(GetRoutingPolicyItemArg())
|
|
# Declare optional routing policy group. If group specified, must contain
|
|
# both routing-policy-type and routing-policy-data args.
|
|
policy_group = base.ArgumentGroup(
|
|
required=False,
|
|
help=(
|
|
'Routing policy arguments. --routing-policy-type should be specified'
|
|
' exactly when one of --routing-policy-data, --routing-policy-item,'
|
|
' or --routing-policy-primary-data is set.'
|
|
),
|
|
)
|
|
health_checking_group = base.ArgumentGroup(
|
|
required=False,
|
|
mutex=True,
|
|
help=(
|
|
'Health checking arguments. You can specify one of --health-check or'
|
|
' --enable-health-checking, but not both.'
|
|
),
|
|
)
|
|
health_checking_group.AddArgument(
|
|
GetResourceRecordSetsEnableHealthChecking(required=False)
|
|
)
|
|
health_checking_group.AddArgument(GetHealthCheckArg(required=False))
|
|
|
|
policy_group.AddArgument(
|
|
GetResourceRecordSetsRoutingPolicyTypeArg(
|
|
required=True, deprecated_name=use_deprecated_names
|
|
)
|
|
)
|
|
policy_group.AddArgument(
|
|
GetResourceRecordSetsEnableFencingArg(required=False)
|
|
)
|
|
policy_group.AddArgument(health_checking_group)
|
|
policy_group.AddArgument(policy_data_group)
|
|
|
|
rrdatas_group = base.ArgumentGroup(
|
|
required=True,
|
|
mutex=True,
|
|
help=(
|
|
'Resource record sets arguments. Can specify either --rrdatas or both'
|
|
' --routing-policy-data and --routing-policy-type.'
|
|
),
|
|
)
|
|
rrdatas_group.AddArgument(GetResourceRecordSetsRrdatasArg(required=False))
|
|
rrdatas_group.AddArgument(policy_group)
|
|
|
|
return rrdatas_group
|
|
|
|
|
|
def GetResourceRecordSetsRoutingPolicyTypeArg(
|
|
required=False, deprecated_name=False
|
|
):
|
|
"""Returns --routing-policy-type command line arg value."""
|
|
flag_name = (
|
|
'--routing_policy_type' if deprecated_name else '--routing-policy-type'
|
|
)
|
|
return base.Argument(
|
|
flag_name,
|
|
metavar='ROUTING_POLICY_TYPE',
|
|
required=required,
|
|
choices=['GEO', 'WRR', 'FAILOVER'],
|
|
help=(
|
|
'Indicates what type of routing policy is being specified. As of this'
|
|
' time, this field can take on either "WRR" for weighted round robin,'
|
|
' "GEO" for geo location, or "FAILOVER" for a primary-backup'
|
|
' configuration. This field cannot be modified - once a policy has a'
|
|
' chosen type, the only way to change it is to delete the policy and'
|
|
' add a new one with the different type.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsEnableFencingArg(required=False):
|
|
"""Returns --enable-geo-fencing command line arg value."""
|
|
return base.Argument(
|
|
'--enable-geo-fencing',
|
|
action='store_true',
|
|
required=required,
|
|
help='Specifies whether to enable fencing for geo queries.',
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsBackupDataTrickleRatio(required=False):
|
|
"""Returns --backup-data-trickle-ratio command line arg value."""
|
|
return base.Argument(
|
|
'--backup-data-trickle-ratio',
|
|
type=float,
|
|
required=required,
|
|
help=(
|
|
'Specifies the percentage of traffic to send to the backup targets'
|
|
' even when the primary targets are healthy.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsRoutingPolicyBackupDataTypeArg(required=True):
|
|
"""Returns --routing_policy_backup_data_type command line arg value."""
|
|
return base.Argument(
|
|
'--routing-policy-backup-data-type',
|
|
metavar='ROUTING_POLICY_BACKUP_DATA_TYPE',
|
|
required=required,
|
|
choices=['GEO'],
|
|
help=(
|
|
'For FAILOVER routing policies, the type of routing policy the backup'
|
|
' data uses. Currently, this must be GEO'
|
|
),
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsEnableHealthChecking(required=False):
|
|
"""Returns --enable-health-checking command line arg value."""
|
|
return base.Argument(
|
|
'--enable-health-checking',
|
|
action='store_true',
|
|
required=required,
|
|
help='Required if specifying forwarding rule names for rrdata.',
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsRoutingPolicyPrimaryDataArg(required=False):
|
|
"""Returns --routing-policy-primary-data command line arg value."""
|
|
|
|
def RoutingPolicyPrimaryDataArg(routing_policy_primary_data):
|
|
"""Converts --routing-policy-primary-data flag value to a list of policy data items.
|
|
|
|
Args:
|
|
routing_policy_primary_data: String value specified in the
|
|
--routing-policy-primary-data flag.
|
|
|
|
Returns:
|
|
A list of forwarding configs in the following format:
|
|
['config1@region1', 'config2@region2', 'config3' ]
|
|
OR a list of IP addresses in the following format:
|
|
['1.1.1.1', '2.2.2.2', '3.3.3.3']
|
|
"""
|
|
|
|
# Grab each policy data item by splitting on ','
|
|
return routing_policy_primary_data.split(',')
|
|
|
|
return base.Argument(
|
|
'--routing-policy-primary-data',
|
|
metavar='ROUTING_POLICY_PRIMARY_DATA',
|
|
required=required,
|
|
type=RoutingPolicyPrimaryDataArg,
|
|
help=(
|
|
'The primary configuration for a primary backup routing policy. '
|
|
'This configuration is a list of forwarding rules of the format '
|
|
'"FORWARDING_RULE_NAME", "FORWARDING_RULE_NAME@scope", or the full '
|
|
'resource path of the forwarding rule.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsRoutingPolicyBackupDataArg(required=False):
|
|
"""Returns --routing-policy-backup-data command line arg value."""
|
|
|
|
def RoutingPolicyBackupDataArg(routing_policy_backup_data):
|
|
"""Converts --routing-policy-backup-data flag value to a list of policy data items.
|
|
|
|
Args:
|
|
routing_policy_backup_data: String value specified in the
|
|
--routing-policy-backup-data flag.
|
|
|
|
Returns:
|
|
A list of policy data items in the format below:
|
|
|
|
[
|
|
{
|
|
'key': <location1>,
|
|
'values': <list of forwarding configs and rrdatas>,
|
|
},
|
|
{
|
|
'key': <location2>,
|
|
'values': <list of forwarding configs and rrdatas>,
|
|
},
|
|
...
|
|
]
|
|
"""
|
|
|
|
backup_data = []
|
|
|
|
# Grab each policy data item, split by ';'
|
|
policy_items = routing_policy_backup_data.split(';')
|
|
for policy_item in policy_items:
|
|
# Grab key and value from policy_item, split by ':'
|
|
key_value_split = policy_item.split('=')
|
|
|
|
# Ensure that there is only one key and value from the string split on ':'
|
|
if len(key_value_split) != 2:
|
|
raise arg_parsers.ArgumentTypeError(
|
|
'Must specify exactly one "=" inside each policy data item'
|
|
)
|
|
key = key_value_split[0]
|
|
value = key_value_split[1]
|
|
|
|
backup_data.append({'key': key, 'values': value})
|
|
|
|
return backup_data
|
|
|
|
return base.Argument(
|
|
'--routing-policy-backup-data',
|
|
action=actions.DeprecationAction(
|
|
'--routing-policy-backup-data',
|
|
warn=(
|
|
'The `--routing-policy-backup-data` flag is deprecated. Use'
|
|
' --routing-policy-backup-item instead.'
|
|
),
|
|
),
|
|
metavar='ROUTING_POLICY_BACKUP_DATA',
|
|
required=required,
|
|
type=RoutingPolicyBackupDataArg,
|
|
help=(
|
|
'Specify the backup configuration for a primary backup routing'
|
|
' policy. This backup configuration uses the same format as the'
|
|
' routing-policy-data argument because it functions as another'
|
|
' geolocation routing policy.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetResourceRecordSetsRoutingPolicyDataArg(
|
|
required=False, deprecated_name=False
|
|
):
|
|
"""Returns --routing-policy-data command line arg value."""
|
|
|
|
def RoutingPolicyDataArgType(routing_policy_data_value):
|
|
"""Converts --routing-policy-data flag value to a list of policy data items.
|
|
|
|
Args:
|
|
routing_policy_data_value: String value specified in the
|
|
--routing-policy-data flag.
|
|
|
|
Returns:
|
|
A list of policy data items in the format below:
|
|
|
|
[
|
|
{
|
|
'key': <routing_policy_data_key1>,
|
|
'values': <list of configs and rrdatas>,
|
|
},
|
|
{
|
|
'key': <routing_policy_data_key2>,
|
|
'values': <list of configs and rrdatas>,
|
|
},
|
|
...
|
|
]
|
|
|
|
Where <routing_policy_data_key> is either a weight or location name,
|
|
depending on whether the user specified --routing-policy-type == WRR or
|
|
--routing-policy-type == GEO, respectively. We keep
|
|
<routing_policy_data_key> a string value, even in the case of weights
|
|
(which will eventually be interpereted as floats). This is to keep this
|
|
flag type generic between WRR and GEO types.
|
|
"""
|
|
routing_policy_data = []
|
|
|
|
# Grab each policy data item, split by ';'
|
|
policy_items = routing_policy_data_value.split(';')
|
|
for policy_item in policy_items:
|
|
# Grab key and value from policy_item, split by ':'
|
|
key_value_split = policy_item.split('=')
|
|
|
|
# Ensure that there is only one key and value from the string split on ':'
|
|
if len(key_value_split) != 2:
|
|
raise arg_parsers.ArgumentTypeError(
|
|
'Must specify exactly one "=" inside each policy data item'
|
|
)
|
|
key = key_value_split[0]
|
|
value = key_value_split[1]
|
|
|
|
routing_policy_data.append({
|
|
'key': key,
|
|
'values': value,
|
|
})
|
|
return routing_policy_data
|
|
|
|
flag_name = (
|
|
'--routing_policy_data' if deprecated_name else '--routing-policy-data'
|
|
)
|
|
return base.Argument(
|
|
flag_name,
|
|
action=actions.DeprecationAction(
|
|
flag_name,
|
|
warn=(
|
|
f'The `{flag_name}` flag is deprecated. Use'
|
|
' --routing-policy-item instead.'
|
|
),
|
|
),
|
|
metavar='ROUTING_POLICY_DATA',
|
|
required=required,
|
|
type=RoutingPolicyDataArgType,
|
|
help=(
|
|
'The routing policy data supports one of two formats below, depending'
|
|
' on the choice of routing-policy-type.\n\nFor --routing-policy-type'
|
|
' = "WRR" this flag indicates the weighted round robin policy data.'
|
|
' The field accepts a semicolon-delimited list of the format'
|
|
' "${weight_percent}=${rrdata},${rrdata}". Specify weight as a'
|
|
' non-negative number (0 is allowed). Ratio of traffic routed to the'
|
|
' target is calculated from the ratio of individual weight over the'
|
|
' total across all weights.\n\nFor --routing-policy-type = "GEO" this'
|
|
' flag indicates the geo-locations policy data. The field accepts a'
|
|
' semicolon-delimited list of the format'
|
|
' "${region}=${rrdata},${rrdata}". Each rrdata can either be an IP'
|
|
' address or a reference to a forwarding rule of the format'
|
|
' "FORWARDING_RULE_NAME", "FORWARDING_RULE_NAME@{region}",'
|
|
' "FORWARDING_RULE_NAME@global", or the full resource path of the'
|
|
' forwarding rule.'
|
|
),
|
|
)
|
|
|
|
|
|
# Response Policy Flags
|
|
def GetResponsePolicyDescriptionArg(required=False):
|
|
return base.Argument(
|
|
'--description',
|
|
required=required,
|
|
help='A description of the response policy.',
|
|
)
|
|
|
|
|
|
def GetResponsePolicyNetworksArg(required=False):
|
|
return base.Argument(
|
|
'--networks',
|
|
type=arg_parsers.ArgList(),
|
|
required=required,
|
|
metavar='NETWORKS',
|
|
help=(
|
|
'The comma-separated list of network names to associate with '
|
|
'the response policy.'
|
|
),
|
|
)
|
|
|
|
|
|
CHANGES_FORMAT = 'table(id, startTime, status)'
|
|
|
|
|
|
def _FormatHealthCheckTarget(health_check_target):
|
|
fields = (
|
|
'ipAddress',
|
|
'port',
|
|
'ipProtocol',
|
|
'networkUrl',
|
|
'project',
|
|
'region',
|
|
'loadBalancerType',
|
|
)
|
|
return ', '.join(
|
|
health_check_target[f] for f in fields if f in health_check_target
|
|
)
|
|
|
|
|
|
def _FormatRrdata(routing_policy_item):
|
|
rrdata = []
|
|
if 'rrdatas' in routing_policy_item:
|
|
rrdata = rrdata + routing_policy_item['rrdatas']
|
|
if 'healthCheckedTargets' in routing_policy_item:
|
|
rrdata = (
|
|
rrdata
|
|
+ [
|
|
'"{}"'.format(_FormatHealthCheckTarget(target))
|
|
for target in routing_policy_item['healthCheckedTargets'].get(
|
|
'internalLoadBalancers', []
|
|
)
|
|
]
|
|
+ routing_policy_item['healthCheckedTargets'].get(
|
|
'externalEndpoints', []
|
|
)
|
|
)
|
|
return ','.join(rrdata)
|
|
|
|
|
|
def _FormatResourceRecordSet(rrdatas_or_routing_policy):
|
|
"""Format rrset based on rrdatas or routing policy type."""
|
|
if 'wrr' in rrdatas_or_routing_policy:
|
|
items = []
|
|
for item in rrdatas_or_routing_policy['wrr']['items']:
|
|
items.append('{}: {}'.format(item['weight'], _FormatRrdata(item)))
|
|
data = '; '.join(items)
|
|
elif 'geo' in rrdatas_or_routing_policy:
|
|
items = []
|
|
for item in rrdatas_or_routing_policy['geo']['items']:
|
|
items.append('{}: {}'.format(item['location'], _FormatRrdata(item)))
|
|
data = '; '.join(items)
|
|
elif 'primaryBackup' in rrdatas_or_routing_policy:
|
|
items = []
|
|
for item in rrdatas_or_routing_policy['primaryBackup']['backupGeoTargets'][
|
|
'items'
|
|
]:
|
|
items.append('{}: {}'.format(item['location'], _FormatRrdata(item)))
|
|
backup = ';'.join(items)
|
|
primary = ','.join(
|
|
list(
|
|
'"{}"'.format(_FormatHealthCheckTarget(target))
|
|
for target in rrdatas_or_routing_policy['primaryBackup'][
|
|
'primaryTargets'
|
|
].get('internalLoadBalancers', [])
|
|
)
|
|
+ rrdatas_or_routing_policy['primaryBackup']['primaryTargets'].get(
|
|
'externalEndpoints', []
|
|
)
|
|
)
|
|
data = 'Primary: {} Backup: {}'.format(primary, backup)
|
|
else:
|
|
data = ','.join(rrdatas_or_routing_policy)
|
|
if 'healthCheck' in rrdatas_or_routing_policy:
|
|
data = data + ' Health Check: {}'.format(
|
|
rrdatas_or_routing_policy['healthCheck']
|
|
)
|
|
return data
|
|
|
|
|
|
RESOURCERECORDSETS_TRANSFORMS = {
|
|
'formatrrset': _FormatResourceRecordSet,
|
|
}
|
|
RESOURCERECORDSETS_FORMAT = """
|
|
table(
|
|
name,
|
|
type,
|
|
ttl,
|
|
firstof(rrdatas,routingPolicy).formatrrset():label=DATA)
|
|
"""
|
|
|
|
|
|
def GetResponsePolicyGkeClustersArg(required=False):
|
|
return base.Argument(
|
|
'--gkeclusters',
|
|
type=arg_parsers.ArgList(),
|
|
required=required,
|
|
metavar='GKECLUSTERS',
|
|
help=(
|
|
'The comma-separated list of GKE cluster names to associate with '
|
|
'the response policy.'
|
|
),
|
|
)
|
|
|
|
|
|
# Response Policy Rule Flags
|
|
def GetResponsePolicyRulesBehaviorFlagMapper(messages):
|
|
return arg_utils.ChoiceEnumMapper(
|
|
'--behavior',
|
|
messages.ResponsePolicyRule.BehaviorValueValuesEnum,
|
|
include_filter=lambda x: x != 'behaviorUnspecified',
|
|
help_str='The response policy rule query behavior.',
|
|
)
|
|
|
|
|
|
def GetResponsePolicyRulesBehavior():
|
|
return base.Argument(
|
|
'--behavior',
|
|
choices=['behaviorUnspecified', 'bypassResponsePolicy'],
|
|
help='The response policy rule query behavior.',
|
|
)
|
|
|
|
|
|
def AddResponsePolicyRulesBehaviorFlagArgs(parser, messages):
|
|
GetResponsePolicyRulesBehaviorFlagMapper(messages).choice_arg.AddToParser(
|
|
parser
|
|
)
|
|
|
|
|
|
def GetLocalDataResourceRecordSets():
|
|
return base.Argument(
|
|
'--local-data',
|
|
type=arg_parsers.ArgDict(
|
|
spec={'name': str, 'type': str, 'ttl': int, 'rrdatas': str}
|
|
),
|
|
metavar='LOCAL_DATA',
|
|
action='append',
|
|
help="""\
|
|
All resource record sets for this selector, one per resource record
|
|
type. The name must match the dns_name.
|
|
|
|
This is a repeated argument that can be specified multiple times to specify
|
|
multiple local data rrsets.
|
|
(e.g. --local-data=name="zone.com.",type="A",ttl=21600,rrdata="1.2.3.4 "
|
|
--local-data=name="www.zone.com.",type="CNAME",ttl=21600,rrdata="1.2.3.4|5.6.7.8")
|
|
|
|
*name*::: The DnsName of a resource record set.
|
|
|
|
*type*::: Type of all resource records in this set. For example, A, AAAA, SOA, MX,
|
|
NS, TXT ...
|
|
|
|
*ttl*::: Number of seconds that this ResourceRecordSet can be cached by resolvers.
|
|
|
|
*rrdatas*::: The list of datas for this record, split by "|".
|
|
""",
|
|
)
|
|
|
|
|
|
def GetResponsePolicyRuleBehavior():
|
|
return base.Argument('--behavior', type=enumerate)
|
|
|
|
|
|
def GetManagedZoneLoggingArg():
|
|
return base.Argument(
|
|
'--log-dns-queries',
|
|
action=arg_parsers.StoreTrueFalseAction,
|
|
help='Specifies whether to enable query logging. Defaults to False.',
|
|
)
|
|
|
|
|
|
def GetResponsePolicyNameArg(positional=True, required=True):
|
|
if positional:
|
|
return base.Argument(
|
|
'response_policy',
|
|
type=str,
|
|
metavar='RESPONSE_POLICY_NAME',
|
|
help='Name of the response policy.',
|
|
)
|
|
else:
|
|
return base.Argument(
|
|
'--response_policy',
|
|
type=str,
|
|
required=required,
|
|
metavar='RESPONSE_POLICY_NAME',
|
|
help='Name of the response policy.',
|
|
)
|
|
|
|
|
|
def GetResponsePoliciesNameArg(positional=True, required=True):
|
|
if positional:
|
|
return base.Argument(
|
|
'response_policies',
|
|
type=str,
|
|
metavar='RESPONSE_POLICY_NAME',
|
|
help='Name of the response policy.',
|
|
)
|
|
else:
|
|
return base.Argument(
|
|
'--response_policies',
|
|
type=str,
|
|
required=required,
|
|
metavar='RESPONSE_POLICY_NAME',
|
|
help='Name of the response policy.',
|
|
)
|
|
|
|
|
|
def GetLocationArg():
|
|
return base.Argument(
|
|
'--location',
|
|
type=str,
|
|
help=(
|
|
'Specifies the desired service location the request is sent to.'
|
|
' Defaults to Cloud DNS global service. Use --location=global if you'
|
|
' want to target the global service.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetHealthCheckArg(required=False):
|
|
return base.Argument(
|
|
'--health-check',
|
|
type=str,
|
|
required=required,
|
|
help=(
|
|
'Specifies the health check to be used for public IP health checking.'
|
|
' Either the health check name or full resource path should be'
|
|
' provided.'
|
|
),
|
|
)
|
|
|
|
|
|
def GetRoutingPolicyItemArg(required: bool = False) -> base.Argument:
|
|
return base.Argument(
|
|
'--routing-policy-item',
|
|
type=arg_parsers.ArgDict(
|
|
spec={
|
|
'weight': float,
|
|
'location': str,
|
|
'rrdatas': str,
|
|
'external_endpoints': str,
|
|
'internal_load_balancers': str,
|
|
}
|
|
),
|
|
required=required,
|
|
metavar='ROUTING_POLICY_ITEM',
|
|
action='append',
|
|
help="""\
|
|
Specify this argument multiple times for a weighted round robin (WRR)
|
|
or geolocation routing policy. Use this repeated argument for only one
|
|
routing policy type (WRR or geolocation), not both. Similarly, use it
|
|
only for health checking either internal load balancers or external IP
|
|
addresses, not both.
|
|
|
|
(e.g. --routing-policy-item=weight=1,rrdatas=1.2.3.4;2.3.4.5,external_endpoints=3.4.5.6;4.5.6.7
|
|
--routing-policy-item=weight=1,rrdatas=10.0.0.1;10.0.0.2,external_endpoints=10.0.0.4)
|
|
|
|
*weight*::: The weight of the item. This is specified only for WRR routing policy items.
|
|
|
|
*location*::: The location corresponding to the item. This is specified only for GEO routing policy items.
|
|
|
|
*rrdatas*::: The list of rrdatas, split by ";".
|
|
|
|
*external_endpoints*::: The list of health checked ips, split by ";".
|
|
|
|
*internal_load_balancers*::: The list of health checked internal load balancers, split by ";".
|
|
""",
|
|
)
|
|
|
|
|
|
def GetRoutingPolicyBackupItemArg(required: bool = False) -> base.Argument:
|
|
return base.Argument(
|
|
'--routing-policy-backup-item',
|
|
type=arg_parsers.ArgDict(
|
|
spec={
|
|
'location': str,
|
|
'rrdatas': str,
|
|
'external_endpoints': str,
|
|
'internal_load_balancers': str,
|
|
}
|
|
),
|
|
required=required,
|
|
metavar='ROUTING_POLICY_BACKUP_ITEM',
|
|
action='append',
|
|
help="""\
|
|
Specify this argument multiple times to define multiple items
|
|
for a primary backup routing policy.
|
|
|
|
(e.g. --routing-policy-backup-item=location=us-east1-a,rrdatas=1.2.3.4;2.3.4.5,external_endpoints=3.4.5.6;4.5.6.7
|
|
--routing-policy-backup-item=location=us-east1-b,rrdatas=10.0.0.1;10.0.0.2,external_endpoints=10.0.0.4)
|
|
|
|
*location*::: The location corresponding to the item.
|
|
|
|
*rrdatas*::: The list of rrdatas, split by ";".
|
|
|
|
*external_endpoints*::: The list of health checked ips, split by ";".
|
|
|
|
*internal_load_balancers*::: The list of health checked internal load balancers, split by ";".
|
|
""",
|
|
)
|