• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

AWS ChatOps Without Lambda? Yes, You Can!

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
Hi, I'm Takashi Iwamoto (

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

), an AWS Community Builder (Cloud Operations).

When I looked for prior examples of building ChatOps on AWS, most of them used Lambda.

However, I had a hunch that we could get rid of Lambda by using the

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

feature of Amazon Q Developer in chat applications (formerly AWS Chatbot), which was announced in November 2023.

After trying it out, I was able to build a fairly practical architecture.

In this post, I'll walk you through how I built AWS ChatOps without Lambda.

Why Avoid Lambda


Before we dive in, let me touch on why I want to avoid Lambda.

In a word: "Because it makes operations easier."

If you don't use Lambda, you never have to worry about runtime end‑of‑life. The more ChatOps targets you have, the more the cost of those EOL updates will hurt.

Services Used & Overall Architecture


Here's what I actually built.

The main AWS services I used are these three:

  • Amazon EventBridge – event detection & routing
  • Amazon SNS – notification delivery
  • Amazon Q Developer in chat applications – Slack notifications & Custom Actions

And the overall architecture looks like this:


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



  1. An EventBridge rule detects the CodeDeploy deployment state‑change event.
  2. The event is transformed with an

    Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

    and routed to an SNS topic.
  3. The message is delivered to an Amazon Q Developer Slack channel.
  4. The notification message and Custom Action buttons appear in Slack.
  5. A user picks one of the Custom Actions.
  6. The corresponding CodeDeploy command is executed (e.g. continue-deployment, stop-deployment).
Creating & Associating Custom Actions


To show Custom Action buttons in chat apps like Slack, you first need to create the Custom Actions themselves.

There are two ways to define Custom Actions:


I chose the API method because I wanted to manage everything as IaC. If you create the action in the chat UI, it seems that the resource is owned by AWS and not created inside your own AWS account.

If you go the API route, you'll also need to associate the Custom Actions with the chat channel yourself.

The steps are:

  1. Call the

    Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

    API to create the action.
  2. Call the

    Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

    API to attach it to the chat channel.

Below is how I implemented it in Terraform. (It's a bit long, so I've collapsed it.)

Definition of Custom Actions

locals {
custom_actions = {
SwitchTasks = {
button_text = "? Switch task sets"
criteria = [
{
operator = "EQUALS"
value = "blue-green-deployment"
variable_name = "ActionGroup"
},
]
variables = {
"ActionGroup" = "event.metadata.additionalContext.ActionGroup"
"DeploymentId" = "event.metadata.additionalContext.DeploymentId"
"Region" = "event.metadata.additionalContext.Region"
}
command_text = "codedeploy continue-deployment --deployment-id $DeploymentId --region $Region --deployment-wait-type READY_WAIT"
}

RollbackDeployment = {
button_text = "? Rollback"
criteria = [
{
operator = "EQUALS"
value = "blue-green-deployment"
variable_name = "ActionGroup"
},
]
variables = {
"ActionGroup" = "event.metadata.additionalContext.ActionGroup"
"DeploymentId" = "event.metadata.additionalContext.DeploymentId"
"Region" = "event.metadata.additionalContext.Region"
}
command_text = "codedeploy stop-deployment --deployment-id $DeploymentId --region $Region --auto-rollback-enabled true"
}

TerminateOldTask = {
button_text = "? Terminate old task set"
criteria = [
{
operator = "EQUALS"
value = "blue-green-deployment"
variable_name = "ActionGroup"
},
]
variables = {
"ActionGroup" = "event.metadata.additionalContext.ActionGroup"
"DeploymentId" = "event.metadata.additionalContext.DeploymentId"
"Region" = "event.metadata.additionalContext.Region"
}
command_text = "codedeploy continue-deployment --deployment-id $DeploymentId --region $Region --deployment-wait-type TERMINATION_WAIT"
}
}
}

resource "awscc_chatbot_custom_action" "this" {
for_each = local.custom_actions

action_name = each.key
attachments = [
{
button_text = each.value.button_text
criteria = each.value.criteria
notification_type = "Custom"
variables = each.value.variables
},
]
definition = {
command_text = each.value.command_text
}
tags = [
for key, value in merge(data.aws_default_tags.this.tags, { "Name" = each.key }) : {
key = key
value = value
}
]
}

Associating the Custom Actions with the Chat Channel (implemented with null_resource)

# In this example we set custom_action_groups = ["blue-green-deployment"]
variable "custom_action_groups" {
description = "A list of Custom Action group names to associate specific AWS Chatbot actions with the specified Slack channel configuration."
type = list(string)
default = []
}

locals {
action_group_map = {
"blue-green-deployment" = ["SwitchTasks", "RollbackDeployment", "TerminateOldTask"]
}

selected_actions = distinct(flatten([
for group in var.custom_action_groups :
lookup(local.action_group_map, group, [])
]))

action_arns = {
for k, v in {
for action in local.selected_actions :
action => try(
one([
for id in data.awscc_chatbot_custom_actions.this.ids : id
if endswith(id, "/${action}")
]),
null
)
} : k => v if v != null
}
}

resource "null_resource" "associate_actions" {
for_each = local.action_arns

triggers = {
action_arn = each.value
chatbot_arn = aws_chatbot_slack_channel_configuration.this.chat_configuration_arn
}

provisioner "local-exec" {
command = "aws chatbot associate-to-configuration --resource ${self.triggers.action_arn} --chat-configuration ${self.triggers.chatbot_arn} --region us-west-2"
}

provisioner "local-exec" {
when = destroy
command = "aws chatbot disassociate-from-configuration --resource ${self.triggers.action_arn} --chat-configuration ${self.triggers.chatbot_arn} --region us-west-2"
}
}

EventBridge Rule

variable "sns_topic_arn" {
description = "The SNS topic to notify when the blue/green deployment is ready for validation."
type = string
nullable = false
}

variable "deployment_group_name" {
description = "The name of the deployment group targeted by ChatOps."
type = string
nullable = false
}

variable "green_url" {
description = "The URL for validating the green environment."
type = string
nullable = false
}

resource "aws_cloudwatch_event_rule" "this" {
description = null
event_bus_name = "default"
event_pattern = jsonencode(
{
detail = {
deploymentGroup = [
var.deployment_group_name,
]
state = [
"READY",
]
}
detail-type = [
"CodeDeploy Deployment State-change Notification",
]
source = [
"aws.codedeploy",
]
}
)
force_destroy = false
name = "${var.deployment_group_name}-deployment-ready"
name_prefix = null
role_arn = null
schedule_expression = null
state = "ENABLED"
tags = {
"Name" = "${var.deployment_group_name}-deployment-ready"
}
}

resource "aws_cloudwatch_event_target" "this" {
arn = var.sns_topic_arn
event_bus_name = "default"
force_destroy = false
input = null
input_path = null
role_arn = aws_iam_role.this.arn
rule = aws_cloudwatch_event_rule.this.name
target_id = "sns"

input_transformer {
input_paths = {
"account" = "$.account"
"deploymentGroup" = "$.detail.deploymentGroup"
"deploymentId" = "$.detail.deploymentId"
"region" = "$.region"
"time" = "$.time"
}
input_template = replace(replace(
jsonencode(
{
content = {
description = trimspace(
<<-EOT
*Deployment group:* <deploymentGroup>
*Deployment ID:* <deploymentId>
*Account:* <account>
*Region:* <region>
*Time:* <time>
EOT
)
nextSteps = [
"Check if the app works correctly at ${var.green_url}",
"If all looks good, switch task sets. If not, trigger a rollback",
"Once validated, terminate the original task set",
]
textType = "client-markdown"
title = ":large_blue_circle::large_green_circle: Deployment is now ready for validation"
}
metadata = {
additionalContext = {
ActionGroup = "blue-green-deployment"
DeploymentId = "<deploymentId>"
Region = "<region>"
}
enableCustomActions = true
}
source = "custom"
version = "1.0"
}
),
"\u003c", "<"), "\u003e", ">")
}
}

With this in place, Slack now shows the following notification, and the entire Blue/Green deployment can be operated using just the Custom Action buttons.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Remaining Challenge


As you can see, this solution works quite well, but one issue is that we can't control the order of the Custom Action buttons.

Sometimes they show up as "? Terminate old task set", "? Rollback", "? Switch task sets", in that order. The screenshot above just happened to be in the desired order.

If we could control that order, I'm sure this approach would be solid enough to become a go-to ChatOps pattern. I've already submitted a feature request to AWS Support, and I'm hopeful it will be addressed in the future.

Conclusion: ChatOps Without Lambda Is Possible


That was an example of ChatOps built with Amazon Q Developer in chat applications Custom Actions.

When you build it without Lambda, operations get easier. The unresolved button‑ordering issue remains, but if you can live with that, it's already perfectly usable.

I plan to expand our ChatOps coverage with this method, and I hope it inspires you to try it out yourself.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу