1

我正在使用 Terraform 外部数据源从 Azure DevOps rest api 获取响应(分支的 objectId 将用作其他脚本/操作的进一步输入)。

我正在通过外部数据源资源调用 python 脚本,如下所示:

data "external" "example" {
  program = ["python", "ex-data-source.py"]

  query = {
    organisation = "https://dev.azure.com/my-org"
    project = "my-proj"
    repositoryId = "my-repo"
    branch = "heads/my-branch"
    new_branch = "heads/newbranch"
    pat = "my-pat"
  }
}

output "branch_id" {
  value = data.external.example.result.branch_id
}

我的 ex-data-source.py 文件是:

import base64
import json
import sys
import requests
from azure.cli.core import get_default_cli

# Step#1 - Parse the input as stdin from terraform external data source
input = sys.stdin.read()
input_json = json.loads(input)

# Step#2 - Extract the relevant data based on key passed
pat = input_json.get("pat")
organisation = input_json.get("organisation")
project = input_json.get("project")
repositoryId = input_json.get("repositoryId")
branch = input_json.get("branch")
new_branch = input_json.get("new_branch")

b64userpass = str(base64.b64encode(bytes(':' + pat, 'ascii')), 'ascii')
headers = {
    'Accept': 'application/json',
    'Authorization': 'Basic %s' % b64userpass
}

list_url = f"https://dev.azure.com/{organisation}/{project}/_apis/git/repositories/{repositoryId}/refs?filtercontain={branch}&api-version=6.1-preview.1"

r = requests.get(list_url, headers=headers)
if r.status_code == 200:
    r_json = r.json()
    branch_id = r_json["value"][0]["objectId"]

# Step#3 - Extract the relevant data based on key passed
output = {
    "objectID": branch_id
}

output_json = json.dumps(output)
print(output_json)

理想的预期输出 我应该取回分支的objectId,例如a750b8eb8e26a2e4b9910c10f29e6d55d8639d50

收到错误

Error: failed to execute "python": Traceback (most recent call last):
│   File "/Users/metro.akaushik/Desktop/Projects/AzDO/ex-data-source.py", line 42, in <module>
│     "objectID": branch_id
│ NameError: name 'branch_id' is not defined
│ 
│ 
│   with data.external.example,
│   on main.tf line 21, in data "external" "example":
│   21: data "external" "example" {

在 terraform 之外执行时,python 代码运行得很好。请帮助解决问题,因为这为我未来的脚本/操作奠定了基础

未经过滤的 api 响应正文是:

{'count': 2,
 'value': [{'creator': {'_links': {'avatar': {'href': 'https://dev.azure.com/xxxx/_apis/GraphProfile/MemberAvatars/aad.xxxxx'}},
                        'descriptor': 'aad.xxxxxx',
                        'displayName': 'xxxxx',
                        'id': 'eb6383c7-bf62-6cec-9ae4-57dc29b68deb',
                        'imageUrl': 'https://dev.azure.com/xxxx/_api/_common/identityImage?id=xxxxx',
                        'uniqueName': 'xxxxx',
                        'url': 'https://spsprodweu1.vssps.visualstudio.com/xxxxx/_apis/Identities/xxxx'},
            'name': 'refs/heads/devops',
            'objectId': 'a750b8eb8e26a2e4b9910c10f29e6d55d8639d50',
            'url': 'https://dev.azure.com/xxxx/xxxxx/_apis/git/repositories/xxxxxx/refs?filter=heads%2Fdevops'},
           {'creator': {'_links': {'avatar': {'href': 'https://dev.azure.com/xxxx/_apis/GraphProfile/MemberAvatars/aad.xxxxx'}},
                        'descriptor': 'aad.xxxxx',
                        'displayName': 'xxxx',
                        'id': 'eb6383c7-bf62-6cec-9ae4-57dc29b68deb',
                        'imageUrl': 'https://dev.azure.com/xxxx/_api/_common/identityImage?id=xxxxx',
                        'uniqueName': 'xxxxx',
                        'url': 'https://spsprodweu1.vssps.visualstudio.com/xxxx/_apis/Identities/xxxx'},
            'name': 'refs/heads/main',
            'objectId': 'a2956c20d33541b337c01f7ddfd5315acc796dfe',
            'url': 'https://dev.azure.com/xxxx/xxxx/_apis/git/repositories/xxxx/refs?filter=heads%2Fmain'}]}
4

1 回答 1

0

谢谢@Marcin ...我实际上从响应正文中获得了 400 状态代码和乱码内容:

"b'\\xef\\xbb\\xbf{\"$id\":\"1\",\"innerException\":null,\"message\":\"A potentially dangerous Request.Path value was detected from the client (:).\",\"typeName\":\"System.Web.HttpException, System.Web\",\"typeKey\":\"HttpException\",\"errorCode\":0,\"eventId\":0}'"

requests 模块在通过 terraform 运行时无法按预期工作(虽然它像终端的魅力一样工作)

如果我直接尝试 json 响应(例如 r = requests.get(list_url, headers=headers).json()),那么我会收到错误

     r = requests.get(list_url, headers=headers).json()
   File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/models.py", line 900, in json
     return complexjson.loads(self.text, **kwargs)
   File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/__init__.py", line 335, in loads
     raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)",
 json.decoder.JSONDecodeError: Unexpected UTF-8 BOM (decode using utf-8-sig)

我确实尝试克服 BOM 编码错误,但没有成功,因为我认为请求模块首先没有给出正确的响应,甚至在尝试解码之前。

r = requests.get(list_url, headers=headers).json()
r_decoded = codecs.decode(r.content, 'utf-8-sig')
branch_id = r_decoded["value"][0]["objectId"]
于 2021-10-14T12:33:42.193 回答