second
هذا الالتزام موجود في:
17
.ghaymah.json
Normal file
17
.ghaymah.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"id": "d7cd2a73-34db-49ef-b663-41a6053515ee",
|
||||||
|
"name": "bin",
|
||||||
|
"projectId": "5f5c8255-5662-49b2-a097-84f52fd16c12",
|
||||||
|
"ports": [
|
||||||
|
{
|
||||||
|
"expose": true,
|
||||||
|
"number": 80
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publicAccess": {
|
||||||
|
"enabled": true,
|
||||||
|
"domain": "auto"
|
||||||
|
},
|
||||||
|
"resourceTier": "t1",
|
||||||
|
"dockerFileName": "Dockerfile"
|
||||||
|
}
|
||||||
38
.github/workflows/ci\cd.yaml
مباع
Normal file
38
.github/workflows/ci\cd.yaml
مباع
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_and_push_image:
|
||||||
|
steps:
|
||||||
|
- name: checkout code
|
||||||
|
uses: actions/checkout@v5.0.0
|
||||||
|
|
||||||
|
- name: login to dockerhub
|
||||||
|
uses: docker/login-action@v3.6.0
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME}}
|
||||||
|
password: ${{ secrets.DOCKER_TOKEN}}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: Docker_API/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: abdelrhmanpasha/abdelrhman:firstV1
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
needs: build_and_push_image
|
||||||
|
steps:
|
||||||
|
- name: checkout code
|
||||||
|
uses: actions/checkout@v5.0.0
|
||||||
|
- name: install ghaymah cli
|
||||||
|
run: curl -sSl https://cli.ghaymah.systems/install.sh | bash
|
||||||
|
|
||||||
|
- name: login to ghaymah
|
||||||
|
run: $HOME/ghaymah/bin/gy auth login --email "${{secrets.GH_EMAIL}}" --password "${{secrets.GH_PASS}}"
|
||||||
|
|
||||||
|
- name: deploy
|
||||||
|
run: $HOME/ghaymah/bin/gy resource app launch
|
||||||
27
.gitignore
مباع
Normal file
27
.gitignore
مباع
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
.venv/
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
|
||||||
|
!.dockerignore
|
||||||
|
|
||||||
|
|
||||||
|
# Virtual env
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
141
API.py
Normal file
141
API.py
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
from fastapi import FastAPI, HTTPException
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import List, Optional
|
||||||
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
#its like a database to store data i wrote in the same session
|
||||||
|
# b4 reload to update or something else... and i can write anything in
|
||||||
|
#and it will be permenant data ... if you deleted a class you can use
|
||||||
|
#dict{} and write data in it to be a data structural ypu wanna use with your code
|
||||||
|
cars={uuid4()
|
||||||
|
:{
|
||||||
|
"country":"Germany",
|
||||||
|
"brand":"Mercedes",
|
||||||
|
"model":"GLC",
|
||||||
|
"year":2026
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# cars = []
|
||||||
|
|
||||||
|
''' class means its something im ganna do frequently in my code
|
||||||
|
and every class must have object like Cars in our project and
|
||||||
|
might has something to range it too as here (basemodel)
|
||||||
|
its a data structural to organize my send and resieve data....'''
|
||||||
|
|
||||||
|
'''here im gonna write my data structure
|
||||||
|
like every thing i wanna know / put in my app and web
|
||||||
|
lets say wanna put an id , name , type and so on ....
|
||||||
|
and how i wanna sent and resieve it'''
|
||||||
|
|
||||||
|
class Cars(BaseModel):
|
||||||
|
name:str
|
||||||
|
country:str
|
||||||
|
brand:str
|
||||||
|
model:str
|
||||||
|
year:int
|
||||||
|
class UpdateCar(BaseModel):
|
||||||
|
name: Optional[str]=None
|
||||||
|
country: Optional[str]=None
|
||||||
|
brand: Optional[str]=None
|
||||||
|
model: Optional[str]=None
|
||||||
|
year: Optional[int]=None
|
||||||
|
|
||||||
|
#Endpoint (URL)
|
||||||
|
#www.Famcars.com/
|
||||||
|
@app.get("/")
|
||||||
|
def get_root():
|
||||||
|
return {"Hello":'im Abdelrhman'}
|
||||||
|
|
||||||
|
#www.Famcars.com/cars/1
|
||||||
|
#GET Cars
|
||||||
|
@app.get("/cars/{car_id}")
|
||||||
|
# def get_cars(car_id:UUID):
|
||||||
|
def get_cars(car_id:int):
|
||||||
|
if car_id not in cars:
|
||||||
|
raise HTTPException(status_code=404,detail="car not found!")
|
||||||
|
return cars[car_id]
|
||||||
|
|
||||||
|
#www.Famcars.com/cars
|
||||||
|
@app.get("/cars/")
|
||||||
|
def get_all_cars():
|
||||||
|
return cars
|
||||||
|
|
||||||
|
#Create
|
||||||
|
#www.Famcars.com/cars/1
|
||||||
|
#POST Cars
|
||||||
|
# @app.post("/cars/{car_id}", response_model=Cars)
|
||||||
|
# def create_car(car_id:int,car:Cars):
|
||||||
|
# if car_id in car:
|
||||||
|
# raise HTTPException(status_code=404,detail="car already exist!")
|
||||||
|
# cars[car_id]=car.dict()
|
||||||
|
# return car
|
||||||
|
|
||||||
|
@app.post("/cars/", response_model=Cars)
|
||||||
|
def create_cars(car:Cars):
|
||||||
|
car_id=uuid4()
|
||||||
|
if car_id in car:
|
||||||
|
raise HTTPException(status_code=404,detail="car already exist!")
|
||||||
|
cars[car_id]=car.dict()
|
||||||
|
return car
|
||||||
|
|
||||||
|
#UPDATE
|
||||||
|
#www.Famcars.com/cars/1
|
||||||
|
#PUT Cars
|
||||||
|
@app.put("/cars/{car_id}", response_model=UpdateCar)
|
||||||
|
def update_car(car_id:UUID,car:UpdateCar):
|
||||||
|
# def update_car(car_id:int,car:UpdateCar):
|
||||||
|
if car_id not in cars:
|
||||||
|
raise HTTPException(status_code=404, detail="Car is not Found")
|
||||||
|
current_car= cars[car_id]
|
||||||
|
# if car.id is not None:
|
||||||
|
# current_car["id"]=car.id
|
||||||
|
if car.name is not None:
|
||||||
|
current_car["name"]=car.name
|
||||||
|
if car.country is not None:
|
||||||
|
current_car["country"] = car.country
|
||||||
|
if car.brand is not None:
|
||||||
|
current_car["brand"] = car.brand
|
||||||
|
if car.model is not None:
|
||||||
|
current_car["model"] = car.model
|
||||||
|
if car.year is not None:
|
||||||
|
current_car["year"] = car.year
|
||||||
|
|
||||||
|
return current_car
|
||||||
|
|
||||||
|
#DELETE
|
||||||
|
#www.Famcars.com/cars/1
|
||||||
|
#DELETE Cars
|
||||||
|
@app.delete("/cars/{car_id}")
|
||||||
|
def deleted_car(car_id:UUID):
|
||||||
|
#def deleted_car(car_id:int):
|
||||||
|
if car_id not in cars:
|
||||||
|
HTTPException(status_code=404, detail="Car is not here")
|
||||||
|
|
||||||
|
removed_car=cars.pop(car_id)
|
||||||
|
return {"massage":"car has been deleted", "deleted_car":removed_car}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# if __name__ == "__main__":
|
||||||
|
# import uvicorn
|
||||||
|
# uvicorn.run(app,host="0.0.0.0",port=8000)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
0
Docker_API/.ghaymah.json
Normal file
0
Docker_API/.ghaymah.json
Normal file
42
Dockerfile
Normal file
42
Dockerfile
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
|
#(Base Image)
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
#(here /app mean name in the fastAPI i used)
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
#(Copy and Install Dependancies/Libraries)
|
||||||
|
COPY Docker_API/requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
#(Copy all files after install dependancies)
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
#(Port my app listen to )
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
#(Run app/file)
|
||||||
|
CMD ["uvicorn", "API:app", "--host", "0.0.0.0", "--port", "8000", "--log-config", "Log.yaml"]
|
||||||
|
|
||||||
|
=======
|
||||||
|
#(Base Image)
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
#(here /app mean name in the fastAPI i used)
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
#(Copy and Install Dependancies/Libraries)
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
#(Copy all files after install dependancies)
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
|
||||||
|
#(Port my app listen to )
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
#(Run app/file)
|
||||||
|
CMD ["uvicorn", "API:app", "--host", "0.0.0.0", "--port", "8000", "--log-config", "Log.yaml"]
|
||||||
|
|
||||||
|
>>>>>>> origin/scripts
|
||||||
120
Final_MOnitor.sh
Executable file
120
Final_MOnitor.sh
Executable file
@@ -0,0 +1,120 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
function get_server_metrics() {
|
||||||
|
SERVER_IP=$(hostname -I | awk '{print $1}')
|
||||||
|
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}' | cut -d'.' -f1)%
|
||||||
|
RAM_AVAILABLE=$(free -m | awk 'NR==2{print $4 "MB"}')
|
||||||
|
DISK_SPACE=$(df -h / | awk 'NR==2 {print $4}')
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
"ip": "$SERVER_IP",
|
||||||
|
"cpu_usage": "$CPU_USAGE",
|
||||||
|
"ram_available": "$RAM_AVAILABLE",
|
||||||
|
"disk_space": "$DISK_SPACE"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
#_____________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
LOG_FILE="/home/abdelrhman/PyCharmMiscProject/AP.log"
|
||||||
|
#STATUS_CODE=$(tail -n1 "$LOG_FILE" | cut -d " " -f9)
|
||||||
|
#REQUEST=$(tail -n1 $LOG_FILE | cut -d " " -f6)
|
||||||
|
#DATE_OF_REQUEST=$(tail -n1 $LOG_FILE | cut -d " " -f1)
|
||||||
|
#REQUEST_TIME=$(tail -n1 $LOG_FILE | cut -d " " -f2)
|
||||||
|
#IP_SERVER=$(tail -n1 $LOG_FILE | cut -d " " -f4 | cut -d ":" -f1)
|
||||||
|
#ALERT_API=______________________________________________________________
|
||||||
|
#SERVER_METRICS=$(get_server_metrics)
|
||||||
|
|
||||||
|
#JSON_PAYLOAD=$(cat <<EOF
|
||||||
|
#{
|
||||||
|
# "error": "$STATUS_CODE Error",
|
||||||
|
#"timestamp": "$DATE_OF_REQUEST:$REQUEST_TIME",
|
||||||
|
#"server_metrics": {
|
||||||
|
# $SERVER_METRICS
|
||||||
|
#}
|
||||||
|
#}
|
||||||
|
#EOF
|
||||||
|
#)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tail -n 0 -f "$LOG_FILE" | while read -r NEW_LINE; do
|
||||||
|
|
||||||
|
|
||||||
|
STATUS_CODE=$(tail -n1 "$LOG_FILE" | cut -d " " -f9)
|
||||||
|
REQUEST=$(tail -n1 $LOG_FILE | cut -d " " -f6)
|
||||||
|
DATE_OF_REQUEST=$(tail -n1 $LOG_FILE | cut -d " " -f1)
|
||||||
|
REQUEST_TIME=$(tail -n1 $LOG_FILE | cut -d " " -f2)
|
||||||
|
IP_SERVER=$(tail -n1 $LOG_FILE | cut -d " " -f4 | cut -d ":" -f1)
|
||||||
|
#ALERT_API=______________________________________________________________
|
||||||
|
#SERVER_METRICS=$(get_server_metrics)
|
||||||
|
|
||||||
|
JSON_PAYLOAD=$(cat <<EOF
|
||||||
|
{
|
||||||
|
"error": "$STATUS_CODE Error",
|
||||||
|
"timestamp": "$DATE_OF_REQUEST:$REQUEST_TIME",
|
||||||
|
"server_metrics": {
|
||||||
|
$SERVER_METRICS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ "$STATUS_CODE" =~ ^[0-9] ]];
|
||||||
|
then
|
||||||
|
# echo $NEW_LINE
|
||||||
|
echo "Status code is $STATUS_CODE "
|
||||||
|
echo "IP is $IP_SERVER "
|
||||||
|
echo "Date of request $DATE_OF_REQUEST "
|
||||||
|
echo "Request time $REQUEST_TIME"
|
||||||
|
echo "The request is $REQUEST "
|
||||||
|
|
||||||
|
case $STATUS_CODE in
|
||||||
|
2??)
|
||||||
|
echo -e "The process\033[32m[DONE]\033[0m correctly"
|
||||||
|
echo
|
||||||
|
|
||||||
|
;;
|
||||||
|
3??)
|
||||||
|
echo -e "there is a \033[33m[REDIRECT]\033[0m Error"
|
||||||
|
echo
|
||||||
|
|
||||||
|
;;
|
||||||
|
4??)
|
||||||
|
echo -e "Not found \033[31m[ERROR]\033[0m"
|
||||||
|
echo
|
||||||
|
|
||||||
|
;;
|
||||||
|
5??)
|
||||||
|
echo -e "Server \033[31m[ERROR]\033[0m"
|
||||||
|
echo
|
||||||
|
#function get_server_metrics
|
||||||
|
#curl -s -X POST -H "Content-Type: application/json" -d "$JSON_PAYLOAD" $ALERT_API
|
||||||
|
|
||||||
|
;;
|
||||||
|
|
||||||
|
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# if [ $STATUS_CODE -ge 200 ] && [ $STATUS_CODE -lt 300 ]
|
||||||
|
# then
|
||||||
|
# echo "its done bro"
|
||||||
|
#
|
||||||
|
# elif [ $STATUS_CODE -ge 300 ] && [ $STATUS_CODE -lt 400 ]
|
||||||
|
# then
|
||||||
|
# echo "Redirect Error"
|
||||||
|
# elif [ $STATUS_CODE -ge 400 ] && [ $STATUS_CODE -lt 500 ]
|
||||||
|
# then
|
||||||
|
# echo "NOT Found"
|
||||||
|
#
|
||||||
|
# else
|
||||||
|
# echo "Server Error"
|
||||||
|
# fi
|
||||||
|
#done
|
||||||
7
Gtest.api.sh
Executable file
7
Gtest.api.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
API_URL="http://127.0.0.1:8000/cars/"
|
||||||
|
|
||||||
|
curl $API_URL
|
||||||
|
|
||||||
|
|
||||||
29
Log.yaml
Normal file
29
Log.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
version: 1
|
||||||
|
disable_existing_loggers: False
|
||||||
|
|
||||||
|
formatters:
|
||||||
|
uvicorn_custom_fmt:
|
||||||
|
format: '%(asctime)s [%(levelname)s]: %(message)s'
|
||||||
|
datefmt: '%Y-%m-%d %H:%M:%S'
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
File:
|
||||||
|
formatter: uvicorn_custom_fmt
|
||||||
|
class: logging.handlers.RotatingFileHandler
|
||||||
|
filename: 'AP.log'
|
||||||
|
encoding: utf8
|
||||||
|
default:
|
||||||
|
formatter: uvicorn_custom_fmt
|
||||||
|
class: logging.StreamHandler
|
||||||
|
stream: ext://sys.stderr
|
||||||
|
|
||||||
|
loggers:
|
||||||
|
uvicorn.access:
|
||||||
|
handlers: [ default , File ]
|
||||||
|
level: INFO
|
||||||
|
propagate: False
|
||||||
|
uvicorn:
|
||||||
|
handlers: [ default , File ]
|
||||||
|
level: INFO
|
||||||
|
propagate: False
|
||||||
|
|
||||||
18
PO.test.api.sh
Executable file
18
PO.test.api.sh
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
API_URL="http://127.0.0.1:8000/cars/"
|
||||||
|
CONCURRENT=1000
|
||||||
|
FILE="/home/abdelrhman/PyCharmMiscProject/data.txt"
|
||||||
|
|
||||||
|
|
||||||
|
for i in $(seq 1 $CONCURRENT)
|
||||||
|
do
|
||||||
|
echo $i
|
||||||
|
curl -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d @$FILE \
|
||||||
|
-s -o /dev/null \
|
||||||
|
-k -L -i "$API_URL"
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
8
data.txt
Normal file
8
data.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "A-Class-List-3",
|
||||||
|
"country": "Germany",
|
||||||
|
"brand": "Mercedes",
|
||||||
|
"model": "A180-2027",
|
||||||
|
"year": 2027
|
||||||
|
}
|
||||||
|
|
||||||
10
requirements.txt
Normal file
10
requirements.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
|
fastapi==0.117.1
|
||||||
|
uvicorn==0.37.0
|
||||||
|
pydantic==2.11.9
|
||||||
|
=======
|
||||||
|
fastapi==0.117.1
|
||||||
|
uvicorn==0.37.0
|
||||||
|
pydantic==2.11.9
|
||||||
|
>>>>>>> origin/scripts
|
||||||
|
PyYAML==6.0.3
|
||||||
47
scripts.sh
Normal file
47
scripts.sh
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
Connection_URL = "http://127.0.0.1:8000"
|
||||||
|
|
||||||
|
|
||||||
|
while true ; do
|
||||||
|
echo "select option :"
|
||||||
|
echo " 1 => to add a car"
|
||||||
|
echo " 2 => to delete item "
|
||||||
|
echo " 3 => to log out from this script"
|
||||||
|
read -p "you choice is : " choice
|
||||||
|
|
||||||
|
case $choice in
|
||||||
|
1)
|
||||||
|
echo "you will add a car "
|
||||||
|
read -p "ID : " id
|
||||||
|
read -p "car name : " name
|
||||||
|
read -p "country : " country
|
||||||
|
read -p "brand : " brand
|
||||||
|
read -p "model : " model
|
||||||
|
read -p "year_of_model : " year_of_model
|
||||||
|
|
||||||
|
curl -s -X POST "$Connection_URL/cars/$id" \ -H "Content-Type : application/json" \ -d "{\"id\":$id , \"name\":\"$name\" , \"country\":\"$country\",\"brand\":\"$brand\" , \"model\":\"$model\" , \"year_of_model\":\"$year_of_model\"}"
|
||||||
|
|
||||||
|
echo "adding is successfully done "
|
||||||
|
;;
|
||||||
|
|
||||||
|
|
||||||
|
2)
|
||||||
|
echo "Enter the ID of item"
|
||||||
|
read -p "ID : " id
|
||||||
|
|
||||||
|
curl -s -X DELETE "$BASE_URL/cars/$id"
|
||||||
|
echo "deleting successfully done "
|
||||||
|
;;
|
||||||
|
|
||||||
|
3)
|
||||||
|
echo "Exit the system"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "you choice isn't exist, please enter right option"
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
done
|
||||||
المرجع في مشكلة جديدة
حظر مستخدم