Merge pull request 'fadeeva_nastya_lab_2 is ready' (#293) from fadeeva_nastya_lab_2 into main

Reviewed-on: #293
This commit is contained in:
Alexey 2024-12-15 14:23:01 +04:00
commit 31346e7082
17 changed files with 500 additions and 0 deletions

View File

@ -0,0 +1,52 @@
# Лабораторная работа №2 - Разработка простейшего распределённого приложения
## Задание
+ По выбранному варианту разработать два приложения такие, что результат первого является исходными данными для второго.
+ Изучить файлы сборки образов docker и разработать их для созданных приложений.
+ Собрать файл docker-compose.yml для запуска приложений.
+ Правильно закоммитить результат.
### Выбранные варианты задания
1. 1-ая программа. Берёт из каталога /var/data случайный файл и перекладывает его в /var/result/data.txt.
2. 2-ая программа. Сохраняет произведение первого и последнего числа из файла /var/result/data.txt в /var/result/result.txt.
### Дополнительная информация
+ Язык разработки приложений - pyton.
+ Содержимое исходных файлов - целые числа.
+ Каждая программа должна лежать в отдельной подпапке.
## Запуск работы программы
Для задания потребуется Docker - платформа для контейнеризации приложений.
В директории создаем файл docker-compose.yaml, чтобы потом можно было собрать и запустить программы всех сервисов:
```docker-compose up --build```
Эта команда сначала выполнит сборку, а затем запустит контейнеры.
После успешного запуска появится папка data со сгенерированными файлами и папка result, в которой два текстовых файла:
+ data.txt - файл, полученный после выполнения первой программы.
+ result.txt -файл, полученный после выполнения второй программы.
## Описание работы
В лабораторке использовали:
1. Генератор файлов в папке generator. Файл generate_files.py, генерирует случайные файлы с числами и сохраняет их в папке data.
2. Папка с первым приложением. Первое приложение worker.py, случайным образом получает один файл из папки data и копирует его содержимое в result/data.txt.
3. Папка со вторым приложением. Второе приложение worker.py находит произведение первого и последнего чисел из result/data.txt и записывает в result/result.txt.
4. Файл docker-compose.yml.
5. Файл Dockerfile. Прописываем базовый образ для Docker.
# Видеозапись работы программмы
https://vkvideo.ru/video186826232_456239553

View File

@ -0,0 +1,45 @@
1000
351
352
836
805
140
108
778
482
196
671
8
58
572
409
269
390
198
62
545
913
109
639
52
947
56
316
578
938
626
952
39
363
680
203
874
308
443
712
781
114
605
74
198
822

View File

@ -0,0 +1,49 @@
478
840
280
940
908
434
98
291
232
486
297
618
764
386
179
308
474
543
619
569
172
227
949
679
804
861
680
998
439
399
673
434
188
815
355
386
808
570
719
635
378
423
93
212
652
698
139
625
691

View File

@ -0,0 +1,47 @@
392
303
278
602
798
208
513
828
713
986
428
675
511
950
646
618
533
432
975
234
891
304
22
634
787
201
216
363
447
402
23
357
171
682
845
50
680
647
953
944
594
657
305
28
78
788
741

View File

@ -0,0 +1 @@
96

View File

@ -0,0 +1,40 @@
884
985
757
289
855
941
500
427
958
508
206
710
721
38
471
855
805
785
333
828
135
211
745
427
886
355
611
69
521
168
132
964
444
785
303
771
832
556
47
946

View File

@ -0,0 +1,34 @@
79
45
347
611
960
291
379
154
531
700
770
399
611
442
458
75
968
474
491
860
635
414
822
800
134
535
961
382
273
173
833
425
286
735

View File

@ -0,0 +1,45 @@
789
914
706
57
225
252
166
253
455
589
809
366
268
625
910
828
371
972
269
801
677
517
209
461
281
104
636
515
1
41
362
416
313
883
809
287
49
874
29
383
491
242
258
489
780

View File

@ -0,0 +1,27 @@
services:
# сервис, отвечающий за генерацию файлов
generator:
build:
context: ./generator # путь к директори с Dokcerfile для генерации
volumes:
- ./data:/var/data # монтирование локальной директории ./data в директорию /var/data внутри контейнера
entrypoint: python generate_files.py # запуск скрипта генерации
# Первый сервис, получающий случайный файл
worker_1:
build:
context: ./worker_1 # путь к директори с Dokcerfile для первого сервиса
volumes:
- ./data:/var/data # Монтирование локальной директории data в /var/data
- ./result:/var/result # Монтирование локальной директории data в /var/result
depends_on: # Указывает, что первый сервис зависит от генератора
- generator
# Второй сервис, считающий произведение первого и последнего чисел из файла
worker_2:
build:
context: ./worker_2 # путь к директори с Dokcerfile для второго сервиса
volumes:
- ./result:/var/result # Монтирование локальной директории data в /var/result
depends_on: # Указывает, что второй сервис зависит от первого
- worker_1

View File

@ -0,0 +1,13 @@
# Указываем базовый образ для Docker
#slim означает, что это более компактный, содержащий только основные компоненты Python, что уменьшает размер образа
FROM python:3.9-slim
# Устанавливаем рабочую директорию внутри контейнера Docker в /worker.
# Все последующие команды в Dockerfile будут выполняться в этой директории.
WORKDIR /worker
# Перемещаем файл в контейнер
COPY generate_files.py /worker/
# Указываем команду, которая будет выполняться при запуске контейнера
CMD ["python", "generate_files.py"]

View File

@ -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)

View File

@ -0,0 +1,34 @@
79
45
347
611
960
291
379
154
531
700
770
399
611
442
458
75
968
474
491
860
635
414
822
800
134
535
961
382
273
173
833
425
286
735

View File

@ -0,0 +1 @@
58065

View File

@ -0,0 +1,13 @@
# Указываем базовый образ для Docker
#slim означает, что это более компактный, содержащий только основные компоненты Python, что уменьшает размер образа
FROM python:3.9-slim
# Устанавливаем рабочую директорию внутри контейнера Docker в /worker.
# Все последующие команды в Dockerfile будут выполняться в этой директории.
WORKDIR /worker
# Перемещаем файл в контейнер
COPY worker.py /worker/
# Указываем команду, которая будет выполняться при запуске контейнера
CMD ["python", "worker.py"]

View File

@ -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')

View File

@ -0,0 +1,13 @@
# Указываем базовый образ для Docker
#slim означает, что это более компактный, содержащий только основные компоненты Python, что уменьшает размер образа
FROM python:3.9-slim
# Устанавливаем рабочую директорию внутри контейнера Docker в /worker.
# Все последующие команды в Dockerfile будут выполняться в этой директории.
WORKDIR /worker
# Перемещаем файл в контейнер
COPY worker.py /worker/
# Указываем команду, которая будет выполняться при запуске контейнера
CMD ["python", "worker.py"]

View File

@ -0,0 +1,27 @@
import os
def find_smallest_number_and_cube(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__":
find_smallest_number_and_cube('/var/result/data.txt', '/var/result/result.txt')