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 - adrian.glaub...@suse.com
+
+- 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: azpy...@microsoft.com
 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: azpy...@microsoft.com
 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',


Reply via email to