353 lines
13 KiB
Python
353 lines
13 KiB
Python
# -*- 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.
|
|
"""Command for creating routes."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import unicode_literals
|
|
|
|
import ipaddress
|
|
|
|
from googlecloudsdk.api_lib.compute import base_classes
|
|
from googlecloudsdk.calliope import actions
|
|
from googlecloudsdk.calliope import arg_parsers
|
|
from googlecloudsdk.calliope import base
|
|
from googlecloudsdk.calliope import exceptions
|
|
from googlecloudsdk.command_lib.compute import completers
|
|
from googlecloudsdk.command_lib.compute import exceptions as compute_exceptions
|
|
from googlecloudsdk.command_lib.compute import flags as compute_flags
|
|
from googlecloudsdk.command_lib.compute import resource_manager_tags_utils
|
|
from googlecloudsdk.command_lib.compute.forwarding_rules import flags as ilb_flags
|
|
from googlecloudsdk.command_lib.compute.instances import flags as instance_flags
|
|
from googlecloudsdk.command_lib.compute.networks import flags as network_flags
|
|
from googlecloudsdk.command_lib.compute.routes import flags
|
|
from googlecloudsdk.command_lib.compute.vpn_tunnels import flags as vpn_flags
|
|
from googlecloudsdk.core import properties
|
|
import six
|
|
|
|
|
|
def _AddGaHops(next_hop_group):
|
|
"""Attach arguments for GA next-hops to the a parser group."""
|
|
|
|
next_hop_group.add_argument(
|
|
'--next-hop-instance',
|
|
help="""\
|
|
Specifies the name of an instance that should handle traffic
|
|
matching this route. When this flag is specified, the zone of
|
|
the instance must be specified using
|
|
``--next-hop-instance-zone''.
|
|
""")
|
|
|
|
next_hop_group.add_argument(
|
|
'--next-hop-address',
|
|
help="""\
|
|
Specifies the IP address of an instance that should handle
|
|
matching packets. The instance must have IP forwarding enabled
|
|
(i.e., include ``--can-ip-forward'' when creating the instance
|
|
using `gcloud compute instances create`)
|
|
""")
|
|
|
|
flags.NEXT_HOP_GATEWAY_ARG.AddArgument(next_hop_group)
|
|
|
|
next_hop_group.add_argument(
|
|
'--next-hop-vpn-tunnel',
|
|
help=('The target VPN tunnel that will receive forwarded traffic.'))
|
|
|
|
|
|
def _Args(parser):
|
|
"""Add arguments for route creation."""
|
|
|
|
parser.add_argument(
|
|
'--description', help='An optional, textual description for the route.')
|
|
|
|
parser.add_argument(
|
|
'--network',
|
|
default='default',
|
|
help='Specifies the network to which the route will be applied.')
|
|
|
|
parser.add_argument(
|
|
'--tags',
|
|
type=arg_parsers.ArgList(min_length=1),
|
|
default=[],
|
|
metavar='TAG',
|
|
help="""\
|
|
Identifies the set of instances that this route will apply to. If no
|
|
tags are provided, the route will apply to all instances in the network.
|
|
""")
|
|
|
|
parser.add_argument(
|
|
'--destination-range',
|
|
required=True,
|
|
help="""\
|
|
The destination range of outgoing packets that the route will
|
|
apply to. To match all traffic, use ``0.0.0.0/0''.
|
|
""")
|
|
|
|
parser.add_argument(
|
|
'--priority',
|
|
default=1000,
|
|
type=int,
|
|
help="""\
|
|
Specifies the priority of this route relative to other routes
|
|
with the same specificity. The lower the value, the higher the
|
|
priority.
|
|
""")
|
|
|
|
next_hop = parser.add_mutually_exclusive_group(required=True)
|
|
|
|
_AddGaHops(next_hop)
|
|
|
|
parser.add_argument(
|
|
'--next-hop-instance-zone',
|
|
action=actions.StoreProperty(properties.VALUES.compute.zone),
|
|
help=('The zone of the next hop instance. ' +
|
|
instance_flags.ZONE_PROPERTY_EXPLANATION))
|
|
|
|
parser.add_argument(
|
|
'--next-hop-vpn-tunnel-region',
|
|
help=('The region of the next hop vpn tunnel. ' +
|
|
compute_flags.REGION_PROPERTY_EXPLANATION))
|
|
|
|
next_hop.add_argument(
|
|
'--next-hop-ilb',
|
|
help="""\
|
|
Specifies the name or IP address of a forwarding rule for an internal TCP/UDP
|
|
load balancer. The forwarding rule's `--load-balancing-scheme` must be
|
|
`INTERNAL`. You can use any `--destination-range` that doesn't exactly
|
|
match the destination of a subnet route and isn't more specific (has a
|
|
longer subnet mask) than the destination of a subnet route. For
|
|
more information, see
|
|
https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview#destination_range.
|
|
""")
|
|
parser.add_argument(
|
|
'--next-hop-ilb-region',
|
|
help=('The region of the next hop forwarding rule. ' +
|
|
compute_flags.REGION_PROPERTY_EXPLANATION))
|
|
|
|
parser.add_argument(
|
|
'--resource-manager-tags',
|
|
type=arg_parsers.ArgDict(),
|
|
metavar='KEY=VALUE',
|
|
help="""\
|
|
A comma-separated list of Resource Manager tags to apply to the route.
|
|
""",
|
|
)
|
|
|
|
parser.display_info.AddCacheUpdater(completers.RoutesCompleter)
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.GA)
|
|
@base.UniverseCompatible
|
|
class Create(base.CreateCommand):
|
|
r"""Create a new route.
|
|
|
|
*{command}* is used to create routes. A route is a rule that
|
|
specifies how certain packets should be handled by the virtual
|
|
network. Routes are associated with virtual machine instances
|
|
by tag, and the set of routes for a particular VM is called
|
|
its routing table. For each packet leaving a virtual machine,
|
|
the system searches that machine's routing table for a single
|
|
best matching route.
|
|
|
|
Routes match packets by destination IP address, preferring
|
|
smaller or more specific ranges over larger ones (see
|
|
`--destination-range`). If there is a tie, the system selects
|
|
the route with the smallest priority value. The packet
|
|
is then forwarded as specified by `--next-hop-address`,
|
|
`--next-hop-instance`, `--next-hop-vpn-tunnel`, or
|
|
`--next-hop-gateway` of the winning route. Packets that do
|
|
not match any route in the sending virtual machine routing
|
|
table will be dropped.
|
|
|
|
Exactly one of `--next-hop-address`, `--next-hop-gateway`,
|
|
`--next-hop-vpn-tunnel`, or `--next-hop-instance` must be
|
|
provided with this command.
|
|
|
|
## EXAMPLES
|
|
|
|
To create a route with the name 'route-name' with destination range
|
|
'0.0.0.0/0' and with next hop gateway 'default-internet-gateway', run:
|
|
|
|
$ {command} route-name \
|
|
--destination-range=0.0.0.0/0 \
|
|
--next-hop-gateway=default-internet-gateway
|
|
|
|
"""
|
|
|
|
NETWORK_ARG = None
|
|
INSTANCE_ARG = None
|
|
VPN_TUNNEL_ARG = None
|
|
ILB_ARG = None
|
|
ROUTE_ARG = None
|
|
|
|
@classmethod
|
|
def Args(cls, parser):
|
|
parser.display_info.AddFormat(flags.DEFAULT_LIST_FORMAT)
|
|
cls.NETWORK_ARG = network_flags.NetworkArgumentForOtherResource(
|
|
'Specifies the network to which the route will be applied.',
|
|
required=False)
|
|
cls.INSTANCE_ARG = instance_flags.InstanceArgumentForRoute(required=False)
|
|
cls.VPN_TUNNEL_ARG = vpn_flags.VpnTunnelArgumentForRoute(required=False)
|
|
cls.ILB_ARG = ilb_flags.ForwardingRuleArgumentForRoute(required=False)
|
|
cls.ROUTE_ARG = flags.RouteArgument()
|
|
cls.ROUTE_ARG.AddArgument(parser, operation_type='create')
|
|
_Args(parser)
|
|
|
|
def Run(self, args):
|
|
"""Issue API requests for route creation, callable from multiple tracks."""
|
|
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
|
|
client = holder.client
|
|
|
|
network_uri = self.NETWORK_ARG.ResolveAsResource(
|
|
args, holder.resources).SelfLink()
|
|
|
|
route_ref = self.ROUTE_ARG.ResolveAsResource(args, holder.resources)
|
|
|
|
if args.next_hop_instance:
|
|
next_hop_instance_uri = self.INSTANCE_ARG.ResolveAsResource(
|
|
args,
|
|
holder.resources,
|
|
scope_lister=instance_flags.GetInstanceZoneScopeLister(
|
|
client)).SelfLink()
|
|
else:
|
|
if args.next_hop_instance_zone:
|
|
raise compute_exceptions.ArgumentError(
|
|
'[--next-hop-instance-zone] can only be specified in conjunction '
|
|
'with [--next-hop-instance].')
|
|
next_hop_instance_uri = None
|
|
|
|
if args.next_hop_gateway:
|
|
next_hop_gateway_ref = flags.NEXT_HOP_GATEWAY_ARG.ResolveAsResource(
|
|
args, holder.resources)
|
|
next_hop_gateway_uri = next_hop_gateway_ref.SelfLink()
|
|
else:
|
|
next_hop_gateway_uri = None
|
|
|
|
next_hop_vpn_tunnel_uri = None
|
|
|
|
if args.next_hop_vpn_tunnel:
|
|
next_hop_vpn_tunnel_uri = self.VPN_TUNNEL_ARG.ResolveAsResource(
|
|
args,
|
|
holder.resources,
|
|
scope_lister=compute_flags.GetDefaultScopeLister(client)).SelfLink()
|
|
elif args.next_hop_vpn_tunnel_region:
|
|
raise compute_exceptions.ArgumentError(
|
|
'[--next-hop-vpn-tunnel-region] can only be specified in '
|
|
'conjunction with [--next-hop-vpn-tunnel].')
|
|
|
|
next_hop_ilb_uri = None
|
|
|
|
if args.next_hop_ilb:
|
|
try:
|
|
ipaddress.ip_address(args.next_hop_ilb)
|
|
if args.next_hop_ilb_region:
|
|
raise exceptions.InvalidArgumentException(
|
|
'--next-hop-ilb-region', 'This should not be specified if '
|
|
'an IP address is used for [--next-hop-ilb].')
|
|
next_hop_ilb_uri = args.next_hop_ilb
|
|
except ValueError:
|
|
next_hop_ilb_uri = self.ILB_ARG.ResolveAsResource(
|
|
args,
|
|
holder.resources,
|
|
scope_lister=compute_flags.GetDefaultScopeLister(
|
|
client)).SelfLink()
|
|
elif args.next_hop_ilb_region:
|
|
raise exceptions.InvalidArgumentException(
|
|
'--next-hop-ilb-region', 'This can only be specified in '
|
|
'conjunction with [--next-hop-ilb].')
|
|
|
|
request = client.messages.ComputeRoutesInsertRequest(
|
|
project=route_ref.project,
|
|
route=client.messages.Route(
|
|
description=args.description,
|
|
destRange=args.destination_range,
|
|
name=route_ref.Name(),
|
|
network=network_uri,
|
|
nextHopInstance=next_hop_instance_uri,
|
|
nextHopIp=args.next_hop_address,
|
|
nextHopGateway=next_hop_gateway_uri,
|
|
nextHopVpnTunnel=next_hop_vpn_tunnel_uri,
|
|
priority=args.priority,
|
|
tags=args.tags,
|
|
),
|
|
)
|
|
request.route.nextHopIlb = next_hop_ilb_uri
|
|
|
|
if args.resource_manager_tags is not None:
|
|
request.route.params = _CreateRouteParams(
|
|
client.messages, args.resource_manager_tags
|
|
)
|
|
|
|
return client.MakeRequests(
|
|
[(client.apitools_client.routes, 'Insert', request)]
|
|
)
|
|
|
|
|
|
def _CreateRouteParams(messages, resource_manager_tags):
|
|
resource_manager_tags_map = (
|
|
resource_manager_tags_utils.GetResourceManagerTags(resource_manager_tags)
|
|
)
|
|
params = messages.RouteParams
|
|
additional_properties = [
|
|
params.ResourceManagerTagsValue.AdditionalProperty(key=key, value=value)
|
|
for key, value in sorted(six.iteritems(resource_manager_tags_map))
|
|
]
|
|
return params(
|
|
resourceManagerTags=params.ResourceManagerTagsValue(
|
|
additionalProperties=additional_properties
|
|
)
|
|
)
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA)
|
|
@base.UniverseCompatible
|
|
class CreateAlphaBeta(Create):
|
|
r"""Create a new route.
|
|
|
|
*{command}* is used to create routes. A route is a rule that
|
|
specifies how certain packets should be handled by the virtual
|
|
network. Routes are associated with virtual machine instances
|
|
by tag, and the set of routes for a particular VM is called
|
|
its routing table. For each packet leaving a virtual machine,
|
|
the system searches that machine's routing table for a single
|
|
best matching route.
|
|
|
|
Routes match packets by destination IP address, preferring
|
|
smaller or more specific ranges over larger ones (see
|
|
``--destination-range''). If there is a tie, the system selects
|
|
the route with the smallest priority value. If there is still
|
|
a tie, it uses the layer 3 and 4 packet headers to
|
|
select just one of the remaining matching routes. The packet
|
|
is then forwarded as specified by ``--next-hop-address'',
|
|
``--next-hop-instance'', ``--next-hop-vpn-tunnel'', ``--next-hop-gateway'',
|
|
or ``--next-hop-ilb'' of the winning route. Packets that do
|
|
not match any route in the sending virtual machine routing
|
|
table will be dropped.
|
|
|
|
Exactly one of ``--next-hop-address'', ``--next-hop-gateway'',
|
|
``--next-hop-vpn-tunnel'', ``--next-hop-instance'', or ``--next-hop-ilb''
|
|
must be provided with this command.
|
|
|
|
## EXAMPLES
|
|
|
|
To create a route with the name 'route-name' with destination range
|
|
'0.0.0.0/0' and with next hop gateway 'default-internet-gateway', run:
|
|
|
|
$ {command} route-name \
|
|
--destination-range=0.0.0.0/0 \
|
|
--next-hop-gateway=default-internet-gateway
|
|
|
|
"""
|