Repository: Azure/azure-cli

Issue:
Add support for querying ARM operations
In the CLI 2.0 today, we don't have a way of showing operations, and (per the ARM team) "operations is critical for RBAC (creating custom roles etc) and auditing (this is what gets written into Event service entries)."

Discussion:
codecov-io: # [Codecov](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=h1) Report
> Merging [#2914](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=desc) into [master](https://codecov.io/gh/Azure/azure-cli/commit/3699ef7fdefc8c40fa76ebd83976fc8d4a0b92d1?src=pr&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `87.5%`.

[![Impacted file tree graph](https://codecov.io/gh/Azure/azure-cli/pull/2914/graphs/tree.svg?token=2pog0TKvF8&src=pr&width=650&height=150)](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #2914      +/-   ##
==========================================
+ Coverage   63.19%   63.21%   +0.01%     
==========================================
  Files         466      466              
  Lines       26168    26190      +22     
  Branches     4003     4003              
==========================================
+ Hits        16536    16555      +19     
- Misses       8548     8551       +3     
  Partials     1084     1084
```


| [Impacted Files](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [...urce/azure/cli/command\_modules/resource/\_params.py](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktcmVzb3VyY2UvYXp1cmUvY2xpL2NvbW1hbmRfbW9kdWxlcy9yZXNvdXJjZS9fcGFyYW1zLnB5) | `100% <100%> (ø)` | :arrow_up: |
| [...re/cli/command\_modules/resource/\_client\_factory.py](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktcmVzb3VyY2UvYXp1cmUvY2xpL2NvbW1hbmRfbW9kdWxlcy9yZXNvdXJjZS9fY2xpZW50X2ZhY3RvcnkucHk=) | `79.54% <100%> (+2.04%)` | :arrow_up: |
| [...source/azure/cli/command\_modules/resource/\_help.py](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktcmVzb3VyY2UvYXp1cmUvY2xpL2NvbW1hbmRfbW9kdWxlcy9yZXNvdXJjZS9faGVscC5weQ==) | `100% <100%> (ø)` | :arrow_up: |
| [...rce/azure/cli/command\_modules/resource/commands.py](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktcmVzb3VyY2UvYXp1cmUvY2xpL2NvbW1hbmRfbW9kdWxlcy9yZXNvdXJjZS9jb21tYW5kcy5weQ==) | `83.11% <100%> (+0.45%)` | :arrow_up: |
| [...ource/azure/cli/command\_modules/resource/custom.py](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=tree#diff-c3JjL2NvbW1hbmRfbW9kdWxlcy9henVyZS1jbGktcmVzb3VyY2UvYXp1cmUvY2xpL2NvbW1hbmRfbW9kdWxlcy9yZXNvdXJjZS9jdXN0b20ucHk=) | `52.71% <78.57%> (+0.53%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=footer). Last update [3699ef7...9cba2af](https://codecov.io/gh/Azure/azure-cli/pull/2914?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/azure-cli.pyproj b/azure-cli.pyproj
index 39b535e11..cadb46c8f 100644
--- a/azure-cli.pyproj
+++ b/azure-cli.pyproj
@@ -43,7 +43,17 @@
     <Compile Include="azure-cli-core\azure\cli\core\extensions\__init__.py" />
     <Compile Include="azure-cli-core\azure\cli\core\help_files.py" />
     <Compile Include="azure-cli-core\azure\cli\core\parser.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\profiles\_shared.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\profiles\_shared.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\profiles\__init__.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\profiles\__init__.py" />
     <Compile Include="azure-cli-core\azure\cli\core\prompting.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\sdk\util.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\sdk\util.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\sdk\validators.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\sdk\validators.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\sdk\__init__.py" />
+    <Compile Include="azure-cli-core\azure\cli\core\sdk\__init__.py" />
     <Compile Include="azure-cli-core\azure\cli\core\telemetry_upload.py" />
     <Compile Include="azure-cli-core\azure\cli\core\test_utils\vcr_test_base.py" />
     <Compile Include="azure-cli-core\azure\cli\core\test_utils\__init__.py" />
@@ -583,6 +593,8 @@
     <Folder Include="azure-cli-core\azure\cli\core\" />
     <Folder Include="azure-cli-core\azure\cli\core\commands\" />
     <Folder Include="azure-cli-core\azure\cli\core\extensions\" />
+    <Folder Include="azure-cli-core\azure\cli\core\profiles\" />
+    <Folder Include="azure-cli-core\azure\cli\core\sdk\" />
     <Folder Include="azure-cli-core\azure\cli\core\test_utils\" />
     <Folder Include="azure-cli-core\tests\" />
     <Folder Include="azure-cli-core\tests\__pycache__\" />
diff --git a/doc/sphinx/azhelpgen/azhelpgen.py b/doc/sphinx/azhelpgen/azhelpgen.py
index 0d98b5e04..969e84530 100644
--- a/doc/sphinx/azhelpgen/azhelpgen.py
+++ b/doc/sphinx/azhelpgen/azhelpgen.py
@@ -10,10 +10,10 @@ from docutils.statemachine import ViewList
 from sphinx.util.compat import Directive
 from sphinx.util.nodes import nested_parse_with_titles
 
-from azure.cli.core.application import APPLICATION, Configuration
+from azure.cli.core.application import Application, Configuration
 import azure.cli.core._help as _help
 
-app = APPLICATION
+app = Application(Configuration())
 for cmd in app.configuration.get_command_table():
     try:
         app.execute(cmd.split() + ['-h'])
@@ -30,8 +30,11 @@ class AzHelpGenDirective(Directive):
 
         help_files = []
         for cmd, parser in parser_dict.items():
-            help_file = _help.GroupHelpFile(cmd, parser) if _is_group(parser) else _help.CommandHelpFile(cmd, parser) 
-            help_file.load(parser)
+            help_file = _help.GroupHelpFile(cmd, parser) if _is_group(parser) else _help.CommandHelpFile(cmd, parser)
+            try:
+                help_file.load(parser)
+            catch Exception as ex:
+                print(ex)
             help_files.append(help_file)
         help_files = sorted(help_files, key=lambda x: x.command)
 
diff --git a/src/azure-cli-core/azure/cli/core/commands/arm.py b/src/azure-cli-core/azure/cli/core/commands/arm.py
index 958124117..5c90c8194 100644
--- a/src/azure-cli-core/azure/cli/core/commands/arm.py
+++ b/src/azure-cli-core/azure/cli/core/commands/arm.py
@@ -10,10 +10,13 @@ from six import string_types
 from azure.cli.core.commands import (CliCommand,
                                      get_op_handler,
                                      command_table as main_command_table,
-                                     command_module_map as main_command_module_map)
+                                     command_module_map as main_command_module_map,
+                                     CONFIRM_PARAM_NAME)
 from azure.cli.core.commands._introspection import extract_args_from_signature
 from azure.cli.core.commands.client_factory import get_mgmt_service_client
 from azure.cli.core.application import APPLICATION, IterateValue
+from azure.cli.core.prompting import prompt_y_n, NoTTYException
+from azure.cli.core._config import az_config
 import azure.cli.core.azlogging as azlogging
 from azure.cli.core.util import CLIError, todict, shell_safe_json_parse
 from azure.cli.core.profiles import ResourceType
@@ -207,12 +210,25 @@ def _get_child(parent, collection_name, item_name, collection_key):
         return result
 
 
+def _user_confirmed(confirmation, command_args):
+    if callable(confirmation):
+        return confirmation(command_args)
+    try:
+        if isinstance(confirmation, string_types):
+            return prompt_y_n(confirmation)
+        return prompt_y_n('Are you sure you want to perform this operation?')
+    except NoTTYException:
+        logger.warning('Unable to prompt for confirmation as no tty available. Use --yes.')
+        return False
+
+
 # pylint: disable=too-many-arguments
 def cli_generic_update_command(module_name, name, getter_op, setter_op, factory=None,
                                setter_arg_name='parameters', table_transformer=None,
                                child_collection_prop_name=None, child_collection_key='name',
                                child_arg_name='item_name', custom_function_op=None,
-                               no_wait_param=None, transform=None):
+                               no_wait_param=None, transform=None, confirmation=None,
+                               exception_handler=None, formatter_class=None):
     if not isinstance(getter_op, string_types):
         raise ValueError("Getter operation must be a string. Got '{}'".format(getter_op))
     if not isinstance(setter_op, string_types):
@@ -246,6 +262,12 @@ def cli_generic_update_command(module_name, name, getter_op, setter_op, factory=
     def handler(args):  # pylint: disable=too-many-branches,too-many-statements
         from msrestazure.azure_operation import AzureOperationPoller
 
+        if confirmation \
+            and not args.items().get(CONFIRM_PARAM_NAME) \
+            and not az_config.getboolean('core', 'disable_confirm_prompt', fallback=False) \
+                and not _user_confirmed(confirmation, args.items()):
+            raise CLIError('Operation cancelled.')
+
         ordered_arguments = args.pop('ordered_arguments', [])
         for item in ['properties_to_add', 'properties_to_set', 'properties_to_remove']:
             if args[item]:
@@ -259,66 +281,73 @@ def cli_generic_update_command(module_name, name, getter_op, setter_op, factory=
 
         getterargs = {key: val for key, val in args.items() if key in get_arguments_loader()}
         getter = get_op_handler(getter_op)
-        if child_collection_prop_name:
-            parent = getter(client, **getterargs) if client else getter(**getterargs)
-            instance = _get_child(
-                parent,
-                child_collection_prop_name,
-                args.get(child_arg_name),
-                child_collection_key
-            )
-        else:
-            parent = None
-            instance = getter(client, **getterargs) if client else getter(**getterargs)
-
-        # pass instance to the custom_function, if provided
-        if custom_function_op:
-            custom_function = get_op_handler(custom_function_op)
-            custom_func_args = {k: v for k, v in args.items() if k in function_arguments_loader()}
+        try:
             if child_collection_prop_name:
-                parent = custom_function(instance, parent, **custom_func_args)
+                parent = getter(client, **getterargs) if client else getter(**getterargs)
+                instance = _get_child(
+                    parent,
+                    child_collection_prop_name,
+                    args.get(child_arg_name),
+                    child_collection_key
+                )
             else:
-                instance = custom_function(instance, **custom_func_args)
-
-        # apply generic updates after custom updates
-        setterargs = {key: val for key, val in args.items() if key in set_arguments_loader()}
-
-        for arg in ordered_arguments:
-            arg_type, arg_values = arg
-            if arg_type == '--set':
-                try:
-                    for expression in arg_values:
-                        set_properties(instance, expression)
-                except ValueError:
-                    raise CLIError('invalid syntax: {}'.format(set_usage))
-            elif arg_type == '--add':
-                try:
-                    add_properties(instance, arg_values)
-                except ValueError:
-                    raise CLIError('invalid syntax: {}'.format(add_usage))
-            elif arg_type == '--remove':
-                try:
-                    remove_properties(instance, arg_values)
-                except ValueError:
-                    raise CLIError('invalid syntax: {}'.format(remove_usage))
-
-        # Done... update the instance!
-        setterargs[setter_arg_name] = parent if child_collection_prop_name else instance
-        setter = get_op_handler(setter_op)
-
-        opres = setter(client, **setterargs) if client else setter(**setterargs)
-
-        if setterargs.get(no_wait_param, None):
-            return None
+                parent = None
+                instance = getter(client, **getterargs) if client else getter(**getterargs)
 
-        result = opres.result() if isinstance(opres, AzureOperationPoller) else opres
-        if child_collection_prop_name:
-            result = _get_child(
-                result,
-                child_collection_prop_name,
-                args.get(child_arg_name),
-                child_collection_key
-            )
+            # pass instance to the custom_function, if provided
+            if custom_function_op:
+                custom_function = get_op_handler(custom_function_op)
+                custom_func_args = \
+                    {k: v for k, v in args.items() if k in function_arguments_loader()}
+                if child_collection_prop_name:
+                    parent = custom_function(instance, parent, **custom_func_args)
+                else:
+                    instance = custom_function(instance, **custom_func_args)
+
+            # apply generic updates after custom updates
+            setterargs = {key: val for key, val in args.items() if key in set_arguments_loader()}
+
+            for arg in ordered_arguments:
+                arg_type, arg_values = arg
+                if arg_type == '--set':
+                    try:
+                        for expression in arg_values:
+                            set_properties(instance, expression)
+                    except ValueError:
+                        raise CLIError('invalid syntax: {}'.format(set_usage))
+                elif arg_type == '--add':
+                    try:
+                        add_properties(instance, arg_values)
+                    except ValueError:
+                        raise CLIError('invalid syntax: {}'.format(add_usage))
+                elif arg_type == '--remove':
+                    try:
+                        remove_properties(instance, arg_values)
+                    except ValueError:
+                        raise CLIError('invalid syntax: {}'.format(remove_usage))
+
+            # Done... update the instance!
+            setterargs[setter_arg_name] = parent if child_collection_prop_name else instance
+            setter = get_op_handler(setter_op)
+
+            opres = setter(client, **setterargs) if client else setter(**setterargs)
+
+            if setterargs.get(no_wait_param, None):
+                return None
+
+            result = opres.result() if isinstance(opres, AzureOperationPoller) else opres
+            if child_collection_prop_name:
+                result = _get_child(
+                    result,
+                    child_collection_prop_name,
+                    args.get(child_arg_name),
+                    child_collection_key
+                )
+        except Exception as ex:  # pylint: disable=broad-except
+            if exception_handler:
+                result = exception_handler(ex)
+            else:
+                raise ex
 
         # apply results transform if specified
         if transform:
@@ -334,7 +363,7 @@ def cli_generic_update_command(module_name, name, getter_op, setter_op, factory=
             namespace.ordered_arguments.append((option_string, values))
 
     cmd = CliCommand(name, handler, table_transformer=table_transformer,
-                     arguments_loader=arguments_loader)
+                     arguments_loader=arguments_loader, formatter_class=formatter_class)
     group_name = 'Generic Update'
     cmd.add_argument('properties_to_set', '--set', nargs='+', action=OrderedArgsAction, default=[],
                      help='Update an object by specifying a property path and value to set.'
@@ -352,7 +381,7 @@ def cli_generic_update_command(module_name, name, getter_op, setter_op, factory=
     main_command_module_map[name] = module_name
 
 
-def cli_generic_wait_command(module_name, name, getter_op, factory=None):
+def cli_generic_wait_command(module_name, name, getter_op, factory=None, exception_handler=None):
 
     if not isinstance(getter_op, string_types):
         raise ValueError("Getter operation must be a string. Got '{}'".format(type(getter_op)))
@@ -374,6 +403,12 @@ def cli_generic_wait_command(module_name, name, getter_op, factory=None):
                 provisioning_state = getattr(properties, 'provisioning_state', None)
         return provisioning_state
 
+    def _handle_exception(ex):
+        if exception_handler:
+            return exception_handler(ex)
+        else:
+            raise ex
+
     def handler(args):
         from msrest.exceptions import ClientException
         import time
@@ -418,9 +453,11 @@ def cli_generic_wait_command(module_name, name, getter_op, factory=None):
                     if wait_for_deleted:
                         return
                     if not any([wait_for_created, wait_for_exists, custom_condition]):
-                        raise
+                        _handle_exception(ex)
                 else:
-                    raise
+                    _handle_exception(ex)
+            except Exception as ex:  # pylint: disable=broad-except
+                _handle_exception(ex)
 
             time.sleep(interval)
 
diff --git a/src/command_modules/azure-cli-redis/azure/cli/command_modules/redis/commands.py b/src/command_modules/azure-cli-redis/azure/cli/command_modules/redis/commands.py
index 453f4d32c..ff1891f51 100644
--- a/src/command_modules/azure-cli-redis/azure/cli/command_modules/redis/commands.py
+++ b/src/command_modules/azure-cli-redis/azure/cli/command_modules/redis/commands.py
@@ -9,6 +9,8 @@ from azure.cli.core.commands import cli_command
 from azure.cli.core.commands.arm import cli_generic_update_command
 from azure.cli.command_modules.redis._client_factory import (cf_redis, cf_patch_schedules)
 
+from azure.cli.command_modules.redis.custom import wrong_vmsize_argument_exception_handler
+
 cli_command(__name__, 'redis create', 'azure.cli.command_modules.redis.custom#cli_redis_create', cf_redis)
 cli_command(__name__, 'redis delete', 'azure.mgmt.redis.operations.redis_operations#RedisOperations.delete', cf_redis)
 cli_command(__name__, 'redis export', 'azure.cli.command_modules.redis.custom#cli_redis_export', cf_redis)
@@ -21,11 +23,12 @@ cli_command(__name__, 'redis regenerate-keys', 'azure.mgmt.redis.operations.redi
 cli_command(__name__, 'redis show', 'azure.mgmt.redis.operations.redis_operations#RedisOperations.get', cf_redis)
 cli_command(__name__, 'redis update-settings', 'azure.cli.command_modules.redis.custom#cli_redis_update_settings', cf_redis)
 
-cli_generic_update_command(__name__, 'redis update', 'azure.mgmt.redis.operations.redis_operations#RedisOperations.get',
-						                     'azure.mgmt.redis.operations.redis_operations#RedisOperations.create_or_update',
-						                     cf_redis, custom_function_op='azure.cli.command_modules.redis.custom#cli_redis_update')
+cli_generic_update_command(__name__, 'redis update',
+                           'azure.mgmt.redis.operations.redis_operations#RedisOperations.get',
+                           'azure.mgmt.redis.operations.redis_operations#RedisOperations.create_or_update', cf_redis,
+                           custom_function_op='azure.cli.command_modules.redis.custom#cli_redis_update',
+                           exception_handler=wrong_vmsize_argument_exception_handler)
 
 cli_command(__name__, 'redis patch-schedule set', 'azure.mgmt.redis.operations.patch_schedules_operations#PatchSchedulesOperations.create_or_update', cf_patch_schedules)
 cli_command(__name__, 'redis patch-schedule delete', 'azure.mgmt.redis.operations.patch_schedules_operations#PatchSchedulesOperations.delete', cf_patch_schedules)
 cli_command(__name__, 'redis patch-schedule show', 'azure.mgmt.redis.operations.patch_schedules_operations#PatchSchedulesOperations.get', cf_patch_schedules)
-
diff --git a/src/command_modules/azure-cli-resource/HISTORY.rst b/src/command_modules/azure-cli-resource/HISTORY.rst
index 4e6a4b0f5..1cb011440 100644
--- a/src/command_modules/azure-cli-resource/HISTORY.rst
+++ b/src/command_modules/azure-cli-resource/HISTORY.rst
@@ -2,8 +2,8 @@
 
 Release History
 ===============
-2.0.3 (unreleased)
-
+2.0.4 (unreleased)
+* Support 'provider operation' commands (#2908)
 * Support generic resource create (#2606)
 
 2.0.3 (2017-04-17)
diff --git a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_client_factory.py b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_client_factory.py
index 120dbaf54..9aa5c14ba 100644
--- a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_client_factory.py
+++ b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_client_factory.py
@@ -28,6 +28,12 @@ def _resource_links_client_factory(**_):
     from azure.cli.core.profiles import ResourceType
     return get_mgmt_service_client(ResourceType.MGMT_RESOURCE_LINKS)
 
+def _authorization_management_client(**_):
+    from azure.cli.core.commands.client_factory import get_mgmt_service_client
+    from azure.mgmt.authorization import AuthorizationManagementClient
+    return get_mgmt_service_client(AuthorizationManagementClient)
+
+
 def cf_resource_groups(_):
     return _resource_client_factory().resource_groups
 
diff --git a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_help.py b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_help.py
index 02da799e6..728f0febe 100644
--- a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_help.py
+++ b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_help.py
@@ -274,6 +274,18 @@ helps['provider unregister'] = """
     type: command
     short-summary: Unregister a provider.
 """
+helps['provider operation'] = """
+    type: group
+    short-summary: Get provider operations metadatas.
+"""
+helps['provider operation show'] = """
+    type: command
+    short-summary: Get an individual provider's operations.
+"""
+helps['provider operation list'] = """
+    type: command
+    short-summary: Get operations from all providers.
+"""
 helps['tag'] = """
     type: group
     short-summary: Manage resource tags.
diff --git a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_params.py b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_params.py
index f6c2b4aae..80c6063b0 100644
--- a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_params.py
+++ b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/_params.py
@@ -46,6 +46,8 @@ register_cli_argument('resource create', 'is_full_object', action='store_true',
 register_cli_argument('provider', 'top', ignore_type)
 register_cli_argument('provider', 'resource_provider_namespace', options_list=('--namespace', '-n'), completer=get_providers_completion_list,
                       help=_PROVIDER_HELP_TEXT)
+register_cli_argument('provider operation', 'api_version', help="The api version of the 'Microsoft.Authorization/providerOperations' resource (omit for latest)")
+
 
 register_cli_argument('feature', 'resource_provider_namespace', options_list=('--namespace',), required=True, help=_PROVIDER_HELP_TEXT)
 register_cli_argument('feature list', 'resource_provider_namespace', options_list=('--namespace',), required=False, help=_PROVIDER_HELP_TEXT)
diff --git a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/commands.py b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/commands.py
index 2321dea4a..bb23b2197 100644
--- a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/commands.py
+++ b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/commands.py
@@ -59,7 +59,8 @@ cli_command(__name__, 'provider list', 'azure.mgmt.resource.resources.operations
 cli_command(__name__, 'provider show', 'azure.mgmt.resource.resources.operations.providers_operations#ProvidersOperations.get', cf_providers, exception_handler=empty_on_404)
 cli_command(__name__, 'provider register', 'azure.cli.command_modules.resource.custom#register_provider')
 cli_command(__name__, 'provider unregister', 'azure.cli.command_modules.resource.custom#unregister_provider')
-
+cli_command(__name__, 'provider operation list', 'azure.cli.command_modules.resource.custom#list_provider_operations')
+cli_command(__name__, 'provider operation show', 'azure.cli.command_modules.resource.custom#show_provider_operations')
 # Resource feature commands
 cli_command(__name__, 'feature list', 'azure.cli.command_modules.resource.custom#list_features', cf_features)
 cli_command(__name__, 'feature show', 'azure.mgmt.resource.features.operations.features_operations#FeaturesOperations.get', cf_features, exception_handler=empty_on_404)
diff --git a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/custom.py b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/custom.py
index 348c44447..38329f140 100644
--- a/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/custom.py
+++ b/src/command_modules/azure-cli-resource/azure/cli/command_modules/resource/custom.py
@@ -27,7 +27,8 @@ from azure.cli.core.profiles import get_sdk, ResourceType
 from ._client_factory import (_resource_client_factory,
                               _resource_policy_client_factory,
                               _resource_lock_client_factory,
-                              _resource_links_client_factory)
+                              _resource_links_client_factory,
+                              _authorization_management_client)
 
 logger = azlogging.get_az_logger(__name__)
 
@@ -352,6 +353,26 @@ def _update_provider(namespace, registering):
     msg_template = '%s is still on-going. You can monitor using \'az provider show -n %s\''
     logger.warning(msg_template, action, namespace)
 
+
+def list_provider_operations(api_version=None):
+    api_version = api_version or _get_auth_provider_latest_api_version()
+    auth_client = _authorization_management_client()
+    return auth_client.provider_operations_metadata.list(api_version)
+
+
+def show_provider_operations(resource_provider_namespace, api_version=None):
+    api_version = api_version or _get_auth_provider_latest_api_version()
+    auth_client = _authorization_management_client()
+    return auth_client.provider_operations_metadata.get(resource_provider_namespace, api_version)
+
+
+def _get_auth_provider_latest_api_version():
+    rcf = _resource_client_factory()
+    api_version = _ResourceUtils.resolve_api_version(rcf, 'Microsoft.Authorization',
+                                                     None, 'providerOperations')
+    return api_version
+
+
 def move_resource(ids, destination_group, destination_subscription_id=None):
     '''Moves resources from one resource group to another(can be under different subscription)
 
@@ -536,6 +557,63 @@ def list_locks(resource_group_name=None, resource_provider_namespace=None,
         resource_group_name, resource_provider_namespace, parent_resource_path, resource_type,
         resource_name, filter=filter_string)
 
+def _validate_lock_params_match_lock(
+        lock_client, name, resource_group_name, resource_provider_namespace,
+        parent_resource_path, resource_type, resource_name):
+    '''
+    Locks are scoped to subscription, resource group or resource.
+    However, the az list command returns all locks for the current scopes
+    and all lower scopes (e.g. resource group level also includes resource locks).
+    This can lead to a confusing user experience where the user specifies a lock
+    name and assumes that it will work, even if they haven't given the right
+    scope. This function attempts to validate the parameters and help the
+    user find the right scope, by first finding the lock, and then infering
+    what it's parameters should be.
+    '''
+    locks = lock_client.management_locks.list_at_subscription_level()
+    found_count = 0 # locks at different levels can have the same name
+    lock_resource_id = None
+    for lock in locks:
+        if lock.name == name:
+            found_count = found_count + 1
+            lock_resource_id = lock.id
+    if found_count == 1:
+        # If we only found one lock, let's validate that the parameters are correct,
+        # if we found more than one, we'll assume the user knows what they're doing
+        # TODO: Add validation for that case too?
+        resource = parse_resource_id(lock_resource_id)
+        _resource_group = resource.get('resource_group', None)
+        _resource_namespace = resource.get('namespace', None)
+        if _resource_group is None:
+            return
+        if resource_group_name != _resource_group:
+            raise CLIError(
+                'Unexpected --resource-group for lock {}, expected {}'.format(
+                    name, _resource_group))
+        if _resource_namespace is None:
+            return
+        if resource_provider_namespace != _resource_namespace:
+            raise CLIError(
+                'Unexpected --namespace for lock {}, expected {}'.format(name, _resource_namespace))
+        if resource.get('grandchild_type', None) is None:
+            _resource_type = resource.get('type', None)
+            _resource_name = resource.get('name', None)
+        else:
+            _resource_type = resource.get('child_type', None)
+            _resource_name = resource.get('child_name', None)
+            parent = (resource['type'] + '/' +  resource['name'])
+            if parent != parent_resource_path:
+                raise CLIError(
+                    'Unexpected --parent for lock {}, expected {}'.format(
+                        name, parent))
+        if resource_type != _resource_type:
+            raise CLIError('Unexpected --resource-type for lock {}, expected {}'.format(
+                name, _resource_type))
+        if resource_name != _resource_name:
+            raise CLIError('Unexpected --resource-name for lock {}, expected {}'.format(
+                name, _resource_name))
+
+
 def get_lock(name, resource_group_name=None):
     '''
     :param name: Name of the lock.
@@ -563,11 +641,16 @@ def delete_lock(name, resource_group_name=None, resource_provider_namespace=None
     lock_client = _resource_lock_client_factory()
     lock_resource = _validate_lock_params(resource_group_name, resource_provider_namespace,
                                           parent_resource_path, resource_type, resource_name)
+    _validate_lock_params_match_lock(lock_client, name, resource_group_name,
+                                     resource_provider_namespace, parent_resource_path,
+                                     resource_type, resource_name)
+
     resource_group_name = lock_resource[0]
     resource_name = lock_resource[1]
     resource_provider_namespace = lock_resource[2]
     resource_type = lock_resource[3]
 
+
     if resource_group_name is None:
         return lock_client.management_locks.delete_at_subscription_level(name)
     if resource_name is None:
@@ -632,7 +715,7 @@ def create_lock(name, resource_group_name=None, resource_provider_namespace=None
     :type notes: str
     '''
     if level != 'ReadOnly' and level != 'CanNotDelete':
-        raise CLIError('--level must be one of "ReadOnly" or "CanNotDelete"')
+        raise CLIError('--lock-type must be one of "ReadOnly" or "CanNotDelete"')
     parameters = ManagementLockObject(level=level, notes=notes, name=name)
 
     lock_client = _resource_lock_client_factory()
@@ -742,10 +825,10 @@ class _ResourceUtils(object): #pylint: disable=too-many-instance-attributes
             else:
                 _validate_resource_inputs(resource_group_name, resource_provider_namespace,
                                           resource_type, resource_name)
-                api_version = _ResourceUtils._resolve_api_version(self.rcf,
-                                                                  resource_provider_namespace,
-                                                                  parent_resource_path,
-                                                                  resource_type)
+                api_version = _ResourceUtils.resolve_api_version(self.rcf,
+                                                                 resource_provider_namespace,
+                                                                 parent_resource_path,
+                                                                 resource_type)
 
         self.resource_group_name = resource_group_name
         self.resource_provider_namespace = resource_provider_namespace
@@ -847,7 +930,7 @@ class _ResourceUtils(object): #pylint: disable=too-many-instance-attributes
                 parameters)
 
     @staticmethod
-    def _resolve_api_version(rcf, resource_provider_namespace, parent_resource_path, resource_type):
+    def resolve_api_version(rcf, resource_provider_namespace, parent_resource_path, resource_type):
         provider = rcf.providers.get(resource_provider_namespace)
 
         #If available, we will use parent resource's api-version
@@ -887,4 +970,4 @@ class _ResourceUtils(object): #pylint: disable=too-many-instance-attributes
             parent = None
             resource_type = parts['type']
 
-        return _ResourceUtils._resolve_api_version(rcf, namespace, parent, resource_type)
+        return _ResourceUtils.resolve_api_version(rcf, namespace, parent, resource_type)
diff --git a/src/command_modules/azure-cli-resource/setup.py b/src/command_modules/azure-cli-resource/setup.py
index a9529b998..b87b9128a 100644
--- a/src/command_modules/azure-cli-resource/setup.py
+++ b/src/command_modules/azure-cli-resource/setup.py
@@ -27,6 +27,7 @@ CLASSIFIERS = [
 DEPENDENCIES = [
     'azure-mgmt-resource==1.0.0rc1',
     'azure-cli-core',
+    'azure-mgmt-authorization==0.30.0rc6'
 ]
 
 with open('README.rst', 'r', encoding='utf-8') as f:
diff --git a/src/command_modules/azure-cli-vm/HISTORY.rst b/src/command_modules/azure-cli-vm/HISTORY.rst
index 4dbdb183b..62dac3bfd 100644
--- a/src/command_modules/azure-cli-vm/HISTORY.rst
+++ b/src/command_modules/azure-cli-vm/HISTORY.rst
@@ -2,6 +2,9 @@
 
 Release History
 ===============
+2.0.4 (unreleased)
+++++++++++++++++++
+* vm/vmss: improve the warning text when generates ssh key pairs
 
 2.0.3 (2017-04-17)
 ++++++++++++++++++
diff --git a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_validators.py b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_validators.py
index 747cef9db..f88ee11c8 100644
--- a/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_validators.py
+++ b/src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_validators.py
@@ -665,7 +665,7 @@ def _validate_admin_password(password, os_type):
 
 def validate_ssh_key(namespace):
     string_or_file = (namespace.ssh_key_value or
-                      os.path.join(os.path.expanduser('~'), '.ssh/id_rsa.pub'))
+                      os.path.join(os.path.expanduser('~'), '.ssh', 'id_rsa.pub'))
     content = string_or_file
     if os.path.exists(string_or_file):
         logger.info('Use existing SSH public key file: %s', string_or_file)
@@ -681,7 +681,10 @@ def validate_ssh_key(namespace):
             else:
                 private_key_filepath = public_key_filepath + '.private'
             content = _generate_ssh_keys(private_key_filepath, public_key_filepath)
-            logger.warning('Created SSH key files: %s,%s',
+            logger.warning("SSH key files '%s' and '%s' have been generated under ~/.ssh to "
+                           "allow SSH access to the VM. If using machines without "
+                           "permanent storage like Azure Cloud Shell without an attached "
+                           "file share, back up your keys to a safe location",
                            private_key_filepath, public_key_filepath)
         else:
             raise CLIError('An RSA key file or key value must be supplied to SSH Key Value. '


Test patch:
diff --git a/src/command_modules/azure-cli-resource/tests/recordings/test_provider_operation.yaml b/src/command_modules/azure-cli-resource/tests/recordings/test_provider_operation.yaml
new file mode 100644
index 000000000..300172ede
--- /dev/null
+++ b/src/command_modules/azure-cli-resource/tests/recordings/test_provider_operation.yaml
@@ -0,0 +1,428 @@
+interactions:
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.14393-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 resourcemanagementclient/1.0.0rc1 Azure-SDK-For-Python
+          AZURECLI/TEST/2.0.3+dev]
+      accept-language: [en-US]
+      x-ms-client-request-id: [b0b09c36-24ae-11e7-b378-64510658e3b3]
+    method: GET
+    uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization?api-version=2016-09-01
+  response:
+    body: {string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization","namespace":"Microsoft.Authorization","resourceTypes":[{"resourceType":"roleAssignments","locations":[],"apiVersions":["2016-07-01","2015-07-01","2015-06-01","2015-05-01-preview","2014-10-01-preview","2014-07-01-preview","2014-04-01-preview"]},{"resourceType":"roleDefinitions","locations":[],"apiVersions":["2016-07-01","2015-07-01","2015-06-01","2015-05-01-preview","2014-10-01-preview","2014-07-01-preview","2014-04-01-preview"]},{"resourceType":"classicAdministrators","locations":[],"apiVersions":["2015-06-01","2015-05-01-preview","2014-10-01-preview","2014-07-01-preview","2014-04-01-preview"]},{"resourceType":"permissions","locations":[],"apiVersions":["2016-07-01","2015-07-01","2015-06-01","2015-05-01-preview","2014-10-01-preview","2014-07-01-preview","2014-04-01-preview"]},{"resourceType":"locks","locations":[],"apiVersions":["2017-04-01","2016-09-01","2015-06-01","2015-05-01-preview","2015-01-01"]},{"resourceType":"operations","locations":[],"apiVersions":["2016-07-01","2015-07-01","2015-01-01","2014-10-01-preview","2014-06-01"]},{"resourceType":"policyDefinitions","locations":[],"apiVersions":["2016-12-01","2016-04-01","2015-10-01-preview"]},{"resourceType":"policyAssignments","locations":[],"apiVersions":["2016-12-01","2016-04-01","2015-10-01-preview"]},{"resourceType":"providerOperations","locations":[],"apiVersions":["2016-07-01","2015-07-01-preview","2015-07-01"]},{"resourceType":"elevateAccess","locations":[],"apiVersions":["2016-07-01","2015-07-01","2015-06-01","2015-05-01-preview","2014-10-01-preview","2014-07-01-preview","2014-04-01-preview"]}],"registrationState":"Registered"}'}
+    headers:
+      Cache-Control: [no-cache]
+      Content-Type: [application/json; charset=utf-8]
+      Date: ['Wed, 19 Apr 2017 03:17:16 GMT']
+      Expires: ['-1']
+      Pragma: [no-cache]
+      Strict-Transport-Security: [max-age=31536000; includeSubDomains]
+      Vary: [Accept-Encoding]
+      content-length: ['1711']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.14393-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 authorizationmanagementclient/0.30.0rc6 Azure-SDK-For-Python
+          AZURECLI/TEST/2.0.3+dev]
+      accept-language: [en-US]
+      x-ms-client-request-id: [b11a8248-24ae-11e7-a4df-64510658e3b3]
+    method: GET
+    uri: https://management.azure.com/providers/Microsoft.Authorization/providerOperations/microsoft.compute?api-version=2016-07-01&$expand=resourceTypes
+  response:
+    body: {string: '{"displayName":"Microsoft Compute","operations":[{"name":"Microsoft.Compute/register/action","displayName":"Register
+        Subscription for Compute","description":"Registers Subscription with Microsoft.Compute
+        resource provider","origin":"user,system","properties":null}],"resourceTypes":[{"name":"restorePointCollections","displayName":"Restore
+        Point Collections","operations":[{"name":"Microsoft.Compute/restorePointCollections/read","displayName":"Get
+        Restore Point Collection","description":"Get the properties of a restore point
+        collection","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/write","displayName":"Create
+        or Update Restore Point Collection","description":"Creates a new restore point
+        collection or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/delete","displayName":"Delete
+        Restore Point Collection","description":"Deletes the restore point collection
+        and contained restore points","origin":"user,system","properties":null}]},{"name":"restorePointCollections/restorePoints","displayName":"Restore
+        Points","operations":[{"name":"Microsoft.Compute/restorePointCollections/restorePoints/read","displayName":"Get
+        Restore Point","description":"Get the properties of a restore point","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/restorePoints/write","displayName":"Create
+        Restore Point","description":"Creates a new restore point","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/restorePoints/delete","displayName":"Delete
+        Restore Point","description":"Deletes the restore point","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/restorePoints/retrieveSasUris/action","displayName":"Get
+        Restore Point along with blob SAS URIs","description":"Get the properties
+        of a restore point along with blob SAS URIs","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets","displayName":"Virtual
+        Machine Scale Sets","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/read","displayName":"Get
+        Virtual Machine Scale Set","description":"Get the properties of a virtual
+        machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/write","displayName":"Create
+        or Update Virtual Machine Scale Set","description":"Creates a new virtual
+        machine scale set or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/delete","displayName":"Delete
+        Virtual Machine Scale Set","description":"Deletes the virtual machine scale
+        set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/start/action","displayName":"Start
+        Virtual Machine Scale Set","description":"Starts the instances of the virtual
+        machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/powerOff/action","displayName":"Power
+        Off Virtual Machine Scale Set","description":"Powers off the instances of
+        the virtual machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/restart/action","displayName":"Restart
+        Virtual Machine Scale Set","description":"Restarts the instances of the virtual
+        machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/deallocate/action","displayName":"Deallocate
+        Virtual Machine Scale Set","description":"Powers off and releases the compute
+        resources for the instances of the virtual machine scale set ","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/manualUpgrade/action","displayName":"Manual
+        Upgrade Virtual Machine Scale Set","description":"Manually updates instances
+        to latest model of the virtual machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/scale/action","displayName":"Scale
+        Virtual Machine Scale Set","description":"Scale In/Scale Out instance count
+        of an existing virtual machine scale set","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets/providers/Microsoft.Insights/metricDefinitions","displayName":"Virtual
+        Machine Scalet Set Metric Definitions","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/providers/Microsoft.Insights/metricDefinitions/read","displayName":"Get
+        Virtual Machine Scalet Set Metric Definitions","description":"Reads Virtual
+        Machine Scalet Set Metric Definitions","origin":"system","properties":{"serviceSpecification":{"metricSpecifications":[{"name":"Percentage
+        CPU","displayName":"Percentage CPU","displayDescription":"The percentage of
+        allocated compute units that are currently in use by the Virtual Machine(s)","unit":"Percent","aggregationType":"Average"},{"name":"Network
+        In","displayName":"Network In","displayDescription":"The number of bytes received
+        on all network interfaces by the Virtual Machine(s) (Incoming Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Network
+        Out","displayName":"Network Out","displayDescription":"The number of bytes
+        out on all network interfaces by the Virtual Machine(s) (Outgoing Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Bytes","displayName":"Disk Read Bytes","displayDescription":"Total bytes
+        read from disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Write Bytes","displayName":"Disk Write Bytes","displayDescription":"Total
+        bytes written to disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Operations/Sec","displayName":"Disk Read Operations/Sec","displayDescription":"Disk
+        Read IOPS","unit":"CountPerSecond","aggregationType":"Average"},{"name":"Disk
+        Write Operations/Sec","displayName":"Disk Write Operations/Sec","displayDescription":"Disk
+        Write IOPS","unit":"CountPerSecond","aggregationType":"Average"}]}}}]},{"name":"virtualMachineScaleSets/instanceView","displayName":"Virtual
+        Machine Scale Set Instance View","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/instanceView/read","displayName":"Get
+        Virtual Machine Scale Set Instance View","description":"Gets the instance
+        view of the virtual machine scale set","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets/skus","displayName":"Virtual
+        Machine Scale Set SKU","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/skus/read","displayName":"List
+        SKUs for Virtual Machine Scale Set","description":"Lists the valid SKUs for
+        an existing virtual machine scale set","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets/virtualMachines","displayName":"Virtual
+        Machine in Scale Set","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/read","displayName":"Gets
+        the properties of a Virtual Machine in a Virtual Machine Scale Set","description":"Retrieves
+        the properties of a Virtual Machine in a VM Scale Set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/delete","displayName":"Delete
+        Virtual Machine in a Virtual Machine Scale Set","description":"Delete a specific
+        Virtual Machine in a VM Scale Set.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/start/action","displayName":"Start
+        Virtual Machine in a Virtual Machine Scale Set","description":"Starts a Virtual
+        Machine instance in a VM Scale Set.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/powerOff/action","displayName":"Power
+        off Virtual Machine in a Virtual Machine Scale Set","description":"Powers
+        Off a Virtual Machine instance in a VM Scale Set.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/restart/action","displayName":"Restart
+        Virtual Machine instance in a Virtual Machine Scale Set","description":"Restarts
+        a Virtual Machine instance in a VM Scale Set.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/deallocate/action","displayName":"Deallocate
+        Virtual Machine in a Virtual Machine Scale Set","description":"Powers off
+        and releases the compute resources for a Virtual Machine in a VM Scale Set.","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets/virtualMachines/providers/Microsoft.Insights/metricDefinitions","displayName":"Virtual
+        Machine in Scale Set Metric Definitions","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/providers/Microsoft.Insights/metricDefinitions/read","displayName":"Get
+        Virtual Machine in Scale Set Metric Definitions","description":"Reads Virtual
+        Machine in Scale Set Metric Definitions","origin":"system","properties":{"serviceSpecification":{"metricSpecifications":[{"name":"Percentage
+        CPU","displayName":"Percentage CPU","displayDescription":"The percentage of
+        allocated compute units that are currently in use by the Virtual Machine(s)","unit":"Percent","aggregationType":"Average"},{"name":"Network
+        In","displayName":"Network In","displayDescription":"The number of bytes received
+        on all network interfaces by the Virtual Machine(s) (Incoming Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Network
+        Out","displayName":"Network Out","displayDescription":"The number of bytes
+        out on all network interfaces by the Virtual Machine(s) (Outgoing Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Bytes","displayName":"Disk Read Bytes","displayDescription":"Total bytes
+        read from disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Write Bytes","displayName":"Disk Write Bytes","displayDescription":"Total
+        bytes written to disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Operations/Sec","displayName":"Disk Read Operations/Sec","displayDescription":"Disk
+        Read IOPS","unit":"CountPerSecond","aggregationType":"Average"},{"name":"Disk
+        Write Operations/Sec","displayName":"Disk Write Operations/Sec","displayDescription":"Disk
+        Write IOPS","unit":"CountPerSecond","aggregationType":"Average"}]}}}]},{"name":"virtualMachineScaleSets/virtualMachines/instanceView","displayName":"Instance
+        View of Virtual Machine in Scale Set","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/instanceView/read","displayName":"Gets
+        Instance View of a Virtual Machine in a Virtual Machine Scale Set","description":"Retrieves
+        the instance view of a Virtual Machine in a VM Scale Set.","origin":"user,system","properties":null}]},{"name":"images","displayName":"Images","operations":[{"name":"Microsoft.Compute/images/read","displayName":"Get
+        Image","description":"Get the properties of the Image","origin":"user,system","properties":null},{"name":"Microsoft.Compute/images/write","displayName":"Create
+        or Update Image","description":"Creates a new Image or updates an existing
+        one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/images/delete","displayName":"Delete
+        Image","description":"Deletes the image","origin":"user,system","properties":null}]},{"name":"operations","displayName":"Available
+        Compute Operations","operations":[{"name":"Microsoft.Compute/operations/read","displayName":"List
+        Available Compute Operations","description":"Lists operations available on
+        Microsoft.Compute resource provider","origin":"user,system","properties":null}]},{"name":"disks","displayName":"Disks","operations":[{"name":"Microsoft.Compute/disks/read","displayName":"Get
+        Disk","description":"Get the properties of a Disk","origin":"user,system","properties":null},{"name":"Microsoft.Compute/disks/write","displayName":"Create
+        or Update Disk","description":"Creates a new Disk or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/disks/delete","displayName":"Delete
+        Disk","description":"Deletes the Disk","origin":"user,system","properties":null},{"name":"Microsoft.Compute/disks/beginGetAccess/action","displayName":"Get
+        Disk SAS URI","description":"Get the SAS URI of the Disk for blob access","origin":"user,system","properties":null},{"name":"Microsoft.Compute/disks/endGetAccess/action","displayName":"Revoke
+        Disk SAS URI","description":"Revoke the SAS URI of the Disk","origin":"user,system","properties":null}]},{"name":"snapshots","displayName":"Snapshots","operations":[{"name":"Microsoft.Compute/snapshots/read","displayName":"Get
+        Snapshot","description":"Get the properties of a Snapshot","origin":"user,system","properties":null},{"name":"Microsoft.Compute/snapshots/write","displayName":"Create
+        or Update Snapshot","description":"Create a new Snapshot or update an existing
+        one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/snapshots/delete","displayName":"Delete
+        Snapshot","description":"Delete a Snapshot","origin":"user,system","properties":null}]},{"name":"availabilitySets","displayName":"Availability
+        Sets","operations":[{"name":"Microsoft.Compute/availabilitySets/read","displayName":"Get
+        Availablity Set","description":"Get the properties of an availability set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/availabilitySets/write","displayName":"Create
+        or Update Availability Set","description":"Creates a new availability set
+        or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/availabilitySets/delete","displayName":"Delete
+        Availability Set","description":"Deletes the availability set","origin":"user,system","properties":null}]},{"name":"availabilitySets/vmSizes","displayName":"Virtual
+        Machine Size for Availability set","operations":[{"name":"Microsoft.Compute/availabilitySets/vmSizes/read","displayName":"List
+        Virtual Machine Sizes for Availability Set","description":"List available
+        sizes for creating or updating a virtual machine in the availability set","origin":"user,system","properties":null}]},{"name":"virtualMachines","displayName":"Virtual
+        Machines","operations":[{"name":"Microsoft.Compute/virtualMachines/read","displayName":"Get
+        Virtual Machine","description":"Get the properties of a virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/write","displayName":"Create
+        or Update Virtual Machine","description":"Creates a new virtual machine or
+        updates an existing virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/delete","displayName":"Delete
+        Virtual Machine","description":"Deletes the virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/start/action","displayName":"Start
+        Virtual Machine","description":"Starts the virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/powerOff/action","displayName":"Power
+        Off Virtual Machine","description":"Powers off the virtual machine. Note that
+        the virtual machine will continue to be billed.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/redeploy/action","displayName":"Redeploy
+        Virtual Machine","description":"Redeploys virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/restart/action","displayName":"Restart
+        Virtual Machine","description":"Restarts the virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/deallocate/action","displayName":"Deallocate
+        Virtual Machine","description":"Powers off the virtual machine and releases
+        the compute resources","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/generalize/action","displayName":"Generalize
+        Virtual Machine","description":"Sets the virtual machine state to Generalized
+        and prepares the virtual machine for capture","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/capture/action","displayName":"Capture
+        Virtual Machine","description":"Captures the virtual machine by copying virtual
+        hard disks and generates a template that can be used to create similar virtual
+        machines","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/convertToManagedDisks/action","displayName":"Convert
+        Virtual Machine disks to Managed Disks","description":"Converts the blob based
+        disks of the virtual machine to managed disks","origin":"user,system","properties":null}]},{"name":"virtualMachines/providers/Microsoft.Insights/metricDefinitions","displayName":"Virtual
+        Machine Metric Definitions","operations":[{"name":"Microsoft.Compute/virtualMachines/providers/Microsoft.Insights/metricDefinitions/read","displayName":"Get
+        Virtual Machine Metric Definitions","description":"Reads Virtual Machine Metric
+        Definitions","origin":"system","properties":{"serviceSpecification":{"metricSpecifications":[{"name":"Percentage
+        CPU","displayName":"Percentage CPU","displayDescription":"The percentage of
+        allocated compute units that are currently in use by the Virtual Machine(s)","unit":"Percent","aggregationType":"Average"},{"name":"Network
+        In","displayName":"Network In","displayDescription":"The number of bytes received
+        on all network interfaces by the Virtual Machine(s) (Incoming Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Network
+        Out","displayName":"Network Out","displayDescription":"The number of bytes
+        out on all network interfaces by the Virtual Machine(s) (Outgoing Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Bytes","displayName":"Disk Read Bytes","displayDescription":"Total bytes
+        read from disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Write Bytes","displayName":"Disk Write Bytes","displayDescription":"Total
+        bytes written to disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Operations/Sec","displayName":"Disk Read Operations/Sec","displayDescription":"Disk
+        Read IOPS","unit":"CountPerSecond","aggregationType":"Average"},{"name":"Disk
+        Write Operations/Sec","displayName":"Disk Write Operations/Sec","displayDescription":"Disk
+        Write IOPS","unit":"CountPerSecond","aggregationType":"Average"}]}}}]},{"name":"virtualMachines/vmSizes","displayName":"Virtual
+        Machine Size","operations":[{"name":"Microsoft.Compute/virtualMachines/vmSizes/read","displayName":"Lists
+        Available Virtual Machine Sizes","description":"Lists available sizes the
+        virtual machine can be updated to","origin":"user,system","properties":null}]},{"name":"virtualMachines/instanceView","displayName":"Virtual
+        Machine Instance View","operations":[{"name":"Microsoft.Compute/virtualMachines/instanceView/read","displayName":"Get
+        Virtual Machine Instance View","description":"Gets the detailed runtime status
+        of the virtual machine and its resources","origin":"user,system","properties":null}]},{"name":"virtualMachines/extensions","displayName":"Virtual
+        Machine Extensions","operations":[{"name":"Microsoft.Compute/virtualMachines/extensions/read","displayName":"Get
+        Virtual Machine Extension","description":"Get the properties of a virtual
+        machine extension","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/extensions/write","displayName":"Create
+        or Update Virtual Machine Extension","description":"Creates a new virtual
+        machine extension or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/extensions/delete","displayName":"Delete
+        Virtual Machine Extension","description":"Deletes the virtual machine extension","origin":"user,system","properties":null}]},{"name":"locations/vmSizes","displayName":"Virtual
+        Machine Sizes","operations":[{"name":"Microsoft.Compute/locations/vmSizes/read","displayName":"List
+        Available Virtual Machine Sizes in Location","description":"Lists available
+        virtual machine sizes in a location","origin":"user,system","properties":null}]},{"name":"locations/usages","displayName":"Usage
+        Metrics","operations":[{"name":"Microsoft.Compute/locations/usages/read","displayName":"Get
+        Usage Metrics","description":"Gets service limits and current usage quantities
+        for the subscription''s compute resources in a location","origin":"user,system","properties":null}]},{"name":"locations/operations","displayName":"Operation","operations":[{"name":"Microsoft.Compute/locations/operations/read","displayName":"Get
+        Operation","description":"Gets the status of an asynchronous operation","origin":"user,system","properties":null}]}],"id":"/providers/Microsoft.Authorization/providerOperations/Microsoft.Compute","type":"Microsoft.Authorization/providerOperations","name":"Microsoft.Compute"}'}
+    headers:
+      Cache-Control: [no-cache]
+      Content-Type: [application/json; charset=utf-8]
+      Date: ['Wed, 19 Apr 2017 03:17:16 GMT']
+      Expires: ['-1']
+      Pragma: [no-cache]
+      Server: [Microsoft-IIS/8.5]
+      Set-Cookie: [x-ms-gateway-slice=productionb; path=/; secure; HttpOnly]
+      Strict-Transport-Security: [max-age=31536000; includeSubDomains]
+      Transfer-Encoding: [chunked]
+      Vary: [Accept-Encoding]
+      X-Content-Type-Options: [nosniff]
+      X-Powered-By: [ASP.NET]
+      content-length: ['20896']
+    status: {code: 200, message: OK}
+- request:
+    body: null
+    headers:
+      Accept: [application/json]
+      Accept-Encoding: ['gzip, deflate']
+      Connection: [keep-alive]
+      Content-Type: [application/json; charset=utf-8]
+      User-Agent: [python/3.5.3 (Windows-10-10.0.14393-SP0) requests/2.9.1 msrest/0.4.7
+          msrest_azure/0.4.7 authorizationmanagementclient/0.30.0rc6 Azure-SDK-For-Python
+          AZURECLI/TEST/2.0.3+dev]
+      accept-language: [en-US]
+      x-ms-client-request-id: [b1821cb8-24ae-11e7-a4ab-64510658e3b3]
+    method: GET
+    uri: https://management.azure.com/providers/Microsoft.Authorization/providerOperations/microsoft.compute?api-version=2015-07-01&$expand=resourceTypes
+  response:
+    body: {string: '{"displayName":"Microsoft Compute","operations":[{"name":"Microsoft.Compute/register/action","displayName":"Register
+        Subscription for Compute","description":"Registers Subscription with Microsoft.Compute
+        resource provider","origin":"user,system","properties":null}],"resourceTypes":[{"name":"restorePointCollections","displayName":"Restore
+        Point Collections","operations":[{"name":"Microsoft.Compute/restorePointCollections/read","displayName":"Get
+        Restore Point Collection","description":"Get the properties of a restore point
+        collection","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/write","displayName":"Create
+        or Update Restore Point Collection","description":"Creates a new restore point
+        collection or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/delete","displayName":"Delete
+        Restore Point Collection","description":"Deletes the restore point collection
+        and contained restore points","origin":"user,system","properties":null}]},{"name":"restorePointCollections/restorePoints","displayName":"Restore
+        Points","operations":[{"name":"Microsoft.Compute/restorePointCollections/restorePoints/read","displayName":"Get
+        Restore Point","description":"Get the properties of a restore point","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/restorePoints/write","displayName":"Create
+        Restore Point","description":"Creates a new restore point","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/restorePoints/delete","displayName":"Delete
+        Restore Point","description":"Deletes the restore point","origin":"user,system","properties":null},{"name":"Microsoft.Compute/restorePointCollections/restorePoints/retrieveSasUris/action","displayName":"Get
+        Restore Point along with blob SAS URIs","description":"Get the properties
+        of a restore point along with blob SAS URIs","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets","displayName":"Virtual
+        Machine Scale Sets","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/read","displayName":"Get
+        Virtual Machine Scale Set","description":"Get the properties of a virtual
+        machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/write","displayName":"Create
+        or Update Virtual Machine Scale Set","description":"Creates a new virtual
+        machine scale set or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/delete","displayName":"Delete
+        Virtual Machine Scale Set","description":"Deletes the virtual machine scale
+        set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/start/action","displayName":"Start
+        Virtual Machine Scale Set","description":"Starts the instances of the virtual
+        machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/powerOff/action","displayName":"Power
+        Off Virtual Machine Scale Set","description":"Powers off the instances of
+        the virtual machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/restart/action","displayName":"Restart
+        Virtual Machine Scale Set","description":"Restarts the instances of the virtual
+        machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/deallocate/action","displayName":"Deallocate
+        Virtual Machine Scale Set","description":"Powers off and releases the compute
+        resources for the instances of the virtual machine scale set ","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/manualUpgrade/action","displayName":"Manual
+        Upgrade Virtual Machine Scale Set","description":"Manually updates instances
+        to latest model of the virtual machine scale set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/scale/action","displayName":"Scale
+        Virtual Machine Scale Set","description":"Scale In/Scale Out instance count
+        of an existing virtual machine scale set","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets/providers/Microsoft.Insights/metricDefinitions","displayName":"Virtual
+        Machine Scalet Set Metric Definitions","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/providers/Microsoft.Insights/metricDefinitions/read","displayName":"Get
+        Virtual Machine Scalet Set Metric Definitions","description":"Reads Virtual
+        Machine Scalet Set Metric Definitions","origin":"system","properties":{"serviceSpecification":{"metricSpecifications":[{"name":"Percentage
+        CPU","displayName":"Percentage CPU","displayDescription":"The percentage of
+        allocated compute units that are currently in use by the Virtual Machine(s)","unit":"Percent","aggregationType":"Average"},{"name":"Network
+        In","displayName":"Network In","displayDescription":"The number of bytes received
+        on all network interfaces by the Virtual Machine(s) (Incoming Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Network
+        Out","displayName":"Network Out","displayDescription":"The number of bytes
+        out on all network interfaces by the Virtual Machine(s) (Outgoing Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Bytes","displayName":"Disk Read Bytes","displayDescription":"Total bytes
+        read from disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Write Bytes","displayName":"Disk Write Bytes","displayDescription":"Total
+        bytes written to disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Operations/Sec","displayName":"Disk Read Operations/Sec","displayDescription":"Disk
+        Read IOPS","unit":"CountPerSecond","aggregationType":"Average"},{"name":"Disk
+        Write Operations/Sec","displayName":"Disk Write Operations/Sec","displayDescription":"Disk
+        Write IOPS","unit":"CountPerSecond","aggregationType":"Average"}]}}}]},{"name":"virtualMachineScaleSets/instanceView","displayName":"Virtual
+        Machine Scale Set Instance View","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/instanceView/read","displayName":"Get
+        Virtual Machine Scale Set Instance View","description":"Gets the instance
+        view of the virtual machine scale set","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets/skus","displayName":"Virtual
+        Machine Scale Set SKU","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/skus/read","displayName":"List
+        SKUs for Virtual Machine Scale Set","description":"Lists the valid SKUs for
+        an existing virtual machine scale set","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets/virtualMachines","displayName":"Virtual
+        Machine in Scale Set","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/read","displayName":"Gets
+        the properties of a Virtual Machine in a Virtual Machine Scale Set","description":"Retrieves
+        the properties of a Virtual Machine in a VM Scale Set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/delete","displayName":"Delete
+        Virtual Machine in a Virtual Machine Scale Set","description":"Delete a specific
+        Virtual Machine in a VM Scale Set.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/start/action","displayName":"Start
+        Virtual Machine in a Virtual Machine Scale Set","description":"Starts a Virtual
+        Machine instance in a VM Scale Set.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/powerOff/action","displayName":"Power
+        off Virtual Machine in a Virtual Machine Scale Set","description":"Powers
+        Off a Virtual Machine instance in a VM Scale Set.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/restart/action","displayName":"Restart
+        Virtual Machine instance in a Virtual Machine Scale Set","description":"Restarts
+        a Virtual Machine instance in a VM Scale Set.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/deallocate/action","displayName":"Deallocate
+        Virtual Machine in a Virtual Machine Scale Set","description":"Powers off
+        and releases the compute resources for a Virtual Machine in a VM Scale Set.","origin":"user,system","properties":null}]},{"name":"virtualMachineScaleSets/virtualMachines/providers/Microsoft.Insights/metricDefinitions","displayName":"Virtual
+        Machine in Scale Set Metric Definitions","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/providers/Microsoft.Insights/metricDefinitions/read","displayName":"Get
+        Virtual Machine in Scale Set Metric Definitions","description":"Reads Virtual
+        Machine in Scale Set Metric Definitions","origin":"system","properties":{"serviceSpecification":{"metricSpecifications":[{"name":"Percentage
+        CPU","displayName":"Percentage CPU","displayDescription":"The percentage of
+        allocated compute units that are currently in use by the Virtual Machine(s)","unit":"Percent","aggregationType":"Average"},{"name":"Network
+        In","displayName":"Network In","displayDescription":"The number of bytes received
+        on all network interfaces by the Virtual Machine(s) (Incoming Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Network
+        Out","displayName":"Network Out","displayDescription":"The number of bytes
+        out on all network interfaces by the Virtual Machine(s) (Outgoing Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Bytes","displayName":"Disk Read Bytes","displayDescription":"Total bytes
+        read from disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Write Bytes","displayName":"Disk Write Bytes","displayDescription":"Total
+        bytes written to disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Operations/Sec","displayName":"Disk Read Operations/Sec","displayDescription":"Disk
+        Read IOPS","unit":"CountPerSecond","aggregationType":"Average"},{"name":"Disk
+        Write Operations/Sec","displayName":"Disk Write Operations/Sec","displayDescription":"Disk
+        Write IOPS","unit":"CountPerSecond","aggregationType":"Average"}]}}}]},{"name":"virtualMachineScaleSets/virtualMachines/instanceView","displayName":"Instance
+        View of Virtual Machine in Scale Set","operations":[{"name":"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/instanceView/read","displayName":"Gets
+        Instance View of a Virtual Machine in a Virtual Machine Scale Set","description":"Retrieves
+        the instance view of a Virtual Machine in a VM Scale Set.","origin":"user,system","properties":null}]},{"name":"images","displayName":"Images","operations":[{"name":"Microsoft.Compute/images/read","displayName":"Get
+        Image","description":"Get the properties of the Image","origin":"user,system","properties":null},{"name":"Microsoft.Compute/images/write","displayName":"Create
+        or Update Image","description":"Creates a new Image or updates an existing
+        one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/images/delete","displayName":"Delete
+        Image","description":"Deletes the image","origin":"user,system","properties":null}]},{"name":"operations","displayName":"Available
+        Compute Operations","operations":[{"name":"Microsoft.Compute/operations/read","displayName":"List
+        Available Compute Operations","description":"Lists operations available on
+        Microsoft.Compute resource provider","origin":"user,system","properties":null}]},{"name":"disks","displayName":"Disks","operations":[{"name":"Microsoft.Compute/disks/read","displayName":"Get
+        Disk","description":"Get the properties of a Disk","origin":"user,system","properties":null},{"name":"Microsoft.Compute/disks/write","displayName":"Create
+        or Update Disk","description":"Creates a new Disk or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/disks/delete","displayName":"Delete
+        Disk","description":"Deletes the Disk","origin":"user,system","properties":null},{"name":"Microsoft.Compute/disks/beginGetAccess/action","displayName":"Get
+        Disk SAS URI","description":"Get the SAS URI of the Disk for blob access","origin":"user,system","properties":null},{"name":"Microsoft.Compute/disks/endGetAccess/action","displayName":"Revoke
+        Disk SAS URI","description":"Revoke the SAS URI of the Disk","origin":"user,system","properties":null}]},{"name":"snapshots","displayName":"Snapshots","operations":[{"name":"Microsoft.Compute/snapshots/read","displayName":"Get
+        Snapshot","description":"Get the properties of a Snapshot","origin":"user,system","properties":null},{"name":"Microsoft.Compute/snapshots/write","displayName":"Create
+        or Update Snapshot","description":"Create a new Snapshot or update an existing
+        one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/snapshots/delete","displayName":"Delete
+        Snapshot","description":"Delete a Snapshot","origin":"user,system","properties":null}]},{"name":"availabilitySets","displayName":"Availability
+        Sets","operations":[{"name":"Microsoft.Compute/availabilitySets/read","displayName":"Get
+        Availablity Set","description":"Get the properties of an availability set","origin":"user,system","properties":null},{"name":"Microsoft.Compute/availabilitySets/write","displayName":"Create
+        or Update Availability Set","description":"Creates a new availability set
+        or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/availabilitySets/delete","displayName":"Delete
+        Availability Set","description":"Deletes the availability set","origin":"user,system","properties":null}]},{"name":"availabilitySets/vmSizes","displayName":"Virtual
+        Machine Size for Availability set","operations":[{"name":"Microsoft.Compute/availabilitySets/vmSizes/read","displayName":"List
+        Virtual Machine Sizes for Availability Set","description":"List available
+        sizes for creating or updating a virtual machine in the availability set","origin":"user,system","properties":null}]},{"name":"virtualMachines","displayName":"Virtual
+        Machines","operations":[{"name":"Microsoft.Compute/virtualMachines/read","displayName":"Get
+        Virtual Machine","description":"Get the properties of a virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/write","displayName":"Create
+        or Update Virtual Machine","description":"Creates a new virtual machine or
+        updates an existing virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/delete","displayName":"Delete
+        Virtual Machine","description":"Deletes the virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/start/action","displayName":"Start
+        Virtual Machine","description":"Starts the virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/powerOff/action","displayName":"Power
+        Off Virtual Machine","description":"Powers off the virtual machine. Note that
+        the virtual machine will continue to be billed.","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/redeploy/action","displayName":"Redeploy
+        Virtual Machine","description":"Redeploys virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/restart/action","displayName":"Restart
+        Virtual Machine","description":"Restarts the virtual machine","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/deallocate/action","displayName":"Deallocate
+        Virtual Machine","description":"Powers off the virtual machine and releases
+        the compute resources","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/generalize/action","displayName":"Generalize
+        Virtual Machine","description":"Sets the virtual machine state to Generalized
+        and prepares the virtual machine for capture","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/capture/action","displayName":"Capture
+        Virtual Machine","description":"Captures the virtual machine by copying virtual
+        hard disks and generates a template that can be used to create similar virtual
+        machines","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/convertToManagedDisks/action","displayName":"Convert
+        Virtual Machine disks to Managed Disks","description":"Converts the blob based
+        disks of the virtual machine to managed disks","origin":"user,system","properties":null}]},{"name":"virtualMachines/providers/Microsoft.Insights/metricDefinitions","displayName":"Virtual
+        Machine Metric Definitions","operations":[{"name":"Microsoft.Compute/virtualMachines/providers/Microsoft.Insights/metricDefinitions/read","displayName":"Get
+        Virtual Machine Metric Definitions","description":"Reads Virtual Machine Metric
+        Definitions","origin":"system","properties":{"serviceSpecification":{"metricSpecifications":[{"name":"Percentage
+        CPU","displayName":"Percentage CPU","displayDescription":"The percentage of
+        allocated compute units that are currently in use by the Virtual Machine(s)","unit":"Percent","aggregationType":"Average"},{"name":"Network
+        In","displayName":"Network In","displayDescription":"The number of bytes received
+        on all network interfaces by the Virtual Machine(s) (Incoming Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Network
+        Out","displayName":"Network Out","displayDescription":"The number of bytes
+        out on all network interfaces by the Virtual Machine(s) (Outgoing Traffic)","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Bytes","displayName":"Disk Read Bytes","displayDescription":"Total bytes
+        read from disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Write Bytes","displayName":"Disk Write Bytes","displayDescription":"Total
+        bytes written to disk during monitoring period","unit":"Bytes","aggregationType":"Total"},{"name":"Disk
+        Read Operations/Sec","displayName":"Disk Read Operations/Sec","displayDescription":"Disk
+        Read IOPS","unit":"CountPerSecond","aggregationType":"Average"},{"name":"Disk
+        Write Operations/Sec","displayName":"Disk Write Operations/Sec","displayDescription":"Disk
+        Write IOPS","unit":"CountPerSecond","aggregationType":"Average"}]}}}]},{"name":"virtualMachines/vmSizes","displayName":"Virtual
+        Machine Size","operations":[{"name":"Microsoft.Compute/virtualMachines/vmSizes/read","displayName":"Lists
+        Available Virtual Machine Sizes","description":"Lists available sizes the
+        virtual machine can be updated to","origin":"user,system","properties":null}]},{"name":"virtualMachines/instanceView","displayName":"Virtual
+        Machine Instance View","operations":[{"name":"Microsoft.Compute/virtualMachines/instanceView/read","displayName":"Get
+        Virtual Machine Instance View","description":"Gets the detailed runtime status
+        of the virtual machine and its resources","origin":"user,system","properties":null}]},{"name":"virtualMachines/extensions","displayName":"Virtual
+        Machine Extensions","operations":[{"name":"Microsoft.Compute/virtualMachines/extensions/read","displayName":"Get
+        Virtual Machine Extension","description":"Get the properties of a virtual
+        machine extension","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/extensions/write","displayName":"Create
+        or Update Virtual Machine Extension","description":"Creates a new virtual
+        machine extension or updates an existing one","origin":"user,system","properties":null},{"name":"Microsoft.Compute/virtualMachines/extensions/delete","displayName":"Delete
+        Virtual Machine Extension","description":"Deletes the virtual machine extension","origin":"user,system","properties":null}]},{"name":"locations/vmSizes","displayName":"Virtual
+        Machine Sizes","operations":[{"name":"Microsoft.Compute/locations/vmSizes/read","displayName":"List
+        Available Virtual Machine Sizes in Location","description":"Lists available
+        virtual machine sizes in a location","origin":"user,system","properties":null}]},{"name":"locations/usages","displayName":"Usage
+        Metrics","operations":[{"name":"Microsoft.Compute/locations/usages/read","displayName":"Get
+        Usage Metrics","description":"Gets service limits and current usage quantities
+        for the subscription''s compute resources in a location","origin":"user,system","properties":null}]},{"name":"locations/operations","displayName":"Operation","operations":[{"name":"Microsoft.Compute/locations/operations/read","displayName":"Get
+        Operation","description":"Gets the status of an asynchronous operation","origin":"user,system","properties":null}]}],"id":"/providers/Microsoft.Authorization/providerOperations/Microsoft.Compute","type":"Microsoft.Authorization/providerOperations","name":"Microsoft.Compute"}'}
+    headers:
+      Cache-Control: [no-cache]
+      Content-Type: [application/json; charset=utf-8]
+      Date: ['Wed, 19 Apr 2017 03:17:17 GMT']
+      Expires: ['-1']
+      Pragma: [no-cache]
+      Server: [Microsoft-IIS/8.5]
+      Set-Cookie: [x-ms-gateway-slice=productionb; path=/]
+      Strict-Transport-Security: [max-age=31536000; includeSubDomains]
+      Transfer-Encoding: [chunked]
+      Vary: [Accept-Encoding]
+      X-Content-Type-Options: [nosniff]
+      X-Powered-By: [ASP.NET]
+      content-length: ['20896']
+    status: {code: 200, message: OK}
+version: 1
diff --git a/src/command_modules/azure-cli-resource/tests/test_resource.py b/src/command_modules/azure-cli-resource/tests/test_resource.py
index 0705f87e8..8a6f1e28f 100644
--- a/src/command_modules/azure-cli-resource/tests/test_resource.py
+++ b/src/command_modules/azure-cli-resource/tests/test_resource.py
@@ -262,6 +262,25 @@ class ProviderRegistrationTest(VCRTestBase): # Not RG test base because it opera
             result = self.cmd('provider show -n {}'.format(provider))
             self.assertTrue(result['registrationState'] in ['Registering', 'Registered'])
 
+
+class ProviderOperationTest(VCRTestBase): # Not RG test base because it operates only on the subscription
+    def __init__(self, test_method):
+        super(ProviderOperationTest, self).__init__(__file__, test_method)
+
+    def test_provider_operation(self):
+        self.execute()
+
+    def body(self):
+        self.cmd('provider operation show --namespace microsoft.compute', checks=[
+            JMESPathCheck('id', '/providers/Microsoft.Authorization/providerOperations/Microsoft.Compute'),
+            JMESPathCheck('type', 'Microsoft.Authorization/providerOperations')
+        ]) 
+        self.cmd('provider operation show --namespace microsoft.compute --api-version 2015-07-01', checks=[
+            JMESPathCheck('id', '/providers/Microsoft.Authorization/providerOperations/Microsoft.Compute'),
+            JMESPathCheck('type', 'Microsoft.Authorization/providerOperations')
+        ])
+
+
 class DeploymentTest(ResourceGroupVCRTestBase):
     def __init__(self, test_method):
         super(DeploymentTest, self).__init__(__file__, test_method, resource_group='azure-cli-deployment-test')