Skip to content

Commit f6a9e0b

Browse files
author
Henry Dai
committed
Fix issues
1 parent 2f72252 commit f6a9e0b

3 files changed

Lines changed: 52 additions & 32 deletions

File tree

src/azure-changesafety/README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,12 @@ az changesafety changerecord create \
7373
--links name=Runbook uri=https://contoso.com/runbook
7474
```
7575

76-
Update the rollout type and add a comment:
76+
Update the ChangeRecord and add a comment:
7777
```bash
7878
az changesafety changerecord update \
7979
-g MyResourceGroup \
8080
-n changerecord-webapp-rollout \
81-
--rollout-type Emergency \
82-
--comments "Escalated due to customer impact"
81+
--comments "Deployment validated in canary region"
8382
```
8483

8584
### StageProgression Examples

src/azure-changesafety/azext_changesafety/custom.py

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
# Code generated by aaz-dev-tools
66
# --------------------------------------------------------------------------------------------
77

8+
# pylint: disable=line-too-long
9+
810
"""Custom command overrides for azure-changesafety CLI extension.
911
1012
This module provides customizations for ChangeRecord CRUD operations:
@@ -424,41 +426,49 @@ def _build_change_definition(self):
424426
}
425427
}
426428

429+
@staticmethod
430+
def _parse_key_value_segment(segment):
431+
"""Parse a single key=value segment and return (mapped_key, value)."""
432+
if '=' not in segment:
433+
raise InvalidArgumentValueError('Each --targets entry must be in key=value format.')
434+
key, value = segment.split('=', 1)
435+
key = key.strip()
436+
value = value.strip()
437+
if not key or not value:
438+
raise InvalidArgumentValueError('Each --targets entry must include a non-empty key and value.')
439+
normalized_key = key.lower()
440+
if normalized_key in TARGET_KEY_MAPPING:
441+
mapped_key = TARGET_KEY_MAPPING[normalized_key]
442+
if mapped_key == 'httpMethod' and value:
443+
value = value.upper()
444+
return mapped_key, value
445+
return key, value
446+
447+
@staticmethod
448+
def _tokenize_target(token):
449+
"""Split a target token into segments, handling both ; and , delimiters."""
450+
if token is None:
451+
return []
452+
segments = []
453+
for part in str(token).split(';'):
454+
segments.extend(segment.strip() for segment in part.split(',') if segment.strip())
455+
return segments
456+
427457
@staticmethod
428458
def _parse_targets(raw_targets):
429-
if raw_targets is None:
430-
raise InvalidArgumentValueError('--targets is required and must include key=value pairs.')
431459
if not raw_targets:
432460
raise InvalidArgumentValueError('--targets is required and must include key=value pairs.')
433461
parsed_targets = []
434462
for token in raw_targets:
435-
if token is None:
436-
continue
437-
segments = []
438-
for part in str(token).split(';'):
439-
segments.extend(segment.strip() for segment in part.split(',') if segment.strip())
463+
segments = ChangeRecordCreate._tokenize_target(token)
440464
if not segments:
441465
continue
442466
target_entry = {}
443467
for segment in segments:
444-
if '=' not in segment:
445-
raise InvalidArgumentValueError('Each --targets entry must be in key=value format.')
446-
key, value = segment.split('=', 1)
447-
key = key.strip()
448-
value = value.strip()
449-
if not key or not value:
450-
raise InvalidArgumentValueError('Each --targets entry must include a non-empty key and value.')
451-
normalized_key = key.lower()
452-
if normalized_key in TARGET_KEY_MAPPING:
453-
mapped_key = TARGET_KEY_MAPPING[normalized_key]
454-
if mapped_key == 'httpMethod' and value:
455-
value = value.upper()
456-
target_entry[mapped_key] = value
457-
else:
458-
target_entry[key] = value
459-
if not target_entry:
460-
continue
461-
parsed_targets.append(target_entry)
468+
mapped_key, value = ChangeRecordCreate._parse_key_value_segment(segment)
469+
target_entry[mapped_key] = value
470+
if target_entry:
471+
parsed_targets.append(target_entry)
462472
if not parsed_targets:
463473
raise InvalidArgumentValueError('--targets must include at least one key=value pair.')
464474
return parsed_targets
@@ -470,13 +480,17 @@ def _output(self, *args, **kwargs):
470480

471481
class ChangeRecordsCreateOrUpdateAtSubscriptionLevel(
472482
_ChangeRecordCreate.ChangeRecordsCreateOrUpdateAtSubscriptionLevel):
483+
"""Override PUT at subscription level to inject custom changeDefinition."""
484+
473485
@property
474486
def content(self):
475487
content = super().content
476488
return _inject_change_definition_into_content(content, self.ctx)
477489

478490
class ChangeRecordsCreateOrUpdate(
479491
_ChangeRecordCreate.ChangeRecordsCreateOrUpdate):
492+
"""Override PUT at resource group level to inject custom changeDefinition."""
493+
480494
@property
481495
def content(self):
482496
content = super().content
@@ -517,6 +531,8 @@ def pre_operations(self):
517531

518532
class ChangeRecordsGetAtSubscriptionLevel(
519533
_ChangeRecordUpdate.ChangeRecordsGetAtSubscriptionLevel):
534+
"""Override GET at subscription level to capture original changeDefinition."""
535+
520536
def on_200(self, session):
521537
# Capture raw changeDefinition from HTTP response before schema loses details
522538
data = self.deserialize_http_content(session)
@@ -528,6 +544,8 @@ def on_200(self, session):
528544
return super().on_200(session)
529545

530546
class ChangeRecordsGet(_ChangeRecordUpdate.ChangeRecordsGet):
547+
"""Override GET at resource group level to capture original changeDefinition."""
548+
531549
def on_200(self, session):
532550
# Capture raw changeDefinition from HTTP response before schema loses details
533551
data = self.deserialize_http_content(session)
@@ -540,6 +558,8 @@ def on_200(self, session):
540558

541559
class ChangeRecordsCreateOrUpdateAtSubscriptionLevel(
542560
_ChangeRecordUpdate.ChangeRecordsCreateOrUpdateAtSubscriptionLevel):
561+
"""Override PUT at subscription level to preserve original changeDefinition."""
562+
543563
@property
544564
def content(self):
545565
content = super().content
@@ -548,6 +568,8 @@ def content(self):
548568

549569
class ChangeRecordsCreateOrUpdate(
550570
_ChangeRecordUpdate.ChangeRecordsCreateOrUpdate):
571+
"""Override PUT at resource group level to preserve original changeDefinition."""
572+
551573
@property
552574
def content(self):
553575
content = super().content
@@ -715,7 +737,7 @@ class ChangeRecordDelete(_ChangeRecordDelete):
715737
# StageMap Help Examples
716738
# -----------------------------------------------------------------------------
717739
# pylint: disable=wrong-import-position
718-
from azext_changesafety.aaz.latest.changesafety.stagemap import (
740+
from azext_changesafety.aaz.latest.changesafety.stagemap import ( # noqa: E402
719741
Create as _StageMapCreate,
720742
Show as _StageMapShow,
721743
Update as _StageMapUpdate,
@@ -818,7 +840,7 @@ class ChangeRecordDelete(_ChangeRecordDelete):
818840
# StageProgression Help Examples
819841
# -----------------------------------------------------------------------------
820842
# pylint: disable=wrong-import-position
821-
from azext_changesafety.aaz.latest.changesafety.stageprogression import (
843+
from azext_changesafety.aaz.latest.changesafety.stageprogression import ( # noqa: E402
822844
Create as _StageProgressionCreate,
823845
Show as _StageProgressionShow,
824846
Update as _StageProgressionUpdate,
@@ -828,7 +850,7 @@ class ChangeRecordDelete(_ChangeRecordDelete):
828850

829851
_StageProgressionCreate.AZ_HELP = {
830852
**_StageProgressionCreate.AZ_HELP,
831-
"short-summary": "Create a StageProgression to track the progress of a stage in a ChangeRecord.",
853+
"short-summary": "Create a StageProgression to track stage progress.",
832854
"long-summary": (
833855
"A StageProgression records the execution status of a specific stage defined "
834856
"in a StageMap. Use this to track which stages have started, completed, or failed "

src/azure-changesafety/setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,3 @@
4747
package_data={'azext_changesafety': ['azext_metadata.json']},
4848
install_requires=DEPENDENCIES
4949
)
50-

0 commit comments

Comments
 (0)