Skip to content

Commit 90f5835

Browse files
authored
Merge pull request #45 from undp/containerize-v1
Containerize v1
2 parents 40595e8 + 84c0a66 commit 90f5835

File tree

240 files changed

+2669
-1415
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

240 files changed

+2669
-1415
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**/node_modules

.github/workflows/frontend-deployment.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
COUNTRY_NAME: 'Antarctic Region'
1616
COUNTRY_FLAG_URL: 'https://carbon-common-dev.s3.amazonaws.com/flag.png'
1717
COUNTRY_CODE: 'NG'
18+
MAPBOXGL_ACCESS_TOKEN: ${{ secrets.MAPBOXGL_ACCESS_TOKEN }}
1819
steps:
1920
- uses: actions/checkout@v3
2021
- name: Cache modules

.github/workflows/server-deployments.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
- develop
66
- main
77
paths:
8-
- lambda/**
8+
- backend/**
99
- libs/**
1010

1111
env:
@@ -24,7 +24,7 @@ jobs:
2424
fetch-depth: 0
2525
- id: check_file_changed
2626
run: |
27-
if [[ $(git diff --name-only HEAD^ HEAD | grep lambda/services/package.json) ]] || [[ $(git diff --name-only HEAD^ HEAD | grep libs/) ]]; then
27+
if [[ $(git diff --name-only HEAD^ HEAD | grep backend/services/package.json) ]] || [[ $(git diff --name-only HEAD^ HEAD | grep libs/) ]]; then
2828
echo "deps_changed=True" >> $GITHUB_OUTPUT
2929
else
3030
echo "deps_changed=False" >> $GITHUB_OUTPUT
@@ -54,29 +54,29 @@ jobs:
5454
run: yarn run build
5555
- name: Copy package.json
5656
if: ${{ needs.check_dependency_change.outputs.deps_changed == 'True' }}
57-
working-directory: ./lambda/layer/dependency_layer
57+
working-directory: ./backend/layer/dependency_layer
5858
run: cp ../../services/package.json ./ && cp ../../services/yarn.lock ./ && cp -r ../../../libs ../../
5959
- name: Install Dependency
6060
if: ${{ needs.check_dependency_change.outputs.deps_changed == 'True' }}
61-
working-directory: ./lambda/layer/dependency_layer
61+
working-directory: ./backend/layer/dependency_layer
6262
run: yarn install --production --frozen-lockfile
6363
# - name: Copy Dependency
6464
# if: ${{ needs.check_dependency_change.outputs.deps_changed == 'True' }}
65-
# working-directory: ./lambda/layer
65+
# working-directory: ./backend/layer
6666
# run: |
6767
# cp -r node_modules ./dependency_layer
6868
# ls
6969
- name: serverless deploy develop
7070
if: ${{ needs.check_dependency_change.outputs.deps_changed == 'True' && github.ref == 'refs/heads/develop'}}
7171
uses: serverless/github-action@v3.1
7272
with:
73-
args: -c "cd ./lambda/layer && serverless deploy --stage dev"
73+
args: -c "cd ./backend/layer && serverless deploy --stage dev"
7474
entrypoint: /bin/sh
7575
- name: serverless deploy main
7676
if: ${{ needs.check_dependency_change.outputs.deps_changed == 'True' && github.ref == 'refs/heads/main'}}
7777
uses: serverless/github-action@v3.1
7878
with:
79-
args: -c "cd ./lambda/layer && serverless deploy --stage prod"
79+
args: -c "cd ./backend/layer && serverless deploy --stage prod"
8080
entrypoint: /bin/sh
8181
deploy:
8282
name: deploy
@@ -89,7 +89,7 @@ jobs:
8989
with:
9090
node-version: ${{ matrix.node-version }}
9191
- name: Install Dependency
92-
working-directory: ./lambda/services
92+
working-directory: ./backend/services
9393
run: yarn install --frozen-lockfile
9494
- name: version
9595
run: |
@@ -106,13 +106,13 @@ jobs:
106106
if: github.ref == 'refs/heads/develop'
107107
uses: serverless/github-action@v3.1
108108
with:
109-
args: -c "cd ./lambda/services && serverless deploy --stage dev --param='depLayerArn1=${{ steps.layerArn.outputs.ARN1 }}' --param='depLayerArn2=${{ steps.layerArn.outputs.ARN2 }}'"
109+
args: -c "cd ./backend/services && serverless deploy --stage dev --param='depLayerArn1=${{ steps.layerArn.outputs.ARN1 }}' --param='depLayerArn2=${{ steps.layerArn.outputs.ARN2 }}'"
110110
entrypoint: /bin/sh
111111
- name: serverless deploy main
112112
if: github.ref == 'refs/heads/main'
113113
uses: serverless/github-action@v3.1
114114
with:
115-
args: -c "cd ./lambda/services && serverless deploy --stage prod"
115+
args: -c "cd ./backend/services && serverless deploy --stage prod"
116116
entrypoint: /bin/sh
117117

118118
# automated-api-tests:

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
**/.serverless/
33
**/dist/
44
**/.build/
5-
lambda/services/.env.local
5+
backend/services/.env.local
66
**/yarn-error.log
77
**/coverage
88
.env.local
9+
./data/*
10+
!./data/README.md

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"name": "Launch Serverless",
99
"request": "launch",
1010
"type": "pwa-node",
11-
"cwd": "${workspaceFolder}/lambda/services/",
11+
"cwd": "${workspaceFolder}/backend/services/",
1212
"program": "/usr/local/bin/serverless",
1313
"args": [
1414
"offline",

README.md

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* [Standards](#standards)
44
* [Architecture](#architecture)
55
* [Project Structure](#structure)
6+
* [Run as Containers](#container)
67
* [Run Services Locally](#local)
78
* [Run Services on Cloud](#cloud)
89
* [User Onboarding](#user)
@@ -34,13 +35,12 @@ https://digitalprinciples.org/
3435

3536
<a name="architecture"></a>
3637
## System Architecture
37-
UNDP Carbon Registry is based on service oriented architecture (SOA). It can be ported and hosted on any Function As A Service (FaaS) stack.
38-
![alt text](./documention/imgs/System%20Architecture.svg)
38+
UNDP Carbon Registry is based on service oriented architecture (SOA). Following diagram visualize the basic components in the system.
3939

40-
As per the above diagram, system contains 4 main services.
40+
![alt text](./documention/imgs/System%20Architecture.svg)
4141

4242
<a name="services"></a>
43-
### **Services**
43+
### **System Services**
4444
#### *National Service*
4545

4646
Authenticate, Validate and Accept user (Government, Programme Developer/Certifier) API requests related to the following functionalities,
@@ -58,20 +58,42 @@ Uses the Carbon Credit Calculator and Serial Number Generator node modules to es
5858
Uses Ledger interface to persist programme and credit life cycles.
5959

6060
#### *Analytics Service*
61-
Serve all the system analytics. Generate all the statistic using the operational database.
61+
Serve all the system analytics. Generate all the statistics using the operational database.
6262
Horizontally scalable.
6363

6464
#### *Replicator Service*
65-
Replicate ledger database new items to a operational database asynchronously. During the replication process it injects additional query information to the data.
66-
The current setup uses AWS QLDB as the ledger database. When it creates or updates data, the change is added to a AWS Kinesis Data Stream and the Replicator service consumes the stream.
65+
Asynchronously replicate ledger database events in to the operational database. During the replication process it injects additional information to the data for query purposes (Eg: Location information).
66+
Currently implemented for QLDB and PostgresSQL ledgers. By implementing [replicator interface](./backend/services/src/ledger-replicator/replicator-interface.service.ts) can support more ledger replicators.
67+
Replicator select based on the `LEDGER_TYPE` environment variable. Support types `QLDB`, `PGSQL(Default)`.
68+
69+
### **Deployment**
70+
System services can deploy in 2 ways.
71+
- **As a Container** - Each service boundary containerized in to a docker container and can deploy on any container orchestration service. [Please refer Docker Compose file](./docker-compose.yml)
72+
- **As a Function** - Each service boundary packaged as a function (Serverless) and host on any Function As A Service (FaaS) stack. [Please refer Serverless configuration file](./backend/services/serverless.yml)
73+
74+
75+
### **External Service Providers**
76+
All the external services access through a generic interface. It will decouple the system implementation from the external services and enable extendability to multiple services.
77+
78+
**Geo Location Service**
6779

68-
#### *Operational Service*
69-
Service that use to do following system operations,
70-
1. Data migrations.
71-
2. User data creation and update.
72-
3. Resource creation.
80+
Currently implemented for 2 options.
81+
1. File based approach. User has to manually add the regions with the geo coordinates. [Sample File](./backend/services/regions.csv). To apply new file changes, replicator service needs to restart.
82+
2. [Mapbox](https://mapbox.com). Dynamically query geo coordinates from the Mapbox API.
7383

74-
Internal service. Cannot be invoked by external sources.
84+
Can add more options by implementing [location interface](./backend/services/src/shared/location/location.interface.ts)
85+
86+
Change by environment variable `LOCATION_SERVICE`. Supported types `MAPBOX`, `FILE(Default)`
87+
88+
**File Service**
89+
90+
Implemented 2 options for static file hosting.
91+
1. NestJS static file hosting using the local storage and container volumes.
92+
2. AWS S3 file storage.
93+
94+
Can add more options by implementing [file handler interface](./backend/services/src/shared/file-handler/filehandler.interface.ts)
95+
96+
Change by environment variable `FILE_SERVICE`. Supported types `S3`, `LOCAL(Default)`
7597

7698
### **Database Architecture**
7799
Primary/secondary database architecture used to store carbon programme and account balances.
@@ -91,8 +113,9 @@ Operational Database is the secondary database. Eventually replicated to this fr
91113

92114
**Ledger Database Interface**
93115

94-
This enables the capability to add any blockchain or ledger database support to the carbon registry without functionality module changes. Currently the production system interface is implemented for AWS QLDB. For testing purposes the interface is implemented for PostgresSQL as well.
116+
This enables the capability to add any blockchain or ledger database support to the carbon registry without functionality module changes. Currently implemented for PostgresSQL and AWS QLDB.
95117

118+
**PostgresSQL Ledger Implementation** storage all the carbon programme and credit events in a separate event database with the sequence number. Support all the ledger functionalities except immutability.
96119

97120

98121
Single database approach used for user and company management.
@@ -106,7 +129,7 @@ Carbon Registry contains 3 ledger tables.
106129

107130
The below diagram demonstrates the the ledger behavior of programme create, authorise, issue and transfer processes. Blue color document icon denotes a single data block in a ledger.
108131

109-
![alt text](./documention/imgs/Ledger.png)
132+
![alt text](./documention/imgs/Ledger.svg)
110133

111134
### **Authentication**
112135
- JWT Authentication - All endpoints based on role permissions.
@@ -118,13 +141,11 @@ The below diagram demonstrates the the ledger behavior of programme create, auth
118141
.
119142
├── .github # CI/CD [Github Actions files]
120143
├── deployment # Declarative configuration files for initial resource creation and setup [AWS Cloudformation]
121-
├── lambda # System service implementation [NestJS applications, Serverless + AWS Lambda]
122-
├── layer # Service dependency layer [AWS Lambda Layers]
123-
├── serverless.yml # Service dependency layer deployment scripts [ Serverless + AWS Lambda Layer]
124-
├── services # Services implementation [AWS lambda - NestJS application]
144+
├── backend # System service implementation
145+
├── services # Services implementation [NestJS application]
125146
├── src
126147
├── national-api # National API [NestJS module]
127-
├── stats-api # Statistic API [NestJS module]
148+
├── stats-api # Statistics API [NestJS module]
128149
├── ledger-replicator # Blockchain Database data replicator [QLDB to Postgres]
129150
├── shared # Shared resources [NestJS module]
130151
├── serverless.yml # Service deployment scripts [Serverless + AWS Lambda]
@@ -133,8 +154,19 @@ The below diagram demonstrates the the ledger behavior of programme create, auth
133154
├── serial-number-gen # Implementation for the carbon programme serial number calculation [Node module + Typescript]
134155
├── web # System web frontend implementation [ReactJS]
135156
├── .gitignore
157+
├── docker-compose.yml # Docker container definitions
136158
└── README.md
137159

160+
<a name="container"></a>
161+
## Run Services As Containers
162+
- Update [docker compose file](./docker-compose.yml) env variables as required.
163+
- Run `docker-compose up -d`. This will build and start containers for following services,
164+
- PostgresDB container
165+
- National service
166+
- Analytics service
167+
- Replicator service
168+
- React web server with Nginx.
169+
138170
<a name="local"></a>
139171
## Run Services Locally
140172
- Setup postgreSQL locally and create a new database.
@@ -144,7 +176,7 @@ The below diagram demonstrates the the ledger behavior of programme create, auth
144176
- DB_USER (Default root)
145177
- DB_PASSWORD
146178
- DB_NAME (Default carbondbdev)
147-
- Move to folder `cd lambda/service`
179+
- Move to folder `cd backend/service`
148180
- Run `yarn run sls:install `
149181
- Initial user data setup `serverless invoke local --stage=local --function setup --data '{"rootEmail": "<Root user email>","systemCountryCode": "<System country Alpha 2 code>", "name": "<System country name>", "logoBase64": "<System country logo base64>"}'`
150182
- Start all the services by executing `sls offline --stage=local`

backend/services/.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**/node_modules
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ STAGE=dev
22
DB_HOST=carbondb.caslz2nn5xor.us-east-1.rds.amazonaws.com
33
DB_PORT=5432
44
DB_USER=root
5-
DB_PASSWORD=abcd1234
65
DB_NAME=carbondbdev
76
LOG_LEVEL=debug
87
carbon_dev_common=carbon-www-common
9-
SOURCE_EMAIL=nce.digital@undp.org
8+
SOURCE_EMAIL=nce.digital@undp.org
9+
IS_EMAIL_DISABLED=true
10+
LEDGER_TYPE=QLDB
11+
FILE_SERVICE=S3
12+
LOCATION_SERVICE=MAPBOX

0 commit comments

Comments
 (0)