File: //snap/google-cloud-cli/396/lib/googlecloudsdk/command_lib/netapp/flags.py
# -*- 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.
"""Flags and helpers for general Cloud NetApp Files commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
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
## Attribute configs ##
def GetLocationAttributeConfig():
"""Return the Location Attribute Config for resources.
Returns:
ResourceParameterAttributeConfig for location.
"""
fallthroughs = [
## if location is not set, use value from
## gcloud config get-value netapp/location or netapp/region
deps.ArgFallthrough('--location'),
deps.PropertyFallthrough(properties.VALUES.netapp.location),
]
return concepts.ResourceParameterAttributeConfig(
name='location',
fallthroughs=fallthroughs,
help_text='The location of the {resource}.')
def GetStoragePoolAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'storage_pool', 'The instance of the {resource}.')
def GetVolumeAttributeConfig(positional=True):
"""Return the Volume Attribute Config for resources.
Args:
positional: boolean value describing whether volume attribute is conditional
Returns:
volume resource parameter attribute config for resource specs
"""
if positional:
fallthroughs = []
else:
## For when we need a volume attribute in Snapshot resource spec, we want
## to assign fallthrough flags
fallthroughs = [deps.ArgFallthrough('--volume')]
help_text = ('The instance of the {resource}' if positional else (
'The volume of the {resource}'))
return concepts.ResourceParameterAttributeConfig(
name='volume', fallthroughs=fallthroughs, help_text=help_text)
def GetSnapshotAttributeConfig(positional=True):
if positional:
help_text = 'The instance of the {resource}'
else:
help_text = 'The snapshot of the {resource}'
return concepts.ResourceParameterAttributeConfig(
'snapshot', help_text=help_text)
def GetReplicationAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'replication', 'The instance of the {resource}')
def GetOperationAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'operation', 'The Cloud NetApp operation.')
def GetActiveDirectoryAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'active_directory', 'The instance of the {resource}.'
)
def GetBackupVaultAttributeConfig(positional=True):
fallthroughs = []
if not positional:
## For when we need a Backup Vault attribute in Backup resource spec
## we want to assign fallthrough flags
fallthroughs = [deps.ArgFallthrough('--backup-vault')]
return concepts.ResourceParameterAttributeConfig(
'backup_vault', 'The Backup Vault of the {resource}.',
fallthroughs=fallthroughs
)
def GetBackupAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'backup', 'The instance of the {resource}.')
def GetBackupPolicyAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'backup_policy', 'The instance of the {resource}.'
)
def GetKmsConfigAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'kms_config', 'The instance of the {resource}')
def GetKeyRingAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'key_ring', 'The instance of the {resource}.'
)
def GetCryptoKeyAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'crypto_key', 'The instance of the {resource}.'
)
def GetQuotaRuleAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'quota_rule', 'The instance of the {resource}.'
)
def GetHostGroupAttributeConfig():
return concepts.ResourceParameterAttributeConfig(
'host_group', 'The instance of the {resource}.'
)
## Resource Specs ##
def GetLocationResourceSpec():
location_attribute_config = GetLocationAttributeConfig()
location_attribute_config.fallthroughs = []
return concepts.ResourceSpec(
constants.LOCATIONS_COLLECTION,
resource_name='location',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=location_attribute_config)
def GetListingLocationResourceSpec():
location_attribute_config = GetLocationAttributeConfig()
location_attribute_config.fallthroughs.insert(
0, deps.Fallthrough(lambda: '-', hint='uses all locations by default.'))
return concepts.ResourceSpec(
constants.LOCATIONS_COLLECTION,
resource_name='location',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=location_attribute_config)
def GetOperationResourceSpec():
return concepts.ResourceSpec(
constants.OPERATIONS_COLLECTION,
resource_name='operation',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
operationsId=GetOperationAttributeConfig())
def GetStoragePoolResourceSpec():
return concepts.ResourceSpec(
constants.STORAGEPOOLS_COLLECTION,
resource_name='storage_pool',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
storagePoolsId=GetStoragePoolAttributeConfig())
def GetVolumeResourceSpec(positional=True):
return concepts.ResourceSpec(
constants.VOLUMES_COLLECTION,
resource_name='volume',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
volumesId=GetVolumeAttributeConfig(positional=positional),
)
def GetSnapshotResourceSpec(source_snapshot_op=False, positional=True):
"""Gets the Resource Spec for Snapshot.
Args:
source_snapshot_op: Boolean on whether operation uses snapshot as source or
not.
positional: Boolean on whether resource is positional arg ornot
Returns:
The Resource Spec for Snapshot
"""
location_attribute_config = GetLocationAttributeConfig()
volume_attribute_config = GetVolumeAttributeConfig(positional=False)
if source_snapshot_op:
# if revert op or backup op (create, update) that is a source snapshot op,
# we don't want volume attribute to have any fallthroughs
# (--volume arg) since volume is positional in revert.
volume_attribute_config.fallthroughs = []
if not positional:
location_attribute_config.fallthroughs = [
deps.PropertyFallthrough(properties.VALUES.netapp.location),
]
return concepts.ResourceSpec(
constants.SNAPSHOTS_COLLECTION,
resource_name='snapshot',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=location_attribute_config,
volumesId=volume_attribute_config,
snapshotsId=GetSnapshotAttributeConfig(positional=positional))
def GetReplicationResourceSpec():
location_attribute_config = GetLocationAttributeConfig()
volume_attribute_config = GetVolumeAttributeConfig(positional=False)
return concepts.ResourceSpec(
constants.REPLICATIONS_COLLECTION,
resource_name='replication',
api_version=constants.BETA_API_VERSION,
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=location_attribute_config,
volumesId=volume_attribute_config,
replicationsId=GetReplicationAttributeConfig())
def GetActiveDirectoryResourceSpec():
return concepts.ResourceSpec(
constants.ACTIVEDIRECTORIES_COLLECTION,
resource_name='active_directory',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
activeDirectoriesId=GetActiveDirectoryAttributeConfig())
def GetKmsConfigResourceSpec():
return concepts.ResourceSpec(
constants.KMSCONFIGS_COLLECTION,
resource_name='kms_config',
api_version=constants.BETA_API_VERSION,
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
kmsConfigsId=GetKmsConfigAttributeConfig())
def GetBackupVaultResourceSpec(positional=True):
return concepts.ResourceSpec(
constants.BACKUPVAULTS_COLLECTION,
resource_name='backup_vault',
api_version=constants.BETA_API_VERSION,
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
backupVaultsId=GetBackupVaultAttributeConfig(positional=positional),
)
def GetBackupResourceSpec(positional=True):
location_attribute_config = GetLocationAttributeConfig()
backup_vault_attribute_config = GetBackupVaultAttributeConfig(
positional=False
)
if not positional:
location_attribute_config.fallthroughs = [
deps.PropertyFallthrough(properties.VALUES.netapp.location),
]
return concepts.ResourceSpec(
constants.BACKUPS_COLLECTION,
resource_name='backup',
api_version=constants.BETA_API_VERSION,
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=location_attribute_config,
backupVaultsId=backup_vault_attribute_config,
backupsId=GetBackupAttributeConfig(),
)
def GetBackupPolicyResourceSpec():
return concepts.ResourceSpec(
constants.BACKUPPOLICIES_COLLECTION,
resource_name='backup_policy',
api_version=constants.BETA_API_VERSION,
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
backupPoliciesId=GetBackupPolicyAttributeConfig())
def GetCryptoKeyResourceSpec():
return concepts.ResourceSpec(
'cloudkms.projects.locations.keyRings.cryptoKeys',
resource_name='crypto_key',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
keyRingsId=GetKeyRingAttributeConfig(),
cryptoKeysId=GetCryptoKeyAttributeConfig()
)
def GetQuotaRuleResourceSpec():
return concepts.ResourceSpec(
constants.QUOTA_RULES_COLLECTION,
resource_name='quota_rule',
api_version=constants.BETA_API_VERSION,
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
volumesId=GetVolumeAttributeConfig(positional=False),
quotaRulesId=GetQuotaRuleAttributeConfig(),
)
def GetHostGroupResourceSpec():
return concepts.ResourceSpec(
constants.HOST_GROUPS_COLLECTION,
resource_name='host_group',
projectsId=concepts.DEFAULT_PROJECT_ATTRIBUTE_CONFIG,
locationsId=GetLocationAttributeConfig(),
hostGroupsId=GetHostGroupAttributeConfig(),
)
## Presentation Specs ##
def GetLocationPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'location', GetLocationResourceSpec(), group_help, required=True)
def GetResourceListingLocationPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'--location',
GetListingLocationResourceSpec(),
group_help)
def GetOperationPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'operation', GetOperationResourceSpec(), group_help, required=True)
def GetStoragePoolPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'storage_pool', GetStoragePoolResourceSpec(), group_help, required=True)
def GetVolumePresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'volume', GetVolumeResourceSpec(), group_help, required=True)
def GetSnapshotPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'snapshot',
GetSnapshotResourceSpec(),
group_help,
required=True,
flag_name_overrides={'volume': ''})
def GetReplicationPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'replication',
GetReplicationResourceSpec(),
group_help,
required=True,
flag_name_overrides={'volume': ''})
def GetActiveDirectoryPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'active_directory',
GetActiveDirectoryResourceSpec(),
group_help,
required=True)
def GetKmsConfigPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'kms_config',
GetKmsConfigResourceSpec(),
group_help,
required=True)
def GetBackupVaultPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'backup_vault',
GetBackupVaultResourceSpec(),
group_help,
required=True)
def GetBackupPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'backup',
GetBackupResourceSpec(),
group_help,
required=True,
flag_name_overrides={'backup_vault': ''})
def GetQuotaRulePresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'quota_rule',
GetQuotaRuleResourceSpec(),
group_help,
required=True,
flag_name_overrides={'volume': ''})
def GetHostGroupPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'host_group',
GetHostGroupResourceSpec(),
group_help,
required=True,
)
# TODO(b/290375665): Add more unit tests to test Backup Poicy
# Presentation, resource specs and flags
def GetBackupPolicyPresentationSpec(group_help):
return presentation_specs.ResourcePresentationSpec(
'backup_policy',
GetBackupPolicyResourceSpec(),
group_help,
required=True)
## Add args to arg parser ##
def AddResourceDescriptionArg(parser, resource_name):
"""Add Description arg to arg_parser for a resource called resource_name."""
parser.add_argument(
'--description',
required=False,
help='A description of the Cloud NetApp {}'.format(resource_name))
def AddResourceCapacityArg(parser, resource_name, required=True):
"""Add Capacity arg to arg_parser for a resource called resource_name."""
parser.add_argument(
'--capacity',
type=arg_parsers.BinarySize(
default_unit='GiB', suggested_binary_size_scales=['GiB', 'TiB']),
required=required,
help=('The desired capacity of the {} in GiB or TiB units.'
'If no capacity unit is specified, GiB is assumed.'.format(
resource_name)))
def AddResourceAsyncFlag(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 AddResourcePeerClusterNameArg(parser, required=True):
"""Adds the Peer Cluster Name (--peer-cluster-name) arg to the given parser.
Args:
parser: Argparse parser.
required: Required to establish both cluster and svm peering.
"""
parser.add_argument(
'--peer-cluster-name',
type=str,
required=required,
help="""Name of the destination cluster to be peered
with the source cluster.""",
)
def AddResourcePeerSvmNameArg(parser, required=True):
"""Adds the Peer SVM Name (--peer-svm-name) arg to the given parser.
Args:
parser: Argparse parser.
required: Required to establish both cluster and svm peering.
"""
parser.add_argument(
'--peer-svm-name',
type=str,
required=required,
help="""Name of the local source vserver svm to be peered
with the destination cluster.""",
)
def AddResourcePeerVolumeNameArg(parser, required=True):
"""Adds the Peer Volume Name (--peer-volume-name) arg to the given parser.
Args:
parser: Argparse parser.
required: Required to establish both cluster and svm peering.
"""
parser.add_argument(
'--peer-volume-name',
type=str,
required=required,
help="""Name of the source volume to be peered
with the destination volume.""",
)
def AddResourcePeerIpAddressesArg(parser):
"""Adds the Peer IP Addresses (--peer-ip-addresses) arg to the given parser.
Args:
parser: Argparse parser.
Not required for svm peering.
"""
parser.add_argument(
'--peer-ip-addresses',
type=arg_parsers.ArgList(min_length=1, element_type=str),
metavar='PEER_IP_ADDRESS',
help=(
'List of ip addresses to be used for peering. This is required for'
' cluster peering, not required for svm peering.'
),
)