使用Python获取Azure订阅资源IP地址时全部返回null
问题原因
脚本所有IP字段返回null,是三个逻辑错误导致的:
- 第一,
ResourceManagementClient.resources.list()默认返回的资源对象带的properties是精简属性集,不会返回各资源类型的专属配置字段,你想读的IP相关字段根本不在默认返回内容里。 - 第二,Azure不同资源的IP存储路径完全不统一,不存在全局通用的
properties.ipAddress字段:公网IP资源的IP存在properties.ip_address,网卡的私有IP存在properties.ip_configurations下的子属性,虚拟机、应用服务等资源本身不直接存储IP,要关联绑定的网卡、公网IP资源才能查到。另外Azure Python SDK会把REST接口返回的驼峰字段自动转成蛇形命名,你写的ipAddress驼峰属性名本身就和SDK的属性命名规则不匹配,就算字段存在也读不到。 - 第三,当前逻辑把资源组对象和普通资源对象混在同一个返回列表里,资源组本身是逻辑管理单元,根本没有关联IP,这部分返回null属于正常情况。
修复方案
- 先安装依赖SDK包:
pip install azure-mgmt-resource azure-mgmt-network azure-identity
- 调整查询逻辑:初始化网络管理客户端专门查网络类资源的IP配置,拉取资源列表时加上
expand="properties"参数拉取完整属性,针对有IP的资源类型单独写查询逻辑,其余无IP资源直接返回null即可。
修正后的可运行代码如下:
import logging import json from azure.mgmt.resource import ResourceManagementClient from azure.mgmt.network import NetworkManagementClient from azure.identity import DefaultAzureCredential def process_rg_instance(group): """提取资源组返回字段""" return { "Name": group.name, "Id": group.id, "Location": group.location, "Type": group.type, "Tags": group.tags, "ProvisioningState": group.properties.provisioning_state if group.properties and hasattr(group.properties, "provisioning_state") else None, "IPAddress": None } def process_r_instance(resource, network_client): """提取资源返回字段,按资源类型匹配IP查询逻辑""" ip_address = None res_type = resource.type.lower() # 公网IP资源直接读取IP属性 if res_type == "microsoft.network/publicipaddresses": if resource.properties and hasattr(resource.properties, "ip_address"): ip_address = resource.properties.ip_address # 网卡资源读取IP配置,包含私有IP和绑定的公网IP elif res_type == "microsoft.network/networkinterfaces": nic_detail = network_client.network_interfaces.get_by_id(resource.id) ip_configs = [] if nic_detail.ip_configurations: for config in nic_detail.ip_configurations: config_ip_map = {"private_ip": config.properties.private_ip_address} if config.properties.public_ip_address: config_ip_map["public_ip"] = config.properties.public_ip_address.ip_address ip_configs.append(config_ip_map) if ip_configs: ip_address = ip_configs # 其余类型资源无直接关联IP的,默认返回None即可 return { "Name": resource.name, "Type": resource.type, "Location": resource.location, "Tags": resource.tags, "IPAddress": ip_address } def list_subscription_resources(credentials, subscription_id): """查询指定订阅下所有资源组、资源及对应IP信息""" result = [] resource_client = None network_client = None try: resource_client = ResourceManagementClient(credentials, subscription_id) network_client = NetworkManagementClient(credentials, subscription_id) # 拉取所有资源组 for rg in resource_client.resource_groups.list(): result.append(process_rg_instance(rg)) # 拉取所有资源,expand参数指定返回完整properties for res in resource_client.resources.list(expand="properties"): result.append(process_r_instance(res, network_client)) except Exception as e: logging.error(f"执行异常: {str(e)}") finally: # 手动关闭客户端,原代码写的with语法对Azure SDK客户端不生效 if resource_client: resource_client.close() if network_client: network_client.close() return json.dumps(result, ensure_ascii=False, indent=2) if __name__ == "__main__": # 替换为实际订阅ID TARGET_SUBSCRIPTION_ID = "替换为你的订阅ID" # 使用默认Azure凭据,支持Azure CLI登录、托管标识等认证方式 cred = DefaultAzureCredential() print(list_subscription_resources(cred, TARGET_SUBSCRIPTION_ID))
注意事项
- 运行脚本使用的账号/服务主体需要有订阅级别的读取权限,否则会因为权限不足拉不到资源属性。
- 如果需要查询虚拟机、负载均衡、应用服务等其他资源的关联IP,只需要在
process_r_instance函数里新增对应资源类型的判断分支,调用对应服务的SDK客户端拉取关联的网卡、公网IP配置即可,不要依赖通用资源列表返回的精简属性。 - 原代码里加的
async关键字没有实际作用,Azure SDK for Python的资源列举方法是同步实现的,加async不会提升执行效率,反而会误导调用方。
内容的提问来源于stack exchange,提问作者Evan Reen
相关产品推荐
相关产品推荐

