Skip to content

Commit 5fd74ec

Browse files
committed
readme
1 parent e345fa2 commit 5fd74ec

2 files changed

Lines changed: 91 additions & 73 deletions

File tree

ErrorMessagesAPI.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
<DockerComposeProjectPath>docker-compose.dcproj</DockerComposeProjectPath>
99
</PropertyGroup>
1010

11+
<ItemGroup>
12+
<None Remove="k8s\api-secret.yml" />
13+
</ItemGroup>
14+
1115
<ItemGroup>
1216
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
1317
<PackageReference Include="MongoDB.Driver" Version="2.11.5" />

README.md

Lines changed: 87 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ The API is built using the *APS.NET core*, The main domain of this API is to pro
1414
# System Requirments:
1515

1616
All you need to run this API is a
17-
### Microsoft Visual Studio Community 2019
18-
### Docker Desktop to run Mongo Docker
19-
### Local Minikube installed
17+
+ Microsoft Visual Studio Community 2019
18+
+ Docker Desktop to run Mongo Docker
19+
+ Local Minikube installed
20+
+ Mongo Database image
2021

2122
# API Methods:
2223

@@ -124,20 +125,13 @@ Push the branch on github :
124125
$ git push origin [name_of_your_new_branch]
125126
```
126127

127-
# API Specification & Testing:
128-
In our API we used the [Swagger OpenAPI](https://swagger.io/) for documentation.
129-
**Swagger** is used together with a set of open-source software tools to design, build, document, and use RESTful web services.
130128

131-
In order to view the documentation of our API, you are supposed to run the project and go to this link:
132-
*https://localhost:5001/swagger*
133-
134-
<sub>Note: The port number may be different in your run.</sub>
135-
136-
![swagger](https://user-images.githubusercontent.com/55650010/100859067-773b1980-3497-11eb-86ee-260f1d881528.png)
137129

138130
# Context Diagram
139131
A system context diagram (SCD) in engineering is a high level view of a system that defines the boundary between the system, or part of a system, and its environment, showing the entities that interact with it.
140132
<img src="https://user-images.githubusercontent.com/55021862/100797714-402f1e80-342b-11eb-8e30-ab00c8866afe.png" width="800" height="600"></img>
133+
134+
---
141135
# 1 - Codebase
142136
*One codebase tracked in revision control, many deploys*. <br />
143137

@@ -148,7 +142,7 @@ In this repository two branches have been created:
148142
2. **dev** branch for the development.
149143
The source code has been tracked using the Github platform, and every team member contributes using pull requests
150144
mechanism.
151-
145+
---
152146
# 2 - Dependencies
153147
*Explicitly declare and isolate dependencies*. <br />
154148

@@ -169,6 +163,7 @@ Visual Studio can restore packages automatically when it builds a project, and y
169163
nuget restore
170164
```
171165
Package Restore first installs the direct dependencies of a project as needed, then installs any dependencies of those packages throughout the entire dependency graph.
166+
---
172167
# 3 - Configuration
173168
*Store config in the environment*. <br />
174169

@@ -177,27 +172,42 @@ According to our application, the database connection string is considered a con
177172

178173
### Environmental Variables for the Error Message API
179174

180-
In the Docker Compose file, under the environment, two variables are defined (MongoDB__URL, Mongo_DB), the values of the two varaibles are stored in the OS environmental Variables.
175+
In the Docker Compose file, under the environment, four variables are defined (Host, MONGO_ROOT_USER, MONGO_ROOT_PASSWORD, DB_Name), the values of the four varaibles are stored in the user environmental Variables.
181176

177+
#### ErrorMessage API
182178
```
183179
environment:
184-
MongoDB__URL: ${ConnectionString}
185-
Mongo_DB: ${DB_Name}
180+
Host: ${Host}
181+
username: ${MONGO_ROOT_USER}
182+
password: ${MONGO_ROOT_PASSWORD}
183+
database: ${DB_Name}
186184
```
187-
Besides, the Mongo database credentials are stored in the docker compose file such as the following:
185+
The four env. variables are read in code to consturct the URL of the mongo database in the Class Name [MongoDbConfig.cs](https://github.com/eng-aomar/ErrorMessagesAPI/blob/master/Config/MongoDbConfig.cs)
186+
Besides, the Mongo database and the mongo express credentials are stored in the docker compose file such as the following:
187+
#### Mongo Env Varaibles
188188
```
189189
environment:
190190
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER}
191191
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD}
192192
```
193+
#### Mongo Express Env Varaibles
194+
```
195+
environment:
196+
ME_CONFIG_MONGODB_ADMINUSERNAME: ${MONGO_ROOT_USER}
197+
ME_CONFIG_MONGODB_ADMINPASSWORD: ${MONGO_ROOT_PASSWORD}
198+
```
199+
200+
In K8s, the configeration is satisied by using secert file to store the base64 encrypted passwords [Mongo-Sercert](https://github.com/eng-aomar/ErrorMessagesAPI/blob/master/k8s/mongo-secret.yml)
201+
202+
---
193203
# 4 - Backing services
194204
*Treat backing services as attached resources*. <br />
195205

196206
Anything external to a service is treated as an attached resource, including other services. In general, backing services are those that our application consumes over the network as part of its normal process.
197207
In our case, MongoDB is considered a backing service, that can be accessed using the credentials stored in the config file (see factor #3).
198208
Applying this factor ensures that every service is completely portable and loosely coupled to the other resources in the system. Strict separation increases flexibility during development, developers only need to run the services they are modifying, not others. A database (Mongo DB) should be referenced by a simple endpoint (URL) and credentials, if necessary.
199209

200-
210+
---
201211
# 5 - Build / Release / Run
202212
*Strictly separate build and run stages*. <br />
203213

@@ -207,6 +217,8 @@ In order to transform our codebase to a deploy, we should pass 3 stages: </br>
207217
2- *Release stage*, where we combines the build produced in the previous stage, with the deploy config. Therefore, ready to be executed. Note that each release must have a unique ID, and using the release management tools we can rollback to previous releases. </br>
208218
3- *Run stage*, where we run the application in the execution environment.</br>
209219

220+
The Whole pipline is automated using GitHub Actios By Buliding a [continous integration](https://github.com/eng-aomar/ErrorMessagesAPI/blob/master/.github/workflows/CI.yml), and a [continous delivery](https://github.com/eng-aomar/ErrorMessagesAPI/blob/master/.github/workflows/CD.yml) for our API.
221+
210222
A release is deployed on the execution environment and must be immutable.
211223

212224
## What does that mean for our application ?
@@ -304,8 +316,10 @@ services:
304316
context: .
305317
dockerfile: Dockerfile
306318
environment:
307-
MongoDB__URL: ${ConnectionString}
308-
Mongo_DB: ${DB_Name}
319+
Host: ${Host}
320+
username: ${MONGO_ROOT_USER}
321+
password: ${MONGO_ROOT_PASSWORD}
322+
database: ${DB_Name}
309323
depends_on:
310324
- mongo
311325
networks:
@@ -319,9 +333,11 @@ services:
319333
environment:
320334
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER}
321335
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD}
336+
MONGO_INITDB_DATABASE: ${DB_Name}
322337
volumes:
323338
- mongo-data:/data/db
324-
#- ./mongo/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
339+
- ./initmongo.js:/docker-entrypoint-initdb.d/initmongo.js:ro
340+
325341
networks:
326342
- error-messgeapi-network
327343
@@ -330,7 +346,10 @@ services:
330346
container_name: mongo-express
331347
restart: always
332348
ports:
333-
- 8081:8081
349+
- '8081:8081'
350+
environment:
351+
ME_CONFIG_MONGODB_ADMINUSERNAME: ${MONGO_ROOT_USER}
352+
ME_CONFIG_MONGODB_ADMINPASSWORD: ${MONGO_ROOT_PASSWORD}
334353
depends_on:
335354
- mongo
336355
networks:
@@ -342,6 +361,7 @@ networks:
342361
error-messgeapi-network:
343362
driver: bridge
344363
```
364+
345365
In the Dockor-Compose we connect three images ( MessagAPI, Mongo, Mongo-express). Docker compose creat the defualt network between the images. Regarding the mongo image, we define the mongo-data volume locally inside the conatiner to presist the data. The Mongo-express is used to provide a simple interface to the mongo database. Mongo-express can be accessed using the following url (http://localhost:8081/). By defualt mongo database has alreday three pre-defined databases as the picture shows. We add messagedb database and Message collection to it.
346366
![mongo-express](https://user-images.githubusercontent.com/55650010/100858792-1c092700-3497-11eb-9e8e-a9f280afb10c.png)
347367

@@ -449,63 +469,26 @@ minikube dashboard
449469
```
450470
Now we can interact with our cluster using the **"Kubectl"**
451471

452-
### Deploy Conatiner to K8s:
453-
To deploy to k8s, we created a service and a depolyment configration yml file.
454-
455-
```
456-
apiVersion: v1
457-
kind: Service
458-
metadata:
459-
name: errormessage-api-service
460-
namespace: default
461-
spec:
462-
selector:
463-
app: error-messagepi-pod
464-
ports:
465-
- protocol: TCP
466-
port: 8080
467-
targetPort: 80
468-
type: LoadBalancer
472+
### Deploy Conatiners to K8s:
469473

470-
---
471-
apiVersion: apps/v1
472-
kind: Deployment
473-
metadata:
474-
name: errormessage-api-deployment
475-
namespace: default
476-
labels:
477-
app: error-messagepi-pod
478-
spec:
479-
replicas: 2
480-
selector:
481-
matchLabels:
482-
app: error-messagepi-pod
483-
template:
484-
metadata:
485-
labels:
486-
app: error-messagepi-pod
487-
spec:
488-
containers:
489-
- name: errormessageapi-container
490-
image: sradockerization/errormessageapi:latest
491-
imagePullPolicy: IfNotPresent
492-
resources:
493-
requests:
494-
cpu: 100m
495-
memory: 128Mi
496-
limits:
497-
cpu: 500m
498-
memory: 128Mi
499-
```
474+
To deploy to k8s, we created:
475+
- Four deployemts.
476+
- One configmap.
477+
- One secert file.
500478

479+
#### To show the yaml files please [click here](https://github.com/eng-aomar/ErrorMessagesAPI/tree/master/k8s).
501480

502481

503482
![image](https://user-images.githubusercontent.com/55650010/105977832-82c34f00-609a-11eb-9df8-24f9424bc07d.png)
504483

505-
To deploy the image to kubernetes, the following command is used:
506-
484+
To deploy the image to kubernetes, the commands [found here](https://github.com/eng-aomar/ErrorMessagesAPI/blob/master/k8s/k8s-commands.md)
485+
are executed in order.
507486
```
508-
kubectl apply -f .\k8s\error_message_api_deployement.yml
487+
kubectl apply -f mongo-secret.yml
488+
kubectl apply -f mongo.yml
489+
kubectl apply -f mongo-configmap.yml
490+
kubectl apply -f mongo-express.yml
491+
kubectl apply -f error-message-api-deployment.yml
509492
```
510493

511494
The following are the service, deployment and pods of our deployed image
@@ -527,18 +510,26 @@ deployment.apps/errormessage-api-deployment 2/2 2 2 3
527510
NAME DESIRED CURRENT READY AGE
528511
replicaset.apps/errormessage-api-deployment-5cf9674f8f 2 2 2 23h
529512
```
513+
---
530514
# 6- Processes
531515
*Execute the app as one or more stateless processes*. <br />
532516
Every meaningful business application creates, modifies, or uses data. In IT, a synonym for data is state. An application service that creates or modifies persistent data is called **stateful component**. In general, database services are stateful component. On the other hand, application components that do not create or modify persistent data are called **stateless components**.
533517
Stateless components are *easier* and *simpler* to handle and can be easily scaled-up and down compared with stateful components. Moreover, they can easily restarted on a completely different node because they have no persistent data associated with them.
518+
519+
#### Error Messsage API is a statless application as we don't store data inside our API, we use backing services [mongo database] to store our data.
534520

521+
---
535522
# 7- Port Binding
536523
*Export services via port binding*. <br />
537524
This factor talks about exposing the application services to the outside world using port binding.
538525
In general, docker containers can connect to the outside world without further configuration, but the outside world cannot connect to Docker containers by default. To allow communication between different containers in the same network we need to publish our container on one or more ports, and this is done by the **expose command**.
539526
In our DockerFile, we put the **Expose 80** command (we can put any port number), this tells Docker that our container’s service can be connected to on port 80.
540527
**Note**: The ports are configured with the "HOST_PORT:CONTAINER_PORT" syntax.
541528

529+
#### In our API, Port binding is satisfied using both Docker-Compose file and K8S YAML (deployment, service) files, as the service of each application forwards the traffic to the specified port
530+
using Target port, that points to the container port.
531+
532+
---
542533
# 8- Concurrency
543534
*Scale out via the process model*. <br />
544535

@@ -557,12 +548,15 @@ For more details, you can click [here]: {https://pspdfkit.com/blog/2018/how-to-u
557548

558549
Moreover, Kubernetes also allows us to scale the stateless application at runtime by defining the **ReplicaSet**, where it automatically scale the number of pods with that number.
559550

551+
---
560552
# 9- Disposability
561553
*Maximize robustness with fast startup and graceful shutdown*. <br />
562554
The different instances of our application are disposable, which means that they can started or stopped at any moment. This actually facilitate the scalability and deployment for the application.
563-
This is achieved in out application when we use **volumes**, storing long-term persistent data outside the container (in an external-to-Docker database, in Docker volumes) means that we can desdtriy any container without affecting the user experienceز
555+
This is achieved in out application when we use **volumes**, storing long-term persistent data outside the container (in an external-to-Docker database, in Docker volumes) means that we can desdtriy any container without affecting the user experience.
564556

557+
Pods in K8S are considered stateless ephemeral objects, they can be stopped, started, and deleted gracefully, without the knowledge of the end-users.
565558

559+
---
566560
# 10- Dev/prod parity
567561
*Keep development, staging, and production as similar as possible.*
568562

@@ -576,12 +570,32 @@ What does that mean for our Application?
576570
WE use continuous deployment to minimize the gap between deveoplment and production, by pushing the docker image continously into docker hub on push and pull reguest of the
577571
master branch.
578572

573+
---
579574
# 11- Logs
580575
*Treat logs as event streams*. </br>
581576
Logs are the stream of aggregated, time-ordered events collected from the output streams of all **running processes and backing services.**
582577

583578
The ```docker logs [OPTIONS] CONTAINER_NAME``` command shows information logged by a running container.
584579
For more details you can read [this article] {https://docs.docker.com/engine/reference/commandline/logs/}
585580

581+
---
586582
# 12- Admin processes
587583
*Run admin/management tasks as one-off processes.*
584+
In our case we stored the TAML files for both kubernetes and docker-compose ready to deploy our apps in any envionment in the same repostory.
585+
You can find all needed YAML files in the following folder [k8s](https://github.com/eng-aomar/ErrorMessagesAPI/tree/master/k8s)
586+
587+
---
588+
# 13- Open API Spesification:
589+
590+
In our API we used the [Swagger OpenAPI](https://swagger.io/) for documentation.
591+
**Swagger** is used together with a set of open-source software tools to design, build, document, and use RESTful web services.
592+
593+
We integrate our dotnet cor api with swagger using the following code in [startup.cs](https://github.com/eng-aomar/ErrorMessagesAPI/blob/master/Startup.cs)
594+
595+
In order to view the documentation of our API, you are supposed to run the project and go to this link:
596+
*https://localhost:5001/swagger*
597+
598+
<sub>Note: The port number may be different in your run.</sub>
599+
600+
![swagger](https://user-images.githubusercontent.com/55650010/100859067-773b1980-3497-11eb-86ee-260f1d881528.png)
601+

0 commit comments

Comments
 (0)