eventbridge.tf:

data "aws_subnet" "subnet_id_A" {
  filter {
    name   = "tag:aws:cloudformation:logical-id"
    values = ["PrivateSubnetA"]
  }
}

data "aws_subnet" "subnet_id_B" {
  filter {
    name   = "tag:aws:cloudformation:logical-id"
    values = ["PrivateSubnetB"]
  }
}

data "aws_subnet" "subnet_id_C" {
  filter {
    name   = "tag:aws:cloudformation:logical-id"
    values = ["PrivateSubnetC"]
  }
}


### Lambda Function
## Create Lambda Role
resource "aws_iam_role" "announcement-nodegroup-rollout" {
  name = "announcement-nodegroup-rollout"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}
##

## Create LogGroup
resource "aws_cloudwatch_log_group" "announcement-nodegroup-rollout" {
  name              = "/aws/lambda/announcement-nodegroup-rollout"
  retention_in_days = 7
}

resource "aws_iam_policy" "announcement-nodegroup-rollout" {
  name        = "announcement-nodegroup-rollout"
  path        = "/"
  description = "IAM policy for logging from a lambda"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*",
      "Effect": "Allow"
    },
    {
        "Effect": "Allow",
        "Action": [
            "ec2:CreateNetworkInterface",
            "ec2:DeleteNetworkInterface",
            "ec2:DescribeNetworkInterfaces"
        ],
        "Resource": "*"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "announcement-nodegroup-rollout" {
  role       = aws_iam_role.announcement-nodegroup-rollout.name
  policy_arn = aws_iam_policy.announcement-nodegroup-rollout.arn
}
##

resource "aws_lambda_function" "announcement-nodegroup-rollout" {

  description      = "Send Nodegroup Rollout Announcement to Teams"
  filename         = data.archive_file.lambda_zip.output_path
  source_code_hash = data.archive_file.lambda_zip.output_base64sha256
  function_name    = "announcement-nodegroup-rollout"
  role             = aws_iam_role.announcement-nodegroup-rollout.arn
  timeout          = 180
  runtime          = "python3.12"
  handler          = "lambda_function.lambda_handler"
  memory_size      = 256

  vpc_config {

    subnet_ids         = [data.aws_subnet.subnet_id_A.id, data.aws_subnet.subnet_id_B.id, data.aws_subnet.subnet_id_C.id]
    security_group_ids = lookup(var.security_group_ids, var.stage)
  }

  environment {
    variables = {
      stage       = var.stage
      webhook_url = var.webhook_url
    }
  }

  tags = {
    Function        = "announcement-nodegroup-rollout"
    Customer        = "os/tvnow/systems"
    CustomerProject = "r5s-announcements"
  }
}

data "archive_file" "lambda_zip" {
  type        = "zip"
  source_dir  = "${path.module}/lambda-nodegroup-rollout-source/package"
  output_path = "${path.module}/lambda-nodegroup-rollout-source/package/lambda_function.zip"
}


###
resource "aws_lambda_permission" "announcement-nodegroup-rollout" {
  statement_id  = "AllowExecutionFromEventBridge"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.announcement-nodegroup-rollout.function_name
  principal     = "events.amazonaws.com"
  source_arn    = module.eventbridge.eventbridge_rule_arns["logs"]
}



module "eventbridge" {
  source  = "terraform-aws-modules/eventbridge/aws"
  version = "v2.3.0"

  create_bus = false

  rules = {
    logs = {
      name          = "announcement-UpdateNodegroupVersion"
      description   = "announcement-UpdateNodegroupVersion"
      event_pattern = jsonencode({ "detail" : { "eventName" : ["UpdateNodegroupVersion"] } })
    }
  }

  targets = {
    logs = [
      {
        name = "announcement-UpdateNodegroupVersion"
        arn  = aws_lambda_function.announcement-nodegroup-rollout.arn
      }
    ]
  }
}

lambda_function.py:

import urllib3
import json
import os

class TeamsWebhookException(Exception):
    """custom exception for failed webhook call"""
    pass


class ConnectorCard:
    def __init__(self, hookurl, http_timeout=60):
        self.http = urllib3.PoolManager()
        self.payload = {}
        self.hookurl = hookurl
        self.http_timeout = http_timeout

    def text(self, mtext):
        self.payload["text"] = mtext
        return self

    def send(self):
        headers = {"Content-Type":"application/json"}
        r = self.http.request(
                'POST',
                f'{self.hookurl}',
                body=json.dumps(self.payload).encode('utf-8'),
                headers=headers, timeout=self.http_timeout)
        if r.status == 200: 
            return True
        else:
            raise TeamsWebhookException(r.reason)

def lambda_handler(event, context):
        print(event['detail']['requestParameters']['nodegroupName'])
        
        if("r5s-default" not in event['detail']['requestParameters']['nodegroupName']):
            return {
                'statusCode': 200,
                'body': json.dumps('Announcing only default Node Group')
            }            
        stage = os.environ['stage']
        webhook_url = os.environ['webhook_url']
        f = open("announcement.tpl", "r").read().replace('###STAGE###', stage)
        myTeamsMessage = ConnectorCard(webhook_url)
        myTeamsMessage.text(f)
        myTeamsMessage.send()

announcement.tpl:

<h1><b>r5s Node Rollout gestarted</b></h1>
Soeben wurde auf r5s ###STAGE### ein Node Rollout gestarted (angestoßen durch Updates, Config Changes,...).<br />

Environment Varbales:

stage = dev|preprod|prod

webhook_url: <webhook url>

Schreibe einen Kommentar