エンジニャーリング

技術ときどきネコ

codepipelineの承認をslack上で行う(その3)

その2までで、slackへの通知ができるようになった。その3ではslackから情報を受け取るところを作る。

4. ApiGatewayとpostのlambdaを作る

まずはLambda

import json
import urllib.request
import boto3

def lambda_handler(event, context):
    client = boto3.client("codepipeline")
    msg = event["body"]  # httpでpostされたpayloadの格納

    if not msg:
        return {
            'statusCode': 403,
            'headers': {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*'
            },
            'body': "Forbidden"
        }

    msg_decode = urllib.parse.unquote(msg)
    msg_replace = msg_decode.replace("payload=", '')
    new_msg = json.loads(msg_replace)

    token = new_msg["actions"][0]["value"]
    approval_data = token.split(',')
    pipeline_name = approval_data[1]
    token = approval_data[0]

    stage_name = "approval-stage"
    action_name = "approval-action"

    if new_msg["actions"][0]["name"] == "ok":
        client.put_approval_result(
            pipelineName=pipeline_name,
            stageName=stage_name,
            result={
                'summary': 'Approval',
                'status': 'Approved',
            },
            token=token,
            actionName=action_name
        )

        return {
            'statusCode': 200,
            'headers': {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*'
            },
            'body': "```承認されました```"
        }

    else:
        client.put_approval_result(
            pipelineName=pipeline_name,
            stageName=stage_name,
            result={
                'summary': 'Rejected',
                'status': 'Rejected',
            },
            token=token,
            actionName=action_name
        )

        return {
            'statusCode': 200,
            'headers': {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*'
            },
            'body': "```却下されました```"
        }

Lambdaのデプロイは2.のやり方と一緒。 APIGatewayとの繋ぎはこのような雰囲気で。

## API Gateway
resource "aws_api_gateway_rest_api" "api" {
  name = "${local.name}-rest_api-${local.environment}"

  endpoint_configuration {
    types = ["REGIONAL"]
  }
}

# /approval-api
resource "aws_api_gateway_resource" "approval" {
  path_part   = "approval"
  parent_id   = aws_api_gateway_rest_api.api.root_resource_id
  rest_api_id = aws_api_gateway_rest_api.api.id
}

resource "aws_api_gateway_method" "approval_method" {
  rest_api_id   = aws_api_gateway_rest_api.api.id
  resource_id   = aws_api_gateway_resource.approval.id
  http_method   = "POST"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "approval_integration" {
  rest_api_id             = aws_api_gateway_rest_api.api.id
  resource_id             = aws_api_gateway_resource.approval.id
  http_method             = aws_api_gateway_method.approval_method.http_method
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = aws_lambda_function.handler.invoke_arn
}

# Lambda
resource "aws_lambda_permission" "apigw_lambda" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.handler.function_name
  principal     = "apigateway.amazonaws.com"

  # More: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-control-access-using-iam-policies-to-invoke-api.html
  source_arn = "arn:aws:execute-api:${local.region}:${data.aws_caller_identity.self.account_id}:${aws_api_gateway_rest_api.api.id}/*/${aws_api_gateway_method.approval_method.http_method}*/*"
}

resource "aws_api_gateway_deployment" "default" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  stage_name  = aws_api_gateway_stage.default.stage_name

  triggers = {
    redeployment = sha1(jsonencode(aws_api_gateway_rest_api.api.body))
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_api_gateway_stage" "default" {
  deployment_id = aws_api_gateway_deployment.dummy.id
  rest_api_id   = aws_api_gateway_rest_api.api.id
  stage_name    = "v1"
  xray_tracing_enabled = true
}

slackからの結果を受け取るAPIが作成できた。

5. ApiGatewayを呼び出すURLをslackアプリにセットする

このAPIをslackアプリへセットする 左メニューの Interactivity & Shortcuts でURLを設定する。

f:id:taiyakikuroann:20211020230109p:plain

slackでの更新の準備ができた

(その4へ続く)