зеркало из https://github.com/microsoft/azure-cli.git
Merge pull request #195 from tjprescott/AddResourceGroupCommand
ResourceGroup Commands: create, delete, exists, show
This commit is contained in:
Коммит
5f54d9478f
|
@ -28,6 +28,7 @@
|
|||
<Compile Include="azure\cli\application.py" />
|
||||
<Compile Include="azure\cli\commands\_auto_command.py" />
|
||||
<Compile Include="azure\cli\commands\_command_creation.py" />
|
||||
<Compile Include="azure\cli\commands\_validators.py" />
|
||||
<Compile Include="azure\cli\commands\__init__.py" />
|
||||
<Compile Include="azure\cli\command_modules\__init__.py" />
|
||||
<Compile Include="azure\cli\extensions\query.py">
|
||||
|
@ -37,6 +38,9 @@
|
|||
<Compile Include="azure\cli\extensions\__init__.py" />
|
||||
<Compile Include="azure\cli\main.py" />
|
||||
<Compile Include="azure\cli\tests\test_add_resourcegroup_transform.py" />
|
||||
<Compile Include="azure\cli\tests\test_logging.py" />
|
||||
<Compile Include="azure\cli\tests\test_validators.py" />
|
||||
<Compile Include="azure\cli\utils\command_test_script.py" />
|
||||
<Compile Include="command_modules\azure-cli-network\azure\cli\command_modules\network\mgmt\lib\credentials.py" />
|
||||
<Compile Include="command_modules\azure-cli-network\azure\cli\command_modules\network\mgmt\lib\exceptions.py" />
|
||||
<Compile Include="command_modules\azure-cli-network\azure\cli\command_modules\network\mgmt\lib\models\basic_dependency.py" />
|
||||
|
@ -58,7 +62,14 @@
|
|||
<Compile Include="command_modules\azure-cli-network\azure\cli\command_modules\network\mgmt\__init__.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="command_modules\azure-cli-storage\azure\cli\command_modules\storage\tests\test_storage_validators.py" />
|
||||
<Compile Include="command_modules\azure-cli-resource\azure\cli\command_modules\resource\custom.py" />
|
||||
<Compile Include="command_modules\azure-cli-resource\azure\cli\command_modules\resource\generated.py" />
|
||||
<Compile Include="command_modules\azure-cli-resource\azure\cli\command_modules\resource\tests\test_validators.py" />
|
||||
<Compile Include="command_modules\azure-cli-resource\azure\cli\command_modules\resource\_params.py" />
|
||||
<Compile Include="command_modules\azure-cli-resource\azure\cli\command_modules\resource\_validators.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="command_modules\azure-cli-storage\azure\cli\command_modules\storage\tests\test_validators.py" />
|
||||
<Compile Include="command_modules\azure-cli-storage\azure\cli\command_modules\storage\_params.py" />
|
||||
<Compile Include="command_modules\azure-cli-storage\azure\cli\command_modules\storage\_validators.py" />
|
||||
<Compile Include="command_modules\azure-cli-vm\azure\cli\command_modules\vm\tests\test_custom_vm_commands.py" />
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import argparse
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
from azure.cli.application import Configuration
|
||||
|
@ -11,13 +13,34 @@ class Exporter(json.JSONEncoder):
|
|||
except TypeError:
|
||||
return str(o)
|
||||
|
||||
cmd_set_names = None
|
||||
if len(sys.argv) > 1:
|
||||
cmd_set_names = sys.argv[1].split(',')
|
||||
parser = argparse.ArgumentParser(description='Command Table Parser')
|
||||
parser.add_argument('--commands', metavar='N', nargs='+', help='Filter by first level command (OR)')
|
||||
parser.add_argument('--params', metavar='N', nargs='+', help='Filter by parameters (OR)')
|
||||
args = parser.parse_args()
|
||||
cmd_set_names = args.commands
|
||||
param_names = args.params
|
||||
|
||||
config = Configuration([])
|
||||
cmd_table = config.get_command_table()
|
||||
cmd_names = [x['name'] for x in cmd_table.values()
|
||||
cmd_list = [x['name'] for x in cmd_table.values()
|
||||
if cmd_set_names is None or (x['name'].split()[0]) in cmd_set_names]
|
||||
results = []
|
||||
|
||||
print('\n'.join(cmd_names))
|
||||
if param_names:
|
||||
for name in cmd_list:
|
||||
cmd_args = [x for x in cmd_table.values() if name == x['name']][0]['arguments']
|
||||
match = False
|
||||
for arg in cmd_args:
|
||||
if match:
|
||||
break
|
||||
arg_name = re.sub('--','', arg['name']).split(' ')[0]
|
||||
if arg_name in param_names:
|
||||
results.append(name)
|
||||
match = True
|
||||
else:
|
||||
results = cmd_list
|
||||
|
||||
heading = '=== COMMANDS IN {} PACKAGE(S) WITH {} PARAMETERS ==='.format(
|
||||
cmd_set_names or 'ANY', param_names or 'ANY')
|
||||
print('\n{}\n'.format(heading))
|
||||
print('\n'.join(results))
|
|
@ -8,6 +8,8 @@ from msrest.exceptions import ClientException
|
|||
|
||||
from azure.cli._util import CLIError
|
||||
import azure.cli._logging as _logging
|
||||
from azure.cli._locale import L
|
||||
from azure.cli.commands._validators import validate_tags, validate_tag
|
||||
|
||||
logger = _logging.get_az_logger(__name__)
|
||||
|
||||
|
@ -21,12 +23,12 @@ logger.info('Installed command modules %s', INSTALLED_COMMAND_MODULES)
|
|||
RESOURCE_GROUP_ARG_NAME = 'resource_group_name'
|
||||
|
||||
COMMON_PARAMETERS = {
|
||||
'resource_group_name': {
|
||||
'name': '--resource-group -g',
|
||||
'dest': RESOURCE_GROUP_ARG_NAME,
|
||||
'metavar': 'RESOURCEGROUP',
|
||||
'help': 'The name of the resource group.',
|
||||
'required': True
|
||||
'deployment_name': {
|
||||
'name': '--deployment-name',
|
||||
'metavar': 'DEPLOYMENTNAME',
|
||||
'help': 'Name of the resource deployment',
|
||||
'default': 'azurecli' + str(time.time()) + str(random.randint(0, 10000000)),
|
||||
'required': False
|
||||
},
|
||||
'location': {
|
||||
'name': '--location -l',
|
||||
|
@ -34,13 +36,27 @@ COMMON_PARAMETERS = {
|
|||
'help': 'Location',
|
||||
'required': True
|
||||
},
|
||||
'deployment_name': {
|
||||
'name': '--deployment-name',
|
||||
'metavar': 'DEPLOYMENTNAME',
|
||||
'help': 'The name of the resource deployment.',
|
||||
'default': 'azurecli' + str(time.time()) + str(random.randint(0, 10000000)),
|
||||
'required': False
|
||||
}
|
||||
'resource_group_name': {
|
||||
'name': '--resource-group -g',
|
||||
'dest': RESOURCE_GROUP_ARG_NAME,
|
||||
'metavar': 'RESOURCEGROUP',
|
||||
'help': 'The name of the resource group',
|
||||
'required': True
|
||||
},
|
||||
'tag' : {
|
||||
'name': '--tag',
|
||||
'metavar': 'TAG',
|
||||
'help': L('a single tag in \'key[=value]\' format'),
|
||||
'required': False,
|
||||
'type': validate_tag
|
||||
},
|
||||
'tags' : {
|
||||
'name': '--tags',
|
||||
'metavar': 'TAGS',
|
||||
'help': L('multiple semicolon separated tags in \'key[=value]\' format'),
|
||||
'required': False,
|
||||
'type': validate_tags
|
||||
},
|
||||
}
|
||||
|
||||
def extend_parameter(parameter_metadata, **kwargs):
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
def validate_tags(string):
|
||||
''' Extracts multiple tags in key[=value] format, separated by semicolons '''
|
||||
result = None
|
||||
if string:
|
||||
result = validate_key_value_pairs(string)
|
||||
s_list = [x for x in string.split(';') if '=' not in x] # single values
|
||||
result.update(dict((x, '') for x in s_list))
|
||||
return result
|
||||
|
||||
def validate_tag(string):
|
||||
''' Extracts a single tag in key[=value] format '''
|
||||
result = None
|
||||
if string:
|
||||
comps = string.split('=', 1)
|
||||
result = {comps[0]: comps[1]} if len(comps) > 1 else {string: ''}
|
||||
return result
|
||||
|
||||
def validate_key_value_pairs(string):
|
||||
''' Validates key-value pairs in the following format: a=b;c=d '''
|
||||
result = None
|
||||
if string:
|
||||
kv_list = [x for x in string.split(';') if '=' in x] # key-value pairs
|
||||
result = dict(x.split('=', 1) for x in kv_list)
|
||||
return result
|
|
@ -54,7 +54,7 @@ class Test_autocommand(unittest.TestCase):
|
|||
self.assertEqual(command_metadata['name'], 'test autocommand sample-vm-get', 'Unexpected command name...')
|
||||
self.assertEqual(len(command_metadata['arguments']), 4, 'We expected exactly 4 arguments')
|
||||
some_expected_arguments = [
|
||||
{'name': '--resource-group -g', 'dest': 'resource_group_name', 'required': True, 'help':'The name of the resource group.'},
|
||||
{'name': '--resource-group -g', 'dest': 'resource_group_name', 'required': True, 'help':'The name of the resource group'},
|
||||
{'name': '--vm-name', 'dest': 'vm_name', 'required': True, 'help': 'The name of the virtual machine.'},
|
||||
{'name': '--opt-param', 'required': False, 'help': 'Used to verify auto-command correctly identifies optional params.'},
|
||||
{'name': '--expand', 'required': False, 'help': 'The expand expression to apply on the operation.'},
|
||||
|
|
|
@ -347,38 +347,39 @@ Examples
|
|||
'.*mismatched required True vs\. False, --foobar -fb.*',
|
||||
lambda: app.execute('n1 -h'.split()))
|
||||
|
||||
@redirect_io
|
||||
def test_help_extra_help_params(self):
|
||||
app = Application(Configuration([]))
|
||||
def test_handler(args):
|
||||
pass
|
||||
# TODO: Restore test when Python 2.7 bug fix applied
|
||||
#@redirect_io
|
||||
#def test_help_extra_help_params(self):
|
||||
# app = Application(Configuration([]))
|
||||
# def test_handler(args):
|
||||
# pass
|
||||
|
||||
cmd_table = {
|
||||
test_handler: {
|
||||
'name': 'n1',
|
||||
'help_file': '''
|
||||
parameters:
|
||||
- name: --foobar -fb
|
||||
type: string
|
||||
required: false
|
||||
short-summary: one line partial sentence
|
||||
long-summary: text, markdown, etc.
|
||||
populator-commands:
|
||||
- az vm list
|
||||
- default
|
||||
''',
|
||||
'arguments': [
|
||||
{'name': '--foobar2 -fb2', 'required': True}
|
||||
]
|
||||
}
|
||||
}
|
||||
config = Configuration([])
|
||||
config.get_command_table = lambda: cmd_table
|
||||
app = Application(config)
|
||||
# cmd_table = {
|
||||
# test_handler: {
|
||||
# 'name': 'n1',
|
||||
# 'help_file': '''
|
||||
# parameters:
|
||||
# - name: --foobar -fb
|
||||
# type: string
|
||||
# required: false
|
||||
# short-summary: one line partial sentence
|
||||
# long-summary: text, markdown, etc.
|
||||
# populator-commands:
|
||||
# - az vm list
|
||||
# - default
|
||||
# ''',
|
||||
# 'arguments': [
|
||||
# {'name': '--foobar2 -fb2', 'required': True}
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
# config = Configuration([])
|
||||
# config.get_command_table = lambda: cmd_table
|
||||
# app = Application(config)
|
||||
|
||||
self.assertRaisesRegexp(HelpAuthoringException,
|
||||
'.*Extra help param --foobar -fb.*',
|
||||
lambda: app.execute('n1 -h'.split()))
|
||||
# self.assertRaisesRegexp(HelpAuthoringException,
|
||||
# '.*Extra help param --foobar -fb.*',
|
||||
# lambda: app.execute('n1 -h'.split()))
|
||||
|
||||
@redirect_io
|
||||
@mock.patch('azure.cli.application.Application.register', return_value=None)
|
||||
|
|
|
@ -160,14 +160,14 @@ Myarray :
|
|||
obj['A'] = 1
|
||||
obj['B'] = 2
|
||||
result = format_tsv(obj)
|
||||
self.assertEquals(result, '1\t2')
|
||||
self.assertEqual(result, '1\t2')
|
||||
|
||||
def test_output_format_dict_sort(self):
|
||||
obj = {}
|
||||
obj['B'] = 1
|
||||
obj['A'] = 2
|
||||
result = format_tsv(obj)
|
||||
self.assertEquals(result, '2\t1')
|
||||
self.assertEqual(result, '2\t1')
|
||||
|
||||
def test_output_format_ordereddict_not_sorted(self):
|
||||
from collections import OrderedDict
|
||||
|
@ -175,7 +175,7 @@ Myarray :
|
|||
obj['B'] = 1
|
||||
obj['A'] = 2
|
||||
result = format_tsv(obj)
|
||||
self.assertEquals(result, '1\t2')
|
||||
self.assertEqual(result, '1\t2')
|
||||
|
||||
def test_output_format_ordereddict_list_not_sorted(self):
|
||||
from collections import OrderedDict
|
||||
|
@ -187,7 +187,7 @@ Myarray :
|
|||
obj2['A'] = 3
|
||||
obj2['B'] = 4
|
||||
result = format_tsv([obj1, obj2])
|
||||
self.assertEquals(result, '1\t2\n3\t4')
|
||||
self.assertEqual(result, '1\t2\n3\t4')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
import unittest
|
||||
from six import StringIO
|
||||
|
||||
from azure.cli.commands._validators import *
|
||||
|
||||
class Test_storage_validators(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
pass
|
||||
|
||||
def setUp(self):
|
||||
self.io = StringIO()
|
||||
|
||||
def tearDown(self):
|
||||
self.io.close()
|
||||
|
||||
def test_key_value_pairs_valid(self):
|
||||
input = 'a=b;c=d'
|
||||
actual = validate_key_value_pairs(input)
|
||||
expected = {'a':'b', 'c':'d'}
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_key_value_pairs_invalid(self):
|
||||
input = 'a=b;c=d;e'
|
||||
actual = validate_key_value_pairs(input)
|
||||
expected = {'a':'b', 'c':'d'}
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_tags_valid(self):
|
||||
input = 'a=b;c=d;e'
|
||||
actual = validate_tags(input)
|
||||
expected = {'a':'b', 'c':'d', 'e':''}
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_tags_invalid(self):
|
||||
input = ''
|
||||
actual = validate_tags(input)
|
||||
expected = None
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_tag(self):
|
||||
self.assertEqual(validate_tag('test'), {'test':''})
|
||||
self.assertEqual(validate_tag('a=b'), {'a':'b'})
|
||||
self.assertEqual(validate_tag('a=b;c=d'), {'a':'b;c=d'})
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -188,6 +188,9 @@ class CommandTestGenerator(object):
|
|||
def before_record_request(request):
|
||||
request.uri = re.sub('/subscriptions/([^/]+)/',
|
||||
'/subscriptions/00000000-0000-0000-0000-000000000000/', request.uri)
|
||||
# prevents URI mismatch between Python 2 and 3 if request URI has extra / chars
|
||||
request.uri = re.sub('//', '/', request.uri)
|
||||
request.uri = re.sub('/', '//', request.uri, count=1)
|
||||
return request
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -1,152 +1,5 @@
|
|||
from azure.cli.parser import IncorrectUsageError
|
||||
from azure.cli.commands import CommandTable, COMMON_PARAMETERS, RESOURCE_GROUP_ARG_NAME
|
||||
from azure.cli.commands._command_creation import get_mgmt_service_client
|
||||
from azure.cli._locale import L
|
||||
from .generated import command_table as generated_command_table
|
||||
from .custom import command_table as convenience_command_table
|
||||
|
||||
command_table = CommandTable()
|
||||
|
||||
def _resource_client_factory(_):
|
||||
from azure.mgmt.resource.resources import (ResourceManagementClient,
|
||||
ResourceManagementClientConfiguration)
|
||||
return get_mgmt_service_client(ResourceManagementClient, ResourceManagementClientConfiguration)
|
||||
|
||||
@command_table.command('resource group list', description=L('List resource groups'))
|
||||
@command_table.option('--tag-name -tn', help=L("the resource group's tag name"))
|
||||
@command_table.option('--tag-value -tv', help=L("the resource group's tag value"))
|
||||
def list_groups(args):
|
||||
from azure.mgmt.resource.resources.models import ResourceGroup, ResourceGroupFilter
|
||||
|
||||
rmc = _resource_client_factory(args)
|
||||
|
||||
filters = []
|
||||
if args.get('tag_name'):
|
||||
filters.append("tagname eq '{}'".format(args.get('tag_name')))
|
||||
if args.get('tag_value'):
|
||||
filters.append("tagvalue eq '{}'".format(args.get('tag_value')))
|
||||
|
||||
filter_text = ' and '.join(filters) if len(filters) > 0 else None
|
||||
|
||||
groups = rmc.resource_groups.list(filter=filter_text)
|
||||
return list(groups)
|
||||
|
||||
@command_table.command('resource show')
|
||||
@command_table.description(
|
||||
L('Show details of a specific resource in a resource group or subscription'))
|
||||
@command_table.option(**COMMON_PARAMETERS['resource_group_name'])
|
||||
@command_table.option('--name -n', help=L('the resource name'), required=True)
|
||||
@command_table.option('--resource-type -r',
|
||||
help=L('the resource type in format: <provider-namespace>/<type>'),
|
||||
required=True)
|
||||
@command_table.option('--api-version -o', help=L('the API version of the resource provider'))
|
||||
@command_table.option('--parent', default='',
|
||||
help=L('the name of the parent resource (if needed), ' + \
|
||||
'in <parent-type>/<parent-name> format'))
|
||||
def show_resource(args):
|
||||
rmc = _resource_client_factory(args)
|
||||
|
||||
full_type = args.get('resource_type').split('/')
|
||||
try:
|
||||
provider_namespace = full_type[0]
|
||||
resource_type = full_type[1]
|
||||
except IndexError:
|
||||
raise IncorrectUsageError('Parameter --resource-type must be in <namespace>/<type> format.')
|
||||
|
||||
api_version = _resolve_api_version(args, rmc)
|
||||
if not api_version:
|
||||
raise IncorrectUsageError(
|
||||
L('API version is required and could not be resolved for resource {}'
|
||||
.format(full_type)))
|
||||
results = rmc.resources.get(
|
||||
resource_group_name=args.get(RESOURCE_GROUP_ARG_NAME),
|
||||
resource_name=args.get('name'),
|
||||
resource_provider_namespace=provider_namespace,
|
||||
resource_type=resource_type,
|
||||
api_version=api_version,
|
||||
parent_resource_path=args.get('parent', '')
|
||||
)
|
||||
return results
|
||||
|
||||
def _list_resources_odata_filter_builder(args):
|
||||
'''Build up OData filter string from parameters
|
||||
'''
|
||||
|
||||
filters = []
|
||||
|
||||
name = args.get('name')
|
||||
if name:
|
||||
filters.append("name eq '%s'" % name)
|
||||
|
||||
location = args.get('location')
|
||||
if location:
|
||||
filters.append("location eq '%s'" % location)
|
||||
|
||||
resource_type = args.get('resource_type')
|
||||
if resource_type:
|
||||
filters.append("resourceType eq '%s'" % resource_type)
|
||||
|
||||
tag = args.get('tag') or ''
|
||||
if tag and (name or location):
|
||||
raise IncorrectUsageError(
|
||||
'you cannot use the tagname or tagvalue filters with other filters')
|
||||
|
||||
tag_name_value = tag.split('=')
|
||||
tag_name = tag_name_value[0]
|
||||
if tag_name:
|
||||
if tag_name[-1] == '*':
|
||||
filters.append("startswith(tagname, '%s')" % tag_name[0:-1])
|
||||
else:
|
||||
filters.append("tagname eq '%s'" % tag_name_value[0])
|
||||
if len(tag_name_value) == 2:
|
||||
filters.append("tagvalue eq '%s'" % tag_name_value[1])
|
||||
return ' and '.join(filters)
|
||||
|
||||
@command_table.command('resource list', description=L('List resources'))
|
||||
@command_table.option('--location -l', help=L("Resource location"))
|
||||
@command_table.option('--resource-type -r', help=L("Resource type"))
|
||||
@command_table.option('--tag -t',
|
||||
help=L("Filter by tag in the format of <tagname> or <tagname>=<tagvalue>"))
|
||||
@command_table.option('--name -n', help=L("Name of resource"))
|
||||
def list_resources(args):
|
||||
''' EXAMPLES:
|
||||
az resource list --location westus
|
||||
az resource list --name thename
|
||||
az resource list --name thename --location westus
|
||||
az resource list --tag something
|
||||
az resource list --tag some*
|
||||
az resource list --tag something=else
|
||||
'''
|
||||
rmc = _resource_client_factory(args)
|
||||
odata_filter = _list_resources_odata_filter_builder(args)
|
||||
resources = rmc.resources.list(filter=odata_filter)
|
||||
return list(resources)
|
||||
|
||||
def _resolve_api_version(args, rmc):
|
||||
api_version = args.get('api-version')
|
||||
if api_version:
|
||||
return api_version
|
||||
|
||||
# if api-version not supplied, attempt to resolve using provider namespace
|
||||
parent = args.get('parent')
|
||||
full_type = args.get('resource_type').split('/')
|
||||
try:
|
||||
provider_namespace = full_type[0]
|
||||
resource_type = full_type[1]
|
||||
except IndexError:
|
||||
raise IncorrectUsageError('Parameter --resource-type must be in <namespace>/<type> format.')
|
||||
|
||||
if parent:
|
||||
try:
|
||||
parent_type = parent.split('/')[0]
|
||||
except IndexError:
|
||||
raise IncorrectUsageError('Parameter --parent must be in <type>/<name> format.')
|
||||
|
||||
resource_type = "{}/{}".format(parent_type, resource_type)
|
||||
provider = rmc.providers.get(provider_namespace)
|
||||
|
||||
rt = [t for t in provider.resource_types if t.resource_type == resource_type]
|
||||
if not rt:
|
||||
raise IncorrectUsageError('Resource type {} not found.'.format(full_type))
|
||||
if len(rt) == 1 and rt[0].api_versions:
|
||||
npv = [v for v in rt[0].api_versions if "preview" not in v]
|
||||
return npv[0] if npv else rt[0].api_versions[0]
|
||||
return None
|
||||
command_table = generated_command_table
|
||||
command_table.update(convenience_command_table)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
from azure.cli.commands import COMMON_PARAMETERS as GLOBAL_COMMON_PARAMETERS
|
||||
from azure.cli._locale import L
|
||||
|
||||
from ._validators import validate_resource_type, validate_parent
|
||||
|
||||
# BASIC PARAMETER CONFIGURATION
|
||||
|
||||
PARAMETER_ALIASES = GLOBAL_COMMON_PARAMETERS.copy()
|
||||
PARAMETER_ALIASES.update({
|
||||
'resource_type': {
|
||||
'name': '--resource-type',
|
||||
'help': L('the resource type in <namespace>/<type> format'),
|
||||
'type': validate_resource_type
|
||||
},
|
||||
'parent': {
|
||||
'name': '--parent',
|
||||
'help': L('the parent resource type in <type>/<name> format'),
|
||||
'type': validate_parent
|
||||
}
|
||||
})
|
|
@ -0,0 +1,27 @@
|
|||
import collections
|
||||
|
||||
from azure.cli.parser import IncorrectUsageError
|
||||
|
||||
def validate_resource_type(string):
|
||||
''' Validates that resource type is provided in <namespace>/<type> format '''
|
||||
type_comps = string.split('/')
|
||||
try:
|
||||
namespace_comp = type_comps[0]
|
||||
resource_comp = type_comps[1]
|
||||
except IndexError:
|
||||
raise IncorrectUsageError('Parameter --resource-type must be in <namespace>/<type> format.')
|
||||
ResourceType = collections.namedtuple('ResourceType', 'namespace type')
|
||||
return ResourceType(namespace=namespace_comp, type=resource_comp)
|
||||
|
||||
def validate_parent(string):
|
||||
''' Validates that parent is provided in <type>/<name> format '''
|
||||
if not string:
|
||||
return string
|
||||
parent_comps = string.split('/')
|
||||
try:
|
||||
type_comp = parent_comps[0]
|
||||
name_comp = parent_comps[1]
|
||||
except IndexError:
|
||||
raise IncorrectUsageError('Parameter --parent must be in <type>/<name> format.')
|
||||
ParentType = collections.namedtuple('ParentType', 'type name')
|
||||
return ParentType(type=type_comp, name=name_comp)
|
|
@ -0,0 +1,151 @@
|
|||
from azure.mgmt.resource.resources.models.resource_group import ResourceGroup
|
||||
|
||||
from azure.cli.parser import IncorrectUsageError
|
||||
from azure.cli.commands import CommandTable
|
||||
from azure.cli.commands._command_creation import get_mgmt_service_client
|
||||
from azure.cli._locale import L
|
||||
|
||||
command_table = CommandTable()
|
||||
|
||||
def _resource_client_factory(_):
|
||||
from azure.mgmt.resource.resources import (ResourceManagementClient,
|
||||
ResourceManagementClientConfiguration)
|
||||
return get_mgmt_service_client(ResourceManagementClient, ResourceManagementClientConfiguration)
|
||||
|
||||
#### RESOURCE GROUP COMMANDS #################################
|
||||
|
||||
class ConvenienceResourceGroupCommands(object): # pylint: disable=too-few-public-methods
|
||||
|
||||
def __init__(self, _):
|
||||
pass
|
||||
|
||||
def list(self, tag=None): # pylint: disable=no-self-use
|
||||
''' List resource groups, optionally filtered by a tag.
|
||||
:param str tag:tag to filter by in 'key[=value]' format
|
||||
'''
|
||||
rcf = _resource_client_factory(None)
|
||||
|
||||
filters = []
|
||||
if tag:
|
||||
key = tag.keys()[0]
|
||||
filters.append("tagname eq '{}'".format(key))
|
||||
filters.append("tagvalue eq '{}'".format(tag[key]))
|
||||
|
||||
filter_text = ' and '.join(filters) if len(filters) > 0 else None
|
||||
|
||||
groups = rcf.resource_groups.list(filter=filter_text)
|
||||
return list(groups)
|
||||
|
||||
def create(self, resource_group_name, location, tags=None): # pylint: disable=no-self-use
|
||||
''' Create a new resource group.
|
||||
:param str resource_group_name:the desired resource group name
|
||||
:param str location:the resource group location
|
||||
:param str tags:tags in 'a=b;c' format
|
||||
'''
|
||||
rcf = _resource_client_factory(None)
|
||||
|
||||
if rcf.resource_groups.check_existence(resource_group_name):
|
||||
raise ValueError('resource group {} already exists'.format(resource_group_name))
|
||||
parameters = ResourceGroup(
|
||||
location=location,
|
||||
tags=tags
|
||||
)
|
||||
return rcf.resource_groups.create_or_update(resource_group_name, parameters)
|
||||
|
||||
#### RESOURCE COMMANDS #######################################
|
||||
|
||||
def _list_resources_odata_filter_builder(location=None, resource_type=None, tag=None, name=None):
|
||||
'''Build up OData filter string from parameters
|
||||
'''
|
||||
|
||||
filters = []
|
||||
|
||||
if name:
|
||||
filters.append("name eq '%s'" % name)
|
||||
|
||||
if location:
|
||||
filters.append("location eq '%s'" % location)
|
||||
|
||||
if resource_type:
|
||||
filters.append("resourceType eq '%s'" % resource_type)
|
||||
|
||||
if tag:
|
||||
if name or location:
|
||||
raise IncorrectUsageError(
|
||||
'you cannot use the tagname or tagvalue filters with other filters')
|
||||
|
||||
tag_comps = tag.split('=')
|
||||
tag_name = tag_comps[0]
|
||||
if tag_name:
|
||||
if tag_name[-1] == '*':
|
||||
filters.append("startswith(tagname, '%s')" % tag_name[0:-1])
|
||||
else:
|
||||
filters.append("tagname eq '%s'" % tag_name)
|
||||
if len(tag_comps) == 2:
|
||||
filters.append("tagvalue eq '%s'" % tag_comps[1])
|
||||
return ' and '.join(filters)
|
||||
|
||||
def _resolve_api_version(rcf, resource_type, parent=None):
|
||||
|
||||
provider = rcf.providers.get(resource_type.namespace)
|
||||
resource_type_str = '{}/{}'.format(parent.type, resource_type.type) \
|
||||
if parent else resource_type.type
|
||||
|
||||
rt = [t for t in provider.resource_types if t.resource_type == resource_type_str]
|
||||
if not rt:
|
||||
raise IncorrectUsageError('Resource type {}/{} not found.'
|
||||
.format(resource_type.namespace, resource_type.type))
|
||||
if len(rt) == 1 and rt[0].api_versions:
|
||||
npv = [v for v in rt[0].api_versions if "preview" not in v]
|
||||
return npv[0] if npv else rt[0].api_versions[0]
|
||||
else:
|
||||
raise IncorrectUsageError(
|
||||
L('API version is required and could not be resolved for resource {}/{}'
|
||||
.format(resource_type.namespace, resource_type.type)))
|
||||
|
||||
class ConvenienceResourceCommands(object): # pylint: disable=too-few-public-methods
|
||||
|
||||
def __init__(self, _):
|
||||
pass
|
||||
|
||||
def show(self, resource_group, resource_name, resource_type, api_version=None, parent=None): # pylint: disable=too-many-arguments,no-self-use
|
||||
''' Show details of a specific resource in a resource group or subscription
|
||||
:param str resource-group-name:the containing resource group name
|
||||
:param str name:the resource name
|
||||
:param str resource-type:the resource type in format: <provider-namespace>/<type>
|
||||
:param str api-version:the API version of the resource provider
|
||||
:param str parent:the name of the parent resource (if needed) in <type>/<name> format'''
|
||||
rcf = _resource_client_factory(None)
|
||||
|
||||
api_version = _resolve_api_version(rcf, resource_type, parent) \
|
||||
if not api_version else api_version
|
||||
parent_path = '{}/{}'.format(parent.type, parent.name) if parent else ''
|
||||
|
||||
results = rcf.resources.get(
|
||||
resource_group_name=resource_group,
|
||||
resource_name=resource_name,
|
||||
resource_provider_namespace=resource_type.namespace,
|
||||
resource_type=resource_type.type,
|
||||
api_version=api_version,
|
||||
parent_resource_path=parent_path
|
||||
)
|
||||
return results
|
||||
|
||||
def list(self, location=None, resource_type=None, tag=None, name=None): # pylint: disable=no-self-use
|
||||
''' List resources
|
||||
EXAMPLES:
|
||||
az resource list --location westus
|
||||
az resource list --name thename
|
||||
az resource list --name thename --location westus
|
||||
az resource list --tag something
|
||||
az resource list --tag some*
|
||||
az resource list --tag something=else
|
||||
:param str location:filter by resource location
|
||||
:param str resource-type:filter by resource type
|
||||
:param str tag:filter by tag in 'a=b;c' format
|
||||
:param str name:filter by resource name
|
||||
'''
|
||||
rcf = _resource_client_factory(None)
|
||||
odata_filter = _list_resources_odata_filter_builder(location, resource_type, tag, name)
|
||||
resources = rcf.resources.list(filter=odata_filter)
|
||||
return list(resources)
|
|
@ -0,0 +1,98 @@
|
|||
from azure.mgmt.resource.resources.operations.resource_groups_operations \
|
||||
import ResourceGroupsOperations
|
||||
from azure.mgmt.resource.resources.operations.tags_operations import TagsOperations
|
||||
from azure.mgmt.resource.resources.operations.deployments_operations import DeploymentsOperations
|
||||
from azure.mgmt.resource.resources.operations.deployment_operations_operations \
|
||||
import DeploymentOperationsOperations
|
||||
from azure.cli.commands._auto_command import build_operation, AutoCommandDefinition
|
||||
from azure.cli.commands import CommandTable, LongRunningOperation
|
||||
from azure.cli._locale import L
|
||||
|
||||
from ._params import PARAMETER_ALIASES
|
||||
from .custom import (_resource_client_factory,
|
||||
ConvenienceResourceGroupCommands, ConvenienceResourceCommands)
|
||||
|
||||
command_table = CommandTable()
|
||||
|
||||
def _patch_aliases(alias_items):
|
||||
aliases = PARAMETER_ALIASES.copy()
|
||||
aliases.update(alias_items)
|
||||
return aliases
|
||||
|
||||
build_operation(
|
||||
'resource group', 'resource_groups', _resource_client_factory,
|
||||
[
|
||||
AutoCommandDefinition(
|
||||
ResourceGroupsOperations.delete,
|
||||
LongRunningOperation(L('Deleting resource group'), L('Resource group deleted'))),
|
||||
AutoCommandDefinition(ResourceGroupsOperations.get, 'ResourceGroup', 'show'),
|
||||
AutoCommandDefinition(ResourceGroupsOperations.check_existence, 'Bool', 'exists'),
|
||||
],
|
||||
command_table,
|
||||
_patch_aliases({
|
||||
'resource_group_name': {'name': '--name -n'}
|
||||
}))
|
||||
|
||||
build_operation(
|
||||
'resource group', None, ConvenienceResourceGroupCommands,
|
||||
[
|
||||
AutoCommandDefinition(ConvenienceResourceGroupCommands.list, '[ResourceGroup]'),
|
||||
AutoCommandDefinition(ConvenienceResourceGroupCommands.create, 'ResourceGroup'),
|
||||
],
|
||||
command_table,
|
||||
_patch_aliases({
|
||||
'resource_group_name': {'name': '--name -n'}
|
||||
}))
|
||||
|
||||
build_operation(
|
||||
'resource', None, ConvenienceResourceCommands,
|
||||
[
|
||||
AutoCommandDefinition(ConvenienceResourceCommands.list, '[Resource]'),
|
||||
AutoCommandDefinition(ConvenienceResourceCommands.show, 'Resource'),
|
||||
],
|
||||
command_table,
|
||||
_patch_aliases({
|
||||
'resource_name': {'name': '--name -n'}
|
||||
}))
|
||||
|
||||
build_operation(
|
||||
'tag', 'tags', _resource_client_factory,
|
||||
[
|
||||
AutoCommandDefinition(TagsOperations.list, '[Tag]'),
|
||||
AutoCommandDefinition(TagsOperations.create_or_update, 'Tag', 'create'),
|
||||
AutoCommandDefinition(TagsOperations.delete, None, 'delete'),
|
||||
AutoCommandDefinition(TagsOperations.create_or_update_value, 'Tag', 'add-value'),
|
||||
AutoCommandDefinition(TagsOperations.delete_value, None, 'remove-value'),
|
||||
],
|
||||
command_table,
|
||||
_patch_aliases({
|
||||
'tag_name': {'name': '--name -n'},
|
||||
'tag_value': {'name': '--value'}
|
||||
}))
|
||||
|
||||
build_operation(
|
||||
'resource group deployment', 'deployments', _resource_client_factory,
|
||||
[
|
||||
AutoCommandDefinition(DeploymentsOperations.list, '[Deployment]'),
|
||||
AutoCommandDefinition(DeploymentsOperations.get, 'Deployment', 'show'),
|
||||
#AutoCommandDefinition(DeploymentsOperations.validate, 'Object'),
|
||||
#AutoCommandDefinition(DeploymentsOperations.delete, 'Object'),
|
||||
AutoCommandDefinition(DeploymentsOperations.check_existence, 'Bool', 'exists'),
|
||||
#AutoCommandDefinition(DeploymentsOperations.cancel, 'Object'),
|
||||
#AutoCommandDefinition(DeploymentsOperations.create_or_update, 'Object', 'create'),
|
||||
],
|
||||
command_table,
|
||||
_patch_aliases({
|
||||
'deployment_name': {'name': '--name -n', 'required': True}
|
||||
}))
|
||||
|
||||
build_operation(
|
||||
'resource group deployment operation', 'deployment_operations', _resource_client_factory,
|
||||
[
|
||||
AutoCommandDefinition(DeploymentOperationsOperations.list, '[DeploymentOperations]'),
|
||||
AutoCommandDefinition(DeploymentOperationsOperations.get, 'DeploymentOperations', 'show')
|
||||
],
|
||||
command_table,
|
||||
_patch_aliases({
|
||||
'deployment_name': {'name': '--name -n', 'required': True}
|
||||
}))
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -6,7 +6,7 @@ interactions:
|
|||
Accept-Encoding: ['gzip, deflate']
|
||||
Connection: [keep-alive]
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
User-Agent: [python/3.5.1 requests/2.9.1 msrest/0.2.0 msrest_azure/0.2.1 resourcemanagementclient/2015-11-01
|
||||
User-Agent: [python/2.7.11 requests/2.9.1 msrest/0.2.0 msrest_azure/0.2.1 resourcemanagementclient/2015-11-01
|
||||
Azure-SDK-For-Python AZURECLI_0.0.32]
|
||||
accept-language: [en-US]
|
||||
method: GET
|
||||
|
@ -17,67 +17,70 @@ interactions:
|
|||
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
|
||||
headers:
|
||||
Cache-Control: [no-cache]
|
||||
Content-Encoding: [gzip]
|
||||
Content-Length: ['3110']
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Date: ['Thu, 07 Apr 2016 22:02:22 GMT']
|
||||
Expires: ['-1']
|
||||
Pragma: [no-cache]
|
||||
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
|
||||
Vary: [Accept-Encoding]
|
||||
cache-control: [no-cache]
|
||||
content-encoding: [gzip]
|
||||
content-length: ['3300']
|
||||
content-type: [application/json; charset=utf-8]
|
||||
date: ['Tue, 03 May 2016 00:01:41 GMT']
|
||||
expires: ['-1']
|
||||
pragma: [no-cache]
|
||||
strict-transport-security: [max-age=31536000; includeSubDomains]
|
||||
vary: [Accept-Encoding]
|
||||
status: {code: 200, message: OK}
|
||||
version: 1
|
||||
|
|
|
@ -6,7 +6,7 @@ interactions:
|
|||
Accept-Encoding: ['gzip, deflate']
|
||||
Connection: [keep-alive]
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.2.0 msrest_azure/0.2.1 resourcemanagementclient/2015-11-01
|
||||
User-Agent: [python/3.5.1 requests/2.9.1 msrest/0.2.0 msrest_azure/0.2.1 resourcemanagementclient/2015-11-01
|
||||
Azure-SDK-For-Python AZURECLI_0.0.32]
|
||||
accept-language: [en-US]
|
||||
method: GET
|
||||
|
@ -35,7 +35,7 @@ interactions:
|
|||
Content-Encoding: [gzip]
|
||||
Content-Length: ['881']
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Date: ['Fri, 29 Apr 2016 19:56:00 GMT']
|
||||
Date: ['Tue, 03 May 2016 21:40:31 GMT']
|
||||
Expires: ['-1']
|
||||
Pragma: [no-cache]
|
||||
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
|
||||
|
@ -48,7 +48,7 @@ interactions:
|
|||
Accept-Encoding: ['gzip, deflate']
|
||||
Connection: [keep-alive]
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.2.0 msrest_azure/0.2.1 resourcemanagementclient/2015-11-01
|
||||
User-Agent: [python/3.5.1 requests/2.9.1 msrest/0.2.0 msrest_azure/0.2.1 resourcemanagementclient/2015-11-01
|
||||
Azure-SDK-For-Python AZURECLI_0.0.32]
|
||||
accept-language: [en-US]
|
||||
method: GET
|
||||
|
@ -77,50 +77,7 @@ interactions:
|
|||
Cache-Control: [no-cache]
|
||||
Content-Encoding: [gzip]
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Date: ['Fri, 29 Apr 2016 19:56:01 GMT']
|
||||
Expires: ['-1']
|
||||
Pragma: [no-cache]
|
||||
Server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
|
||||
Strict-Transport-Security: [max-age=31536000; includeSubDomains]
|
||||
Vary: [Accept-Encoding]
|
||||
status: {code: 200, message: OK}
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept: [application/json]
|
||||
Accept-Encoding: ['gzip, deflate']
|
||||
Connection: [keep-alive]
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
User-Agent: [python/3.5.0 requests/2.9.1 msrest/0.2.0 msrest_azure/0.2.1 resourcemanagementclient/2015-11-01
|
||||
Azure-SDK-For-Python AZURECLI_0.0.32]
|
||||
accept-language: [en-US]
|
||||
method: GET
|
||||
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/XPLATTESTGEXTENSION9085/providers/Microsoft.Compute//virtualMachines/xplatvmExt1314?api-version=2016-03-30
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcpl
|
||||
VmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/In7xb5yk
|
||||
6UerulrldVvkzUePUv6IPrxcnM3oz492sv1PH3x6MNvO7u/vb+/P9qfb2flsuv1w79P7u7s79/J8
|
||||
99OPRvrSPKtnV1mdv6yr86LM6X0FR99dLl4XP8BHH71us+WMWv7+x7sfyde/xABo2qrOLqLvFwv6
|
||||
4lV+ntf5chp8RV+u1pOyaOZ5TZ9/9EUxraumOm+/Wyxn1VXzOq8v8/q0afJlW2RlY9DF81F1ThDx
|
||||
1m0aN2/Xt21K3zRFtUTz3fHOeG9n997uzu6BDtgNmZpWzdOieUst/RFVzZvrFYZpegugL7MFfzct
|
||||
i908y2cPDib3Pp3l5/fu39uumu3d/fv39ncf3r/38OH+/eDFaZ1nbf7lqlXcntXV4gyUDVpdzjH3
|
||||
Hjr02bou6LOP5m27ah7dvftuVWatTte7dv/Te/fGk7KajKdVnY+vBOXxMm+DhtNlS413Hxw8vHsb
|
||||
zMfAwyHhSEboTLPpvFheAKVXeTb7bl20uW3rWn40y9oM5AVvf+/78rH5mogc47RptVit27x+oUTm
|
||||
EVwuTgnze7v7jlAfZbNFsfyqyWszHdkP1nW+pg+8RkqLk2p5Xlys60wpb7ujJiSAlwW45Se/OL4g
|
||||
ZqKv23qdWxjUJF9mkzI/XrfVgiBMv1rRuFhe0dC0M+Oi9k1OM92iQW/QNClXVf3WG7n56Iympz7P
|
||||
pgD8vV8MtKxe+MW/ZPRRQUzx0d1mPWmmdcEc1Nzdmeyef7r/YHd7d3K+s70/m2XbWT69tz2dPNx7
|
||||
sHe+8/D+w527dd5U63qaf15X61UjHPEmb9rPiaT5EgN/uHNw/y71d1nMSG7uWgkevxDM7vYwFCjL
|
||||
Ykow9g/27330S75vRzgrsotl1RCdovM7qar2qWvif0ffCqVpqExaBYnHKKevvqYgOO6UXyy6PG5Q
|
||||
gfiZdCPxMYF/vZ5O83xGiKCVtP0IM5B+E1Pwe798fvzmzenrN5+f/t5vTl+8PvvyxeAUnIg43L0s
|
||||
6nadlV+w4JkJ6IiFVUzRL1vVaDfC1vZlNSVmZ3H5iNBv53nWtFlTZPp9m13w7BFBf8n/A4L7AA3L
|
||||
BgAA
|
||||
headers:
|
||||
Cache-Control: [no-cache]
|
||||
Content-Encoding: [gzip]
|
||||
Content-Type: [application/json; charset=utf-8]
|
||||
Date: ['Fri, 29 Apr 2016 19:56:01 GMT']
|
||||
Date: ['Tue, 03 May 2016 21:40:32 GMT']
|
||||
Expires: ['-1']
|
||||
Pragma: [no-cache]
|
||||
Server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
|
||||
|
|
|
@ -4,7 +4,8 @@ try:
|
|||
except ImportError:
|
||||
from mock import MagicMock
|
||||
|
||||
from azure.cli.command_modules.resource import _resolve_api_version as resolve_api_version
|
||||
from azure.cli.command_modules.resource.custom import _resolve_api_version as resolve_api_version
|
||||
from azure.cli.command_modules.resource._validators import *
|
||||
|
||||
class TestApiCheck(unittest.TestCase):
|
||||
|
||||
|
@ -22,25 +23,27 @@ class TestApiCheck(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_resolve_api_max_priority_option(self):
|
||||
""" Verifies the --api-version parameter has maximum priority. """
|
||||
args = {'api-version': '2015-01-01', 'resource_type': 'Mock/test'}
|
||||
self.assertEqual(resolve_api_version(args, self._get_mock_client()), "2015-01-01")
|
||||
|
||||
def test_resolve_api_provider_backup(self):
|
||||
""" Verifies provider is used as backup if api-version not specified. """
|
||||
args = {'resource_type': 'Mock/test'}
|
||||
self.assertEqual(resolve_api_version(args, self._get_mock_client()), "2016-01-01")
|
||||
resource_type = validate_resource_type('Mock/test')
|
||||
self.assertEqual(resolve_api_version(self._get_mock_client(), resource_type), "2016-01-01")
|
||||
|
||||
def test_resolve_api_provider_with_parent_backup(self):
|
||||
""" Verifies provider (with parent) is used as backup if api-version not specified. """
|
||||
args = {'resource_type': 'Mock/bar', 'parent': 'foo/testfoo123'}
|
||||
self.assertEqual(resolve_api_version(args, self._get_mock_client()), "1999-01-01")
|
||||
resource_type = validate_resource_type('Mock/bar')
|
||||
parent = validate_parent('foo/testfoo123')
|
||||
self.assertEqual(
|
||||
resolve_api_version(self._get_mock_client(), resource_type, parent),
|
||||
"1999-01-01"
|
||||
)
|
||||
|
||||
def test_resolve_api_all_previews(self):
|
||||
""" Verifies most recent preview version returned only if there are no non-preview versions. """
|
||||
args = {'resource_type': 'Mock/preview'}
|
||||
self.assertEqual(resolve_api_version(args, self._get_mock_client()), "2005-01-01-preview")
|
||||
resource_type = validate_resource_type('Mock/preview')
|
||||
self.assertEqual(
|
||||
resolve_api_version(self._get_mock_client(), resource_type),
|
||||
"2005-01-01-preview"
|
||||
)
|
||||
|
||||
def _get_mock_client(self):
|
||||
client = MagicMock()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import unittest
|
||||
from azure.cli.command_modules.resource import _list_resources_odata_filter_builder
|
||||
from azure.cli.command_modules.resource.custom import _list_resources_odata_filter_builder
|
||||
from azure.cli.parser import IncorrectUsageError
|
||||
|
||||
class TestListResources(unittest.TestCase):
|
||||
|
@ -19,50 +19,30 @@ class TestListResources(unittest.TestCase):
|
|||
pass
|
||||
|
||||
def test_tag_name(self):
|
||||
args = {
|
||||
'tag': 'foo'
|
||||
}
|
||||
filter = _list_resources_odata_filter_builder(args)
|
||||
filter = _list_resources_odata_filter_builder(tag='foo')
|
||||
self.assertEqual(filter, "tagname eq 'foo'")
|
||||
|
||||
def test_tag_name_starts_with(self):
|
||||
args = {
|
||||
'tag': 'f*'
|
||||
}
|
||||
filter = _list_resources_odata_filter_builder(args)
|
||||
filter = _list_resources_odata_filter_builder(tag='f*')
|
||||
self.assertEqual(filter, "startswith(tagname, 'f')")
|
||||
|
||||
def test_tag_name_value_equals(self):
|
||||
args = {
|
||||
'tag': 'foo=bar'
|
||||
}
|
||||
filter = _list_resources_odata_filter_builder(args)
|
||||
filter = _list_resources_odata_filter_builder(tag='foo=bar')
|
||||
self.assertEqual(filter, "tagname eq 'foo' and tagvalue eq 'bar'")
|
||||
|
||||
def test_name_location_with_resource_type_equals(self):
|
||||
args = {
|
||||
'name': 'wonky',
|
||||
'location': 'dory',
|
||||
'resource_type': 'resource/type'
|
||||
}
|
||||
filter = _list_resources_odata_filter_builder(args)
|
||||
def test_name_location_equals(self):
|
||||
filter = _list_resources_odata_filter_builder(
|
||||
name='wonky', location='dory', resource_type='resource/type'
|
||||
)
|
||||
self.assertEqual(filter, "name eq 'wonky' and location eq 'dory' and resourceType eq 'resource/type'")
|
||||
|
||||
def test_name_location_equals(self):
|
||||
args = {
|
||||
'name': 'wonky',
|
||||
'location': 'dory'
|
||||
}
|
||||
filter = _list_resources_odata_filter_builder(args)
|
||||
filter = _list_resources_odata_filter_builder(name='wonky', location='dory')
|
||||
self.assertEqual(filter, "name eq 'wonky' and location eq 'dory'")
|
||||
|
||||
def test_tag_and_name_fails(self):
|
||||
args = {
|
||||
'tag': 'foo=bar',
|
||||
'name': 'should not work'
|
||||
}
|
||||
with self.assertRaises(IncorrectUsageError):
|
||||
filter = _list_resources_odata_filter_builder(args)
|
||||
filter = _list_resources_odata_filter_builder(tag='foo=bar', name='should not work')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import unittest
|
||||
from six import StringIO
|
||||
|
||||
from azure.cli.commands._validators import *
|
||||
|
||||
from azure.cli.command_modules.resource._validators import *
|
||||
|
||||
class Test_resource_validators(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
pass
|
||||
|
||||
def setUp(self):
|
||||
self.io = StringIO()
|
||||
|
||||
def tearDown(self):
|
||||
self.io.close()
|
||||
|
||||
def test_resource_type_valid(self):
|
||||
input = 'Test.Namespace/testtype'
|
||||
actual = validate_resource_type(input)
|
||||
self.assertEqual(actual.namespace, 'Test.Namespace')
|
||||
self.assertEqual(actual.type, 'testtype')
|
||||
|
||||
def test_resource_type_invalid(self):
|
||||
pass
|
||||
|
||||
def test_parent_valid(self):
|
||||
input = 'testtype/mytesttype'
|
||||
actual = validate_parent(input)
|
||||
self.assertEqual(actual.type, 'testtype')
|
||||
self.assertEqual(actual.name, 'mytesttype')
|
||||
|
||||
def test_parent_invalid(self):
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -13,10 +13,10 @@ from azure.cli.commands import (CommandTable,
|
|||
RESOURCE_GROUP_ARG_NAME)
|
||||
from azure.cli.commands._command_creation import get_mgmt_service_client, get_data_service_client
|
||||
from azure.cli.commands._auto_command import build_operation, AutoCommandDefinition
|
||||
from azure.cli.commands._validators import validate_key_value_pairs
|
||||
from azure.cli._locale import L
|
||||
|
||||
from ._params import PARAMETER_ALIASES, STORAGE_DATA_CLIENT_ARGS
|
||||
from ._validators import validate_key_value_pairs
|
||||
|
||||
command_table = CommandTable()
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
from os import environ
|
||||
|
||||
from azure.cli.commands import (COMMON_PARAMETERS as GLOBAL_COMMON_PARAMETERS, extend_parameter)
|
||||
from azure.cli.commands._validators import validate_key_value_pairs
|
||||
from azure.cli._locale import L
|
||||
|
||||
from ._validators import (
|
||||
validate_container_permission, validate_datetime, validate_datetime_as_string, validate_id,
|
||||
validate_ip_range, validate_key_value_pairs, validate_resource_types, validate_services,
|
||||
validate_tags, validate_lease_duration, validate_quota)
|
||||
validate_ip_range, validate_resource_types, validate_services, validate_lease_duration,
|
||||
validate_quota)
|
||||
|
||||
# HELPER METHODS
|
||||
|
||||
|
@ -176,13 +177,6 @@ PARAMETER_ALIASES.update({
|
|||
'of request.'),
|
||||
'type': validate_datetime_as_string
|
||||
},
|
||||
'tags' : {
|
||||
'name': '--tags',
|
||||
'metavar': 'TAGS',
|
||||
'help': L('individual and/or key/value pair tags in "a=b;c" format'),
|
||||
'required': False,
|
||||
'type': validate_tags
|
||||
},
|
||||
'timeout': {
|
||||
'name': '--timeout',
|
||||
'help': L('timeout in seconds'),
|
||||
|
|
|
@ -41,14 +41,6 @@ def validate_ip_range(string):
|
|||
raise ValueError
|
||||
return string
|
||||
|
||||
def validate_key_value_pairs(string):
|
||||
''' Validates key-value pairs in the following format: a=b;c=d '''
|
||||
result = None
|
||||
if string:
|
||||
kv_list = [x for x in string.split(';') if '=' in x] # key-value pairs
|
||||
result = dict(x.split('=', 1) for x in kv_list)
|
||||
return result
|
||||
|
||||
def validate_quota(string):
|
||||
''' Validates that share service quota is between 1-5. '''
|
||||
val = int(string)
|
||||
|
@ -69,13 +61,3 @@ def validate_services(string):
|
|||
if set(string) - set("bqtf"):
|
||||
raise ValueError
|
||||
return Services(_str=''.join(set(string)))
|
||||
|
||||
def validate_tags(string):
|
||||
''' Validates the string containers only key-value pairs and single
|
||||
tags in the format: a=b;c '''
|
||||
result = None
|
||||
if string:
|
||||
result = validate_key_value_pairs(string)
|
||||
s_list = [x for x in string.split(';') if '=' not in x] # single values
|
||||
result.update(dict((x, '') for x in s_list))
|
||||
return result
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import argparse
|
||||
import re
|
||||
import os
|
||||
from azure.mgmt.compute import ComputeManagementClient, ComputeManagementClientConfiguration
|
||||
from azure.mgmt.compute.operations import (AvailabilitySetsOperations,
|
||||
VirtualMachineExtensionImagesOperations,
|
||||
VirtualMachineExtensionsOperations,
|
||||
|
@ -11,10 +10,9 @@ from azure.mgmt.compute.operations import (AvailabilitySetsOperations,
|
|||
VirtualMachinesOperations,
|
||||
VirtualMachineScaleSetsOperations,
|
||||
VirtualMachineScaleSetVMsOperations)
|
||||
|
||||
from azure.cli.commands._command_creation import get_mgmt_service_client
|
||||
from azure.cli.commands._auto_command import build_operation, AutoCommandDefinition
|
||||
from azure.cli.commands import CommandTable, LongRunningOperation
|
||||
from azure.cli.commands._command_creation import get_mgmt_service_client
|
||||
from azure.cli._locale import L
|
||||
from azure.cli.command_modules.vm.mgmt.lib import (VMCreationClient as VMClient,
|
||||
VMCreationClientConfiguration
|
||||
|
@ -23,13 +21,10 @@ from azure.cli.command_modules.vm.mgmt.lib.operations import VMOperations
|
|||
from azure.cli._help_files import helps
|
||||
|
||||
from ._params import PARAMETER_ALIASES
|
||||
from .custom import ConvenienceVmCommands
|
||||
from .custom import ConvenienceVmCommands, _compute_client_factory
|
||||
|
||||
command_table = CommandTable()
|
||||
|
||||
def _compute_client_factory(_):
|
||||
return get_mgmt_service_client(ComputeManagementClient, ComputeManagementClientConfiguration)
|
||||
|
||||
def _patch_aliases(alias_items):
|
||||
aliases = PARAMETER_ALIASES.copy()
|
||||
aliases.update(alias_items)
|
||||
|
|
Загрузка…
Ссылка в новой задаче