@@ -271,3 +271,254 @@ def test_generate_signing_key():
271271 s , b64 = utils .generate_signing_key ()
272272 assert isinstance (s , str )
273273 assert isinstance (b64 , str )
274+
275+
276+ # ------------------------------
277+ # build_infrastructure_tags
278+ # ------------------------------
279+
280+ def test_build_infrastructure_tags_with_enum ():
281+ """Test build_infrastructure_tags with INFRASTRUCTURE enum."""
282+ result = utils .build_infrastructure_tags (INFRASTRUCTURE .SIMPLE_APIM )
283+ expected = {'infrastructure' : 'simple-apim' }
284+ assert result == expected
285+
286+ def test_build_infrastructure_tags_with_string ():
287+ """Test build_infrastructure_tags with string infrastructure."""
288+ result = utils .build_infrastructure_tags ("test-infra" )
289+ expected = {'infrastructure' : 'test-infra' }
290+ assert result == expected
291+
292+ def test_build_infrastructure_tags_with_custom_tags ():
293+ """Test build_infrastructure_tags with custom tags."""
294+ custom_tags = {'env' : 'dev' , 'team' : 'platform' }
295+ result = utils .build_infrastructure_tags (INFRASTRUCTURE .APIM_ACA , custom_tags )
296+ expected = {
297+ 'infrastructure' : 'apim-aca' ,
298+ 'env' : 'dev' ,
299+ 'team' : 'platform'
300+ }
301+ assert result == expected
302+
303+ def test_build_infrastructure_tags_custom_tags_override ():
304+ """Test that custom tags can override standard tags."""
305+ custom_tags = {'infrastructure' : 'custom-override' }
306+ result = utils .build_infrastructure_tags (INFRASTRUCTURE .AFD_APIM_PE , custom_tags )
307+ expected = {'infrastructure' : 'custom-override' }
308+ assert result == expected
309+
310+ def test_build_infrastructure_tags_empty_custom_tags ():
311+ """Test build_infrastructure_tags with empty custom tags dict."""
312+ result = utils .build_infrastructure_tags (INFRASTRUCTURE .SIMPLE_APIM , {})
313+ expected = {'infrastructure' : 'simple-apim' }
314+ assert result == expected
315+
316+ def test_build_infrastructure_tags_none_custom_tags ():
317+ """Test build_infrastructure_tags with None custom tags."""
318+ result = utils .build_infrastructure_tags (INFRASTRUCTURE .APIM_ACA , None )
319+ expected = {'infrastructure' : 'apim-aca' }
320+ assert result == expected
321+
322+
323+ # ------------------------------
324+ # create_resource_group
325+ # ------------------------------
326+
327+ def test_create_resource_group_not_exists_no_tags (monkeypatch ):
328+ """Test create_resource_group when resource group doesn't exist and no tags provided."""
329+ monkeypatch .setattr (utils , 'does_resource_group_exist' , lambda x : False )
330+ mock_run = MagicMock (return_value = MagicMock (success = True ))
331+ monkeypatch .setattr (utils , 'run' , mock_run )
332+ monkeypatch .setattr (utils , 'print_info' , MagicMock ())
333+
334+ utils .create_resource_group ('test-rg' , 'eastus' )
335+
336+ # Verify the correct command was called
337+ expected_cmd = 'az group create --name test-rg --location eastus --tags source=apim-sample'
338+ mock_run .assert_called_once ()
339+ actual_cmd = mock_run .call_args [0 ][0 ]
340+ assert actual_cmd == expected_cmd
341+
342+ def test_create_resource_group_not_exists_with_tags (monkeypatch ):
343+ """Test create_resource_group when resource group doesn't exist and tags are provided."""
344+ monkeypatch .setattr (utils , 'does_resource_group_exist' , lambda x : False )
345+ mock_run = MagicMock (return_value = MagicMock (success = True ))
346+ monkeypatch .setattr (utils , 'run' , mock_run )
347+ monkeypatch .setattr (utils , 'print_info' , MagicMock ())
348+
349+ tags = {'infrastructure' : 'simple-apim' , 'env' : 'dev' }
350+ utils .create_resource_group ('test-rg' , 'eastus' , tags )
351+
352+ # Verify the correct command was called with tags
353+ mock_run .assert_called_once ()
354+ actual_cmd = mock_run .call_args [0 ][0 ]
355+ assert 'source=apim-sample' in actual_cmd
356+ assert 'infrastructure="simple-apim"' in actual_cmd
357+ assert 'env="dev"' in actual_cmd
358+
359+ def test_create_resource_group_already_exists (monkeypatch ):
360+ """Test create_resource_group when resource group already exists."""
361+ monkeypatch .setattr (utils , 'does_resource_group_exist' , lambda x : True )
362+ mock_run = MagicMock ()
363+ monkeypatch .setattr (utils , 'run' , mock_run )
364+
365+ utils .create_resource_group ('existing-rg' , 'eastus' )
366+
367+ # Verify run was not called since RG already exists
368+ mock_run .assert_not_called ()
369+
370+ def test_create_resource_group_tags_with_special_chars (monkeypatch ):
371+ """Test create_resource_group with tags containing special characters."""
372+ monkeypatch .setattr (utils , 'does_resource_group_exist' , lambda x : False )
373+ mock_run = MagicMock (return_value = MagicMock (success = True ))
374+ monkeypatch .setattr (utils , 'run' , mock_run )
375+ monkeypatch .setattr (utils , 'print_info' , MagicMock ())
376+
377+ tags = {
'description' :
'This is a "test" environment' ,
'owner' :
'[email protected] ' }
378+ utils .create_resource_group ('test-rg' , 'eastus' , tags )
379+
380+ mock_run .assert_called_once ()
381+ actual_cmd = mock_run .call_args [0 ][0 ]
382+ # Check that quotes are properly escaped
383+ assert 'description="This is a \\ "test\\ " environment"' in actual_cmd
384+ assert 'owner="[email protected] "' in actual_cmd 385+
386+ def test_create_resource_group_tags_with_numeric_values (monkeypatch ):
387+ """Test create_resource_group with tags containing numeric values."""
388+ monkeypatch .setattr (utils , 'does_resource_group_exist' , lambda x : False )
389+ mock_run = MagicMock (return_value = MagicMock (success = True ))
390+ monkeypatch .setattr (utils , 'run' , mock_run )
391+ monkeypatch .setattr (utils , 'print_info' , MagicMock ())
392+
393+ tags = {'cost-center' : 12345 , 'version' : 1.0 }
394+ utils .create_resource_group ('test-rg' , 'eastus' , tags )
395+
396+ mock_run .assert_called_once ()
397+ actual_cmd = mock_run .call_args [0 ][0 ]
398+ # Numeric values should be converted to strings
399+ assert 'cost-center="12345"' in actual_cmd
400+ assert 'version="1.0"' in actual_cmd
401+
402+
403+ # ------------------------------
404+ # create_bicep_deployment_group
405+ # ------------------------------
406+
407+ def test_create_bicep_deployment_group_with_enum (monkeypatch ):
408+ """Test create_bicep_deployment_group with INFRASTRUCTURE enum."""
409+ mock_create_rg = MagicMock ()
410+ monkeypatch .setattr (utils , 'create_resource_group' , mock_create_rg )
411+ mock_run = MagicMock (return_value = MagicMock (success = True ))
412+ monkeypatch .setattr (utils , 'run' , mock_run )
413+ mock_open_func = mock_open ()
414+ monkeypatch .setattr (builtins , 'open' , mock_open_func )
415+ monkeypatch .setattr (builtins , 'print' , MagicMock ())
416+
417+ bicep_params = {'param1' : {'value' : 'test' }}
418+ rg_tags = {'infrastructure' : 'simple-apim' }
419+
420+ result = utils .create_bicep_deployment_group (
421+ 'test-rg' , 'eastus' , INFRASTRUCTURE .SIMPLE_APIM , bicep_params , 'params.json' , rg_tags
422+ )
423+
424+ # Verify create_resource_group was called with correct parameters
425+ mock_create_rg .assert_called_once_with ('test-rg' , 'eastus' , rg_tags )
426+
427+ # Verify deployment command was called with enum value
428+ mock_run .assert_called_once ()
429+ actual_cmd = mock_run .call_args [0 ][0 ]
430+ assert 'az deployment group create' in actual_cmd
431+ assert '--name simple-apim' in actual_cmd
432+ assert '--resource-group test-rg' in actual_cmd
433+
434+ def test_create_bicep_deployment_group_with_string (monkeypatch ):
435+ """Test create_bicep_deployment_group with string deployment name."""
436+ mock_create_rg = MagicMock ()
437+ monkeypatch .setattr (utils , 'create_resource_group' , mock_create_rg )
438+ mock_run = MagicMock (return_value = MagicMock (success = True ))
439+ monkeypatch .setattr (utils , 'run' , mock_run )
440+ mock_open_func = mock_open ()
441+ monkeypatch .setattr (builtins , 'open' , mock_open_func )
442+ monkeypatch .setattr (builtins , 'print' , MagicMock ())
443+
444+ bicep_params = {'param1' : {'value' : 'test' }}
445+
446+ result = utils .create_bicep_deployment_group (
447+ 'test-rg' , 'eastus' , 'custom-deployment' , bicep_params
448+ )
449+
450+ # Verify create_resource_group was called without tags
451+ mock_create_rg .assert_called_once_with ('test-rg' , 'eastus' , None )
452+
453+ # Verify deployment command uses string deployment name
454+ mock_run .assert_called_once ()
455+ actual_cmd = mock_run .call_args [0 ][0 ]
456+ assert '--name custom-deployment' in actual_cmd
457+
458+ def test_create_bicep_deployment_group_params_file_written (monkeypatch ):
459+ """Test that bicep parameters are correctly written to file."""
460+ mock_create_rg = MagicMock ()
461+ monkeypatch .setattr (utils , 'create_resource_group' , mock_create_rg )
462+ mock_run = MagicMock (return_value = MagicMock (success = True ))
463+ monkeypatch .setattr (utils , 'run' , mock_run )
464+ mock_open_func = mock_open ()
465+ monkeypatch .setattr (builtins , 'open' , mock_open_func )
466+ monkeypatch .setattr (builtins , 'print' , MagicMock ())
467+
468+ bicep_params = {
469+ 'apiManagementName' : {'value' : 'test-apim' },
470+ 'location' : {'value' : 'eastus' }
471+ }
472+
473+ utils .create_bicep_deployment_group (
474+ 'test-rg' , 'eastus' , INFRASTRUCTURE .APIM_ACA , bicep_params , 'custom-params.json'
475+ )
476+
477+ # Verify file was opened for writing
478+ mock_open_func .assert_called_once_with ('custom-params.json' , 'w' )
479+
480+ # Verify the correct JSON structure was written
481+ written_content = '' .join (call .args [0 ] for call in mock_open_func ().write .call_args_list )
482+ import json
483+ written_data = json .loads (written_content )
484+
485+ assert written_data ['$schema' ] == "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#"
486+ assert written_data ['contentVersion' ] == "1.0.0.0"
487+ assert written_data ['parameters' ] == bicep_params
488+
489+ def test_create_bicep_deployment_group_no_tags (monkeypatch ):
490+ """Test create_bicep_deployment_group without tags."""
491+ mock_create_rg = MagicMock ()
492+ monkeypatch .setattr (utils , 'create_resource_group' , mock_create_rg )
493+ mock_run = MagicMock (return_value = MagicMock (success = True ))
494+ monkeypatch .setattr (utils , 'run' , mock_run )
495+ mock_open_func = mock_open ()
496+ monkeypatch .setattr (builtins , 'open' , mock_open_func )
497+ monkeypatch .setattr (builtins , 'print' , MagicMock ())
498+
499+ bicep_params = {'param1' : {'value' : 'test' }}
500+
501+ utils .create_bicep_deployment_group ('test-rg' , 'eastus' , 'test-deployment' , bicep_params )
502+
503+ # Verify create_resource_group was called with None tags
504+ mock_create_rg .assert_called_once_with ('test-rg' , 'eastus' , None )
505+
506+ def test_create_bicep_deployment_group_deployment_failure (monkeypatch ):
507+ """Test create_bicep_deployment_group when deployment fails."""
508+ mock_create_rg = MagicMock ()
509+ monkeypatch .setattr (utils , 'create_resource_group' , mock_create_rg )
510+ mock_run = MagicMock (return_value = MagicMock (success = False ))
511+ monkeypatch .setattr (utils , 'run' , mock_run )
512+ mock_open_func = mock_open ()
513+ monkeypatch .setattr (builtins , 'open' , mock_open_func )
514+ monkeypatch .setattr (builtins , 'print' , MagicMock ())
515+
516+ bicep_params = {'param1' : {'value' : 'test' }}
517+
518+ result = utils .create_bicep_deployment_group ('test-rg' , 'eastus' , 'test-deployment' , bicep_params )
519+
520+ # Should still create resource group
521+ mock_create_rg .assert_called_once ()
522+
523+ # Result should indicate failure
524+ assert result .success is False
0 commit comments