Polyglot Sentences
Polyglot Sentences is a Go-based application designed to help users learn and master sentences in multiple languages. The app provides a wide range of sentence structures and vocabulary to facilitate language learning through practical and contextual examples.
Go Version
- The project uses Go version
1.22.5
Installation and Setup
To simplify the installation and setup process for developers, we have provided an install_service.sh
script. This script will:
- Check if Docker is installed, and if not, it will install Docker.
- Install Docker Compose if it is not already installed.
- Set up the environment file.
- Run Docker Compose to start the necessary containers.
- Wait for the PostgreSQL and Kong containers to be ready.
- Run the database migrations.
- Set up the services in the API Gateway.
- Set up the API Gateway.
Steps to Install and Run the Service
- Make the script executable:
chmod +x install_service.sh
./install_service.sh
Default admin user detail
- username(email):
john.doe@gmail.com
- password:
QWer123!@#
Project Architecture
The project is structured using the Hexagonal Architecture. Hereβs an overview of the directory structure:
πpolyglot-sentences/
βββ π.github/
βββ πcmd/
β βββ πapigateway/
β β βββ πmain.go
β βββ πauthserver/
β β βββ πmain.go
β βββ πmigration/
β β βββ πmain.go
β βββ πnotificationserver/
β β βββ πmain.go
β βββ πsetup/
β β βββ πsetup.go
β βββ πuserserver/
β βββ πmain.go
βββ πdeploy/
β βββ πDeployment.yml
β βββ πService.yml
βββ πdocker/
β βββ πalertmanager/
β βββ πelk/
β βββ πgrafana/
β βββ πkong/
β βββ πprometheus/
βββ πdocs/
β βββ πdocs.go
β βββ πswagger.json
β βββ πswagger.yaml
βββ πinternal/
β βββ πadapter/
β β βββ πconstant/
β β β βββ πmessages.go
β β βββ πemail/
β β β βββ πmock_sendgrid.go
β β β βββ πsendgrid.go
β β β βββ πsendgrid_test.go
β β βββ πgrpc/
β β β βββ πclient/
β β β β βββ πmock_user_client.go
β β β β βββ πuser_client.go
β β β βββ πproto/
β β β β βββ πuser/
β β β β βββ πuser.pb.go
β β β β βββ πuser.proto
β β β β βββ πuser_grpc.pb.go
β β β βββ πserver/
β β β βββ πuser_server.go
β β βββ πhttp/
β β β βββ πhandler/
β β β β βββ πhealth.go
β β β β βββ πstatus_code_mapping.go
β β β β βββ πuser.go
β β β βββ πmiddleware/
β β β β βββ πcustom_recovery.go
β β β βββ πpresenter/
β β β β βββ πbase.go
β β β β βββ πbase_test.go
β β β β βββ πuser.go
β β β β βββ πuser_test.go
β β β βββ πrequest/
β β β β βββ πbase.go
β β β β βββ πuser.go
β β β β βββ πuser_test.go
β β β βββ πroutes/
β β β β βββ πauth_router.go
β β β β βββ πrouter.go
β β β β βββ πswagger.go
β β β β βββ πuser_router.go
β β β βββ πvalidations/
β β β βββ πvalidator.go
β β β βββ πvalidator_test.go
β β βββ πmessagebroker/
β β β βββ πqueue.go
β β β βββ πrabbitmq.go
β β βββ πminio/
β β β βββ πclient.go
β β βββ πstorage/
β β βββ πpostgres/
β β β βββ πauthrepository/
β β β β βββ πaccess_control.go
β β β β βββ πmock_access_control.go
β β β β βββ πmock_permission.go
β β β β βββ πmock_role.go
β β β β βββ πmock_unit_of_work.go
β β β β βββ πpermission.go
β β β β βββ πrole.go
β β β β βββ πunit_of_work.go
β β β βββ πmigrations/
β β β β βββ π202404031147_create_users_table.down.sql
β β β β βββ π202404031147_create_users_table.up.sql
β β β βββ πtests/
β β β β βββ πaccess_control_test.go
β β β β βββ πpermission_test.go
β β β β βββ πrepositories_test.go
β β β β βββ πrole_test.go
β β β β βββ πuser_test.go
β β β βββ πuserrepository/
β β β β βββ πmock_unit_of_work.go
β β β β βββ πmock_user.go
β β β β βββ πunit_of_work.go
β β β β βββ πuser.go
β β β βββ πdb.go
β β βββ πredis/
β β βββ πauthrepository/
β β β βββ πauth.go
β β β βββ πmock_auth.go
β β β βββ πmock_otp.go
β β β βββ πmock_role.go
β β β βββ πotp.go
β β β βββ πrole.go
β β βββ πdb.go
β βββ πcore/
β βββ πconfig/
β β βββ πconfig.go
β βββ πconstant/
β β βββ πcache.go
β βββ πdomain/
β β βββ πaccess_control.go
β β βββ πbase.go
β β βββ πgrammer.go
β β βββ πlanguage.go
β β βββ πpermission.go
β β βββ πrole.go
β β βββ πsentence.go
β β βββ πuser.go
β βββ πevent/
β β βββ πauthevent/
β β βββ πsend_email_otp_queue.go
β β βββ πsend_reset_password_link_queue.go
β β βββ πsend_welcome_queue.go
β βββ πport/
β β βββ πaccess_control.go
β β βββ πaut.go
β β βββ πemail.go
β β βββ πevent.go
β β βββ πotp.go
β β βββ πpermission.go
β β βββ πrole.go
β β βββ πuser.go
β βββ πservice/
β β βββ πauthservice/
β β β βββ πjwt.go
β β βββ πroleservice/
β β β βββ πcache.go
β β β βββ πrole.go
β β βββ πuserservice/
β β βββ πuser.go
β βββ πviews/
β βββ πemail/
β βββ πauth
β β βββ πverify_email.html
β β βββ πwelcome.html
β βββ πbase.html
βββ πlogs/
β βββ πlogs-2024-05-21.log
βββ πpkg/
β βββ πclaim/
β β βββ πgin.go
β βββ πhelper/
β β βββ πauthenticate.go
β β βββ πauthenticate_bench_test.go
β β βββ πstring.go
β βββ πlogger/
β β βββ πconst.go
β β βββ πlogger.go
β βββ πmetrics/
β β βββ πcounters.go
β β βββ πhistograms.go
β βββ πoauth/
β β βββ πgoogle.go
β βββ πserviceerror/
β β βββ πerror_message.go
β β βββ πgrpc.go
β β βββ πservice_error.go
β βββ πtranslation/
β βββ πtrans.go
β βββ πlang/
β βββ πar.json
β βββ πen.json
β βββ πfa.json
βββ πproto/
β βββ πcommon/
β βββ πerror_details.pb.go
β βββ πerror_details.proto
βββ πgo.mod
βββ π.env
βββ πdocker-compose.yml
Profiling
To profile the application, we use the pprof
tool for CPU, goroutine, and memory usage data.
curl http://localhost:2526/debug/pprof/goroutine --output goroutine.o
go tool pprof -http=:2020 goroutine.o
Make sure the debug mode is enabled for the above links to work.
API Gateway
We use Kong
as the API gateway for managing the APIs. The APIs are available at http://localhost:8000
. You can access the Kong Dashboard here:
workspaces
Requirements
Authentication/Authorization:
- Proto buffer:
To get user details, run the protoc command for the user management service:
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
proto/common/error_details.proto
protoc --experimental_allow_proto3_optional --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
internal/adapter/grpc/proto/user/user.proto
User Management
Questions Management
Questions Planner
Telegram Integration
Test
Setup
Create a .env.test file with the necessary test environment variables.
Running Tests
To run the tests, execute:
go test -cover -count=1 ./...
To generate a coverage profile:
go test -covermode=count -coverprofile=prof.out ./...
To visualize the coverage profile:
go tool cover -html=prof.out
Test Suites
The project includes comprehensive test suites to ensure the functionality and reliability of the codebase, covering various components and features.
Running All Tests
To run all the tests in the project:
go test ./... -v
Linter
To install the linter package:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
To check code with the linter:
golangci-lint run
Cloud
Install minikube in local machine
- Download the Minikube binary:
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
- Install Minikube and remove the binary:
sudo install minikube-linux-amd64 /usr/local/bin/minikube
rm minikube-linux-amd64
- Start Minikube:
minikube start
minikube start --memory=6144 --cpus=4
- Verify the Minikube installation:
minikube status
- Check Kubernetes pods across all namespaces:
kubectl get po -A
- Configure Docker to use Minikube's Docker daemon:
eval $(minikube -p minikube docker-env)
- List Docker images:
docker images
Create Polyglot sentences namespace
- Create the
polyglot-sentences
namespace:
kubectl create namespace polyglot-sentences
- Set the current context to the
polyglot-sentences
namespace:
kubectl config set-context --current --namespace=polyglot-sentences
Create config map
- Apply the configuration map from the specified YAML file:
kubectl apply -f deploy/configs/config-maps.yaml
- Verify the config maps:
kubectl get configmaps
kubectl describe configmap polyglot-sentences-env-config
kubectl describe configmap polyglot-sentences-file-config
Create Services
- Apply the
auth-service
configuration:
kubectl apply -f deploy/authservice/service.yaml
- Apply the gRPC user management service configuration:
kubectl apply -f deploy/userservice/grpc-service.yaml
- Apply the HTTP user management service configuration:
kubectl apply -f deploy/userservice/http-service.yaml
- Verify the created services:
kubectl get services -o wide
Create Secrets for environments
- Create a secret for the
polyglot-sentences
namespace:
kubectl -n=polyglot-sentences create secret generic polyglot-sentences-secret --from-literal JWT_ACCESS_TOKEN_SECRET="your-access-token-secret" --from-literal SEND_GRID_KEY="send-grid-key"
- Verify the secret:
kubectl get secret polyglot-sentences-secret -o yaml
Create deployments
- Apply the user management deployment:
kubectl apply -f deploy/userservice/deployment.yaml
- Apply the authentication deployment:
kubectl apply -f deploy/authservice/deployment.yaml
- Apply the notification deployment:
kubectl apply -f deploy/notificationservice/deployment.yaml
- Verify the deployments:
kubectl get deployments -o wide
- Check the status of the pods:
kubectl get pods -o wide
Apply all Micro services related configurations at once:
kubectl apply -f deploy/userservice
kubectl apply -f deploy/authservice
kubectl apply -f deploy/notificationservice
Rollout deployments for apply new version images
- Rollout restart for all deployments in the polyglot-sentences namespace:
kubectl rollout restart deployment -n polyglot-sentences
- Rollout restart specific deployments:
kubectl rollout restart deployment.apps/auth-deployment -n polyglot-sentences
kubectl rollout restart deployment.apps/user-management-deployment -n polyglot-sentences
kubectl rollout restart deployment.apps/notification-deployment -n polyglot-sentences
Jenkins
- Create the
jenkins
namespace:
kubectl create namespace jenkins
- Set the current context to the
jenkins
namespace:
kubectl config set-context --current --namespace=jenkins
- Apply the Jenkins persistent volume configuration:
kubectl apply -f deploy/jenkins/persistent-volume.yaml
- Apply the Jenkins persistent volume claim configuration:
kubectl apply -f deploy/jenkins/persistent-volume-claim.yaml
- Verify the persistent volume:
kubectl get pvc
kubectl describe pvc jenkins-volume-claim
- Apply the Jenkins service configuration:
kubectl apply -f deploy/jenkins/service.yaml
- Apply the Jenkins master deployment configuration:
kubectl apply -f deploy/jenkins/master-deployment.yaml
- Apply all Jenkins-related configurations at once:
kubectl apply -f deploy/jenkins
Setup docker sock API
- Edit the Docker service file:
sudo nano /lib/systemd/system/docker.service
- Find and remove the following line:
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
- Replace it with:
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock
- Reload the systemd daemon and restart Docker:
sudo systemctl daemon-reload
sudo service docker restart
- Check the Docker service status:
sudo service docker status
- Verify the Docker daemon is working:
curl http://localhost:4243/version
Dashboard URL
http://jenkins.local:30080
kubectl -n jenkins exec -it $(kubectl get pods -n jenkins -o jsonpath="{.items[0].metadata.name}") -- cat /var/jenkins_home/secrets/initialAdminPassword
plugins
After running the Jenkins service, navigate to: Manage Jenkins
-> System Configuration
-> Plugins
-> Available plugins
. Search for and install the following plugins:
- Kubernetes
- SSH Agent
- Blue Ocean
- ThinBackup
- Slack Notification
- Role-based Authorization Strategy
Setup Kubernetes plugins
To configure the Kubernetes plugin, follow these steps:
- Go to:
Manage Jenkins
-> Clouds
-> New cloud
, select Kubernetes
, and enter a name (e.g., kubernetes
).
- Set the
Kubernetes URL
by retrieving it with the following command:
kubectl cluster-info
- Check the
Disable https certificate check
option.
- Set the
Kubernetes Namespace
to jenkins.
- Add credentials:
- Select
Secret text
- ID:
JENKINS_SECRET
- For the secret, retrieve the Kubernetes service account token by following these steps:
kubectl create serviceaccount jenkins --namespace=jenkins
kubectl apply -f deploy/jenkins/token.yaml
kubectl create rolebinding jenkins-admin-binding --clusterrole=admin --serviceaccount=jenkins:jenkins --namespace=jenkins
TOKEN_NAME=$(kubectl get secret --namespace=jenkins | grep jenkins-token | awk '{print $1}')
kubectl describe secret $TOKEN_NAME --namespace=jenkins
- Check
WebSocket
under the connection options.
Credentials
- Docker Hub: Use
Username and Password
.
- ID:
docker-hub-credentials
- Username: Your Docker Hub Username.
- Password: Your Docker Hub Password.
- Kubernetes: Use service account token as
Secret text
.
- GitHub App: Use the following:
- ID:
GitHub-APP
- App ID:
Your GitHub App ID
- Token: Convert and provide the token with
$ cat path/to/converted-github-app.pem
- DB_PASSWORD_TEST: Use
Secret text
(Your test DB password).
- DB_PASSWORD_STAGE: Use
Secret text
(Your stage DB password).
- SSH Agent: Use
SSH Username with private key
:
- ID:
k8s
- Username: Kubernetes host user
- Private key:
- Generate:
$ ssh-keygen -t rsa -b 4096 -C "jenkins@example.com"
- Copy:
$ ssh-copy-id Β«kubernetes host userΒ»@Β«kubernetes remote addressΒ»
- Retrieve value:
$ cat ~/.ssh/id_rsa
Variable
- DB_HOST_TEST: Your test DB Host address
- DB_PORT_TEST: 5425
- DB_NAME_TEST: Your test DB name
- DB_USERNAME_TEST: Your test DB username
- REDIS_HOST_TEST: Your test Redis Host address
- REDIS_PORT_TEST: 6325
- K8S_USER: Kubernetes host user
- K8S_REMOTE_ADDRESS: Kubernetes remote address
- DB_HOST_STAGE: Your stage DB Host address
- DB_PORT_STAGE: 5425
- DB_NAME_STAGE: Your stage DB name
- DB_USERNAME_STAGE: Your stage DB username
Jobs
First Job: Polyglot Sentences Linting and Run Test
- Name:
Polyglot Sentences linting and run test
- Trigger: Check
GitHub hook trigger for GITScm polling
- Pipeline:
- Definition:
Pipeline script from SCM
- SCM:
Git
- Repository URL:
https://github.com/mohsenabedy91/polyglot-sentences.git
- Credentials:
GitHub-APP
- Branches to build:
- Branch Specifier:
:^(?!origin/master$|origin/develop$).*
- Script Path:
jenkinsfile-linter-and-test
Second Job: Polyglot Sentences Deploy to Develop
- Name:
Polyglot Sentences deploy to develop
- Trigger:
Check GitHub hook trigger for GITScm polling
- Pipeline:
- Definition:
Pipeline script from SCM
- SCM:
Git
- Repository URL:
https://github.com/mohsenabedy91/polyglot-sentences.git
- Credentials:
GitHub-APP
- Branches to build:
- Branch Specifier:
*/develop
- Script Path:
Jenkinsfile
Kong Api gateway
- Create the
kong
namespace:
kubectl create namespace kong
- Set the current context to the
kong
namespace:
kubectl config set-context --current --namespace=kong
- Create a ConfigMap for
Kong
plugins:
kubectl create configmap kong-plugins --from-file=/path/to/polyglot-sentences/docker/kong/plugins/ps-authorize/
- Verify the ConfigMap:
kubectl get configmaps
kubectl describe configmap kong-plugins
- Create a secret for the Kong database:
kubectl -n=kong create secret generic kong-db-secrets --from-literal POSTGRES_PASSWORD="password"
- Verify the secret:
kubectl get secret
kubectl describe secret kong-db-secrets
- Apply the Kong persistent volume claim configuration:
kubectl apply -f deploy/kong/persistent-volume-claim.yaml
- Verify the persistent volume:
kubectl get pvc
kubectl describe pvc gateway-postgres-volume-claim
- Apply the PostgreSQL service configuration for Kong:
kubectl apply -f deploy/kong/postgres-service.yaml
- Apply the PostgreSQL deployment configuration for Kong:
kubectl apply -f deploy/kong/postgres-deployment.yaml
- Apply the Kong service configuration:
kubectl apply -f deploy/kong/kong-service.yaml
- Apply the Kong ingress configuration:
kubectl apply -f deploy/kong/ingress.yaml
- Apply the Kong deployment configuration:
kubectl apply -f deploy/kong/kong-deployment.yaml
- Check the status of the pods:
kubectl get pods -o wide
- Apply all Kong-related configurations at once:
kubectl apply -f deploy/kong
- Rollout restart for all deployments in the
kong
namespace:
kubectl rollout restart deployment -n kong
Dashboard URL
http://kong.local:30080