Skip to content

Commit b9aac2d

Browse files
MoChiliawangzelin007Copilot
authored
Wzl/Support --what-if argument (#2)
* Add what if feature * Update src/azure-cli-core/azure/cli/core/commands/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * minor fix * Update what_if.py --------- Co-authored-by: ZelinWang <zelinwang@microsoft.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent e11f6aa commit b9aac2d

File tree

7 files changed

+62
-4
lines changed

7 files changed

+62
-4
lines changed

src/azure-cli-core/azure/cli/core/commands/__init__.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,8 @@ class AzCliCommandInvoker(CommandInvoker):
506506

507507
# pylint: disable=too-many-statements,too-many-locals,too-many-branches
508508
def execute(self, args):
509+
args_copy = args[:]
510+
509511
from knack.events import (EVENT_INVOKER_PRE_CMD_TBL_CREATE, EVENT_INVOKER_POST_CMD_TBL_CREATE,
510512
EVENT_INVOKER_CMD_TBL_LOADED, EVENT_INVOKER_PRE_PARSE_ARGS,
511513
EVENT_INVOKER_POST_PARSE_ARGS,
@@ -586,7 +588,8 @@ def execute(self, args):
586588
args[0] = '--help'
587589

588590
self.parser.enable_autocomplete()
589-
591+
if '--what-if' in (args_copy):
592+
return self._what_if(args_copy)
590593
self.cli_ctx.raise_event(EVENT_INVOKER_PRE_PARSE_ARGS, args=args)
591594
parsed_args = self.parser.parse_args(args)
592595
self.cli_ctx.raise_event(EVENT_INVOKER_POST_PARSE_ARGS, command=parsed_args.command, args=parsed_args)
@@ -691,6 +694,45 @@ def execute(self, args):
691694
table_transformer=self.commands_loader.command_table[parsed_args.command].table_transformer,
692695
is_query_active=self.data['query_active'])
693696

697+
def _what_if(self, args):
698+
# DEBUG: Add logging to see if this method is called
699+
print(f"DEBUG: _what_if called with command: {args}")
700+
if '--what-if' in args:
701+
print("DEBUG: Entering what-if mode")
702+
from azure.cli.core.what_if import show_what_if
703+
try:
704+
# Get subscription ID with priority: --subscription parameter > current login subscription
705+
if '--subscription' in args:
706+
index = args.index('--subscription')
707+
if index + 1 < len(args):
708+
subscription_value = args[index + 1]
709+
subscription_id = subscription_value
710+
else:
711+
from azure.cli.core.commands.client_factory import get_subscription_id
712+
subscription_id = get_subscription_id(self.cli_ctx)
713+
print(f"DEBUG: Using current login subscription ID: {subscription_id}")
714+
715+
args = ["az"] + args if args[0] != 'az' else args
716+
command = " ".join(args)
717+
what_if_result = show_what_if(self.cli_ctx, command, subscription_id=subscription_id)
718+
719+
# Ensure output format is set for proper formatting
720+
# Default to 'json' if not already set
721+
if 'output' not in self.cli_ctx.invocation.data or self.cli_ctx.invocation.data['output'] is None:
722+
self.cli_ctx.invocation.data['output'] = 'json'
723+
724+
# Return the formatted what-if output as the result
725+
# Similar to the normal flow in execute() method
726+
return CommandResultItem(
727+
what_if_result,
728+
table_transformer=None,
729+
is_query_active=self.data.get('query_active', False),
730+
exit_code=0
731+
)
732+
except Exception as ex:
733+
# If what-if service fails, still show an informative message
734+
return CommandResultItem(None, exit_code=1, error=CLIError(f'What-if preview failed: {str(ex)}\nNote: This was a preview operation. No actual changes were made.'))
735+
694736
@staticmethod
695737
def _extract_parameter_names(args):
696738
# note: name start with more than 2 '-' will be treated as value e.g. certs in PEM format

src/azure-cli-core/azure/cli/core/commands/parameters.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,16 @@ def get_location_type(cli_ctx):
268268
return location_type
269269

270270

271+
def get_what_if_type():
272+
what_if_type = CLIArgumentType(
273+
options_list=['--what-if'],
274+
help="Preview the changes that will be made without actually executing the command. "
275+
"This will call the what-if service to compare the current state with the expected state after execution.",
276+
is_preview=True
277+
)
278+
return what_if_type
279+
280+
271281
deployment_name_type = CLIArgumentType(
272282
help=argparse.SUPPRESS,
273283
required=False,

src/azure-cli-core/azure/cli/core/what_if.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Licensed under the MIT License. See License.txt in the project root for license information.
44
# --------------------------------------------------------------------------------------------
55

6+
67
import threading
78
import time
89
import sys
@@ -164,4 +165,4 @@ def _create_resource_change(change_data):
164165
for change_data in what_if_json_result.get('potential_changes', []):
165166
potential_changes.append(_create_resource_change(change_data))
166167

167-
return WhatIfOperationResult(changes, potential_changes, [])
168+
return WhatIfOperationResult(changes, potential_changes, [])

src/azure-cli/azure/cli/command_modules/sql/_params.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
get_enum_type,
4141
get_resource_name_completion_list,
4242
get_location_type,
43+
get_what_if_type,
4344
tags_type,
4445
resource_group_name_type
4546
)
@@ -1915,6 +1916,7 @@ def _configure_security_policy_storage_params(arg_ctx):
19151916
with self.argument_context('sql server create') as c:
19161917
c.argument('location',
19171918
arg_type=get_location_type_with_default_from_resource_group(self.cli_ctx))
1919+
c.argument('what_if', get_what_if_type())
19181920

19191921
# Create args that will be used to build up the Server object
19201922
create_args_for_complex_type(

src/azure-cli/azure/cli/command_modules/sql/custom.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4369,6 +4369,7 @@ def server_create(
43694369
external_admin_principal_type=None,
43704370
external_admin_sid=None,
43714371
external_admin_name=None,
4372+
what_if=None,
43724373
**kwargs):
43734374
'''
43744375
Creates a server.

src/azure-cli/azure/cli/command_modules/vm/_params.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from azure.cli.core.commands.validators import (
1414
get_default_location_from_resource_group, validate_file_or_dict)
1515
from azure.cli.core.commands.parameters import (
16-
get_location_type, get_resource_name_completion_list, tags_type, get_three_state_flag,
16+
get_location_type, get_what_if_type, get_resource_name_completion_list, tags_type, get_three_state_flag,
1717
file_type, get_enum_type, zone_type, zones_type)
1818
from azure.cli.command_modules.vm._actions import _resource_not_exists
1919
from azure.cli.command_modules.vm._completers import (
@@ -413,6 +413,7 @@ def load_arguments(self, _):
413413
c.argument('workspace', is_preview=True, arg_group='Monitor', help='Name or ID of Log Analytics Workspace. If you specify the workspace through its name, the workspace should be in the same resource group with the vm, otherwise a new workspace will be created.')
414414

415415
with self.argument_context('vm update') as c:
416+
c.argument('what_if', get_what_if_type())
416417
c.argument('os_disk', min_api='2017-12-01', help="Managed OS disk ID or name to swap to")
417418
c.argument('write_accelerator', nargs='*', min_api='2017-12-01',
418419
help="enable/disable disk write accelerator. Use singular value 'true/false' to apply across, or specify individual disks, e.g.'os=true 1=true 2=true' for os disk and data disks with lun of 1 & 2")
@@ -1058,6 +1059,7 @@ def load_arguments(self, _):
10581059
for scope in ['vm create', 'vmss create']:
10591060
with self.argument_context(scope) as c:
10601061
c.argument('location', get_location_type(self.cli_ctx), help='Location in which to create VM and related resources. If default location is not configured, will default to the resource group\'s location')
1062+
c.argument('what_if', get_what_if_type())
10611063
c.argument('tags', tags_type)
10621064
c.argument('no_wait', help='Do not wait for the long-running operation to finish.')
10631065
c.argument('validate', options_list=['--validate'], help='Generate and validate the ARM template without creating any resources.', action='store_true')

src/azure-cli/azure/cli/command_modules/vm/custom.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ def create_vm(cmd, vm_name, resource_group_name, image=None, size='Standard_DS1_
868868
enable_user_redeploy_scheduled_events=None, zone_placement_policy=None, include_zones=None,
869869
exclude_zones=None, align_regional_disks_to_vm_zone=None, wire_server_mode=None, imds_mode=None,
870870
wire_server_access_control_profile_reference_id=None, imds_access_control_profile_reference_id=None,
871-
key_incarnation_id=None):
871+
key_incarnation_id=None, what_if=False):
872872

873873
from azure.cli.core.commands.client_factory import get_subscription_id
874874
from azure.cli.core.util import random_string, hash_string

0 commit comments

Comments
 (0)