如果在我们的 Azure 容器注册表中发生了新操作,我会努力将通知推送到我们的团队频道。
- Webhook 在另一个事件处理程序上工作
- 如果我将其推送到 MS Teams,我会收到回复:文本丢失
问题是:
如何在 Webhook 的有效负载中添加更多信息?我找不到任何文档
如果在我们的 Azure 容器注册表中发生了新操作,我会努力将通知推送到我们的团队频道。
问题是:
如何在 Webhook 的有效负载中添加更多信息?我找不到任何文档
@Matthias,谢谢您的提问。
如架构图所示,两个服务之间使用 Azure Functions 应用程序来转换从 ACR Webhook 接收到的负载。它也是自定义函数,它将调用 Microsoft Teams 来创建自定义消息。
要将消息发送到 Microsoft Teams,需要传入 Webhook。要创建和配置新的传入 Webhook,请导航到所需的团队并从选项菜单中选择连接器。
查找传入的 Webhook,然后添加它。添加后,必须配置传入 Webhook。使用官方 ACR 徽标进行演示,并将名称设置为“Azure Container Registry”。
在 Microsoft Teams 中配置传入 Webhook 连接器后,您必须将 Webhook URL 存储在 Azure Functions 应用程序中。同样,使用 Azure CLI 完成此操作:
# Variables
FUNCTION_APP_NAME=fnapp-acr-teams
RESOURCE_GROUP_NAME=rg-acr-teams
WEBHOOK_URL=<your webhook url provided by Microsoft Teams>
# Set appSettings on Azure Functions App
az functionapp config appsettings set \
-n $FUNCTION_APP_NAME \
-g $RESOURCE_GROUP_NAME \
--settings "ContainerRegistryTeams__TeamsWebhookUrl=$WEBHOOK_URL"
当涉及到 Azure Functions 时,我们使用了Azure Functions Core Tools ( ) 来完成所有工作。func
如果您更关注 UI 方面,请使用首选 IDE 或编辑器创建新的 Azure Functions 项目。
# Create a project dir
mkdir -p ~/projects/acr-teams-integration
cd ~/projects/acr-teams-integration
# Create an Azure Functions project
func init --worker-runtime dotnet
# Create a new function
func new -l csharp --template "Http Trigger" \
-n FnNotifyTeams -a function
若要在 Azure Functions 项目中使用 .NET 的依赖项注入 (DI) 和配置功能,必须安装以下 NuGet 包:
dotnet add package Microsoft.NET.Sdk.Functions
dotnet add package Microsoft.Azure.Functions.Extensions
dotnet add package Microsoft.Extensions.DependencyInjection
如果您想IOptions<T>
使用强类型 C# 类访问配置数据,请考虑添加FunctionsStartup
如下所示的自定义实现:
[assembly: FunctionsStartup(typeof(Thns.Functions.Startup))]
namespace Thns.Functions
{
public class Startup: FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddOptions<TeamsConfig>()
.Configure<IConfiguration>((settings, configuration) =>
{
configuration.GetSection("ContainerRegistryTeams")
.Bind(settings);
});
}
}
}
我们函数的配置非常简单。这只是 webhook URL。也就是说,这个TeamsConfig
类很简单:
public class TeamsConfig
{
public string TeamsWebhookUrl { get; set; }
}
您现在可以使用常规 DI 模式在请求期间获取配置数据:
public class FnNotifyTeams
{
public FnNotifyTeams(IOptions<TeamsConfig> options)
{
Config = options.Value;
}
protected TeamsConfig Config { get; }
// omitted
}
现在让我们基于HTTPTrigger实现我们的 Azure 函数。该功能负责:
验证来自 ACR 的传入请求
构建 Microsoft Teams 消息的有效负载
调用 Microsoft Teams webhook
[FunctionName("FnNotifyTeams")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "POST", Route = "images")] HttpRequest req, ILogger log)
{
string body = await new StreamReader(req.Body).ReadToEndAsync();
dynamic d = JsonConvert.DeserializeObject(body);
string action = d?.action;
if (action != "push" && action != "chart_push")
{
log.LogWarning($"Action {action} is not supported.");
return new BadRequestResult();
}
var metadata = ImageMetadata.FromPayload(d);
if(metadata == null)
{
log.LogWarning($"Received invalid request. Got {body}");
return new BadRequestResult();
}
var message = new {
Title = $"New Container Image published in ACR",
Text = $"`{metadata.Repository}:{metadata.Tag}` has been published at `{metadata.Registry}`. You can pull it now using: {Environment.NewLine}`docker pull {metadata.Registry}/{metadata.Repository}:{metadata.Tag}{Environment.NewLine}`"
};
var h = new HttpClient();
var content = new StringContent(JsonConvert.SerializeObject(message), Encoding.UTF8, "application/json");
var r = await h.PostAsync(Config.TeamsWebhookUrl, content);
if (r.IsSuccessStatusCode){
return new OkResult();
}
log.LogError($"Teams response -> {r.StatusCode}: {r.ReasonPhrase}");
return new StatusCodeResult(500);
}
前面的代码获取从 ACR 接收的原始有效负载,提取并验证基本元数据。假设所有必要的信息都可用,并且 ACR 由于 a push
orchart_push
动作而发出调用。在这种情况下,调用 Microsoft Teams 的请求负载将使用该HttpClient::PostAsync
方法构造和发送。
主要将入站消息验证封装到ImageMetadata
类中,如下所示:
public class ImageMetadata
{
public string Registry { get; private set; }
public string Repository { get; private set; }
public string Tag { get; private set; }
public static ImageMetadata FromPayload(dynamic d)
{
string repository = d?.target?.repository;
string tag = d?.target?.tag;
string registry = d?.request?.host;
if (string.IsNullOrWhiteSpace(repository) ||
string.IsNullOrWhiteSpace(tag) ||
string.IsNullOrWhiteSpace(registry))
{
return null;
}
return new ImageMetadata
{
Registry = registry,
Repository = repository,
Tag = tag,
};
}
}
立即将其发布到云端:
# Variables
FUNCTION_APP_NAME=fnapp-acr-teams
# go to the functions directory
cd projects/acr-teams-integration
# deploy the current code to Azure Functions app
func azure functionapp publish $FUNCTION_APP_NAME -b local
现在代码已部署到 Azure Functions 应用程序,您必须获取函数的 URL,包括用于身份验证的函数密钥。同样,您可以使用 func CLI 从命令行直接执行此操作:
# Variables
FUNCTION_APP_NAME=fnapp-acr-teams
# Grab function url with function key
func azure functionapp list-functions $FUNCTION_APP_NAME --show-keys
从输出中复制调用 URL。
最后但同样重要的是,我们必须在 ACR 中创建一个新的传出 webhook。此时,我们对通过 webhookpush
和从 ACR 公开的两个事件感兴趣chart_push
:
# Variables
FUNCTION_URL=<paste function app url including function-key>
ACR_NAME=acrteams2021
# create a webhook in ACR
az acr webhook create -n webhook-notify-teams \
-r $ACR_NAME \
--uri $FUNCTION_URL \
--actions push chart_push
您可以使用任何 Docker 映像或符合 OCI 的工件来测试集成。我们将在此处使用 alpine Linux 容器映像作为示例:
# Variables
ACR_NAME=acrteams2021
docker pull alpine:latest
docker tag alpine:latest $ACR_NAME.azurecr.io/alpine:0.0.1
# Login to ACR
az acr login -n $ACR_NAME
# Push the container image to ACR
docker push $ACR_NAME.azurecr.io/alpine:0.0.1
几秒钟后,您应该会在 Microsoft Teams 中看到一条消息。
参考:https ://www.thorsten-hans.com/send-microsoft-teams-message-oci-artifacts-azure-container-registry/