feat: Add new gcloud commands, API clients, and third-party libraries across various services.

This commit is contained in:
2026-01-01 20:26:35 +01:00
parent 5e23cbece0
commit a19e592eb7
25221 changed files with 8324611 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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.
"""A helper library for the Cloud Filestore command group."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 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.
"""A helper library for the Cloud Filestore command group."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 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 utility functions for Cloud Filestore update backup commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import encoding
from googlecloudsdk.api_lib.filestore import filestore_client
from googlecloudsdk.command_lib.filestore import update_util
from googlecloudsdk.command_lib.filestore import util
from googlecloudsdk.core import properties
from googlecloudsdk.core import resources
def UpdateLabels(unused_ref, args, req):
"""Update backup labels."""
new_labels = update_util.GetUpdatedLabels(args, req,
update_util.backup_feature_name)
if new_labels:
req.backup.labels = new_labels
return req
def AddDescription(unused_instance_ref, args, patch_request):
return update_util.AddDescription(unused_instance_ref, args, patch_request,
update_util.backup_feature_name)
def GetResourceRef(args):
project = properties.VALUES.core.project.Get(required=True)
location = args.region
ref = resources.REGISTRY.Create(
'file.projects.locations.backups',
projectsId=project,
locationsId=location,
backupsId=args.backup)
return ref
def GetExistingBackup(unused_resource_ref, args, patch_request):
"""Fetch existing Filestore instance to update and add it to Patch request."""
resource_ref = GetResourceRef(args)
api_version = util.GetApiVersionFromArgs(args)
client = filestore_client.FilestoreClient(api_version)
orig_backup = client.GetBackup(resource_ref)
patch_request.backup = orig_backup
return patch_request
def FormatBackupUpdateResponse(response, args):
"""Python hook to generate the backup update response."""
del response
# Return backup describe output.
resource_ref = GetResourceRef(args)
api_version = util.GetApiVersionFromArgs(args)
client = filestore_client.FilestoreClient(api_version)
return encoding.MessageToDict(client.GetBackup(resource_ref))

View File

@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*- #
# Copyright 2019 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 utility functions for Cloud Filestore backup commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.command_lib.filestore import util
from googlecloudsdk.core import properties
INSTANCE_NAME_TEMPLATE = 'projects/{}/locations/{}/instances/{}'
BACKUP_NAME_TEMPLATE = 'projects/{}/locations/{}/backups/{}'
PARENT_TEMPLATE = 'projects/{}/locations/{}'
V1_API_VERSION = 'v1'
ALPHA_API_VERSION = 'v1p1alpha1'
def FormatBackupCreateRequest(ref, args, req):
"""Python hook for yaml commands to supply the backup create request with proper values."""
del ref
req.backupId = args.backup
project = properties.VALUES.core.project.Get(required=True)
location = args.region
req.parent = PARENT_TEMPLATE.format(project, location)
return req
def FormatBackupAccessRequest(ref, args, req):
"""Python hook for yaml commands to supply backup access requests with the proper name."""
del ref
project = properties.VALUES.core.project.Get(required=True)
location = args.region
req.name = BACKUP_NAME_TEMPLATE.format(project, location, args.backup)
return req
def AddInstanceNameToRequest(ref, args, req):
"""Python hook for yaml commands to process the source instance name."""
del ref
project = properties.VALUES.core.project.Get(required=True)
api_version = util.GetApiVersionFromArgs(args)
if api_version == ALPHA_API_VERSION:
req.backup.sourceInstance = INSTANCE_NAME_TEMPLATE.format(
project, args.instance_zone, args.instance)
return req
if args.instance_zone is not None:
req.backup.sourceInstance = INSTANCE_NAME_TEMPLATE.format(
project, args.instance_zone, args.instance)
if args.instance_location is not None:
req.backup.sourceInstance = INSTANCE_NAME_TEMPLATE.format(
project, args.instance_location, args.instance)
return req
def AddBackupNameToRequest(ref, args, req):
"""Python hook for yaml commands to process the source backup name."""
del ref # Not used to infer location for backups.
if args.source_backup is None or args.source_backup_region is None:
return req
project = properties.VALUES.core.project.Get(required=True)
req.restoreInstanceRequest.sourceBackup = BACKUP_NAME_TEMPLATE.format(
project, args.source_backup_region, args.source_backup)
return req

View File

@@ -0,0 +1,125 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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 general Cloud Filestore commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope.concepts import concepts
from googlecloudsdk.calliope.concepts import deps
from googlecloudsdk.command_lib.util.concepts import presentation_specs
from googlecloudsdk.core import properties
LIST_HELP = ('Instances in all locations will be listed if this argument is '
'not specified.')
def GetZoneAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
# TODO(b/180447280): Switch to use location as the default argument here.
'zone',
'The zone of the {resource}.',
fallthroughs=[
deps.ArgFallthrough('region'),
deps.ArgFallthrough('location'),
deps.PropertyFallthrough(properties.VALUES.filestore.zone),
deps.PropertyFallthrough(properties.VALUES.filestore.region),
deps.PropertyFallthrough(properties.VALUES.filestore.location),
])
def GetInstanceAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'instance',
'The instance of the {resource}.')
def GetOperationAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'operation',
'The Cloud Filestore operation.')
def GetLocationResourceSpec():
location_attribute_config = GetZoneAttributeConfig()
location_attribute_config.fallthroughs = []
return concepts.ResourceSpec(
'file.projects.locations',
'zone',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=location_attribute_config)
def GetListingLocationResourceSpec():
location_attribute_config = GetZoneAttributeConfig()
location_attribute_config.fallthroughs.insert(
0,
deps.Fallthrough(lambda: '-', hint='uses all locations by default.'))
return concepts.ResourceSpec(
'file.projects.locations',
'zone',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=location_attribute_config)
def GetInstanceResourceSpec():
return concepts.ResourceSpec(
'file.projects.locations.instances',
'instance',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetZoneAttributeConfig(),
instancesId=GetInstanceAttributeConfig())
def GetOperationResourceSpec():
return concepts.ResourceSpec(
'file.projects.locations.operations',
'operation',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetZoneAttributeConfig(),
operationsId=GetOperationAttributeConfig())
def GetLocationPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'zone',
GetLocationResourceSpec(),
group_help,
required=True)
def GetListingLocationPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'--zone',
GetListingLocationResourceSpec(),
group_help)
def GetInstancePresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'instance',
GetInstanceResourceSpec(),
group_help,
required=True)
def GetOperationPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'operation',
GetOperationResourceSpec(),
group_help,
required=True)

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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.

View File

@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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.
"""Module for deletion protection related utility functions."""
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import parser_errors
_DELETION_PROTECTION_GROUP_HELP = """\
Deletion protection control options. When deletion protection is enabled,
the instance cannot be deleted."""
_DELETION_PROTECTION_HELP = 'Enables deletion protection for the instance.'
_DELETION_PROTECTION_REASON_HELP = """\
The reason for enabling deletion protection for the instance."""
def AddDeletionProtectionCreateArgs(parser):
"""Adds deletion protection related create flags to the parser."""
group = parser.add_group(
help=_DELETION_PROTECTION_GROUP_HELP,
required=False)
group.add_argument(
'--deletion-protection',
action='store_true',
default=None,
required=True,
help=_DELETION_PROTECTION_HELP)
group.add_argument(
'--deletion-protection-reason',
required=False,
help=_DELETION_PROTECTION_REASON_HELP)
def AddDeletionProtectionUpdateArgs(parser):
"""Adds deletion protection related update flags to the parser."""
group = parser.add_group(
help=_DELETION_PROTECTION_GROUP_HELP)
group.add_argument(
'--deletion-protection',
action=arg_parsers.StoreTrueFalseAction,
help=_DELETION_PROTECTION_HELP)
group.add_argument(
'--deletion-protection-reason',
help=_DELETION_PROTECTION_REASON_HELP)
def GetDeletionProtectionUpdateMask(args):
"""Returns the update mask for deletion protection.
Args:
args: The args from the command.
"""
mask = []
if (args.IsSpecified('deletion_protection')):
mask.append('deletionProtectionEnabled')
if args.IsSpecified('deletion_protection_reason'):
mask.append('deletionProtectionReason')
return mask
def ValidateDeletionProtectionUpdateArgs(args):
"""Validates the deletion protection args.
Args:
args: The args from the command.
"""
deletion_protection_enabled = args.deletion_protection
deletion_protection_reason = args.deletion_protection_reason
if (deletion_protection_enabled is not None
and not deletion_protection_enabled
and deletion_protection_reason is not None):
raise parser_errors.ArgumentException(
'--deletion-protection-reason cannot be used with '
'--no-deletion-protection')

View File

@@ -0,0 +1,892 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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 Cloud Filestore instances commands."""
from googlecloudsdk.api_lib.filestore import filestore_client
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.calliope.concepts import concepts
from googlecloudsdk.command_lib.filestore import flags
from googlecloudsdk.command_lib.filestore.instances import dp_util
from googlecloudsdk.command_lib.kms import resource_args as kms_resource_args
from googlecloudsdk.command_lib.util.apis import arg_utils
from googlecloudsdk.command_lib.util.args import labels_util
from googlecloudsdk.command_lib.util.concepts import concept_parsers
import six
INSTANCES_LIST_FORMAT_V1_ALPAH = """\
table(
name.basename():label=INSTANCE_NAME:sort=1,
name.segment(3):label=LOCATION,
tier,
fileShares[0].capacityGb:label=CAPACITY_GB,
fileShares[0].name.yesno(no="N/A"):label=FILE_SHARE_NAME,
networks[0].ipAddresses[0]:label=IP_ADDRESS,
state,
createTime.date()
)"""
INSTANCES_LIST_FORMAT_BETA = """\
table(
name.basename():label=INSTANCE_NAME:sort=1,
name.segment(3):label=LOCATION,
tier,
protocol,
capacityGb:label=CAPACITY_GB,
fileShares[0].name.yesno(no="N/A"):label=FILE_SHARE_NAME,
networks[0].ipAddresses[0]:label=IP_ADDRESS,
state,
createTime.date()
)"""
FILE_SHARE_ARG_SPEC = {
'name': str,
'capacity': arg_parsers.BinarySize(
default_unit='GB',
suggested_binary_size_scales=['GB', 'GiB', 'TB', 'TiB'],
),
'nfs-export-options': list,
}
FILE_TIER_TO_TYPE = {
'TIER_UNSPECIFIED': 'BASIC',
'STANDARD': 'BASIC',
'PREMIUM': 'BASIC',
'BASIC_HDD': 'BASIC',
'BASIC_SSD': 'BASIC',
'ENTERPRISE': 'ENTERPRISE',
'HIGH_SCALE_SSD': 'HIGH SCALE',
'ZONAL': 'ZONAL',
'REGIONAL': 'REGIONAL',
}
_LDAP_HELP_TEXT = """\
LDAP configuration for an instance. Specifies the domain name, servers,
users-ou, and groups-ou to be created by the filestore instance. users-ou
and groups-ou are optional.
domain
The desired domain name. i.e.:
'my-domain.com'
servers
The desired LDAP servers. i.e.:
'ldap.example.com', 'ldap2.example.com'
users-ou
The desired users Organizational Unit (OU).
groups-ou
The desired groups Organizational Unit (OU).
Use the following format to specify the LDAP configuration:
--ldap=^:^domain=my-domain.com:servers=ldap.example.com,ldap2.example.com:users-ou=users:groups-ou=groups
"""
_MANAGED_AD_HELP_TEXT = """\
Managed Active Directory configuration for an instance. Specifies both
the domain name and a computer name (unique to the domain) to be created
by the filestore instance.
domain
The desired domain full uri. i.e.:
projects/PROJECT/locations/global/domains/DOMAIN
computer
The desired active directory computer name to be created by
the filestore instance when connecting to the domain.
"""
def AddAsyncFlag(parser):
help_text = """Return immediately, without waiting for the operation
in progress to complete."""
concepts.ResourceParameterAttributeConfig(name='async', help_text=help_text)
base.ASYNC_FLAG.AddToParser(parser)
def AddForceArg(parser):
help_text = """Forces the deletion of an instance and its child resources,
such as snapshots."""
parser.add_argument('--force', action='store_true', help=(help_text))
def AddClearNfsExportOptionsArg(parser):
help_text = """Clears the NfsExportOptions. Must specify `--file-share`
flag if --clear-nfs-export-options is specified."""
parser.add_argument(
'--clear-nfs-export-options',
action='store_true',
required=False,
help=help_text,
)
def GetTierType(instance_tier):
tier_type = dict(FILE_TIER_TO_TYPE)
return tier_type.get(instance_tier, 'BASIC')
def AddLocationArg(parser):
parser.add_argument(
'--location',
required=False,
help='Location of the Cloud Filestore instance/operation.',
)
def AddRegionArg(parser):
parser.add_argument(
'--region', required=False, help='Region of the Cloud Filestore instance.'
)
def GetTagsArg():
"""Makes the base.Argument for --tags flag."""
help_parts = [
'List of tags KEY=VALUE pairs to bind.',
'Each item must be expressed as',
'`<tag-key-namespaced-name>=<tag-value-short-name>`.\n',
'Example: `123/environment=production,123/costCenter=marketing`\n',
]
return base.Argument(
'--tags',
metavar='KEY=VALUE',
type=arg_parsers.ArgDict(),
action=arg_parsers.UpdateAction,
help='\n'.join(help_parts),
hidden=False,
)
def GetTagsFromArgs(args, tags_message, tags_arg_name='tags'):
"""Makes the tags message object."""
tags = getattr(args, tags_arg_name)
if not tags:
return None
# Sorted for test stability
return tags_message(
additionalProperties=[
tags_message.AdditionalProperty(key=key, value=value)
for key, value in sorted(six.iteritems(tags))
]
)
def AddDescriptionArg(parser):
parser.add_argument(
'--description', help='A description of the Cloud Filestore instance.'
)
def GetAndValidateKmsKeyName(args):
"""Parse the KMS key resource arg, make sure the key format is correct."""
kms_ref = args.CONCEPTS.kms_key.Parse()
if kms_ref:
return kms_ref.RelativeName()
# If parsing fails but args were specified, raise error.
for keyword in ['kms-key', 'kms-keyring', 'kms-location', 'kms-project']:
if getattr(args, keyword.replace('-', '_'), None):
raise exceptions.InvalidArgumentException(
'--kms-project --kms-location --kms-keyring --kms-key',
'Specify fully qualified KMS key ID with --kms-key, or use '
'combination of --kms-project, --kms-location, --kms-keyring and '
'--kms-key to specify the key ID in pieces.',
)
return None # user didn't specify KMS key
def AddKmsKeyArg(parser):
permission_info = '{} must hold permission {}'.format(
"The 'Filestore Service Agent' service account",
"'Cloud KMS CryptoKey Encrypter/Decrypter'",
)
kms_resource_args.AddKmsKeyResourceArg(
parser=parser,
resource='instance',
permission_info=permission_info,
required=False,
)
def GetTierArg(messages):
"""Adds a --tier flag to the given parser.
Args:
messages: The messages module.
Returns:
the choice arg.
"""
custom_mappings = {
'STANDARD': (
'standard',
"""Standard Filestore instance, An alias for BASIC_HDD.
Use BASIC_HDD instead whenever possible.""",
),
'PREMIUM': (
'premium',
"""Premium Filestore instance, An alias for BASIC_SSD.
Use BASIC_SSD instead whenever possible.""",
),
'BASIC_HDD': ('basic-hdd', 'Performant NFS storage system using HDD.'),
'BASIC_SSD': ('basic-ssd', 'Performant NFS storage system using SSD.'),
'ENTERPRISE': (
'enterprise',
"""Enterprise instance.
Use REGIONAL instead whenever possible.""",
),
'HIGH_SCALE_SSD': (
'high-scale-ssd',
"""High Scale SSD instance, an alias for ZONAL.
Use ZONAL instead whenever possible.""",
),
'ZONAL': (
'zonal',
"""Zonal instances offer NFS storage\
system suitable for high performance computing application\
requirements. It offers fast performance that scales\
with capacity and allows you to grow and shrink\
capacity.""",
),
'REGIONAL': (
'regional',
"""Regional instances offer the features\
and availability needed for mission-critical workloads.""",
),
}
tier_arg = arg_utils.ChoiceEnumMapper(
'--tier',
messages.Instance.TierValueValuesEnum,
help_str="""The service tier for the Cloud Filestore instance.
For more details, see:
https://cloud.google.com/filestore/docs/instance-tiers """,
custom_mappings=custom_mappings,
default='BASIC_HDD',
)
return tier_arg
def GetProtocolArg(messages):
"""Creates a --protocol flag spec for the arg parser.
Args:
messages: The messages module.
Returns:
The chosen protocol arg.
"""
protocol_arg = arg_utils.ChoiceEnumMapper(
'--protocol',
messages.Instance.ProtocolValueValuesEnum,
help_str='The service protocol for the Cloud Filestore instance.',
custom_mappings={
'NFS_V3': ('nfs-v3', 'NFSv3 protocol.'),
'NFS_V4_1': ('nfs-v4-1', 'NFSv4.1 protocol.'),
},
default='NFS_V3',
)
return protocol_arg
def GetBackendTypeArg(messages):
"""Creates a --backendType flag spec for the arg parser.
Args:
messages: The messages module.
Returns:
The chosen backendType arg.
"""
backend_type_arg = (
arg_utils.ChoiceEnumMapper(
'--backend-type',
messages.Instance.BackendTypeValueValuesEnum,
help_str='The service backend type for the Cloud Filestore instance.',
custom_mappings={
'COMPUTE_BASED_BACKEND':
('compute-based-backend',
'Compute based backend.'),
'FILESTORE_BACKEND':
('filestore-backend',
'Filestore backend.'),
},
# This flag stays hidden in v1beta1 throughout its whole lifecycle.
hidden=True))
return backend_type_arg
def AddConnectManagedActiveDirectoryArg(parser):
"""Adds a --managed-ad flag to the parser.
Args:
parser: argparse parser.
"""
managed_ad_arg_spec = {
'domain': str,
'computer': str,
}
parser.add_argument(
'--managed-ad',
type=arg_parsers.ArgDict(
spec=managed_ad_arg_spec, required_keys=['domain', 'computer']
),
required=False,
help=_MANAGED_AD_HELP_TEXT,
)
def AddConnectLdapArg(parser):
"""Adds a --ldap flag to the parser.
Args:
parser: argparse parser.
"""
ldap_arg_spec = {
'domain': str,
'servers': str,
'users-ou': str,
'groups-ou': str,
}
parser.add_argument(
'--ldap',
metavar='^:^domain=DOMAIN:servers=SERVER1,SERVER2:users-ou=USERSOU:groups-ou=GROUPSOU',
type=arg_parsers.ArgDict(
spec=ldap_arg_spec,
required_keys=['domain', 'servers'],
),
required=False,
help=_LDAP_HELP_TEXT,
hidden=True,
)
def AddDisconnectLdapArg(parser):
"""Adds a --disconnect-ldap flag to the parser.
Args:
parser: argparse parser.
"""
disconnect_ldap_help = """\
Disconnect the instance from LDAP."""
parser.add_argument(
'--disconnect-ldap',
action='store_true',
required=False,
hidden=True,
help=disconnect_ldap_help,
)
def AddDirectoryServicesArg(parser, api_version):
"""Adds --managed-ad and --ldap flags to the parser.
Args:
parser: argparse parser.
api_version: filestore_client api version.
"""
# Managed AD is not supported in alpha.
if api_version == filestore_client.ALPHA_API_VERSION:
return
# Managed AD and LDAP are both supported in beta.
elif api_version == filestore_client.BETA_API_VERSION:
group = parser.add_group(
help='Directory services configuration for an instance.',
required=False,
mutex=True,
)
AddConnectManagedActiveDirectoryArg(group)
AddConnectLdapArg(group)
# LDAP is supported in GA.
else:
AddConnectLdapArg(parser)
def AddDisconnectManagedActiveDirectoryArg(parser):
"""Adds a --disconnect-managed-ad flag to the parser.
Args:
parser: argparse parser.
"""
disconnect_managed_ad_help = """\
Disconnect the instance from Managed Active Directory."""
parser.add_argument(
'--disconnect-managed-ad',
action='store_true',
required=False,
help=disconnect_managed_ad_help,
)
def AddDirectoryServicesConnectDisconnectArgs(parser, api_version):
"""Adds --managed-ad, --disconnect-managed-ad, --ldap, --disconnect-ldap flags to the parser.
Args:
parser: argparse parser.
api_version: filestore_client api version.
"""
connection_arg_group = parser.add_mutually_exclusive_group(
hidden=api_version == filestore_client.V1_API_VERSION,
)
# Managed AD is supported in beta only.
if api_version == filestore_client.BETA_API_VERSION:
AddConnectManagedActiveDirectoryArg(connection_arg_group)
AddDisconnectManagedActiveDirectoryArg(connection_arg_group)
# LDAP is supported in both beta and GA.
AddConnectLdapArg(connection_arg_group)
AddDisconnectLdapArg(connection_arg_group)
def AddSourceInstanceArg(parser):
parser.add_argument(
'--source-instance',
required=False,
help='The replication source instance of the Cloud Filestore instance.',
)
def AddNetworkArg(parser, api_version):
"""Adds a --network flag to the given parser.
Args:
parser: argparse parser.
api_version: filestore_client api version.
"""
network_arg_spec_alpha = {
'name': str,
'reserved-ip-range': str,
'connect-mode': str,
}
network_arg_spec_beta_v1 = {
'name': str,
'reserved-ip-range': str,
'connect-mode': str,
'address-mode': str,
'psc-endpoint-project': str,
}
network_arg_spec = {
filestore_client.V1_API_VERSION: network_arg_spec_beta_v1,
filestore_client.ALPHA_API_VERSION: network_arg_spec_alpha,
filestore_client.BETA_API_VERSION: network_arg_spec_beta_v1,
}
network_help_alpha = """\
Network configuration for a Cloud Filestore instance. Specifying
`reserved-ip-range` and `connect-mode` is optional.
*name*::: The name of the Google Compute Engine
[VPC network](/compute/docs/networks-and-firewalls#networks) to which
the instance is connected.
*reserved-ip-range*::: The `reserved-ip-range` can have one of the
following two types of values: a CIDR range value when using
DIRECT_PEERING connect mode or an allocated IP address range
(https://cloud.google.com/compute/docs/ip-addresses/reserve-static-internal-ip-address)
when using PRIVATE_SERVICE_ACCESS connect mode. When the name of an
allocated IP address range is specified, it must be one of the ranges
associated with the private service access connection. When specified as
a direct CIDR value, it must be a /29 CIDR block for Basic tier or a /24
CIDR block for High Scale, Zonal, Enterprise or Regional tier in one of the internal IP
address ranges (https://www.arin.net/knowledge/address_filters.html)
that identifies the range of IP addresses reserved for this instance.
For example, 10.0.0.0/29 or 192.168.0.0/24. The range you specify can't
overlap with either existing subnets or assigned IP address ranges for
other Cloud Filestore instances in the selected VPC network.
*connect-mode*::: Network connection mode used by instances.
CONNECT_MODE must be one of: DIRECT_PEERING or PRIVATE_SERVICE_ACCESS.
"""
network_help_beta_v1 = """\
Network configuration for a Cloud Filestore instance. Specifying
`reserved-ip-range`, `address-mode` and `connect-mode` is optional.
*name*::: The name of the Google Compute Engine
[VPC network](/compute/docs/networks-and-firewalls#networks) to which
the instance is connected.
*reserved-ip-range*::: The `reserved-ip-range` can have one of the
following two types of values: a CIDR range value when using
DIRECT_PEERING connect mode or an allocated IP address range
(https://cloud.google.com/compute/docs/ip-addresses/reserve-static-internal-ip-address)
when using PRIVATE_SERVICE_ACCESS connect mode. When the name of an
allocated IP address range is specified, it must be one of the ranges
associated with the private service access connection. When specified as
a direct CIDR value, it must be a /29 CIDR block for Basic tier or a /24
CIDR block for High Scale, Zonal, Enterprise or Regional tier in one of the internal IP
address ranges (https://www.arin.net/knowledge/address_filters.html)
that identifies the range of IP addresses reserved for this instance.
For example, 10.0.0.0/29 or 192.168.0.0/24. The range you specify can't
overlap with either existing subnets or assigned IP address ranges for
other Cloud Filestore instances in the selected VPC network.
*connect-mode*::: Network connection mode used by instances.
CONNECT_MODE must be one of: DIRECT_PEERING, PRIVATE_SERVICE_ACCESS or
PRIVATE_SERVICE_CONNECT.
*address-mode*::: Internet protocol version for which the instance has IP address assigned.
*psc-endpoint-project*::: Consumer service project in which the psc
endpoint would be set up. This is optional, and only relevant in case
the network is a shared VPC. If this is not specified, the psc endpoint
would be setup in the VPC host project.
"""
network_help = {
filestore_client.V1_API_VERSION: network_help_beta_v1,
filestore_client.ALPHA_API_VERSION: network_help_alpha,
filestore_client.BETA_API_VERSION: network_help_beta_v1,
}
parser.add_argument(
'--network',
type=arg_parsers.ArgDict(
spec=network_arg_spec[api_version], required_keys=['name']
),
required=True,
help=network_help[api_version],
)
def AddFileShareArg(
parser,
api_version,
include_snapshot_flags=False,
include_backup_flags=False,
include_backupdr_flags=False,
clear_nfs_export_options_required=False,
required=True,
):
"""Adds a --file-share flag to the given parser.
Args:
parser: argparse parser.
api_version: filestore_client api version.
include_snapshot_flags: bool, whether to include --source-snapshot flags.
include_backup_flags: bool, whether to include --source-backup flags.
include_backupdr_flags: bool, whether to include --source-backupdr-backup
flag.
clear_nfs_export_options_required: bool, whether to include
--clear-nfs-export-options flags.
required: bool, passthrough to parser.add_argument.
"""
alpha_beta_help_text = """
File share configuration for an instance. Specifying both `name` and `capacity`
is required.
*capacity*::: The desired capacity of the volume in GB or TB units. If no capacity
unit is specified, GB is assumed. Acceptable instance capacities for each tier are as follows:
* BASIC_HDD: 1TB-63.9TB in 1GB increments or its multiples.
* BASIC_SSD: 2.5TB-63.9TB in 1GB increments or its multiples.
* HIGH_SCALE_SSD: 10TB-100TB in 2.5TB increments or its multiples.
* ZONAL: 1TB-100TB:
- 1TB-9.75TB in 256GB increments or its multiples.
- 10TB-100TB in 2.5TB increments or its multiples.
* ENTERPRISE: 1TB-10TB in 256GB increments or its multiples.
* REGIONAL: 1TB-100TB:
- 1TB-9.75TB in 256GB increments or its multiples.
- 10TB-100TB in 2.5TB increments or its multiples.
*name*::: The desired logical name of the volume.
*nfs-export-options*::: The NfsExportOptions for the Cloud Filestore instance file share.
Configuring NfsExportOptions is optional and can only be set using flags-file. Use the `--flags-file`
flag to specify the path to a JSON or YAML configuration file that contains the required NfsExportOptions flags.
*ip-ranges*::: A list of IPv4 addresses or CIDR ranges that are allowed to mount the file share.
IPv4 addresses format: {octet 1}.{octet 2}.{octet 3}.{octet 4}.
CIDR range format: {octet 1}.{octet 2}.{octet 3}.{octet 4}/{mask size}.
Overlapping IP ranges are allowed for all tiers other than BASIC_HDD and
BASIC_SSD. The limit of IP ranges/addresses for each FileShareConfig among all
NfsExportOptions is 64 per instance.
*access-mode*::: The type of access allowed for the specified IP-addresses or CIDR ranges.
READ_ONLY: Allows only read requests on the exported file share.
READ_WRITE: Allows both read and write requests on the exported file share.
The default setting is READ_WRITE.
*squash-mode*::: Enables or disables root squash for the specified
IP addresses or CIDR ranges.
NO_ROOT_SQUASH: Disables root squash to allow root access on the exported file share.
ROOT_SQUASH. Enables root squash to remove root access on the exported file share.
The default setting is NO_ROOT_SQUASH.
*anon_uid*::: An integer that represents the user ID of anonymous users.
Anon_uid may only be set when squash_mode is set to ROOT_SQUASH.
If NO_ROOT_SQUASH is specified, an error will be returned.
The default value is 65534.
*anon_gid*::: An integer that represents the group ID of anonymous groups.
Anon_gid may only be set when squash_mode is set to ROOT_SQUASH.
If NO_ROOT_SQUASH is specified, an error will be returned.
The default value is 65534.
*security-flavors*:: A list of security flavors that are allowed to be used
during mount command in NFSv4.1 filestore instances.
The security flavors supported are:
- SECURITY_FLAVOR_UNSPECIFIED: SecurityFlavor not set. Defaults to AUTH_SYS.
- AUTH_SYS: The user's UNIX user-id and group-ids are passed in the clear.
- KRB5: The end-user authentication is done using Kerberos V5.
- KRB5I: KRB5 plus integrity protection (data packets are tamper proof).
- KRB5P: KRB5I plus privacy protection (data packets are tamper proof and
encrypted).
*network*::: The source VPC network for `ip-ranges`. Required for instances using
Private Service Connect, optional otherwise. If provided, must be the same
network specified in the `network.name` field.
"""
file_share_help = {
filestore_client.V1_API_VERSION: """\
File share configuration for an instance. Specifying both `name` and `capacity`
is required.
*capacity*::: The desired capacity of the volume in GB or TB units. If no capacity
unit is specified, GB is assumed. Acceptable instance capacities for each tier are as follows:
* BASIC_HDD: 1TB-63.9TB in 1GB increments or its multiples.
* BASIC_SSD: 2.5TB-63.9TB in 1GB increments or its multiples.
* HIGH_SCALE_SSD: 10TB-100TB in 2.5TB increments or its multiples.
* ZONAL: 1TB-100TB:
- 1TB-9.75TB in 256GB increments or its multiples.
- 10TB-100TB in 2.5TB increments or its multiples.
* ENTERPRISE: 1TB-10TB in 256GB increments or its multiples.
* REGIONAL: 1TB-100TB:
- 1TB-9.75TB in 256GB increments or its multiples.
- 10TB-100TB in 2.5TB increments or its multiples.
*name*::: The desired logical name of the volume.
*nfs-export-options*::: The NfsExportOptions for the Cloud Filestore instance file share.
Configuring NfsExportOptions is optional and can only be set using flags-file. Use the `--flags-file`
flag to specify the path to a JSON or YAML configuration file that contains the required NfsExportOptions flags.
*ip-ranges*::: A list of IPv4 addresses or CIDR ranges that are allowed to mount the file share.
IPv4 addresses format: {octet 1}.{octet 2}.{octet 3}.{octet 4}.
CIDR range format: {octet 1}.{octet 2}.{octet 3}.{octet 4}/{mask size}.
Overlapping IP ranges are allowed for all tiers other than BASIC_HDD and
BASIC_SSD. The limit of IP ranges/addresses for each FileShareConfig among all
NfsExportOptions is 64 per instance.
*access-mode*::: The type of access allowed for the specified IP-addresses or CIDR ranges.
READ_ONLY: Allows only read requests on the exported file share.
READ_WRITE: Allows both read and write requests on the exported file share.
The default setting is READ_WRITE.
*squash-mode*::: Enables or disables root squash for the specified
IP addresses or CIDR ranges.
NO_ROOT_SQUASH: Disables root squash to allow root access on the exported file share.
ROOT_SQUASH. Enables root squash to remove root access on the exported file share.
The default setting is NO_ROOT_SQUASH.
*anon_uid*::: An integer that represents the user ID of anonymous users.
Anon_uid may only be set when squash_mode is set to ROOT_SQUASH.
If NO_ROOT_SQUASH is specified, an error will be returned.
The default value is 65534.
*anon_gid*::: An integer that represents the group ID of anonymous groups.
Anon_gid may only be set when squash_mode is set to ROOT_SQUASH.
If NO_ROOT_SQUASH is specified, an error will be returned.
The default value is 65534.
""",
filestore_client.ALPHA_API_VERSION: alpha_beta_help_text,
filestore_client.BETA_API_VERSION: alpha_beta_help_text,
}
source_snapshot_help = """\
*source-snapshot*::: The name of the snapshot to restore from. Supported for BASIC instances only.
*source-snapshot-region*::: The region of the source snapshot. If
unspecified, it is assumed that the Filestore snapshot is local and
instance-zone will be used.
"""
source_backup_help = """\
*source-backup*::: The name of the backup to restore from.
*source-backup-region*::: The region of the source backup.
"""
spec = FILE_SHARE_ARG_SPEC.copy()
if include_backup_flags:
spec['source-backup'] = str
spec['source-backup-region'] = str
if include_snapshot_flags:
spec['source-snapshot'] = str
spec['source-snapshot-region'] = str
if include_backupdr_flags:
spec['source-backupdr-backup'] = str
file_share_help = file_share_help[api_version]
if clear_nfs_export_options_required:
required = True
file_share_arg_group = parser.add_argument_group(
help='Parameters for file-share.'
)
AddClearNfsExportOptionsArg(file_share_arg_group)
file_share_arg_group.add_argument(
'--file-share',
type=arg_parsers.ArgDict(spec=spec, required_keys=['name', 'capacity']),
required=required,
help=file_share_help
+ (source_snapshot_help if include_snapshot_flags else '')
+ (source_backup_help if include_backup_flags else ''),
)
else:
parser.add_argument(
'--file-share',
type=arg_parsers.ArgDict(spec=spec, required_keys=['name', 'capacity']),
required=required,
help=file_share_help
+ (source_snapshot_help if include_snapshot_flags else '')
+ (source_backup_help if include_backup_flags else ''),
)
def AddPerformanceArg(parser, hidden=False):
"""Adds a --performance flag to the given parser.
Args:
parser: argparse parser.
hidden: if hidden or not.
"""
performance_help = """\
Performance configuration for the instance. This flag is used
to configure the read IOPS provisioned for the instance. The
instance's write IOPS and read/write throughputs will be derived from the
configured read IOPS. For more information about the derived performance
limits and default performance see: https://cloud.google.com/filestore/docs/performance.
Must be one of:
max-iops
The number of IOPS to provision for the instance.
MAX-IOPS must be in multiple of 1000 and in the supported IOPS
range for the current capacity of the instance.
For more details, see: https://cloud.google.com/filestore/docs/performance.
max-iops-per-tb
Is used for setting the max IOPS of the instance by
specifying the IOPS per TB. When this parameter is used, the
max IOPS are derived from the instance capacity:
The instance max IOPS will be calculated by multiplying the
capacity of the instance (TB) by MAX-IOPS-PER-TB, and rounding
to the nearest 1000. The max IOPS will be changed
dynamically based on the instance capacity.
MAX-IOPS-PER-TB must be in the supported range of the instance.
For more details, see: https://cloud.google.com/filestore/docs/performance.
Examples:
Configure an instance with `max-iops` performance:
$ {command} example-cluster --performance=max-iops=17000
Configure an instance with `max-iops-per-tb` performance:
$ {command} example-cluster --performance=max-iops-per-tb=17000
"""
performance_arg_spec = {
'max-iops': arg_parsers.BoundedInt(1),
'max-iops-per-tb': arg_parsers.BoundedInt(1),
}
parser.add_argument(
'--performance',
type=arg_parsers.ArgDict(spec=performance_arg_spec, max_length=1),
help=performance_help,
hidden=hidden,
)
def AddInstanceCreateArgs(parser, api_version):
"""Add args for creating an instance."""
concept_parsers.ConceptParser(
[flags.GetInstancePresentationSpec('The instance to create.')]
).AddToParser(parser)
AddDescriptionArg(parser)
AddLocationArg(parser)
AddRegionArg(parser)
AddAsyncFlag(parser)
labels_util.AddCreateLabelsFlags(parser)
AddNetworkArg(parser, api_version)
messages = filestore_client.GetMessages(version=api_version)
GetTierArg(messages).choice_arg.AddToParser(parser)
if api_version in [
filestore_client.BETA_API_VERSION,
filestore_client.V1_API_VERSION,
]:
GetProtocolArg(messages).choice_arg.AddToParser(parser)
AddDirectoryServicesArg(parser, api_version)
if api_version in [
filestore_client.BETA_API_VERSION,
]:
GetBackendTypeArg(messages).choice_arg.AddToParser(parser)
AddFileShareArg(
parser,
api_version,
include_snapshot_flags=(
api_version == filestore_client.ALPHA_API_VERSION
),
include_backup_flags=True,
include_backupdr_flags=api_version != filestore_client.ALPHA_API_VERSION,
)
if api_version in [
filestore_client.BETA_API_VERSION,
filestore_client.V1_API_VERSION,
]:
AddKmsKeyArg(parser)
AddSourceInstanceArg(parser)
AddPerformanceArg(parser)
GetTagsArg().AddToParser(parser)
dp_util.AddDeletionProtectionCreateArgs(parser)
def AddInstanceUpdateArgs(parser, api_version):
"""Add args for updating an instance."""
concept_parsers.ConceptParser(
[flags.GetInstancePresentationSpec('The instance to update.')]
).AddToParser(parser)
AddDescriptionArg(parser)
AddLocationArg(parser)
AddRegionArg(parser)
AddAsyncFlag(parser)
labels_util.AddUpdateLabelsFlags(parser)
AddFileShareArg(
parser,
api_version,
include_snapshot_flags=(
api_version == filestore_client.ALPHA_API_VERSION
),
clear_nfs_export_options_required=True,
required=False,
)
if api_version in [
filestore_client.BETA_API_VERSION,
filestore_client.V1_API_VERSION,
]:
AddDirectoryServicesConnectDisconnectArgs(parser, api_version)
AddPerformanceArg(parser)
dp_util.AddDeletionProtectionUpdateArgs(parser)

View File

@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""A helper library for the Cloud Filestore instances snapshots command group."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,124 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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 utility functions for Cloud Filestore snapshot commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import encoding
from googlecloudsdk.api_lib.filestore import filestore_client
from googlecloudsdk.command_lib.filestore import update_util
from googlecloudsdk.command_lib.filestore import util
from googlecloudsdk.core import properties
PARENT_TEMPLATE = 'projects/{}/locations/{}/instances/{}'
SNAPSHOT_NAME_TEMPLATE = PARENT_TEMPLATE + '/snapshots/{}'
V1_API_VERSION = 'v1'
def FormatSnapshotCreateRequest(ref, args, req):
"""Python hook for yaml commands to supply the snapshot create request with proper values."""
del ref
req.snapshotId = args.snapshot
project = properties.VALUES.core.project.Get(required=True)
location_id = args.instance_location if args.instance_region is None else (
args.instance_region)
req.parent = PARENT_TEMPLATE.format(
project, location_id, args.instance)
return req
def FormatSnapshotAccessRequest(ref, args, req):
"""Python hook for yaml commands to supply snapshot access requests with the proper name."""
del ref
project = properties.VALUES.core.project.Get(required=True)
location_id = args.instance_location if args.instance_region is None else (
args.instance_region)
req.name = SNAPSHOT_NAME_TEMPLATE.format(
project, location_id, args.instance, args.snapshot)
return req
def FormatSnapshotsListRequest(ref, args, req):
"""Python hook for yaml commands to supply the list snapshots request with proper values."""
del ref
project = properties.VALUES.core.project.Get(required=True)
location_id = args.instance_location if args.instance_region is None else (
args.instance_region)
req.parent = PARENT_TEMPLATE.format(
project, location_id, args.instance)
return req
def UpdateLabels(ref, args, req):
"""Update snapshot labels."""
del ref
new_labels = update_util.GetUpdatedLabels(args, req,
update_util.snapshot_feature_name)
if new_labels:
req.snapshot.labels = new_labels
return req
def GetResourceRef(args):
"""Creates a Snapshot and returns its reference."""
project = properties.VALUES.core.project.Get(required=True)
api_version = util.GetApiVersionFromArgs(args)
registry = filestore_client.GetFilestoreRegistry(api_version)
location_id = args.instance_location if args.instance_region is None else (
args.instance_region)
ref = registry.Create(
'file.projects.locations.instances.snapshots',
projectsId=project,
locationsId=location_id,
instancesId=args.instance,
snapshotsId=args.snapshot)
return ref
def GetExistingSnapshot(ref, args, patch_request):
"""Fetch existing Filestore instance to update and add it to Patch request."""
del ref
resource_ref = GetResourceRef(args)
api_version = util.GetApiVersionFromArgs(args)
client = filestore_client.FilestoreClient(api_version)
orig_snapshot = client.GetInstanceSnapshot(resource_ref)
patch_request.snapshot = orig_snapshot
return patch_request
def FormatSnapshotUpdateResponse(response, args):
"""Python hook to generate the backup update response."""
del response
# Return backup describe output.
resource_ref = GetResourceRef(args)
api_version = util.GetApiVersionFromArgs(args)
client = filestore_client.FilestoreClient(api_version)
return encoding.MessageToDict(client.GetInstanceSnapshot(resource_ref))
def AddDescription(unused_instance_ref, args, patch_request):
"""Adds description to the patch request."""
return update_util.AddDescription(unused_instance_ref, args, patch_request,
update_util.snapshot_feature_name)

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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.

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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 Cloud Filestore locations commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
LOCATIONS_LIST_FORMAT = """\
table(
name.basename():label=NAME:sort=1
)"""

View File

@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*- #
# Copyright 2019 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.
"""Utilities for `gcloud filestore zones` commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
def IsZonal(location):
"""Returns True if the location string is a GCP zone."""
return len(location.split('-')) == 3
def IsRegional(location):
"""Returns True if the location string is a GCP region."""
return len(location.split('-')) == 2
def GetRegionFromZone(zone):
"""Returns the GCP region that the input zone is in."""
return '-'.join(zone.split('-')[:-1])
def ExtractRegionsFromLocationsListResponse(locations, limit):
"""Extract the regions from a list of GCP locations.
Args:
locations: a list of location objects.
limit: int, The maximum number of records to yield. None if all available
records should be yielded.
Yields:
location objects that represent a GCP region.
"""
for location in locations:
if limit is not None and limit <= 0:
return
if IsRegional(location.locationId):
yield location
if limit is not None:
limit -= 1
def ExtractZonesFromLocationsListResponse(locations, limit):
"""Extract the zones from a list of GCP locations.
Args:
locations: a list of location objects.
limit: int, The maximum number of records to yield. None if all available
records should be yielded.
Yields:
location objects that represent a GCP zone.
"""
for location in locations:
if limit is not None and limit <= 0:
return
if IsZonal(location.locationId):
yield location
if limit is not None:
limit -= 1

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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.

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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 Cloud Filestore operations commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
OPERATIONS_LIST_FORMAT = """\
table(
name.basename():label=OPERATION_NAME,
name.segment(3):label=LOCATION,
metadata.verb:label=TYPE,
metadata.target.basename(),
done.yesno(yes='DONE', no='RUNNING'):label=STATUS,
metadata.createTime.date():sort=1,
duration(start=metadata.createTime,end=metadata.endTime,precision=0,calendar=false).slice(2:).join("").yesno(no="<1S"):label=DURATION
)"""

View File

@@ -0,0 +1,87 @@
project:
name: project
collection: file.projects
attributes:
- parameter_name: projectsId
attribute_name: project
help: |
The project name.
property: core/project
zone:
name: zone
collection: file.projects.locations
attributes:
- &zone
parameter_name: locationsId
attribute_name: zone
help: |
The zone of the Filestore {resource}.
property: filestore/zone
disable_auto_completers: false
region:
name: region
collection: file.projects.locations
attributes:
- &region
parameter_name: locationsId
attribute_name: region
help: |
The region of the Filestore {resource}.
property: filestore/region
disable_auto_completers: false
location:
name: location
collection: file.projects.locations
attributes:
- &location
parameter_name: locationsId
attribute_name: location
help: |
The location of the Filestore {resource}.
property: filestore/location
disable_auto_completers: false
instance:
name: instance
collection: file.projects.locations.instances
request_id_field: instanceId
attributes:
- *zone
- parameter_name: instancesId
attribute_name: instance
help: The name of the Filestore instance.
disable_auto_completers: false
instance_with_generic_location:
name: instance
collection: file.projects.locations.instances
request_id_field: instanceId
attributes:
- *location
- parameter_name: instancesId
attribute_name: instance
help: The name of the Filestore instance.
disable_auto_completers: false
snapshot:
name: snapshot
collection: file.projects.locations.snapshots
request_id_field: snapshotId
attributes:
- parameter_name: snapshotsId
attribute_name: snapshot
help: The name of the Filestore snapshot.
disable_auto_completers: false
backup:
name: backup
collection: file.projects.locations.backups
request_id_field: backupId
attributes:
- parameter_name: backupId
attribute_name: backup
help: The name of the Filestore backup.
disable_auto_completers: false

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*- #
# Copyright 2019 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.

View File

@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*- #
# Copyright 2019 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 utility functions for Cloud Filestore update snapshot commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import encoding
from googlecloudsdk.api_lib.filestore import filestore_client
from googlecloudsdk.command_lib.filestore import update_util
from googlecloudsdk.command_lib.filestore import util
from googlecloudsdk.core import properties
from googlecloudsdk.core import resources
def UpdateLabels(unused_ref, args, req):
"""Update snapshot labels."""
new_labels = update_util.GetUpdatedLabels(args, req,
update_util.snapshot_feature_name)
if new_labels:
req.snapshot.labels = new_labels
return req
def AddDescription(unused_instance_ref, args, patch_request):
return update_util.AddDescription(unused_instance_ref, args, patch_request,
update_util.snapshot_feature_name)
def GetResourceRef(args):
project = properties.VALUES.core.project.Get(required=True)
location = args.region or args.zone
ref = resources.REGISTRY.Create(
'file.projects.locations.snapshots',
projectsId=project,
locationsId=location,
snapshotsId=args.snapshot)
return ref
def GetExistingSnapshot(unused_resource_ref, args, patch_request):
"""Fetch existing Filestore instance to update and add it to Patch request."""
resource_ref = GetResourceRef(args)
api_version = util.GetApiVersionFromArgs(args)
client = filestore_client.FilestoreClient(api_version)
orig_snapshot = client.GetSnapshot(resource_ref)
patch_request.snapshot = orig_snapshot
return patch_request
def FormatSnapshotUpdateResponse(response, args):
"""Python hook to generate the snapshot update response."""
del response
# Return snapshot describe output.
resource_ref = GetResourceRef(args)
api_version = util.GetApiVersionFromArgs(args)
client = filestore_client.FilestoreClient(api_version)
return encoding.MessageToDict(client.GetSnapshot(resource_ref))

View File

@@ -0,0 +1,65 @@
# -*- coding: utf-8 -*- #
# Copyright 2019 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 utility functions for Cloud Filestore snapshot commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.core import properties
INSTANCE_NAME_TEMPLATE = 'projects/{}/locations/{}/instances/{}'
SNAPSHOT_NAME_TEMPLATE = 'projects/{}/locations/{}/snapshots/{}'
PARENT_TEMPLATE = 'projects/{}/locations/{}'
def FormatSnapshotCreateRequest(ref, args, req):
"""Python hook for yaml commands to supply the snapshot create request with proper values."""
del ref
req.snapshotId = args.snapshot
# If this is a local snapshot, create it in args.instance_zone
project = properties.VALUES.core.project.Get(required=True)
location = args.region or args.instance_zone
req.parent = PARENT_TEMPLATE.format(project, location)
return req
def FormatSnapshotAccessRequest(ref, args, req):
"""Python hook for yaml commands to supply snapshot access requests with the proper name."""
del ref
project = properties.VALUES.core.project.Get(required=True)
location = args.region or args.zone
req.name = SNAPSHOT_NAME_TEMPLATE.format(project, location, args.snapshot)
return req
def AddInstanceNameToRequest(ref, args, req):
"""Python hook for yaml commands to process the source instance name."""
del ref
project = properties.VALUES.core.project.Get(required=True)
req.snapshot.sourceInstance = INSTANCE_NAME_TEMPLATE.format(
project, args.instance_zone, args.instance)
return req
def AddSnapshotNameToRequest(ref, args, req):
"""Python hook for yaml commands to process the source snapshot name."""
location = args.source_snapshot_region or ref.locationsId
if args.source_snapshot is None or location is None:
return req
project = properties.VALUES.core.project.Get(required=True)
req.restoreInstanceRequest.sourceSnapshot = SNAPSHOT_NAME_TEMPLATE.format(
project, location, args.source_snapshot)
return req

View File

@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 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 utility functions for Cloud Filestore update snapshot commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.filestore import filestore_client
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.filestore import util
from googlecloudsdk.command_lib.util.args import labels_util
snapshot_feature_name = 'snapshot'
backup_feature_name = 'backup'
def UpdateLabelsFlags():
remove_group = base.ArgumentGroup(mutex=True)
remove_group.AddArgument(labels_util.GetClearLabelsFlag())
remove_group.AddArgument(labels_util.GetRemoveLabelsFlag(''))
return [labels_util.GetUpdateLabelsFlag(''), remove_group]
def AddFieldToUpdateMask(field, patch_request):
update_mask = patch_request.updateMask
if update_mask:
if update_mask.count(field) == 0:
patch_request.updateMask = update_mask + ',' + field
else:
patch_request.updateMask = field
return patch_request
def GetUpdatedLabels(args, req, feature_name):
"""Return updated resource labels."""
labels_diff = labels_util.Diff.FromUpdateArgs(args)
if labels_diff.MayHaveUpdates():
req = AddFieldToUpdateMask('labels', req)
api_version = util.GetApiVersionFromArgs(args)
messages = filestore_client.GetMessages(api_version)
if feature_name == snapshot_feature_name:
return labels_diff.Apply(messages.Snapshot.LabelsValue,
req.snapshot.labels).GetOrNone()
if feature_name == backup_feature_name:
return labels_diff.Apply(messages.Backup.LabelsValue,
req.backup.labels).GetOrNone()
return None
def AddDescription(unused_instance_ref, args, patch_request, feature_name):
del unused_instance_ref
if args.IsSpecified('description'):
if feature_name == snapshot_feature_name:
patch_request.snapshot.description = args.description
if feature_name == backup_feature_name:
patch_request.backup.description = args.description
patch_request = AddFieldToUpdateMask('description', patch_request)
return patch_request

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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 utility functions for all Cloud Filestore commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import properties
V1_API_VERSION = 'v1'
ALPHA_API_VERSION = 'v1p1alpha1'
BETA_API_VERSION = 'v1beta1'
PARENT_TEMPLATE = 'projects/{}/locations/{}'
LOCATION_WILDCARD = '-'
def AddDefaultLocationToListRequest(ref, args, req):
"""Python hook for yaml commands to wildcard the region in list requests."""
del ref
project = properties.VALUES.core.project.Get(required=True)
if hasattr(args, 'zone'):
location = args.region or args.zone or LOCATION_WILDCARD
else:
location = args.region or LOCATION_WILDCARD
req.parent = PARENT_TEMPLATE.format(project, location)
return req
def GetApiVersionFromArgs(args):
"""Return API version based on args."""
release_track = args.calliope_command.ReleaseTrack()
if release_track == base.ReleaseTrack.ALPHA:
return ALPHA_API_VERSION
if release_track == base.ReleaseTrack.BETA:
return BETA_API_VERSION
if release_track == base.ReleaseTrack.GA:
return V1_API_VERSION
raise exceptions.UnsupportedReleaseTrackError(release_track)