174 lines
6.0 KiB
Python
174 lines
6.0 KiB
Python
# -*- coding: utf-8 -*- #
|
|
# Copyright 2022 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.
|
|
"""Bare Metal Solution network update command."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import unicode_literals
|
|
|
|
from googlecloudsdk.api_lib.bms.bms_client import BmsClient
|
|
from googlecloudsdk.api_lib.bms.bms_client import IpRangeReservation
|
|
from googlecloudsdk.api_lib.util import waiter
|
|
from googlecloudsdk.calliope import base
|
|
from googlecloudsdk.command_lib.bms import exceptions
|
|
from googlecloudsdk.command_lib.bms import flags
|
|
from googlecloudsdk.command_lib.util.args import labels_util
|
|
from googlecloudsdk.core import log
|
|
from googlecloudsdk.core import resources
|
|
|
|
DETAILED_HELP = {
|
|
'DESCRIPTION':
|
|
"""
|
|
Update a Bare Metal Solution network.
|
|
|
|
This call returns immediately, but the update operation may take
|
|
several minutes to complete. To check if the operation is complete,
|
|
use the `describe` command for the network.
|
|
""",
|
|
'EXAMPLES':
|
|
"""
|
|
To update an network called ``my-network'' in region ``us-central1'' with
|
|
a new label ``key1=value1'', run:
|
|
|
|
$ {command} my-network --region=us-central1 --update-labels=key1=value1
|
|
|
|
To clear all labels, run:
|
|
|
|
$ {command} my-network --region=us-central1 --clear-labels
|
|
""",
|
|
}
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.GA)
|
|
class Update(base.UpdateCommand):
|
|
"""Update a Bare Metal Solution network."""
|
|
|
|
@staticmethod
|
|
def Args(parser):
|
|
"""Register flags for this command."""
|
|
flags.AddNetworkArgToParser(parser, positional=True)
|
|
labels_util.AddUpdateLabelsFlags(parser)
|
|
base.ASYNC_FLAG.AddToParser(parser)
|
|
flags.AddNetworkIpReservationToParser(parser, hidden=False)
|
|
|
|
def Run(self, args):
|
|
client = BmsClient()
|
|
network = args.CONCEPTS.network.Parse()
|
|
labels_update = None
|
|
labels_diff = labels_util.Diff.FromUpdateArgs(args)
|
|
|
|
orig_resource = client.GetNetwork(network)
|
|
labels_update = labels_diff.Apply(
|
|
client.messages.Network.LabelsValue,
|
|
orig_resource.labels).GetOrNone()
|
|
ip_reservations = _ApplyIpReservationsUpdates(args, orig_resource)
|
|
|
|
op_ref = client.UpdateNetwork(
|
|
network_resource=network, labels=labels_update,
|
|
ip_reservations=ip_reservations)
|
|
|
|
if op_ref.done:
|
|
log.UpdatedResource(network.Name(), kind='network')
|
|
return op_ref
|
|
|
|
if args.async_:
|
|
log.status.Print('Update request issued for: [{}]\nCheck operation '
|
|
'[{}] for status.'.format(network.Name(), op_ref.name))
|
|
return op_ref
|
|
|
|
op_resource = resources.REGISTRY.ParseRelativeName(
|
|
op_ref.name,
|
|
collection='baremetalsolution.projects.locations.operations',
|
|
api_version='v2')
|
|
poller = waiter.CloudOperationPollerNoResources(
|
|
client.operation_service)
|
|
res = waiter.WaitFor(poller, op_resource,
|
|
'Waiting for operation [{}] to complete'.format(
|
|
op_ref.name))
|
|
log.UpdatedResource(network.Name(), kind='network')
|
|
return res
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
|
|
class UpdateAlpha(Update):
|
|
"""Update a Bare Metal Solution network."""
|
|
|
|
@staticmethod
|
|
def Args(parser):
|
|
# Flags which are only available in ALPHA should be added to parser here.
|
|
Update.Args(parser)
|
|
|
|
|
|
def _ApplyIpReservationsUpdates(args, existing_network):
|
|
"""Applies the changes in args to the reservations in existing_network.
|
|
|
|
Returns None if no changes were to be applied.
|
|
|
|
Args:
|
|
args: The arguments passed to the command.
|
|
existing_network: The existing network.
|
|
|
|
Returns:
|
|
List of IP range reservations after applying updates or None if there are
|
|
no changes.
|
|
"""
|
|
|
|
if _IsSpecified(args, 'clear_ip_range_reservations'):
|
|
return []
|
|
|
|
existing_reservations = [
|
|
IpRangeReservation(res.startAddress, res.endAddress, res.note)
|
|
for res in existing_network.reservations
|
|
]
|
|
|
|
if _IsSpecified(args, 'add_ip_range_reservation'):
|
|
res_dict = args.add_ip_range_reservation
|
|
_ValidateAgainstSpec(res_dict, flags.IP_RESERVATION_SPEC,
|
|
'add-ip-range-reservation')
|
|
return existing_reservations + [
|
|
IpRangeReservation(res_dict['start-address'], res_dict['end-address'],
|
|
res_dict['note'])
|
|
]
|
|
|
|
if _IsSpecified(args, 'remove_ip_range_reservation'):
|
|
return _RemoveReservation(existing_reservations,
|
|
args.remove_ip_range_reservation)
|
|
|
|
|
|
def _RemoveReservation(reservations, remove_key_dict):
|
|
_ValidateAgainstSpec(remove_key_dict, flags.IP_RESERVATION_KEY_SPEC,
|
|
'remove-ip-range-reservation')
|
|
start_address = remove_key_dict['start-address']
|
|
end_address = remove_key_dict['end-address']
|
|
for i, res in enumerate(reservations):
|
|
if res.start_address == start_address and res.end_address == end_address:
|
|
return reservations[:i] + reservations[i + 1:]
|
|
raise LookupError('Cannot find an IP range reservation with start-address'
|
|
' [{}] and end-address [{}]'.format(start_address,
|
|
end_address))
|
|
|
|
|
|
def _ValidateAgainstSpec(dict_to_validate, spec, flag_name):
|
|
for prop in spec.keys():
|
|
if prop not in dict_to_validate:
|
|
raise exceptions.MissingPropertyError(flag_name, prop)
|
|
|
|
|
|
def _IsSpecified(args, name):
|
|
"""Returns true if an arg is defined and specified, false otherwise."""
|
|
return args.IsKnownAndSpecified(name)
|
|
|
|
Update.detailed_help = DETAILED_HELP
|