├── .gitignore ├── .golangci.yml ├── 01-anti-bruteforce.md ├── 02-banners-rotation.md ├── 03-image-previewer.md ├── 04-sql-migrator.md ├── 05-system-stats-daemon.md ├── README.md └── examples ├── banners-rotation └── conceptual_model.png └── image-previewer ├── _gopher_original_1024x504.jpg ├── gopher_1024x252.jpg ├── gopher_2000x1000.jpg ├── gopher_200x700.jpg ├── gopher_256x126.jpg ├── gopher_333x666.jpg ├── gopher_500x500.jpg └── gopher_50x50.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE system files 2 | .idea 3 | .vscode 4 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | tests: true 3 | 4 | linters-settings: 5 | funlen: 6 | lines: 150 7 | statements: 80 8 | 9 | linters: 10 | disable-all: true 11 | enable: 12 | - asciicheck 13 | - bodyclose 14 | - deadcode 15 | - depguard 16 | - dogsled 17 | - dupl 18 | - durationcheck 19 | - errorlint 20 | - exhaustive 21 | - exportloopref 22 | - funlen 23 | - gci 24 | - gocognit 25 | - goconst 26 | - gocritic 27 | - gocyclo 28 | - godot 29 | - gofmt 30 | - gofumpt 31 | - goheader 32 | - gomoddirectives 33 | - gomodguard 34 | - goprintffuncname 35 | - gosec 36 | - gosimple 37 | - govet 38 | - ifshort 39 | - importas 40 | - ineffassign 41 | - lll 42 | - makezero 43 | - misspell 44 | - nestif 45 | - nilerr 46 | - noctx 47 | - nolintlint 48 | - prealloc 49 | - predeclared 50 | - revive 51 | - rowserrcheck 52 | - sqlclosecheck 53 | - staticcheck 54 | - structcheck 55 | - stylecheck 56 | - tagliatelle 57 | - thelper 58 | - tparallel 59 | - typecheck 60 | - unconvert 61 | - unparam 62 | - unused 63 | - varcheck 64 | - wastedassign 65 | - whitespace 66 | -------------------------------------------------------------------------------- /01-anti-bruteforce.md: -------------------------------------------------------------------------------- 1 | # ТЗ на разработку сервиса "Анти-брутфорс" 2 | 3 | ## Общее описание 4 | Сервис предназначен для борьбы с подбором паролей при авторизации в какой-либо системе. 5 | 6 | Сервис вызывается перед авторизацией пользователя и может либо разрешить, либо заблокировать попытку. 7 | 8 | Предполагается, что сервис используется только для server-server, т.е. скрыт от конечного пользователя. 9 | 10 | ## Алгоритм работы 11 | Сервис ограничивает частоту попыток авторизации для различных комбинаций параметров, например: 12 | * не более N = 10 попыток в минуту для данного логина. 13 | * не более M = 100 попыток в минуту для данного пароля (защита от обратного brute-force). 14 | * не более K = 1000 попыток в минуту для данного IP (число большое, т.к. NAT). 15 | 16 | Для подсчета и ограничения частоты запросов, можно использовать например алгоритм leaky bucket. 17 | Или иные аналогичные: https://en.wikipedia.org/wiki/Rate_limiting 18 | 19 | Причем сервис будет поддерживать множество bucket-ов, по одному на каждый логин/пароль/ip. 20 | 21 | Bucket-ы можно хранить: 22 | * в памяти (в таком случае нужно продумать удаление неактивных bucket-ов, чтобы избежать утечек памяти). 23 | * во внешнем хранилище (например redis или СУБД, в таком случае нужно продумать производительность). 24 | 25 | White/black листы содержат списки адресов сетей, которые обрабатываются более простым способом: 26 | * Если входящий IP в whitelist, то сервис безусловно разрешает авторизацию (ok=true); 27 | * Если - в blacklist, то отклоняет (ok=false). 28 | 29 | ## Архитектура 30 | Микросервис состоит из API, базы данных для хранения настроек и black/white списков. 31 | Опционально - хранилище для bucket'ов. Сервис должен предоставлять GRPC **или** REST API. 32 | 33 | ## Описание методов API 34 | 35 | ### Попытка авторизации 36 | Запрос: 37 | * login 38 | * password 39 | * ip 40 | 41 | Ответ: 42 | * ok (true/false) - сервис должен возвращать ok=true, если считает что запрос нормальный 43 | и ok=false, если считает что происходит bruteforce. 44 | 45 | ### Сброс bucket 46 | Должен очистить bucket-ы соответствующие переданным login и ip. 47 | * login 48 | * ip 49 | 50 | ### Добавление IP в blacklist 51 | * подсеть (IP + маска) 52 | 53 | ### Удаление IP из blacklist 54 | * подсеть (IP + маска) 55 | 56 | ### Добавление IP в whitelist 57 | * подсеть (IP + маска) 58 | 59 | ### Удаление IP из whitelist 60 | * подсеть (IP + маска) 61 | 62 | --- 63 | 64 | - Достаточно IPv4 65 | - Пример подсети: 192.1.1.0/25 - представляет собой адрес 192.1.1.0 с маской 255.255.255.128 66 | - Во время работы сервиса при поступлении очередного IP мы проходимся по подсетям в черных и белых списках и вычисляем, принадлежит ли IP одной из них. 67 | 68 | --- 69 | 70 | ## Конфигурация 71 | Основные параметры конфигурации: N, M, K - лимиты по достижению которых, сервис считает попытку брутфорсом. 72 | 73 | ## Command-Line интерфейс 74 | Необходимо так же разработать command-line интерфейс для ручного администрирования сервиса. 75 | Через CLI должна быть возможность вызвать сброс бакета и управлять whitelist/blacklist-ом. 76 | CLI может работать через GRPC/HTTP интерфейс. 77 | 78 | ## Развертывание 79 | Развертывание микросервиса должно осуществляться командой `make run` (внутри `docker compose up`) 80 | в директории с проектом. 81 | 82 | ## Тестирование 83 | Рекомендуется выделить модуль обработки одного bucket и протестировать его с помощью unit-тестов. 84 | 85 | Так же необходимо написать интеграционные тесты, проверяющие все вызовы API. 86 | 87 | ## Разбалловка 88 | Максимум - **15 баллов** 89 | (при условии выполнения [обязательных требований](./README.md)): 90 | 91 | * Реализован алгоритм rate limit - 2 балла. 92 | * Реализованы фичи whitelist/blacklist - 2 балла. 93 | * Реализовано API сервиса - 2 балла. 94 | * Реализован CLI-интерфейс - 1 балла. 95 | * Написаны юнит-тесты - 1 балл. 96 | * Написаны интеграционные тесты - 2 балла. 97 | * Тесты адекватны и полностью покрывают функциональность - 1 балл. 98 | * Проект возможно собрать через `make build`, запустить через `make run` 99 | и протестировать через `make test` - 1 балл. 100 | * Понятность и чистота кода - до 3 баллов. 101 | 102 | #### Зачёт от 10 баллов 103 | -------------------------------------------------------------------------------- /02-banners-rotation.md: -------------------------------------------------------------------------------- 1 | # ТЗ на разработку сервиса "Ротация баннеров" 2 | 3 | ## Общее описание 4 | Сервис "Ротация баннеров" предназначен для выбора наиболее эффективных (кликабельных) баннеров, 5 | в условиях меняющихся предпочтений пользователей и набора баннеров. 6 | 7 | Предположим, что на сайте есть место для показа баннеров (слот) и есть набор баннеров, которые 8 | конкурируют за право показа в этом месте. Набор баннеров постоянно обновляется - добавляются новые, 9 | старые удаляются. Так же у пользователя меняются предпочтения - если им показывать все время один 10 | и тот же баннер, пользователь перестает его замечать. 11 | 12 | **Задача сервиса - осуществлять "ротацию" баннеров, показывая те, которые наиболее вероятно приведут 13 | к переходу**. Для этого предполагается использовать алгоритм "Многорукий бандит": 14 | https://habr.com/ru/company/surfingbird/blog/168611/ 15 | 16 | Кроме того пользователи неоднородны - их можно условно разделить на социально-демографические группы. 17 | В разных группах пользователей могут быть разные предпочтения. 18 | 19 | 20 | 21 | ## Архитектура 22 | Сервис состоит из API и базы данных в которой хранится информация о баннерах. 23 | Сервис должен предоставлять GRPC **или** REST API. 24 | 25 | ## Описание сущностей 26 | ### Слот 27 | Слот - место на сайте, на котором мы показываем баннер. 28 | * ID 29 | * Описание 30 | 31 | ### Баннер 32 | Баннер - рекламный/информационный элемент, который показывается в слоте. 33 | * ID 34 | * Описание 35 | 36 | Один баннер может участвовать в ротации в нескольких слотах. 37 | 38 | Статистика по баннеру ведется в рамках одного слота. 39 | 40 | ### Соц-дем. группа пользователей 41 | Соц-дем. группа - это группа пользователей сайта со схожими интересами, 42 | например "девушки 20-25" или "дедушки 80+". 43 | * ID 44 | * Описание 45 | 46 | ## Описание методов 47 | 48 | ### Добавить баннер 49 | Добавляет новый баннер в ротацию в данном слоте. 50 | * ID баннера 51 | * ID слота 52 | 53 | ### Удалить баннер 54 | Удаляет баннер из ротации в данном слоте. 55 | * ID слота 56 | * ID баннера 57 | 58 | ### Засчитать переход 59 | Увеличивает счетчик переходов на 1 для указанного баннера в данном слоте в указанной группе. 60 | * ID слота 61 | * ID баннера 62 | * ID соц-дем. группы 63 | 64 | ### Выбрать баннер для показа 65 | Основной метод. Возвращает баннер, который следует показать в данный момент в указанном 66 | слоте для указанной соц-дем. группы. Увеличивает число показов баннера в группе. 67 | 68 | Принимает: 69 | * ID слота 70 | * ID соц-дем. группы 71 | 72 | Возвращает: 73 | * ID баннера 74 | 75 | ## Выгрузка статистики 76 | Микросервис должен отправлять события кликов и показов в очередь (например kafka) 77 | для дальнейшей обработки в аналитических системах. 78 | 79 | Формат событий следующий: 80 | * Тип: клик или показ 81 | * ID слота 82 | * ID баннера 83 | * ID соц.дем группы 84 | * Дата и время 85 | 86 | ## Развертывание 87 | Развертывание микросервиса должно осуществляться командой `make run` (внутри `docker compose up`) 88 | в директории с проектом. 89 | 90 | ## Тестирование 91 | Алгоритм "многорукого бандита" рекомендуется выделить в отдельный модуль и покрыть unit-тестами. 92 | 93 | Также необходимо написать интеграционные тесты проверяющие работу сервиса через его API. 94 | 95 | При тестировании необходимо проверить сценарии: 96 | * Перебор всех: после большого количества показов, каждый баннер должен быть показан хотя один раз. 97 | * Выбор популярных: если на один из баннеров кликают, у него должно быть существенно больше показов чем у остальных. 98 | 99 | ## Разбалловка 100 | Максимум - **15 баллов** 101 | (при условии выполнения [обязательных требований](./README.md)): 102 | 103 | * Реализован алгоритм "многорукого бандита" - 2 балла. 104 | * Реализовано разделение на "слоты" и "соц.дем. группы" - 2 балла. 105 | * Реализовано API сервиса - 2 балла. 106 | * Реализована отправка статистики в очередь - 1 балл. 107 | * Написаны юнит-тесты - 1 балл. 108 | * Написаны интеграционные тесты - 2 балла. 109 | * Тесты адекватны и полностью покрывают функциональность - 1 балл. 110 | * Проект возможно собрать через `make build`, запустить через `make run` 111 | и протестировать через `make test` - 1 балл. 112 | * Понятность и чистота кода - до 3 баллов. 113 | 114 | #### Зачёт от 10 баллов 115 | -------------------------------------------------------------------------------- /03-image-previewer.md: -------------------------------------------------------------------------------- 1 | # ТЗ на разработку сервиса "Превьювер изображений" 2 | 3 | ## Общее описание 4 | Сервис предназначен для изготовления preview (создания изображения 5 | с новыми размерами на основе имеющегося изображения). 6 | 7 | #### Пример превьюшек в папке [examples](./examples/image-previewer) 8 | 9 | ## Архитектура 10 | Сервис представляет собой web-сервер (прокси), загружающий изображения, 11 | масштабирующий/обрезающий их до нужного формата и возвращающий пользователю. 12 | 13 | ## Основной обработчик 14 | http://cut-service.com/fill/300/200/raw.githubusercontent.com/OtusGolang/final_project/master/examples/image-previewer/_gopher_original_1024x504.jpg 15 | 16 | <---- микросервис ----><- размеры превью -><--------- URL исходного изображения ---------------------------------> 17 | 18 | В URL выше мы видим: 19 | - http://cut-service.com/fill/300/200/ - endpoint нашего сервиса, 20 | в котором 300x200 - это размеры финального изображения. 21 | - https://raw.githubusercontent.com/OtusGolang/final_project/master/examples/image-previewer/_gopher_original_1024x504.jpg - 22 | адрес исходного изображения; сервис должен скачать его, произвести resize, закэшировать и отдать клиенту. 23 | 24 | Сервис должен получить URL исходного изображения, скачать его, изменить до необходимых размеров и вернуть как HTTP-ответ. 25 | 26 | - Работаем только с HTTP. 27 | - Ошибки удалённого сервиса или проксируем как есть, или логируем и отвечаем клиенту 502 Bad Gateway. 28 | - Поддержка JPEG является минимальным и достаточным требованием. 29 | 30 | **Важно**: необходимо проксировать все заголовки исходного HTTP запроса к целевому сервису (raw.githubusercontent.com в примере). 31 | 32 | Сервис должен сохранить (кэшировать) полученное preview на локальном диске и при повторном запросе 33 | отдавать изображение с диска, без запроса к удаленному HTTP-серверу. 34 | 35 | Поскольку размер места для кэширования ограничен, то для удаления редко используемых изображений 36 | необходимо использовать алгоритм **"Least Recent Used"**. 37 | 38 | ## Конфигурация 39 | Основной параметр конфигурации сервиса - разрешенный размер LRU-кэша. 40 | 41 | Он может измеряться как количеством закэшированных изображений, так и суммой их байт (на выбор разработчика). 42 | 43 | ## Развертывание 44 | Развертывание микросервиса должно осуществляться командой `make run` (внутри `docker compose up`) 45 | в директории с проектом. 46 | 47 | ## Тестирование 48 | Реализацию алгоритма LRU нужно покрыть unit-тестами. 49 | 50 | Для интеграционного тестирования можно использовать контейнер с Nginx в качестве удаленного HTTP-сервера, 51 | раздающего вам заданный набор изображений. 52 | 53 | Необходимо проверить работу сервера в разных сценариях: 54 | * картинка найдена в кэше; 55 | * удаленный сервер не существует; 56 | * удаленный сервер существует, но изображение не найдено (404 Not Found); 57 | * удаленный сервер существует, но изображение не изображение, а скажем, exe-файл; 58 | * удаленный сервер вернул ошибку; 59 | * удаленный сервер вернул изображение; 60 | * изображение меньше, чем нужный размер; 61 | и пр. 62 | 63 | ## Разбалловка 64 | Максимум - **15 баллов** 65 | (при условии выполнения [обязательных требований](./README.md)): 66 | 67 | * Реализован HTTP-сервер, проксирующий запросы к удаленному серверу - 2 балла. 68 | * Реализована нарезка изображений - 2 балла. 69 | * Кэширование нарезанных изображений на диске - 1 балл. 70 | * Ограничение кэша одним из способов (LRU кэш) - 1 балл. 71 | * Прокси сервер правильно передает заголовки запроса - 1 балл. 72 | * Написаны интеграционные тесты - 3 балла. 73 | * Тесты адекватны и полностью покрывают функциональность - 1 балл. 74 | * Проект возможно собрать через `make build`, запустить через `make run` 75 | и протестировать через `make test` - 1 балл. 76 | * Понятность и чистота кода - до 3 баллов. 77 | 78 | #### Зачёт от 10 баллов 79 | -------------------------------------------------------------------------------- /04-sql-migrator.md: -------------------------------------------------------------------------------- 1 | # ТЗ на разработку инструмента "SQL-мигратор" 2 | 3 | ## Общее описание 4 | Аналог инструментов, приведенных в секции "Database schema migration" 5 | [awesome-go](https://github.com/avelino/awesome-go). 6 | 7 | Тулза, работающая с миграциями, написанными на Go или представленными в виде SQL-файлов. 8 | 9 | Позволяет: 10 | - генерировать шаблон миграции; 11 | - применять миграции; 12 | - откатывать миграции. 13 | 14 | ## Архитектура 15 | Тулза должна создавать свои служебные таблицы в БД и работать с ними. 16 | 17 | ## Требования 18 | Тулза устанавливается в `$GOPATH/bin` командой `go get github.com/awesomegother/migrator/cmd/gomigrator`. 19 | 20 | Или можно использовать её API в своих программах напрямую, импортировав библиотеку как пакет. 21 | 22 | При этом вся логика тулзы должна располагаться в `internal`, а экспортируемое API в `pkg`. 23 | 24 | ### Команды 25 | Необходимо реализовать следующие команды (флаги команд см. в разделе **Конфигурирование**). 26 | 27 | #### Создание миграции 28 | ``` 29 | $ gomigrator create <имя_миграции> 30 | ``` 31 | 32 | #### Применение всех миграций 33 | ``` 34 | $ gomigrator up 35 | ``` 36 | 37 | #### Откат последней миграции 38 | ``` 39 | $ gomigrator down 40 | ``` 41 | 42 | #### Повтор последней миграции (откат + накат) 43 | ``` 44 | $ gomigrator redo 45 | ``` 46 | 47 | #### Вывод статуса миграций 48 | ``` 49 | $ gomigrator status 50 | ``` 51 | Таблица из: 52 | - Статус (применена, применяется, ошибка и пр.) 53 | - Время последнего обновления статуса 54 | - Имя миграции 55 | 56 | #### Вывод версии базы 57 | ``` 58 | $ gomigrator dbversion 59 | ``` 60 | \- по сути номер последней примененной миграции. 61 | 62 | ### Формат миграций 63 | Вы должны предоставить пользователю API для описания up/down шагов миграции. 64 | 65 | Если миграция в формате Go-кода, то она может иметь формат: 66 | ```golang 67 | func Up_migration(o *someObject) { 68 | } 69 | 70 | func Down_migration(o *someObject) { 71 | } 72 | ``` 73 | Где `someObject` - один из аргументов, которые вы считаете, могут пригодиться 74 | при описании миграции (транзакция, структура вашей библиотеки и пр.) 75 | 76 | Если миграция в формате SQL, то необходимо придумать способ разделения 77 | между Up и Down шагами, например, с помощью комментариев. 78 | 79 | ### Драйвер 80 | Поддержки PostgreSQL достаточно. 81 | 82 | ### Консистентность 83 | Запуск тулзы в параллельных процессах возможен (например, две ноды приложения решили на старте применить 84 | свои миграции), при этом процессы не должны мешать друг другу и дублировать свои миграции, 85 | что можно реализовать с помощью блокировок на уровне БД (`SELECT FOR UPDATE`, `pg_advisory_lock`, etc). 86 | 87 | Если идентификаторы миграций совпадают (ID, время, имя, пр. атрибут, который вы решили 88 | выбрать для идентификации миграции), то возможно, что один из процессов пропускает 89 | свои миграции, так как они уже применены другим. 90 | 91 | ### Логирование 92 | На ваше усмотрение, но здорово, когда инструмент имеет понятный и подробный 93 | вывод о ходе своей работы и статусе выполнения команды (ошибка, успех, 94 | что было сделано, какие идентификаторы и пр.). 95 | 96 | ## Конфигурация 97 | Основные параметры: 98 | * Строка подключения (DSN) к БД 99 | * Путь к директории с файлами миграций 100 | * Тип миграции: `go`/`sql` 101 | 102 | Конфигурировать должно быть можно как через аргументы командной строки, 103 | так и через файл, при этом в файле можно указывать переменные окружения, 104 | которые [должны заэкспандиться](https://golang.org/pkg/os/#ExpandEnv): 105 | ```yaml 106 | dsn: $DB_DSN 107 | ``` 108 | 109 | ## Тестирование 110 | #### Юнит-тесты 111 | - по возможности мок интерфейсов и проверка вызовов конкретных методов; 112 | - тесты вспомогательных функций и пр. 113 | 114 | #### Интеграционные тесты 115 | - docker-compose + проверка работы тулзы на контейнере с PSQL; 116 | - тестовые миграции можно хардкодить; 117 | - можно напрямую дергать PSQL, чтобы проверить результат миграций. 118 | 119 | ## Разбалловка 120 | Максимум - **15 баллов** 121 | (при условии выполнения [обязательных требований](./README.md)): 122 | 123 | * Можно использовать как отдельную тулзу - 1 балл. 124 | * Можно использовать как библиотеку из кода - 1 балл. 125 | * Поддержка миграций на Go - 2 балла. 126 | * Поддержка миграций на SQL - 2 балла. 127 | * Реализован механизм блокировки на время миграции - 1 балл. 128 | * Реализованы различные способы конфигурирования - 2 балла. 129 | * Написаны юнит-тесты - 1 балл. 130 | * Написаны интеграционные тесты - 2 балла. 131 | * Тесты адекватны и полностью покрывают функциональность - 1 балл. 132 | * Понятность и чистота кода - до 3 баллов. 133 | 134 | #### Зачёт от 10 баллов 135 | -------------------------------------------------------------------------------- /05-system-stats-daemon.md: -------------------------------------------------------------------------------- 1 | # ТЗ на разработку демона, осуществляющего "Системный мониторинг" 2 | 3 | ## Общее описание 4 | Демон - программа, собирающая информацию о системе, на которой запущена, 5 | и отправляющая её своим клиентам по GRPC. 6 | 7 | ## Архитектура 8 | - GRPC сервер; 9 | - допускается использование временных (`/tmp`) файлов; 10 | - статистика хранится в памяти, долговременное хранение не предусмотрено. 11 | 12 | ## Требования 13 | Необходимо каждые **N** секунд выдавать информацию, усредненную за последние **M** секунд. 14 | 15 | Например, N = 5с, а M = 15с, тогда демон "молчит" первые 15 секунд, 16 | затем выдает снапшот за 0-15с; через 5с (в 20с) выдает снапшот за 5-20с; 17 | через 5с (в 25с) выдает снапшот за 10-25с и т.д. 18 | 19 | **N** и **M** указывает клиент в запросе на получение статистики. 20 | 21 | Что необходимо собирать: 22 | - Средняя загрузка системы (load average). 23 | 24 | - Средняя загрузка CPU (%user_mode, %system_mode, %idle). 25 | 26 | - Загрузка дисков: 27 | - tps (transfers per second); 28 | - KB/s (kilobytes (read+write) per second); 29 | 30 | - Информация о дисках по каждой файловой системе: 31 | - использовано мегабайт, % от доступного количества; 32 | - использовано inode, % от доступного количества. 33 | 34 | - Top talkers по сети: 35 | - по протоколам: protocol (TCP, UDP, ICMP, etc), bytes, % от sum(bytes) за последние **M**), сортируем по убыванию процента; 36 | - по трафику: source ip:port, destination ip:port, protocol, bytes per second (bps), сортируем по убыванию bps. 37 | 38 | - Статистика по сетевым соединениям: 39 | - слушающие TCP & UDP сокеты: command, pid, user, protocol, port; 40 | - количество TCP соединений, находящихся в разных состояниях (ESTAB, FIN_WAIT, SYN_RCV и пр.). 41 | 42 | #### Разрешено использовать только стандартную библиотеку языка Go! 43 | 44 | Команды, которые могут пригодиться: 45 | ``` 46 | $ top -b -n1 47 | $ df -k 48 | $ df -i 49 | $ iostat -d -k 50 | $ cat /proc/net/dev 51 | $ sudo netstat -lntup 52 | $ ss -ta 53 | $ tcpdump -ntq -i any -P inout -l 54 | $ tcpdump -nt -i any -P inout -ttt -l 55 | ``` 56 | 57 | Статистика представляет собой объекты, описанные в формате Protobuf. 58 | 59 | Информацию необходимо выдавать всем подключенным по GRPC клиентам 60 | с использованием [однонаправленного потока](https://grpc.io/docs/tutorials/basic/go/#server-side-streaming-rpc). 61 | 62 | Выдавать "снапшот" системы можно как отдельными сообщениями, так и одним жирным объектом. 63 | 64 | Сбор информации, её парсинг и пр. должен осуществляться как можно более конкурентно. 65 | 66 | ## Поддерживаемая ОС 67 | Минимум - Linux (Ubuntu 18.04). 68 | 69 | Максимум - несколько сборок под набор из популярных ОС/процессоров: 70 | - darwin, linux, windows 71 | - 386, amd64 72 | 73 | [Список возможных вариантов](https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63). 74 | 75 | Но тогда придется постараться с реализацией использования различных команд для сбора данных. 76 | 77 | Пригодятся [build тэги](https://www.digitalocean.com/community/tutorials/building-go-applications-for-different-operating-systems-and-architectures). 78 | 79 | ## Конфигурация 80 | - Через аргументы командной строки можно указать, на каком порту стартует сервер. 81 | - Через файл можно указать, какие из подсистем сбора включены/выключены. 82 | 83 | ## Тестирование 84 | #### Юнит-тесты 85 | - по возможности мок интерфейсов и проверка вызовов конкретных методов; 86 | - тесты вспомогательных функций и пр. 87 | 88 | #### Интеграционные тесты 89 | - потестировать факт потока статистики, можно без конкретных цифр; 90 | - можно посоздавать файлы, пооткрывать сокеты и посмотреть на изменение снапшота. 91 | 92 | #### Клиент 93 | Необходимо реализовать простой клиент, который в реальном времени получает 94 | и выводит в STDOUT статистику по одному из пунктов (например, сетевую информацию) 95 | в читаемом формате (например, в виде таблицы). 96 | 97 | ## Разбалловка 98 | Максимум - **20 баллов** 99 | (при условии выполнения [обязательных требований](./README.md)): 100 | 101 | * Реализован сбор: 102 | - load average - 1 балл; 103 | - загрузка CPU - 1 балл; 104 | - загрузка дисков - 1 балл; 105 | - top talkers по сети - 1 балла; 106 | - статистика по сети - 1 балл. 107 | * Через конфигурацию можно отключать отдельную статистику - 2 балла. 108 | * Написаны юнит-тесты - 1 балл. 109 | * Написаны интеграционные тесты - 2 балла. 110 | * Реализован простой клиент к демону - 2 балла. 111 | * Сбор хотя бы одного типа статистики работает на разных ОС - 5 баллов. 112 | * Понятность и чистота кода - до 3 баллов. 113 | 114 | #### Зачёт от 10 баллов 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Проектная работа 2 | 3 | Необходимо выбрать и реализовать одну из предложенных тем: 4 | * [Анти-брутфорс](./01-anti-bruteforce.md) 5 | * [Ротация баннеров](./02-banners-rotation.md) 6 | * [Превьювер изображений](./03-image-previewer.md) 7 | * [SQL-мигратор](./04-sql-migrator.md) 8 | * [Системный мониторинг](./05-system-stats-daemon.md) 9 | 10 | ### Обязательные требования для каждого проекта 11 | * Наличие юнит-тестов на ключевые алгоритмы (core-логику) сервиса. 12 | * Наличие валидных Dockerfile и Makefile/Taskfile для сервиса. 13 | * Ветка master успешно проходит пайплайн в CI-CD системе 14 | (на ваш вкус, GitHub Actions, Circle CI, Travis CI, Jenkins, GitLab CI и пр.). 15 | **Пайплайн должен в себе содержать**: 16 | - запуск последней версии `golangci-lint` на весь проект с 17 | [конфигом, представленным в данном репозитории](./.golangci.yml); 18 | - запуск юнит тестов командой вида `go test -race -count 100`; 19 | - сборку бинаря сервиса для версии Go не ниже 1.22. 20 | 21 | При невыполнении хотя бы одного из требований выше - максимальная оценка за проект **4 балла** 22 | (незачёт), несмотря на, например, полностью написанный код сервиса. 23 | 24 | Более подробная разбалловка представлена в описании конкретной темы. 25 | 26 | ### Использование сторонних библиотек для core-логики 27 | Допускается только в следующих темах: 28 | - Анти-брутфорс 29 | - Превьювер изображений 30 | 31 | Но: 32 | - вы должны иметь представление о том, что происходит внутри. 33 | - точно ли подходит данная библиотека для решения вашей задачи? 34 | - не станет ли библиотека узким местом сервиса? 35 | - не полезнее ли написать функционал, которые вы хотите получить от библиотеки, самому? 36 | 37 | --- 38 | 39 | Для упрощения проверки вашего репозитория, рекомендуем использовать значки GitHub 40 | ([GitHub badges](https://github.com/dwyl/repo-badges)), а также 41 | [Go Report Card](https://goreportcard.com/). 42 | 43 | --- 44 | Авторы ТЗ: 45 | - [Дмитрий Смаль](https://github.com/mialinx) 46 | - [Антон Телышев](https://github.com/Antonboom) 47 | -------------------------------------------------------------------------------- /examples/banners-rotation/conceptual_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtusGolang/final_project/f4c84681c866770441fbe98d9d4964d6178134bc/examples/banners-rotation/conceptual_model.png -------------------------------------------------------------------------------- /examples/image-previewer/_gopher_original_1024x504.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtusGolang/final_project/f4c84681c866770441fbe98d9d4964d6178134bc/examples/image-previewer/_gopher_original_1024x504.jpg -------------------------------------------------------------------------------- /examples/image-previewer/gopher_1024x252.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtusGolang/final_project/f4c84681c866770441fbe98d9d4964d6178134bc/examples/image-previewer/gopher_1024x252.jpg -------------------------------------------------------------------------------- /examples/image-previewer/gopher_2000x1000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtusGolang/final_project/f4c84681c866770441fbe98d9d4964d6178134bc/examples/image-previewer/gopher_2000x1000.jpg -------------------------------------------------------------------------------- /examples/image-previewer/gopher_200x700.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtusGolang/final_project/f4c84681c866770441fbe98d9d4964d6178134bc/examples/image-previewer/gopher_200x700.jpg -------------------------------------------------------------------------------- /examples/image-previewer/gopher_256x126.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtusGolang/final_project/f4c84681c866770441fbe98d9d4964d6178134bc/examples/image-previewer/gopher_256x126.jpg -------------------------------------------------------------------------------- /examples/image-previewer/gopher_333x666.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtusGolang/final_project/f4c84681c866770441fbe98d9d4964d6178134bc/examples/image-previewer/gopher_333x666.jpg -------------------------------------------------------------------------------- /examples/image-previewer/gopher_500x500.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtusGolang/final_project/f4c84681c866770441fbe98d9d4964d6178134bc/examples/image-previewer/gopher_500x500.jpg -------------------------------------------------------------------------------- /examples/image-previewer/gopher_50x50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OtusGolang/final_project/f4c84681c866770441fbe98d9d4964d6178134bc/examples/image-previewer/gopher_50x50.jpg --------------------------------------------------------------------------------