Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
windWingWalker committed Jul 28, 2022
0 parents commit 455537d
Show file tree
Hide file tree
Showing 33 changed files with 1,439 additions and 0 deletions.
46 changes: 46 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Local .terraform directories
**/.terraform/*

# .tfstate files
**/*.tfstate
**/*.tfstate.*

# Crash log files
**/crash.log

# Exclude all .tfvars files, which are likely to contain sentitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
#
**/*.tfvars

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
**/override.tf
**/override.tf.json
**/*_override.tf
**/*_override.tf.json

# Include override files you do wish to add to version control using negated pattern
#
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

# Ignore CLI configuration files
**/.terraformrc
**/terraform.rc
**/hello-world.zip
**/response.json

# Misc
**/.terraform.lock.hcl
**/__pycache__/
**/package/
**/export/
**/node_modules/
**/test.md
**/input.json
**/ibond/
674 changes: 674 additions & 0 deletions LICENSE.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Calculator
21 changes: 21 additions & 0 deletions iac/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.48.0"
}
}

required_version = "~> 1.0"
}

provider "aws" {
region = var.aws_region
}

module "api-gateway" {
source = "./modules/api-gateway"
project_name = var.project_name
}


60 changes: 60 additions & 0 deletions iac/modules/api-gateway/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
resource "aws_apigatewayv2_api" "default" {
name = "${var.project_name}-gateway"
protocol_type = "HTTP"
}

resource "aws_apigatewayv2_stage" "dev" {
api_id = aws_apigatewayv2_api.default.id

name = "dev"
auto_deploy = true

access_log_settings {
destination_arn = aws_cloudwatch_log_group.default.arn

format = jsonencode({
requestId = "$context.requestId"
sourceIp = "$context.identity.sourceIp"
requestTime = "$context.requestTime"
protocol = "$context.protocol"
httpMethod = "$context.httpMethod"
resourcePath = "$context.resourcePath"
routeKey = "$context.routeKey"
status = "$context.status"
responseLength = "$context.responseLength"
integrationErrorMessage = "$context.integrationErrorMessage"
}
)
}
}

resource "aws_apigatewayv2_stage" "prod" {
api_id = aws_apigatewayv2_api.default.id

name = "prod"
auto_deploy = false

access_log_settings {
destination_arn = aws_cloudwatch_log_group.default.arn

format = jsonencode({
requestId = "$context.requestId"
sourceIp = "$context.identity.sourceIp"
requestTime = "$context.requestTime"
protocol = "$context.protocol"
httpMethod = "$context.httpMethod"
resourcePath = "$context.resourcePath"
routeKey = "$context.routeKey"
status = "$context.status"
responseLength = "$context.responseLength"
integrationErrorMessage = "$context.integrationErrorMessage"
}
)
}
}

resource "aws_cloudwatch_log_group" "default" {
name = "/aws/api_gw/${aws_apigatewayv2_api.default.name}"

retention_in_days = 30
}
3 changes: 3 additions & 0 deletions iac/modules/api-gateway/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
variable "project_name" {
type = string
}
27 changes: 27 additions & 0 deletions iac/modules/api-route/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
data "aws_apigatewayv2_api" "default" {
api_id = var.api_id
}

resource "aws_apigatewayv2_integration" "default" {
api_id = var.api_id

integration_uri = var.lambda_function_invoke_arn
integration_type = "AWS_PROXY"
integration_method = "POST"
}

resource "aws_apigatewayv2_route" "default" {
api_id = var.api_id

route_key = "${var.http_method} ${var.resource_name}"
target = "integrations/${aws_apigatewayv2_integration.default.id}"
}

resource "aws_lambda_permission" "default" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = var.ms_name
principal = "apigateway.amazonaws.com"

source_arn = "${aws_apigatewayv2_api.default.execution_arn}/*/*"
}
19 changes: 19 additions & 0 deletions iac/modules/api-route/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
variable "api_id" {
type = string
}

variable "resource_name" {
type = string
}

variable "ms_name" {
type = string
}

variable "http_method" {
type = string
}

variable "lambda_function_invoke_arn" {
description = "Lambda's Arn for API Gateway to invoke lambda"
}
39 changes: 39 additions & 0 deletions iac/modules/lambda/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
data "aws_iam_role" "default" {
name = "lambda-admin"
}

resource "aws_ecr_repository" "default" {
name = var.ms_name
image_tag_mutability = "IMMUTABLE"

image_scanning_configuration {
scan_on_push = true
}
}

resource "aws_lambda_alias" "default" {
name = "dev"
function_name = aws_lambda_function.default.arn
function_version = aws_lambda_function.default.version
}

resource "aws_lambda_function" "default" {
# Neccessary
function_name = var.ms_name
package_type = "Image"
image_uri = "${aws_ecr_repository.default.repository_url}:${var.image_tag}"
role = data.aws_iam_role.default.arn
publish = true

# Optional
depends_on = [
aws_ecr_repository.default,
aws_cloudwatch_log_group.default
]
}

resource "aws_cloudwatch_log_group" "default" {
name = "/aws/lambda/${var.ms_name}"

retention_in_days = 30
}
3 changes: 3 additions & 0 deletions iac/modules/lambda/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "function_invoke_arn" {
value = aws_lambda_function.default.invoke_arn
}
7 changes: 7 additions & 0 deletions iac/modules/lambda/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
variable "ms_name" {
type = string
}

variable "image_tag" {
type = string
}
10 changes: 10 additions & 0 deletions iac/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
variable "aws_region" {
description = "AWS region for all resources."

type = string
default = "us-east-1"
}

variable "project_name" {
type = string
}
1 change: 1 addition & 0 deletions microservices/gathering-fee/.devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FROM python:3.8-buster
11 changes: 11 additions & 0 deletions microservices/gathering-fee/.devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "Gathering Fee Calculator",

"dockerComposeFile": [
"docker-compose.yml"
],

"service": "default",

"workspaceFolder": "/workspace"
}
22 changes: 22 additions & 0 deletions microservices/gathering-fee/.devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: "3.8"

services:
default:
build: .
volumes:
- ../:/workspace/:cached
- ../../../model/:/lib/model/
- ~/.aws/credentials:/root/.aws/credentials
- vscode-extension-python:/root/.vscode-server/extensions
command: /bin/sh -c "pip install --no-cache-dir -r /workspace/requirements.txt && while sleep 1000; do :; done;"
networks:
- default

volumes:
vscode-extension-python:
external: true

networks:
default:
external: true
name: development
11 changes: 11 additions & 0 deletions microservices/gathering-fee/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM public.ecr.aws/lambda/python:3.8

# Copy function code
WORKDIR ${LAMBDA_TASK_ROOT}
COPY src/ .
COPY ../../model/ /lib/model/
COPY requirements.txt .
RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "prod_main.lambda_handler" ]
57 changes: 57 additions & 0 deletions microservices/gathering-fee/Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
pipeline{
agent any
environment {
AWS_ACCESS_KEY_ID = credentials('aws_access_key_id')
AWS_SECRET_ACCESS_KEY = credentials('aws_secret_access_key')
AWS_ACCOUNT_ID = credentials('aws_account_id')

PROJECT_NAME = "calculator"
RESOURCE_NAME = "gathering-fee"
MS_NAME = "calculate-gathering-fee"
HTTP_METHOD = "POST"

TF_VAR_project_name = "${PROJECT_NAME}"
TF_VAR_resource_name = "${RESOURCE_NAME}"
TF_VAR_ms_name = "${MS_NAME}"
TF_VAR_http_method = "${HTTP_METHOD}"
TF_VAR_image_tag = "${env.BUILD_NUMBER}"
TF_VAR_api_id = "tbc"
}
tools {
terraform 'TerraformDefault'
}
options {
ansiColor('xterm')
}
stages{
stage('Build Image'){
steps{
sh 'ls -al'
dir("microservices/${MS_NAME}/"){
script{
image = docker.build("${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/${MS_NAME}:${TF_VAR_image_tag}")
}
}
}
}
stage('Push Image'){
steps{
script{
docker.withRegistry("https://${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com", "ecr:us-east-1:aws_credentials") {
image.push()
}
}
}
}
stage('Deploy'){
steps{
dir("microservices/${MS_NAME}/iac"){
sh 'terraform init -input=false'
sh 'terraform plan -out=tfplan -input=false'
sh 'terraform apply -input=false -auto-approve tfplan'
}
sh 'rm -rf dist/'
}
}
}
}
24 changes: 24 additions & 0 deletions microservices/gathering-fee/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Gathering Fee Calculator

## Background
When you hanging out with your friends, you may encounter a situation that someone pay the bills(resturants, party, etc) for everyone first, after fews days, you have no idea how much you should pay / receive because the bills were a complete mess.

## Program I/O
- Input: A 2D list in JSON format
- e.g. [["PersonA", 30, "PersonB"], ["PersonA", 20, "PersonC"], ["PersonD", 20, "PersonA"]...]
- ["PersonA", 30, "PersonB"] represents PersonA lends PersonB $30
- The data type of "PersonA" and "PersonB" must be str, 30 must be either int or float
- Output: Stdout showing each person's receivable, payable and net flow (receivable - payable)
- PersonA's receivable is: 30(PersonB) + 20(PersonC) = 50.0
PersonA's payable is: 20(PersonD) = 20.0
PersonA's net flow is: 50.0 - 20.0 = 30.0

## File Structure
- .devcontainer/: Settings of VSCode lcoal development with container
- .gitignore
- *_main.py: Main program
- people.py: a module
- person.py: a module
- transaction.py: a module
- Dockerfile: Used for creating container
- requirements.txt: Listing dependencies for container to install
Loading

0 comments on commit 455537d

Please sign in to comment.