diff --git a/polevoy_sergey_lab_3/docker-compose.yml b/polevoy_sergey_lab_3/docker-compose.yml new file mode 100644 index 0000000..d18475c --- /dev/null +++ b/polevoy_sergey_lab_3/docker-compose.yml @@ -0,0 +1,26 @@ +services: + service: + container_name: service + build: + context: ./service_service + dockerfile: Dockerfile + expose: + - 5000 + + tariff: + container_name: tariff + build: + context: ./tariff_service + dockerfile: Dockerfile + expose: + - 5001 + + nginx: + image: nginx:latest + ports: + - "80:80" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf + depends_on: + - service + - tariff \ No newline at end of file diff --git a/polevoy_sergey_lab_3/nginx.conf b/polevoy_sergey_lab_3/nginx.conf new file mode 100644 index 0000000..579cc7f --- /dev/null +++ b/polevoy_sergey_lab_3/nginx.conf @@ -0,0 +1,25 @@ +events { worker_connections 1024; } + +http { + server { + listen 80; + listen [::]:80; + server_name localhost; + + location /services/ { + proxy_pass http://service:5000/; + 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 /tariffs/ { + proxy_pass http://tariff:5001/; + 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; + } + } +} \ No newline at end of file diff --git a/polevoy_sergey_lab_3/readme.md b/polevoy_sergey_lab_3/readme.md new file mode 100644 index 0000000..7c782ba --- /dev/null +++ b/polevoy_sergey_lab_3/readme.md @@ -0,0 +1,34 @@ +# Лабораторная работа №3 +#### ПИбд-42. Полевой Сергей. + +#### При выполнении использовал: +- Python 3.12 +- Flask +- requests +- Docker +- Docker Compose + +#### Задание: +Создать CRUD сервис для каждой сущности с синхронным обменом сообщений. Для этого были выбраны следующие сущности: +##### 1. Услуга. Имеет поля: + - id + - name + - description +##### 2. Тариф. Имеет поля: + - id + - name + - price + - service_uuid + +##### У услуги может быть несколько тарифов с разными ценами. +##### Были развернуты два сервиса - service_service и tariff_service, синхронно обменивающиеся сообщениями. +##### Сущности хранятся в оперативной памяти (без БД) + +#### Инструкция +Для запуска лабораторной работы, перейдите в папку *polevoy_sergey_lab_3* и выполните команду: +``` +docker-compose up --build --remove-orphans +``` + +#### Демонстрация работы +Доступна по [ссылке](https://disk.yandex.ru/i/TwtZbHobhkfNAg) \ No newline at end of file diff --git a/polevoy_sergey_lab_3/service_service/Dockerfile b/polevoy_sergey_lab_3/service_service/Dockerfile new file mode 100644 index 0000000..cb6da10 --- /dev/null +++ b/polevoy_sergey_lab_3/service_service/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.12-alpine + +WORKDIR /app + +COPY requirements.txt . + +RUN pip install --no-cache-dir -r requirements.txt + +COPY app.py . + +CMD ["python", "app.py"] \ No newline at end of file diff --git a/polevoy_sergey_lab_3/service_service/app.py b/polevoy_sergey_lab_3/service_service/app.py new file mode 100644 index 0000000..0004bb3 --- /dev/null +++ b/polevoy_sergey_lab_3/service_service/app.py @@ -0,0 +1,66 @@ +import requests +from flask import Flask, jsonify, request +import uuid + +app = Flask(__name__) + +services = {} + +@app.route('/', methods=['GET']) +def get_services(): + return jsonify(list(services.values())) + +@app.route('/', methods=['GET']) +def get_service(service_uuid): + if str(service_uuid) in services: + service = services[str(service_uuid)].copy() + tariffs_list = [] + try: + response = requests.get(f'http://tariff:5001/with-service/{service_uuid}') + tariffs_list = response.json() + except requests.exceptions.RequestException: + pass + + service['tariffs'] = tariffs_list + return jsonify(service) + + return jsonify({'message': 'Service not found'}), 404 + +@app.route('/', methods=['POST']) +def create_service(): + data = request.get_json() + if not data or 'name' not in data or 'description' not in data: + return jsonify({'message': 'Invalid data. Name and description are required'}), 400 + + service_uuid = str(uuid.uuid4()) + services[service_uuid] = {'uuid': service_uuid, 'name': data['name'], 'description': data['description']} + + return jsonify(services[service_uuid]), 201 + + +@app.route('/', methods=['PUT']) +def update_service(service_uuid): + if str(service_uuid) not in services: + return jsonify({'message': 'Service not found'}), 404 + + data = request.get_json() + if not data or 'name' not in data or 'description' not in data: + return jsonify({'message': 'Invalid data'}), 400 + + services[str(service_uuid)]['name'] = data['name'] + services[str(service_uuid)]['description'] = data['description'] + + return jsonify(services[str(service_uuid)]), 200 + + +@app.route('/', methods=['DELETE']) +def delete_service(service_uuid): + if str(service_uuid) in services: + del services[str(service_uuid)] + return jsonify({'message': 'Service deleted'}), 200 + + return jsonify({'message': 'Service not found'}), 404 + + +if __name__ == '__main__': + app.run(debug=True, host='0.0.0.0', port=5000) diff --git a/polevoy_sergey_lab_3/service_service/requirements.txt b/polevoy_sergey_lab_3/service_service/requirements.txt new file mode 100644 index 0000000..494909e --- /dev/null +++ b/polevoy_sergey_lab_3/service_service/requirements.txt @@ -0,0 +1,2 @@ +Flask==3.0.3 +requests==2.32.3 \ No newline at end of file diff --git a/polevoy_sergey_lab_3/tariff_service/Dockerfile b/polevoy_sergey_lab_3/tariff_service/Dockerfile new file mode 100644 index 0000000..cb6da10 --- /dev/null +++ b/polevoy_sergey_lab_3/tariff_service/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.12-alpine + +WORKDIR /app + +COPY requirements.txt . + +RUN pip install --no-cache-dir -r requirements.txt + +COPY app.py . + +CMD ["python", "app.py"] \ No newline at end of file diff --git a/polevoy_sergey_lab_3/tariff_service/app.py b/polevoy_sergey_lab_3/tariff_service/app.py new file mode 100644 index 0000000..065e9eb --- /dev/null +++ b/polevoy_sergey_lab_3/tariff_service/app.py @@ -0,0 +1,66 @@ +from flask import Flask, jsonify, request +import uuid + + +app = Flask(__name__) + +tariffs = {} + + +@app.route('/', methods=['GET']) +def get_tariffs(): + return jsonify(list(tariffs.values())) + + +@app.route('/with-service/', methods=['GET']) +def get_tariffs_with_service(service_uuid): + return jsonify(list(filter(lambda t: t["service_uuid"] == str(service_uuid), tariffs.values()))) + + +@app.route('/', methods=['GET']) +def get_tariff(tariff_uuid): + if str(tariff_uuid) in tariffs: + return jsonify(tariffs[str(tariff_uuid)]) + + return jsonify({'message': 'Tariff not found'}), 404 + + +@app.route('/', methods=['POST']) +def create_tariff(): + data = request.get_json() + if not data or 'name' not in data or 'price' not in data or 'service_uuid' not in data: + return jsonify({'message': 'Invalid data'}), 400 + + tariff_uuid = str(uuid.uuid4()) + tariffs[tariff_uuid] = {'uuid': tariff_uuid, 'name': data['name'], 'price': data['price'], 'service_uuid': data['service_uuid']} + + return jsonify(tariffs[tariff_uuid]), 201 + + +@app.route('/', methods=['PUT']) +def update_tariff(tariff_uuid): + if str(tariff_uuid) not in tariffs: + return jsonify({'message': 'Tariff not found'}), 404 + + data = request.get_json() + if not data or 'name' not in data or 'price' not in data or 'service_uuid' not in data: + return jsonify({'message': 'Invalid data'}), 400 + + tariffs[str(tariff_uuid)]['name'] = data['name'] + tariffs[str(tariff_uuid)]['price'] = data['price'] + tariffs[str(tariff_uuid)]['service_uuid'] = data['service_uuid'] + + return jsonify(tariffs[str(tariff_uuid)]), 200 + + +@app.route('/', methods=['DELETE']) +def delete_tariff(tariff_uuid): + if str(tariff_uuid) in tariffs: + del tariffs[str(tariff_uuid)] + return jsonify({'message': 'Tariff deleted'}), 200 + + return jsonify({'message': 'Tariff not found'}), 404 + + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5001) diff --git a/polevoy_sergey_lab_3/tariff_service/requirements.txt b/polevoy_sergey_lab_3/tariff_service/requirements.txt new file mode 100644 index 0000000..494909e --- /dev/null +++ b/polevoy_sergey_lab_3/tariff_service/requirements.txt @@ -0,0 +1,2 @@ +Flask==3.0.3 +requests==2.32.3 \ No newline at end of file