You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Terraform external数据源异常报错及函数密钥获取咨询

问题分析与解决方案

一、异常原因解析

1. 首次执行报错:"JSON输入意外结束"

脚本未输出任何合法JSON内容导致的。函数应用刚部署完成时,函数的密钥还未完成生成,脚本循环30次后仍未获取到有效密钥,最终没有输出任何JSON,Terraform解析空输出时触发该错误。

2. 第二次执行报错:"顶层值后出现无效字符'{' "

添加az login和订阅切换命令后,Azure CLI会输出登录验证、订阅切换的额外信息(比如登录成功的JSON响应、订阅切换提示文本),这些内容和脚本最终输出的密钥JSON混合在一起,导致整体输出不是单一的合法JSON对象。Terraform要求外部数据源的输出必须是唯一的顶层JSON对象,混杂的输出触发了解析错误。

3. 第三次执行无报错

第三次恢复原脚本时,函数应用已经完成部署流程,密钥已生成就绪,脚本能在循环内快速获取到密钥并输出合法JSON,Terraform可以正常解析,因此没有报错。

二、替代获取函数密钥的方案

方案1:使用AzureRM原生数据源(推荐)

从AzureRM Provider 3.x版本开始,支持直接通过数据源获取函数密钥,无需依赖外部脚本,稳定性和可靠性更高:

获取指定函数的密钥(对应你的httptrigger)

data "azurerm_function_app_function_keys" "httptrigger" {
  provider         = azurerm.sub-fits-55070-dev-01
  function_app_id  = module.function_app_zis.function_app_id
  function_name    = "httptrigger"
  depends_on       = [module.function_app_zis]
}

# 使用示例:data.azurerm_function_app_function_keys.httptrigger.default_key

获取函数应用主机级密钥(若需全局密钥)

data "azurerm_function_app_host_keys" "this" {
  provider        = azurerm.sub-fits-55070-dev-01
  function_app_id = module.function_app_zis.function_app_id
  depends_on      = [module.function_app_zis]
}

# 使用示例:data.azurerm_function_app_host_keys.this.default_function_key

方案2:优化现有Shell脚本(若必须保留脚本方式)

如果因特殊场景需要保留外部脚本,需解决输出纯净度和超时问题:

  • 屏蔽Azure CLI的所有无关输出,仅保留最终JSON
  • 增加超时后的错误输出,避免空输出
  • 从Terraform传递参数,避免脚本硬编码资源信息

优化后的脚本示例:

#!/bin/bash

# 接收Terraform传递的参数
APP_NAME="$1"
RESOURCE_GROUP="$2"
SUBSCRIPTION="$3"
FUNCTION_NAME="$4"

# 循环尝试获取密钥,屏蔽CLI无关输出
for i in {1..30}; do
    FUNCTION_KEY=$(az functionapp function keys list --subscription "$SUBSCRIPTION" --resource-group "$RESOURCE_GROUP" --name "$APP_NAME" --function-name "$FUNCTION_NAME" --query default --output tsv 2>/dev/null)
    if [ -n "$FUNCTION_KEY" ]; then
        echo "{\"function_key\": \"$FUNCTION_KEY\"}"
        exit 0
    fi
    sleep 2
done

# 超时后输出错误JSON,避免空输出
echo "{\"error\": \"超时未获取到函数密钥\"}"
exit 1

对应的Terraform external数据源修改:

data "external" "function_key" {
    program    = ["bash", "${path.module}/get_function_key.sh", module.function_app_zis.function_app_name, module.function_app_zis.resource_group_name, "sub-fits-55070-dev-01", "httptrigger"]
    count      = module.function_app_zis.function_app_name != "" ? 1 : 0
    depends_on = [module.function_app_zis]
}

三、总结

优先选择AzureRM原生数据源方案,完全基于Terraform生态,避免外部脚本的不确定性;若必须使用脚本,务必保证输出纯净且包含超时处理逻辑。

内容的提问来源于stack exchange,提问作者Odelys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 08:57:06