From 3e5105218976549a0a782f179bb358edfd4e89c9 Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Fri, 19 Feb 2016 18:20:21 -0800 Subject: [PATCH 01/23] Add load_tests / __init__.py to the azure/cli/tests module to allow for simpler unit test discovery --- src/azure/cli/tests/__init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/azure/cli/tests/__init__.py diff --git a/src/azure/cli/tests/__init__.py b/src/azure/cli/tests/__init__.py new file mode 100644 index 000000000..82d46fc17 --- /dev/null +++ b/src/azure/cli/tests/__init__.py @@ -0,0 +1,12 @@ +from .test_argparse import Test_argparse + +from unittest import TestSuite + +test_cases = [Test_argparse] + +def load_tests(loader, tests, pattern): + suite = TestSuite() + for testclass in test_cases: + tests = loader.loadTestsFromTestCase(testclass) + suite.addTests(tests) + return suite From a1c3be88431146e3e37f0d8e9b548af529060e2d Mon Sep 17 00:00:00 2001 From: "Johan Stenberg (MSFT)" Date: Fri, 19 Feb 2016 18:57:39 -0800 Subject: [PATCH 02/23] Create configuring_your_machine.md --- Doc/configuring_your_machine.md | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Doc/configuring_your_machine.md diff --git a/Doc/configuring_your_machine.md b/Doc/configuring_your_machine.md new file mode 100644 index 000000000..f51e4cb1f --- /dev/null +++ b/Doc/configuring_your_machine.md @@ -0,0 +1,72 @@ +Setting up your development environment +======================================== +The Azure Python CLI projects sources are located on GitHub (https://github.com/Azure/azure-cli/). In order to contribute to the project, you are expected to: +- Have a GitHub account. For Microsoft contributors, follow the guidelines on https://opensourcehub.microsoft.com/ to create, configure and link your account +- Fork the https://github.com/Azure/azure-cli/ repository into your private GitHub account +- Create pull requests against the httips://github.com/azure/azure-cli repository to get your code changes merged into the project repository. + +##Preparing your machine ++ Install Python 3.5.x from http://python.org. Please note that the version of Python that comes preinstalled on OSX is 2.7. ++ Clone your repository and check out the master branch ++ Create a new virtual environment “env” for Python 3.5 in the root of your clone. You can do this by running: + +Windows +```BatchFile +python.exe -m venv \env +``` +OSX/Ubuntu +```Shell +python –m venv /env +``` + ++ Activate the env virtual environment by running: + +Windows: +```BatchFile +\env\scripts\activate.bat +``` +OSX/Ubuntu (bash): +```Shell +. /env/bin/activate +``` + ++ Install the latest autorest generated azure sdk. +```Shell +python –m pip install azure==2.0.0a1 +``` ++ Add \src to your PYTHONPATH environment variable: + +Windows: +```BatchFile +set PYTHONPATH=\src;%PYTHONPATH% +``` +OSX/Ubuntu (bash): +```Shell +export PYTHONPATH=/src:${PYTHONPATH} +``` + +##Configuring your IDE +###Visual Studio (Windows only) ++ Install Python Tools for Visual Studio. As of 2/18/2016, the current version (PTVS 2.2) can be found here. ++ Open the azure-cli.pyproj project +You should now be able to launch your project by pressing F5/start debugging + +###Visual Studio Code (Any platform) +Experimental steps – still haven’t been able to get virtual environments to work well with VSCode ++ Install VS Code ++ Install (one of) the python extension(s) (https://marketplace.visualstudio.com/items?itemName=donjayamanne.python) +Debugging should now work (including stepping and setting breakpoints). + +The repo has a launch.json file that will launch the version of Python that is first on your path. + +##Running unit tests: + +###Command line: +If you have configured your PYTHONPATH correctly (see above), you should be able to run all unit tests by executing python -m unittest from your /src directory. + +###VS Code: + + +###Visual Studio + + From 4dc8c1483212abe5c0a32c05ca8a63f58372f4ce Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Thu, 25 Feb 2016 14:26:22 -0800 Subject: [PATCH 03/23] Initial prototype of semi-generated commands --- src/azure/cli/commands/__init__.py | 1 + src/azure/cli/commands/generated.py | 134 ++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 src/azure/cli/commands/generated.py diff --git a/src/azure/cli/commands/__init__.py b/src/azure/cli/commands/__init__.py index 0f92fab95..2bf7c8aae 100644 --- a/src/azure/cli/commands/__init__.py +++ b/src/azure/cli/commands/__init__.py @@ -5,6 +5,7 @@ from .._logging import logging COMMAND_MODULES = [ 'login', 'storage', + 'generated', ] _COMMANDS = {} diff --git a/src/azure/cli/commands/generated.py b/src/azure/cli/commands/generated.py new file mode 100644 index 000000000..d1f81e126 --- /dev/null +++ b/src/azure/cli/commands/generated.py @@ -0,0 +1,134 @@ +import inspect +import azure.mgmt.network +import azure.mgmt.compute + +from ..main import CONFIG, SESSION +from .._logging import logging +from .._util import TableOutput +from ..commands import command, description, option +from .._profile import Profile + +def _network_client_factory(): + from msrestazure.azure_active_directory import UserPassCredentials + + profile = Profile() + configuration = azure.mgmt.network.NetworkManagementClientConfiguration(*profile.get_credentials()) + client = azure.mgmt.network.NetworkManagementClient(configuration) + return client + +def _compute_client_factory(): + from msrestazure.azure_active_directory import UserPassCredentials + + profile = Profile() + configuration = azure.mgmt.compute.ComputeManagementClientConfiguration(*profile.get_credentials()) + client = azure.mgmt.compute.ComputeManagementClient(configuration) + return client + +def _decorate_command(name, func): + return command(name)(func) + +def _decorate_description(desc, func): + return description(desc)(func) + +def _decorate_option(spec, description, func): + return option(spec, description)(func) + +def _make_func(client_factory, member_name, unbound_func): + def call_client(args, unexpected): + client = client_factory() + ops_instance = getattr(client, member_name) + result = unbound_func(ops_instance, **args) + print(result) + return result + return call_client + +def _option_description(op, arg): + return ' '.join([l.split(':')[-1] for l in inspect.getdoc(op).splitlines() if l.startswith(':param') and l.find(arg + ':') != -1]) + +def _operation_builder(package_name, resource_type, member_name, client_type, operations): + excluded_params = ['self', 'raw', 'custom_headers', 'operation_config'] + for operation in operations: + opname = operation.__name__ + sig = inspect.signature(operation) # BUGBUG: only supported in python3 - we should probably switch to argspec + func = _make_func(client_type, member_name, operation) + func = _decorate_command(' '.join([package_name, resource_type, opname]), func) + func = _decorate_description('This is the description of the command...', func) + for arg in [a for a in sig.parameters if not a in excluded_params]: + func = _decorate_option('--%s <%s>' % (arg, arg), _option_description(operation, arg), func=func) + + +_operation_builder("network", + "vnetgateway", + "virtual_network_gateway_connections", + _network_client_factory, + [azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.reset_shared_key, + azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.get, + azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.list, + azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.get_shared_key, + azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.set_shared_key + ]) + +_operation_builder("network", + "vnet", + "virtual_networks", + _network_client_factory, + [azure.mgmt.network.operations.VirtualNetworksOperations.delete, + azure.mgmt.network.operations.VirtualNetworksOperations.get, + azure.mgmt.network.operations.VirtualNetworksOperations.list_all, + azure.mgmt.network.operations.VirtualNetworksOperations.list + ]) + +_operation_builder("network", + "nic", + "network_interfaces", + _network_client_factory, + [azure.mgmt.network.operations.NetworkInterfacesOperations.delete, + azure.mgmt.network.operations.NetworkInterfacesOperations.get, + azure.mgmt.network.operations.NetworkInterfacesOperations.list_virtual_machine_scale_set_vm_network_interfaces, + azure.mgmt.network.operations.NetworkInterfacesOperations.list_virtual_machine_scale_set_network_interfaces, + azure.mgmt.network.operations.NetworkInterfacesOperations.get_virtual_machine_scale_set_network_interface, + azure.mgmt.network.operations.NetworkInterfacesOperations.list_all, + azure.mgmt.network.operations.NetworkInterfacesOperations.list + ]) + +_operation_builder("compute", + "vm", + "virtual_machines", + _compute_client_factory, + [azure.mgmt.compute.operations.VirtualMachinesOperations.list, + azure.mgmt.compute.operations.VirtualMachinesOperations.list_all, + azure.mgmt.compute.operations.VirtualMachinesOperations.start, + azure.mgmt.compute.operations.VirtualMachinesOperations.deallocate, + azure.mgmt.compute.operations.VirtualMachinesOperations.power_off + ]) + +_operation_builder("compute", + "vmscaleset", + "virtual_machine_scalesets", + _compute_client_factory, + [azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.deallocate, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete_instances, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get_instance_view, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_all, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_skus, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.power_off, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.restart, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.start, + azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.update_instances, + ]) + + +_operation_builder("compute", + "images", + "virtual_machine_images", + _compute_client_factory, + [azure.mgmt.compute.operations.VirtualMachineImagesOperations.get, + azure.mgmt.compute.operations.VirtualMachineImagesOperations.list, + azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_offers, + azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_publishers, + azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_skus, + ]) + From ed57ff1d16932a0a669137c3684945c5feef44ef Mon Sep 17 00:00:00 2001 From: Derek Bekoe Date: Fri, 26 Feb 2016 15:10:27 -0800 Subject: [PATCH 04/23] Load the python module in CI to catch import errors The command returns 0 if successful, 1 otherwise. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index adbf848c3..feabc1101 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,5 @@ install: - pip install azure==2.0.0a1 script: - export PYTHONPATH=$PATHONPATH:./src - - python -m unittest discover -s src/azure/cli/tests \ No newline at end of file + - python -m azure.cli + - python -m unittest discover -s src/azure/cli/tests From 1275535f3ed72d11dead1bbfabc2c30d56372ec1 Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Fri, 26 Feb 2016 18:26:40 -0800 Subject: [PATCH 05/23] Split vm from network commands, use service client factory and add support for python2.7 --- azure-cli.pyproj | 8 +++ src/azure/cli/commands/__init__.py | 6 +- src/azure/cli/commands/_auto_command.py | 51 +++++++++++++ src/azure/cli/commands/generated.py | 85 ---------------------- src/azure/cli/commands/vm.py | 96 +++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 88 deletions(-) create mode 100644 src/azure/cli/commands/_auto_command.py create mode 100644 src/azure/cli/commands/vm.py diff --git a/azure-cli.pyproj b/azure-cli.pyproj index 0fa304524..d3910aa64 100644 --- a/azure-cli.pyproj +++ b/azure-cli.pyproj @@ -14,6 +14,8 @@ Standard Python launcher {1dd9c42b-5980-42ce-a2c3-46d3bf0eede4} 3.5 + vm extensions get + False @@ -22,10 +24,15 @@ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets + + Code + + + @@ -43,6 +50,7 @@ Code + Code diff --git a/src/azure/cli/commands/__init__.py b/src/azure/cli/commands/__init__.py index 0c007c0eb..6e05a664d 100644 --- a/src/azure/cli/commands/__init__.py +++ b/src/azure/cli/commands/__init__.py @@ -3,12 +3,12 @@ from .._logging import logger # TODO: Alternatively, simply scan the directory for all modules COMMAND_MODULES = [ + 'account', 'login', 'logout', - 'account', - 'storage', - 'generated', 'resourcegroup', + 'storage', + 'vm', ] _COMMANDS = {} diff --git a/src/azure/cli/commands/_auto_command.py b/src/azure/cli/commands/_auto_command.py new file mode 100644 index 000000000..b57439a96 --- /dev/null +++ b/src/azure/cli/commands/_auto_command.py @@ -0,0 +1,51 @@ +import inspect +import sys +from msrest import Serializer +from ..main import CONFIG, SESSION +from ..commands import command, description, option +from .._logging import logger + +def _decorate_command(name, func): + return command(name)(func) + +def _decorate_description(desc, func): + return description(desc)(func) + +def _decorate_option(spec, description, func): + return option(spec, description)(func) + +def _make_func(client_factory, member_name, return_type_name, unbound_func): + def call_client(args, unexpected): + client = client_factory() + ops_instance = getattr(client, member_name) + try: + result = unbound_func(ops_instance, **args) + if not return_type_name: + return {} + return Serializer().serialize_data(result, return_type_name) + except TypeError as e: + logger.warn(e) + + return call_client + +def _option_description(op, arg): + return ' '.join([l.split(':')[-1] for l in inspect.getdoc(op).splitlines() if l.startswith(':param') and l.find(arg + ':') != -1]) + +def _operation_builder(package_name, resource_type, member_name, client_type, operations): + excluded_params = ['self', 'raw', 'custom_headers', 'operation_config'] + for operation, return_type_name in operations: + opname = operation.__name__ + func = _make_func(client_type, member_name, return_type_name, operation) + func = _decorate_command(' '.join([package_name, resource_type, opname]), func) + func = _decorate_description('This is the description of the command...', func) + + args = [] + try: + sig = inspect.signature(operation) # only supported in python3 - falling back to argspec if not available + args = sig.parameters + except AttributeError: + sig = inspect.getargspec(operation) + args = sig.args + + for arg in [a for a in args if not a in excluded_params]: + func = _decorate_option('--%s <%s>' % (arg, arg), _option_description(operation, arg), func=func) diff --git a/src/azure/cli/commands/generated.py b/src/azure/cli/commands/generated.py index d1f81e126..7505dafcb 100644 --- a/src/azure/cli/commands/generated.py +++ b/src/azure/cli/commands/generated.py @@ -1,10 +1,6 @@ -import inspect import azure.mgmt.network import azure.mgmt.compute -from ..main import CONFIG, SESSION -from .._logging import logging -from .._util import TableOutput from ..commands import command, description, option from .._profile import Profile @@ -16,46 +12,6 @@ def _network_client_factory(): client = azure.mgmt.network.NetworkManagementClient(configuration) return client -def _compute_client_factory(): - from msrestazure.azure_active_directory import UserPassCredentials - - profile = Profile() - configuration = azure.mgmt.compute.ComputeManagementClientConfiguration(*profile.get_credentials()) - client = azure.mgmt.compute.ComputeManagementClient(configuration) - return client - -def _decorate_command(name, func): - return command(name)(func) - -def _decorate_description(desc, func): - return description(desc)(func) - -def _decorate_option(spec, description, func): - return option(spec, description)(func) - -def _make_func(client_factory, member_name, unbound_func): - def call_client(args, unexpected): - client = client_factory() - ops_instance = getattr(client, member_name) - result = unbound_func(ops_instance, **args) - print(result) - return result - return call_client - -def _option_description(op, arg): - return ' '.join([l.split(':')[-1] for l in inspect.getdoc(op).splitlines() if l.startswith(':param') and l.find(arg + ':') != -1]) - -def _operation_builder(package_name, resource_type, member_name, client_type, operations): - excluded_params = ['self', 'raw', 'custom_headers', 'operation_config'] - for operation in operations: - opname = operation.__name__ - sig = inspect.signature(operation) # BUGBUG: only supported in python3 - we should probably switch to argspec - func = _make_func(client_type, member_name, operation) - func = _decorate_command(' '.join([package_name, resource_type, opname]), func) - func = _decorate_description('This is the description of the command...', func) - for arg in [a for a in sig.parameters if not a in excluded_params]: - func = _decorate_option('--%s <%s>' % (arg, arg), _option_description(operation, arg), func=func) - _operation_builder("network", "vnetgateway", @@ -91,44 +47,3 @@ _operation_builder("network", azure.mgmt.network.operations.NetworkInterfacesOperations.list ]) -_operation_builder("compute", - "vm", - "virtual_machines", - _compute_client_factory, - [azure.mgmt.compute.operations.VirtualMachinesOperations.list, - azure.mgmt.compute.operations.VirtualMachinesOperations.list_all, - azure.mgmt.compute.operations.VirtualMachinesOperations.start, - azure.mgmt.compute.operations.VirtualMachinesOperations.deallocate, - azure.mgmt.compute.operations.VirtualMachinesOperations.power_off - ]) - -_operation_builder("compute", - "vmscaleset", - "virtual_machine_scalesets", - _compute_client_factory, - [azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.deallocate, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete_instances, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get_instance_view, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_all, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_skus, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.power_off, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.restart, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.start, - azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.update_instances, - ]) - - -_operation_builder("compute", - "images", - "virtual_machine_images", - _compute_client_factory, - [azure.mgmt.compute.operations.VirtualMachineImagesOperations.get, - azure.mgmt.compute.operations.VirtualMachineImagesOperations.list, - azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_offers, - azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_publishers, - azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_skus, - ]) - diff --git a/src/azure/cli/commands/vm.py b/src/azure/cli/commands/vm.py new file mode 100644 index 000000000..5cb579447 --- /dev/null +++ b/src/azure/cli/commands/vm.py @@ -0,0 +1,96 @@ +import azure.mgmt.compute + +from ._command_creation import get_service_client + +from ..commands import _auto_command +from .._profile import Profile + +def _compute_client_factory(): + return get_service_client(azure.mgmt.compute.ComputeManagementClient, azure.mgmt.compute.ComputeManagementClientConfiguration) + +_auto_command._operation_builder("vm", + "availabilityset", + "availability_sets", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.AvailabilitySetsOperations.delete, None), + (azure.mgmt.compute.operations.AvailabilitySetsOperations.get, 'AvailabilitySet'), + (azure.mgmt.compute.operations.AvailabilitySetsOperations.list, '[AvailabilitySet]'), + (azure.mgmt.compute.operations.AvailabilitySetsOperations.list_available_sizes, '[VirtualMachineSize]') + ]) + + +_auto_command._operation_builder("vm", + "machineextensionimages", + "virtual_machine_extension_images", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.VirtualMachineExtensionImagesOperations.get, 'VirtualMachineExtensionImage'), + (azure.mgmt.compute.operations.VirtualMachineExtensionImagesOperations.list_types, '[VirtualMachineImageResource]'), + (azure.mgmt.compute.operations.VirtualMachineExtensionImagesOperations.list_versions, '[VirtualMachineImageResource]'), + ]) + +_auto_command._operation_builder("vm", + "extensions", + "virtual_machine_extensions", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.VirtualMachineExtensionsOperations.delete, None), + (azure.mgmt.compute.operations.VirtualMachineExtensionsOperations.get, 'VirtualMachineExtension'), + ]) + +_auto_command._operation_builder("vm", + "image", + "virtual_machine_images", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.VirtualMachineImagesOperations.get, 'VirtualMachineImage'), + (azure.mgmt.compute.operations.VirtualMachineImagesOperations.list, '[VirtualMachineImageResource]'), + (azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_offers, '[VirtualMachineImageResource]'), + (azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_publishers, '[VirtualMachineImageResource]'), + (azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_skus, '[VirtualMachineImageResource]'), + ]) + +# TODO: VM UsageOperations + +# TODO: VM SizeOperations + +_auto_command._operation_builder("vm", + "operations", + "virtual_machines", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.VirtualMachinesOperations.delete, None), + (azure.mgmt.compute.operations.VirtualMachinesOperations.deallocate, None), + (azure.mgmt.compute.operations.VirtualMachinesOperations.generalize, None), + (azure.mgmt.compute.operations.VirtualMachinesOperations.get, 'VirtualMachine'), + (azure.mgmt.compute.operations.VirtualMachinesOperations.list, '[VirtualMachine]'), + (azure.mgmt.compute.operations.VirtualMachinesOperations.list_all, '[VirtualMachine]'), + (azure.mgmt.compute.operations.VirtualMachinesOperations.list_available_sizes, '[VirtualMachineSize]'), + (azure.mgmt.compute.operations.VirtualMachinesOperations.power_off, None), + (azure.mgmt.compute.operations.VirtualMachinesOperations.restart, None), + (azure.mgmt.compute.operations.VirtualMachinesOperations.start, None), + ]) + +if False: + _auto_command._operation_builder("vm", + "scaleset", + "virtual_machine_scalesets", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.deallocate, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get, 'VirtualMachineScaleSet'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete_instances, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get_instance_view, 'VirtualMachineScaleSetInstanceView'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list, '[VirtualMachineScaleSet]'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_all, '[VirtualMachineScaleSet]'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_skus, '[VirtualMachineScaleSet]'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.power_off, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.restart, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.start, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.update_instances, None), + ]) + + +# TODO: VirtualMachineScaleSetVMsOperations \ No newline at end of file From 3556fc93b131c551afe38b3472c641546ab90d80 Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Sat, 27 Feb 2016 11:09:41 -0800 Subject: [PATCH 06/23] Undo addition of __init__.py for tests... --- src/azure/cli/tests/__init__.py | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 src/azure/cli/tests/__init__.py diff --git a/src/azure/cli/tests/__init__.py b/src/azure/cli/tests/__init__.py deleted file mode 100644 index 82d46fc17..000000000 --- a/src/azure/cli/tests/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .test_argparse import Test_argparse - -from unittest import TestSuite - -test_cases = [Test_argparse] - -def load_tests(loader, tests, pattern): - suite = TestSuite() - for testclass in test_cases: - tests = loader.loadTestsFromTestCase(testclass) - suite.addTests(tests) - return suite From feec1b1a4d6b41e77f157af83e80f0bc8191a932 Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Sat, 27 Feb 2016 11:13:11 -0800 Subject: [PATCH 07/23] Change casing of doc folder --- {Doc => doc}/configuring_your_machine.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {Doc => doc}/configuring_your_machine.md (100%) diff --git a/Doc/configuring_your_machine.md b/doc/configuring_your_machine.md similarity index 100% rename from Doc/configuring_your_machine.md rename to doc/configuring_your_machine.md From f8cf1f3f25a16879bb2a2a617277b7ec007b7354 Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Sat, 27 Feb 2016 12:58:30 -0800 Subject: [PATCH 08/23] Add basic tests for autocommand --- azure-cli.pyproj | 3 + src/azure/cli/tests/test_autocommand.py | 77 +++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/azure/cli/tests/test_autocommand.py diff --git a/azure-cli.pyproj b/azure-cli.pyproj index d3910aa64..486697e4b 100644 --- a/azure-cli.pyproj +++ b/azure-cli.pyproj @@ -38,6 +38,9 @@ Code + + Code + Code diff --git a/src/azure/cli/tests/test_autocommand.py b/src/azure/cli/tests/test_autocommand.py new file mode 100644 index 000000000..ec56f5384 --- /dev/null +++ b/src/azure/cli/tests/test_autocommand.py @@ -0,0 +1,77 @@ +import logging +import unittest + +from azure.cli.commands._auto_command import _decorate_command, _decorate_option, _decorate_description, _operation_builder +from azure.cli.commands import _COMMANDS + +class Test_autocommand(unittest.TestCase): + @classmethod + def setUpClass(cls): + # Ensure initialization has occurred correctly + import azure.cli.main + logging.basicConfig(level=logging.DEBUG) + + @classmethod + def tearDownClass(cls): + logging.shutdown() + + def test_raw_register_command(self): + command_name = 'da command' + def testfunc(): + return testfunc + + # Run test code + _decorate_command(command_name, testfunc) + + # Verify + registered_command =_COMMANDS.get(testfunc, None) + self.assertIsNotNone(registered_command) + self.assertFalse('args' in registered_command.keys()) + self.assertEqual(registered_command['name'], command_name) + + def test_raw_register_command_with_one_option(self): + command_name = 'da command with one arg' + def testfunc(): + return testfunc + + # Run test code + func = _decorate_command(command_name, testfunc) + spec = '--tre ' + desc = 'Kronor' + func = _decorate_option(spec, desc, func) + + # Verify + registered_command =_COMMANDS.get(testfunc, None) + self.assertIsNotNone(registered_command) + self.assertEqual(registered_command['name'], command_name) + self.assertEqual(len(registered_command['args']), 1) + self.assertEqual(registered_command['args'][0], (spec, desc)) + + def test_load_test_commands(self): + import sys + from azure.cli._argparse import ArgumentParser + from azure.cli.commands import add_to_parser + + # sneaky trick to avoid loading any command modules... + sys.modules['azure.cli.commands.test'] = sys + + command_name = 'da command with one arg and unexpected' + def testfunc(args, _): + # Check that the argument passing actually works... + self.assertEqual(args['tre'], 'wombat') + return testfunc + + # Run test code + func = _decorate_command(command_name, testfunc) + spec = '--tre ' + desc = 'Kronor' + func = _decorate_option(spec, desc, func) + + p = ArgumentParser('automcommandtest') + add_to_parser(p, 'test') + + result = p.execute(command_name.split(' ') + '--tre wombat'.split(' ')) + self.assertEqual(result, func) + +if __name__ == '__main__': + unittest.main() From fffd63068126a0296e6bfe5ce62320d1a535744b Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Sat, 27 Feb 2016 15:57:04 -0800 Subject: [PATCH 09/23] Add auto generated network commands --- azure-cli.pyproj | 4 +- src/azure/cli/_argparse.py | 2 +- src/azure/cli/commands/_auto_command.py | 8 +- src/azure/cli/commands/generated.py | 49 ------ src/azure/cli/commands/network.py | 224 ++++++++++++++++++++++++ src/azure/cli/commands/vm.py | 73 +++++--- 6 files changed, 281 insertions(+), 79 deletions(-) delete mode 100644 src/azure/cli/commands/generated.py create mode 100644 src/azure/cli/commands/network.py diff --git a/azure-cli.pyproj b/azure-cli.pyproj index 486697e4b..bce66fdf1 100644 --- a/azure-cli.pyproj +++ b/azure-cli.pyproj @@ -24,12 +24,10 @@ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets - - Code - + diff --git a/src/azure/cli/_argparse.py b/src/azure/cli/_argparse.py index 5e0e7f9c3..2e46c9186 100644 --- a/src/azure/cli/_argparse.py +++ b/src/azure/cli/_argparse.py @@ -208,7 +208,7 @@ class ArgumentParser(object): return handler(parsed, others) except IncorrectUsageError as ex: print(str(ex), file=out) - return self.display_usage(nouns, m, args, out) + return self._display_usage(nouns, m, args, out) finally: sys.stdout = old_stdout diff --git a/src/azure/cli/commands/_auto_command.py b/src/azure/cli/commands/_auto_command.py index b57439a96..454648a8b 100644 --- a/src/azure/cli/commands/_auto_command.py +++ b/src/azure/cli/commands/_auto_command.py @@ -4,6 +4,7 @@ from msrest import Serializer from ..main import CONFIG, SESSION from ..commands import command, description, option from .._logging import logger +from azure.cli._argparse import IncorrectUsageError def _decorate_command(name, func): return command(name)(func) @@ -24,11 +25,16 @@ def _make_func(client_factory, member_name, return_type_name, unbound_func): return {} return Serializer().serialize_data(result, return_type_name) except TypeError as e: - logger.warn(e) + # TODO: Evaluate required/missing parameters and provide specific + # usage for missing params... + raise IncorrectUsageError(e) return call_client def _option_description(op, arg): + """Pull out parameter help from doccomments of the command + """ + # TODO: We are currently doing this for every option/argument. We should do it (at most) once for a given command... return ' '.join([l.split(':')[-1] for l in inspect.getdoc(op).splitlines() if l.startswith(':param') and l.find(arg + ':') != -1]) def _operation_builder(package_name, resource_type, member_name, client_type, operations): diff --git a/src/azure/cli/commands/generated.py b/src/azure/cli/commands/generated.py deleted file mode 100644 index 7505dafcb..000000000 --- a/src/azure/cli/commands/generated.py +++ /dev/null @@ -1,49 +0,0 @@ -import azure.mgmt.network -import azure.mgmt.compute - -from ..commands import command, description, option -from .._profile import Profile - -def _network_client_factory(): - from msrestazure.azure_active_directory import UserPassCredentials - - profile = Profile() - configuration = azure.mgmt.network.NetworkManagementClientConfiguration(*profile.get_credentials()) - client = azure.mgmt.network.NetworkManagementClient(configuration) - return client - - -_operation_builder("network", - "vnetgateway", - "virtual_network_gateway_connections", - _network_client_factory, - [azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.reset_shared_key, - azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.get, - azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.list, - azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.get_shared_key, - azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.set_shared_key - ]) - -_operation_builder("network", - "vnet", - "virtual_networks", - _network_client_factory, - [azure.mgmt.network.operations.VirtualNetworksOperations.delete, - azure.mgmt.network.operations.VirtualNetworksOperations.get, - azure.mgmt.network.operations.VirtualNetworksOperations.list_all, - azure.mgmt.network.operations.VirtualNetworksOperations.list - ]) - -_operation_builder("network", - "nic", - "network_interfaces", - _network_client_factory, - [azure.mgmt.network.operations.NetworkInterfacesOperations.delete, - azure.mgmt.network.operations.NetworkInterfacesOperations.get, - azure.mgmt.network.operations.NetworkInterfacesOperations.list_virtual_machine_scale_set_vm_network_interfaces, - azure.mgmt.network.operations.NetworkInterfacesOperations.list_virtual_machine_scale_set_network_interfaces, - azure.mgmt.network.operations.NetworkInterfacesOperations.get_virtual_machine_scale_set_network_interface, - azure.mgmt.network.operations.NetworkInterfacesOperations.list_all, - azure.mgmt.network.operations.NetworkInterfacesOperations.list - ]) - diff --git a/src/azure/cli/commands/network.py b/src/azure/cli/commands/network.py new file mode 100644 index 000000000..b39730d94 --- /dev/null +++ b/src/azure/cli/commands/network.py @@ -0,0 +1,224 @@ +import azure.mgmt.network + +from ._command_creation import get_service_client + +from ..commands import _auto_command +from .._profile import Profile + +def _network_client_factory(): + return get_service_client(azure.mgmt.network.NetworkManagementClient, azure.mgmt.network.NetworkManagementClientConfiguration) + +# Application gateways +_auto_command._operation_builder("network", + "appgateway", + "application_gateways", + _network_client_factory, + [ + (azure.mgmt.network.operations.ApplicationGatewaysOperations.delete, None), + (azure.mgmt.network.operations.ApplicationGatewaysOperations.get, 'ApplicationGateway'), + (azure.mgmt.network.operations.ApplicationGatewaysOperations.list, '[ApplicationGateway]'), + (azure.mgmt.network.operations.ApplicationGatewaysOperations.list_all, '[ApplicationGateway]'), + (azure.mgmt.network.operations.ApplicationGatewaysOperations.start, None), + (azure.mgmt.network.operations.ApplicationGatewaysOperations.stop, None), + ]) + +# ExpressRouteCircuitAuthorizationsOperations +_auto_command._operation_builder("network", + "expressroutecircuitauth", + "express_route_circuit_authorizations", + _network_client_factory, + [ + (azure.mgmt.network.operations.ExpressRouteCircuitAuthorizationsOperations.delete, None), + (azure.mgmt.network.operations.ExpressRouteCircuitAuthorizationsOperations.get, 'ExpressRouteCircuitAuthorization'), + (azure.mgmt.network.operations.ExpressRouteCircuitAuthorizationsOperations.list, '[ExpressRouteCircuitAuthorization]'), + ]) + +# ExpressRouteCircuitPeeringsOperations +_auto_command._operation_builder("network", + "expressroutecircuitpeering", + "express_route_circuit_peerings", + _network_client_factory, + [ + (azure.mgmt.network.operations.ExpressRouteCircuitPeeringsOperations.delete, None), + (azure.mgmt.network.operations.ExpressRouteCircuitPeeringsOperations.get, 'ExpressRouteCircuitPeering'), + (azure.mgmt.network.operations.ExpressRouteCircuitPeeringsOperations.list, '[ExpressRouteCircuitPeering]'), + ]) + +# ExpressRouteCircuitsOperations +_auto_command._operation_builder("network", + "expressroutecircuit", + "express_route_circuits", + _network_client_factory, + [ + (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.delete, None), + (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.get, 'ExpressRouteCircuit'), + (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list_arp_table, '[ExpressRouteCircuitArpTable]'), + (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list_routes_table, '[ExpressRouteCircuitRoutesTable]'), + (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list_stats, '[ExpressRouteCircuitStats]'), + (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list, '[ExpressRouteCircuit]'), + (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list_all, '[ExpressRouteCircuit]'), + ]) + +# ExpressRouteServiceProvidersOperations +_auto_command._operation_builder("network", + "expressroutesp", + "express_route_service_providers", + _network_client_factory, + [ + (azure.mgmt.network.operations.ExpressRouteServiceProvidersOperations.list, '[ExpressRouteServiceProvider]'), + ]) + +# LoadBalancersOperations +_auto_command._operation_builder("network", + "loadbalancer", + "load_balancers", + _network_client_factory, + [ + (azure.mgmt.network.operations.LoadBalancersOperations.delete, None), + (azure.mgmt.network.operations.LoadBalancersOperations.get, 'LoadBalancer'), + (azure.mgmt.network.operations.LoadBalancersOperations.list_all, '[LoadBalancer]'), + (azure.mgmt.network.operations.LoadBalancersOperations.list, '[LoadBalancer]'), + ]) + +# LocalNetworkGatewaysOperations +_auto_command._operation_builder("network", + "localgateways", + "local_network_gateways", + _network_client_factory, + [ + (azure.mgmt.network.operations.LocalNetworkGatewaysOperations.get, 'LocalNetworkGateway'), + (azure.mgmt.network.operations.LocalNetworkGatewaysOperations.delete, None), + (azure.mgmt.network.operations.LocalNetworkGatewaysOperations.list, '[LocalNetworkGateway]'), + ]) + + +# NetworkInterfacesOperations +_auto_command._operation_builder("network", + "nic", + "network_interfaces", + _network_client_factory, + [ + (azure.mgmt.network.operations.NetworkInterfacesOperations.delete, None), + (azure.mgmt.network.operations.NetworkInterfacesOperations.get, 'NetworkInterface'), + (azure.mgmt.network.operations.NetworkInterfacesOperations.list_virtual_machine_scale_set_vm_network_interfaces, '[NetworkInterface]'), + (azure.mgmt.network.operations.NetworkInterfacesOperations.list_virtual_machine_scale_set_network_interfaces, '[NetworkInterface]'), + (azure.mgmt.network.operations.NetworkInterfacesOperations.get_virtual_machine_scale_set_network_interface, 'NetworkInterface'), + (azure.mgmt.network.operations.NetworkInterfacesOperations.list_all, '[NetworkInterface]'), + (azure.mgmt.network.operations.NetworkInterfacesOperations.list, '[NetworkInterface]'), + ]) + +# NetworkSecurityGroupsOperations +_auto_command._operation_builder("network", + "securitygroup", + "network_security_groups", + _network_client_factory, + [ + (azure.mgmt.network.operations.NetworkSecurityGroupsOperations.delete, None), + (azure.mgmt.network.operations.NetworkSecurityGroupsOperations.delete, 'NetworkSecurityGroup'), + (azure.mgmt.network.operations.NetworkSecurityGroupsOperations.list_all, '[NetworkSecurityGroup]'), + (azure.mgmt.network.operations.NetworkSecurityGroupsOperations.list, '[NetworkSecurityGroup]'), + ]) + +# PublicIPAddressesOperations +_auto_command._operation_builder("network", + "publicipaddress", + "public_ip_addresses", + _network_client_factory, + [ + (azure.mgmt.network.operations.PublicIPAddressesOperations.delete, None), + (azure.mgmt.network.operations.PublicIPAddressesOperations.get, 'PublicIPAddress'), + (azure.mgmt.network.operations.PublicIPAddressesOperations.list_all, '[PublicIPAddress]'), + (azure.mgmt.network.operations.PublicIPAddressesOperations.list, '[PublicIPAddress]'), + ]) + +# RouteTablesOperations +_auto_command._operation_builder("network", + "routetable", + "route_tables", + _network_client_factory, + [ + (azure.mgmt.network.operations.RouteTablesOperations.delete, None), + (azure.mgmt.network.operations.RouteTablesOperations.get, 'RouteTable'), + (azure.mgmt.network.operations.RouteTablesOperations.list, '[RouteTable]'), + (azure.mgmt.network.operations.RouteTablesOperations.list_all, '[RouteTable]'), + ]) + +# RoutesOperations +_auto_command._operation_builder("network", + "routeoperation", + "routes", + _network_client_factory, + [ + (azure.mgmt.network.operations.RoutesOperations.delete, None), + (azure.mgmt.network.operations.RoutesOperations.get, 'Route'), + (azure.mgmt.network.operations.RoutesOperations.list, '[Route]'), + ]) + +# SecurityRulesOperations +_auto_command._operation_builder("network", + "securityrules", + "security_rules", + _network_client_factory, + [ + (azure.mgmt.network.operations.SecurityRulesOperations.delete, None), + (azure.mgmt.network.operations.SecurityRulesOperations.get, 'SecurityRule'), + (azure.mgmt.network.operations.SecurityRulesOperations.list, '[SecurityRule]'), + ]) + +# SubnetsOperations +_auto_command._operation_builder("network", + "subnet", + "subnets", + _network_client_factory, + [ + (azure.mgmt.network.operations.SubnetsOperations.delete, None), + (azure.mgmt.network.operations.SubnetsOperations.get, 'Subnet'), + (azure.mgmt.network.operations.SubnetsOperations.list, '[Subnet]'), + ]) + +# UsagesOperations +_auto_command._operation_builder("network", + "usage", + "usages", + _network_client_factory, + [ + (azure.mgmt.network.operations.UsagesOperations.list, '[Usage]'), + ]) + +# VirtualNetworkGatewayConnectionsOperations +_auto_command._operation_builder("network", + "vnetgatewayconnection", + "virtual_network_gateway_connections", + _network_client_factory, + [ + (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.delete, None), + (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.get, 'VirtualNetworkGatewayConnection'), + (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.get_shared_key, 'ConnectionSharedKeyResult'), + (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.list, '[VirtualNetworkGatewayConnection]'), + (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.reset_shared_key, 'ConnectionResetSharedKey'), + (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.set_shared_key, 'ConnectionSharedKey'), + ]) + +# VirtualNetworkGatewaysOperations +_auto_command._operation_builder("network", + "vnetgateway", + "virtual_network_gateways", + _network_client_factory, + [ + (azure.mgmt.network.operations.VirtualNetworkGatewaysOperations.delete, None), + (azure.mgmt.network.operations.VirtualNetworkGatewaysOperations.get, 'VirtualNetworkGateway'), + (azure.mgmt.network.operations.VirtualNetworkGatewaysOperations.list, '[VirtualNetworkGateway]'), + (azure.mgmt.network.operations.VirtualNetworkGatewaysOperations.reset, 'VirtualNetworkGateway'), + ]) + +# VirtualNetworksOperations +_auto_command._operation_builder("network", + "vnet", + "virtual_networks", + _network_client_factory, + [ + (azure.mgmt.network.operations.VirtualNetworksOperations.delete, None), + (azure.mgmt.network.operations.VirtualNetworksOperations.get, 'VirtualNetwork'), + (azure.mgmt.network.operations.VirtualNetworksOperations.list, '[VirtualNetwork]'), + (azure.mgmt.network.operations.VirtualNetworksOperations.list_all, '[VirtualNetwork]'), + ]) diff --git a/src/azure/cli/commands/vm.py b/src/azure/cli/commands/vm.py index 5cb579447..b9ce85847 100644 --- a/src/azure/cli/commands/vm.py +++ b/src/azure/cli/commands/vm.py @@ -51,12 +51,24 @@ _auto_command._operation_builder("vm", (azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_skus, '[VirtualMachineImageResource]'), ]) -# TODO: VM UsageOperations - -# TODO: VM SizeOperations +_auto_command._operation_builder("vm", + "usage", + "usage", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.UsageOperations.list, '[Usage]'), + ]) _auto_command._operation_builder("vm", - "operations", + "size", + "virtual_machine_sizes", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.VirtualMachineSizesOperations.list, '[VirtualMachineSize]'), + ]) + +_auto_command._operation_builder("vm", + "", "virtual_machines", _compute_client_factory, [ @@ -72,25 +84,36 @@ _auto_command._operation_builder("vm", (azure.mgmt.compute.operations.VirtualMachinesOperations.start, None), ]) -if False: - _auto_command._operation_builder("vm", - "scaleset", - "virtual_machine_scalesets", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.deallocate, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get, 'VirtualMachineScaleSet'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete_instances, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get_instance_view, 'VirtualMachineScaleSetInstanceView'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list, '[VirtualMachineScaleSet]'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_all, '[VirtualMachineScaleSet]'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_skus, '[VirtualMachineScaleSet]'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.power_off, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.restart, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.start, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.update_instances, None), - ]) +_auto_command._operation_builder("vm", + "scaleset", + "virtual_machine_scale_sets", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.deallocate, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get, 'VirtualMachineScaleSet'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete_instances, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get_instance_view, 'VirtualMachineScaleSetInstanceView'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list, '[VirtualMachineScaleSet]'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_all, '[VirtualMachineScaleSet]'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_skus, '[VirtualMachineScaleSet]'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.power_off, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.restart, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.start, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.update_instances, None), + ]) - -# TODO: VirtualMachineScaleSetVMsOperations \ No newline at end of file +_auto_command._operation_builder("vm", + "vmscaleset", + "virtual_machine_scale_set_vms", + _compute_client_factory, + [ + (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.deallocate, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.delete, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.get, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.get_instance_view, 'VirtualMachineScaleSetVMInstanceView'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.list, '[VirtualMachineScaleSetVM]'), + (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.power_off, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.restart, None), + (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.start, None), + ]) \ No newline at end of file From e9b40d41947126a4af35f50fec2442be635cfc6b Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Sat, 27 Feb 2016 16:09:26 -0800 Subject: [PATCH 10/23] Rename loadbalancer to lb --- src/azure/cli/commands/network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure/cli/commands/network.py b/src/azure/cli/commands/network.py index b39730d94..be5b8f8b2 100644 --- a/src/azure/cli/commands/network.py +++ b/src/azure/cli/commands/network.py @@ -70,7 +70,7 @@ _auto_command._operation_builder("network", # LoadBalancersOperations _auto_command._operation_builder("network", - "loadbalancer", + "lb", "load_balancers", _network_client_factory, [ From fce8297f347f101ab3515605b68518b6f3902e66 Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Sat, 27 Feb 2016 16:23:04 -0800 Subject: [PATCH 11/23] Add missing network entry to COMMAND_MODULES --- src/azure/cli/commands/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/azure/cli/commands/__init__.py b/src/azure/cli/commands/__init__.py index 6e05a664d..f4172e18b 100644 --- a/src/azure/cli/commands/__init__.py +++ b/src/azure/cli/commands/__init__.py @@ -6,6 +6,7 @@ COMMAND_MODULES = [ 'account', 'login', 'logout', + 'network', 'resourcegroup', 'storage', 'vm', From 39f4ac0cfa47438d17cdc1a37d3481b0ca20899d Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Sat, 27 Feb 2016 16:50:47 -0800 Subject: [PATCH 12/23] add simple az shell wrapper to launch CLI --- az | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 az diff --git a/az b/az new file mode 100755 index 000000000..67012eaa1 --- /dev/null +++ b/az @@ -0,0 +1,13 @@ +#!/bin/bash + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +export PYTHONPATH="${DIR}/src:${PYTHONPATH}" + +python -m azure.cli "$@" From 96b1c769ae084c7b6624554764a5aa05135c6ec4 Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Mon, 29 Feb 2016 13:37:38 -0800 Subject: [PATCH 13/23] Address code review + pylint complaints... --- azure-cli.pyproj | 4 +- src/azure/cli/commands/_auto_command.py | 41 +-- src/azure/cli/commands/network.py | 381 +++++++++++++----------- src/azure/cli/commands/vm.py | 218 +++++++------- src/azure/cli/tests/test_autocommand.py | 2 +- 5 files changed, 337 insertions(+), 309 deletions(-) diff --git a/azure-cli.pyproj b/azure-cli.pyproj index bce66fdf1..4b0868355 100644 --- a/azure-cli.pyproj +++ b/azure-cli.pyproj @@ -14,7 +14,8 @@ Standard Python launcher {1dd9c42b-5980-42ce-a2c3-46d3bf0eede4} 3.5 - vm extensions get + + False @@ -28,6 +29,7 @@ + diff --git a/src/azure/cli/commands/_auto_command.py b/src/azure/cli/commands/_auto_command.py index 454648a8b..e79f8f28e 100644 --- a/src/azure/cli/commands/_auto_command.py +++ b/src/azure/cli/commands/_auto_command.py @@ -1,9 +1,6 @@ import inspect -import sys from msrest import Serializer -from ..main import CONFIG, SESSION from ..commands import command, description, option -from .._logging import logger from azure.cli._argparse import IncorrectUsageError def _decorate_command(name, func): @@ -12,11 +9,11 @@ def _decorate_command(name, func): def _decorate_description(desc, func): return description(desc)(func) -def _decorate_option(spec, description, func): - return option(spec, description)(func) - +def _decorate_option(spec, descr, func): + return option(spec, descr)(func) + def _make_func(client_factory, member_name, return_type_name, unbound_func): - def call_client(args, unexpected): + def call_client(args, unexpected): #pylint: disable=unused-argument client = client_factory() ops_instance = getattr(client, member_name) try: @@ -24,34 +21,38 @@ def _make_func(client_factory, member_name, return_type_name, unbound_func): if not return_type_name: return {} return Serializer().serialize_data(result, return_type_name) - except TypeError as e: + except TypeError as exception: # TODO: Evaluate required/missing parameters and provide specific # usage for missing params... - raise IncorrectUsageError(e) + raise IncorrectUsageError(exception) return call_client - -def _option_description(op, arg): + +def _option_description(operation, arg): """Pull out parameter help from doccomments of the command """ - # TODO: We are currently doing this for every option/argument. We should do it (at most) once for a given command... - return ' '.join([l.split(':')[-1] for l in inspect.getdoc(op).splitlines() if l.startswith(':param') and l.find(arg + ':') != -1]) + # TODO: We are currently doing this for every option/argument. + # We should do it (at most) once for a given command... + return ' '.join(l.split(':')[-1] for l in inspect.getdoc(operation).splitlines() + if l.startswith(':param') and arg + ':' in l) -def _operation_builder(package_name, resource_type, member_name, client_type, operations): - excluded_params = ['self', 'raw', 'custom_headers', 'operation_config'] +EXCLUDED_PARAMS = frozenset(['self', 'raw', 'custom_headers', 'operation_config']) + +def operation_builder(package_name, resource_type, member_name, client_type, operations): for operation, return_type_name in operations: opname = operation.__name__ func = _make_func(client_type, member_name, return_type_name, operation) func = _decorate_command(' '.join([package_name, resource_type, opname]), func) - func = _decorate_description('This is the description of the command...', func) args = [] try: - sig = inspect.signature(operation) # only supported in python3 - falling back to argspec if not available + # only supported in python3 - falling back to argspec if not available + sig = inspect.signature(operation) args = sig.parameters except AttributeError: - sig = inspect.getargspec(operation) + sig = inspect.getargspec(operation) #pylint: disable=deprecated-method args = sig.args - for arg in [a for a in args if not a in excluded_params]: - func = _decorate_option('--%s <%s>' % (arg, arg), _option_description(operation, arg), func=func) + for arg in [a for a in args if not a in EXCLUDED_PARAMS]: + spec = '--%s <%s>' % (arg, arg) + func = _decorate_option(spec, _option_description(operation, arg), func=func) diff --git a/src/azure/cli/commands/network.py b/src/azure/cli/commands/network.py index be5b8f8b2..08fff22a7 100644 --- a/src/azure/cli/commands/network.py +++ b/src/azure/cli/commands/network.py @@ -1,224 +1,241 @@ -import azure.mgmt.network +from azure.mgmt.network import NetworkManagementClient, NetworkManagementClientConfiguration +from azure.mgmt.network.operations import (ApplicationGatewaysOperations, + ExpressRouteCircuitAuthorizationsOperations, + ExpressRouteCircuitPeeringsOperations, + ExpressRouteCircuitsOperations, + ExpressRouteServiceProvidersOperations, + LoadBalancersOperations, + LocalNetworkGatewaysOperations, + NetworkInterfacesOperations, + NetworkSecurityGroupsOperations, + PublicIPAddressesOperations, + RouteTablesOperations, + RoutesOperations, + SecurityRulesOperations, + SubnetsOperations, + UsagesOperations, + VirtualNetworkGatewayConnectionsOperations, + VirtualNetworkGatewaysOperations, + VirtualNetworksOperations) from ._command_creation import get_service_client - from ..commands import _auto_command -from .._profile import Profile def _network_client_factory(): - return get_service_client(azure.mgmt.network.NetworkManagementClient, azure.mgmt.network.NetworkManagementClientConfiguration) + return get_service_client(NetworkManagementClient, NetworkManagementClientConfiguration) +# pylint: disable=line-too-long # Application gateways -_auto_command._operation_builder("network", - "appgateway", - "application_gateways", - _network_client_factory, - [ - (azure.mgmt.network.operations.ApplicationGatewaysOperations.delete, None), - (azure.mgmt.network.operations.ApplicationGatewaysOperations.get, 'ApplicationGateway'), - (azure.mgmt.network.operations.ApplicationGatewaysOperations.list, '[ApplicationGateway]'), - (azure.mgmt.network.operations.ApplicationGatewaysOperations.list_all, '[ApplicationGateway]'), - (azure.mgmt.network.operations.ApplicationGatewaysOperations.start, None), - (azure.mgmt.network.operations.ApplicationGatewaysOperations.stop, None), - ]) +_auto_command.operation_builder("network", + "appgateway", + "application_gateways", + _network_client_factory, + [ + (ApplicationGatewaysOperations.delete, None), + (ApplicationGatewaysOperations.get, 'ApplicationGateway'), + (ApplicationGatewaysOperations.list, '[ApplicationGateway]'), + (ApplicationGatewaysOperations.list_all, '[ApplicationGateway]'), + (ApplicationGatewaysOperations.start, None), + (ApplicationGatewaysOperations.stop, None), + ]) # ExpressRouteCircuitAuthorizationsOperations -_auto_command._operation_builder("network", - "expressroutecircuitauth", - "express_route_circuit_authorizations", - _network_client_factory, - [ - (azure.mgmt.network.operations.ExpressRouteCircuitAuthorizationsOperations.delete, None), - (azure.mgmt.network.operations.ExpressRouteCircuitAuthorizationsOperations.get, 'ExpressRouteCircuitAuthorization'), - (azure.mgmt.network.operations.ExpressRouteCircuitAuthorizationsOperations.list, '[ExpressRouteCircuitAuthorization]'), - ]) +_auto_command.operation_builder("network", + "expressroutecircuitauth", + "express_route_circuit_authorizations", + _network_client_factory, + [ + (ExpressRouteCircuitAuthorizationsOperations.delete, None), + (ExpressRouteCircuitAuthorizationsOperations.get, 'ExpressRouteCircuitAuthorization'), + (ExpressRouteCircuitAuthorizationsOperations.list, '[ExpressRouteCircuitAuthorization]'), + ]) # ExpressRouteCircuitPeeringsOperations -_auto_command._operation_builder("network", - "expressroutecircuitpeering", - "express_route_circuit_peerings", - _network_client_factory, - [ - (azure.mgmt.network.operations.ExpressRouteCircuitPeeringsOperations.delete, None), - (azure.mgmt.network.operations.ExpressRouteCircuitPeeringsOperations.get, 'ExpressRouteCircuitPeering'), - (azure.mgmt.network.operations.ExpressRouteCircuitPeeringsOperations.list, '[ExpressRouteCircuitPeering]'), - ]) +_auto_command.operation_builder("network", + "expressroutecircuitpeering", + "express_route_circuit_peerings", + _network_client_factory, + [ + (ExpressRouteCircuitPeeringsOperations.delete, None), + (ExpressRouteCircuitPeeringsOperations.get, 'ExpressRouteCircuitPeering'), + (ExpressRouteCircuitPeeringsOperations.list, '[ExpressRouteCircuitPeering]'), + ]) # ExpressRouteCircuitsOperations -_auto_command._operation_builder("network", - "expressroutecircuit", - "express_route_circuits", - _network_client_factory, - [ - (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.delete, None), - (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.get, 'ExpressRouteCircuit'), - (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list_arp_table, '[ExpressRouteCircuitArpTable]'), - (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list_routes_table, '[ExpressRouteCircuitRoutesTable]'), - (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list_stats, '[ExpressRouteCircuitStats]'), - (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list, '[ExpressRouteCircuit]'), - (azure.mgmt.network.operations.ExpressRouteCircuitsOperations.list_all, '[ExpressRouteCircuit]'), - ]) +_auto_command.operation_builder("network", + "expressroutecircuit", + "express_route_circuits", + _network_client_factory, + [ + (ExpressRouteCircuitsOperations.delete, None), + (ExpressRouteCircuitsOperations.get, 'ExpressRouteCircuit'), + (ExpressRouteCircuitsOperations.list_arp_table, '[ExpressRouteCircuitArpTable]'), + (ExpressRouteCircuitsOperations.list_routes_table, '[ExpressRouteCircuitRoutesTable]'), + (ExpressRouteCircuitsOperations.list_stats, '[ExpressRouteCircuitStats]'), + (ExpressRouteCircuitsOperations.list, '[ExpressRouteCircuit]'), + (ExpressRouteCircuitsOperations.list_all, '[ExpressRouteCircuit]'), + ]) # ExpressRouteServiceProvidersOperations -_auto_command._operation_builder("network", - "expressroutesp", - "express_route_service_providers", - _network_client_factory, - [ - (azure.mgmt.network.operations.ExpressRouteServiceProvidersOperations.list, '[ExpressRouteServiceProvider]'), - ]) +_auto_command.operation_builder("network", + "expressroutesp", + "express_route_service_providers", + _network_client_factory, + [ + (ExpressRouteServiceProvidersOperations.list, '[ExpressRouteServiceProvider]'), + ]) # LoadBalancersOperations -_auto_command._operation_builder("network", - "lb", - "load_balancers", - _network_client_factory, - [ - (azure.mgmt.network.operations.LoadBalancersOperations.delete, None), - (azure.mgmt.network.operations.LoadBalancersOperations.get, 'LoadBalancer'), - (azure.mgmt.network.operations.LoadBalancersOperations.list_all, '[LoadBalancer]'), - (azure.mgmt.network.operations.LoadBalancersOperations.list, '[LoadBalancer]'), - ]) +_auto_command.operation_builder("network", + "lb", + "load_balancers", + _network_client_factory, + [ + (LoadBalancersOperations.delete, None), + (LoadBalancersOperations.get, 'LoadBalancer'), + (LoadBalancersOperations.list_all, '[LoadBalancer]'), + (LoadBalancersOperations.list, '[LoadBalancer]'), + ]) # LocalNetworkGatewaysOperations -_auto_command._operation_builder("network", - "localgateways", - "local_network_gateways", - _network_client_factory, - [ - (azure.mgmt.network.operations.LocalNetworkGatewaysOperations.get, 'LocalNetworkGateway'), - (azure.mgmt.network.operations.LocalNetworkGatewaysOperations.delete, None), - (azure.mgmt.network.operations.LocalNetworkGatewaysOperations.list, '[LocalNetworkGateway]'), - ]) +_auto_command.operation_builder("network", + "localgateways", + "local_network_gateways", + _network_client_factory, + [ + (LocalNetworkGatewaysOperations.get, 'LocalNetworkGateway'), + (LocalNetworkGatewaysOperations.delete, None), + (LocalNetworkGatewaysOperations.list, '[LocalNetworkGateway]'), + ]) # NetworkInterfacesOperations -_auto_command._operation_builder("network", - "nic", - "network_interfaces", - _network_client_factory, - [ - (azure.mgmt.network.operations.NetworkInterfacesOperations.delete, None), - (azure.mgmt.network.operations.NetworkInterfacesOperations.get, 'NetworkInterface'), - (azure.mgmt.network.operations.NetworkInterfacesOperations.list_virtual_machine_scale_set_vm_network_interfaces, '[NetworkInterface]'), - (azure.mgmt.network.operations.NetworkInterfacesOperations.list_virtual_machine_scale_set_network_interfaces, '[NetworkInterface]'), - (azure.mgmt.network.operations.NetworkInterfacesOperations.get_virtual_machine_scale_set_network_interface, 'NetworkInterface'), - (azure.mgmt.network.operations.NetworkInterfacesOperations.list_all, '[NetworkInterface]'), - (azure.mgmt.network.operations.NetworkInterfacesOperations.list, '[NetworkInterface]'), - ]) +_auto_command.operation_builder("network", + "nic", + "network_interfaces", + _network_client_factory, + [ + (NetworkInterfacesOperations.delete, None), + (NetworkInterfacesOperations.get, 'NetworkInterface'), + (NetworkInterfacesOperations.list_virtual_machine_scale_set_vm_network_interfaces, '[NetworkInterface]'), + (NetworkInterfacesOperations.list_virtual_machine_scale_set_network_interfaces, '[NetworkInterface]'), + (NetworkInterfacesOperations.get_virtual_machine_scale_set_network_interface, 'NetworkInterface'), + (NetworkInterfacesOperations.list_all, '[NetworkInterface]'), + (NetworkInterfacesOperations.list, '[NetworkInterface]'), + ]) # NetworkSecurityGroupsOperations -_auto_command._operation_builder("network", - "securitygroup", - "network_security_groups", - _network_client_factory, - [ - (azure.mgmt.network.operations.NetworkSecurityGroupsOperations.delete, None), - (azure.mgmt.network.operations.NetworkSecurityGroupsOperations.delete, 'NetworkSecurityGroup'), - (azure.mgmt.network.operations.NetworkSecurityGroupsOperations.list_all, '[NetworkSecurityGroup]'), - (azure.mgmt.network.operations.NetworkSecurityGroupsOperations.list, '[NetworkSecurityGroup]'), - ]) +_auto_command.operation_builder("network", + "securitygroup", + "network_security_groups", + _network_client_factory, + [ + (NetworkSecurityGroupsOperations.delete, None), + (NetworkSecurityGroupsOperations.delete, 'NetworkSecurityGroup'), + (NetworkSecurityGroupsOperations.list_all, '[NetworkSecurityGroup]'), + (NetworkSecurityGroupsOperations.list, '[NetworkSecurityGroup]'), + ]) # PublicIPAddressesOperations -_auto_command._operation_builder("network", - "publicipaddress", - "public_ip_addresses", - _network_client_factory, - [ - (azure.mgmt.network.operations.PublicIPAddressesOperations.delete, None), - (azure.mgmt.network.operations.PublicIPAddressesOperations.get, 'PublicIPAddress'), - (azure.mgmt.network.operations.PublicIPAddressesOperations.list_all, '[PublicIPAddress]'), - (azure.mgmt.network.operations.PublicIPAddressesOperations.list, '[PublicIPAddress]'), - ]) +_auto_command.operation_builder("network", + "publicipaddress", + "public_ip_addresses", + _network_client_factory, + [ + (PublicIPAddressesOperations.delete, None), + (PublicIPAddressesOperations.get, 'PublicIPAddress'), + (PublicIPAddressesOperations.list_all, '[PublicIPAddress]'), + (PublicIPAddressesOperations.list, '[PublicIPAddress]'), + ]) # RouteTablesOperations -_auto_command._operation_builder("network", - "routetable", - "route_tables", - _network_client_factory, - [ - (azure.mgmt.network.operations.RouteTablesOperations.delete, None), - (azure.mgmt.network.operations.RouteTablesOperations.get, 'RouteTable'), - (azure.mgmt.network.operations.RouteTablesOperations.list, '[RouteTable]'), - (azure.mgmt.network.operations.RouteTablesOperations.list_all, '[RouteTable]'), - ]) +_auto_command.operation_builder("network", + "routetable", + "route_tables", + _network_client_factory, + [ + (RouteTablesOperations.delete, None), + (RouteTablesOperations.get, 'RouteTable'), + (RouteTablesOperations.list, '[RouteTable]'), + (RouteTablesOperations.list_all, '[RouteTable]'), + ]) # RoutesOperations -_auto_command._operation_builder("network", - "routeoperation", - "routes", - _network_client_factory, - [ - (azure.mgmt.network.operations.RoutesOperations.delete, None), - (azure.mgmt.network.operations.RoutesOperations.get, 'Route'), - (azure.mgmt.network.operations.RoutesOperations.list, '[Route]'), - ]) +_auto_command.operation_builder("network", + "routeoperation", + "routes", + _network_client_factory, + [ + (RoutesOperations.delete, None), + (RoutesOperations.get, 'Route'), + (RoutesOperations.list, '[Route]'), + ]) # SecurityRulesOperations -_auto_command._operation_builder("network", - "securityrules", - "security_rules", - _network_client_factory, - [ - (azure.mgmt.network.operations.SecurityRulesOperations.delete, None), - (azure.mgmt.network.operations.SecurityRulesOperations.get, 'SecurityRule'), - (azure.mgmt.network.operations.SecurityRulesOperations.list, '[SecurityRule]'), - ]) +_auto_command.operation_builder("network", + "securityrules", + "security_rules", + _network_client_factory, + [ + (SecurityRulesOperations.delete, None), + (SecurityRulesOperations.get, 'SecurityRule'), + (SecurityRulesOperations.list, '[SecurityRule]'), + ]) # SubnetsOperations -_auto_command._operation_builder("network", - "subnet", - "subnets", - _network_client_factory, - [ - (azure.mgmt.network.operations.SubnetsOperations.delete, None), - (azure.mgmt.network.operations.SubnetsOperations.get, 'Subnet'), - (azure.mgmt.network.operations.SubnetsOperations.list, '[Subnet]'), - ]) +_auto_command.operation_builder("network", + "subnet", + "subnets", + _network_client_factory, + [ + (SubnetsOperations.delete, None), + (SubnetsOperations.get, 'Subnet'), + (SubnetsOperations.list, '[Subnet]'), + ]) # UsagesOperations -_auto_command._operation_builder("network", - "usage", - "usages", - _network_client_factory, - [ - (azure.mgmt.network.operations.UsagesOperations.list, '[Usage]'), - ]) +_auto_command.operation_builder("network", + "usage", + "usages", + _network_client_factory, + [ + (UsagesOperations.list, '[Usage]'), + ]) # VirtualNetworkGatewayConnectionsOperations -_auto_command._operation_builder("network", - "vnetgatewayconnection", - "virtual_network_gateway_connections", - _network_client_factory, - [ - (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.delete, None), - (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.get, 'VirtualNetworkGatewayConnection'), - (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.get_shared_key, 'ConnectionSharedKeyResult'), - (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.list, '[VirtualNetworkGatewayConnection]'), - (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.reset_shared_key, 'ConnectionResetSharedKey'), - (azure.mgmt.network.operations.VirtualNetworkGatewayConnectionsOperations.set_shared_key, 'ConnectionSharedKey'), - ]) +_auto_command.operation_builder("network", + "vnetgatewayconnection", + "virtual_network_gateway_connections", + _network_client_factory, + [ + (VirtualNetworkGatewayConnectionsOperations.delete, None), + (VirtualNetworkGatewayConnectionsOperations.get, 'VirtualNetworkGatewayConnection'), + (VirtualNetworkGatewayConnectionsOperations.get_shared_key, 'ConnectionSharedKeyResult'), + (VirtualNetworkGatewayConnectionsOperations.list, '[VirtualNetworkGatewayConnection]'), + (VirtualNetworkGatewayConnectionsOperations.reset_shared_key, 'ConnectionResetSharedKey'), + (VirtualNetworkGatewayConnectionsOperations.set_shared_key, 'ConnectionSharedKey'), + ]) # VirtualNetworkGatewaysOperations -_auto_command._operation_builder("network", - "vnetgateway", - "virtual_network_gateways", - _network_client_factory, - [ - (azure.mgmt.network.operations.VirtualNetworkGatewaysOperations.delete, None), - (azure.mgmt.network.operations.VirtualNetworkGatewaysOperations.get, 'VirtualNetworkGateway'), - (azure.mgmt.network.operations.VirtualNetworkGatewaysOperations.list, '[VirtualNetworkGateway]'), - (azure.mgmt.network.operations.VirtualNetworkGatewaysOperations.reset, 'VirtualNetworkGateway'), - ]) +_auto_command.operation_builder("network", + "vnetgateway", + "virtual_network_gateways", + _network_client_factory, + [ + (VirtualNetworkGatewaysOperations.delete, None), + (VirtualNetworkGatewaysOperations.get, 'VirtualNetworkGateway'), + (VirtualNetworkGatewaysOperations.list, '[VirtualNetworkGateway]'), + (VirtualNetworkGatewaysOperations.reset, 'VirtualNetworkGateway'), + ]) # VirtualNetworksOperations -_auto_command._operation_builder("network", - "vnet", - "virtual_networks", - _network_client_factory, - [ - (azure.mgmt.network.operations.VirtualNetworksOperations.delete, None), - (azure.mgmt.network.operations.VirtualNetworksOperations.get, 'VirtualNetwork'), - (azure.mgmt.network.operations.VirtualNetworksOperations.list, '[VirtualNetwork]'), - (azure.mgmt.network.operations.VirtualNetworksOperations.list_all, '[VirtualNetwork]'), - ]) +_auto_command.operation_builder("network", + "vnet", + "virtual_networks", + _network_client_factory, + [ + (VirtualNetworksOperations.delete, None), + (VirtualNetworksOperations.get, 'VirtualNetwork'), + (VirtualNetworksOperations.list, '[VirtualNetwork]'), + (VirtualNetworksOperations.list_all, '[VirtualNetwork]'), + ]) diff --git a/src/azure/cli/commands/vm.py b/src/azure/cli/commands/vm.py index b9ce85847..3cd18407c 100644 --- a/src/azure/cli/commands/vm.py +++ b/src/azure/cli/commands/vm.py @@ -1,119 +1,127 @@ -import azure.mgmt.compute +from azure.mgmt.compute import ComputeManagementClient, ComputeManagementClientConfiguration +from azure.mgmt.compute.operations import (AvailabilitySetsOperations, + VirtualMachineExtensionImagesOperations, + VirtualMachineExtensionsOperations, + VirtualMachineImagesOperations, + UsageOperations, + VirtualMachineSizesOperations, + VirtualMachinesOperations, + VirtualMachineScaleSetsOperations, + VirtualMachineScaleSetVMsOperations) from ._command_creation import get_service_client - from ..commands import _auto_command -from .._profile import Profile def _compute_client_factory(): - return get_service_client(azure.mgmt.compute.ComputeManagementClient, azure.mgmt.compute.ComputeManagementClientConfiguration) - -_auto_command._operation_builder("vm", - "availabilityset", - "availability_sets", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.AvailabilitySetsOperations.delete, None), - (azure.mgmt.compute.operations.AvailabilitySetsOperations.get, 'AvailabilitySet'), - (azure.mgmt.compute.operations.AvailabilitySetsOperations.list, '[AvailabilitySet]'), - (azure.mgmt.compute.operations.AvailabilitySetsOperations.list_available_sizes, '[VirtualMachineSize]') - ]) + return get_service_client(ComputeManagementClient, ComputeManagementClientConfiguration) + +# pylint: disable=line-too-long +_auto_command.operation_builder("vm", + "availabilityset", + "availability_sets", + _compute_client_factory, + [ + (AvailabilitySetsOperations.delete, None), + (AvailabilitySetsOperations.get, 'AvailabilitySet'), + (AvailabilitySetsOperations.list, '[AvailabilitySet]'), + (AvailabilitySetsOperations.list_available_sizes, '[VirtualMachineSize]') + ]) -_auto_command._operation_builder("vm", - "machineextensionimages", - "virtual_machine_extension_images", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.VirtualMachineExtensionImagesOperations.get, 'VirtualMachineExtensionImage'), - (azure.mgmt.compute.operations.VirtualMachineExtensionImagesOperations.list_types, '[VirtualMachineImageResource]'), - (azure.mgmt.compute.operations.VirtualMachineExtensionImagesOperations.list_versions, '[VirtualMachineImageResource]'), - ]) +_auto_command.operation_builder("vm", + "machineextensionimages", + "virtual_machine_extension_images", + _compute_client_factory, + [ + (VirtualMachineExtensionImagesOperations.get, 'VirtualMachineExtensionImage'), + (VirtualMachineExtensionImagesOperations.list_types, '[VirtualMachineImageResource]'), + (VirtualMachineExtensionImagesOperations.list_versions, '[VirtualMachineImageResource]'), + ]) -_auto_command._operation_builder("vm", - "extensions", - "virtual_machine_extensions", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.VirtualMachineExtensionsOperations.delete, None), - (azure.mgmt.compute.operations.VirtualMachineExtensionsOperations.get, 'VirtualMachineExtension'), - ]) +_auto_command.operation_builder("vm", + "extensions", + "virtual_machine_extensions", + _compute_client_factory, + [ + (VirtualMachineExtensionsOperations.delete, None), + (VirtualMachineExtensionsOperations.get, 'VirtualMachineExtension'), + ]) -_auto_command._operation_builder("vm", - "image", - "virtual_machine_images", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.VirtualMachineImagesOperations.get, 'VirtualMachineImage'), - (azure.mgmt.compute.operations.VirtualMachineImagesOperations.list, '[VirtualMachineImageResource]'), - (azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_offers, '[VirtualMachineImageResource]'), - (azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_publishers, '[VirtualMachineImageResource]'), - (azure.mgmt.compute.operations.VirtualMachineImagesOperations.list_skus, '[VirtualMachineImageResource]'), - ]) +_auto_command.operation_builder("vm", + "image", + "virtual_machine_images", + _compute_client_factory, + [ + (VirtualMachineImagesOperations.get, 'VirtualMachineImage'), + (VirtualMachineImagesOperations.list, '[VirtualMachineImageResource]'), + (VirtualMachineImagesOperations.list_offers, '[VirtualMachineImageResource]'), + (VirtualMachineImagesOperations.list_publishers, '[VirtualMachineImageResource]'), + (VirtualMachineImagesOperations.list_skus, '[VirtualMachineImageResource]'), + ]) -_auto_command._operation_builder("vm", - "usage", - "usage", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.UsageOperations.list, '[Usage]'), - ]) +_auto_command.operation_builder("vm", + "usage", + "usage", + _compute_client_factory, + [ + (UsageOperations.list, '[Usage]'), + ]) -_auto_command._operation_builder("vm", - "size", - "virtual_machine_sizes", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.VirtualMachineSizesOperations.list, '[VirtualMachineSize]'), - ]) +_auto_command.operation_builder("vm", + "size", + "virtual_machine_sizes", + _compute_client_factory, + [ + (VirtualMachineSizesOperations.list, '[VirtualMachineSize]'), + ]) -_auto_command._operation_builder("vm", - "", - "virtual_machines", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.VirtualMachinesOperations.delete, None), - (azure.mgmt.compute.operations.VirtualMachinesOperations.deallocate, None), - (azure.mgmt.compute.operations.VirtualMachinesOperations.generalize, None), - (azure.mgmt.compute.operations.VirtualMachinesOperations.get, 'VirtualMachine'), - (azure.mgmt.compute.operations.VirtualMachinesOperations.list, '[VirtualMachine]'), - (azure.mgmt.compute.operations.VirtualMachinesOperations.list_all, '[VirtualMachine]'), - (azure.mgmt.compute.operations.VirtualMachinesOperations.list_available_sizes, '[VirtualMachineSize]'), - (azure.mgmt.compute.operations.VirtualMachinesOperations.power_off, None), - (azure.mgmt.compute.operations.VirtualMachinesOperations.restart, None), - (azure.mgmt.compute.operations.VirtualMachinesOperations.start, None), - ]) +_auto_command.operation_builder("vm", + "", + "virtual_machines", + _compute_client_factory, + [ + (VirtualMachinesOperations.delete, None), + (VirtualMachinesOperations.deallocate, None), + (VirtualMachinesOperations.generalize, None), + (VirtualMachinesOperations.get, 'VirtualMachine'), + (VirtualMachinesOperations.list, '[VirtualMachine]'), + (VirtualMachinesOperations.list_all, '[VirtualMachine]'), + (VirtualMachinesOperations.list_available_sizes, '[VirtualMachineSize]'), + (VirtualMachinesOperations.power_off, None), + (VirtualMachinesOperations.restart, None), + (VirtualMachinesOperations.start, None), + ]) -_auto_command._operation_builder("vm", - "scaleset", - "virtual_machine_scale_sets", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.deallocate, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get, 'VirtualMachineScaleSet'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.delete_instances, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.get_instance_view, 'VirtualMachineScaleSetInstanceView'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list, '[VirtualMachineScaleSet]'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_all, '[VirtualMachineScaleSet]'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.list_skus, '[VirtualMachineScaleSet]'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.power_off, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.restart, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.start, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetsOperations.update_instances, None), - ]) +_auto_command.operation_builder("vm", + "scaleset", + "virtual_machine_scale_sets", + _compute_client_factory, + [ + (VirtualMachineScaleSetsOperations.deallocate, None), + (VirtualMachineScaleSetsOperations.delete, None), + (VirtualMachineScaleSetsOperations.get, 'VirtualMachineScaleSet'), + (VirtualMachineScaleSetsOperations.delete_instances, None), + (VirtualMachineScaleSetsOperations.get_instance_view, 'VirtualMachineScaleSetInstanceView'), + (VirtualMachineScaleSetsOperations.list, '[VirtualMachineScaleSet]'), + (VirtualMachineScaleSetsOperations.list_all, '[VirtualMachineScaleSet]'), + (VirtualMachineScaleSetsOperations.list_skus, '[VirtualMachineScaleSet]'), + (VirtualMachineScaleSetsOperations.power_off, None), + (VirtualMachineScaleSetsOperations.restart, None), + (VirtualMachineScaleSetsOperations.start, None), + (VirtualMachineScaleSetsOperations.update_instances, None), + ]) -_auto_command._operation_builder("vm", - "vmscaleset", - "virtual_machine_scale_set_vms", - _compute_client_factory, - [ - (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.deallocate, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.delete, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.get, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.get_instance_view, 'VirtualMachineScaleSetVMInstanceView'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.list, '[VirtualMachineScaleSetVM]'), - (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.power_off, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.restart, None), - (azure.mgmt.compute.operations.VirtualMachineScaleSetVMsOperations.start, None), - ]) \ No newline at end of file +_auto_command.operation_builder("vm", + "vmscaleset", + "virtual_machine_scale_set_vms", + _compute_client_factory, + [ + (VirtualMachineScaleSetVMsOperations.deallocate, None), + (VirtualMachineScaleSetVMsOperations.delete, None), + (VirtualMachineScaleSetVMsOperations.get, None), + (VirtualMachineScaleSetVMsOperations.get_instance_view, 'VirtualMachineScaleSetVMInstanceView'), + (VirtualMachineScaleSetVMsOperations.list, '[VirtualMachineScaleSetVM]'), + (VirtualMachineScaleSetVMsOperations.power_off, None), + (VirtualMachineScaleSetVMsOperations.restart, None), + (VirtualMachineScaleSetVMsOperations.start, None), + ]) diff --git a/src/azure/cli/tests/test_autocommand.py b/src/azure/cli/tests/test_autocommand.py index ec56f5384..4f3142af9 100644 --- a/src/azure/cli/tests/test_autocommand.py +++ b/src/azure/cli/tests/test_autocommand.py @@ -1,7 +1,7 @@ import logging import unittest -from azure.cli.commands._auto_command import _decorate_command, _decorate_option, _decorate_description, _operation_builder +from azure.cli.commands._auto_command import _decorate_command, _decorate_option, _decorate_description, operation_builder from azure.cli.commands import _COMMANDS class Test_autocommand(unittest.TestCase): From cf20270e7d99bdd8b1ae0a7f50427c26cc0942dc Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Mon, 29 Feb 2016 13:43:40 -0800 Subject: [PATCH 14/23] Fix pylint complaints --- src/azure/cli/tests/test_autocommand.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/azure/cli/tests/test_autocommand.py b/src/azure/cli/tests/test_autocommand.py index 4f3142af9..ee403cae0 100644 --- a/src/azure/cli/tests/test_autocommand.py +++ b/src/azure/cli/tests/test_autocommand.py @@ -1,7 +1,9 @@ import logging import unittest -from azure.cli.commands._auto_command import _decorate_command, _decorate_option, _decorate_description, operation_builder +from azure.cli.commands._auto_command import (_decorate_command, + _decorate_option) + from azure.cli.commands import _COMMANDS class Test_autocommand(unittest.TestCase): @@ -23,8 +25,8 @@ class Test_autocommand(unittest.TestCase): # Run test code _decorate_command(command_name, testfunc) - # Verify - registered_command =_COMMANDS.get(testfunc, None) + # Verify + registered_command = _COMMANDS.get(testfunc, None) self.assertIsNotNone(registered_command) self.assertFalse('args' in registered_command.keys()) self.assertEqual(registered_command['name'], command_name) @@ -39,9 +41,9 @@ class Test_autocommand(unittest.TestCase): spec = '--tre ' desc = 'Kronor' func = _decorate_option(spec, desc, func) - + # Verify - registered_command =_COMMANDS.get(testfunc, None) + registered_command = _COMMANDS.get(testfunc, None) self.assertIsNotNone(registered_command) self.assertEqual(registered_command['name'], command_name) self.assertEqual(len(registered_command['args']), 1) From 9ea72a3915f44218703ba546cb79d85f7216be23 Mon Sep 17 00:00:00 2001 From: yugangw-msft Date: Thu, 25 Feb 2016 21:56:26 -0800 Subject: [PATCH 15/23] address code analysis errors by pylints --- .travis.yml | 4 +- azure-cli.pyproj | 2 + pylintrc | 13 +++++++ src/azure/cli/_argparse.py | 50 ++++++++++++++----------- src/azure/cli/_debug.py | 3 +- src/azure/cli/_locale.py | 19 +++++----- src/azure/cli/_logging.py | 2 +- src/azure/cli/_output.py | 14 +++---- src/azure/cli/_profile.py | 11 +++--- src/azure/cli/_session.py | 6 +-- src/azure/cli/_util.py | 1 - src/azure/cli/commands/__init__.py | 16 ++++---- src/azure/cli/commands/account.py | 17 +++++---- src/azure/cli/commands/login.py | 23 +++++++----- src/azure/cli/commands/logout.py | 9 +++-- src/azure/cli/commands/resourcegroup.py | 18 ++++----- src/azure/cli/commands/storage.py | 19 ++++------ src/azure/cli/main.py | 12 +++--- 18 files changed, 133 insertions(+), 106 deletions(-) create mode 100644 pylintrc diff --git a/.travis.yml b/.travis.yml index 2c5e2e0fe..fc69fd757 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,9 @@ python: install: - pip install azure==2.0.0a1 - pip install mock==1.3.0 + - pip install pylint==1.5.4 script: - export PYTHONPATH=$PATHONPATH:./src - python -m azure.cli - - python -m unittest discover -s src/azure/cli/tests + - pylint src/azure + - python -m unittest discover -s src/azure/cli/tests \ No newline at end of file diff --git a/azure-cli.pyproj b/azure-cli.pyproj index 4b0868355..10e839a95 100644 --- a/azure-cli.pyproj +++ b/azure-cli.pyproj @@ -44,6 +44,7 @@ Code + @@ -52,6 +53,7 @@ Code + diff --git a/pylintrc b/pylintrc new file mode 100644 index 000000000..f9e4a383c --- /dev/null +++ b/pylintrc @@ -0,0 +1,13 @@ +[MESSAGES CONTROL] +# For all codes, run 'pylint --list-msgs' or go to 'http://pylint-messages.wikidot.com/all-codes' +# C0111 Missing docstring +# C0103 Invalid %s name "%s" +# C0303 Trailing whitespace +# I0011 Warning locally suppressed using disable-msg +# W0511 fixme +disable=C0111,C0103,C0303,I0011,W0511 +[DESIGN] +# Maximum number of locals for function / method body +max-locals=25 +# Maximum number of branch for function / method body +max-branches=20 \ No newline at end of file diff --git a/src/azure/cli/_argparse.py b/src/azure/cli/_argparse.py index 2e46c9186..623bfbadc 100644 --- a/src/azure/cli/_argparse.py +++ b/src/azure/cli/_argparse.py @@ -1,9 +1,7 @@ from __future__ import print_function -import json -import os import sys -from ._locale import get_file as locale_get_file +from ._locale import L, get_file as locale_get_file from ._logging import logger # Named arguments are prefixed with one of these strings @@ -20,7 +18,7 @@ class IncorrectUsageError(Exception): pass class Arguments(dict): - def __init__(self, source=None): + def __init__(self, source=None): #pylint: disable=super-init-not-called self.positional = [] if source: self.update(source) @@ -40,7 +38,7 @@ class Arguments(dict): except LookupError: pass logger.debug('Argument %s is required', key) - raise IncorrectUsageError(_("Argument {0} is required").format(key)) + raise IncorrectUsageError(L('Argument {0} is required').format(key)) def _read_arg(string): for prefix in ARG_PREFIXES: @@ -66,11 +64,15 @@ class ArgumentParser(object): self.noun_map = { '$doc': 'azure-cli.txt', } - self.help_args = { '--help', '-h' } - self.complete_args = { '--complete' } - self.global_args = { '--verbose', '--debug' } + self.help_args = {'--help', '-h'} + self.complete_args = {'--complete'} + self.global_args = {'--verbose', '--debug'} - def add_command(self, handler, name=None, description=None, args=None): + def add_command(self, + handler, + name=None, + description=None, + args=None): '''Registers a command that may be parsed by this parser. `handler` is the function to call with two `Arguments` objects. @@ -105,7 +107,7 @@ class ArgumentParser(object): m['$args'] = [] m['$kwargs'] = kw = {} m['$argdoc'] = ad = [] - for spec, desc in (args or []): + for spec, desc in args or []: if not any(spec.startswith(p) for p in ARG_PREFIXES): m['$args'].append(spec.strip('<> ')) ad.append((spec, desc)) @@ -121,7 +123,11 @@ class ArgumentParser(object): ad.append(('/'.join(aliases), desc)) - def execute(self, args, show_usage=False, show_completions=False, out=sys.stdout): + def execute(self, + args, + show_usage=False, + show_completions=False, + out=sys.stdout): '''Parses `args` and invokes the associated handler. The handler is passed two `Arguments` objects with all arguments other @@ -142,10 +148,11 @@ class ArgumentParser(object): if not show_completions: show_completions = any(a in self.complete_args for a in args) - all_global_args = set(a.lstrip('-/') for a in self.help_args | self.complete_args | self.global_args) + all_global_args = set( + a.lstrip('-/') for a in self.help_args | self.complete_args | self.global_args) def not_global(a): return a.lstrip('-/') not in all_global_args - it = filter(not_global, args).__iter__() + it = filter(not_global, args).__iter__() #pylint: disable=bad-builtin m = self.noun_map nouns = [] @@ -161,7 +168,6 @@ class ArgumentParser(object): n = next(it, '') try: - expected_args = m['$args'] expected_kwargs = m['$kwargs'] handler = m['$handler'] except LookupError: @@ -169,9 +175,9 @@ class ArgumentParser(object): show_usage = True if show_completions: - return self._display_completions(nouns, m, args, out) + return ArgumentParser._display_completions(m, out) if show_usage: - return self._display_usage(nouns, m, args, out) + return self._display_usage(nouns, m, out) parsed = Arguments() others = Arguments() @@ -189,8 +195,9 @@ class ArgumentParser(object): elif target_value[1] is True: # Arg with no value if value is not None: - print(_("argument '{0}' does not take a value").format(key_n), file=out) - return self._display_usage(nouns, m, args, out) + print(L("argument '{0}' does not take a value").format(key_n), + file=out) + return self._display_usage(nouns, m, out) parsed.add_from_dotted(target_value[0], True) else: # Arg with a value @@ -208,11 +215,11 @@ class ArgumentParser(object): return handler(parsed, others) except IncorrectUsageError as ex: print(str(ex), file=out) - return self._display_usage(nouns, m, args, out) + return self._display_usage(nouns, m, out) finally: sys.stdout = old_stdout - def _display_usage(self, nouns, noun_map, arguments, out=sys.stdout): + def _display_usage(self, nouns, noun_map, out=sys.stdout): spec = ' '.join(noun_map.get('$spec') or nouns) print(' {} {}'.format(self.prog, spec), file=out) print(file=out) @@ -246,7 +253,8 @@ class ArgumentParser(object): out.flush() logger.debug('Expected documentation at %s', doc_file) - def _display_completions(self, nouns, noun_map, arguments, out=sys.stdout): + @staticmethod + def _display_completions(noun_map, out=sys.stdout): completions = [k for k in noun_map if not k.startswith('$')] kwargs = noun_map.get('$kwargs') diff --git a/src/azure/cli/_debug.py b/src/azure/cli/_debug.py index 845ec253c..c5d8a1db7 100644 --- a/src/azure/cli/_debug.py +++ b/src/azure/cli/_debug.py @@ -5,7 +5,8 @@ DISABLE_VERIFY_VARIABLE_NAME = "AZURE_CLI_DISABLE_CONNECTION_VERIFICATION" def allow_debug_connection(client): if should_disable_connection_verify(): - logger.warn("Connection verification disabled by environment variable %s", DISABLE_VERIFY_VARIABLE_NAME) + logger.warning("Connection verification disabled by environment variable %s", + DISABLE_VERIFY_VARIABLE_NAME) client.config.connection.verify = False def should_disable_connection_verify(): diff --git a/src/azure/cli/_locale.py b/src/azure/cli/_locale.py index 97faae764..b56abe94a 100644 --- a/src/azure/cli/_locale.py +++ b/src/azure/cli/_locale.py @@ -1,11 +1,16 @@ import os.path +from codecs import open as codecs_open -from codecs import open +_translations = dict() +_locale_dir = '' + +def L(key): + return _translations.get(key) or ''.format(key) def install(locale_dir): mapping = [] - with open(os.path.join(locale_dir, "messages.txt"), 'r', encoding='utf-8-sig') as f: + with codecs_open(os.path.join(locale_dir, "messages.txt"), 'r', encoding='utf-8-sig') as f: for i in f: if not i or i.startswith('#') or not i.strip(): continue @@ -14,16 +19,12 @@ def install(locale_dir): else: mapping[-1] = (mapping[-1][0], i.strip()) - translations = dict(mapping) - def _(key): - return translations.get(key) or ''.format(key) - _.locale_dir = locale_dir - - __builtins__['_'] = _ + globals()['_translations'] = dict(mapping) + globals()['_locale_dir'] = locale_dir def get_file(name): try: - src = _.locale_dir + src = _locale_dir except (NameError, AttributeError): raise RuntimeError("localizations not installed") diff --git a/src/azure/cli/_logging.py b/src/azure/cli/_logging.py index ada07b71e..0102e0aab 100644 --- a/src/azure/cli/_logging.py +++ b/src/azure/cli/_logging.py @@ -1,7 +1,7 @@ import logging as _logging import sys -__all__ = ['logging', 'configure_logging'] +__all__ = ['logger', 'configure_logging'] logger = _logging.Logger('az', _logging.WARNING) diff --git a/src/azure/cli/_output.py b/src/azure/cli/_output.py index 53d84bc87..529e25ea9 100644 --- a/src/azure/cli/_output.py +++ b/src/azure/cli/_output.py @@ -8,7 +8,7 @@ try: from io import StringIO except ImportError: # Python 2 - from StringIO import StringIO + from StringIO import StringIO #pylint: disable=import-error class OutputFormatException(Exception): pass @@ -40,9 +40,9 @@ def format_text(obj): except TypeError: return '' -class OutputProducer(object): +class OutputProducer(object): #pylint: disable=too-few-public-methods - def __init__(self, formatter=format_json, file=sys.stdout): + def __init__(self, formatter=format_json, file=sys.stdout): #pylint: disable=redefined-builtin self.formatter = formatter self.file = file @@ -100,14 +100,14 @@ class TextOutput(object): def dump(self): with StringIO() as io: - for id in sorted(self.identifiers): - io.write(id.upper()) + for identifier in sorted(self.identifiers): + io.write(identifier.upper()) io.write('\t') - for col in self.identifiers[id]: + for col in self.identifiers[identifier]: if isinstance(col, str): io.write(col) else: - # TODO: Handle complex objects + # TODO: Need to handle complex objects io.write("null") io.write('\t') io.write('\n') diff --git a/src/azure/cli/_profile.py b/src/azure/cli/_profile.py index f72e70eca..87834bbef 100644 --- a/src/azure/cli/_profile.py +++ b/src/azure/cli/_profile.py @@ -1,6 +1,6 @@ -from msrest.authentication import BasicTokenAuthentication +import collections +from msrest.authentication import BasicTokenAuthentication from .main import CONFIG -import collections class Profile(object): @@ -37,10 +37,9 @@ class Profile(object): for s in subscriptions: s['active'] = False - if new_active_one: - new_active_one['active'] = True - else: - new_subscriptions[0]['active'] = True + if not new_active_one: + new_active_one = new_subscriptions[0] + new_active_one['active'] = True else: new_subscriptions[0]['active'] = True diff --git a/src/azure/cli/_session.py b/src/azure/cli/_session.py index 45cdcab16..39881574e 100644 --- a/src/azure/cli/_session.py +++ b/src/azure/cli/_session.py @@ -7,7 +7,7 @@ except ImportError: import collections -from codecs import open +from codecs import open as codecs_open class Session(collections.MutableMapping): '''A simple dict-like class that is backed by a JSON file. @@ -28,14 +28,14 @@ class Session(collections.MutableMapping): st = os.stat(self.filename) if st.st_mtime + max_age < time.clock(): self.save() - with open(self.filename, 'r', encoding='utf-8-sig') as f: + with codecs_open(self.filename, 'r', encoding='utf-8-sig') as f: self.data = json.load(f) except (OSError, IOError): self.save() def save(self): if self.filename: - with open(self.filename, 'w', encoding='utf-8-sig') as f: + with codecs_open(self.filename, 'w', encoding='utf-8-sig') as f: json.dump(self.data, f) def save_with_retry(self, retries=5): diff --git a/src/azure/cli/_util.py b/src/azure/cli/_util.py index 6449b6317..f667ddd59 100644 --- a/src/azure/cli/_util.py +++ b/src/azure/cli/_util.py @@ -1,3 +1,2 @@ - def normalize_newlines(str_to_normalize): return str_to_normalize.replace('\r\n', '\n') diff --git a/src/azure/cli/commands/__init__.py b/src/azure/cli/commands/__init__.py index f4172e18b..b39c45a54 100644 --- a/src/azure/cli/commands/__init__.py +++ b/src/azure/cli/commands/__init__.py @@ -21,21 +21,21 @@ def command(name): return handler return add_command -def description(description): +def description(description_text): def add_description(handler): - _COMMANDS.setdefault(handler, {})['description'] = description - logger.debug('Added description "%s" to %s', description, handler) + _COMMANDS.setdefault(handler, {})['description'] = description_text + logger.debug('Added description "%s" to %s', description_text, handler) return handler return add_description -def option(spec, description=None): +def option(spec, description_text=None): def add_option(handler): - _COMMANDS.setdefault(handler, {}).setdefault('args', []).append((spec, description)) + _COMMANDS.setdefault(handler, {}).setdefault('args', []).append((spec, description_text)) logger.debug('Added option "%s" to %s', spec, handler) return handler return add_option -def add_to_parser(parser, command=None): +def add_to_parser(parser, command_name=None): '''Loads commands into the parser When `command` is specified, only commands from that module will be loaded. @@ -45,9 +45,9 @@ def add_to_parser(parser, command=None): # Importing the modules is sufficient to invoke the decorators. Then we can # get all of the commands from the _COMMANDS variable. loaded = False - if command: + if command_name: try: - __import__('azure.cli.commands.' + command) + __import__('azure.cli.commands.' + command_name) loaded = True except ImportError: # Unknown command - we'll load all below diff --git a/src/azure/cli/commands/account.py b/src/azure/cli/commands/account.py index 4df6168ec..c49a479b5 100644 --- a/src/azure/cli/commands/account.py +++ b/src/azure/cli/commands/account.py @@ -1,21 +1,22 @@ from .._profile import Profile from ..commands import command, description, option +from .._locale import L @command('account list') -@description(_('List the imported subscriptions.')) -def list_subscriptions(args, unexpected): +@description(L('List the imported subscriptions.')) +def list_subscriptions(args, unexpected): #pylint: disable=unused-argument profile = Profile() subscriptions = profile.load_subscriptions() return subscriptions @command('account set') -@description(_('Set the current subscription')) -@option('--subscription-id -n ', _('Subscription Id, unique name also works.')) -def set_active_subscription(args, unexpected): - id = args.get('subscription-id') +@description(L('Set the current subscription')) +@option('--subscription-id -n ', L('Subscription Id, unique name also works.')) +def set_active_subscription(args, unexpected): #pylint: disable=unused-argument + subscription_id = args.get('subscription-id') if not id: - raise ValueError(_('Please provide subscription id or unique name.')) + raise ValueError(L('Please provide subscription id or unique name.')) profile = Profile() - profile.set_active_subscription(id) + profile.set_active_subscription(subscription_id) diff --git a/src/azure/cli/commands/login.py b/src/azure/cli/commands/login.py index 09e30b57a..31125f349 100644 --- a/src/azure/cli/commands/login.py +++ b/src/azure/cli/commands/login.py @@ -1,33 +1,36 @@ -from msrestazure.azure_active_directory import UserPassCredentials +from msrest import Serializer +from msrestazure.azure_active_directory import UserPassCredentials from azure.mgmt.resource.subscriptions import SubscriptionClient, \ SubscriptionClientConfiguration -from msrest import Serializer - from .._profile import Profile from ..commands import command, description, option from .._debug import should_disable_connection_verify +from .._locale import L CLIENT_ID = '04b07795-8ddb-461a-bbee-02f9e1bf7b46' @command('login') -@description(_('log in to an Azure subscription using Active Directory Organization Id')) -@option('--username -u ', _('organization Id. Microsoft Account is not yet supported.')) -@option('--password -p ', _('user password, will prompt if not given.')) -def login(args, unexpected): +@description(L('log in to an Azure subscription using Active Directory Organization Id')) +@option('--username -u ', L('organization Id. Microsoft Account is not yet supported.')) +@option('--password -p ', L('user password, will prompt if not given.')) +def login(args, unexpected): #pylint: disable=unused-argument username = args.get('username') password = args.get('password') if not password: import getpass - password = getpass.getpass(_('Password: ')) + password = getpass.getpass(L('Password: ')) - credentials = UserPassCredentials(username, password, client_id=CLIENT_ID, verify=not should_disable_connection_verify()) + credentials = UserPassCredentials(username, + password, + client_id=CLIENT_ID, + verify=not should_disable_connection_verify()) client = SubscriptionClient(SubscriptionClientConfiguration(credentials)) subscriptions = client.subscriptions.list() if not subscriptions: - raise RuntimeError(_('No subscriptions found for this account.')) + raise RuntimeError(L('No subscriptions found for this account.')) serializable = Serializer().serialize_data(subscriptions, "[Subscription]") diff --git a/src/azure/cli/commands/logout.py b/src/azure/cli/commands/logout.py index 341904576..d4ce01a20 100644 --- a/src/azure/cli/commands/logout.py +++ b/src/azure/cli/commands/logout.py @@ -1,13 +1,14 @@ from .._profile import Profile from ..commands import command, description, option +from .._locale import L @command('logout') -@description(_('Log out from Azure subscription using Active Directory.')) -@option('--username -u ', _('User name used to log out from Azure Active Directory.')) -def logout(args, unexpected): +@description(L('Log out from Azure subscription using Active Directory.')) +@option('--username -u ', L('User name used to log out from Azure Active Directory.')) +def logout(args, unexpected): #pylint: disable=unused-argument username = args.get('username') if not username: - raise ValueError(_('Please provide a valid username to logout.')) + raise ValueError(L('Please provide a valid username to logout.')) profile = Profile() profile.logout(username) diff --git a/src/azure/cli/commands/resourcegroup.py b/src/azure/cli/commands/resourcegroup.py index 6a7eec557..bea80ae2c 100644 --- a/src/azure/cli/commands/resourcegroup.py +++ b/src/azure/cli/commands/resourcegroup.py @@ -1,24 +1,24 @@ from msrest import Serializer - -from ..commands import command, description, option +from ..commands import command, description from .._profile import Profile @command('resource group list') @description('List resource groups') # TODO: waiting on Python Azure SDK bug fixes -#@option('--tag-name -g ', _("the resource group's tag name")) -#@option('--tag-value -g ', _("the resource group's tag value")) -#@option('--top -g ', _("Top N resource groups to retrieve")) -def list_groups(args, unexpected): - from azure.mgmt.resource.resources import ResourceManagementClient, ResourceManagementClientConfiguration +# @option('--tag-name -g ', L('the resource group's tag name')) +# @option('--tag-value -g ', L('the resource group's tag value')) +# @option('--top -g ', L('Top N resource groups to retrieve')) +def list_groups(args, unexpected): #pylint: disable=unused-argument + from azure.mgmt.resource.resources import ResourceManagementClient, \ + ResourceManagementClientConfiguration from azure.mgmt.resource.resources.models import ResourceGroup, ResourceGroupFilter - rmc = ResourceManagementClient(ResourceManagementClientConfiguration(*Profile().get_login_credentials())) + rmc = ResourceManagementClient( + ResourceManagementClientConfiguration(*Profile().get_login_credentials())) # TODO: waiting on Python Azure SDK bug fixes #group_filter = ResourceGroupFilter(args.get('tag-name'), args.get('tag-value')) #groups = rmc.resource_groups.list(filter=None, top=args.get('top')) groups = rmc.resource_groups.list() - serializable = Serializer().serialize_data(groups, "[ResourceGroup]") return serializable diff --git a/src/azure/cli/commands/storage.py b/src/azure/cli/commands/storage.py index 15fde8488..b765431c9 100644 --- a/src/azure/cli/commands/storage.py +++ b/src/azure/cli/commands/storage.py @@ -1,14 +1,14 @@ from msrest import Serializer - -from ..main import SESSION from ..commands import command, description, option from ._command_creation import get_service_client +from .._logging import logger +from .._locale import L @command('storage account list') -@description(_('List storage accounts')) -@option('--resource-group -g ', _('the resource group name')) -@option('--subscription -s ', _('the subscription id')) -def list_accounts(args, unexpected): +@description(L('List storage accounts')) +@option('--resource-group -g ', L('the resource group name')) +@option('--subscription -s ', L('the subscription id')) +def list_accounts(args, unexpected): #pylint: disable=unused-argument from azure.mgmt.storage import StorageManagementClient, StorageManagementClientConfiguration from azure.mgmt.storage.models import StorageAccount from msrestazure.azure_active_directory import UserPassCredentials @@ -26,10 +26,7 @@ def list_accounts(args, unexpected): @command('storage account check') @option('--account-name ') -def checkname(args, unexpected): +def checkname(args, unexpected): #pylint: disable=unused-argument from azure.mgmt.storage import StorageManagementClient, StorageManagementClientConfiguration - smc = get_service_client(StorageManagementClient, StorageManagementClientConfiguration) - logger.warn(smc.storage_accounts.check_name_availability(args.account_name)) - - + logger.warning(smc.storage_accounts.check_name_availability(args.account_name)) diff --git a/src/azure/cli/main.py b/src/azure/cli/main.py index 08aaeee6e..a685484cc 100644 --- a/src/azure/cli/main.py +++ b/src/azure/cli/main.py @@ -1,7 +1,6 @@ import os from ._argparse import ArgumentParser -from ._locale import install as locale_install from ._logging import configure_logging, logger from ._session import Session from ._output import OutputProducer @@ -12,17 +11,18 @@ CONFIG = Session() # SESSION provides read-write session variables SESSION = Session() -# Load the user's preferred locale from their configuration -LOCALE = CONFIG.get('locale', 'en-US') -locale_install(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'locale', LOCALE)) - - def main(args): CONFIG.load(os.path.expanduser('~/az.json')) SESSION.load(os.path.expanduser('~/az.sess'), max_age=3600) configure_logging(args, CONFIG) + from ._locale import install as locale_install + locale_install(os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'locale', + CONFIG.get('locale', 'en-US'))) + + parser = ArgumentParser("az") import azure.cli.commands as commands From d2064a659abb28e17539d61e70648d7bff3edf7f Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Mon, 29 Feb 2016 17:19:15 -0800 Subject: [PATCH 16/23] Simple shell script wrapper for azure.cli --- az | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/az b/az index 67012eaa1..c4b5a8d6d 100755 --- a/az +++ b/az @@ -10,4 +10,6 @@ DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" export PYTHONPATH="${DIR}/src:${PYTHONPATH}" -python -m azure.cli "$@" +python -m azure.cli "$@" + + From c6d8ba93b6fe9e937cf7b2aa966437811d98b24e Mon Sep 17 00:00:00 2001 From: Johan Stenberg Date: Mon, 29 Feb 2016 17:23:58 -0800 Subject: [PATCH 17/23] Simple batch file wrapper for az --- az.bat | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 az.bat diff --git a/az.bat b/az.bat new file mode 100644 index 000000000..e8bf88e49 --- /dev/null +++ b/az.bat @@ -0,0 +1,7 @@ +@echo off +setlocal + +SET PYTHONPATH=%~dp0/src;%PYTHONPATH% +python -m azure.cli %* + +endlocal \ No newline at end of file From d049cbbcbe00f7aeaf489a902f57a7ba747531fb Mon Sep 17 00:00:00 2001 From: yugangw-msft Date: Mon, 29 Feb 2016 10:41:13 -0800 Subject: [PATCH 18/23] initial docker file based on ubuntu14.04 --- Dockerfile | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..815df5af5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +FROM ubuntu:14.04 + +RUN rm /bin/sh && ln -s /bin/bash /bin/sh + +RUN apt-get update -qq && \ + apt-get install -qqy --no-install-recommends\ + build-essential \ + curl \ + ca-certificates \ + git \ + python-pip \ + libffi-dev \ + libssl-dev \ + python-dev \ + vim \ + nano \ + jq && \ + rm -rf /var/lib/apt/lists/* && \ + pip install azure==2.0.0a1 && \ + pip install --upgrade requests && \ + pip install cryptography && \ + pip install pyopenssl ndg-httpsclient pyasn1 + +ENV PYTHONPATH ./src:PYTHONPATH + +RUN echo '#!/bin/bash'>./az && \ + echo 'python -m azure.cli "$@"'>>./az && \ + chmod +x ./az && \ + ./az + +ENV EDITOR vim From e0d8d9ba7c0b3b4c7b51bce089f7806bc5e0d00c Mon Sep 17 00:00:00 2001 From: yugangw-msft Date: Mon, 29 Feb 2016 20:09:07 -0800 Subject: [PATCH 19/23] use env set correctly to set pythonpath in docker image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 815df5af5..896e0afa1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN apt-get update -qq && \ pip install cryptography && \ pip install pyopenssl ndg-httpsclient pyasn1 -ENV PYTHONPATH ./src:PYTHONPATH +ENV PYTHONPATH ./src:$PYTHONPATH RUN echo '#!/bin/bash'>./az && \ echo 'python -m azure.cli "$@"'>>./az && \ From f11d29c6a94eddba7b9963acd11f1966a633a89f Mon Sep 17 00:00:00 2001 From: yugangw-msft Date: Mon, 29 Feb 2016 21:21:40 -0800 Subject: [PATCH 20/23] set up path and pythonpath in docker file --- Dockerfile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 896e0afa1..4798613b1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,11 +21,13 @@ RUN apt-get update -qq && \ pip install cryptography && \ pip install pyopenssl ndg-httpsclient pyasn1 -ENV PYTHONPATH ./src:$PYTHONPATH +ENV PYTHONPATH $PYTHONPATH:/root/azure-cli/src +ENV PATH $PATH:/root/azure-cli -RUN echo '#!/bin/bash'>./az && \ - echo 'python -m azure.cli "$@"'>>./az && \ - chmod +x ./az && \ - ./az +RUN echo `pwd` && \ + echo '#!/bin/bash'>~/azure-cli/az && \ + echo 'python ~/azure-cli/src/azure/cli/__main__.py "$@"'>>~/azure-cli/az && \ + chmod +x ~/azure-cli/az && \ + az ENV EDITOR vim From 88d81aa59c9ef03001968c26cf79dc6a92466518 Mon Sep 17 00:00:00 2001 From: yugangw-msft Date: Tue, 1 Mar 2016 08:09:11 -0800 Subject: [PATCH 21/23] enabled lint error for trailing whitespaces --- pylintrc | 3 +-- src/azure/cli/_argparse.py | 24 ++++++++++----------- src/azure/cli/_debug.py | 13 +++++------ src/azure/cli/_locale.py | 10 ++++----- src/azure/cli/_logging.py | 4 ++-- src/azure/cli/_output.py | 10 ++++----- src/azure/cli/_profile.py | 12 +++++------ src/azure/cli/commands/__init__.py | 4 ++-- src/azure/cli/commands/_command_creation.py | 4 ++-- src/azure/cli/commands/login.py | 8 +++---- src/azure/cli/commands/storage.py | 6 +++--- src/azure/cli/main.py | 8 +++---- 12 files changed, 53 insertions(+), 53 deletions(-) diff --git a/pylintrc b/pylintrc index f9e4a383c..f30419087 100644 --- a/pylintrc +++ b/pylintrc @@ -2,10 +2,9 @@ # For all codes, run 'pylint --list-msgs' or go to 'http://pylint-messages.wikidot.com/all-codes' # C0111 Missing docstring # C0103 Invalid %s name "%s" -# C0303 Trailing whitespace # I0011 Warning locally suppressed using disable-msg # W0511 fixme -disable=C0111,C0103,C0303,I0011,W0511 +disable=C0111,C0103,I0011,W0511 [DESIGN] # Maximum number of locals for function / method body max-locals=25 diff --git a/src/azure/cli/_argparse.py b/src/azure/cli/_argparse.py index 623bfbadc..70abf3e3b 100644 --- a/src/azure/cli/_argparse.py +++ b/src/azure/cli/_argparse.py @@ -1,4 +1,4 @@ -from __future__ import print_function +from __future__ import print_function import sys from ._locale import L, get_file as locale_get_file @@ -69,9 +69,9 @@ class ArgumentParser(object): self.global_args = {'--verbose', '--debug'} def add_command(self, - handler, - name=None, - description=None, + handler, + name=None, + description=None, args=None): '''Registers a command that may be parsed by this parser. @@ -124,9 +124,9 @@ class ArgumentParser(object): def execute(self, - args, - show_usage=False, - show_completions=False, + args, + show_usage=False, + show_completions=False, out=sys.stdout): '''Parses `args` and invokes the associated handler. @@ -173,7 +173,7 @@ class ArgumentParser(object): except LookupError: logger.debug('Missing data for noun %s', n) show_usage = True - + if show_completions: return ArgumentParser._display_completions(m, out) if show_usage: @@ -195,7 +195,7 @@ class ArgumentParser(object): elif target_value[1] is True: # Arg with no value if value is not None: - print(L("argument '{0}' does not take a value").format(key_n), + print(L("argument '{0}' does not take a value").format(key_n), file=out) return self._display_usage(nouns, m, out) parsed.add_from_dotted(target_value[0], True) @@ -219,12 +219,12 @@ class ArgumentParser(object): finally: sys.stdout = old_stdout - def _display_usage(self, nouns, noun_map, out=sys.stdout): + def _display_usage(self, nouns, noun_map, out=sys.stdout): spec = ' '.join(noun_map.get('$spec') or nouns) print(' {} {}'.format(self.prog, spec), file=out) print(file=out) out.flush() - + subnouns = sorted(k for k in noun_map if not k.startswith('$')) if subnouns: print('Subcommands', file=out) @@ -232,7 +232,7 @@ class ArgumentParser(object): print(' {}'.format(n), file=out) print(file=out) out.flush() - + argdoc = noun_map.get('$argdoc') if argdoc: print('Arguments', file=out) diff --git a/src/azure/cli/_debug.py b/src/azure/cli/_debug.py index c5d8a1db7..806fcb252 100644 --- a/src/azure/cli/_debug.py +++ b/src/azure/cli/_debug.py @@ -1,13 +1,14 @@ -import os +import os from ._logging import logger DISABLE_VERIFY_VARIABLE_NAME = "AZURE_CLI_DISABLE_CONNECTION_VERIFICATION" -def allow_debug_connection(client): - if should_disable_connection_verify(): +def allow_debug_connection(client): + if should_disable_connection_verify(): logger.warning("Connection verification disabled by environment variable %s", DISABLE_VERIFY_VARIABLE_NAME) client.config.connection.verify = False - -def should_disable_connection_verify(): - return bool(os.environ.get(DISABLE_VERIFY_VARIABLE_NAME)) + +def should_disable_connection_verify(): + return bool(os.environ.get(DISABLE_VERIFY_VARIABLE_NAME)) + diff --git a/src/azure/cli/_locale.py b/src/azure/cli/_locale.py index b56abe94a..7ded22207 100644 --- a/src/azure/cli/_locale.py +++ b/src/azure/cli/_locale.py @@ -1,15 +1,15 @@ -import os.path +import os.path from codecs import open as codecs_open _translations = dict() _locale_dir = '' def L(key): - return _translations.get(key) or ''.format(key) + return _translations.get(key) or ''.format(key) def install(locale_dir): mapping = [] - + with codecs_open(os.path.join(locale_dir, "messages.txt"), 'r', encoding='utf-8-sig') as f: for i in f: if not i or i.startswith('#') or not i.strip(): @@ -18,7 +18,7 @@ def install(locale_dir): mapping.append((i[5:].strip(), None)) else: mapping[-1] = (mapping[-1][0], i.strip()) - + globals()['_translations'] = dict(mapping) globals()['_locale_dir'] = locale_dir @@ -27,5 +27,5 @@ def get_file(name): src = _locale_dir except (NameError, AttributeError): raise RuntimeError("localizations not installed") - + return os.path.join(src, name) diff --git a/src/azure/cli/_logging.py b/src/azure/cli/_logging.py index 0102e0aab..c0dc58797 100644 --- a/src/azure/cli/_logging.py +++ b/src/azure/cli/_logging.py @@ -1,4 +1,4 @@ -import logging as _logging +import logging as _logging import sys __all__ = ['logger', 'configure_logging'] @@ -13,7 +13,7 @@ def _arg_name(arg): def configure_logging(argv, config): level = _logging.WARNING - + # Load logging info from config if config.get('verbose'): level = _logging.INFO diff --git a/src/azure/cli/_output.py b/src/azure/cli/_output.py index 529e25ea9..f5dc596f7 100644 --- a/src/azure/cli/_output.py +++ b/src/azure/cli/_output.py @@ -1,4 +1,4 @@ -from __future__ import print_function, unicode_literals +from __future__ import print_function, unicode_literals import sys import json @@ -40,8 +40,8 @@ def format_text(obj): except TypeError: return '' -class OutputProducer(object): #pylint: disable=too-few-public-methods - +class OutputProducer(object): #pylint: disable=too-few-public-methods + def __init__(self, formatter=format_json, file=sys.stdout): #pylint: disable=redefined-builtin self.formatter = formatter self.file = file @@ -58,7 +58,7 @@ class TableOutput(object): def dump(self): if len(self._rows) == 1: return - + with StringIO() as io: cols = [(c, self._columns[c]) for c in self._column_order] io.write(' | '.join(c.center(w) for c, w in cols)) @@ -91,7 +91,7 @@ class TextOutput(object): def __init__(self): self.identifiers = {} - + def add(self, identifier, value): if identifier in self.identifiers: self.identifiers[identifier].append(value) diff --git a/src/azure/cli/_profile.py b/src/azure/cli/_profile.py index 87834bbef..af5b58667 100644 --- a/src/azure/cli/_profile.py +++ b/src/azure/cli/_profile.py @@ -59,20 +59,20 @@ class Profile(object): raise ValueError('Please run "account set" to select active account.') return BasicTokenAuthentication( - {'access_token': active[0]['access_token']}), active[0]['id'] + {'access_token': active[0]['access_token']}), active[0]['id'] def set_active_subscription(self, subscription_id_or_name): subscriptions = self.load_subscriptions() - + subscription_id_or_name = subscription_id_or_name.lower() - result = [x for x in subscriptions - if subscription_id_or_name == x['id'].lower() or + result = [x for x in subscriptions + if subscription_id_or_name == x['id'].lower() or subscription_id_or_name == x['name'].lower()] if len(result) != 1: raise ValueError('The subscription of "{}" does not exist or has more than' ' one match.'.format(subscription_id_or_name)) - + for s in subscriptions: s['active'] = False result[0]['active'] = True @@ -90,7 +90,7 @@ class Profile(object): subscriptions[0]['active'] = True self._save_subscriptions(subscriptions) - + def load_subscriptions(self): return self._storage.get('subscriptions') or [] diff --git a/src/azure/cli/commands/__init__.py b/src/azure/cli/commands/__init__.py index b39c45a54..d27ce5d15 100644 --- a/src/azure/cli/commands/__init__.py +++ b/src/azure/cli/commands/__init__.py @@ -1,4 +1,4 @@ -from .._argparse import IncorrectUsageError +from .._argparse import IncorrectUsageError from .._logging import logger # TODO: Alternatively, simply scan the directory for all modules @@ -41,7 +41,7 @@ def add_to_parser(parser, command_name=None): When `command` is specified, only commands from that module will be loaded. If the module is not found, all commands are loaded. ''' - + # Importing the modules is sufficient to invoke the decorators. Then we can # get all of the commands from the _COMMANDS variable. loaded = False diff --git a/src/azure/cli/commands/_command_creation.py b/src/azure/cli/commands/_command_creation.py index daacf0aeb..5c46fa04c 100644 --- a/src/azure/cli/commands/_command_creation.py +++ b/src/azure/cli/commands/_command_creation.py @@ -1,10 +1,10 @@ -from .._profile import Profile +from .._profile import Profile import azure.cli._debug as _debug import azure.cli as cli def get_service_client(client_type, config_type): profile = Profile() client = client_type(config_type(*profile.get_login_credentials())) - _debug.allow_debug_connection(client) + _debug.allow_debug_connection(client) client.config.add_user_agent("AZURECLI_{}".format(cli.__version__)) return client diff --git a/src/azure/cli/commands/login.py b/src/azure/cli/commands/login.py index 31125f349..fc165e373 100644 --- a/src/azure/cli/commands/login.py +++ b/src/azure/cli/commands/login.py @@ -22,9 +22,9 @@ def login(args, unexpected): #pylint: disable=unused-argument import getpass password = getpass.getpass(L('Password: ')) - credentials = UserPassCredentials(username, - password, - client_id=CLIENT_ID, + credentials = UserPassCredentials(username, + password, + client_id=CLIENT_ID, verify=not should_disable_connection_verify()) client = SubscriptionClient(SubscriptionClientConfiguration(credentials)) subscriptions = client.subscriptions.list() @@ -34,7 +34,7 @@ def login(args, unexpected): #pylint: disable=unused-argument serializable = Serializer().serialize_data(subscriptions, "[Subscription]") - #keep useful properties and not json serializable + #keep useful properties and not json serializable profile = Profile() consolidated = Profile.normalize_properties(username, subscriptions) profile.set_subscriptions(consolidated, credentials.token['access_token']) diff --git a/src/azure/cli/commands/storage.py b/src/azure/cli/commands/storage.py index b765431c9..6a7ca9514 100644 --- a/src/azure/cli/commands/storage.py +++ b/src/azure/cli/commands/storage.py @@ -1,4 +1,4 @@ -from msrest import Serializer +from msrest import Serializer from ..commands import command, description, option from ._command_creation import get_service_client from .._logging import logger @@ -8,7 +8,7 @@ from .._locale import L @description(L('List storage accounts')) @option('--resource-group -g ', L('the resource group name')) @option('--subscription -s ', L('the subscription id')) -def list_accounts(args, unexpected): #pylint: disable=unused-argument +def list_accounts(args, unexpected): #pylint: disable=unused-argument from azure.mgmt.storage import StorageManagementClient, StorageManagementClientConfiguration from azure.mgmt.storage.models import StorageAccount from msrestazure.azure_active_directory import UserPassCredentials @@ -26,7 +26,7 @@ def list_accounts(args, unexpected): #pylint: disable=unused-argument @command('storage account check') @option('--account-name ') -def checkname(args, unexpected): #pylint: disable=unused-argument +def checkname(args, unexpected): #pylint: disable=unused-argument from azure.mgmt.storage import StorageManagementClient, StorageManagementClientConfiguration smc = get_service_client(StorageManagementClient, StorageManagementClientConfiguration) logger.warning(smc.storage_accounts.check_name_availability(args.account_name)) diff --git a/src/azure/cli/main.py b/src/azure/cli/main.py index a685484cc..7c822cca7 100644 --- a/src/azure/cli/main.py +++ b/src/azure/cli/main.py @@ -1,4 +1,4 @@ -import os +import os from ._argparse import ArgumentParser from ._logging import configure_logging, logger @@ -18,8 +18,8 @@ def main(args): configure_logging(args, CONFIG) from ._locale import install as locale_install - locale_install(os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'locale', + locale_install(os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'locale', CONFIG.get('locale', 'en-US'))) @@ -36,7 +36,7 @@ def main(args): else: # No noun found, so load all commands. commands.add_to_parser(parser) - + try: result = parser.execute(args) # Commands can return a dictionary/list of results From b24354da02a9b56cfa9c614339dd3e15d0d0922f Mon Sep 17 00:00:00 2001 From: yugangw-msft Date: Tue, 1 Mar 2016 08:58:44 -0800 Subject: [PATCH 22/23] Use /tmp staging folder to confiure azure cli to run from --- Dockerfile | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4798613b1..d6c1c213c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,13 +21,16 @@ RUN apt-get update -qq && \ pip install cryptography && \ pip install pyopenssl ndg-httpsclient pyasn1 -ENV PYTHONPATH $PYTHONPATH:/root/azure-cli/src -ENV PATH $PATH:/root/azure-cli +ENV AZURECLITEMP /tmp/azure-cli +ENV PYTHONPATH $PYTHONPATH:$AZURECLITEMP/src +ENV PATH $PATH:$AZURECLITEMP -RUN echo `pwd` && \ - echo '#!/bin/bash'>~/azure-cli/az && \ - echo 'python ~/azure-cli/src/azure/cli/__main__.py "$@"'>>~/azure-cli/az && \ - chmod +x ~/azure-cli/az && \ - az +RUN mkdir -p $AZURECLITEMP && \ + cp src $AZURECLITEMP -R + +RUN echo '#!/bin/bash'>$AZURECLITEMP/az && \ + echo 'python -m azure.cli "$@"'>>$AZURECLITEMP/az && \ + chmod +x $AZURECLITEMP/az && \ + az ENV EDITOR vim From 25468ddb311e538b219591f4e90a4a6a2ef340ed Mon Sep 17 00:00:00 2001 From: yugangw-msft Date: Tue, 1 Mar 2016 10:10:03 -0800 Subject: [PATCH 23/23] Use ADD to copy cli from local into container --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index d6c1c213c..204659f5c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,8 +25,8 @@ ENV AZURECLITEMP /tmp/azure-cli ENV PYTHONPATH $PYTHONPATH:$AZURECLITEMP/src ENV PATH $PATH:$AZURECLITEMP -RUN mkdir -p $AZURECLITEMP && \ - cp src $AZURECLITEMP -R +RUN mkdir -p $AZURECLITEMP +ADD src $AZURECLITEMP/src RUN echo '#!/bin/bash'>$AZURECLITEMP/az && \ echo 'python -m azure.cli "$@"'>>$AZURECLITEMP/az && \