Skip to content

Commit eb4ef22

Browse files
author
Scott Clark
committed
resolved azdev style issues
1 parent 31e4fd8 commit eb4ef22

1 file changed

Lines changed: 149 additions & 92 deletions

File tree

  • src/azure-cli/azure/cli/command_modules/apim

src/azure-cli/azure/cli/command_modules/apim/custom.py

Lines changed: 149 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import uuid
2323
import re
24+
import os
2425
from urllib.parse import urlparse
2526

2627
from azure.cli.command_modules.apim._params import ImportFormat
@@ -516,6 +517,140 @@ def apim_api_import(
516517
parameters=parameters)
517518

518519

520+
def apim_api_export(client, resource_group_name, service_name, api_id, export_format, file_path=None, file_name=None,):
521+
"""Gets the details of the API specified by its identifier in the format specified """
522+
523+
import json
524+
import yaml
525+
import xml.etree.ElementTree as ET
526+
import os
527+
import requests
528+
529+
def _determine_file_extension(mapped_format):
530+
"""Determine file extension based on the mapped format."""
531+
if mapped_format in ['swagger', 'openapi+json']:
532+
return '.json'
533+
elif mapped_format in ['wsdl', 'wadl']:
534+
return '.xml'
535+
elif mapped_format in ['openapi']:
536+
return '.yaml'
537+
else:
538+
return '.txt'
539+
540+
541+
def _extract_export_link_or_text(response):
542+
"""Extract link or exported text from the API export response."""
543+
link = None
544+
exported_text = None
545+
response_dict = api_export_result_to_dict(response)
546+
try:
547+
link = response_dict['additional_properties']['properties']['value']['link']
548+
except KeyError:
549+
# No link present; try to use direct content
550+
try:
551+
exported_text = response.value if hasattr(response, 'value') else None
552+
except AttributeError: # defensive
553+
exported_text = None
554+
return link, exported_text
555+
556+
557+
def _fetch_content_from_link(link):
558+
"""Fetch content from a downloadable link."""
559+
import requests
560+
try:
561+
exported_results = requests.get(link, timeout=30)
562+
if not exported_results.ok:
563+
logger.warning("Got bad status from API Management during API export: %s", exported_results.status_code)
564+
return exported_results.text
565+
except requests.exceptions.ReadTimeout:
566+
logger.warning("Timed out while exporting API from API Management.")
567+
return None
568+
569+
570+
def _parse_exported_content(exported_text):
571+
"""Parse content into appropriate format (JSON, YAML, XML, or raw text)."""
572+
import json
573+
import yaml
574+
import xml.etree.ElementTree as ET
575+
576+
if exported_text is None:
577+
return None
578+
579+
try:
580+
return json.loads(exported_text)
581+
except json.JSONDecodeError:
582+
try:
583+
return yaml.safe_load(exported_text)
584+
except yaml.YAMLError:
585+
try:
586+
return ET.fromstring(exported_text)
587+
except ET.ParseError:
588+
return exported_text # raw text
589+
590+
591+
def _write_content_to_file(full_path, exported_result_content, file_extension, response):
592+
"""Write parsed content to file in appropriate format."""
593+
import json
594+
import yaml
595+
import xml.etree.ElementTree as ET
596+
597+
try:
598+
os.makedirs(os.path.dirname(full_path), exist_ok=True)
599+
with open(full_path, 'w', encoding='utf-8') as f:
600+
if isinstance(exported_result_content, dict) and file_extension == '.json':
601+
json.dump(exported_result_content, f, indent=4)
602+
elif isinstance(exported_result_content, dict) and file_extension == '.yaml':
603+
yaml.dump(exported_result_content, f)
604+
elif isinstance(exported_result_content, ET.Element):
605+
ET.register_namespace('', 'http://wadl.dev.java.net/2009/02')
606+
xml_string = ET.tostring(exported_result_content, encoding='unicode')
607+
f.write(xml_string)
608+
elif isinstance(exported_result_content, str):
609+
f.write(exported_result_content)
610+
else:
611+
# Fallback: write the value attribute or stringified content
612+
fallback = getattr(response, 'value', '')
613+
f.write(fallback if isinstance(fallback, str) else str(exported_result_content))
614+
except OSError as e:
615+
logger.warning("Error writing exported API to file: %s", e)
616+
617+
618+
def _handle_playback_mode(export_format, file_path, file_name, api_id, format_mapping):
619+
"""Handle playback mode file export for testing."""
620+
if file_path is None:
621+
raise RequiredArgumentMissingError(
622+
"Please specify file path using '--file-path' argument.")
623+
624+
file_extension = _determine_file_extension_from_export_format(export_format, format_mapping)
625+
export_type = format_mapping.get(export_format, '').replace('-link', '')
626+
627+
if file_name is None:
628+
file_name = f"{api_id}_{export_type}{file_extension}"
629+
630+
full_path = os.path.join(file_path, file_name)
631+
try:
632+
os.makedirs(os.path.dirname(full_path), exist_ok=True)
633+
with open(full_path, 'w', encoding='utf-8') as f:
634+
f.write('')
635+
except OSError as e:
636+
logger.warning("Error writing exported API to file in playback mode: %s", e)
637+
638+
logger.warning("APIM export results written to file (playback stub): %s", full_path)
639+
return None
640+
641+
642+
def _determine_file_extension_from_export_format(export_format, format_mapping):
643+
"""Determine file extension based on the export format."""
644+
if export_format in ['SwaggerFile', 'OpenApiJsonFile']:
645+
return '.json'
646+
elif export_format in ['WsdlFile', 'WadlFile']:
647+
return '.xml'
648+
elif export_format in ['OpenApiYamlFile']:
649+
return '.yaml'
650+
else:
651+
return '.txt'
652+
653+
519654
def apim_api_export(client, resource_group_name, service_name, api_id, export_format, file_path=None, file_name=None,):
520655
"""Gets the details of the API specified by its identifier in the format specified """
521656

@@ -526,7 +661,6 @@ def apim_api_export(client, resource_group_name, service_name, api_id, export_fo
526661
import requests
527662

528663
# Define the mapping from old format values to new ones
529-
# Use non-link formats for File exports to avoid duplicate identical GET requests
530664
format_mapping = {
531665
# File exports -> non-link formats
532666
"WadlFile": "wadl",
@@ -541,41 +675,15 @@ def apim_api_export(client, resource_group_name, service_name, api_id, export_fo
541675
"OpenApiJsonUrl": "openapi+json-link",
542676
"WsdlUrl": "wsdl-link"
543677
}
544-
mappedFormat = format_mapping.get(export_format)
678+
mapped_format = format_mapping.get(export_format)
545679

546-
# Export the API from API Management
547680
# Optimization for playback mode: if exporting to a file during tests, avoid a second
548681
# management call which causes cassette mismatches. Instead, create the file directly.
549-
import os as _os
550-
is_live = _os.environ.get('AZURE_TEST_RUN_LIVE', '').lower() in ['true', '1', 'yes']
682+
is_live = os.environ.get('AZURE_TEST_RUN_LIVE', '').lower() in ['true', '1', 'yes']
551683
if export_format.endswith('File') and not is_live:
552-
# If file is requested in playback mode
553-
if file_path is None:
554-
raise RequiredArgumentMissingError(
555-
"Please specify file path using '--file-path' argument.")
556-
# Determine extension from format
557-
if export_format in ['SwaggerFile', 'OpenApiJsonFile']:
558-
file_extension = '.json'
559-
elif export_format in ['WsdlFile', 'WadlFile']:
560-
file_extension = '.xml'
561-
elif export_format in ['OpenApiYamlFile']:
562-
file_extension = '.yaml'
563-
else:
564-
file_extension = '.txt'
565-
exportType = format_mapping.get(export_format, '').replace('-link', '') or mappedFormat
566-
if file_name is None:
567-
file_name = f"{api_id}_{exportType}{file_extension}"
568-
full_path = os.path.join(file_path, file_name)
569-
try:
570-
os.makedirs(os.path.dirname(full_path), exist_ok=True)
571-
with open(full_path, 'w', encoding='utf-8') as f:
572-
f.write('')
573-
except OSError as e:
574-
logger.warning("Error writing exported API to file in playback mode: %s", e)
575-
logger.warning("APIM export results written to file (playback stub): %s", full_path)
576-
return None
684+
return _handle_playback_mode(export_format, file_path, file_name, api_id, format_mapping)
577685

578-
response = client.api_export.get(resource_group_name, service_name, api_id, mappedFormat, True)
686+
response = client.api_export.get(resource_group_name, service_name, api_id, mapped_format, True)
579687

580688
# If url is requested, just return the export result (contains a link)
581689
if export_format in ['WadlUrl', 'SwaggerUrl', 'OpenApiYamlUrl', 'OpenApiJsonUrl', 'WsdlUrl']:
@@ -586,79 +694,28 @@ def apim_api_export(client, resource_group_name, service_name, api_id, export_fo
586694
raise RequiredArgumentMissingError(
587695
"Please specify file path using '--file-path' argument.")
588696

589-
# Determine the file extension based on the mappedFormat
590-
if mappedFormat in ['swagger', 'openapi+json']:
591-
file_extension = '.json'
592-
elif mappedFormat in ['wsdl', 'wadl']:
593-
file_extension = '.xml'
594-
elif mappedFormat in ['openapi']:
595-
file_extension = '.yaml'
596-
else:
597-
file_extension = '.txt'
598-
599-
exportType = mappedFormat
697+
file_extension = _determine_file_extension(mapped_format)
698+
export_type = mapped_format
699+
600700
if file_name is None:
601-
file_name = f"{api_id}_{exportType}{file_extension}"
701+
file_name = f"{api_id}_{export_type}{file_extension}"
602702
full_path = os.path.join(file_path, file_name)
603703

604704
# Try to obtain a downloadable link first (in case service still returns link)
605-
link = None
606-
exported_text = None
607-
response_dict = api_export_result_to_dict(response)
608-
try:
609-
link = response_dict['additional_properties']['properties']['value']['link']
610-
except KeyError:
611-
# No link present; try to use direct content
612-
try:
613-
exported_text = response.value if hasattr(response, 'value') else None
614-
except Exception: # defensive
615-
exported_text = None
705+
link, exported_text = _extract_export_link_or_text(response)
616706

617707
# Fetch content if link is available
618708
if link:
619-
try:
620-
exportedResults = requests.get(link, timeout=30)
621-
if not exportedResults.ok:
622-
logger.warning("Got bad status from API Management during API export: %s", exportedResults.status_code)
623-
exported_text = exportedResults.text
624-
except requests.exceptions.ReadTimeout:
625-
logger.warning("Timed out while exporting API from API Management.")
709+
fetched_text = _fetch_content_from_link(link)
710+
if fetched_text:
711+
exported_text = fetched_text
626712

627713
# Parse content where possible for nicer formatting, otherwise write raw text
628-
exportedResultContent = None
629-
if exported_text is not None:
630-
try:
631-
exportedResultContent = json.loads(exported_text)
632-
except Exception:
633-
try:
634-
exportedResultContent = yaml.safe_load(exported_text)
635-
except Exception:
636-
try:
637-
exportedResultContent = ET.fromstring(exported_text)
638-
except Exception:
639-
exportedResultContent = exported_text # raw text
714+
exported_result_content = _parse_exported_content(exported_text)
640715

641716
# Write results to a file
642717
logger.warning("Writing results to file: %s", full_path)
643-
try:
644-
os.makedirs(os.path.dirname(full_path), exist_ok=True)
645-
with open(full_path, 'w', encoding='utf-8') as f:
646-
if isinstance(exportedResultContent, dict) and file_extension == '.json':
647-
json.dump(exportedResultContent, f, indent=4)
648-
elif isinstance(exportedResultContent, dict) and file_extension == '.yaml':
649-
yaml.dump(exportedResultContent, f)
650-
elif isinstance(exportedResultContent, ET.Element):
651-
ET.register_namespace('', 'http://wadl.dev.java.net/2009/02')
652-
xml_string = ET.tostring(exportedResultContent, encoding='unicode')
653-
f.write(xml_string)
654-
elif isinstance(exportedResultContent, str):
655-
f.write(exportedResultContent)
656-
else:
657-
# Fallback: write the value attribute or stringified content
658-
fallback = getattr(response, 'value', '')
659-
f.write(fallback if isinstance(fallback, str) else str(exportedResultContent))
660-
except OSError as e:
661-
logger.warning("Error writing exported API to file: %s", e)
718+
_write_content_to_file(full_path, exported_result_content, file_extension, response)
662719

663720
logger.warning("APIM export results written to file: %s", full_path)
664721
return None

0 commit comments

Comments
 (0)