python - Azure SDK Python : tag a particular resource

标签 python azure azure-sdk-python

我想使用 python 在 Azure 中的每个资源上创建标签。

我在文档中看到这个模块: http://azure-sdk-for-python.readthedocs.io/en/latest/ref/azure.mgmt.resource.resources.operations.html#azure.mgmt.resource.resources.operations.TagsOperations

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={},
    )

代码示例中的响应错误消息显示“参数属性具有无效值”。所以我猜测参数=资源需要修复。我会进一步研究这一点。

更新(已解决!):

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 时,我会发布更多问题;)

最佳答案

如果您使用的是 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 resources 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 中的资源类型,通过资源提供程序 get 操作查找该资源类型的可用 API 版本。此代码(缺少一些验证)将检索不是预览版本的最新 API 版本(除非这是唯一可用的版本)。仅仅在字符串中任意指定版本通常是行不通的,因为不同的资源将具有不同的 API 版本。

此外,您的代码指定“”作为父路径,因此这通常不适用于子资源。

关于python - Azure SDK Python : tag a particular resource,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38992201/

相关文章:

python - 根据用户输入创建文件

azure - 我可以在 Azure 虚拟机中安装集成运行时并将本地服务器添加为链接服务吗?

azure - 如何在 Azure Web App 上为 SSL 获取静态 IP 地址

azure - 在 Azure 函数代码中使用 Python 包

python - 在BeautifulSoup抓取之后,从Python列表中提取数据,并创建Pandas表

python - 什么时候应该使用 HStoreField 而不是 JSONField?

python - 如何计算 python 列表中单独列表中的数字?

azure - Datafactory 映射数据流无法将日期时间格式化为 yyyy/MM/dd

python - 使用 python API 列出 Azure Blob 存储上的文件

python - 如何使用 python 获取对 azure 订阅拥有所有者访问权限的用户列表