@@ -57,7 +57,7 @@ def check_prerequisites():
5757 print (f"Running on { platform .system ()} { platform .release ()} " )
5858 if platform .system ().lower () == "windows" :
5959 print ("Note: On Windows, run the script with administrator privileges if needed." )
60-
60+
6161 # Verify Azure CLI login status but don't enforce login
6262 is_logged_in = verify_azure_login ()
6363 if not is_logged_in :
@@ -93,7 +93,7 @@ def get_user_input():
9393 ).strip ()
9494 or "https://github.com"
9595 )
96-
96+
9797 print ("\n Creating the GitHub App...\n " )
9898 print (f"Visit the following link to create your GitHub App:" )
9999 print (
@@ -134,7 +134,7 @@ def get_user_input():
134134 print ("You'll need to make this GitHub App public for it to work properly with organization repositories." )
135135 print ("For personal GitHub accounts, you can skip this step." )
136136 is_org_account = input ("Are you using a GitHub organization account? (y/n): " ).strip ().lower ()
137-
137+
138138 if is_org_account in ['y' , 'yes' ]:
139139 advanced_settings_url = f"https://github.com/settings/apps/{ gh_app_name } /advanced"
140140 print (f"\n Visit the following URL to set the GitHub App to public: { advanced_settings_url } " )
@@ -159,18 +159,18 @@ def get_user_input():
159159 " - VNet Name: max 7 characters (e.g., DEP01)\n "
160160 "Control Plane name: "
161161 ).strip ().upper ()
162-
162+
163163 # Validate format
164164 parts = control_plane_name .split ('-' )
165165 if len (parts ) != 3 :
166166 print ("Error: Control Plane name must have format: <Environment>-<RegionCode>-<VNetName>" )
167167 print ("Example: MGMT-WEEU-DEP01" )
168168 continue
169-
169+
170170 environment = parts [0 ]
171171 region_code = parts [1 ]
172172 vnet_name = parts [2 ]
173-
173+
174174 # Validate each component
175175 if len (environment ) > 5 :
176176 print (f"Error: Environment code '{ environment } ' must be maximum 5 characters." )
@@ -181,61 +181,61 @@ def get_user_input():
181181 if len (vnet_name ) > 7 :
182182 print (f"Error: VNet name '{ vnet_name } ' must be maximum 7 characters." )
183183 continue
184-
184+
185185 print (f"\n Parsed Control Plane components:" )
186186 print (f" Environment: { environment } " )
187187 print (f" Region Code: { region_code } " )
188188 print (f" VNet Name: { vnet_name } " )
189-
189+
190190 confirm = input ("Is this correct? (y/n): " ).strip ().lower ()
191191 if confirm in ['y' , 'yes' ]:
192192 break
193193
194194 # Azure details
195195 # Check if the user is logged in and get subscription and tenant details
196196 is_logged_in = verify_azure_login ()
197-
197+
198198 subscription_id = ""
199199 tenant_id = ""
200-
200+
201201 if is_logged_in :
202202 # Get the current subscription ID automatically
203203 print ("Fetching your current Azure subscription details..." )
204204 sub_result = run_az_command ([
205- "account" ,
206- "show" ,
207- "--query" ,
208- "id" ,
209- "-o" ,
205+ "account" ,
206+ "show" ,
207+ "--query" ,
208+ "id" ,
209+ "-o" ,
210210 "tsv"
211211 ], capture_output = True , text = True )
212-
212+
213213 if sub_result .returncode == 0 and sub_result .stdout .strip ():
214214 subscription_id = sub_result .stdout .strip ()
215215 print (f"Using subscription ID: { subscription_id } " )
216-
216+
217217 # Get the tenant ID automatically
218218 tenant_result = run_az_command ([
219- "account" ,
220- "show" ,
221- "--query" ,
222- "tenantId" ,
223- "-o" ,
219+ "account" ,
220+ "show" ,
221+ "--query" ,
222+ "tenantId" ,
223+ "-o" ,
224224 "tsv"
225225 ], capture_output = True , text = True )
226-
226+
227227 if tenant_result .returncode == 0 and tenant_result .stdout .strip ():
228228 tenant_id = tenant_result .stdout .strip ()
229229 print (f"Using tenant ID: { tenant_id } " )
230230 else :
231231 print ("Could not automatically detect tenant ID." )
232232 else :
233233 print ("Could not automatically detect subscription ID." )
234-
234+
235235 # Only prompt if we couldn't get the values automatically
236236 if not subscription_id :
237237 subscription_id = input ("\n Enter your Azure Subscription ID: " ).strip ()
238-
238+
239239 if not tenant_id :
240240 tenant_id = input ("Enter your Azure Tenant ID: " ).strip ()
241241
@@ -245,44 +245,44 @@ def get_user_input():
245245 print ("2. User Managed Identity (MSI) - more secure, no need for secrets" )
246246 print ("\n Note: Even if you choose User Managed Identity, GitHub Actions requires a Service Principal" )
247247 print ("for initial authentication until a self-hosted runner is set up." )
248-
248+
249249 auth_choice = ""
250250 while auth_choice not in ["1" , "2" ]:
251251 auth_choice = input ("\n Enter your choice (1/2): " ).strip ()
252252 if auth_choice not in ["1" , "2" ]:
253253 print ("Invalid choice. Please enter 1 or 2." )
254-
254+
255255 use_managed_identity = (auth_choice == "2" )
256-
256+
257257 # Initialize Service Principal related variables
258258 use_existing_spn = False
259259 spn_name = ""
260260 spn_appid = None
261261 spn_password = None
262262 spn_object_id = None
263-
263+
264264 # Initialize User-Assigned Managed Identity related variables
265265 use_existing_identity = False
266266 identity_name = ""
267267 identity_client_id = None
268268 identity_principal_id = None
269269 identity_id = None
270270 region_map = ""
271-
271+
272272 # Handle User-Assigned Managed Identity details if that option was selected
273273 resource_group_name = ""
274274 if use_managed_identity : # If Managed Identity was selected
275275 print ("\n --- User-Assigned Managed Identity Configuration ---" )
276276 use_existing_identity = input ("\n Do you want to use an existing User-Assigned Managed Identity? (y/n): " ).strip ().lower () in ['y' , 'yes' ]
277-
277+
278278 if use_existing_identity :
279279 # Get details for existing User-Assigned Managed Identity
280280 identity_name = input ("Enter the name of your existing User-Assigned Managed Identity: " ).strip ()
281281 identity_client_id = input ("Enter the Client ID of your Managed Identity: " ).strip ()
282-
282+
283283 # Get the resource group for the existing identity
284284 resource_group_name = input ("Enter the Resource Group containing the Managed Identity: " ).strip ()
285-
285+
286286 # Get the object/principal ID for the existing identity
287287 print ("Retrieving Principal ID for the Managed Identity..." )
288288 identity_show_args = [
@@ -292,12 +292,12 @@ def get_user_input():
292292 "--resource-group" , resource_group_name
293293 ]
294294 identity_show_result = run_az_command (identity_show_args , capture_output = True , text = True )
295-
295+
296296 if identity_show_result .returncode != 0 :
297297 print ("Failed to retrieve Managed Identity information." )
298298 print (identity_show_result .stderr )
299299 sys .exit (1 )
300-
300+
301301 try :
302302 identity_show_data = json .loads (identity_show_result .stdout )
303303 identity_principal_id = identity_show_data ["principalId" ]
@@ -313,7 +313,7 @@ def get_user_input():
313313 f"\n Enter Azure region to deploy to (full name for region code '{ region_code } ').\n "
314314 "Please use the short name (e.g., 'northeurope', 'westeurope', 'eastus2'): "
315315 ).strip ()
316-
316+
317317 # Ask for resource group name for creating a new Managed Identity
318318 print ("\n You need to specify a resource group for creating the Managed Identity." )
319319 default_resource_group = f"{ environment } -INFRASTRUCTURE-RG"
@@ -336,45 +336,45 @@ def get_user_input():
336336 # For Managed Identity, still need an SPN for initial authentication
337337 print ("\n You'll need a Service Principal for initial GitHub Actions authentication." )
338338 use_existing_spn = input ("Do you want to use an existing Service Principal for initial authentication? (y/n): " ).strip ().lower () in ['y' , 'yes' ]
339-
339+
340340 if use_existing_spn :
341341 spn_name = input ("Enter the name of your existing Service Principal: " ).strip ()
342342 spn_appid = input ("Enter the Application (client) ID of your Service Principal: " ).strip ()
343343 generate_new_secret = input ("Do you want to generate a new client secret? (y/n): " ).strip ().lower () in ['y' , 'yes' ]
344-
344+
345345 if generate_new_secret :
346346 print ("Generating a new client secret..." )
347347 # First try to reset credential at the app level
348348 app_secret_args = [
349- "ad" ,
350- "app" ,
351- "credential" ,
349+ "ad" ,
350+ "app" ,
351+ "credential" ,
352352 "reset" ,
353- "--id" ,
353+ "--id" ,
354354 spn_appid ,
355355 "--display-name" , "rbac" ,
356356 ]
357357 secret_result = run_az_command (app_secret_args , capture_output = True , text = True )
358-
358+
359359 # If app credential reset fails, try service principal credential reset
360360 if secret_result .returncode != 0 :
361361 print ("App credential reset failed, trying service principal credential reset..." )
362362 sp_secret_args = [
363- "ad" ,
364- "sp" ,
365- "credential" ,
363+ "ad" ,
364+ "sp" ,
365+ "credential" ,
366366 "reset" ,
367- "--id" ,
367+ "--id" ,
368368 spn_appid ,
369369 "--name" , "rbac" ,
370370 ]
371371 secret_result = run_az_command (sp_secret_args , capture_output = True , text = True )
372-
372+
373373 if secret_result .returncode != 0 :
374374 print ("Failed to generate new client secret. Please check the error and try again." )
375375 print (secret_result .stderr )
376376 sys .exit (1 )
377-
377+
378378 try :
379379 secret_data = json .loads (secret_result .stdout )
380380 # Handle different JSON formats from different CLI versions/commands
@@ -387,7 +387,7 @@ def get_user_input():
387387 spn_password = secret_data ["credentials" ][0 ].get ("password" )
388388 else :
389389 raise ValueError ("Could not find password in the response" )
390-
390+
391391 if not spn_password :
392392 print ("Failed to get the generated client secret." )
393393 sys .exit (1 )
@@ -398,7 +398,7 @@ def get_user_input():
398398 sys .exit (1 )
399399 else :
400400 spn_password = getpass .getpass ("Enter the client secret for your Service Principal: " ).strip ()
401-
401+
402402 # Get the object ID for the existing service principal
403403 print ("Retrieving Object ID for the Service Principal..." )
404404 spn_show_args = [
@@ -409,12 +409,12 @@ def get_user_input():
409409 spn_appid
410410 ]
411411 spn_show_result = run_az_command (spn_show_args , capture_output = True , text = True )
412-
412+
413413 if spn_show_result .returncode != 0 :
414414 print ("Failed to retrieve Service Principal information." )
415415 print (spn_show_result .stderr )
416416 sys .exit (1 )
417-
417+
418418 try :
419419 spn_show_data = json .loads (spn_show_result .stdout )
420420 spn_object_id = spn_show_data ["id" ]
@@ -425,25 +425,25 @@ def get_user_input():
425425 print ("\n \033 [1;33mWARNING: Using a placeholder value for Object ID.\033 [0m" )
426426 print ("This may cause issues during deployment. You should verify the Object ID manually." )
427427 spn_object_id = "PLACEHOLDER-OBJECT-ID"
428-
428+
429429 else :
430430 # Only ask for SPN name if creating a new one
431431 spn_name = input ("Enter the name for the new Azure Service Principal: " ).strip ()
432432 # Flag to indicate we need to create a new SPN
433433 spn_appid = None
434434 spn_password = None
435435 spn_object_id = None
436-
436+
437437 # SAP S-User credentials
438438 add_suser = input ("\n Do you want to add SAP S-User credentials? (y/n): " ).strip ().lower ()
439439 s_username = ""
440440 s_password = ""
441441 if add_suser in ['y' , 'yes' ]:
442442 s_username = input ("Enter your SAP S-Username: " ).strip ()
443443 s_password = getpass .getpass ("Enter your SAP S-User password: " ).strip ()
444-
444+
445445 # Docker image for SDAF
446- default_docker_image = "ghcr.io/Azure /sap-automation:main"
446+ default_docker_image = "ghcr.io/azure /sap-automation:main"
447447 print (f"\n Docker image for SDAF (default: { default_docker_image } )" )
448448 custom_docker_image = input (f"Enter a custom Docker image or press Enter to use the default: " ).strip ()
449449 docker_image = custom_docker_image if custom_docker_image else default_docker_image
0 commit comments