Azure Automation Webhook如何返回VM关机自定义响应信息
核心机制说明
Azure Automation Webhook 默认采用异步触发模式:请求到达后服务端会立即创建Runbook作业,返回HTTP 202响应与作业ID,不会等待Runbook执行完毕。脚本中Write-Output写入的内容只会存入作业输出流,不会直接作为Webhook的HTTP响应返回给调用方,这是平台默认行为,不属于脚本语法错误。
第一步:调整Runbook脚本
首先修正原脚本的变量命名问题(原脚本覆盖了PowerShell内置自动变量$input,易引发运行时异常),同时补充作业ID获取、结果统一组装逻辑,调整后的完整脚本如下:
Param ( [Parameter (Mandatory = $false)] [object] $WebhookData ) # 初始化统一返回结构 $response = [ordered]@{ JobId = $null VmName = $null Message = $null Status = $null } if ($WebhookData) { $WebhookName = $WebHookData.WebhookName $WebhookHeaders = $WebhookData.RequestHeader $WebhookBody = $WebhookData.RequestBody # 替换原脚本的$input变量,避免覆盖PowerShell内置变量 $webhookRequestBody = ConvertFrom-Json -InputObject $WebhookData.RequestBody # 通过内置变量直接获取当前作业ID,无需额外调用接口 $response.JobId = $PSPrivateMetadata.JobId.Guid } # Azure登录逻辑 $connectionName = 'AzureRunAsConnection' try { $servicePrincipalConnection= Get-AutomationConnection -Name $connectionName Write-Output "Logging in to Azure..." Connect-AzAccount -ServicePrincipal -TenantId $servicePrincipalConnection.TenantId -ApplicationId $servicePrincipalConnection.ApplicationId -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint -WarningAction Ignore } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." $response.Status = "Failed" $response.Message = $ErrorMessage throw $ErrorMessage } else{ Write-Error -Message $_.Exception $response.Status = "Failed" $response.Message = $_.Exception.Message throw $_.Exception } } # 读取传入参数 $ResourceGroupName = $webhookRequestBody.ResourceGroupName $VmName = $webhookRequestBody.VmName $response.VmName = $VmName # 执行关机操作 try { Stop-AzVM -Name $VmName -ResourceGroupName $ResourceGroupName -Force -ErrorAction Stop $response.Status = "Succeeded" $response.Message = "VM $VmName in Resource Group $ResourceGroupName was stopped Successfully" } catch { $response.Status = "Failed" $response.Message = "Failed to stop VM: $($_.Exception.Message)" throw $_.Exception } finally { # 将组装好的结果序列化为JSON写入作业输出流 $response | ConvertTo-Json | Write-Output }
脚本调整点说明:
- 新增统一返回结构,固定存放作业ID、虚拟机名称、执行结果、状态四个字段
- 通过内置变量
$PSPrivateMetadata.JobId.Guid直接获取当前运行的作业ID- 修正原脚本覆盖PowerShell内置变量
$input的问题,避免运行时异常- 为关机操作增加异常捕获,避免关机失败时返回错误的成功提示
- 最终结果统一以JSON格式写入作业输出流,方便后续拉取解析
第二步:获取自定义响应内容的两种可选方案
原生Webhook的同步响应无法通过修改Runbook自定义,只能返回JobId,可根据自身场景选择以下方案获取预期内容:
方案1:调用方轮询作业结果(无额外资源成本)
调用Webhook拿到返回的JobId后,增加轮询逻辑等待作业执行完成,再拉取作业输出即可,PowerShell调用示例:
# 1. 调用Webhook触发关机 $webhookUri = "替换为你的Webhook完整URI" $requestBody = @{ ResourceGroupName = "替换为目标资源组名" VmName = "替换为目标虚拟机名" } | ConvertTo-Json $invokeResult = Invoke-WebRequest -Uri $webhookUri -Method Post -Body $requestBody -ContentType "application/json" # 提取默认返回的JobId $jobId = ($invokeResult.Content | ConvertFrom-Json).JobId # 2. 轮询作业状态直到执行结束 $automationAccountName = "替换为你的Automation账号名" $automationRgName = "替换为Automation账号所在资源组名" do { Start-Sleep -Seconds 5 $job = Get-AzAutomationJob -Id $jobId -AutomationAccountName $automationAccountName -ResourceGroupName $automationRgName } while ($job.Status -notin "Completed", "Failed", "Suspended", "Stopped") # 3. 拉取作业输出,即可获取VmName、执行提示、JobId三个核心字段 $jobOutput = Get-AzAutomationJobOutput -Id $jobId -AutomationAccountName $automationAccountName -ResourceGroupName $automationRgName -Stream Output $finalResult = $jobOutput.Summary | ConvertFrom-Json $finalResult
方案2:同步入口代理(适合需要即时返回响应的场景)
如果不想在调用方写轮询逻辑,可以给Automation账号开启系统托管标识并分配对应权限,在Webhook层前置Azure Function或者API Management作为代理,由代理负责触发Runbook、轮询作业结果,最终直接将组装好的自定义内容作为HTTP响应返回给调用方。
参考现象截图

截图中仅返回JobId的内容是Webhook的默认异步响应格式,无法直接通过修改Runbook脚本变更该默认同步响应的内容。
内容的提问来源于stack exchange,提问作者DSH
相关产品推荐
相关产品推荐

