From adac0967263c202380a96f087cefa9e9b669fb9d Mon Sep 17 00:00:00 2001
From: igors <igors-2011@mail.ru>
Date: Sat, 14 Dec 2024 22:45:25 +0400
Subject: [PATCH] /

---
 .idea/misc.xml                                |  5 ++-
 melnikov_igor_lab_2/README.md                 | 44 +++++++++++++++++++
 melnikov_igor_lab_2/app_1/Dockerfile          | 13 ++++++
 melnikov_igor_lab_2/app_1/app.py              | 28 ++++++++++++
 melnikov_igor_lab_2/app_2/Dockerfile          |  8 ++++
 melnikov_igor_lab_2/app_2/app.py              | 27 ++++++++++++
 melnikov_igor_lab_2/docker-compose.yml        | 27 ++++++++++++
 melnikov_igor_lab_2/generator/Dockerfile      |  7 +++
 .../generator/generate_files.py               | 31 +++++++++++++
 9 files changed, 189 insertions(+), 1 deletion(-)
 create mode 100644 melnikov_igor_lab_2/README.md
 create mode 100644 melnikov_igor_lab_2/app_1/Dockerfile
 create mode 100644 melnikov_igor_lab_2/app_1/app.py
 create mode 100644 melnikov_igor_lab_2/app_2/Dockerfile
 create mode 100644 melnikov_igor_lab_2/app_2/app.py
 create mode 100644 melnikov_igor_lab_2/docker-compose.yml
 create mode 100644 melnikov_igor_lab_2/generator/Dockerfile
 create mode 100644 melnikov_igor_lab_2/generator/generate_files.py

diff --git a/.idea/misc.xml b/.idea/misc.xml
index ae8ddd2..c023adf 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (tukaeva_alfiya_lab_4)" project-jdk-type="Python SDK" />
+  <component name="Black">
+    <option name="sdkName" value="Python 3.12 (DAS_2024_1)" />
+  </component>
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (DAS_2024_1)" project-jdk-type="Python SDK" />
 </project>
\ No newline at end of file
diff --git a/melnikov_igor_lab_2/README.md b/melnikov_igor_lab_2/README.md
new file mode 100644
index 0000000..563d182
--- /dev/null
+++ b/melnikov_igor_lab_2/README.md
@@ -0,0 +1,44 @@
+# Лабораторная работа №2 - Разработка простейшего распределённого приложения
+
+## Задание
+
+* Разработать два приложения такие, что результат первого является исходными данными для второго.
+* Изучить файлы сборки образов ```docker``` и разработать их для созданных приложений и правильно закоммитить решение
+* Собрать файл ```docker-compose.yml``` для запуска приложений.
+
+### Варианты задания:
+&nbsp;1. Первое приложение берёт из каталога /var/data случайный файл и перекладывает его в /var/result/data.txt
+
+&nbsp;2. Второе приложение сохраняет произведение первого и последнего числа из файла /var/result/data.txt в /var/result/result.txt
+
+## Запуск работы программы
+
+1. Убедиться, что установлены необходимые технологии:
+   - Docker: Платформа для контейнеризации приложений.
+   - Docker Compose: Инструмент для запуска много контейнерных приложений на основе `docker-compose.yaml`. Обычно поставляется вместе с Docker. Чтобы проверить, установлена ли утилита, нужно запустить команду:
+```bash
+    docker-compose --version
+```
+
+2. В директории, где находится файл `docker-compose.yaml`, выполнить следующую команду для запуска всех сервисов:
+```bash
+    docker-compose up --build
+```
+Эта команда сначала выполнит сборку, а затем запустит контейнеры.
+
+3. После успешного запуска можно перейти в каталог проекта и увидеть папку data со сгенерированными файлами и папку result, в которой два текстовых файла:
+   - data.txt - файл, полученный после выполнения первой программы.
+   - result.txt -файл, полученный после выполнения второй программы.
+
+## Описание работы:
+
+1. **Генератор файлов**
+    generate_files.py, генерирует случайные файлы с числами и сохраняет их в папке data. 
+2. **Первое приложение**
+    app.py, случайным образом получает один файл из папки data и копирует его содержимое в result/data.txt. 
+3. **Второе приложение**
+    app.py, находит произведение первого и последнего чисел из result/data.txt и записывает в result/result.txt. 
+4. **Файла docker-compose.yml**
+    docker-compose.yml построчно описан в комментариях в коде.
+
+Файл Docker построчно описан в коде на примере Docker первого сервиса app_1.
\ No newline at end of file
diff --git a/melnikov_igor_lab_2/app_1/Dockerfile b/melnikov_igor_lab_2/app_1/Dockerfile
new file mode 100644
index 0000000..007eb06
--- /dev/null
+++ b/melnikov_igor_lab_2/app_1/Dockerfile
@@ -0,0 +1,13 @@
+# Указываем базовый образ для Docker
+#slim означает, что это более компактный, содержащий только основные компоненты Python, что уменьшает размер образа
+FROM python:3.9-slim
+
+# Устанавливаем рабочую директорию внутри контейнера Docker в /app. 
+# Все последующие команды в Dockerfile будут выполняться в этой директории.
+WORKDIR /app
+
+# Перемещаем файл в контейнер
+COPY app.py /app/
+
+# Указываем команду, которая будет выполняться при запуске контейнера
+CMD ["python", "app.py"]
diff --git a/melnikov_igor_lab_2/app_1/app.py b/melnikov_igor_lab_2/app_1/app.py
new file mode 100644
index 0000000..1994c5c
--- /dev/null
+++ b/melnikov_igor_lab_2/app_1/app.py
@@ -0,0 +1,28 @@
+import os
+import random
+
+def find_shortest_filename(source_dir, result_file):
+    # Проверяем есть ли папка result, если нет - создаем
+    result_dir = os.path.dirname(result_file)
+    if not os.path.exists(result_dir):
+        os.makedirs(result_dir)
+        print(f"Created directory {result_dir}")
+    
+    files = [f for f in os.listdir(source_dir) if os.path.isfile(os.path.join(source_dir, f))]
+    
+    if not files:
+        print(f"No files found in {source_dir}")
+        return
+    
+    # Выбор случайного файла
+    random_file = random.choice(files)
+    random_file_path = os.path.join(source_dir, random_file)
+    
+    # Копируем файл в result/data.txt., если файл уже есть перезаписываем
+    with open(random_file_path, 'r') as f_in, open(result_file, 'w') as f_out:
+        f_out.write(f_in.read())
+
+    print(f"Moved {random_file} to {result_file}")
+
+if __name__ == "__main__":
+    find_shortest_filename('/var/data', '/var/result/data.txt')
diff --git a/melnikov_igor_lab_2/app_2/Dockerfile b/melnikov_igor_lab_2/app_2/Dockerfile
new file mode 100644
index 0000000..2e497ae
--- /dev/null
+++ b/melnikov_igor_lab_2/app_2/Dockerfile
@@ -0,0 +1,8 @@
+# См. описание Dockerfile для первого приложения app_1
+FROM python:3.9-slim
+
+WORKDIR /app
+
+COPY app.py /app/
+
+CMD ["python", "app.py"]
diff --git a/melnikov_igor_lab_2/app_2/app.py b/melnikov_igor_lab_2/app_2/app.py
new file mode 100644
index 0000000..75222e2
--- /dev/null
+++ b/melnikov_igor_lab_2/app_2/app.py
@@ -0,0 +1,27 @@
+import os
+
+def multiply_first_and_last(input_file, output_file):
+    # Проверяем, существует файл data.txt
+    if not os.path.exists(input_file):
+        print(f"File {input_file} does not exist.")
+        return
+
+    # Считываем содержимое файла
+    with open(input_file, 'r') as f:
+        numbers = [int(line.strip()) for line in f.readlines()]
+    
+    if numbers:
+        first_number = numbers[0]
+        last_number = numbers.pop()
+        result = first_number * last_number
+
+        # Записываем полученный результата в result.txt
+        with open(output_file, 'w') as f_out:
+            f_out.write(str(result))
+
+        print(f"Saved {first_number}х{last_number} to {output_file}")
+    else:
+        print(f"No numbers found in {input_file}")
+
+if __name__ == "__main__":
+    multiply_first_and_last('/var/result/data.txt', '/var/result/result.txt')
diff --git a/melnikov_igor_lab_2/docker-compose.yml b/melnikov_igor_lab_2/docker-compose.yml
new file mode 100644
index 0000000..c516177
--- /dev/null
+++ b/melnikov_igor_lab_2/docker-compose.yml
@@ -0,0 +1,27 @@
+services:
+# сервис, отвечающий за генерацию файлов
+  generator:
+    build: 
+      context: ./generator # путь к директории с Dockerfile для генерации
+    volumes:
+      - ./data:/var/data # монтирование локальной директории ./data в директорию /var/data внутри контейнера
+    entrypoint: python generate_files.py # запуск скрипта генерации
+
+  # Первый сервис, получающий случайный файл
+  app_1:
+    build: 
+      context: ./app_1 # путь к директории с Dockerfile для первого сервиса
+    volumes:
+      - ./data:/var/data # Монтирование локальной директории data в /var/data
+      - ./result:/var/result # Монтирование локальной директории data в /var/result 
+    depends_on: # Указывает, что первый сервис зависит от генератора
+      - generator  
+
+  # Второй сервис, считающий произведение первого и последнего чисел из файла
+  app_2:
+    build: 
+      context: ./app_2 # путь к директории с Dockerfile для второго сервиса
+    volumes:
+      - ./result:/var/result # Монтирование локальной директории data в /var/result 
+    depends_on: # Указывает, что второй сервис зависит от первого
+      - app_1  
\ No newline at end of file
diff --git a/melnikov_igor_lab_2/generator/Dockerfile b/melnikov_igor_lab_2/generator/Dockerfile
new file mode 100644
index 0000000..5c924e5
--- /dev/null
+++ b/melnikov_igor_lab_2/generator/Dockerfile
@@ -0,0 +1,7 @@
+# См. описание Dockerfile для первого приложения app_1
+FROM python:3.9-slim 
+
+WORKDIR /app
+COPY generate_files.py /app/
+
+CMD ["python", "generate_files.py"]
\ No newline at end of file
diff --git a/melnikov_igor_lab_2/generator/generate_files.py b/melnikov_igor_lab_2/generator/generate_files.py
new file mode 100644
index 0000000..2db8ac7
--- /dev/null
+++ b/melnikov_igor_lab_2/generator/generate_files.py
@@ -0,0 +1,31 @@
+import os
+import random
+import string
+
+def generate_random_filename(length):
+    return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length)) + '.txt'
+
+def generate_data_files(directory, num_files, min_lines, max_lines):
+    # Создание директории, если таковой не существует
+    if not os.path.exists(directory):
+        os.makedirs(directory)
+
+    # Проверка, пустая ли директория
+    if os.listdir(directory):
+        print(f"{directory} is not empty, skipping file generation.")
+        return
+
+    # Генерация файлов
+    for _ in range(num_files):
+        file_name = generate_random_filename(random.randint(1, 20))
+        file_path = os.path.join(directory, file_name)
+        
+        with open(file_path, 'w') as f:
+            num_lines = random.randint(min_lines, max_lines)
+            for _ in range(num_lines):
+                f.write(f"{random.randint(1, 1000)}\n")
+        
+        print(f"Generated file: {file_path}")
+
+if __name__ == "__main__":
+    generate_data_files('/var/data', num_files=random.randint(5, 15), min_lines=1, max_lines=50)