Skip to content

Commit 3d6c838

Browse files
committed
Merge remote-tracking branch 'azure/dev' into auth
2 parents 83d1c4a + 3d8ac89 commit 3d6c838

807 files changed

Lines changed: 164638 additions & 276863 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.githooks/pre-commit

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
#!/usr/bin/env sh
2-
":" //; if command -v pwsh >/dev/null 2>&1; then pwsh -ExecutionPolicy Bypass -File .githooks/pre-commit.ps1; else sh .githooks/pre-commit.sh; fi; exit $? # Try PowerShell Core first, then sh on Unix
3-
":" //; exit # Skip rest on Unix
42

5-
@echo off
6-
powershell -NoProfile -Command "if (Get-Command powershell -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"
7-
if %errorlevel% equ 0 (
8-
powershell -ExecutionPolicy Bypass -File .githooks\pre-commit.ps1
9-
) else (
10-
echo Error: PowerShell is not available. Please install PowerShell.
11-
exit /b 1
12-
)
13-
exit /b %errorlevel%
3+
# Check if running in Windows
4+
if [ -n "$COMSPEC" ]; then
5+
# Windows section - Execute directly with PowerShell
6+
powershell -NoProfile -Command "
7+
if (Get-Command powershell -ErrorAction SilentlyContinue) {
8+
Write-Host 'PowerShell found, executing pre-commit.ps1...'
9+
powershell -ExecutionPolicy Bypass -File '.githooks\pre-commit.ps1'
10+
exit $LASTEXITCODE
11+
} else {
12+
Write-Host 'Error: PowerShell is not available. Please install PowerShell.'
13+
exit 1
14+
}
15+
"
16+
echo "Exiting with status $?"
17+
exit $?
18+
else
19+
# Unix-like system section
20+
echo "Unix-like system found, executing pre-commit.sh..."
21+
sh .githooks/pre-commit.sh
22+
echo "Exiting with status $?"
23+
exit $?
24+
fi

.githooks/pre-push

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
#!/usr/bin/env sh
2-
":" //; if command -v pwsh >/dev/null 2>&1; then pwsh -ExecutionPolicy Bypass -File .githooks/pre-push.ps1; else sh .githooks/pre-push.sh; fi; exit $? # Try PowerShell Core first, then sh on Unix
3-
":" //; exit # Skip rest on Unix
42

5-
@echo off
6-
powershell -NoProfile -Command "if (Get-Command powershell -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"
7-
if %errorlevel% equ 0 (
8-
powershell -ExecutionPolicy Bypass -File .githooks\pre-push.ps1
9-
) else (
10-
echo Error: PowerShell is not available. Please install PowerShell.
11-
exit /b 1
12-
)
13-
exit /b %errorlevel%
3+
# Check if running in Windows
4+
if [ -n "$COMSPEC" ]; then
5+
# Windows section - Execute directly with PowerShell
6+
powershell -NoProfile -Command "
7+
if (Get-Command powershell -ErrorAction SilentlyContinue) {
8+
Write-Host 'PowerShell found, executing pre-push.ps1...'
9+
powershell -ExecutionPolicy Bypass -File '.githooks\pre-push.ps1'
10+
exit $LASTEXITCODE
11+
} else {
12+
Write-Host 'Error: PowerShell is not available. Please install PowerShell.'
13+
exit 1
14+
}
15+
"
16+
echo "Exiting with status $?"
17+
exit $?
18+
else
19+
# Unix-like system section
20+
echo "Unix-like system found, executing pre-push.sh..."
21+
sh .githooks/pre-push.sh
22+
echo "Exiting with status $?"
23+
exit $?
24+
fi

.githooks/pre-push.ps1

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ if ($mergeBase -ne $upstreamHead) {
4545
Write-Host "Would you like to automatically rebase and setup? [Y/n]" -ForegroundColor Yellow
4646

4747
try {
48-
$reader = [System.IO.StreamReader]::new("CON")
49-
$input = $reader.ReadLine()
48+
$input = Read-Host
49+
if ([string]::IsNullOrEmpty($input)) {
50+
$input = "Y"
51+
}
5052
} catch {
5153
Write-Host "Error reading input. Aborting push..." -ForegroundColor Red
5254
exit 1

src/azure-cli-core/HISTORY.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
Release History
44
===============
55

6+
2.70.0
7+
++++++
8+
* Resolve CVE-2024-12797 (#30816)
9+
* Drop Track 1 SDK authentication (#29631)
10+
* `aaz`: Add cross tenants control for `AAZResourceIdArgFormat` (#30817)
11+
* `aaz`: Support `Any` type with full value shorthand syntax allowed (#30868)
12+
613
2.69.0
714
++++++
815
* `aaz`: Support simple type parsed from string value (#30623)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --------------------------------------------------------------------------------------------
55
# pylint: disable=line-too-long
66

7-
__version__ = "2.69.0"
7+
__version__ = "2.70.0"
88

99
import os
1010
import sys

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
from ._arg import AAZArgumentsSchema, AAZArgEnum, AAZStrArg, AAZIntArg, AAZObjectArg, AAZDictArg, \
1313
AAZFreeFormDictArg, AAZFloatArg, AAZBaseArg, AAZBoolArg, AAZListArg, AAZResourceGroupNameArg, \
1414
AAZResourceLocationArg, AAZResourceIdArg, AAZSubscriptionIdArg, AAZUuidArg, AAZDateArg, AAZTimeArg, \
15-
AAZDateTimeArg, AAZDurationArg, AAZFileArg, AAZPasswordArg, AAZPaginationTokenArg, AAZPaginationLimitArg
15+
AAZDateTimeArg, AAZDurationArg, AAZFileArg, AAZPasswordArg, AAZPaginationTokenArg, AAZPaginationLimitArg, \
16+
AAZAnyTypeArg
1617
from ._arg_fmt import AAZStrArgFormat, AAZIntArgFormat, AAZFloatArgFormat, AAZBoolArgFormat, AAZObjectArgFormat, \
1718
AAZDictArgFormat, AAZFreeFormDictArgFormat, AAZListArgFormat, AAZResourceLocationArgFormat, \
1819
AAZResourceIdArgFormat, AAZSubscriptionIdArgFormat, AAZUuidFormat, AAZDateFormat, AAZTimeFormat, \
@@ -22,7 +23,7 @@
2223
from ._command import AAZCommand, AAZWaitCommand, AAZCommandGroup, \
2324
register_callback, register_command, register_command_group, load_aaz_command_table, link_helper
2425
from ._field_type import AAZIntType, AAZFloatType, AAZStrType, AAZBoolType, AAZDictType, AAZFreeFormDictType, \
25-
AAZListType, AAZObjectType, AAZIdentityObjectType
26+
AAZListType, AAZObjectType, AAZIdentityObjectType, AAZAnyType
2627
from ._operation import AAZHttpOperation, AAZJsonInstanceUpdateOperation, AAZGenericInstanceUpdateOperation, \
2728
AAZJsonInstanceDeleteOperation, AAZJsonInstanceCreateOperation
2829
from ._prompt import AAZPromptInput, AAZPromptPasswordInput

src/azure-cli-core/azure/cli/core/aaz/_arg.py

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
from knack.util import status_tag_messages
1414
from knack.log import get_logger
1515

16-
from ._arg_action import AAZSimpleTypeArgAction, AAZObjectArgAction, AAZDictArgAction, AAZFreeFormDictArgAction, \
17-
AAZListArgAction, AAZGenericUpdateAction, AAZGenericUpdateForceStringAction
16+
from ._arg_action import AAZSimpleTypeArgAction, AAZObjectArgAction, AAZDictArgAction, \
17+
AAZListArgAction, AAZGenericUpdateAction, AAZGenericUpdateForceStringAction, AAZAnyTypeArgAction
1818
from ._base import AAZBaseType, AAZUndefined
1919
from ._field_type import AAZObjectType, AAZStrType, AAZIntType, AAZBoolType, AAZFloatType, AAZListType, AAZDictType, \
20-
AAZSimpleType, AAZFreeFormDictType
20+
AAZSimpleType, AAZFreeFormDictType, AAZAnyType
2121
from ._field_value import AAZObject
2222
from ._arg_fmt import AAZObjectArgFormat, AAZListArgFormat, AAZDictArgFormat, AAZFreeFormDictArgFormat, \
2323
AAZSubscriptionIdArgFormat, AAZResourceLocationArgFormat, AAZResourceIdArgFormat, AAZUuidFormat, AAZDateFormat, \
@@ -356,6 +356,28 @@ def _type_in_help(self):
356356
return "Float"
357357

358358

359+
class AAZAnyTypeArg(AAZBaseArg, AAZAnyType):
360+
361+
def _build_cmd_action(self):
362+
class Action(AAZAnyTypeArgAction):
363+
_schema = self # bind action class with current schema
364+
return Action
365+
366+
def to_cmd_arg(self, name, **kwargs):
367+
from ._help import shorthand_help_messages
368+
arg = super().to_cmd_arg(name, **kwargs)
369+
short_summary = arg.type.settings.get('help', None) or ''
370+
if short_summary:
371+
short_summary += ' '
372+
short_summary += shorthand_help_messages['short-summary-anytype']
373+
arg.help = short_summary
374+
return arg
375+
376+
@property
377+
def _type_in_help(self):
378+
return "Any"
379+
380+
359381
class AAZCompoundTypeArg(AAZBaseArg):
360382

361383
@abc.abstractmethod
@@ -427,30 +449,15 @@ def _type_in_help(self):
427449
return f"Dict<String,{self.Element._type_in_help}>"
428450

429451

430-
class AAZFreeFormDictArg(AAZBaseArg, AAZFreeFormDictType):
452+
# Warning: This type should not be used any more, the new aaz-dev-tools only use AAZDictType with AAZAnyType
453+
class AAZFreeFormDictArg(AAZDictArg, AAZFreeFormDictType):
431454

432455
def __init__(self, fmt=None, **kwargs):
433456
fmt = fmt or AAZFreeFormDictArgFormat()
434457
super().__init__(fmt=fmt, **kwargs)
435-
436-
def to_cmd_arg(self, name, **kwargs):
437-
arg = super().to_cmd_arg(name, **kwargs)
438-
short_summary = arg.type.settings.get('help', None) or ''
439-
if short_summary:
440-
short_summary += ' '
441-
short_summary += "Support json-file and yaml-file."
442-
arg.help = short_summary
443-
return arg
444-
445-
def _build_cmd_action(self):
446-
class Action(AAZFreeFormDictArgAction):
447-
_schema = self # bind action class with current schema
448-
449-
return Action
450-
451-
@property
452-
def _type_in_help(self):
453-
return "Dict<String, Any>"
458+
# for backward compatible, support nullable value here for AAZFreeFormDictArg,
459+
# from the new code gen tools, it will avoid using AAZFreeFormDictArg
460+
self._element = AAZAnyTypeArg(nullable=True)
454461

455462

456463
class AAZListArg(AAZCompoundTypeArg, AAZListType):

src/azure-cli-core/azure/cli/core/aaz/_arg_action.py

Lines changed: 85 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ def format_data(cls, data):
150150
return AAZPromptInputOperation(prompt=cls._schema._blank, action_cls=cls)
151151
data = copy.deepcopy(cls._schema._blank)
152152

153+
if data is None:
154+
if cls._schema._nullable:
155+
return data
156+
raise AAZInvalidValueError("field is not nullable")
157+
158+
if cls._schema.DataType == str and isinstance(data, (int, bool, float)):
159+
data = str(data).lower() # convert to json raw values
160+
153161
if isinstance(data, str):
154162
# transfer string into correct data
155163
if cls._schema.enum:
@@ -159,12 +167,86 @@ def format_data(cls, data):
159167
if isinstance(data, cls._schema.DataType):
160168
return data
161169

170+
if isinstance(data, int) and cls._schema.DataType == float:
171+
return data
172+
173+
raise AAZInvalidValueError(f"{cls._schema.DataType} type value expected, got '{data}'({type(data)})")
174+
175+
176+
class AAZAnyTypeArgAction(AAZArgAction):
177+
178+
@classmethod
179+
def setup_operations(cls, dest_ops, values, prefix_keys=None):
180+
if prefix_keys is None:
181+
prefix_keys = []
182+
if values is None:
183+
data = AAZBlankArgValue # use blank data when values string is None
184+
else:
185+
if isinstance(values, list):
186+
assert prefix_keys # the values will be input as an list when parse singular option of a list argument
187+
if len(values) != 1:
188+
raise AAZInvalidValueError(f"only support 1 value, got {len(values)}: {values}")
189+
values = values[0]
190+
191+
if isinstance(values, str) and len(values) > 0:
192+
try:
193+
data = cls.decode_str(values)
194+
except AAZShowHelp as aaz_help:
195+
aaz_help.schema = cls._schema
196+
raise aaz_help
197+
else:
198+
data = values
199+
data = cls.format_data(data)
200+
dest_ops.add(data, *prefix_keys)
201+
202+
@classmethod
203+
def decode_str(cls, value):
204+
from azure.cli.core.util import get_file_json, shell_safe_json_parse, get_file_yaml
205+
206+
# check if the value is a partial value
207+
key, _, v = cls._str_parser.split_partial_value(value)
208+
if key is not None:
209+
raise AAZInvalidValueError(
210+
"AnyType args only support full value shorthand syntax, "
211+
"please don't use partial value shorthand syntax. "
212+
"If it's a simple string, please wrap it with single quotes.")
213+
214+
# read from file
215+
path = os.path.expanduser(value)
216+
if os.path.exists(path):
217+
if path.endswith('.yml') or path.endswith('.yaml'):
218+
# read from yaml file
219+
v = get_file_yaml(path)
220+
else:
221+
# read from json file
222+
v = get_file_json(path, preserve_order=True)
223+
else:
224+
try:
225+
v = cls._str_parser(value)
226+
except AAZInvalidShorthandSyntaxError as shorthand_ex:
227+
try:
228+
v = shell_safe_json_parse(value, True)
229+
except Exception as ex:
230+
logger.debug(ex) # log parse json failed expression
231+
raise shorthand_ex # raise shorthand syntax exception
232+
return v
233+
234+
@classmethod
235+
def format_data(cls, data):
236+
if data == AAZBlankArgValue:
237+
if cls._schema._blank == AAZUndefined:
238+
raise AAZInvalidValueError("argument value cannot be blank")
239+
if isinstance(cls._schema._blank, AAZPromptInput):
240+
# Postpone the prompt input when apply the operation.
241+
# In order not to break the logic of displaying help or validating other parameters.
242+
return AAZPromptInputOperation(prompt=cls._schema._blank, action_cls=cls)
243+
data = copy.deepcopy(cls._schema._blank)
244+
162245
if data is None:
163246
if cls._schema._nullable:
164247
return data
165248
raise AAZInvalidValueError("field is not nullable")
166-
167-
raise AAZInvalidValueError(f"{cls._schema.DataType} type value expected, got '{data}'({type(data)})")
249+
return data
168250

169251

170252
class AAZCompoundTypeArgAction(AAZArgAction): # pylint: disable=abstract-method
@@ -245,7 +327,7 @@ def _decode_value(cls, schema, value): # pylint: disable=unused-argument
245327
# simple type
246328
v = cls._str_parser(value, is_simple=True)
247329
else:
248-
# compound type
330+
# compound type or any type
249331
# read from file
250332
path = os.path.expanduser(value)
251333
if os.path.exists(path):
@@ -264,7 +346,6 @@ def _decode_value(cls, schema, value): # pylint: disable=unused-argument
264346
except Exception as ex:
265347
logger.debug(ex) # log parse json failed expression
266348
raise shorthand_ex # raise shorthand syntax exception
267-
268349
return v
269350

270351

@@ -324,52 +405,6 @@ def format_data(cls, data):
324405
raise AAZInvalidValueError(f"dict type value expected, got '{data}'({type(data)})")
325406

326407

327-
class AAZFreeFormDictArgAction(AAZSimpleTypeArgAction):
328-
329-
@classmethod
330-
def decode_str(cls, value):
331-
from azure.cli.core.util import get_file_json, shell_safe_json_parse, get_file_yaml
332-
333-
if len(value) == 0:
334-
# the express "a=" will return the blank value of schema 'a'
335-
return AAZBlankArgValue
336-
337-
path = os.path.expanduser(value)
338-
if os.path.exists(path):
339-
if path.endswith('.yml') or path.endswith('.yaml'):
340-
# read from yaml file
341-
v = get_file_yaml(path)
342-
else:
343-
# read from json file
344-
v = get_file_json(path, preserve_order=True)
345-
else:
346-
try:
347-
v = shell_safe_json_parse(value, True)
348-
except Exception as ex:
349-
logger.debug(ex) # log parse json failed expression
350-
raise
351-
return v
352-
353-
@classmethod
354-
def format_data(cls, data):
355-
if data == AAZBlankArgValue:
356-
if cls._schema._blank == AAZUndefined:
357-
raise AAZInvalidValueError("argument value cannot be blank")
358-
assert not isinstance(cls._schema._blank, AAZPromptInput), "Prompt input is not supported in " \
359-
"FreeFormDict args."
360-
data = copy.deepcopy(cls._schema._blank)
361-
362-
if isinstance(data, dict):
363-
return data
364-
365-
if data is None:
366-
if cls._schema._nullable:
367-
return data
368-
raise AAZInvalidValueError("field is not nullable")
369-
370-
raise AAZInvalidValueError(f"dict type value expected, got '{data}'({type(data)})")
371-
372-
373408
class AAZListArgAction(AAZCompoundTypeArgAction):
374409

375410
def __call__(self, parser, namespace, values, option_string=None):

0 commit comments

Comments
 (0)