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 c795e23e998..f3f955d354e 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 @@ -33,7 +33,10 @@ 'return_client_request_id', 'max_results' } -IGNORE_PARAMETERS = {'callback'} +IGNORE_PARAMETERS = [ + 'callback', + 'thumbprint_algorithm' +] FLATTEN_OPTIONS = { # Options to be flattened into multiple arguments. 'ocp_range': {'start_range': "The byte range to be retrieved. " "If not set the file will be retrieved from the beginning.", @@ -53,6 +56,22 @@ 'decimal', 'unix-time' } +QUALIFIED_PROPERTIES = [ # Common argument names the should always be prefixed by their context + 'id', + 'display_name', + 'command_line', + 'environment_settings', + 'run_elevated', + 'wait_for_success', + 'max_task_retry_count', + 'constraints_max_task_retry_count', + 'max_wall_clock_time', + 'constraints_max_wall_clock_time', + 'retention_time', + 'constraints_retention_time', + 'application_package_references', + 'resource_files' +] def _load_model(name): @@ -71,6 +90,22 @@ def _load_model(name): return model +def _join_prefix(prefix, name): + """Filter certain superflous parameter name suffixes + from argument names. + :param str prefix: The potential prefix that will be filtered. + :param str name: The arg name to be prefixed. + :returns: Combined name with prefix. + """ + if prefix.endswith("_specification"): + return prefix[:-14] + "_" + name + elif prefix.endswith("_patch_parameter"): + return prefix[:-16] + "_" + name + elif prefix.endswith("_update_parameter"): + return prefix[:-17] + "_" + name + return prefix + "_" + name + + def _build_prefix(arg, param, path): """Recursively build a command line argument prefix from the request parameter object to avoid name conflicts. @@ -81,11 +116,11 @@ def _build_prefix(arg, param, path): prefix_list = path.split('.') if len(prefix_list) == 1: return arg - resolved_name = prefix_list[0] + "_" + param + resolved_name = _join_prefix(prefix_list[0], param) if arg == resolved_name: return arg for prefix in prefix_list[1:]: - new_name = prefix + "_" + param + new_name = _join_prefix(prefix, param) if new_name == arg: return resolved_name resolved_name = new_name @@ -160,8 +195,14 @@ def group_title(path): :param str path: The complex object path of the argument. :returns: str """ + def filter(group): + for suffix in ["_patch_parameter", "_update_parameter", "_parameter"]: + if group.endswith(suffix): + group = group[:0 - len(suffix)] + return group group_path = path.split('.') - title = ' : '.join(group_path) + group_path = list(map(filter, group_path)) + title = ': '.join(group_path) for group in group_path: title = title.replace(group, " ".join([n.title() for n in group.split('_')]), 1) return title @@ -201,6 +242,26 @@ def __iter__(self): for arg, details in self._arg_tree.items(): yield arg, details + def _is_bool(self, name): + """Whether argument value is a boolean""" + return self._arg_tree[name]['type'] == 'bool' + + def _is_list(self, name): + """Whether argument value is a list""" + return self._arg_tree[name]['type'].startswith('[') + + def _is_datetime(self, name): + """Whether argument value is a timestamp""" + return self._arg_tree[name]['type'] in ['iso-8601', 'rfc-1123'] + + def _is_duration(self, name): + """Whether argument is value is a duration""" + return self._arg_tree[name]['type'] == 'duration' + + def _help(self, name, text): + """Append phrase to existing help text""" + self._arg_tree[name]['options']['help'] += ' ' + text + def _get_children(self, group): """Find all the arguments under to a specific complex argument group. :param str group: The namespace of the complex parameter. @@ -302,16 +363,20 @@ def compile_args(self): objects. """ for name, details in self._arg_tree.items(): - if details['type'] == 'bool': - details['options']['action'] = 'store_true' - details['options']['help'] += \ - ' True if flag present, otherwise default will be used.' - elif details['type'].startswith('['): + if self._is_bool(name): + if self._request_param['name'].endswith('patch_parameter'): + self._help(name, "Specify either 'true' or 'false' to update the property.") + else: + details['options']['action'] = 'store_true' + self._help(name, "True if flag present, otherwise defaults to False.") + elif self._is_list(name): details['options']['nargs'] = '+' - elif details['type'] in ['iso-8601', 'rfc-1123']: + elif self._is_datetime(name): details['options']['type'] = validators.datetime_format - elif details['type'] == 'duration': + self._help(name, "Expected format is an ISO-8601 timestamp.") + elif self._is_duration(name): details['options']['type'] = validators.duration_format + self._help(name, "Expected format is an ISO-8601 duration.") yield (name, CliCommandArgument(dest=name, **details['options'])) def existing(self, name): @@ -409,8 +474,6 @@ def __init__(self, module_name, name, operation, factory, transform_result, # p # The name of the request options parameter self._options_param = format_options_name(operation) - # The name of the group for options arguments - self._options_group = group_title(self._options_param) # Arguments used for request options self._options_attrs = [] # The loaded options model to populate for the request @@ -575,7 +638,7 @@ def _process_options(self): for param in [o for o in self._options_attrs if o not in IGNORE_OPTIONS]: options = {} options['required'] = False - options['arg_group'] = self._options_group + options['arg_group'] = 'Pre-condition and Query' if param in ['if_modified_since', 'if_unmodified_since']: options['type'] = validators.datetime_format if param in FLATTEN_OPTIONS: @@ -610,9 +673,9 @@ def _resolve_conflict(self, arg, param, path, options, typestr, dependencies, co new = _build_prefix(arg, param, path) options['options_list'] = [arg_name(new)] self._resolve_conflict(new, param, path, options, typestr, dependencies, conflicting) - elif arg in conflicting: + elif arg in conflicting or arg in QUALIFIED_PROPERTIES: new = _build_prefix(arg, param, path) - if new in conflicting and '.' not in path: + if new in conflicting or new in QUALIFIED_PROPERTIES and '.' not in path: self.parser.queue_argument(arg, path, param, options, typestr, dependencies) else: options['options_list'] = [arg_name(new)] @@ -691,6 +754,20 @@ def _load_transformed_arguments(self, handler): if arg[0] == self._options_param: for option_arg in self._process_options(): yield option_arg + elif arg_type.startswith("str or"): + docstring = find_param_help(handler, arg[0]) + choices = [] + values_index = docstring.find(' Possible values include') + if values_index >= 0: + choices = docstring[values_index + 25:].split(', ') + choices = [c for c in choices if c != "'unmapped'"] + docstring = docstring[0:values_index] + yield (arg[0], CliCommandArgument(arg[0], + options_list=[arg_name(arg[0])], + required=False, + default=None, + choices=choices, + help=docstring)) elif arg_type.startswith(":class:"): # TODO: could add handling for enums param_type = class_name(arg_type) self.parser.set_request_param(arg[0], param_type) @@ -699,10 +776,9 @@ def _load_transformed_arguments(self, handler): for flattened_arg in self.parser.compile_args(): yield flattened_arg param = 'json_file' - json_class = class_name(arg_type).split('.')[-1] - docstring = "A file containing the {} object in JSON format. " \ - "If this parameter is specified, all {} arguments" \ - " are ignored.".format(json_class, group_title(arg[0])) + docstring = "A file containing the {} specification in JSON format. " \ + "If this parameter is specified, all '{} Arguments'" \ + " are ignored.".format(arg[0].replace('_', ' '), group_title(arg[0])) yield (param, CliCommandArgument(param, options_list=[arg_name(param)], required=False, 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 3c75c9dae3f..0edf798f946 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 @@ -29,7 +29,7 @@ helps['batch account set'] = """ type: command - short-summary: Updates the properties of the specified Batch account. + short-summary: Updates the properties of the specified Batch account. Properties that are not specified remain unchanged. """ helps['batch account autostorage-keys'] = """ @@ -49,7 +49,7 @@ helps['batch application set'] = """ type: command - short-summary: Updates the properties of the specified application. + short-summary: Updates the properties of the specified application. Properties that are not specified remain unchanged. """ helps['batch application package'] = """ @@ -57,6 +57,16 @@ short-summary: Commands to manage your Batch application packages. """ +helps['batch application package create'] = """ + type: command + short-summary: Creates an application package record and attempts to activate it. +""" + +helps['batch application package activate'] = """ + type: command + short-summary: Activates the specified application package. This step is unnecessary if the package has already been successfully activated by the 'create' command. +""" + helps['batch application summary'] = """ type: group short-summary: Commands to view a summary of your Batch application packages. @@ -92,24 +102,29 @@ short-summary: Commands to manage your Batch compute node files. """ +helps['batch node file download'] = """ + type: command + short-summary: Downloads the content of the specified node file. +""" + helps['batch job'] = """ type: group short-summary: Commands to manage your Batch jobs. """ -helps['batch job all-stats'] = """ +helps['batch job all-statistics'] = """ type: group - short-summary: Commands to manage the statistics of all the jobs under your Batch account + short-summary: Commands to view statistics of all the jobs under your Batch account """ -helps['batch job all-stats show'] = """ +helps['batch job all-statistics show'] = """ type: command short-summary: Gets lifetime summary statistics for all of the jobs in the specified account. Statistics are aggregated across all jobs that have ever existed in the account, from account creation to the last update time of the statistics. """ helps['batch job prep-release-status'] = """ type: group - short-summary: Commands to manage the status of your job preparation and release tasks. + short-summary: Commands to view the status of your job preparation and release tasks. """ helps['batch job-schedule'] = """ @@ -127,9 +142,9 @@ short-summary: Adds a user account to the specified compute node. """ -helps['batch node user set'] = """ +helps['batch node user reset'] = """ type: command - short-summary: Updates the properties of a user account on the specified compute node. + short-summary: Updates the properties of a user account on the specified compute node. All updatable properties are replaced with the values specified or reset if unspecified. """ helps['batch node'] = """ @@ -139,17 +154,17 @@ helps['batch node remote-login-settings'] = """ type: group - short-summary: Commands to manage the remote login settings for a Batch compute node. + short-summary: Commands to retrieve the remote login settings for a Batch compute node. """ helps['batch node remote-desktop'] = """ type: group - short-summary: Commands to manage the remote desktop protocol for a Batch compute node. + short-summary: Commands to retrieve the remote desktop protocol for a Batch compute node. """ helps['batch node scheduling'] = """ type: group - short-summary: Commands to manage the scheduling property for a Batch compute node. + short-summary: Commands to manage task scheduling for a Batch compute node. """ helps['batch pool'] = """ @@ -167,24 +182,24 @@ short-summary: Commands to manage automatic scaling of your Batch pools. """ -helps['batch pool all-stats'] = """ +helps['batch pool all-statistics'] = """ type: group - short-summary: Commands to manage statistics of all pools under your Batch account. + short-summary: Commands to view statistics of all pools under your Batch account. """ -helps['batch pool all-stats show'] = """ +helps['batch pool all-statistics show'] = """ type: command short-summary: Gets lifetime summary statistics for all of the pools in the specified account. Statistics are aggregated across all pools that have ever existed in the account, from account creation to the last update time of the statistics. """ helps['batch pool usage-metrics'] = """ type: group - short-summary: Commands to manage usage metrics of your Batch pools. + short-summary: Commands to view usage metrics of your Batch pools. """ helps['batch pool node-agent-skus'] = """ type: group - short-summary: Commands to manage node agent skus of pools using a Virtual Machine Configuration. + short-summary: Commands to retrieve node agent SKUs of pools using a Virtual Machine Configuration. """ helps['batch task'] = """ @@ -199,32 +214,32 @@ helps['batch certificate create'] = """ type: command - short-summary: Add a certificate. + short-summary: Adds a certificate. """ helps['batch certificate delete'] = """ type: command - short-summary: Delete the specified Batch certificate. + short-summary: Deletes the specified Batch certificate. """ helps['batch pool create'] = """ type: command - short-summary: Create a Batch pool. + short-summary: Creates a pool in the specified account. When creating a pool, please chose arguments from either Cloud Services Configuration or Virtual Machine Configuration. """ helps['batch pool set'] = """ type: command - short-summary: Updates the properties of the specified pool. Properties that are not specified remain unchanged. + short-summary: Updates the properties of the specified pool. Properties can be updated independently, but please note that an updated property in a sub-group (i.e. 'start task') will result in all properties of that group being reset. """ helps['batch pool reset'] = """ type: command - short-summary: Updates the properties of the specified pool. All updatable properties are replaced with the values specified or cleared if unspecified. + short-summary: Updates the properties of the specified pool. All updatable properties are replaced with the values specified or cleared/defaulted if unspecified. """ helps['batch pool resize'] = """ type: command - short-summary: Resize (or stop resizing) the Batch pool. + short-summary: Resizes (or stops resizing) the Batch pool. """ helps['batch job create'] = """ @@ -239,12 +254,12 @@ helps['batch job set'] = """ type: command - short-summary: Patch the properties of a job. + short-summary: Updates the properties of a job. Properties can be updated independently, but please note that an updated property in a sub-group (i.e. 'constraints' and 'pool info') will result in all properties of that group being reset. """ helps['batch job reset'] = """ type: command - short-summary: Update the properties of a job. + short-summary: Updates the properties of a job. All updatable properties are replaced with the values specified or cleared/defaulted if unspecified. """ helps['batch job-schedule create'] = """ @@ -254,15 +269,20 @@ helps['batch job-schedule set'] = """ type: command - short-summary: Patch the properties of the specified job schedule. + short-summary: Updates the properties of the specified job schedule. You can independently update the 'schedule' and/or the 'job specification', but note that any change to either of these entities will reset all properties in that entity. """ helps['batch job-schedule reset'] = """ type: command - short-summary: Update the properties of the specified job schedule. + short-summary: Updates the properties of the specified job schedule. All updatable properties are replaced with the values specified or cleared if unspecified. An updated job-specification will only apply to new jobs. """ helps['batch task create'] = """ type: command - short-summary: Create a single Batch task or multiple Batch tasks. + short-summary: Creates a single Batch task or multiple Batch tasks. +""" + +helps['batch task reset'] = """ + type: command + short-summary: Updates the properties of the specified task. All updatable properties are replaced with the values specified or reset if unspecified. """ 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 417fab5270c..a1256e4495d 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 @@ -6,6 +6,8 @@ from argcomplete.completers import FilesCompleter from azure.mgmt.batch.models.batch_management_client_enums import \ (AccountKeyType) +from azure.batch.models.batch_service_client_enums import \ + (ComputeNodeDeallocationOption) from azure.cli.core.commands import \ (register_cli_argument, CliArgumentType, register_extra_cli_argument) @@ -16,7 +18,8 @@ from azure.cli.command_modules.batch._validators import \ (application_enabled, datetime_format, storage_account_id, application_package_reference_format, validate_client_parameters, validate_pool_resize_parameters, metadata_item_format, - certificate_reference_format, validate_json_file, validate_cert_file) + certificate_reference_format, validate_json_file, validate_cert_file, + environment_setting_format, validate_cert_settings, resource_file_format) # pylint: disable=line-too-long # ARGUMENT DEFINITIONS @@ -29,13 +32,13 @@ register_cli_argument('batch account', 'account_name', batch_name_type, options_list=('--name', '-n')) register_cli_argument('batch account create', 'location', location_type, help='The region in which to create the account.') register_cli_argument('batch account create', 'tags', tags_type, help="Space separated tags in 'key[=value]' format.") -register_extra_cli_argument('batch account create', 'storage_account', help='The storage account name or resource id to be used for auto storage.', validator=storage_account_id) +register_extra_cli_argument('batch account create', 'storage_account', help='The storage account name or resource ID to be used for auto storage.', validator=storage_account_id) register_cli_argument('batch account set', 'tags', tags_type) -register_extra_cli_argument('batch account set', 'storage_account', help='The storage account name or resource id to be used for auto storage.', validator=storage_account_id) +register_extra_cli_argument('batch account set', 'storage_account', help='The storage account name or resource ID to be used for auto storage.', validator=storage_account_id) register_cli_argument('batch account keys renew', 'key_name', **enum_choice_list(AccountKeyType)) register_cli_argument('batch application set', 'application_id', options_list=('--application-id',), help="The ID of the application.") -register_cli_argument('batch application set', 'allow_updates', options_list=('--allow-updates',), action="store_true", help="A value indicating whether packages within the application may be overwritten using the same version string. True if flag present.") -register_cli_argument('batch application create', 'allow_updates', options_list=('--allow-updates',), action="store_true", help="A value indicating whether packages within the application may be overwritten using the same version string. True if flag present.") +register_cli_argument('batch application set', 'allow_updates', options_list=('--allow-updates',), help="Specify to indicate whether packages within the application may be overwritten using the same version string. Specify either 'true' or 'false' to update the property.") +register_cli_argument('batch application create', 'allow_updates', options_list=('--allow-updates',), action="store_true", help="Specify to indicate whether packages within the application may be overwritten using the same version string. True if flag present.") register_cli_argument('batch application package create', 'package_file', type=file_type, help='The path of the application package in zip format', completer=FilesCompleter()) register_cli_argument('batch application package create', 'application_id', options_list=('--application-id',), help="The ID of the application.") register_cli_argument('batch application package create', 'version', options_list=('--version',), help="The version of the application.") @@ -44,34 +47,53 @@ for command in ['list', 'show', 'create', 'set', 'delete', 'package']: register_cli_argument('batch application {}'.format(command), 'account_name', batch_name_type, options_list=('--name', '-n'), validator=application_enabled) -register_cli_argument('batch pool resize', 'if_modified_since', help='The operation will be performed only if the resource has been modified since the specified timestamp.', type=datetime_format, arg_group='Pre-condition') -register_cli_argument('batch pool resize', 'if_unmodified_since', help='The operation will not be performed only if the resource has been modified since the specified timestamp.', type=datetime_format, arg_group='Pre-condition') -register_cli_argument('batch pool resize', 'if_match', help='The operation will be performed only if the resource\'s current ETag exactly matches the specified value.', arg_group='Pre-condition') -register_cli_argument('batch pool resize', 'if_none_match', help='The operation will not be performed only if the resource\'s current ETag exactly matches the specified value.', arg_group='Pre-condition') +# TODO: Refactor so the help text can be extracted automatically +register_cli_argument('batch pool resize', 'if_modified_since', help='The operation will be performed only if the resource has been modified since the specified timestamp.', type=datetime_format, arg_group='Pre-condition and Query') +register_cli_argument('batch pool resize', 'if_unmodified_since', help='The operation will not be performed only if the resource has been modified since the specified timestamp.', type=datetime_format, arg_group='Pre-condition and Query') +register_cli_argument('batch pool resize', 'if_match', help='The operation will be performed only if the resource\'s current ETag exactly matches the specified value.', arg_group='Pre-condition and Query') +register_cli_argument('batch pool resize', 'if_none_match', help='The operation will not be performed only if the resource\'s current ETag exactly matches the specified value.', arg_group='Pre-condition and Query') register_cli_argument('batch pool resize', 'pool_id', help='The ID of the pool.') register_cli_argument('batch pool resize', 'abort', action='store_true', help='Stop the pool resize operation.', validator=validate_pool_resize_parameters) +register_cli_argument('batch pool resize', 'node_deallocation_option', options_list=('--node-deallocation-option',), help='When nodes may be removed from the pool, if the pool size is decreasing.', **enum_choice_list(ComputeNodeDeallocationOption)) -register_cli_argument('batch pool reset', 'json_file', type=file_type, help='The file containing PoolUpdatePropertiesParameter object in JSON format, if this parameter is specified, all other parameters are ignored.', validator=validate_json_file, completer=FilesCompleter()) -register_cli_argument('batch pool reset', 'pool_id', help='The ID of the pool to be updated.') -register_cli_argument('batch pool reset', 'application_package_references', nargs='+', type=application_package_reference_format) -register_cli_argument('batch pool reset', 'certificate_references', nargs='+', type=certificate_reference_format) -register_cli_argument('batch pool reset', 'metadata', nargs='+', type=metadata_item_format) +# TODO: Refactor so the help text can be extracted automatically +register_cli_argument('batch pool reset', '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()) +register_cli_argument('batch pool reset', 'pool_id', help='The ID of the pool to update.') +register_cli_argument('batch pool reset', 'application_package_references', nargs='+', type=application_package_reference_format, arg_group='Pool') +register_cli_argument('batch pool reset', 'certificate_references', nargs='+', type=certificate_reference_format, arg_group='Pool') +register_cli_argument('batch pool reset', 'metadata', nargs='+', type=metadata_item_format, arg_group='Pool') +register_cli_argument('batch pool reset', 'start_task_command_line', arg_group='Pool: Start Task', + help='The command line of the start task. The command line does not run under a shell, and therefore cannot take advantage of shell features such as environment variable expansion. If you want to take advantage of such features, you should invoke the shell in the command line, for example using "cmd /c MyCommand" in Windows or "/bin/sh -c MyCommand" in Linux.') +register_cli_argument('batch pool reset', 'start_task_run_elevated', action='store_true', arg_group='Pool: Start Task', + help='Whether to run the start task in elevated mode. The default value is false. True if flag present, otherwise defaults to False.') +register_cli_argument('batch pool reset', 'start_task_wait_for_success', action='store_true', arg_group='Pool: Start Task', + help='Whether the Batch service should wait for the start task to complete successfully (that is, to exit with exit code 0) before scheduling any tasks on the compute node. True if flag present, otherwise defaults to False.') +register_cli_argument('batch pool reset', 'start_task_max_task_retry_count', arg_group='Pool: Start Task', + help='The maximum number of times the task may be retried.') +register_cli_argument('batch pool reset', 'start_task_environment_settings', nargs='+', type=environment_setting_format, arg_group='Pool: Start Task', + help='A list of environment variable settings for the start task. Space separated values in \'key=value\' format.') -register_cli_argument('batch job list', 'filter', help=' An OData $filter clause.', arg_group='OData') -register_cli_argument('batch job list', 'select', help=' An OData $select clause.', arg_group='OData') -register_cli_argument('batch job list', 'expand', help=' An OData $expand clause.', arg_group='OData') -register_cli_argument('batch job list', 'job_schedule_id', help='The ID of the job schedule from which you want to get a list of jobs.') +register_cli_argument('batch job list', 'filter', help=' An OData $filter clause.', arg_group='Pre-condition and Query') +register_cli_argument('batch job list', 'select', help=' An OData $select clause.', arg_group='Pre-condition and Query') +register_cli_argument('batch job list', 'expand', help=' An OData $expand clause.', arg_group='Pre-condition and Query') +register_cli_argument('batch job list', 'job_schedule_id', help='The ID of the job schedule from which you want to get a list of jobs. If omitted, lists all jobs in the account.') +for command in ['job create', 'job set', 'job reset', 'job-schedule create', 'job-schedule set', 'job-schedule reset']: + register_cli_argument('batch {}'.format(command), 'pool_id', options_list=('--pool-id',), help='The id of an existing pool. All the tasks of the job will run on the specified pool.') register_cli_argument('batch certificate', 'thumbprint', help='The certificate thumbprint.') -register_cli_argument('batch certificate', 'thumbprint_algorithm', help='The certificate thumbprint algorithm.') +register_cli_argument('batch certificate show', 'thumbprint', help='The certificate thumbprint.', validator=validate_cert_settings) register_cli_argument('batch certificate', 'password', help='The password to access the certificate\'s private key.') -register_cli_argument('batch certificate', 'cert_file', type=file_type, help='The certificate file: cer file or pfx file.', validator=validate_cert_file, completer=FilesCompleter()) +register_cli_argument('batch certificate', 'file', type=file_type, help='The certificate file: cer file or pfx file.', validator=validate_cert_file, completer=FilesCompleter()) register_cli_argument('batch certificate delete', 'abort', action='store_true', help='Cancel the failed certificate deletion operation.') register_cli_argument('batch task create', '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()) -register_cli_argument('batch task create', 'application_package_references', nargs='+', help='The space separated list of ids specifying the application packages to be installed.', type=application_package_reference_format) +register_cli_argument('batch task create', '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) register_cli_argument('batch task create', 'job_id', help='The ID of the job containing the task.') register_cli_argument('batch task create', 'task_id', help='The ID of the task.') +register_cli_argument('batch task create', 'command_line', help='The command line of the task. The command line does not run under a shell, and therefore cannot take advantage of shell features such as environment variable expansion. If you want to take advantage of such features, you should invoke the shell in the command line, for example using "cmd /c MyCommand" in Windows or "/bin/sh -c MyCommand" in Linux.') +register_cli_argument('batch task create', 'environment_settings', nargs='+', help='A list of environment variable settings for the task. Space separated values in \'key=value\' format.', type=environment_setting_format) +register_cli_argument('batch task create', 'run_elevated', action='store_true', help='Whether to run the task in elevated mode. True if flag present, otherwise defaults to False.') +register_cli_argument('batch task create', 'resource_files', nargs='+', help='A list of files that the Batch service will download to the compute node before running the command line. Space separated resource references in filename=blobsource format.', type=resource_file_format) for item in ['batch certificate delete', 'batch certificate create', 'batch pool resize', 'batch pool reset', 'batch job list', 'batch task create']: register_extra_cli_argument(item, 'account_name', arg_group='Batch Account', diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_validators.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_validators.py index de2b5bd3af2..716e2d0396b 100644 --- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_validators.py +++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/_validators.py @@ -77,6 +77,30 @@ def certificate_reference_format(value): return cert +def task_id_ranges_format(value): + """Space separated number ranges in 'start-end' format.""" + try: + start, end = [int(i) for i in value.split('-')] + except ValueError: + message = ("Incorrectly formatted task ID range. " + "Argmuent values should be numbers in the format 'start-end'") + raise ValueError(message) + else: + return {'start': start, 'end': end} + + +def resource_file_format(value): + """Space separated resource references in filename=blobsource format.""" + try: + file_name, blob_source = value.split('=') + except ValueError: + message = ("Incorrectly formatted resource reference. " + "Argmuent values should be in the format filename=blobsource") + raise ValueError(message) + else: + return {'file_path': file_name, 'blob_source': blob_source} + + # COMMAND NAMESPACE VALIDATORS def validate_required_parameter(ns, parser): @@ -138,10 +162,10 @@ def validate_json_file(namespace): def validate_cert_file(namespace): """Validate the give cert file existing""" try: - with open(namespace.cert_file, "rb"): + with open(namespace.file, "rb"): pass except EnvironmentError: - raise ValueError("Cannot access certificate file: " + namespace.cert_file) + raise ValueError("Cannot access certificate file: " + namespace.file) def validate_options(namespace): @@ -236,3 +260,10 @@ def validate_pool_settings(ns, parser): "Please swap for the equivalent: Standard_A1 (small), Standard_A2 " "(medium), Standard_A3 (large), or Standard_A4 (extra large).") raise ValueError(message) + + +def validate_cert_settings(ns): + """Custom parsing for certificate commands - adds default thumbprint + algorithm. + """ + ns.thumbprint_algorithm = 'sha1' 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 b179b1cb158..89a8b9fffc8 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 @@ -6,7 +6,7 @@ from azure.cli.core.commands import cli_command from azure.cli.command_modules.batch._command_type import cli_batch_data_plane_command -from azure.cli.command_modules.batch._validators import validate_pool_settings +from azure.cli.command_modules.batch._validators import validate_pool_settings, validate_cert_settings from azure.cli.command_modules.batch._client_factory import ( account_mgmt_client_factory, account_client_factory, @@ -43,10 +43,10 @@ cli_command(__name__, 'batch application show', mgmt_path.format('application', 'ApplicationOperations.get'), application_mgmt_client_factory) cli_command(__name__, 'batch application create', mgmt_path.format('application', 'ApplicationOperations.create'), application_mgmt_client_factory) cli_command(__name__, 'batch application set', custom_path.format('update_application'), application_mgmt_client_factory) -cli_command(__name__, 'batch application delete', mgmt_path.format('application', 'ApplicationOperations.delete'), application_mgmt_client_factory) +cli_command(__name__, 'batch application delete', mgmt_path.format('application', 'ApplicationOperations.delete'), application_mgmt_client_factory, confirmation=True) cli_command(__name__, 'batch application package create', custom_path.format('create_application_package'), application_package_client_factory) -cli_command(__name__, 'batch application package delete', mgmt_path.format('application_package', 'ApplicationPackageOperations.delete'), application_package_client_factory) +cli_command(__name__, 'batch application package delete', mgmt_path.format('application_package', 'ApplicationPackageOperations.delete'), application_package_client_factory, confirmation=True) cli_command(__name__, 'batch application package show', mgmt_path.format('application_package', 'ApplicationPackageOperations.get'), application_package_client_factory) cli_command(__name__, 'batch application package activate', mgmt_path.format('application_package', 'ApplicationPackageOperations.activate'), application_package_client_factory) @@ -61,12 +61,14 @@ cli_command(__name__, 'batch certificate create', custom_path.format('create_certificate'), certificate_client_factory) cli_command(__name__, 'batch certificate delete', custom_path.format('delete_certificate'), certificate_client_factory, confirmation=True) -cli_batch_data_plane_command('batch certificate show', data_path.format('certificate', 'CertificateOperations.get'), certificate_client_factory) +cli_batch_data_plane_command('batch certificate show', data_path.format('certificate', 'CertificateOperations.get'), certificate_client_factory, validator=validate_cert_settings) cli_batch_data_plane_command('batch certificate list', data_path.format('certificate', 'CertificateOperations.list'), certificate_client_factory) cli_batch_data_plane_command('batch pool usage-metrics list', data_path.format('pool', 'PoolOperations.list_pool_usage_metrics'), pool_client_factory) -cli_batch_data_plane_command('batch pool all-stats show', data_path.format('pool', 'PoolOperations.get_all_pools_lifetime_statistics'), pool_client_factory) -cli_batch_data_plane_command('batch pool create', data_path.format('pool', 'PoolOperations.add'), pool_client_factory, validator=validate_pool_settings, ignore=['pool.cloud_service_configuration.current_os_version']) +cli_batch_data_plane_command('batch pool all-statistics show', data_path.format('pool', 'PoolOperations.get_all_pools_lifetime_statistics'), pool_client_factory) +cli_batch_data_plane_command('batch pool create', data_path.format('pool', 'PoolOperations.add'), pool_client_factory, + validator=validate_pool_settings, + ignore=['pool.cloud_service_configuration.current_os_version', 'pool.virtual_machine_configuration.windows_configuration']) cli_batch_data_plane_command('batch pool list', data_path.format('pool', 'PoolOperations.list'), pool_client_factory) cli_batch_data_plane_command('batch pool delete', data_path.format('pool', 'PoolOperations.delete'), pool_client_factory) cli_batch_data_plane_command('batch pool show', data_path.format('pool', 'PoolOperations.get'), pool_client_factory) @@ -79,23 +81,42 @@ cli_batch_data_plane_command('batch pool os upgrade', data_path.format('pool', 'PoolOperations.upgrade_os'), pool_client_factory) cli_batch_data_plane_command('batch node delete', data_path.format('pool', 'PoolOperations.remove_nodes'), pool_client_factory) -cli_batch_data_plane_command('batch job all-stats show', data_path.format('job', 'JobOperations.get_all_jobs_lifetime_statistics'), job_client_factory) -cli_batch_data_plane_command('batch job create', data_path.format('job', 'JobOperations.add'), job_client_factory) +cli_batch_data_plane_command('batch job all-statistics show', data_path.format('job', 'JobOperations.get_all_jobs_lifetime_statistics'), job_client_factory) +cli_batch_data_plane_command('batch job create', data_path.format('job', 'JobOperations.add'), job_client_factory, + ignore=['job.job_preparation_task', 'job.job_release_task', 'job.pool_info.auto_pool_specification', + 'job.job_manager_task.kill_job_on_completion', + 'job.job_manager_task.run_exclusive']) cli_batch_data_plane_command('batch job delete', data_path.format('job', 'JobOperations.delete'), job_client_factory) cli_batch_data_plane_command('batch job show', data_path.format('job', 'JobOperations.get'), job_client_factory) -cli_batch_data_plane_command('batch job set', data_path.format('job', 'JobOperations.patch'), job_client_factory) -cli_batch_data_plane_command('batch job reset', data_path.format('job', 'JobOperations.update'), job_client_factory) +cli_batch_data_plane_command('batch job set', data_path.format('job', 'JobOperations.patch'), job_client_factory, flatten=2) +cli_batch_data_plane_command('batch job reset', data_path.format('job', 'JobOperations.update'), job_client_factory, flatten=2) cli_command(__name__, 'batch job list', custom_path.format('list_job'), job_client_factory) cli_batch_data_plane_command('batch job disable', data_path.format('job', 'JobOperations.disable'), job_client_factory) cli_batch_data_plane_command('batch job enable', data_path.format('job', 'JobOperations.enable'), job_client_factory) cli_batch_data_plane_command('batch job stop', data_path.format('job', 'JobOperations.terminate'), job_client_factory) cli_batch_data_plane_command('batch job prep-release-status list', data_path.format('job', 'JobOperations.list_preparation_and_release_task_status'), job_client_factory) -cli_batch_data_plane_command('batch job-schedule create', data_path.format('job_schedule', 'JobScheduleOperations.add'), job_schedule_client_factory) +cli_batch_data_plane_command('batch job-schedule create', data_path.format('job_schedule', 'JobScheduleOperations.add'), job_schedule_client_factory, + ignore=['cloud_job_schedule.job_specification.job_preparation_task', + 'cloud_job_schedule.job_specification.job_release_task', + 'cloud_job_schedule.job_specification.job_manager_task.kill_job_on_completion', + 'cloud_job_schedule.job_specification.job_manager_task.run_exclusive']) cli_batch_data_plane_command('batch job-schedule delete', data_path.format('job_schedule', 'JobScheduleOperations.delete'), job_schedule_client_factory) cli_batch_data_plane_command('batch job-schedule show', data_path.format('job_schedule', 'JobScheduleOperations.get'), job_schedule_client_factory) -cli_batch_data_plane_command('batch job-schedule set', data_path.format('job_schedule', 'JobScheduleOperations.patch'), job_schedule_client_factory) -cli_batch_data_plane_command('batch job-schedule reset', data_path.format('job_schedule', 'JobScheduleOperations.update'), job_schedule_client_factory) +cli_batch_data_plane_command('batch job-schedule set', data_path.format('job_schedule', 'JobScheduleOperations.patch'), job_schedule_client_factory, + ignore=['job_schedule_patch_parameter.job_specification.job_preparation_task', + 'job_schedule_patch_parameter.job_specification.job_release_task', + 'job_schedule_patch_parameter.job_specification.constraints', + 'job_schedule_patch_parameter.job_specification.job_manager_task.kill_job_on_completion', + 'job_schedule_patch_parameter.job_specification.job_manager_task.run_exclusive', + 'job_schedule_patch_parameter.job_specification.job_manager_task.constraints']) +cli_batch_data_plane_command('batch job-schedule reset', data_path.format('job_schedule', 'JobScheduleOperations.update'), job_schedule_client_factory, + ignore=['job_schedule_update_parameter.job_specification.job_preparation_task', + 'job_schedule_update_parameter.job_specification.job_release_task', + 'job_schedule_update_parameter.job_specification.constraints', + 'job_schedule_update_parameter.job_specification.job_manager_task.kill_job_on_completion', + 'job_schedule_update_parameter.job_specification.job_manager_task.run_exclusive', + 'job_schedule_update_parameter.job_specification.job_manager_task.constraints']) cli_batch_data_plane_command('batch job-schedule disable', data_path.format('job_schedule', 'JobScheduleOperations.disable'), job_schedule_client_factory) cli_batch_data_plane_command('batch job-schedule enable', data_path.format('job_schedule', 'JobScheduleOperations.enable'), job_schedule_client_factory) cli_batch_data_plane_command('batch job-schedule stop', data_path.format('job_schedule', 'JobScheduleOperations.terminate'), job_schedule_client_factory) @@ -117,7 +138,7 @@ cli_batch_data_plane_command('batch node user create', data_path.format('compute_node', 'ComputeNodeOperations.add_user'), compute_node_client_factory) cli_batch_data_plane_command('batch node user delete', data_path.format('compute_node', 'ComputeNodeOperations.delete_user'), compute_node_client_factory) -cli_batch_data_plane_command('batch node user set', data_path.format('compute_node', 'ComputeNodeOperations.update_user'), compute_node_client_factory) +cli_batch_data_plane_command('batch node user reset', data_path.format('compute_node', 'ComputeNodeOperations.update_user'), compute_node_client_factory) cli_batch_data_plane_command('batch node show', data_path.format('compute_node', 'ComputeNodeOperations.get'), compute_node_client_factory) cli_batch_data_plane_command('batch node list', data_path.format('compute_node', 'ComputeNodeOperations.list'), compute_node_client_factory) cli_batch_data_plane_command('batch node reboot', data_path.format('compute_node', 'ComputeNodeOperations.reboot'), compute_node_client_factory) 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 83a87ce5858..2566b3d51d7 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 @@ -148,13 +148,15 @@ def _handle_batch_exception(action): @transfer_doc(CertificateAddParameter) -def create_certificate(client, cert_file, thumbprint, thumbprint_algorithm, password=None): +def create_certificate(client, file, thumbprint, password=None): + thumbprint_algorithm = 'sha1' + def action(): client.add(cert) return client.get(thumbprint_algorithm, thumbprint) certificate_format = 'pfx' if password else 'cer' - with open(cert_file, "rb") as f: + with open(file, "rb") as f: data_bytes = f.read() data = base64.b64encode(data_bytes).decode('utf-8') cert = CertificateAddParameter(thumbprint, thumbprint_algorithm, data, @@ -163,7 +165,9 @@ def action(): return _handle_batch_exception(action) -def delete_certificate(client, thumbprint, thumbprint_algorithm, abort=False): +def delete_certificate(client, thumbprint, abort=False): + thumbprint_algorithm = 'sha1' + def action(): if abort: client.cancel_deletion(thumbprint_algorithm, thumbprint) @@ -199,8 +203,10 @@ def action(): @transfer_doc(PoolUpdatePropertiesParameter, StartTask) -def update_pool(client, pool_id, json_file=None, command_line=None, # pylint:disable=too-many-arguments - certificate_references=None, application_package_references=None, metadata=None): +def update_pool(client, pool_id, json_file=None, start_task_command_line=None, # pylint:disable=too-many-arguments + certificate_references=None, application_package_references=None, metadata=None, + start_task_run_elevated=None, start_task_environment_settings=None, start_task_wait_for_success=None, + start_task_max_task_retry_count=None): def action(): client.update_properties(pool_id=pool_id, pool_update_properties_parameter=param) return client.get(pool_id) @@ -233,8 +239,12 @@ def action(): application_package_references, metadata) - if command_line: - param.start_task = StartTask(command_line) + if start_task_command_line: + param.start_task = StartTask(start_task_command_line, + environment_settings=start_task_environment_settings, + run_elevated=start_task_run_elevated, + wait_for_success=start_task_wait_for_success, + max_task_retry_count=start_task_max_task_retry_count) return _handle_batch_exception(action) diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_commands.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_commands.py index e46a7498ece..a145858222a 100644 --- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_commands.py +++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_commands.py @@ -75,6 +75,35 @@ def test_batch_certificate_reference_format(self): self.assertEqual(cert, {'thumbprint': 'thumbprint_lkjsahakjg', 'thumbprint_algorithm': 'sha1'}) + def test_batch_task_id_ranges_format(self): + id_range = _validators.task_id_ranges_format("5-10") + self.assertEqual(id_range, {'start': 5, 'end': 10}) + + with self.assertRaises(ValueError): + _validators.task_id_ranges_format("5") + + with self.assertRaises(ValueError): + _validators.task_id_ranges_format("test") + + with self.assertRaises(ValueError): + _validators.environment_setting_format("5-") + + with self.assertRaises(ValueError): + _validators.environment_setting_format("5-test") + + with self.assertRaises(ValueError): + _validators.environment_setting_format("start-end") + + def test_batch_resource_file_format(self): + meta = _validators.resource_file_format("file=source") + self.assertEqual(meta, {'file_path': 'file', 'blob_source': 'source'}) + + with self.assertRaises(ValueError): + _validators.resource_file_format("file") + + with self.assertRaises(ValueError): + _validators.resource_file_format("file=source=mode") + def test_batch_validate_options(self): ns = TestObj() _validators.validate_options(ns) @@ -136,6 +165,9 @@ def test_batch_build_prefix(self): resolved = _command_type._build_prefix('id', 'id', 'pool.start_task') self.assertEqual(resolved, 'start_task_id') + resolved = _command_type._build_prefix('id', 'id', 'job_schedule.job_specification') + self.assertEqual(resolved, 'job_id') + resolved = _command_type._build_prefix('properties_id', 'id', 'pool.start_task.properties') self.assertEqual(resolved, 'start_task_id') @@ -255,11 +287,20 @@ def test_batch_group_title(self): path = "pool" self.assertEqual(_command_type.group_title(path), "Pool") + path = "pool_patch_parameter" + self.assertEqual(_command_type.group_title(path), "Pool") + + path = "pool_update_parameter" + self.assertEqual(_command_type.group_title(path), "Pool") + + path = "pool_update_properties_parameter" + self.assertEqual(_command_type.group_title(path), "Pool Update Properties") + path = "pool.start_task" - self.assertEqual(_command_type.group_title(path), "Pool : Start Task") + self.assertEqual(_command_type.group_title(path), "Pool: Start Task") path = "pool.start_task.constraints" - self.assertEqual(_command_type.group_title(path), "Pool : Start Task : Constraints") + self.assertEqual(_command_type.group_title(path), "Pool: Start Task: Constraints") def test_batch_arg_name(self): self.assertEqual(_command_type.arg_name("pool_id"), "--pool-id") @@ -537,12 +578,12 @@ def test_batch_load_arguments(self): # pylint: disable=too-many-statements handler = operations.pool_operations.PoolOperations.add args = list(self.command_pool._load_transformed_arguments(handler)) - self.assertEqual(len(args), 30) + self.assertEqual(len(args), 31) self.assertFalse('force' in [a for a, _ in args]) self.assertTrue('json_file' in [a for a, _ in args]) self.assertFalse('destination' in [a for a, _ in args]) self.assertTrue('application_package_references' in [a for a, _ in args]) - self.assertTrue('environment_settings' in [a for a, _ in args]) + self.assertTrue('start_task_environment_settings' in [a for a, _ in args]) self.assertTrue('certificate_references' in [a for a, _ in args]) self.assertTrue('metadata' in [a for a, _ in args]) handler = operations.job_operations.JobOperations.add @@ -553,7 +594,7 @@ def test_batch_load_arguments(self): self.assertFalse('destination' in [a for a, _ in args]) handler = operations.task_operations.TaskOperations.add args = list(self.command_task._load_transformed_arguments(handler)) - self.assertEqual(len(args), 8) + self.assertEqual(len(args), 9) self.assertFalse('force' in [a for a, _ in args]) self.assertTrue('json_file' in [a for a, _ in args]) self.assertFalse('destination' in [a for a, _ in args]) @@ -577,15 +618,11 @@ def test_batch_load_arguments(self): self.assertFalse('destination' in [a for a, _ in args]) handler = operations.job_schedule_operations.JobScheduleOperations.add args = list(self.command_conflicts._load_transformed_arguments(handler)) - self.assertEqual(len(args), 45) + self.assertEqual(len(args), 48) self.assertTrue('id' in [a for a, _ in args]) self.assertTrue('job_manager_task_id' in [a for a, _ in args]) - self.assertTrue('job_preparation_task_id' in [a for a, _ in args]) - self.assertTrue('job_release_task_id' in [a for a, _ in args]) self.assertTrue('job_manager_task_max_wall_clock_time' in [a for a, _ in args]) - self.assertTrue('job_preparation_task_max_wall_clock_time' in [a for a, _ in args]) - self.assertTrue('job_release_task_max_wall_clock_time' in [a for a, _ in args]) - self.assertTrue('job_specification_max_wall_clock_time' in [a for a, _ in args]) + self.assertTrue('job_max_wall_clock_time' in [a for a, _ in args]) self.assertFalse('force' in [a for a, _ in args]) self.assertTrue('json_file' in [a for a, _ in args]) self.assertFalse('destination' in [a for a, _ in args]) diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_data_plane_commands.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_data_plane_commands.py index e84270ca99f..5f9cf7f1532 100644 --- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_data_plane_commands.py +++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_data_plane_commands.py @@ -24,8 +24,7 @@ def test_batch_certificate_cmd(self): def body(self): # test create certificate with default set - self.cmd('batch certificate create --thumbprint {} ' - '--thumbprint-algorithm sha1 --cert-file "{}"'. + self.cmd('batch certificate create --thumbprint {} --file "{}"'. format(self.cert_thumbprint, self.create_cert_file_path), checks=[ JMESPathCheck('thumbprint', self.cert_thumbprint), @@ -39,10 +38,10 @@ def body(self): JMESPathCheck('[0].thumbprint', self.cert_thumbprint), ]) - self.cmd("batch certificate delete --thumbprint {} --thumbprint-algorithm sha1 --force". + self.cmd("batch certificate delete --thumbprint {} --force". format(self.cert_thumbprint)) - self.cmd('batch certificate show --thumbprint {} --thumbprint-algorithm sha1'. + self.cmd('batch certificate show --thumbprint {}'. format(self.cert_thumbprint), checks=[ JMESPathCheck('thumbprint', self.cert_thumbprint), @@ -105,7 +104,7 @@ def body(self): JMESPathCheck('id', self.create_pool_id), JMESPathCheck('startTask.commandLine', "cmd /c echo updated")]) - self.cmd('batch pool reset --pool-id {} --command-line hostname --metadata a=b c=d'. + self.cmd('batch pool reset --pool-id {} --start-task-command-line hostname --metadata a=b c=d'. format(self.create_pool_id), checks=[JMESPathCheck('allocationState', 'steady'), JMESPathCheck('id', self.create_pool_id), diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_mgmt_commands.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_mgmt_commands.py index 933bd908d6d..81e1c8bbda3 100644 --- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_mgmt_commands.py +++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_mgmt_commands.py @@ -180,7 +180,8 @@ def body(self): JMESPathCheck('packages[0].state', 'active')]) # test batch applcation delete - self.cmd('batch application package delete -g {} -n {} --application-id {} --version {}'. + self.cmd('batch application package delete -g {} -n {} --application-id {} --version {} --force'. # pylint: disable=line-too-long format(rg, name, aname, ver)) - self.cmd('batch application delete -g {} -n {} --application-id {}'.format(rg, name, aname)) + self.cmd('batch application delete -g {} -n {} --application-id {} --force'. + format(rg, name, aname)) self.cmd('batch application list -g {} -n {}'.format(rg, name), checks=NoneCheck()) diff --git a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_pool_commands.py b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_pool_commands.py index 8e4153b8b52..1649b1c11eb 100644 --- a/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_pool_commands.py +++ b/src/command_modules/azure-cli-batch/azure/cli/command_modules/batch/tests/test_batch_pool_commands.py @@ -151,7 +151,7 @@ def body(self): # test patch pool using parameters current = self.cmd('batch pool show --pool-id {} --select "startTask"'.format( self.pool_json)) - self.cmd('batch pool set --pool-id {} --command-line new_value'.format( + self.cmd('batch pool set --pool-id {} --start-task-command-line new_value'.format( self.pool_json)) updated = self.cmd('batch pool show --pool-id {} --select "startTask"'.format( self.pool_json))