55
66from itertools import groupby
77
8- from azure .mgmt .resource .resources .models import ChangeType , PropertyChangeType
8+ from azure .mgmt .resource .resources .models import ChangeType , PropertyChangeType , Level
99
1010from ._symbol import Symbol
1111from ._color import Color , ColoredStringBuilder
3030 PropertyChangeType .no_effect : Color .GRAY ,
3131}
3232
33+ _diagnostic_level_to_color = {
34+ Level .ERROR : Color .RED ,
35+ Level .WARNING : Color .DARK_YELLOW ,
36+ Level .INFO : Color .RESET ,
37+ }
38+
3339_change_type_to_symbol = {
3440 ChangeType .create : Symbol .PLUS ,
3541 ChangeType .delete : Symbol .MINUS ,
@@ -73,8 +79,22 @@ def format_what_if_operation_result(what_if_operation_result, enable_color=True)
7379 builder = ColoredStringBuilder (enable_color )
7480 _format_noise_notice (builder )
7581 _format_change_type_legend (builder , what_if_operation_result .changes )
76- _format_resource_changes (builder , what_if_operation_result .changes )
77- _format_resource_changes_stats (builder , what_if_operation_result .changes )
82+ _format_resource_changes (builder ,
83+ what_if_operation_result .changes ,
84+ definite_changes = True )
85+ _format_resource_changes_stats (builder ,
86+ what_if_operation_result .changes ,
87+ definite_changes = True )
88+ _format_resource_changes (builder ,
89+ what_if_operation_result .potential_changes ,
90+ definite_changes = False )
91+ _format_resource_changes_stats (builder ,
92+ what_if_operation_result .potential_changes ,
93+ definite_changes = False )
94+ _format_diagnostics (builder ,
95+ what_if_operation_result .changes ,
96+ what_if_operation_result .potential_changes ,
97+ what_if_operation_result .diagnostics )
7898 return builder .build ()
7999
80100
@@ -120,20 +140,24 @@ def populate_change_type_set(property_changes):
120140 builder .append_line (change_type .title ())
121141
122142
123- def _format_resource_changes_stats (builder , resource_changes ):
124- builder .append_line ().append ("Resource changes: " )
143+ def _format_resource_changes_stats (builder , resource_changes , definite_changes = True ):
144+ if definite_changes :
145+ builder .append_line ().append ("Resource changes: " )
125146
126- if not resource_changes :
127- builder .append ("no change." )
128- return
147+ if not resource_changes :
148+ builder .append ("no change." )
149+ return
150+ elif resource_changes :
151+ builder .append_line ().append ("Potential changes: " )
129152
130- sorted_resource_changes = sorted (resource_changes , key = lambda x : _change_type_to_weight [x .change_type ])
131- resource_changes_by_change_type = groupby (sorted_resource_changes , lambda x : x .change_type )
132- count_by_change_type = map (lambda x : (x [0 ], len (list (x [1 ]))), resource_changes_by_change_type )
133- count_by_change_type = filter (lambda x : x [1 ] > 0 , count_by_change_type )
134- change_type_stats = map (lambda x : _format_change_type_count (x [0 ], x [1 ]), count_by_change_type )
153+ if resource_changes :
154+ sorted_resource_changes = sorted (resource_changes , key = lambda x : _change_type_to_weight [x .change_type ])
155+ resource_changes_by_change_type = groupby (sorted_resource_changes , lambda x : x .change_type )
156+ count_by_change_type = map (lambda x : (x [0 ], len (list (x [1 ]))), resource_changes_by_change_type )
157+ count_by_change_type = filter (lambda x : x [1 ] > 0 , count_by_change_type )
158+ change_type_stats = map (lambda x : _format_change_type_count (x [0 ], x [1 ]), count_by_change_type )
135159
136- builder .append (", " .join (change_type_stats )).append ("." )
160+ builder .append (", " .join (change_type_stats )).append ("." )
137161
138162
139163def _format_change_type_count (change_type , count ): # pylint: disable=too-many-return-statements
@@ -155,15 +179,49 @@ def _format_change_type_count(change_type, count): # pylint: disable=too-many-r
155179 raise ValueError (f"Invalid ChangeType: { change_type } " )
156180
157181
158- def _format_resource_changes (builder , resource_changes ):
182+ def _format_diagnostics (builder , resource_changes , potential_changes , diagnostics ):
183+ short_circuited_resources = [r for r in (resource_changes or []) + (potential_changes or [])
184+ if r .change_type == ChangeType .UNSUPPORTED ]
185+
186+ diags = diagnostics or []
187+
188+ if len (short_circuited_resources ) + len (diags ) > 0 :
189+ builder .append_line ()
190+ builder .append_line ()
191+ builder .append (f"Diagnostics ({ len (short_circuited_resources ) + len (diags )} ): " )
192+ builder .append_line ()
193+
194+ for change in short_circuited_resources :
195+ with builder .new_color_scope (_diagnostic_level_to_color [Level .WARNING ]):
196+ builder .append (change .resource_id )
197+ builder .append (" (Unsupported) " )
198+ builder .append (change .unsupported_reason )
199+ builder .append_line ()
200+
201+ for diag in diags :
202+ with builder .new_color_scope (_diagnostic_level_to_color [diag .level ]):
203+ builder .append (diag .target )
204+ builder .append (" (" )
205+ builder .append (diag .code )
206+ builder .append (") " )
207+ builder .append (diag .message )
208+ builder .append_line ()
209+
210+
211+ def _format_resource_changes (builder , resource_changes , definite_changes = True ):
159212 if not resource_changes :
160213 return
161214
162215 num_scopes = len (set (map (_get_scope_uppercase , resource_changes )))
163216 resource_changes_by_scope = groupby (sorted (resource_changes , key = _get_scope_uppercase ), _get_scope_uppercase )
164217
165218 builder .append_line ()
166- builder .append_line (f"The deployment will update the following { 'scope:' if num_scopes == 1 else 'scopes' } " )
219+ if definite_changes :
220+ builder .append ("The deployment will update the following " )
221+ else :
222+ builder .append ("The following change MAY OR MAY NOT be deployed to the following " )
223+
224+ builder .append_line ('scope:' if num_scopes == 1 else 'scopes:' )
167225
168226 for _ , resource_changes_in_scope in resource_changes_by_scope :
169227 resource_changes_in_scope_list = list (resource_changes_in_scope )
0 commit comments