@@ -10947,3 +10947,94 @@ def _compute_checksum(input_bytes):
1094710947 logger.info("Computing the checksum of the file failed with exception:'%s'", ex)
1094810948
1094910949 return file_hash
10950+
10951+
10952+ def _execute_command_on_instance(scm_url, headers, cookies, command, working_directory=None):
10953+ from azure.cli.core.util import should_disable_connection_verify
10954+ import requests
10955+
10956+ # Build the exec endpoint URL
10957+ exec_url = f"{scm_url}/exec/execute"
10958+
10959+ # Build request body
10960+ body = {"Command": command}
10961+ if working_directory:
10962+ body["WorkingDirectory"] = working_directory
10963+
10964+ # Make the request
10965+ response = requests.post(
10966+ exec_url,
10967+ json=body,
10968+ headers=headers,
10969+ cookies=cookies,
10970+ verify=not should_disable_connection_verify()
10971+ )
10972+
10973+ # Handle response
10974+ if response.status_code == 202:
10975+ # Success - command accepted (no response body expected)
10976+ return None
10977+ else:
10978+ # Error - response contains JSON with ErrorMessage
10979+ raise CLIError(f"Command execution failed with status code {response.status_code}: {response.text}")
10980+
10981+
10982+ def webapp_exec(cmd, resource_group_name, name, command, mode='execute', working_directory=None, instance=None, slot=None):
10983+ # Validate Linux App
10984+ webapp = _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'get', slot)
10985+ if not webapp:
10986+ raise ResourceNotFoundError("Unable to find resource '{}' in ResourceGroup '{}'.".format(name, resource_group_name))
10987+
10988+ is_linux = webapp.reserved
10989+ if not is_linux:
10990+ raise ValidationError("Only Linux App Service Plans supported.")
10991+
10992+ # Allow mode 'execute' only
10993+ if mode.lower() != 'execute':
10994+ raise ValidationError("Only 'execute' mode is supported currently.")
10995+
10996+ # Validate command is provided if mode is 'execute'
10997+ if mode.lower() == 'execute' and not command:
10998+ raise ValidationError("Command is required.")
10999+
11000+ # Get scm site and authorization
11001+ scm_url = _get_scm_url(cmd, resource_group_name, name, slot)
11002+ headers = get_scm_site_headers(cmd.cli_ctx, name, resource_group_name, slot)
11003+
11004+ # Get target instances if specified
11005+ target_instances = []
11006+ if instance is not None:
11007+ # If command execution on all instances
11008+ if instance.lower() == "all":
11009+ instances = list_instances(cmd, resource_group_name, name, slot=slot)
11010+ target_instances = [i.name for i in instances]
11011+ if not target_instances:
11012+ raise ValidationError("No instances found for this web app.")
11013+ else:
11014+ # Validate listed instances
11015+ instances = list_instances(cmd, resource_group_name, name, slot=slot)
11016+ requested_instances = [i.strip() for i in instance.split(',')]
11017+ instance_names = set(i.name for i in instances)
11018+ invalid_instances = [inst for inst in requested_instances if inst not in instance_names]
11019+ if invalid_instances:
11020+ raise ValidationError("The following instances are not valid for this webapp: {}. Valid instances: {}".format(
11021+ ', '.join(invalid_instances), ', '.join(sorted(instance_names))))
11022+ target_instances = requested_instances
11023+
11024+ # Execute command on target instances
11025+ results = []
11026+ for target in target_instances if target_instances else [None]:
11027+ cookies = {}
11028+ if target is not None:
11029+ cookies['ARRAffinity'] = target
11030+
11031+ try:
11032+ result = _execute_command_on_instance(scm_url, headers, cookies, command, working_directory)
11033+ results.append({'instance': target or 'default', 'status': 'success', 'result': result})
11034+ except CLIError as e:
11035+ results.append({'instance': target or 'default', 'status': 'failed', 'error': str(e)})
11036+
11037+ return results if len(results) > 1 else results[0] if results else None
11038+
11039+
11040+
0 commit comments