Azure SDK Python:标记特定资源
Azure SDK Python: tag a particular resource
我想使用 python 在 Azure 中的每个资源上创建标签。
create_or_update:创建订阅资源标签
list:获取订阅资源标签列表
好像只能对资源组做标签操作,不能对资源做标签操作?
示例:
向资源组添加标签:Set-AzureRmResourceGroup
向资源添加标签:Set-AzureRmResource
编辑:
感谢 api 查找代码,非常简洁。但我相信我手动输入的旧 api 也应该有效。我几乎没有修改就尝试了您的代码(我们可能有不同的 Azure SDK,我使用的是 2.0.0rc5)。添加api功能后(很有帮助),不幸的是我仍然有同样的错误。
from azure.common.credentials import UserPassCredentials
from azure.mgmt.resource.resources import ResourceManagementClient
def resolve_resource_api(client, resource):
""" This method retrieves the latest non-preview api version for
the given resource (unless the preview version is the only available
api version) """
provider = client.providers.get(resource.id.split('/')[6])
rt = next((t for t in provider.resource_types
if t.resource_type == '/'.join(resource.type.split('/')[1:])), None)
#print(rt)
if rt and 'api_versions' in rt.__dict__:
#api_version = [v for v in rt[0].api_versions if 'preview' not in v.lower()]
#return npv[0] if npv else rt[0].api_versions[0]
api_version = [v for v in rt.__dict__['api_versions'] if 'preview' not in v.lower()]
return api_version[0] if api_version else rt.__dict__['api_versions'][0]
credentials = UserPassCredentials(
'****@****.com', # Your new user
'******', # Your password
)
subscription_id= '*****-***-****-****-*******'
resource_client = ResourceManagementClient(credentials,
subscription_id)
for resource in resource_client.resources.list():
#print(resource)
#print(resolve_resource_api(resource_client, resource))
if resource.id.split('/')[4] == 'Build':
#resource.tags = {'foo':'bar'}
if resource.type == 'Microsoft.Web/sites':
print('resource.id: ', resource.id)
print('resource_group_name: ', resource.id.split('/')[4])
print('resource_provider_namespace: ', resource.id.split('/')[6])
print('parent_resource_path: ', '')
print('resource_type: ', str(resource.type).split('/')[-1])
print('resource_name: ', resource.name)
print('api_version: ', resolve_resource_api(resource_client, resource))
resource.tags['test'] = 'test1'
#print(resolve_resource_api(resource_client, resource))
#continue
print(resource)
resource_client.resources.create_or_update(
resource_group_name= resource.id.split('/')[4], # Extract from resource.id
resource_provider_namespace=resource.id.split('/')[6], # Extract from resource.id
parent_resource_path='', # Extract from resource.id
resource_type=str(resource.type).split('/')[-1], # Extract from resource type
resource_name=resource.name,
api_version=resolve_resource_api(resource_client, resource),
parameters=resource
)
print('-'*10)
Error
Traceback (most recent call last):
File "C:\Python35-32\Scripts\Azure\temp.py", line 56, in
parameters=resource
File "C:\Python35-32\lib\site-packages\azure\mgmt\resource\resources\operations\resources_operations.py", line 408, in create_or_update
raise exp
msrestazure.azure_exceptions.CloudError: Operation failed with status: 'Bad Request'. Details: 400 Client Error: Bad Request for url: https://management.azure.com/subscriptions/--***-*****-*******/resourcegroups/Build/providers/Microsoft.Web/sites/build-dev?api-version=2016-03-01
我工作了更多,发现我可以通过以下方式使用 create_or_update 方法:
from azure.mgmt.resource.resources.models import GenericResource
parameters=GenericResource(
location='West US',
properties={},
)
您的代码示例的响应错误消息显示 "The parameter properties has an invalid value"。所以我猜 parameters=resource 需要修复。我会仔细研究一下。
更新(已解决!):
for resource in resource_client.resources.list():
#print(resource)
if resource.id.split('/')[4] == 'Build':
if resource.type == 'Microsoft.Web/sites':
print('resource.id: ', resource.id)
print('resource_group_name: ', resource.id.split('/')[4])
print('resource_provider_namespace: ', resource.id.split('/')[6])
print('parent_resource_path: ', '')
print('resource_type: ', str(resource.type).split('/')[-1])
print('resource_name: ', resource.name)
print('api_version: ', resolve_resource_api(resource_client, resource))
if not resource.tags:
resource.tags = {}
resource.tags['test'] = 'test1'
else:
resource.tags['test'] = 'test1'
# This solves the error 400 Client Error: Bad Request. The parameter properties has an invalid value.
if not resource.properties:
resource.properties = {}
resource_client.resources.create_or_update(
resource_group_name= resource.id.split('/')[4], # Extract from resource.id
resource_provider_namespace=resource.id.split('/')[6], # Extract from resource.id
parent_resource_path='', # Extract from resource.id
resource_type=str(resource.type).split('/')[-1], # Extract from resource type
resource_name=resource.name,
api_version=resolve_resource_api(resource_client, resource),
parameters=resource,
)
print('-'*10)
出于某种奇怪的原因,如果 resource.properties 是 None,则请求不喜欢它。必须是 {}.
感谢特拉维斯的帮助!当我在 Azure SDK 上工作时,我会 post 更多问题 ;)
如果您使用 Python SDK,通常可以使用该资源的 create_or_update
方法向该资源添加标签。这些方法采用一个名为 parameters
的对象,该对象通常是您感兴趣的资源的对象类型。您可以在此处找到标签。
例如标记一个虚拟网络:
from azure.mgmt.network.models import VirtualNetwork
vnet = client.virtual_networks.get(resource_group_name, vnet_name)
vnet.tags = {'a':'b'}
client.virtual_networks.create_or_update(resource_group_name, virtual_network_name, vnet)
此外,您可以使用(对于本示例)azure network vnet set -t {tags}
命令通过 Xplat-Cli 标记您的资源。
您可以使用 azure group set -t {tags}
标记资源组,使用 azure resource set -t {tags}
标记资源。
希望对您有所帮助。
更新 (8/26/16)
获取 API 版本可能很棘手。您会认为它只是通用资源对象的一部分,但由于某些原因它不是。但是,尝试这样的事情:
from azure.common.credentials import UserPassCredentials
from azure.mgmt.resource.resources import ResourceManagementClient
def resolve_resource_api(client, resource):
""" This method retrieves the latest non-preview api version for
the given resource (unless the preview version is the only available
api version) """
provider = client.providers.get(resource.id.split('/')[6])
rt = next((t for t in provider.resource_types if t.resource_type == resource.type), None)
if rt and len(rt) == 1 and rt[0].api_versions:
api_version = [v for v in rt[0].api_versions if 'preview' not in v.lower()]
return npv[0] if npv else rt[0].api_versions[0]
credentials = UserPassCredentials(
'****@****.com', # Your new user
'******', # Your password
)
subscription_id= '*****-***-****-****-*******'
resource_client = ResourceManagementClient(credentials, subscription_id)
for resource in resource_client.resources.list():
resource.tags['test'] = 'test1'
# avoid error 400 if properties must be set
if not resource.properties:
resource.properties = {}
resource_client.resources.create_or_update(
resource_group_name= resource.id.split('/')[4],
resource_provider_namespace=resource.id.split('/')[6],
parent_resource_path='', # WARNING: this will not work with child resources
resource_type=str(resource.type).split('/')[-1],
resource_name=resource.name,
api_version=resolve_resource_api(resource_client, resource),
parameters=resource
)
client.resources 下的列表操作给出了整个订阅的 GenericResource 对象的分页列表。您发布的方式是一个接一个地遍历资源组,然后遍历每个资源组中的资源。这会很好地工作,并且可以避免您必须从 ID 中提取资源组名称,但我认为这个解决方案更简洁一些。
resolve_resource_api
方法使用提供程序命名空间和资源 ID 中的资源类型,使用资源提供程序获取操作查找该资源类型的可用 API 版本。此代码(缺少一些验证)将检索不是预览版本的最新 API 版本(除非它是唯一可用的版本)。仅仅在字符串中任意指定一个版本通常是行不通的,因为不同的资源会有不同的 API 版本。
此外,您的代码为父路径指定了“”,因此这通常不适用于子资源。
我想使用 python 在 Azure 中的每个资源上创建标签。
create_or_update:创建订阅资源标签 list:获取订阅资源标签列表
好像只能对资源组做标签操作,不能对资源做标签操作?
示例:
向资源组添加标签:Set-AzureRmResourceGroup 向资源添加标签:Set-AzureRmResource
编辑:
感谢 api 查找代码,非常简洁。但我相信我手动输入的旧 api 也应该有效。我几乎没有修改就尝试了您的代码(我们可能有不同的 Azure SDK,我使用的是 2.0.0rc5)。添加api功能后(很有帮助),不幸的是我仍然有同样的错误。
from azure.common.credentials import UserPassCredentials
from azure.mgmt.resource.resources import ResourceManagementClient
def resolve_resource_api(client, resource):
""" This method retrieves the latest non-preview api version for
the given resource (unless the preview version is the only available
api version) """
provider = client.providers.get(resource.id.split('/')[6])
rt = next((t for t in provider.resource_types
if t.resource_type == '/'.join(resource.type.split('/')[1:])), None)
#print(rt)
if rt and 'api_versions' in rt.__dict__:
#api_version = [v for v in rt[0].api_versions if 'preview' not in v.lower()]
#return npv[0] if npv else rt[0].api_versions[0]
api_version = [v for v in rt.__dict__['api_versions'] if 'preview' not in v.lower()]
return api_version[0] if api_version else rt.__dict__['api_versions'][0]
credentials = UserPassCredentials(
'****@****.com', # Your new user
'******', # Your password
)
subscription_id= '*****-***-****-****-*******'
resource_client = ResourceManagementClient(credentials,
subscription_id)
for resource in resource_client.resources.list():
#print(resource)
#print(resolve_resource_api(resource_client, resource))
if resource.id.split('/')[4] == 'Build':
#resource.tags = {'foo':'bar'}
if resource.type == 'Microsoft.Web/sites':
print('resource.id: ', resource.id)
print('resource_group_name: ', resource.id.split('/')[4])
print('resource_provider_namespace: ', resource.id.split('/')[6])
print('parent_resource_path: ', '')
print('resource_type: ', str(resource.type).split('/')[-1])
print('resource_name: ', resource.name)
print('api_version: ', resolve_resource_api(resource_client, resource))
resource.tags['test'] = 'test1'
#print(resolve_resource_api(resource_client, resource))
#continue
print(resource)
resource_client.resources.create_or_update(
resource_group_name= resource.id.split('/')[4], # Extract from resource.id
resource_provider_namespace=resource.id.split('/')[6], # Extract from resource.id
parent_resource_path='', # Extract from resource.id
resource_type=str(resource.type).split('/')[-1], # Extract from resource type
resource_name=resource.name,
api_version=resolve_resource_api(resource_client, resource),
parameters=resource
)
print('-'*10)
Error Traceback (most recent call last): File "C:\Python35-32\Scripts\Azure\temp.py", line 56, in parameters=resource File "C:\Python35-32\lib\site-packages\azure\mgmt\resource\resources\operations\resources_operations.py", line 408, in create_or_update raise exp msrestazure.azure_exceptions.CloudError: Operation failed with status: 'Bad Request'. Details: 400 Client Error: Bad Request for url: https://management.azure.com/subscriptions/--***-*****-*******/resourcegroups/Build/providers/Microsoft.Web/sites/build-dev?api-version=2016-03-01
我工作了更多,发现我可以通过以下方式使用 create_or_update 方法:
from azure.mgmt.resource.resources.models import GenericResource
parameters=GenericResource(
location='West US',
properties={},
)
您的代码示例的响应错误消息显示 "The parameter properties has an invalid value"。所以我猜 parameters=resource 需要修复。我会仔细研究一下。
更新(已解决!):
for resource in resource_client.resources.list():
#print(resource)
if resource.id.split('/')[4] == 'Build':
if resource.type == 'Microsoft.Web/sites':
print('resource.id: ', resource.id)
print('resource_group_name: ', resource.id.split('/')[4])
print('resource_provider_namespace: ', resource.id.split('/')[6])
print('parent_resource_path: ', '')
print('resource_type: ', str(resource.type).split('/')[-1])
print('resource_name: ', resource.name)
print('api_version: ', resolve_resource_api(resource_client, resource))
if not resource.tags:
resource.tags = {}
resource.tags['test'] = 'test1'
else:
resource.tags['test'] = 'test1'
# This solves the error 400 Client Error: Bad Request. The parameter properties has an invalid value.
if not resource.properties:
resource.properties = {}
resource_client.resources.create_or_update(
resource_group_name= resource.id.split('/')[4], # Extract from resource.id
resource_provider_namespace=resource.id.split('/')[6], # Extract from resource.id
parent_resource_path='', # Extract from resource.id
resource_type=str(resource.type).split('/')[-1], # Extract from resource type
resource_name=resource.name,
api_version=resolve_resource_api(resource_client, resource),
parameters=resource,
)
print('-'*10)
出于某种奇怪的原因,如果 resource.properties 是 None,则请求不喜欢它。必须是 {}.
感谢特拉维斯的帮助!当我在 Azure SDK 上工作时,我会 post 更多问题 ;)
如果您使用 Python SDK,通常可以使用该资源的 create_or_update
方法向该资源添加标签。这些方法采用一个名为 parameters
的对象,该对象通常是您感兴趣的资源的对象类型。您可以在此处找到标签。
例如标记一个虚拟网络:
from azure.mgmt.network.models import VirtualNetwork
vnet = client.virtual_networks.get(resource_group_name, vnet_name)
vnet.tags = {'a':'b'}
client.virtual_networks.create_or_update(resource_group_name, virtual_network_name, vnet)
此外,您可以使用(对于本示例)azure network vnet set -t {tags}
命令通过 Xplat-Cli 标记您的资源。
您可以使用 azure group set -t {tags}
标记资源组,使用 azure resource set -t {tags}
标记资源。
希望对您有所帮助。
更新 (8/26/16)
获取 API 版本可能很棘手。您会认为它只是通用资源对象的一部分,但由于某些原因它不是。但是,尝试这样的事情:
from azure.common.credentials import UserPassCredentials
from azure.mgmt.resource.resources import ResourceManagementClient
def resolve_resource_api(client, resource):
""" This method retrieves the latest non-preview api version for
the given resource (unless the preview version is the only available
api version) """
provider = client.providers.get(resource.id.split('/')[6])
rt = next((t for t in provider.resource_types if t.resource_type == resource.type), None)
if rt and len(rt) == 1 and rt[0].api_versions:
api_version = [v for v in rt[0].api_versions if 'preview' not in v.lower()]
return npv[0] if npv else rt[0].api_versions[0]
credentials = UserPassCredentials(
'****@****.com', # Your new user
'******', # Your password
)
subscription_id= '*****-***-****-****-*******'
resource_client = ResourceManagementClient(credentials, subscription_id)
for resource in resource_client.resources.list():
resource.tags['test'] = 'test1'
# avoid error 400 if properties must be set
if not resource.properties:
resource.properties = {}
resource_client.resources.create_or_update(
resource_group_name= resource.id.split('/')[4],
resource_provider_namespace=resource.id.split('/')[6],
parent_resource_path='', # WARNING: this will not work with child resources
resource_type=str(resource.type).split('/')[-1],
resource_name=resource.name,
api_version=resolve_resource_api(resource_client, resource),
parameters=resource
)
client.resources 下的列表操作给出了整个订阅的 GenericResource 对象的分页列表。您发布的方式是一个接一个地遍历资源组,然后遍历每个资源组中的资源。这会很好地工作,并且可以避免您必须从 ID 中提取资源组名称,但我认为这个解决方案更简洁一些。
resolve_resource_api
方法使用提供程序命名空间和资源 ID 中的资源类型,使用资源提供程序获取操作查找该资源类型的可用 API 版本。此代码(缺少一些验证)将检索不是预览版本的最新 API 版本(除非它是唯一可用的版本)。仅仅在字符串中任意指定一个版本通常是行不通的,因为不同的资源会有不同的 API 版本。
此外,您的代码为父路径指定了“”,因此这通常不适用于子资源。