Skip to content

Commit

Permalink
Merge pull request #25 from axelarnetwork/feat/dockerize-build
Browse files Browse the repository at this point in the history
feat: dockerize lambda deploy
  • Loading branch information
nrsirapop authored Apr 30, 2024
2 parents 4ec57e9 + 0513206 commit ff4c49f
Show file tree
Hide file tree
Showing 9 changed files with 363 additions and 125 deletions.
10 changes: 10 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform
.gitignore
README.md
LICENSE
yarn.lock
.env.example
.env
.git
test
node_modules
61 changes: 61 additions & 0 deletions .github/workflows/build-latest-docker-image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Build and push latest docker image

on:
push:
branches:
- main
workflow_dispatch:
jobs:
build-and-push-latest-docker-image:
strategy:
matrix:
os:
- ubuntu-20.04
runs-on: ${{ matrix.os }}
permissions:
id-token: write
contents: read
env:
REPOSITORY: axelarscan-api
IMAGE_TAG: ${{ github.sha }}
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: fetch tags
run: |
git fetch --unshallow
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/ghwf-${{ github.event.repository.name }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

- name: check if an image already build on same commit hash
id: image-tag-check
run: |
app_version="v$(jq -r .version package.json)"
if [ ${{ github.ref }} != 'refs/heads/main' ]; then
app_version="${app_version}-dev_${GITHUB_RUN_NUMBER}.${GITHUB_RUN_ATTEMPT}"
fi
image_tag_exists=$(aws ecr batch-get-image --repository-name ${REPOSITORY} --image-ids "imageTag=${app_version}" | jq '.images | length')
echo "image_tag_exists=${image_tag_exists}" >> $GITHUB_OUTPUT
echo "IMAGE_TAG=${app_version}" >> $GITHUB_ENV
- name: Build docker image
if: steps.image-tag-check.outputs.image_tag_exists == 0
run: |
docker build --platform linux/amd64 -t axelarscan/axelarscan-api .
- name: Push to ECR
if: steps.image-tag-check.outputs.image_tag_exists == 0
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
docker image tag axelarscan/axelarscan-api "${ECR_REGISTRY}/${REPOSITORY}:${IMAGE_TAG}"
docker push "${ECR_REGISTRY}/${REPOSITORY}:${IMAGE_TAG}"
12 changes: 12 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM public.ecr.aws/lambda/nodejs:20

COPY --from=public.ecr.aws/datadog/lambda-extension:55 /opt/extensions/ /opt/extensions

COPY . ${LAMBDA_TASK_ROOT}

RUN npm install yarn --global
RUN npm install datadog-lambda-js dd-trace

RUN yarn

CMD [ "index.handler" ]
125 changes: 84 additions & 41 deletions terraform/mainnet/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ provider "aws" {
}
}

provider "archive" {}

locals {
url_subpath_api_mapping = "api" # map apigw to url subpath /api from aws_api_gateway_domain_name
}
Expand All @@ -34,55 +32,92 @@ data "aws_api_gateway_domain_name" "mainnet" {
domain_name = "api.axelarscan.io"
}

data "archive_file" "zip" {
type = "zip"
source_dir = "../../"
excludes = ["terraform", ".gitignore", "README.md", "LICENSE", "yarn.lock", ".env.example", ".env", "test"]
output_path = "${var.package_name}.zip"
}

data "aws_iam_policy_document" "policy" {
statement {
sid = ""
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
identifiers = ["lambda.amazonaws.com"]
type = "Service"
resource "aws_iam_role" "lambda_role" {
name = "${var.package_name}-${var.environment}-role"
assume_role_policy = jsonencode(
{
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
},
]
Version = "2012-10-17"
}
)

inline_policy {
name = "secret_manager_policy"
policy = jsonencode(
{
Statement = [
{
Action = [
"secretsmanager:GetSecretValue",
]
Effect = "Allow"
Resource = "*"
},
]
Version = "2012-10-17"
}
)
}
}

data "aws_iam_role" "role" {
name = var.iam_role
}

resource "aws_iam_policy_attachment" "attachment" {
name = "${var.project_name}-attachment"
roles = [data.aws_iam_role.role.name]
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
inline_policy {
name = "lambda_execution_policy"
policy = jsonencode(
{
Statement = [
{
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
Effect = "Deny"
Resource = "*"
},
]
Version = "2012-10-17"
}
)
}
}

resource "aws_lambda_function" "function" {
function_name = "${var.package_name}-${var.environment}"
filename = data.archive_file.zip.output_path
source_code_hash = data.archive_file.zip.output_base64sha256
role = data.aws_iam_role.role.arn
handler = "index.handler"
runtime = "nodejs20.x"
timeout = 840
memory_size = 512
publish = true
function_name = "${var.package_name}-${var.environment}"
package_type = "Image"
image_uri = "${var.aws_account}.dkr.ecr.us-east-2.amazonaws.com/axelarscan-api:v${var.app_version}"
role = aws_iam_role.lambda_role.arn
timeout = 840
memory_size = 512
publish = true
environment {
variables = {
NODE_NO_WARNINGS = 1
ENVIRONMENT = var.environment
INDEXER_URL = var.indexer_url
INDEXER_USERNAME = var.indexer_username
INDEXER_PASSWORD = var.indexer_password
LOG_LEVEL = var.log_level
NODE_NO_WARNINGS = 1
ENVIRONMENT = var.environment
INDEXER_URL = var.indexer_url
INDEXER_USERNAME = var.indexer_username
INDEXER_PASSWORD = var.indexer_password
LOG_LEVEL = var.log_level
DD_LAMBDA_HANDLER = "index.handler"
DD_SITE = "datadoghq.com"
DD_API_KEY_SECRET_ARN = "arn:aws:secretsmanager:us-east-2:${var.aws_account}:secret:DdApiKeySecret-gJ9EIYVknJGu-HYZ3nM"
DD_TRACE_ENABLED = true
DD_ENV = var.environment
DD_SERVICE = "${var.package_name}-${var.environment}"
DD_VERSION = "${var.app_version}"
}
}
image_config {
command = [
"node_modules/datadog-lambda-js/dist/handler.handler",
]
}
kms_key_arn = ""
}

Expand All @@ -100,6 +135,14 @@ resource "aws_lambda_permission" "api" {
source_arn = "${aws_apigatewayv2_api.api.execution_arn}/*/*"
}

resource "aws_lambda_permission" "allow_cloudwatch" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.function.function_name
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.schedule.arn
}

resource "aws_apigatewayv2_api" "api" {
name = "${var.package_name}-${var.environment}-api"
protocol_type = "HTTP"
Expand Down
16 changes: 15 additions & 1 deletion terraform/mainnet/variables.tf.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ variable "aws_region" {
default = "us-east-2"
}

variable "aws_account" {
description = "AWS account id"
default = ""
}

variable "iam_role" {
description = "AWS IAM role"
default = "axelar-gmp-role-lambda"
Expand Down Expand Up @@ -41,4 +46,13 @@ variable "indexer_password" {
variable "log_level" {
description = "Log level"
default = "debug"
}
}

variable "app_version" {
description = "App version, same as docker image version"
default = "0.0.1"
validation {
error_message = "Must be valid semantic version. $Major.$Minor.$Patch"
condition = can(regex("^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", var.app_version))
}
}
Loading

0 comments on commit ff4c49f

Please sign in to comment.