minhasapov_ruslan_lab_3
This commit is contained in:
parent
3b9698ac38
commit
fc6efda0c2
40
minhasapov_ruslan_lab_3/README.md
Normal file
40
minhasapov_ruslan_lab_3/README.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Лабораторная работа №3
|
||||||
|
#### ПИбд-42. Минхасапов Руслан.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### При выполнении лабораторной работы были использованы:
|
||||||
|
- Python 3.12
|
||||||
|
- Flask
|
||||||
|
- requests
|
||||||
|
- Docker
|
||||||
|
- Docker Compose
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Задание:
|
||||||
|
В рамках данной работы были созданы сущности:
|
||||||
|
##### 1. Клуб. Имеет поля:
|
||||||
|
- id
|
||||||
|
- address
|
||||||
|
- phone
|
||||||
|
##### 2. Ресурс. Имеет поля:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- amount
|
||||||
|
- club_id
|
||||||
|
|
||||||
|
##### Каждому клубу могут принадлежать много ресурсов.
|
||||||
|
##### Были развернуты два сервиса - club_service и resource_service, синхронно обменивающиеся сообщениями.
|
||||||
|
##### Сущности хранятся в оперативной памяти (без БД)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Инструкция
|
||||||
|
Для запуска выполненной лабораторной работы необходимо перейти в директорию *minhasapov_ruslan_lab_3* и выполнить команду в терминале:
|
||||||
|
```
|
||||||
|
docker-compose up --build -d --remove-orphans
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Демонстрация работы
|
||||||
|
Доступна по [ссылке](https://disk.yandex.ru/i/IeNyzBXG1oDSWg)
|
11
minhasapov_ruslan_lab_3/club_service/Dockerfile
Normal file
11
minhasapov_ruslan_lab_3/club_service/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
FROM python:latest
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY club_service/club_service.py .
|
||||||
|
|
||||||
|
CMD ["python", "club_service.py"]
|
103
minhasapov_ruslan_lab_3/club_service/club_service.py
Normal file
103
minhasapov_ruslan_lab_3/club_service/club_service.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
from flask import Flask, jsonify, request
|
||||||
|
import requests
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
resources_url = 'http://resourceService:20002/'
|
||||||
|
|
||||||
|
class Club:
|
||||||
|
def __init__(self, id: int, address: str, phone: str):
|
||||||
|
self.id = id
|
||||||
|
self.address = address
|
||||||
|
self.phone = phone
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
"id": self.id,
|
||||||
|
"address": self.address,
|
||||||
|
"phone": self.phone
|
||||||
|
}
|
||||||
|
|
||||||
|
def to_dict_with_resources(self, resources: list):
|
||||||
|
return{
|
||||||
|
"id": self.id,
|
||||||
|
"address": self.address,
|
||||||
|
"phone": self.phone,
|
||||||
|
"resources": resources
|
||||||
|
}
|
||||||
|
|
||||||
|
clubs = [
|
||||||
|
Club(1, 'Пушкина 3', '88005553535'),
|
||||||
|
Club(2, 'Колотушкина 4', '89006664646')
|
||||||
|
]
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET'])
|
||||||
|
def get_all_clubs():
|
||||||
|
return jsonify([club.to_dict() for club in clubs]), 200
|
||||||
|
|
||||||
|
@app.route('/<int:club_id>', methods=['GET'])
|
||||||
|
def get_club(club_id):
|
||||||
|
for club in clubs:
|
||||||
|
if club.id == club_id:
|
||||||
|
return club.to_dict(), 200
|
||||||
|
|
||||||
|
return f'Club with id {club_id} not found', 404
|
||||||
|
|
||||||
|
@app.route('/info/<int:club_id>', methods=['GET'])
|
||||||
|
def get_club_with_resources(club_id):
|
||||||
|
for club in clubs:
|
||||||
|
if club.id == club_id:
|
||||||
|
response = requests.get(resources_url + f'by-club/{club_id}')
|
||||||
|
|
||||||
|
return club.to_dict_with_resources(response.json()), 200
|
||||||
|
|
||||||
|
return f'Club with id {club_id} not found', 404
|
||||||
|
|
||||||
|
@app.route('/check/<int:club_id>', methods=['GET'])
|
||||||
|
def check_club_exists(club_id):
|
||||||
|
for club in clubs:
|
||||||
|
if club.id == club_id:
|
||||||
|
return '', 200
|
||||||
|
|
||||||
|
return '', 404
|
||||||
|
|
||||||
|
@app.route('/', methods=['POST'])
|
||||||
|
def create_club():
|
||||||
|
data = request.json
|
||||||
|
address = data.get('address')
|
||||||
|
phone = data.get('phone')
|
||||||
|
|
||||||
|
if address is None or phone is None:
|
||||||
|
return 'Address and phone required to create club', 400
|
||||||
|
|
||||||
|
next_id = max([c.id for c in clubs]) + 1 if clubs else 1
|
||||||
|
new_club = Club(next_id, address, phone)
|
||||||
|
clubs.append(new_club)
|
||||||
|
|
||||||
|
return jsonify(new_club.to_dict()), 201
|
||||||
|
|
||||||
|
@app.route('/<int:club_id>', methods=['PUT'])
|
||||||
|
def update_club(club_id):
|
||||||
|
data = request.json
|
||||||
|
|
||||||
|
for club in clubs:
|
||||||
|
if club.id == club_id:
|
||||||
|
club.address = data.get('address', club.address)
|
||||||
|
club.phone = data.get('phone', club.phone)
|
||||||
|
|
||||||
|
return jsonify(club.to_dict()), 200
|
||||||
|
|
||||||
|
return f'Club with id {club_id} not found', 404
|
||||||
|
|
||||||
|
@app.route('/<int:club_id>', methods=['DELETE'])
|
||||||
|
def delete_club(club_id):
|
||||||
|
for club in clubs:
|
||||||
|
if club.id == club_id:
|
||||||
|
clubs.remove(club)
|
||||||
|
|
||||||
|
return 'Club deleted', 200
|
||||||
|
|
||||||
|
return f'Club with id {club_id} not found', 404
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=20001, debug=True)
|
26
minhasapov_ruslan_lab_3/docker-compose.yaml
Normal file
26
minhasapov_ruslan_lab_3/docker-compose.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
services:
|
||||||
|
club_service:
|
||||||
|
container_name: clubService
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./club_service/Dockerfile
|
||||||
|
expose:
|
||||||
|
- 20001
|
||||||
|
|
||||||
|
resource_service:
|
||||||
|
container_name: resourceService
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./resource_service/Dockerfile
|
||||||
|
expose:
|
||||||
|
- 20002
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
image: nginx:latest
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
depends_on:
|
||||||
|
- club_service
|
||||||
|
- resource_service
|
25
minhasapov_ruslan_lab_3/nginx.conf
Normal file
25
minhasapov_ruslan_lab_3/nginx.conf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
events { worker_connections 1024; }
|
||||||
|
|
||||||
|
http {
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
location /clubService/ {
|
||||||
|
proxy_pass http://clubService:20001/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /resourceService/ {
|
||||||
|
proxy_pass http://resourceService:20002/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
minhasapov_ruslan_lab_3/requirements.txt
Normal file
2
minhasapov_ruslan_lab_3/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Flask==3.0.3
|
||||||
|
requests==2.32.3
|
11
minhasapov_ruslan_lab_3/resource_service/Dockerfile
Normal file
11
minhasapov_ruslan_lab_3/resource_service/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
FROM python:latest
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY resource_service/resource_service.py .
|
||||||
|
|
||||||
|
CMD ["python", "resource_service.py"]
|
118
minhasapov_ruslan_lab_3/resource_service/resource_service.py
Normal file
118
minhasapov_ruslan_lab_3/resource_service/resource_service.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
from flask import Flask, jsonify, request
|
||||||
|
import requests
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
clubs_url = 'http://clubService:20001/'
|
||||||
|
|
||||||
|
class Resource:
|
||||||
|
def __init__(self, id: int, name: str, amount: int, club_id: int):
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
self.amount = amount
|
||||||
|
self.club_id = club_id
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
"id": self.id,
|
||||||
|
"name": self.name,
|
||||||
|
"amount": self.amount,
|
||||||
|
"club_id": self.club_id
|
||||||
|
}
|
||||||
|
|
||||||
|
def to_dict_with_club(self, club):
|
||||||
|
return {
|
||||||
|
"id": self.id,
|
||||||
|
"name": self.name,
|
||||||
|
"amount": self.amount,
|
||||||
|
"club": club
|
||||||
|
}
|
||||||
|
|
||||||
|
resources = [
|
||||||
|
Resource(1, 'PS5', 3, 1),
|
||||||
|
Resource(2, 'XBOX', 4, 2)
|
||||||
|
]
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET'])
|
||||||
|
def get_all_resources():
|
||||||
|
return jsonify([resource.to_dict() for resource in resources]), 200
|
||||||
|
|
||||||
|
@app.route('/by-club/<int:club_id>', methods=['GET'])
|
||||||
|
def get_resources_by_club(club_id):
|
||||||
|
resources_for_club = [resource.to_dict() for resource in resources if resource.club_id == club_id]
|
||||||
|
|
||||||
|
return jsonify(resources_for_club), 200
|
||||||
|
|
||||||
|
@app.route('/<int:resource_id>', methods=['GET'])
|
||||||
|
def get_resource(resource_id):
|
||||||
|
for resource in resources:
|
||||||
|
if resource.id == resource_id:
|
||||||
|
return jsonify(resource.to_dict()), 200
|
||||||
|
|
||||||
|
return f'Resource with id {resource_id} not found', 404
|
||||||
|
|
||||||
|
@app.route('/info/<int:resource_id>', methods=['GET'])
|
||||||
|
def get_resource_with_club(resource_id):
|
||||||
|
for resource in resources:
|
||||||
|
if resource.id == resource_id:
|
||||||
|
try:
|
||||||
|
response = requests.get(clubs_url + str(resource.club_id))
|
||||||
|
response.raise_for_status()
|
||||||
|
club = response.json()
|
||||||
|
|
||||||
|
return jsonify(resource.to_dict_with_club(club)), 200
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
return f"Error fetching club: {e}", 500
|
||||||
|
|
||||||
|
return f'Resource with id {resource_id} not found', 404
|
||||||
|
|
||||||
|
@app.route('/', methods=['POST'])
|
||||||
|
def create_resource():
|
||||||
|
data = request.json
|
||||||
|
name = data.get('name')
|
||||||
|
amount = data.get('amount')
|
||||||
|
club_id = data.get('club_id')
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(clubs_url + f'check/{club_id}')
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
next_id = max([r.id for r in resources]) + 1 if resources else 1
|
||||||
|
new_resource = Resource(next_id, name, amount, club_id)
|
||||||
|
resources.append(new_resource)
|
||||||
|
|
||||||
|
return jsonify(new_resource.to_dict()), 201
|
||||||
|
else:
|
||||||
|
return f"Club with ID {club_id} not found", 404
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
return f"Error checking club: {e}", 500
|
||||||
|
|
||||||
|
@app.route('/<int:resource_id>', methods=['PUT'])
|
||||||
|
def update_resource(resource_id):
|
||||||
|
data = request.json
|
||||||
|
|
||||||
|
for resource in resources:
|
||||||
|
if resource.id == resource_id:
|
||||||
|
resource.name = data.get('name', resource.name)
|
||||||
|
resource.amount = data.get('amount', resource.amount)
|
||||||
|
resource.club_id = data.get('club_id', resource.club_id)
|
||||||
|
|
||||||
|
return jsonify(resource.to_dict()), 200
|
||||||
|
|
||||||
|
return f'Resource with id {resource_id} not found', 404
|
||||||
|
|
||||||
|
@app.route('/<int:resource_id>', methods=['DELETE'])
|
||||||
|
def delete_resource(resource_id):
|
||||||
|
for resource in resources:
|
||||||
|
if resource.id == resource_id:
|
||||||
|
resources.remove(resource)
|
||||||
|
|
||||||
|
return 'Resource deleted', 200
|
||||||
|
|
||||||
|
return f'Resource with id {resource_id} not found', 404
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=20002, debug=True)
|
Loading…
Reference in New Issue
Block a user