【问题标题】:How to run Azure CLI commands using python?如何使用 python 运行 Azure CLI 命令?
【发布时间】:2019-01-03 21:03:00
【问题描述】:

我想使用 Azure CLI 获取资源组中所有 VM 的列表。但我想使用 python 脚本实现相同的功能。

例如,我将在 Azure CLI 中使用以下命令列出我的资源组中的 VM:

" az vm list -g MyResourceGroup"

但是,我希望 python 脚本也这样做,我只需将 CLI 命令合并到 python 程序中。

【问题讨论】:

  • 只是好奇:当您已经拥有可用的管理 REST API(包装在 python SDK 中)时,为什么还要尝试调用 CLI 命令? CLI 和各种 SDK(包括 python)建立在同一个 REST API 之上。
  • 它的 cli 使用起来要容易得多,就像很多一样。我们在 python 解决方案中使用了一些 sdk 调用和一些 cli 调用。主要是因为这个
  • 好吧,只要做一个标准的shell命令就可以了
  • 如果你想这样做,你需要subprocess 模块。阅读介绍,浏览“替换旧函数”中的示例,然后将其余部分作为参考,以帮助您根据需要充实细节。
  • @4c74356b41 - 在 python sdk (list_resources()) 中定义了一个函数,用于枚举资源组中的项目。除非 OP 正在做一些深奥的事情,否则这都是内置的,并且不依赖于正在运行的 shell 进程。

标签: python azure azure-virtual-machine azure-powershell azure-cli


【解决方案1】:

在过去的几天里,我一直在实施这一点。 @cbehrenberg 提供的方法主要是我使用的,但我发现您可以在不使用临时文件的情况下做到这一点。而是直接从 azure 客户端捕获输出。觉得可能有用。

from azure.cli.core import get_default_cli

def az_cli (args_str):
    args = args_str.split()
    cli = get_default_cli()
    cli.invoke(args)
    if cli.result.result:
        return cli.result.result
    elif cli.result.error:
        raise cli.result.error
    return True

然后以同样的方式调用:

from azhelper import az_cli

response = az_cli("vm list")
print("vm's: %s" % (response))

【讨论】:

  • 如果你想抑制输出到标准输出,然后像这样调用 cli:cli.invoke(args, out_file = open(os.devnull, 'w'))
  • 当我运行 az ad sp list --display-name example-name --query "[].appId" 时,我可以从 az cli 获得结果,但是当我从像 run_az_cli('ad sp list --display-name example-name --query "[].appId"') 这样的 python 脚本调用它时,我没有得到任何结果。当我将 --query "[].appId" 包含到字符串中时,就会发生这种情况。不知何故,cli 无法获得结果,因为我假设库不支持 --query "[].appId"?你有没有尝试过这样的事情?
  • @alpersilistre 尝试删除查询周围的双引号 - 我今天遇到了这个问题。双引号在 shell 中工作但不能与这个答案中的 az_cli 函数一起工作的原因是 shell 在将参数传递给 az cli 之前解释然后删除引号。另一方面,az_cli python 函数只是按空格分隔,将所有引号留在原处。
  • 运行此程序时出现此错误:CommandNotFoundError: 'az' is misspelled or not recognized by the system.
  • @Sajal - 我收到了相同的错误消息,因为我们在参数的开头包含了“az”。由于 CLI 会自动调用“az”命令,因此我们不需要将其包含在 arg 列表中。
【解决方案2】:

如何使用 python 运行 Azure CLI 命令?

据此file。我们可以通过以下方式调用 Azure CLI:

from azure.cli.core import get_default_cli
get_default_cli().invoke(['vm', 'list', '-g', 'groupname'])

注意:如果遇到No module named 'azure.cli.command_modules'错误,请安装azure-cli

【讨论】:

  • 我收到您在使用 cx_freeze 打包应用程序时提到的错误。它以 .py 格式工作就好了。任何想法为什么包装会破坏它?
【解决方案3】:

使用 subprocess 解决方案是有问题的,因为 subprocess 不会检查找到 Azure CLI 的 PATH,例如在 Windows 上。使用“cmd -c”将是一个特定于 Windows 的解决方案,并且需要一个 fork if/else 以获得额外的 Linux 支持。

@tom-sun 的回答几乎是正确的,因为您可以重用 Azure CLI python 模块,因为 CLI 也是用 Python 编写的。问题是, .invoke() 指令的返回总是返回错误代码。要获得完整的正文响应,您必须在底层 Knack Code 的参数列表中传递一个类似对象的文件以获取响应。默认情况下,这会重定向到 StdOut,这就是您可以看到它的原因,例如在您的终端中,但您总是获得零分。

我写了一个小辅助函数,它在一个字符串中接受 Azure CLI 指令(我不喜欢列表中的许多参数,它读起来不太好 - 但这只是个人喜好,不要怪我) .它使用一个临时文件作为输出目标,然后在内存中读回 - 这是底层 Knack CLI 代码所必需的;默认情况下,StdOut 是标准管道。

需要为 Python 安装 azure-cli:pip install azure-cli

文件azhelper.py

from azure.cli.core import get_default_cli
import tempfile

def az_cli (args_str):
    temp = tempfile.TemporaryFile()
    args = args_str.split()
    code = get_default_cli().invoke(args, None, temp)
    temp.seek(0)
    data = temp.read().strip()
    temp.close()
    return [code, data]

然后您可以像这样调用:

from azhelper import *

code, response = az_cli("vm list")
print("vm's: %s" % (response))

您当然需要登录,请参阅@4c74356b41 答案。

如果有人找到更好的方法来处理响应而不是使用临时文件,我们将不胜感激!我尝试使用内存中的 StringIO 对象,但这不知何故不符合底层 Knack CLI 代码。

【讨论】:

  • 改用 supprocess.Popen() 和 az 二进制文件。直接管道json。我不使用 pypi azure-cli 的主要原因是需要安装 335MB 的模块,而 az 二进制文件(apt install azure-cli)只需几秒钟。
  • 我必须使用 tempfile.TemporaryFile(mode = "r+") 和 code = get_default_cli().invoke(args, out_file=temp) 但所有其他位都很好用!!谢谢。
【解决方案4】:

我认为您可以使用子进程并调用 az cli 来获取输出,而不是使用 get_default_cli。参考Git Repo

import subprocess
import json

process = subprocess.Popen(['az','network', 'ddos-protection', 'list'], stdout=subprocess.PIPE)
out, err = process.communicate()
d = json.loads(out)
print(d)

【讨论】:

    【解决方案5】:

    既然你还没有删除它,我假设你还在寻找方法。

    from subprocess import call   
    call(["az", "vm", "list", "-g", "rgName"])
    

    您还需要先通过以下方式进行静默身份验证:

    az login --service-principal -u http://sample-cli-login -p Test1234 --tenant 54826b22-38d6-4fb2-bad9-b7b93a3e9c5a
    

    【讨论】:

      【解决方案6】:

      使用subprocess.run 而不是subprocess.Popen

      默认情况下,它会导致 python 脚本等到从子进程运行的程序(在本例中为 azure cli 命令)完成。

      例如,让我们创建一个 Azure AD 应用程序。

      import subprocess
      import json
      
      # create command you want to run on az cli as a string
      create_app_command = "az ad sp create-for-rbac --skip-assignment --years 20 --name dummy_app"
      
      # use 'shell = True' as Azure CLI installed on system is accessible from native shell
      # using 'subprocess.PIPE' will return stderr and stdout to create_app object
      create_app = subprocess.run(create_app_command, shell = True, stdout=subprocess.PIPE, stderr = subprocess.PIPE)
      
      # reading output and error
      create_app_stdout =  create_app.stdout.decode("utf-8")
      create_app_stderr = create_app.stderr.decode("utf-8")
      
      # now you can log error to a file 'logging.error(create_app_stderr)
      
      # you can use stdout for further logic in code
      # You get need to get appID and password for authentication somewhere later in code
      ad_app_details = json.loads(create_app_stdout)
      ad_app_appId = ad_app_details['appId']
      ad_app_password = ad_app_details['password']
      

      有关使用子进程模块的更多信息,请参阅this 链接

      【讨论】:

        【解决方案7】:

        我的理解是,目前的建议是为此使用管理库。

        SDK 的管理(或“管理平面”)库的名称均以 azure-mgmt- 开头,可帮助您通过 Python 脚本创建、配置和以其他方式管理 Azure 资源。所有 Azure 服务都有相应的管理库。
        借助管理库,您可以编写配置和部署脚本来执行与通过 Azure 门户或 Azure CLI 相同的任务。

        更多信息在这里:Provision and manage Azure resources with management libraries

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-01-11
          • 2020-04-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-01
          相关资源
          最近更新 更多