Repository: Azure/azure-cli (Python)

Issue:
Add support for Azure workbooks in Az CLI 
Request to add support for Azure workbooks in Az CLI

**Related command**
az monitor workbook 

**Is your feature request related to a problem? Please describe.**
No, it's a new set of sub verbs.

**Describe the solution you'd like**
The idea is have CURD operation for Azure workbook in Az CLI.

az monitor workbook create/update/remove/list

**Describe alternatives you've considered**
The alternate option is to use REST API or ARM or bicep template.

**Additional context**
N/A




Fix (patch):
diff --git a/src/command_modules/azure-cli-batch/HISTORY.rst b/src/command_modules/azure-cli-batch/HISTORY.rst
index 9ca26dfa68b..add2b1f64b5 100644
--- a/src/command_modules/azure-cli-batch/HISTORY.rst
+++ b/src/command_modules/azure-cli-batch/HISTORY.rst
@@ -3,6 +3,13 @@
 Release History
 ===============
 
+3.3.4
++++++
+* Update adding tasks through --json-file to support AddTaskCollectionParameter syntax
+* Update documentation of accepted --json-file formats
+* Add --max-tasks-per-node-option to az batch pool create
+* Update show behavior of az batch account to show currently logged in account if no options are specified.
+
 3.3.3
 +++++
 * Update Batch Management SDK dependency
diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_command_type.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_command_type.py
index de0da662641..ee25c680367 100644
--- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_command_type.py
+++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_command_type.py
@@ -766,7 +766,8 @@ def _load_transformed_arguments(self, handler):
                 for flattened_arg in self.parser.compile_args():
                     args.append(flattened_arg)
                 param = 'json_file'
-                docstring = "A file containing the {} specification in JSON format. " \
+                docstring = "A file containing the {} specification in JSON " \
+                            "(formatted to match the respective REST API body). " \
                             "If this parameter is specified, all '{} Arguments'" \
                             " are ignored.".format(arg[0].replace('_', ' '), group_title(arg[0]))
                 args.append((param, CLICommandArgument(param,
diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_help.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_help.py
index 45bbc9399a4..50eefaa02ff 100644
--- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_help.py
+++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_help.py
@@ -47,6 +47,11 @@
     short-summary: Log in to a Batch account through Azure Active Directory or Shared Key authentication.
 """
 
+helps['batch account show'] = """
+    type: command
+    short-summary: Get a specified Batch account or the currently set account.
+"""
+
 helps['batch application'] = """
     type: group
     short-summary: Manage Batch applications.
@@ -73,6 +78,7 @@
     long-summary: This step is unnecessary if the package has already been successfully activated by the `create` command.
 """
 
+
 helps['batch application summary'] = """
     type: group
     short-summary: View a summary of Batch application packages.
diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_parameter_format.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_parameter_format.py
index ee1f22f06cd..46836c4bf5c 100644
--- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_parameter_format.py
+++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_parameter_format.py
@@ -66,7 +66,6 @@
     'job_release_task',
     'auto_pool_specification',
     'on_task_failure',
-    'max_tasks_per_node',
     'job.on_all_tasks_complete',
     'job_manager_task.kill_job_on_completion',
     'job_manager_task.run_exclusive',
diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_params.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_params.py
index 688b227f9c2..4b334da81be 100644
--- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_params.py
+++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_params.py
@@ -8,8 +8,7 @@
 from knack.arguments import CLIArgumentType
 
 from azure.mgmt.batch.models import AccountKeyType
-from azure.batch.models.batch_service_client_enums import \
-    (ComputeNodeDeallocationOption)
+from azure.batch.models import ComputeNodeDeallocationOption
 
 from azure.cli.core.commands.parameters import \
     (tags_type, get_location_type, resource_group_name_type,
@@ -38,6 +37,10 @@ def load_arguments(self, _):
     with self.argument_context('batch account') as c:
         c.argument('account_name', batch_name_type, options_list=('--name', '-n'))
 
+    with self.argument_context('batch account show') as c:
+        c.argument('resource_group_name', resource_group_name_type, help='Name of the resource group. If not specified will display currently set account.', required=False)
+        c.argument('account_name', batch_name_type, options_list=('--name', '-n'), help='Name of the batch account to show. If not specified will display currently set account.', required=False)
+
     with self.argument_context('batch account list') as c:
         c.argument('resource_group_name', resource_group_name_type, help='Name of the resource group', required=False)
 
@@ -90,7 +93,7 @@ def load_arguments(self, _):
 
     # TODO: Refactor so the help text can be extracted automatically
     with self.argument_context('batch pool reset') as c:
-        c.argument('json_file', type=file_type, help='The file containing pool update properties parameter specification in JSON format. If this parameter is specified, all \'Pool Update Properties Parameter Arguments\' are ignored.', validator=validate_json_file, completer=FilesCompleter())
+        c.argument('json_file', type=file_type, help='The file containing pool update properties parameter specification in JSON(formatted to match REST API request body). If this parameter is specified, all \'Pool Update Properties Parameter Arguments\' are ignored.', validator=validate_json_file, completer=FilesCompleter())
         c.argument('pool_id', help='The ID of the pool to update.')
         c.argument('application_package_references', nargs='+', type=application_package_reference_format, arg_group='Pool')
         c.argument('certificate_references', nargs='+', type=certificate_reference_format, arg_group='Pool')
@@ -130,7 +133,7 @@ def load_arguments(self, _):
         c.argument('thumbprint', help='The certificate thumbprint.', validator=validate_cert_settings)
 
     with self.argument_context('batch task create') as c:
-        c.argument('json_file', type=file_type, help='The file containing the task(s) to create in JSON format, if this parameter is specified, all other parameters are ignored.', validator=validate_json_file, completer=FilesCompleter())
+        c.argument('json_file', type=file_type, help='The file containing the task(s) to create in JSON(formatted to match REST API request body). When submitting multiple tasks, accepts either an array of tasks or a TaskAddCollectionParamater. If this parameter is specified, all other parameters are ignored.', validator=validate_json_file, completer=FilesCompleter())
         c.argument('application_package_references', nargs='+', help='The space-separated list of IDs specifying the application packages to be installed. Space-separated application IDs with optional version in \'id[#version]\' format.', type=application_package_reference_format)
         c.argument('job_id', help='The ID of the job containing the task.')
         c.argument('task_id', help='The ID of the task.')
diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/commands.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/commands.py
index 6f5008ac824..b2c50b3f0b4 100644
--- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/commands.py
+++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/commands.py
@@ -51,7 +51,7 @@ def get_data_factory(name):
     # Mgmt Account Operations
     with self.command_group('batch account', get_mgmt_type('batch_account'), client_factory=get_mgmt_factory('batch_account')) as g:
         g.custom_command('list', 'list_accounts', table_transformer=account_list_table_format)
-        g.show_command('show', 'get')
+        g.custom_command('show', 'get_account')
         g.custom_command('create', 'create_account', supports_no_wait=True)
         g.custom_command('set', 'update_account')
         g.command('delete', 'delete', supports_no_wait=True, confirmation=True)
diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/custom.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/custom.py
index 13a9ce58663..48930eb3975 100644
--- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/custom.py
+++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/custom.py
@@ -18,8 +18,8 @@
 
 from azure.batch.models import (CertificateAddParameter, PoolStopResizeOptions, PoolResizeParameter,
                                 PoolResizeOptions, JobListOptions, JobListFromJobScheduleOptions,
-                                TaskAddParameter, TaskConstraints, PoolUpdatePropertiesParameter,
-                                StartTask, AffinityInformation)
+                                TaskAddParameter, TaskAddCollectionParameter, TaskConstraints,
+                                PoolUpdatePropertiesParameter, StartTask, AffinityInformation)
 
 from azure.cli.core.commands.client_factory import get_mgmt_service_client
 from azure.cli.core.profiles import get_sdk, ResourceType
@@ -41,13 +41,29 @@ def _decorator(func):
 
 
 # Mgmt custom commands
-
 def list_accounts(client, resource_group_name=None):
     acct_list = client.list_by_resource_group(resource_group_name=resource_group_name) \
         if resource_group_name else client.list()
     return list(acct_list)
 
 
+def get_account(cmd, client, resource_group_name=None, account_name=None):
+    if resource_group_name and account_name:
+        return client.get(resource_group_name, account_name)
+    else:
+        account_endpoint = cmd.cli_ctx.config.get('batch', 'endpoint')
+        if not account_endpoint:
+            raise ValueError(
+                "Missing required arguments. Either specify --resource-group-name and "
+                "--account-name or must be logged into a batch account")
+        account_list = list_accounts(client)
+        for account in account_list:
+            if account.account_endpoint in account_endpoint:
+                return account
+    raise ValueError("Missing required arguments. Either specify --resource-group-name and "
+                     "--account-name or must be logged into a batch account")
+
+
 @transfer_doc(AutoStorageBaseProperties)
 def create_account(client,
                    resource_group_name, account_name, location, tags=None, storage_account=None,
@@ -106,6 +122,8 @@ def login_account(cmd, client, resource_group_name, account_name, shared_key_aut
             profile = Profile(cli_ctx=cmd.cli_ctx)
             creds, subscription, tenant = profile.get_raw_token(resource=resource)
             return {
+                'account': account.name,
+                'endpoint': 'https://{}/'.format(account.account_endpoint),
                 'tokenType': creds[0],
                 'accessToken': creds[1],
                 'expiresOn': creds[2]['expiresOn'],
@@ -272,7 +290,6 @@ def list_job(client, job_schedule_id=None, filter=None,  # pylint: disable=redef
                                                 expand=expand)
         return list(client.list_from_job_schedule(job_schedule_id=job_schedule_id,
                                                   job_list_from_job_schedule_options=option1))
-
     option2 = JobListOptions(filter=filter,
                              select=select,
                              expand=expand)
@@ -291,13 +308,16 @@ def create_task(client,
         json_obj = get_file_json(json_file)
         try:
             task = TaskAddParameter.from_dict(json_obj)
-        except DeserializationError:
-            tasks = []
+        except (DeserializationError, TypeError):
             try:
-                for json_task in json_obj:
-                    tasks.append(TaskAddParameter.from_dict(json_task))
+                task_collection = TaskAddCollectionParameter.from_dict(json_obj)
+                tasks = task_collection.value
             except (DeserializationError, TypeError):
-                raise ValueError("JSON file '{}' is not formatted correctly.".format(json_file))
+                try:
+                    for json_task in json_obj:
+                        tasks.append(TaskAddParameter.from_dict(json_task))
+                except (DeserializationError, TypeError):
+                    raise ValueError("JSON file '{}' is not formatted correctly.".format(json_file))
     else:
         if command_line is None or task_id is None:
             raise ValueError("Missing required arguments.\nEither --json-file, "
diff --git a/src/command_modules/azure-cli-batch/setup.py b/src/command_modules/azure-cli-batch/setup.py
index 0bedd074b43..9288243aeaa 100644
--- a/src/command_modules/azure-cli-batch/setup.py
+++ b/src/command_modules/azure-cli-batch/setup.py
@@ -15,7 +15,7 @@
     logger.warn("Wheel is not available, disabling bdist_wheel hook")
     cmdclass = {}
 
-VERSION = "3.3.3"
+VERSION = "3.3.4"
 # The full list of classifiers is available at
 # https://pypi.python.org/pypi?%3Aaction=list_classifiers
 CLASSIFIERS = [