зеркало из https://github.com/microsoft/azure-cli.git
Merge branch 'master' into pip-requirements
Moved the pylint requirement to the requirements.txt file # Conflicts: # .travis.yml
This commit is contained in:
Коммит
2fc6d50d1c
|
@ -7,4 +7,6 @@ install:
|
||||||
- pip install -r requirements.txt
|
- pip install -r requirements.txt
|
||||||
script:
|
script:
|
||||||
- export PYTHONPATH=$PATHONPATH:./src
|
- export PYTHONPATH=$PATHONPATH:./src
|
||||||
- python -m unittest discover -s src/azure/cli/tests
|
- python -m azure.cli
|
||||||
|
- pylint src/azure
|
||||||
|
- python -m unittest discover -s src/azure/cli/tests
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
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 AZURECLITEMP /tmp/azure-cli
|
||||||
|
ENV PYTHONPATH $PYTHONPATH:$AZURECLITEMP/src
|
||||||
|
ENV PATH $PATH:$AZURECLITEMP
|
||||||
|
|
||||||
|
RUN mkdir -p $AZURECLITEMP
|
||||||
|
ADD src $AZURECLITEMP/src
|
||||||
|
|
||||||
|
RUN echo '#!/bin/bash'>$AZURECLITEMP/az && \
|
||||||
|
echo 'python -m azure.cli "$@"'>>$AZURECLITEMP/az && \
|
||||||
|
chmod +x $AZURECLITEMP/az && \
|
||||||
|
az
|
||||||
|
|
||||||
|
ENV EDITOR vim
|
|
@ -0,0 +1,15 @@
|
||||||
|
#!/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 "$@"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
@echo off
|
||||||
|
setlocal
|
||||||
|
|
||||||
|
SET PYTHONPATH=%~dp0/src;%PYTHONPATH%
|
||||||
|
python -m azure.cli %*
|
||||||
|
|
||||||
|
endlocal
|
|
@ -14,6 +14,9 @@
|
||||||
<LaunchProvider>Standard Python launcher</LaunchProvider>
|
<LaunchProvider>Standard Python launcher</LaunchProvider>
|
||||||
<InterpreterId>{1dd9c42b-5980-42ce-a2c3-46d3bf0eede4}</InterpreterId>
|
<InterpreterId>{1dd9c42b-5980-42ce-a2c3-46d3bf0eede4}</InterpreterId>
|
||||||
<InterpreterVersion>3.5</InterpreterVersion>
|
<InterpreterVersion>3.5</InterpreterVersion>
|
||||||
|
<CommandLineArguments>
|
||||||
|
</CommandLineArguments>
|
||||||
|
<EnableNativeCodeDebugging>False</EnableNativeCodeDebugging>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'" />
|
<PropertyGroup Condition="'$(Configuration)' == 'Debug'" />
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'" />
|
<PropertyGroup Condition="'$(Configuration)' == 'Release'" />
|
||||||
|
@ -25,15 +28,23 @@
|
||||||
<Compile Include="azure\cli\commands\account.py" />
|
<Compile Include="azure\cli\commands\account.py" />
|
||||||
<Compile Include="azure\cli\commands\login.py" />
|
<Compile Include="azure\cli\commands\login.py" />
|
||||||
<Compile Include="azure\cli\commands\logout.py" />
|
<Compile Include="azure\cli\commands\logout.py" />
|
||||||
|
<Compile Include="azure\cli\commands\network.py" />
|
||||||
|
<Compile Include="azure\cli\commands\resourcegroup.py" />
|
||||||
<Compile Include="azure\cli\commands\storage.py" />
|
<Compile Include="azure\cli\commands\storage.py" />
|
||||||
|
<Compile Include="azure\cli\commands\vm.py" />
|
||||||
|
<Compile Include="azure\cli\commands\_auto_command.py" />
|
||||||
<Compile Include="azure\cli\commands\__init__.py" />
|
<Compile Include="azure\cli\commands\__init__.py" />
|
||||||
<Compile Include="azure\cli\main.py" />
|
<Compile Include="azure\cli\main.py" />
|
||||||
<Compile Include="azure\cli\tests\test_argparse.py">
|
<Compile Include="azure\cli\tests\test_argparse.py">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="azure\cli\tests\test_autocommand.py">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="azure\cli\tests\test_connection_verify.py">
|
<Compile Include="azure\cli\tests\test_connection_verify.py">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="azure\cli\tests\test_output.py" />
|
||||||
<Compile Include="azure\cli\tests\test_profile.py" />
|
<Compile Include="azure\cli\tests\test_profile.py" />
|
||||||
<Compile Include="azure\cli\_argparse.py" />
|
<Compile Include="azure\cli\_argparse.py" />
|
||||||
<Compile Include="azure\cli\commands\_command_creation.py">
|
<Compile Include="azure\cli\commands\_command_creation.py">
|
||||||
|
@ -42,7 +53,9 @@
|
||||||
<Compile Include="azure\cli\_debug.py">
|
<Compile Include="azure\cli\_debug.py">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="azure\cli\_locale.py" />
|
||||||
<Compile Include="azure\cli\_logging.py" />
|
<Compile Include="azure\cli\_logging.py" />
|
||||||
|
<Compile Include="azure\cli\_output.py" />
|
||||||
<Compile Include="azure\cli\_profile.py" />
|
<Compile Include="azure\cli\_profile.py" />
|
||||||
<Compile Include="azure\cli\_session.py">
|
<Compile Include="azure\cli\_session.py">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
|
|
|
@ -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 <clone root>\env
|
||||||
|
```
|
||||||
|
OSX/Ubuntu
|
||||||
|
```Shell
|
||||||
|
python –m venv <clone root>/env
|
||||||
|
```
|
||||||
|
|
||||||
|
+ Activate the env virtual environment by running:
|
||||||
|
|
||||||
|
Windows:
|
||||||
|
```BatchFile
|
||||||
|
<clone root>\env\scripts\activate.bat
|
||||||
|
```
|
||||||
|
OSX/Ubuntu (bash):
|
||||||
|
```Shell
|
||||||
|
. <clone root>/env/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
+ Install the latest autorest generated azure sdk.
|
||||||
|
```Shell
|
||||||
|
python –m pip install azure==2.0.0a1
|
||||||
|
```
|
||||||
|
+ Add <clone root>\src to your PYTHONPATH environment variable:
|
||||||
|
|
||||||
|
Windows:
|
||||||
|
```BatchFile
|
||||||
|
set PYTHONPATH=<clone root>\src;%PYTHONPATH%
|
||||||
|
```
|
||||||
|
OSX/Ubuntu (bash):
|
||||||
|
```Shell
|
||||||
|
export PYTHONPATH=<clone root>/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 <clone root>/src directory.
|
||||||
|
|
||||||
|
###VS Code:
|
||||||
|
<Working on it>
|
||||||
|
|
||||||
|
###Visual Studio
|
||||||
|
<Working on it>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
[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"
|
||||||
|
# I0011 Warning locally suppressed using disable-msg
|
||||||
|
# W0511 fixme
|
||||||
|
disable=C0111,C0103,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
|
|
@ -1,3 +1,3 @@
|
||||||
azure==2.0.0a1
|
azure==2.0.0a1
|
||||||
mock==1.3.0
|
mock==1.3.0
|
||||||
|
pylint==1.5.4
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import sys
|
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
|
from ._logging import logger
|
||||||
|
|
||||||
# Named arguments are prefixed with one of these strings
|
# Named arguments are prefixed with one of these strings
|
||||||
|
@ -20,7 +18,7 @@ class IncorrectUsageError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Arguments(dict):
|
class Arguments(dict):
|
||||||
def __init__(self, source=None):
|
def __init__(self, source=None): #pylint: disable=super-init-not-called
|
||||||
self.positional = []
|
self.positional = []
|
||||||
if source:
|
if source:
|
||||||
self.update(source)
|
self.update(source)
|
||||||
|
@ -40,7 +38,7 @@ class Arguments(dict):
|
||||||
except LookupError:
|
except LookupError:
|
||||||
pass
|
pass
|
||||||
logger.debug('Argument %s is required', key)
|
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):
|
def _read_arg(string):
|
||||||
for prefix in ARG_PREFIXES:
|
for prefix in ARG_PREFIXES:
|
||||||
|
@ -66,11 +64,15 @@ class ArgumentParser(object):
|
||||||
self.noun_map = {
|
self.noun_map = {
|
||||||
'$doc': 'azure-cli.txt',
|
'$doc': 'azure-cli.txt',
|
||||||
}
|
}
|
||||||
self.help_args = { '--help', '-h' }
|
self.help_args = {'--help', '-h'}
|
||||||
self.complete_args = { '--complete' }
|
self.complete_args = {'--complete'}
|
||||||
self.global_args = { '--verbose', '--debug' }
|
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.
|
'''Registers a command that may be parsed by this parser.
|
||||||
|
|
||||||
`handler` is the function to call with two `Arguments` objects.
|
`handler` is the function to call with two `Arguments` objects.
|
||||||
|
@ -105,7 +107,7 @@ class ArgumentParser(object):
|
||||||
m['$args'] = []
|
m['$args'] = []
|
||||||
m['$kwargs'] = kw = {}
|
m['$kwargs'] = kw = {}
|
||||||
m['$argdoc'] = ad = []
|
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):
|
if not any(spec.startswith(p) for p in ARG_PREFIXES):
|
||||||
m['$args'].append(spec.strip('<> '))
|
m['$args'].append(spec.strip('<> '))
|
||||||
ad.append((spec, desc))
|
ad.append((spec, desc))
|
||||||
|
@ -121,7 +123,11 @@ class ArgumentParser(object):
|
||||||
ad.append(('/'.join(aliases), desc))
|
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.
|
'''Parses `args` and invokes the associated handler.
|
||||||
|
|
||||||
The handler is passed two `Arguments` objects with all arguments other
|
The handler is passed two `Arguments` objects with all arguments other
|
||||||
|
@ -142,10 +148,11 @@ class ArgumentParser(object):
|
||||||
if not show_completions:
|
if not show_completions:
|
||||||
show_completions = any(a in self.complete_args for a in args)
|
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):
|
def not_global(a):
|
||||||
return a.lstrip('-/') not in all_global_args
|
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
|
m = self.noun_map
|
||||||
nouns = []
|
nouns = []
|
||||||
|
@ -161,17 +168,16 @@ class ArgumentParser(object):
|
||||||
n = next(it, '')
|
n = next(it, '')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
expected_args = m['$args']
|
|
||||||
expected_kwargs = m['$kwargs']
|
expected_kwargs = m['$kwargs']
|
||||||
handler = m['$handler']
|
handler = m['$handler']
|
||||||
except LookupError:
|
except LookupError:
|
||||||
logger.debug('Missing data for noun %s', n)
|
logger.debug('Missing data for noun %s', n)
|
||||||
show_usage = True
|
show_usage = True
|
||||||
|
|
||||||
if show_completions:
|
if show_completions:
|
||||||
return self._display_completions(nouns, m, args, out)
|
return ArgumentParser._display_completions(m, out)
|
||||||
if show_usage:
|
if show_usage:
|
||||||
return self._display_usage(nouns, m, args, out)
|
return self._display_usage(nouns, m, out)
|
||||||
|
|
||||||
parsed = Arguments()
|
parsed = Arguments()
|
||||||
others = Arguments()
|
others = Arguments()
|
||||||
|
@ -189,8 +195,9 @@ class ArgumentParser(object):
|
||||||
elif target_value[1] is True:
|
elif target_value[1] is True:
|
||||||
# Arg with no value
|
# Arg with no value
|
||||||
if value is not None:
|
if value is not None:
|
||||||
print(_("argument '{0}' does not take a value").format(key_n), file=out)
|
print(L("argument '{0}' does not take a value").format(key_n),
|
||||||
return self._display_usage(nouns, m, args, out)
|
file=out)
|
||||||
|
return self._display_usage(nouns, m, out)
|
||||||
parsed.add_from_dotted(target_value[0], True)
|
parsed.add_from_dotted(target_value[0], True)
|
||||||
else:
|
else:
|
||||||
# Arg with a value
|
# Arg with a value
|
||||||
|
@ -208,16 +215,16 @@ class ArgumentParser(object):
|
||||||
return handler(parsed, others)
|
return handler(parsed, others)
|
||||||
except IncorrectUsageError as ex:
|
except IncorrectUsageError as ex:
|
||||||
print(str(ex), file=out)
|
print(str(ex), file=out)
|
||||||
return self.display_usage(nouns, m, args, out)
|
return self._display_usage(nouns, m, out)
|
||||||
finally:
|
finally:
|
||||||
sys.stdout = old_stdout
|
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)
|
spec = ' '.join(noun_map.get('$spec') or nouns)
|
||||||
print(' {} {}'.format(self.prog, spec), file=out)
|
print(' {} {}'.format(self.prog, spec), file=out)
|
||||||
print(file=out)
|
print(file=out)
|
||||||
out.flush()
|
out.flush()
|
||||||
|
|
||||||
subnouns = sorted(k for k in noun_map if not k.startswith('$'))
|
subnouns = sorted(k for k in noun_map if not k.startswith('$'))
|
||||||
if subnouns:
|
if subnouns:
|
||||||
print('Subcommands', file=out)
|
print('Subcommands', file=out)
|
||||||
|
@ -225,7 +232,7 @@ class ArgumentParser(object):
|
||||||
print(' {}'.format(n), file=out)
|
print(' {}'.format(n), file=out)
|
||||||
print(file=out)
|
print(file=out)
|
||||||
out.flush()
|
out.flush()
|
||||||
|
|
||||||
argdoc = noun_map.get('$argdoc')
|
argdoc = noun_map.get('$argdoc')
|
||||||
if argdoc:
|
if argdoc:
|
||||||
print('Arguments', file=out)
|
print('Arguments', file=out)
|
||||||
|
@ -246,7 +253,8 @@ class ArgumentParser(object):
|
||||||
out.flush()
|
out.flush()
|
||||||
logger.debug('Expected documentation at %s', doc_file)
|
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('$')]
|
completions = [k for k in noun_map if not k.startswith('$')]
|
||||||
|
|
||||||
kwargs = noun_map.get('$kwargs')
|
kwargs = noun_map.get('$kwargs')
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import os
|
import os
|
||||||
from ._logging import logger
|
from ._logging import logger
|
||||||
|
|
||||||
DISABLE_VERIFY_VARIABLE_NAME = "AZURE_CLI_DISABLE_CONNECTION_VERIFICATION"
|
DISABLE_VERIFY_VARIABLE_NAME = "AZURE_CLI_DISABLE_CONNECTION_VERIFICATION"
|
||||||
|
|
||||||
def allow_debug_connection(client):
|
def allow_debug_connection(client):
|
||||||
if should_disable_connection_verify():
|
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
|
client.config.connection.verify = False
|
||||||
|
|
||||||
def should_disable_connection_verify():
|
def should_disable_connection_verify():
|
||||||
return bool(os.environ.get(DISABLE_VERIFY_VARIABLE_NAME))
|
return bool(os.environ.get(DISABLE_VERIFY_VARIABLE_NAME))
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
import os.path
|
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 '<NO_TRANSLATION:{}>'.format(key)
|
||||||
|
|
||||||
def install(locale_dir):
|
def install(locale_dir):
|
||||||
mapping = []
|
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:
|
for i in f:
|
||||||
if not i or i.startswith('#') or not i.strip():
|
if not i or i.startswith('#') or not i.strip():
|
||||||
continue
|
continue
|
||||||
|
@ -13,18 +18,14 @@ def install(locale_dir):
|
||||||
mapping.append((i[5:].strip(), None))
|
mapping.append((i[5:].strip(), None))
|
||||||
else:
|
else:
|
||||||
mapping[-1] = (mapping[-1][0], i.strip())
|
mapping[-1] = (mapping[-1][0], i.strip())
|
||||||
|
|
||||||
translations = dict(mapping)
|
globals()['_translations'] = dict(mapping)
|
||||||
def _(key):
|
globals()['_locale_dir'] = locale_dir
|
||||||
return translations.get(key) or '<NO_TRANSLATION:{}>'.format(key)
|
|
||||||
_.locale_dir = locale_dir
|
|
||||||
|
|
||||||
__builtins__['_'] = _
|
|
||||||
|
|
||||||
def get_file(name):
|
def get_file(name):
|
||||||
try:
|
try:
|
||||||
src = _.locale_dir
|
src = _locale_dir
|
||||||
except (NameError, AttributeError):
|
except (NameError, AttributeError):
|
||||||
raise RuntimeError("localizations not installed")
|
raise RuntimeError("localizations not installed")
|
||||||
|
|
||||||
return os.path.join(src, name)
|
return os.path.join(src, name)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import logging as _logging
|
import logging as _logging
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
__all__ = ['logging', 'configure_logging']
|
__all__ = ['logger', 'configure_logging']
|
||||||
|
|
||||||
logger = _logging.Logger('az', _logging.WARNING)
|
logger = _logging.Logger('az', _logging.WARNING)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ def _arg_name(arg):
|
||||||
|
|
||||||
def configure_logging(argv, config):
|
def configure_logging(argv, config):
|
||||||
level = _logging.WARNING
|
level = _logging.WARNING
|
||||||
|
|
||||||
# Load logging info from config
|
# Load logging info from config
|
||||||
if config.get('verbose'):
|
if config.get('verbose'):
|
||||||
level = _logging.INFO
|
level = _logging.INFO
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from __future__ import print_function, unicode_literals
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
@ -8,7 +8,7 @@ try:
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# Python 2
|
# Python 2
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO #pylint: disable=import-error
|
||||||
|
|
||||||
class OutputFormatException(Exception):
|
class OutputFormatException(Exception):
|
||||||
pass
|
pass
|
||||||
|
@ -40,9 +40,9 @@ def format_text(obj):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return ''
|
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.formatter = formatter
|
||||||
self.file = file
|
self.file = file
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ class TableOutput(object):
|
||||||
def dump(self):
|
def dump(self):
|
||||||
if len(self._rows) == 1:
|
if len(self._rows) == 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
with StringIO() as io:
|
with StringIO() as io:
|
||||||
cols = [(c, self._columns[c]) for c in self._column_order]
|
cols = [(c, self._columns[c]) for c in self._column_order]
|
||||||
io.write(' | '.join(c.center(w) for c, w in cols))
|
io.write(' | '.join(c.center(w) for c, w in cols))
|
||||||
|
@ -91,7 +91,7 @@ class TextOutput(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.identifiers = {}
|
self.identifiers = {}
|
||||||
|
|
||||||
def add(self, identifier, value):
|
def add(self, identifier, value):
|
||||||
if identifier in self.identifiers:
|
if identifier in self.identifiers:
|
||||||
self.identifiers[identifier].append(value)
|
self.identifiers[identifier].append(value)
|
||||||
|
@ -100,14 +100,14 @@ class TextOutput(object):
|
||||||
|
|
||||||
def dump(self):
|
def dump(self):
|
||||||
with StringIO() as io:
|
with StringIO() as io:
|
||||||
for id in sorted(self.identifiers):
|
for identifier in sorted(self.identifiers):
|
||||||
io.write(id.upper())
|
io.write(identifier.upper())
|
||||||
io.write('\t')
|
io.write('\t')
|
||||||
for col in self.identifiers[id]:
|
for col in self.identifiers[identifier]:
|
||||||
if isinstance(col, str):
|
if isinstance(col, str):
|
||||||
io.write(col)
|
io.write(col)
|
||||||
else:
|
else:
|
||||||
# TODO: Handle complex objects
|
# TODO: Need to handle complex objects
|
||||||
io.write("null")
|
io.write("null")
|
||||||
io.write('\t')
|
io.write('\t')
|
||||||
io.write('\n')
|
io.write('\n')
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from msrest.authentication import BasicTokenAuthentication
|
import collections
|
||||||
|
from msrest.authentication import BasicTokenAuthentication
|
||||||
from .main import CONFIG
|
from .main import CONFIG
|
||||||
import collections
|
|
||||||
|
|
||||||
class Profile(object):
|
class Profile(object):
|
||||||
|
|
||||||
|
@ -37,10 +37,9 @@ class Profile(object):
|
||||||
for s in subscriptions:
|
for s in subscriptions:
|
||||||
s['active'] = False
|
s['active'] = False
|
||||||
|
|
||||||
if new_active_one:
|
if not new_active_one:
|
||||||
new_active_one['active'] = True
|
new_active_one = new_subscriptions[0]
|
||||||
else:
|
new_active_one['active'] = True
|
||||||
new_subscriptions[0]['active'] = True
|
|
||||||
else:
|
else:
|
||||||
new_subscriptions[0]['active'] = True
|
new_subscriptions[0]['active'] = True
|
||||||
|
|
||||||
|
@ -60,20 +59,20 @@ class Profile(object):
|
||||||
raise ValueError('Please run "account set" to select active account.')
|
raise ValueError('Please run "account set" to select active account.')
|
||||||
|
|
||||||
return BasicTokenAuthentication(
|
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):
|
def set_active_subscription(self, subscription_id_or_name):
|
||||||
subscriptions = self.load_subscriptions()
|
subscriptions = self.load_subscriptions()
|
||||||
|
|
||||||
subscription_id_or_name = subscription_id_or_name.lower()
|
subscription_id_or_name = subscription_id_or_name.lower()
|
||||||
result = [x for x in subscriptions
|
result = [x for x in subscriptions
|
||||||
if subscription_id_or_name == x['id'].lower() or
|
if subscription_id_or_name == x['id'].lower() or
|
||||||
subscription_id_or_name == x['name'].lower()]
|
subscription_id_or_name == x['name'].lower()]
|
||||||
|
|
||||||
if len(result) != 1:
|
if len(result) != 1:
|
||||||
raise ValueError('The subscription of "{}" does not exist or has more than'
|
raise ValueError('The subscription of "{}" does not exist or has more than'
|
||||||
' one match.'.format(subscription_id_or_name))
|
' one match.'.format(subscription_id_or_name))
|
||||||
|
|
||||||
for s in subscriptions:
|
for s in subscriptions:
|
||||||
s['active'] = False
|
s['active'] = False
|
||||||
result[0]['active'] = True
|
result[0]['active'] = True
|
||||||
|
@ -91,7 +90,7 @@ class Profile(object):
|
||||||
subscriptions[0]['active'] = True
|
subscriptions[0]['active'] = True
|
||||||
|
|
||||||
self._save_subscriptions(subscriptions)
|
self._save_subscriptions(subscriptions)
|
||||||
|
|
||||||
def load_subscriptions(self):
|
def load_subscriptions(self):
|
||||||
return self._storage.get('subscriptions') or []
|
return self._storage.get('subscriptions') or []
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ except ImportError:
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
|
|
||||||
from codecs import open
|
from codecs import open as codecs_open
|
||||||
|
|
||||||
class Session(collections.MutableMapping):
|
class Session(collections.MutableMapping):
|
||||||
'''A simple dict-like class that is backed by a JSON file.
|
'''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)
|
st = os.stat(self.filename)
|
||||||
if st.st_mtime + max_age < time.clock():
|
if st.st_mtime + max_age < time.clock():
|
||||||
self.save()
|
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)
|
self.data = json.load(f)
|
||||||
except (OSError, IOError):
|
except (OSError, IOError):
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
if self.filename:
|
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)
|
json.dump(self.data, f)
|
||||||
|
|
||||||
def save_with_retry(self, retries=5):
|
def save_with_retry(self, retries=5):
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
|
|
||||||
def normalize_newlines(str_to_normalize):
|
def normalize_newlines(str_to_normalize):
|
||||||
return str_to_normalize.replace('\r\n', '\n')
|
return str_to_normalize.replace('\r\n', '\n')
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
from .._argparse import IncorrectUsageError
|
from .._argparse import IncorrectUsageError
|
||||||
from .._logging import logger
|
from .._logging import logger
|
||||||
|
|
||||||
# TODO: Alternatively, simply scan the directory for all modules
|
# TODO: Alternatively, simply scan the directory for all modules
|
||||||
COMMAND_MODULES = [
|
COMMAND_MODULES = [
|
||||||
|
'account',
|
||||||
'login',
|
'login',
|
||||||
'logout',
|
'logout',
|
||||||
'account',
|
'network',
|
||||||
|
'resourcegroup',
|
||||||
'storage',
|
'storage',
|
||||||
'resourcegroup'
|
'vm',
|
||||||
]
|
]
|
||||||
|
|
||||||
_COMMANDS = {}
|
_COMMANDS = {}
|
||||||
|
@ -19,33 +21,33 @@ def command(name):
|
||||||
return handler
|
return handler
|
||||||
return add_command
|
return add_command
|
||||||
|
|
||||||
def description(description):
|
def description(description_text):
|
||||||
def add_description(handler):
|
def add_description(handler):
|
||||||
_COMMANDS.setdefault(handler, {})['description'] = description
|
_COMMANDS.setdefault(handler, {})['description'] = description_text
|
||||||
logger.debug('Added description "%s" to %s', description, handler)
|
logger.debug('Added description "%s" to %s', description_text, handler)
|
||||||
return handler
|
return handler
|
||||||
return add_description
|
return add_description
|
||||||
|
|
||||||
def option(spec, description=None):
|
def option(spec, description_text=None):
|
||||||
def add_option(handler):
|
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)
|
logger.debug('Added option "%s" to %s', spec, handler)
|
||||||
return handler
|
return handler
|
||||||
return add_option
|
return add_option
|
||||||
|
|
||||||
def add_to_parser(parser, command=None):
|
def add_to_parser(parser, command_name=None):
|
||||||
'''Loads commands into the parser
|
'''Loads commands into the parser
|
||||||
|
|
||||||
When `command` is specified, only commands from that module will be loaded.
|
When `command` is specified, only commands from that module will be loaded.
|
||||||
If the module is not found, all commands are loaded.
|
If the module is not found, all commands are loaded.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# Importing the modules is sufficient to invoke the decorators. Then we can
|
# Importing the modules is sufficient to invoke the decorators. Then we can
|
||||||
# get all of the commands from the _COMMANDS variable.
|
# get all of the commands from the _COMMANDS variable.
|
||||||
loaded = False
|
loaded = False
|
||||||
if command:
|
if command_name:
|
||||||
try:
|
try:
|
||||||
__import__('azure.cli.commands.' + command)
|
__import__('azure.cli.commands.' + command_name)
|
||||||
loaded = True
|
loaded = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# Unknown command - we'll load all below
|
# Unknown command - we'll load all below
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import inspect
|
||||||
|
from msrest import Serializer
|
||||||
|
from ..commands import command, description, option
|
||||||
|
from azure.cli._argparse import IncorrectUsageError
|
||||||
|
|
||||||
|
def _decorate_command(name, func):
|
||||||
|
return command(name)(func)
|
||||||
|
|
||||||
|
def _decorate_description(desc, func):
|
||||||
|
return description(desc)(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): #pylint: disable=unused-argument
|
||||||
|
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 exception:
|
||||||
|
# TODO: Evaluate required/missing parameters and provide specific
|
||||||
|
# usage for missing params...
|
||||||
|
raise IncorrectUsageError(exception)
|
||||||
|
|
||||||
|
return call_client
|
||||||
|
|
||||||
|
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(operation).splitlines()
|
||||||
|
if l.startswith(':param') and arg + ':' in l)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
args = []
|
||||||
|
try:
|
||||||
|
# only supported in python3 - falling back to argspec if not available
|
||||||
|
sig = inspect.signature(operation)
|
||||||
|
args = sig.parameters
|
||||||
|
except AttributeError:
|
||||||
|
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]:
|
||||||
|
spec = '--%s <%s>' % (arg, arg)
|
||||||
|
func = _decorate_option(spec, _option_description(operation, arg), func=func)
|
|
@ -1,10 +1,10 @@
|
||||||
from .._profile import Profile
|
from .._profile import Profile
|
||||||
import azure.cli._debug as _debug
|
import azure.cli._debug as _debug
|
||||||
import azure.cli as cli
|
import azure.cli as cli
|
||||||
|
|
||||||
def get_service_client(client_type, config_type):
|
def get_service_client(client_type, config_type):
|
||||||
profile = Profile()
|
profile = Profile()
|
||||||
client = client_type(config_type(*profile.get_login_credentials()))
|
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__))
|
client.config.add_user_agent("AZURECLI_{}".format(cli.__version__))
|
||||||
return client
|
return client
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
from .._profile import Profile
|
from .._profile import Profile
|
||||||
from ..commands import command, description, option
|
from ..commands import command, description, option
|
||||||
|
from .._locale import L
|
||||||
|
|
||||||
@command('account list')
|
@command('account list')
|
||||||
@description(_('List the imported subscriptions.'))
|
@description(L('List the imported subscriptions.'))
|
||||||
def list_subscriptions(args, unexpected):
|
def list_subscriptions(args, unexpected): #pylint: disable=unused-argument
|
||||||
profile = Profile()
|
profile = Profile()
|
||||||
subscriptions = profile.load_subscriptions()
|
subscriptions = profile.load_subscriptions()
|
||||||
|
|
||||||
return subscriptions
|
return subscriptions
|
||||||
|
|
||||||
@command('account set')
|
@command('account set')
|
||||||
@description(_('Set the current subscription'))
|
@description(L('Set the current subscription'))
|
||||||
@option('--subscription-id -n <subscription-id>', _('Subscription Id, unique name also works.'))
|
@option('--subscription-id -n <subscription-id>', L('Subscription Id, unique name also works.'))
|
||||||
def set_active_subscription(args, unexpected):
|
def set_active_subscription(args, unexpected): #pylint: disable=unused-argument
|
||||||
id = args.get('subscription-id')
|
subscription_id = args.get('subscription-id')
|
||||||
if not 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 = Profile()
|
||||||
profile.set_active_subscription(id)
|
profile.set_active_subscription(subscription_id)
|
||||||
|
|
|
@ -1,37 +1,40 @@
|
||||||
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, \
|
from azure.mgmt.resource.subscriptions import SubscriptionClient, \
|
||||||
SubscriptionClientConfiguration
|
SubscriptionClientConfiguration
|
||||||
|
|
||||||
from msrest import Serializer
|
|
||||||
|
|
||||||
from .._profile import Profile
|
from .._profile import Profile
|
||||||
from ..commands import command, description, option
|
from ..commands import command, description, option
|
||||||
from .._debug import should_disable_connection_verify
|
from .._debug import should_disable_connection_verify
|
||||||
|
from .._locale import L
|
||||||
|
|
||||||
CLIENT_ID = '04b07795-8ddb-461a-bbee-02f9e1bf7b46'
|
CLIENT_ID = '04b07795-8ddb-461a-bbee-02f9e1bf7b46'
|
||||||
|
|
||||||
@command('login')
|
@command('login')
|
||||||
@description(_('log in to an Azure subscription using Active Directory Organization Id'))
|
@description(L('log in to an Azure subscription using Active Directory Organization Id'))
|
||||||
@option('--username -u <username>', _('organization Id. Microsoft Account is not yet supported.'))
|
@option('--username -u <username>', L('organization Id. Microsoft Account is not yet supported.'))
|
||||||
@option('--password -p <password>', _('user password, will prompt if not given.'))
|
@option('--password -p <password>', L('user password, will prompt if not given.'))
|
||||||
def login(args, unexpected):
|
def login(args, unexpected): #pylint: disable=unused-argument
|
||||||
username = args.get('username')
|
username = args.get('username')
|
||||||
|
|
||||||
password = args.get('password')
|
password = args.get('password')
|
||||||
if not password:
|
if not password:
|
||||||
import getpass
|
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))
|
client = SubscriptionClient(SubscriptionClientConfiguration(credentials))
|
||||||
subscriptions = client.subscriptions.list()
|
subscriptions = client.subscriptions.list()
|
||||||
|
|
||||||
if not subscriptions:
|
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]")
|
serializable = Serializer().serialize_data(subscriptions, "[Subscription]")
|
||||||
|
|
||||||
#keep useful properties and not json serializable
|
#keep useful properties and not json serializable
|
||||||
profile = Profile()
|
profile = Profile()
|
||||||
consolidated = Profile.normalize_properties(username, subscriptions)
|
consolidated = Profile.normalize_properties(username, subscriptions)
|
||||||
profile.set_subscriptions(consolidated, credentials.token['access_token'])
|
profile.set_subscriptions(consolidated, credentials.token['access_token'])
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
from .._profile import Profile
|
from .._profile import Profile
|
||||||
from ..commands import command, description, option
|
from ..commands import command, description, option
|
||||||
|
from .._locale import L
|
||||||
|
|
||||||
@command('logout')
|
@command('logout')
|
||||||
@description(_('Log out from Azure subscription using Active Directory.'))
|
@description(L('Log out from Azure subscription using Active Directory.'))
|
||||||
@option('--username -u <username>', _('User name used to log out from Azure Active Directory.'))
|
@option('--username -u <username>', L('User name used to log out from Azure Active Directory.'))
|
||||||
def logout(args, unexpected):
|
def logout(args, unexpected): #pylint: disable=unused-argument
|
||||||
username = args.get('username')
|
username = args.get('username')
|
||||||
if not 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 = Profile()
|
||||||
profile.logout(username)
|
profile.logout(username)
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
def _network_client_factory():
|
||||||
|
return get_service_client(NetworkManagementClient, NetworkManagementClientConfiguration)
|
||||||
|
|
||||||
|
# pylint: disable=line-too-long
|
||||||
|
# Application gateways
|
||||||
|
_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,
|
||||||
|
[
|
||||||
|
(ExpressRouteCircuitAuthorizationsOperations.delete, None),
|
||||||
|
(ExpressRouteCircuitAuthorizationsOperations.get, 'ExpressRouteCircuitAuthorization'),
|
||||||
|
(ExpressRouteCircuitAuthorizationsOperations.list, '[ExpressRouteCircuitAuthorization]'),
|
||||||
|
])
|
||||||
|
|
||||||
|
# ExpressRouteCircuitPeeringsOperations
|
||||||
|
_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,
|
||||||
|
[
|
||||||
|
(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,
|
||||||
|
[
|
||||||
|
(ExpressRouteServiceProvidersOperations.list, '[ExpressRouteServiceProvider]'),
|
||||||
|
])
|
||||||
|
|
||||||
|
# LoadBalancersOperations
|
||||||
|
_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,
|
||||||
|
[
|
||||||
|
(LocalNetworkGatewaysOperations.get, 'LocalNetworkGateway'),
|
||||||
|
(LocalNetworkGatewaysOperations.delete, None),
|
||||||
|
(LocalNetworkGatewaysOperations.list, '[LocalNetworkGateway]'),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
# NetworkInterfacesOperations
|
||||||
|
_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,
|
||||||
|
[
|
||||||
|
(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,
|
||||||
|
[
|
||||||
|
(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,
|
||||||
|
[
|
||||||
|
(RouteTablesOperations.delete, None),
|
||||||
|
(RouteTablesOperations.get, 'RouteTable'),
|
||||||
|
(RouteTablesOperations.list, '[RouteTable]'),
|
||||||
|
(RouteTablesOperations.list_all, '[RouteTable]'),
|
||||||
|
])
|
||||||
|
|
||||||
|
# RoutesOperations
|
||||||
|
_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,
|
||||||
|
[
|
||||||
|
(SecurityRulesOperations.delete, None),
|
||||||
|
(SecurityRulesOperations.get, 'SecurityRule'),
|
||||||
|
(SecurityRulesOperations.list, '[SecurityRule]'),
|
||||||
|
])
|
||||||
|
|
||||||
|
# SubnetsOperations
|
||||||
|
_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,
|
||||||
|
[
|
||||||
|
(UsagesOperations.list, '[Usage]'),
|
||||||
|
])
|
||||||
|
|
||||||
|
# VirtualNetworkGatewayConnectionsOperations
|
||||||
|
_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,
|
||||||
|
[
|
||||||
|
(VirtualNetworkGatewaysOperations.delete, None),
|
||||||
|
(VirtualNetworkGatewaysOperations.get, 'VirtualNetworkGateway'),
|
||||||
|
(VirtualNetworkGatewaysOperations.list, '[VirtualNetworkGateway]'),
|
||||||
|
(VirtualNetworkGatewaysOperations.reset, 'VirtualNetworkGateway'),
|
||||||
|
])
|
||||||
|
|
||||||
|
# VirtualNetworksOperations
|
||||||
|
_auto_command.operation_builder("network",
|
||||||
|
"vnet",
|
||||||
|
"virtual_networks",
|
||||||
|
_network_client_factory,
|
||||||
|
[
|
||||||
|
(VirtualNetworksOperations.delete, None),
|
||||||
|
(VirtualNetworksOperations.get, 'VirtualNetwork'),
|
||||||
|
(VirtualNetworksOperations.list, '[VirtualNetwork]'),
|
||||||
|
(VirtualNetworksOperations.list_all, '[VirtualNetwork]'),
|
||||||
|
])
|
|
@ -1,24 +1,24 @@
|
||||||
from msrest import Serializer
|
from msrest import Serializer
|
||||||
|
from ..commands import command, description
|
||||||
from ..commands import command, description, option
|
|
||||||
from .._profile import Profile
|
from .._profile import Profile
|
||||||
|
|
||||||
@command('resource group list')
|
@command('resource group list')
|
||||||
@description('List resource groups')
|
@description('List resource groups')
|
||||||
# TODO: waiting on Python Azure SDK bug fixes
|
# TODO: waiting on Python Azure SDK bug fixes
|
||||||
#@option('--tag-name -g <tagName>', _("the resource group's tag name"))
|
# @option('--tag-name -g <tagName>', L('the resource group's tag name'))
|
||||||
#@option('--tag-value -g <tagValue>', _("the resource group's tag value"))
|
# @option('--tag-value -g <tagValue>', L('the resource group's tag value'))
|
||||||
#@option('--top -g <number>', _("Top N resource groups to retrieve"))
|
# @option('--top -g <number>', L('Top N resource groups to retrieve'))
|
||||||
def list_groups(args, unexpected):
|
def list_groups(args, unexpected): #pylint: disable=unused-argument
|
||||||
from azure.mgmt.resource.resources import ResourceManagementClient, ResourceManagementClientConfiguration
|
from azure.mgmt.resource.resources import ResourceManagementClient, \
|
||||||
|
ResourceManagementClientConfiguration
|
||||||
from azure.mgmt.resource.resources.models import ResourceGroup, ResourceGroupFilter
|
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
|
# TODO: waiting on Python Azure SDK bug fixes
|
||||||
#group_filter = ResourceGroupFilter(args.get('tag-name'), args.get('tag-value'))
|
#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(filter=None, top=args.get('top'))
|
||||||
groups = rmc.resource_groups.list()
|
groups = rmc.resource_groups.list()
|
||||||
|
|
||||||
serializable = Serializer().serialize_data(groups, "[ResourceGroup]")
|
serializable = Serializer().serialize_data(groups, "[ResourceGroup]")
|
||||||
return serializable
|
return serializable
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
from msrest import Serializer
|
from msrest import Serializer
|
||||||
|
|
||||||
from ..main import SESSION
|
|
||||||
from ..commands import command, description, option
|
from ..commands import command, description, option
|
||||||
from ._command_creation import get_service_client
|
from ._command_creation import get_service_client
|
||||||
|
from .._logging import logger
|
||||||
|
from .._locale import L
|
||||||
|
|
||||||
@command('storage account list')
|
@command('storage account list')
|
||||||
@description(_('List storage accounts'))
|
@description(L('List storage accounts'))
|
||||||
@option('--resource-group -g <resourceGroup>', _('the resource group name'))
|
@option('--resource-group -g <resourceGroup>', L('the resource group name'))
|
||||||
@option('--subscription -s <id>', _('the subscription id'))
|
@option('--subscription -s <id>', L('the subscription id'))
|
||||||
def list_accounts(args, unexpected):
|
def list_accounts(args, unexpected): #pylint: disable=unused-argument
|
||||||
from azure.mgmt.storage import StorageManagementClient, StorageManagementClientConfiguration
|
from azure.mgmt.storage import StorageManagementClient, StorageManagementClientConfiguration
|
||||||
from azure.mgmt.storage.models import StorageAccount
|
from azure.mgmt.storage.models import StorageAccount
|
||||||
from msrestazure.azure_active_directory import UserPassCredentials
|
from msrestazure.azure_active_directory import UserPassCredentials
|
||||||
|
@ -26,10 +26,7 @@ def list_accounts(args, unexpected):
|
||||||
|
|
||||||
@command('storage account check')
|
@command('storage account check')
|
||||||
@option('--account-name <name>')
|
@option('--account-name <name>')
|
||||||
def checkname(args, unexpected):
|
def checkname(args, unexpected): #pylint: disable=unused-argument
|
||||||
from azure.mgmt.storage import StorageManagementClient, StorageManagementClientConfiguration
|
from azure.mgmt.storage import StorageManagementClient, StorageManagementClientConfiguration
|
||||||
|
|
||||||
smc = get_service_client(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))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
def _compute_client_factory():
|
||||||
|
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,
|
||||||
|
[
|
||||||
|
(VirtualMachineExtensionImagesOperations.get, 'VirtualMachineExtensionImage'),
|
||||||
|
(VirtualMachineExtensionImagesOperations.list_types, '[VirtualMachineImageResource]'),
|
||||||
|
(VirtualMachineExtensionImagesOperations.list_versions, '[VirtualMachineImageResource]'),
|
||||||
|
])
|
||||||
|
|
||||||
|
_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,
|
||||||
|
[
|
||||||
|
(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,
|
||||||
|
[
|
||||||
|
(UsageOperations.list, '[Usage]'),
|
||||||
|
])
|
||||||
|
|
||||||
|
_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,
|
||||||
|
[
|
||||||
|
(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,
|
||||||
|
[
|
||||||
|
(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,
|
||||||
|
[
|
||||||
|
(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),
|
||||||
|
])
|
|
@ -1,7 +1,6 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ._argparse import ArgumentParser
|
from ._argparse import ArgumentParser
|
||||||
from ._locale import install as locale_install
|
|
||||||
from ._logging import configure_logging, logger
|
from ._logging import configure_logging, logger
|
||||||
from ._session import Session
|
from ._session import Session
|
||||||
from ._output import OutputProducer
|
from ._output import OutputProducer
|
||||||
|
@ -12,17 +11,18 @@ CONFIG = Session()
|
||||||
# SESSION provides read-write session variables
|
# SESSION provides read-write session variables
|
||||||
SESSION = Session()
|
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):
|
def main(args):
|
||||||
CONFIG.load(os.path.expanduser('~/az.json'))
|
CONFIG.load(os.path.expanduser('~/az.json'))
|
||||||
SESSION.load(os.path.expanduser('~/az.sess'), max_age=3600)
|
SESSION.load(os.path.expanduser('~/az.sess'), max_age=3600)
|
||||||
|
|
||||||
configure_logging(args, CONFIG)
|
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")
|
parser = ArgumentParser("az")
|
||||||
|
|
||||||
import azure.cli.commands as commands
|
import azure.cli.commands as commands
|
||||||
|
@ -36,7 +36,7 @@ def main(args):
|
||||||
else:
|
else:
|
||||||
# No noun found, so load all commands.
|
# No noun found, so load all commands.
|
||||||
commands.add_to_parser(parser)
|
commands.add_to_parser(parser)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = parser.execute(args)
|
result = parser.execute(args)
|
||||||
# Commands can return a dictionary/list of results
|
# Commands can return a dictionary/list of results
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
import logging
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from azure.cli.commands._auto_command import (_decorate_command,
|
||||||
|
_decorate_option)
|
||||||
|
|
||||||
|
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 <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 <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()
|
Загрузка…
Ссылка в новой задаче