Hello community,
here is the log from the commit of package azure-cli-extension for
openSUSE:Factory checked in at 2018-02-14 09:30:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/azure-cli-extension (Old)
and /work/SRC/openSUSE:Factory/.azure-cli-extension.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "azure-cli-extension"
Wed Feb 14 09:30:52 2018 rev:2 rq:574811 version:0.0.8
Changes:
--------
--- /work/SRC/openSUSE:Factory/azure-cli-extension/azure-cli-extension.changes
2017-11-10 14:53:47.683896237 +0100
+++
/work/SRC/openSUSE:Factory/.azure-cli-extension.new/azure-cli-extension.changes
2018-02-14 09:30:53.229077707 +0100
@@ -1,0 +2,9 @@
+Thu Feb 8 11:51:52 UTC 2018 - [email protected]
+
+- New upstream release
+ + Version 0.0.8
+ + For detailed information about changes see the
+ HISTORY.rst file provided with this package
+- Install HISTORY.rst into doc directory
+
+-------------------------------------------------------------------
Old:
----
azure-cli-extension-0.0.3.tar.gz
New:
----
azure-cli-extension-0.0.8.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ azure-cli-extension.spec ++++++
--- /var/tmp/diff_new_pack.ecm3q2/_old 2018-02-14 09:30:54.153044226 +0100
+++ /var/tmp/diff_new_pack.ecm3q2/_new 2018-02-14 09:30:54.157044081 +0100
@@ -1,7 +1,7 @@
#
# spec file for package azure-cli-extension
#
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -15,8 +15,9 @@
# Please submit bugfixes or comments via http://bugs.opensuse.org/
#
+
Name: azure-cli-extension
-Version: 0.0.3
+Version: 0.0.8
Release: 0
Summary: Microsoft Azure CLI 'extension' Command Module
License: MIT
@@ -24,16 +25,16 @@
Url: https://github.com/Azure/azure-cli
Source:
https://files.pythonhosted.org/packages/source/a/azure-cli-extension/azure-cli-extension-%{version}.tar.gz
Source1: LICENSE.txt
-BuildRequires: python3-devel
-BuildRequires: python3-setuptools
-BuildRequires: unzip
BuildRequires: azure-cli-command-modules-nspkg
BuildRequires: azure-cli-nspkg
BuildRequires: python3-azure-nspkg
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: unzip
Requires: azure-cli-command-modules-nspkg
+Requires: azure-cli-core
Requires: azure-cli-nspkg
Requires: python3-azure-nspkg
-Requires: azure-cli-core
Requires: python3-pip
Requires: python3-wheel
Conflicts: azure-cli < 2.0.0
@@ -64,7 +65,8 @@
%files
%defattr(-,root,root,-)
-%doc LICENSE.txt README.rst
+%doc HISTORY.rst LICENSE.txt README.rst
%{python3_sitelib}/azure/cli/command_modules/extension
%{python3_sitelib}/azure_cli_extension-*.egg-info
+
%changelog
++++++ azure-cli-extension-0.0.3.tar.gz -> azure-cli-extension-0.0.8.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/azure-cli-extension-0.0.3/HISTORY.rst
new/azure-cli-extension-0.0.8/HISTORY.rst
--- old/azure-cli-extension-0.0.3/HISTORY.rst 2017-09-23 01:47:00.000000000
+0200
+++ new/azure-cli-extension-0.0.8/HISTORY.rst 2018-01-26 17:12:23.000000000
+0100
@@ -2,8 +2,34 @@
Release History
===============
+0.0.8
+++++++
+Minor fixes
+
+0.0.7
+++++++
+* Update for CLI core changes.
+
+0.0.6
++++++
+
+* `az extension add --name NAME` - Allows users to add an extension by name
+* `az extension list-available` - Allows users to list the available
extensions in the index
+* `az extension update --name NAME` - Allows users to update an extension
+
+0.0.5
++++++
+
+* minor fixes
+
+0.0.4 (2017-10-09)
+++++++++++++++++++
+
+* minor fixes
+
0.0.3 (2017-09-22)
++++++++++++++++++
+
* minor fixes
0.0.2 (2017-09-11)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/azure-cli-extension-0.0.3/PKG-INFO
new/azure-cli-extension-0.0.8/PKG-INFO
--- old/azure-cli-extension-0.0.3/PKG-INFO 2017-09-23 01:49:38.000000000
+0200
+++ new/azure-cli-extension-0.0.8/PKG-INFO 2018-01-26 17:12:38.000000000
+0100
@@ -1,12 +1,11 @@
Metadata-Version: 1.1
Name: azure-cli-extension
-Version: 0.0.3
+Version: 0.0.8
Summary: Microsoft Azure Command-Line Tools Extension Command Module
Home-page: https://github.com/Azure/azure-cli
Author: Microsoft Corporation
Author-email: [email protected]
License: MIT
-Description-Content-Type: UNKNOWN
Description: Microsoft Azure CLI 'extension' Command Module
==============================================
@@ -20,8 +19,34 @@
Release History
===============
+ 0.0.8
+ ++++++
+ Minor fixes
+
+ 0.0.7
+ ++++++
+ * Update for CLI core changes.
+
+ 0.0.6
+ +++++
+
+ * `az extension add --name NAME` - Allows users to add an extension by
name
+ * `az extension list-available` - Allows users to list the available
extensions in the index
+ * `az extension update --name NAME` - Allows users to update an
extension
+
+ 0.0.5
+ +++++
+
+ * minor fixes
+
+ 0.0.4 (2017-10-09)
+ ++++++++++++++++++
+
+ * minor fixes
+
0.0.3 (2017-09-22)
++++++++++++++++++
+
* minor fixes
0.0.2 (2017-09-11)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/__init__.py
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/__init__.py
---
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/__init__.py
2017-09-23 01:47:00.000000000 +0200
+++
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/__init__.py
2018-01-26 17:12:23.000000000 +0100
@@ -3,12 +3,63 @@
# Licensed under the MIT License. See License.txt in the project root for
license information.
#
--------------------------------------------------------------------------------------------
+import argparse
+from collections import OrderedDict
+
+from knack.prompting import prompt_y_n
+from knack.util import CLIError
+
+from azure.cli.core import AzCommandsLoader
+from azure.cli.core.commands import CliCommandType
+
import azure.cli.command_modules.extension._help # pylint:
disable=unused-import
-def load_params(_):
- import azure.cli.command_modules.extension._params # pylint:
disable=redefined-outer-name, unused-variable
+# pylint: disable=line-too-long
+class ExtensionCommandsLoader(AzCommandsLoader):
+
+ def __init__(self, cli_ctx=None):
+ super(ExtensionCommandsLoader, self).__init__(cli_ctx=cli_ctx)
+
+ def load_command_table(self, args):
+
+ def ext_add_has_confirmed(command_args):
+ return bool(not command_args.get('source') or prompt_y_n('Are you
sure you want to install this extension?'))
+
+ def transform_extension_list_available(results):
+ return [OrderedDict([('Name', r)]) for r in results]
+
+ def validate_extension_add(namespace):
+ if (namespace.extension_name and namespace.source) or (not
namespace.extension_name and not namespace.source):
+ raise CLIError("usage error: --name NAME | --source SOURCE")
+
+ extension_custom =
CliCommandType(operations_tmpl='azure.cli.command_modules.extension.custom#{}')
+
+ with self.command_group('extension', extension_custom) as g:
+ g.command('add', 'add_extension',
confirmation=ext_add_has_confirmed, validator=validate_extension_add)
+ g.command('remove', 'remove_extension')
+ g.command('list', 'list_extensions')
+ g.command('show', 'show_extension')
+ g.command('list-available', 'list_available_extensions',
table_transformer=transform_extension_list_available)
+ g.command('update', 'update_extension')
+
+ return self.command_table
+
+ def load_arguments(self, command):
+
+ from argcomplete.completers import FilesCompleter
+ from azure.cli.command_modules.extension._completers import (
+ extension_name_completion_list,
extension_name_from_index_completion_list)
+
+ with self.argument_context('extension') as c:
+ c.argument('extension_name', options_list=['--name', '-n'],
help='Name of extension', completer=extension_name_completion_list)
+ # This is a hidden parameter for now
+ c.argument('index_url', options_list=['--index'],
help=argparse.SUPPRESS)
+
+ with self.argument_context('extension add') as c:
+ c.argument('extension_name',
completer=extension_name_from_index_completion_list)
+ c.argument('source', options_list=['--source', '-s'],
help='Filepath or URL to an extension', completer=FilesCompleter())
+ c.argument('yes', options_list=['--yes', '-y'],
action='store_true', help='Do not prompt for confirmation.')
-def load_commands():
- import azure.cli.command_modules.extension.commands # pylint:
disable=redefined-outer-name, unused-variable
+COMMAND_LOADER_CLS = ExtensionCommandsLoader
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_completers.py
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_completers.py
---
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_completers.py
1970-01-01 01:00:00.000000000 +0100
+++
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_completers.py
2018-01-26 17:12:23.000000000 +0100
@@ -0,0 +1,19 @@
+#
--------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
license information.
+#
--------------------------------------------------------------------------------------------
+
+from azure.cli.core.decorators import Completer
+from azure.cli.core.extension import get_extension_names
+
+from azure.cli.command_modules.extension.custom import get_index_extensions
+
+
+@Completer
+def extension_name_completion_list(cmd, prefix, namespace, **kwargs): #
pylint: disable=unused-argument
+ return get_extension_names()
+
+
+@Completer
+def extension_name_from_index_completion_list(cmd, prefix, namespace,
**kwargs): # pylint: disable=unused-argument
+ return get_index_extensions().keys()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_help.py
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_help.py
--- old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_help.py
2017-09-23 01:47:00.000000000 +0200
+++ new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_help.py
2018-01-26 17:12:23.000000000 +0100
@@ -3,7 +3,7 @@
# Licensed under the MIT License. See License.txt in the project root for
license information.
#
--------------------------------------------------------------------------------------------
-from azure.cli.core.help_files import helps
+from knack.help_files import helps
helps['extension'] = """
type: group
@@ -13,6 +13,13 @@
helps['extension add'] = """
type: command
short-summary: Add an extension.
+ examples:
+ - name: Add extension by name
+ text: az extension add --name anextension
+ - name: Add extension from URL
+ text: az extension add --source
https://contoso.com/anextension-0.0.1-py2.py3-none-any.whl
+ - name: Add extension from local disk
+ text: az extension add --source ~/anextension-0.0.1-py2.py3-none-any.whl
"""
helps['extension list'] = """
@@ -23,6 +30,11 @@
helps['extension list-available'] = """
type: command
short-summary: List publicly available extensions.
+ examples:
+ - name: List all publicly available extensions
+ text: az extension list-available
+ - name: List details on a particular extension
+ text: az extension list-available --query anextension
"""
helps['extension show'] = """
@@ -34,3 +46,8 @@
type: command
short-summary: Remove an extension.
"""
+
+helps['extension update'] = """
+ type: command
+ short-summary: Update an extension.
+"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_homebrew_patch.py
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_homebrew_patch.py
---
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_homebrew_patch.py
2017-09-23 01:47:00.000000000 +0200
+++
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_homebrew_patch.py
2018-01-26 17:12:23.000000000 +0100
@@ -5,9 +5,9 @@
import os
import sys
-import azure.cli.core.azlogging as azlogging
+from knack.log import get_logger
-logger = azlogging.get_az_logger(__name__)
+logger = get_logger(__name__)
HOMEBREW_CELLAR_PATH = '/usr/local/Cellar/azure-cli/'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_index.py
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_index.py
--- old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_index.py
1970-01-01 01:00:00.000000000 +0100
+++ new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_index.py
2018-01-26 17:12:23.000000000 +0100
@@ -0,0 +1,46 @@
+#
--------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
license information.
+#
--------------------------------------------------------------------------------------------
+import requests
+
+from knack.log import get_logger
+from knack.util import CLIError
+
+logger = get_logger(__name__)
+
+DEFAULT_INDEX_URL = "https://aka.ms/azure-cli-extension-index-v1"
+
+ERR_TMPL_EXT_INDEX = 'Unable to get extension index.\n'
+ERR_TMPL_NON_200 = '{}Server returned status code {{}} for
{{}}'.format(ERR_TMPL_EXT_INDEX)
+ERR_TMPL_NO_NETWORK = '{}Please ensure you have network connection. Error
detail: {{}}'.format(ERR_TMPL_EXT_INDEX)
+ERR_TMPL_BAD_JSON = '{}Response body does not contain valid json. Error
detail: {{}}'.format(ERR_TMPL_EXT_INDEX)
+
+ERR_UNABLE_TO_GET_EXTENSIONS = 'Unable to get extensions from index. Improper
index format.'
+
+
+# pylint: disable=inconsistent-return-statements
+def get_index(index_url=None):
+ from azure.cli.core.util import should_disable_connection_verify
+ index_url = index_url or DEFAULT_INDEX_URL
+ try:
+ response = requests.get(index_url, verify=(not
should_disable_connection_verify()))
+ if response.status_code == 200:
+ return response.json()
+ else:
+ msg = ERR_TMPL_NON_200.format(response.status_code, index_url)
+ raise CLIError(msg)
+ except (requests.exceptions.ConnectionError,
requests.exceptions.HTTPError) as err:
+ msg = ERR_TMPL_NO_NETWORK.format(str(err))
+ raise CLIError(msg)
+ except ValueError as err:
+ msg = ERR_TMPL_BAD_JSON.format(str(err))
+ raise CLIError(msg)
+
+
+def get_index_extensions(index_url=None):
+ index = get_index(index_url=index_url)
+ extensions = index.get('extensions')
+ if extensions is None:
+ logger.warning(ERR_UNABLE_TO_GET_EXTENSIONS)
+ return extensions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_params.py
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_params.py
---
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_params.py
2017-09-23 01:47:00.000000000 +0200
+++
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_params.py
1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-#
--------------------------------------------------------------------------------------------
-# Copyright (c) Microsoft Corporation. All rights reserved.
-# Licensed under the MIT License. See License.txt in the project root for
license information.
-#
--------------------------------------------------------------------------------------------
-
-from argcomplete.completers import FilesCompleter
-
-from azure.cli.core.sdk.util import ParametersContext
-from azure.cli.core.extension import get_extension_names
-
-
-def extension_name_completion_list(prefix, **kwargs): # pylint:
disable=unused-argument
- return get_extension_names()
-
-
-with ParametersContext('extension') as c:
- c.register('extension_name', ('--name', '-n'), help='Name of extension',
completer=extension_name_completion_list)
-
-
-with ParametersContext('extension add') as c:
- c.argument('extension_name', completer=None)
- c.register('source', ('--source', '-s'), help='Filepath or URL to an
extension', completer=FilesCompleter())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_resolve.py
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_resolve.py
---
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/_resolve.py
1970-01-01 01:00:00.000000000 +0100
+++
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/_resolve.py
2018-01-26 17:12:23.000000000 +0100
@@ -0,0 +1,78 @@
+#
--------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
license information.
+#
--------------------------------------------------------------------------------------------
+from wheel.install import WHEEL_INFO_RE
+from pkg_resources import parse_version
+
+from knack.log import get_logger
+
+from azure.cli.core.extension import ext_compat_with_cli
+
+from azure.cli.command_modules.extension._index import get_index_extensions
+
+
+logger = get_logger(__name__)
+
+
+class NoExtensionCandidatesError(Exception):
+ pass
+
+
+def _is_not_platform_specific(item):
+ parsed_filename = WHEEL_INFO_RE(item['filename'])
+ p = parsed_filename.groupdict()
+ if p.get('pyver') == 'py2.py3' and p.get('abi') == 'none' and
p.get('plat') == 'any':
+ return True
+ logger.debug("Skipping '%s' as not universal wheel."
+ "We do not currently support platform specific extension
detection. "
+ "They can be installed with the full URL %s",
item['filename'], item.get('downloadUrl'))
+ return False
+
+
+def _is_compatible_with_cli_version(item):
+ is_compatible, cli_core_version, min_required, max_required =
ext_compat_with_cli(item['metadata'])
+ if is_compatible:
+ return True
+ logger.debug("Skipping '%s' as not compatible with this version of the
CLI. "
+ "Extension compatibility result: is_compatible=%s
cli_core_version=%s min_required=%s "
+ "max_required=%s", item['filename'], is_compatible,
cli_core_version, min_required, max_required)
+ return False
+
+
+def _is_greater_than_cur_version(cur_version):
+ if not cur_version:
+ return None
+ cur_version_parsed = parse_version(cur_version)
+
+ def filter_func(item):
+ item_version = parse_version(item['metadata']['version'])
+ if item_version > cur_version_parsed:
+ return True
+ logger.debug("Skipping '%s' as %s not greater than current version
%s", item['filename'],
+ item_version, cur_version_parsed)
+ return False
+ return filter_func
+
+
+def resolve_from_index(extension_name, cur_version=None, index_url=None):
+ candidates = get_index_extensions(index_url=index_url).get(extension_name,
[])
+ if not candidates:
+ raise NoExtensionCandidatesError("No extension found with name
'{}'".format(extension_name))
+
+ filters = [_is_not_platform_specific, _is_compatible_with_cli_version,
_is_greater_than_cur_version(cur_version)]
+ for f in filters:
+ logger.debug("Candidates %s", [c['filename'] for c in candidates])
+ candidates = list(filter(f, candidates))
+ if not candidates:
+ raise NoExtensionCandidatesError("No suitable extensions found.")
+
+ candidates_sorted = sorted(candidates, key=lambda c:
parse_version(c['metadata']['version']), reverse=True)
+ logger.debug("Candidates %s", [c['filename'] for c in candidates_sorted])
+ logger.debug("Choosing the latest of the remaining candidates.")
+ chosen = candidates_sorted[0]
+ logger.debug("Chosen %s", chosen)
+ download_url, digest = chosen.get('downloadUrl'),
chosen.get('sha256Digest')
+ if not download_url:
+ raise NoExtensionCandidatesError("No download url found.")
+ return download_url, digest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/commands.py
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/commands.py
---
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/commands.py
2017-09-23 01:47:00.000000000 +0200
+++
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/commands.py
1970-01-01 01:00:00.000000000 +0100
@@ -1,13 +0,0 @@
-#
--------------------------------------------------------------------------------------------
-# Copyright (c) Microsoft Corporation. All rights reserved.
-# Licensed under the MIT License. See License.txt in the project root for
license information.
-#
--------------------------------------------------------------------------------------------
-
-# pylint: disable=line-too-long
-
-from azure.cli.core.commands import cli_command
-
-cli_command(__name__, 'extension add',
'azure.cli.command_modules.extension.custom#add_extension')
-cli_command(__name__, 'extension remove',
'azure.cli.command_modules.extension.custom#remove_extension')
-cli_command(__name__, 'extension list',
'azure.cli.command_modules.extension.custom#list_extensions')
-cli_command(__name__, 'extension show',
'azure.cli.command_modules.extension.custom#show_extension')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/custom.py
new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/custom.py
--- old/azure-cli-extension-0.0.3/azure/cli/command_modules/extension/custom.py
2017-09-23 01:47:00.000000000 +0200
+++ new/azure-cli-extension-0.0.8/azure/cli/command_modules/extension/custom.py
2018-01-26 17:12:23.000000000 +0100
@@ -2,29 +2,30 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
license information.
#
--------------------------------------------------------------------------------------------
+import sys
import os
import tempfile
import shutil
-import logging
import zipfile
import traceback
-
+import hashlib
+from subprocess import check_output, STDOUT, CalledProcessError
import requests
from wheel.install import WHEEL_INFO_RE
-
-from six import StringIO
from six.moves.urllib.parse import urlparse # pylint: disable=import-error
+from knack.log import get_logger
+
from azure.cli.core.util import CLIError
from azure.cli.core.extension import (extension_exists, get_extension_path,
get_extensions,
get_extension, ext_compat_with_cli,
WheelExtension,
ExtensionNotInstalledException)
-import azure.cli.core.azlogging as azlogging
from ._homebrew_patch import HomebrewPipPatch
+from ._index import get_index_extensions
+from ._resolve import resolve_from_index, NoExtensionCandidatesError
-
-logger = azlogging.get_az_logger(__name__)
+logger = get_logger(__name__)
OUT_KEY_NAME = 'name'
OUT_KEY_VERSION = 'version'
@@ -32,28 +33,24 @@
OUT_KEY_METADATA = 'metadata'
-def _run_pip(pip, pip_exec_args):
- log_stream = StringIO()
- log_handler = logging.StreamHandler(log_stream)
- log_handler.setFormatter(logging.Formatter('%(name)s : %(message)s'))
-
- pip.logger.handlers = []
- pip.logger.addHandler(log_handler)
-
- # Don't propagate to root logger as we catch the pip logs in our own log
stream
- pip.logger.propagate = False
- logger.debug('Running pip: %s %s', pip, pip_exec_args)
- status_code = pip.main(pip_exec_args)
-
- log_output = log_stream.getvalue()
- logger.debug(log_output)
- log_stream.close()
- return status_code
+def _run_pip(pip_exec_args):
+ cmd = [sys.executable, '-m', 'pip'] + pip_exec_args + ['-vv',
'--disable-pip-version-check', '--no-cache-dir']
+ logger.debug('Running: %s', cmd)
+ try:
+ log_output = check_output(cmd, stderr=STDOUT, universal_newlines=True)
+ logger.debug(log_output)
+ returncode = 0
+ except CalledProcessError as e:
+ logger.debug(e.output)
+ logger.debug(e)
+ returncode = e.returncode
+ return returncode
def _whl_download_from_url(url_parse_result, ext_file):
+ from azure.cli.core.util import should_disable_connection_verify
url = url_parse_result.geturl()
- r = requests.get(url, stream=True)
+ r = requests.get(url, stream=True, verify=(not
should_disable_connection_verify()))
if r.status_code != 200:
raise CLIError("Request to {} failed with {}".format(url,
r.status_code))
with open(ext_file, 'wb') as f:
@@ -89,14 +86,16 @@
_validate_whl_cli_compat(azext_metadata)
-def _add_whl_ext(source): # pylint: disable=too-many-statements
- import pip
+def _add_whl_ext(source, ext_sha256=None): # pylint:
disable=too-many-statements
+ if not source.endswith('.whl'):
+ raise ValueError('Unknown extension type. Only Python wheels are
supported.')
url_parse_result = urlparse(source)
is_url = (url_parse_result.scheme == 'http' or url_parse_result.scheme ==
'https')
logger.debug('Extension source is url? %s', is_url)
whl_filename = os.path.basename(url_parse_result.path) if is_url else
os.path.basename(source)
parsed_filename = WHEEL_INFO_RE(whl_filename)
- extension_name = parsed_filename.groupdict().get('name') if
parsed_filename else None
+ # Extension names can have - but .whl format changes it to _ (PEP 0427).
Undo this.
+ extension_name = parsed_filename.groupdict().get('name').replace('_', '-')
if parsed_filename else None
if not extension_name:
raise CLIError('Unable to determine extension name from {}. Is the
file name correct?'.format(source))
if extension_exists(extension_name):
@@ -118,7 +117,16 @@
if not os.path.isfile(ext_file):
raise CLIError("File {} not found.".format(source))
# Validate the extension
- logger.debug('Validating the extension {}'.format(ext_file))
+ logger.debug('Validating the extension %s', ext_file)
+ if ext_sha256:
+ valid_checksum, computed_checksum = is_valid_sha256sum(ext_file,
ext_sha256)
+ if valid_checksum:
+ logger.debug("Checksum of %s is OK", ext_file)
+ else:
+ logger.debug("Invalid checksum for %s. Expected '%s', computed
'%s'.",
+ ext_file, ext_sha256, computed_checksum)
+ raise CLIError("The checksum of the extension does not match the
expected value. "
+ "Use --debug for more information.")
try:
_validate_whl_extension(ext_file)
except AssertionError:
@@ -126,13 +134,13 @@
raise CLIError('The extension is invalid. Use --debug for more
information.')
except CLIError as e:
raise e
- logger.debug('Validation successful on {}'.format(ext_file))
+ logger.debug('Validation successful on %s', ext_file)
# Install with pip
extension_path = get_extension_path(extension_name)
pip_args = ['install', '--target', extension_path, ext_file]
logger.debug('Executing pip with args: %s', pip_args)
with HomebrewPipPatch():
- pip_status_code = _run_pip(pip, pip_args)
+ pip_status_code = _run_pip(pip_args)
if pip_status_code > 0:
logger.debug('Pip failed so deleting anything we might have installed
at %s', extension_path)
shutil.rmtree(extension_path, ignore_errors=True)
@@ -144,11 +152,25 @@
logger.debug('Saved the whl to %s', dst)
-def add_extension(source):
- if source.endswith('.whl'):
- _add_whl_ext(source)
- else:
- raise ValueError('Unknown extension type. Only Python wheels are
supported.')
+def is_valid_sha256sum(a_file, expected_sum):
+ sha256 = hashlib.sha256()
+ with open(a_file, 'rb') as f:
+ sha256.update(f.read())
+ computed_hash = sha256.hexdigest()
+ return expected_sum == computed_hash, computed_hash
+
+
+def add_extension(source=None, extension_name=None, index_url=None, yes=None):
# pylint: disable=unused-argument
+ ext_sha256 = None
+ if extension_name:
+ if extension_exists(extension_name):
+ raise CLIError('The extension {} already
exists.'.format(extension_name))
+ try:
+ source, ext_sha256 = resolve_from_index(extension_name,
index_url=index_url)
+ except NoExtensionCandidatesError as err:
+ logger.debug(err)
+ raise CLIError("No matching extensions for '{}'. Use --debug for
more information.".format(extension_name))
+ _add_whl_ext(source, ext_sha256=ext_sha256)
def remove_extension(extension_name):
@@ -173,3 +195,38 @@
OUT_KEY_METADATA: extension.metadata}
except ExtensionNotInstalledException as e:
raise CLIError(e)
+
+
+def update_extension(extension_name, index_url=None):
+ try:
+ ext = get_extension(extension_name)
+ cur_version = ext.get_version()
+ try:
+ download_url, ext_sha256 = resolve_from_index(extension_name,
cur_version=cur_version, index_url=index_url)
+ except NoExtensionCandidatesError as err:
+ logger.debug(err)
+ raise CLIError("No updates available for '{}'. Use --debug for
more information.".format(extension_name))
+ # Copy current version of extension to tmp directory in case we need
to restore it after a failed install.
+ backup_dir = os.path.join(tempfile.mkdtemp(), extension_name)
+ extension_path = get_extension_path(extension_name)
+ logger.debug('Backing up the current extension: %s to %s',
extension_path, backup_dir)
+ shutil.copytree(extension_path, backup_dir)
+ # Remove current version of the extension
+ shutil.rmtree(extension_path)
+ # Install newer version
+ try:
+ _add_whl_ext(download_url, ext_sha256=ext_sha256)
+ logger.debug('Deleting backup of old extension at %s', backup_dir)
+ shutil.rmtree(backup_dir)
+ except Exception as err:
+ logger.error('An error occurred whilst updating.')
+ logger.error(err)
+ logger.debug('Copying %s to %s', backup_dir, extension_path)
+ shutil.copytree(backup_dir, extension_path)
+ raise CLIError('Failed to update. Rolled {} back to
{}.'.format(extension_name, cur_version))
+ except ExtensionNotInstalledException as e:
+ raise CLIError(e)
+
+
+def list_available_extensions(index_url=None):
+ return get_index_extensions(index_url=index_url)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure_cli_extension.egg-info/PKG-INFO
new/azure-cli-extension-0.0.8/azure_cli_extension.egg-info/PKG-INFO
--- old/azure-cli-extension-0.0.3/azure_cli_extension.egg-info/PKG-INFO
2017-09-23 01:49:38.000000000 +0200
+++ new/azure-cli-extension-0.0.8/azure_cli_extension.egg-info/PKG-INFO
2018-01-26 17:12:38.000000000 +0100
@@ -1,12 +1,11 @@
Metadata-Version: 1.1
Name: azure-cli-extension
-Version: 0.0.3
+Version: 0.0.8
Summary: Microsoft Azure Command-Line Tools Extension Command Module
Home-page: https://github.com/Azure/azure-cli
Author: Microsoft Corporation
Author-email: [email protected]
License: MIT
-Description-Content-Type: UNKNOWN
Description: Microsoft Azure CLI 'extension' Command Module
==============================================
@@ -20,8 +19,34 @@
Release History
===============
+ 0.0.8
+ ++++++
+ Minor fixes
+
+ 0.0.7
+ ++++++
+ * Update for CLI core changes.
+
+ 0.0.6
+ +++++
+
+ * `az extension add --name NAME` - Allows users to add an extension by
name
+ * `az extension list-available` - Allows users to list the available
extensions in the index
+ * `az extension update --name NAME` - Allows users to update an
extension
+
+ 0.0.5
+ +++++
+
+ * minor fixes
+
+ 0.0.4 (2017-10-09)
+ ++++++++++++++++++
+
+ * minor fixes
+
0.0.3 (2017-09-22)
++++++++++++++++++
+
* minor fixes
0.0.2 (2017-09-11)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure_cli_extension.egg-info/SOURCES.txt
new/azure-cli-extension-0.0.8/azure_cli_extension.egg-info/SOURCES.txt
--- old/azure-cli-extension-0.0.3/azure_cli_extension.egg-info/SOURCES.txt
2017-09-23 01:49:38.000000000 +0200
+++ new/azure-cli-extension-0.0.8/azure_cli_extension.egg-info/SOURCES.txt
2018-01-26 17:12:38.000000000 +0100
@@ -7,10 +7,11 @@
azure/cli/__init__.py
azure/cli/command_modules/__init__.py
azure/cli/command_modules/extension/__init__.py
+azure/cli/command_modules/extension/_completers.py
azure/cli/command_modules/extension/_help.py
azure/cli/command_modules/extension/_homebrew_patch.py
-azure/cli/command_modules/extension/_params.py
-azure/cli/command_modules/extension/commands.py
+azure/cli/command_modules/extension/_index.py
+azure/cli/command_modules/extension/_resolve.py
azure/cli/command_modules/extension/custom.py
azure_cli_extension.egg-info/PKG-INFO
azure_cli_extension.egg-info/SOURCES.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/azure-cli-extension-0.0.3/azure_cli_extension.egg-info/requires.txt
new/azure-cli-extension-0.0.8/azure_cli_extension.egg-info/requires.txt
--- old/azure-cli-extension-0.0.3/azure_cli_extension.egg-info/requires.txt
2017-09-23 01:49:38.000000000 +0200
+++ new/azure-cli-extension-0.0.8/azure_cli_extension.egg-info/requires.txt
2018-01-26 17:12:38.000000000 +0100
@@ -1,4 +1,3 @@
azure-cli-core
pip
wheel
-azure-cli-command-modules-nspkg>=2.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/azure-cli-extension-0.0.3/setup.py
new/azure-cli-extension-0.0.8/setup.py
--- old/azure-cli-extension-0.0.3/setup.py 2017-09-23 01:49:37.000000000
+0200
+++ new/azure-cli-extension-0.0.8/setup.py 2018-01-26 17:12:23.000000000
+0100
@@ -14,7 +14,7 @@
logger.warn("Wheel is not available, disabling bdist_wheel hook")
cmdclass = {}
-VERSION = "0.0.3"
+VERSION = "0.0.8"
CLASSIFIERS = [
'Development Status :: 5 - Production/Stable',