generated from yandex-praktikum/go-musthave-devops-tpl
-
Notifications
You must be signed in to change notification settings - Fork 0
411 lines (370 loc) · 25.7 KB
/
devopstest.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
name: autotests
on:
pull_request:
push:
branches:
- main
jobs:
devopstest:
runs-on: ubuntu-latest
container: golang:1.18
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: praktikum
options: >-
--health-cmd pg_isready
--health-interval 5s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Download autotests binaries
uses: robinraju/release-downloader@v1.2
with:
repository: Yandex-Practicum/go-autotests-bin
latest: true
fileName: "*"
out-file-path: .tools
- name: Setup autotest binary
run: |
chmod -R +x $GITHUB_WORKSPACE/.tools
mv $GITHUB_WORKSPACE/.tools/devopstest /usr/local/bin/devopstest
mv $GITHUB_WORKSPACE/.tools/random /usr/local/bin/random
- name: Build agent binary
run: |
cd cmd/agent
go build -o agent
# Соглашение:
# Во всех заданиях, нужно обрабатывать все пограничные случаи и негатив-кейсы.
# По ходу продвижения по инкрементам, тесты становятся строже.
# Темплейты могут обновляться, добавляя все более строгие проверки.
# I. Задание к первому инкременту.
# Разработать агент по сбору рантайм метрик и их последующей отправке на сервер по протоколу http.
# Разработку необходимо вести с использованием шаблона https://github.com/yandex-praktikum/go-musthave-devops-tpl.git
# Агент должен собирать метрики двух типов:
# * gauge, тип float64
# * counter, тип int64
# В качестве источника метрик использовать пакет runtime. Собирать следующие метрики:
# * Имя метрики: "Alloc", тип: gauge
# * Имя метрики: "BuckHashSys", тип: gauge
# * Имя метрики: "Frees", тип: gauge
# * Имя метрики: "GCCPUFraction", тип: gauge
# * Имя метрики: "GCSys", тип: gauge
# * Имя метрики: "HeapAlloc", тип: gauge
# * Имя метрики: "HeapIdle", тип: gauge
# * Имя метрики: "HeapInuse", тип: gauge
# * Имя метрики: "HeapObjects", тип: gauge
# * Имя метрики: "HeapReleased", тип: gauge
# * Имя метрики: "HeapSys", тип: gauge
# * Имя метрики: "LastGC", тип: gauge
# * Имя метрики: "Lookups", тип: gauge
# * Имя метрики: "MCacheInuse", тип: gauge
# * Имя метрики: "MCacheSys", тип: gauge
# * Имя метрики: "MSpanInuse", тип: gauge
# * Имя метрики: "MSpanSys", тип: gauge
# * Имя метрики: "Mallocs", тип: gauge
# * Имя метрики: "NextGC", тип: gauge
# * Имя метрики: "NumForcedGC", тип: gauge
# * Имя метрики: "NumGC", тип: gauge
# * Имя метрики: "OtherSys", тип: gauge
# * Имя метрики: "PauseTotalNs", тип: gauge
# * Имя метрики: "StackInuse", тип: gauge
# * Имя метрики: "StackSys", тип: gauge
# * Имя метрики: "Sys", тип: gauge
# * Имя метрики: "TotalAlloc", тип: gauge
# К метрикам пакета runtime, добавить метрики:
# * Имя метрики: "PollCount", тип: counter - счетчик, увеличивающийся на 1, при каждом обновлении метрики из пакета runtime (на каждый pollInterval - см. ниже)
# * Имя метрики: "RandomValue", тип: gauge - обновляемое рандомное значение
# По умолчанию, приложение должно обновлять метрики из пакета runtime с заданной частотой:
# pollInterval - 2 секунды
# По умолчанию, приложение должно отправлять метрики на сервер с заданной частотой:
# reportInterval - 10 секунд
# Метрики отправлять по протоколу http, методом POST:
# * по умолчанию на адрес: 127.0.0.1, порт: 8080
# * в формате: "http://<АДРЕС_СЕРВЕРА>/update/<ТИП_МЕТРИКИ>/<ИМЯ_МЕТРИКИ>/<ЗНАЧЕНИЕ_МЕТРИКИ>"
# * application-type: "text/plain"
# Агент должен штатно завершаться по сигналам: syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT
- name: "Code increment #1"
if: always()
run: |
devopstest -test.v -test.run=^TestIteration1$ \
-agent-binary-path=cmd/agent/agent
- name: Build server binary
run: |
cd cmd/server
go build -o server
# II. Задание ко второму инкременту.
# Разработать сервер по сбору рантайм метрик, который собирает репорты от агентов по протоколу http.
# Разработку следует продолжать в ранее используемом репозитории (с предыдущими инкрементами), однако сервер стоит размещать по своему пути: cmd/server/
# Сервер должен собирать и хранить произвольные метрики двух типов:
# * gauge, тип float64, новое значение должно замещать предыдущее.
# * counter, тип int64, новое значение должно добавляться к предыдущему (если оно ранее уже было известно серверу).
# Метрики принимаются сервером по протоколу http, методом POST:
# * по умолчанию открывать порт: 8080, на адресе: 127.0.0.1
# * в формате: "http://<АДРЕС_СЕРВЕРА>/update/<ТИП_МЕТРИКИ>/<ИМЯ_МЕТРИКИ>/<ЗНАЧЕНИЕ_МЕТРИКИ>"
# * application-type: "text/plain"
# * при успешном приеме, возвращать статус: http.StatusOK
# Сервер должен штатно завершаться по сигналам: syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT
# Покройте код агента и сервера юнит тестами
- name: "Code increment #2"
if: always()
run: |
devopstest -test.v -test.run=^TestIteration2[b]*$ \
-source-path=. \
-binary-path=cmd/server/server
# III. Задание к третьему инкременту.
# Переписать код с использованием одного из распространенных web-фреймворков. Например: github.com/go-chi/chi
# Сервер должен возвращать текущее значение запрашиваемой метрики в текстовом виде по запросу GET http://<АДРЕС_СЕРВЕРА>/value/<ТИП_МЕТРИКИ>/<ИМЯ_МЕТРИКИ> со статусом http.StatusOK
# При попытке запроса неизвестной серверу метрики, сервер должен возвращать http.StatusNotFound
# По запросу GET http://<АДРЕС_СЕРВЕРА>/ сервер должен отдавать html-страничку, со списком имен и значений всех известных ему на текущий момент метрик.
- name: "Code increment #3"
if: always()
run: |
devopstest -test.v -test.run=^TestIteration3[b]*$ \
-source-path=. \
-binary-path=cmd/server/server
# IV. Задание к четвертому инкременту.
# Дополнить(!) API сервера, которое позволяет принимать метрики в формате JSON.
# При реализации задействовать одну из распространенных библиотек. Например: encoding/json
# * Обмен с сервером организовать с использованием следующей структуры:
# type Metrics struct {
# ID string `json:"id"` // Имя метрики
# MType string `json:"type"` // Параметр принимающий значение gauge или counter
# Delta *int64 `json:"delta,omitempty"` // Значение метрики в случае передачи counter
# Value *float64 `json:"value,omitempty"` // Значение метрики в случае передачи gauge
# }
# * Для передачи метрик на сервер использовать Content-Type: "application/json",
# в теле запроса описанный выше JSON, передача через: POST update/
# * Для получения метрик с сервера использовать Content-Type: "application/json",
# в теле запроса описанный выше JSON (заполняем только ID и MType),
# в ответ получаем такой же JSON, но уже с заполненными значениями метрик. Запрос через: POST value/
# Перевести Агента на новое API
# Тесты проверяют, что агент экспортирует и обновляет метрики на сервере, описанные в первом инкременте.
- name: "Code increment #4"
if: always()
run: |
devopstest -test.v -test.run=^TestIteration4$ \
-source-path=. \
-binary-path=cmd/server/server \
-agent-binary-path=cmd/agent/agent
# V. Задание к пятому инкременту.
# Доработать агента, что бы он мог изменять свои параметры запуска по умолчанию, через переменные окружения:
# ADDRESS (по умолчанию: "127.0.0.1:8080" или "localhost:8080")
# REPORT_INTERVAL (по умолчанию: 10 секунд)
# POLL_INTERVAL (по умолчанию: 2 секунды)
# Значения интервалов времени должно задаваться в секундах.
# Доработать сервер, что бы он мог изменять свои параметры запуска по умолчанию, через переменные окружения:
# ADDRESS (по умолчанию: "127.0.0.1:8080" или "localhost:8080")
- name: "Code increment #5"
if: always()
run: |
SERVER_PORT=$(random unused-port)
ADDRESS="localhost:${SERVER_PORT}"
devopstest -test.v -test.run=^TestIteration5$ \
-source-path=. \
-agent-binary-path=cmd/agent/agent \
-binary-path=cmd/server/server \
-server-port=$SERVER_PORT
# VI. Задание к шестому инкременту.
# Доработать сервер, что бы он с заданной периодичностью сохранял текущие значения метрик на диск в указанный файл.
# На старте опционально мог загружать сохраненные ранее значения.
# При штатном завершении сервера, все накопленные данные должны сохраняться.
# Сервер должен принимать конфигурацию, через переменные окружения:
# STORE_INTERVAL (по умолчанию 300) - интервал времени в секундах, по истечении которого текущие показания сервера сбрасываются на диск. (значение 0 - делает запись синхронной)
# STORE_FILE по умолчанию ("/tmp/devops-metrics-db.json") - строка - имя файла, где хранятся значения (пустое значение - отключает функцию записи на диск)
# RESTORE по умолчанию (true) - булево значение (true|false), определяющее загружать или нет начальные значения из указанного файла при старте сервера.
- name: "Code increment #6"
if: always()
run: |
SERVER_PORT=$(random unused-port)
ADDRESS="localhost:${SERVER_PORT}"
TEMP_FILE=$(random tempfile)
devopstest -test.v -test.run=^TestIteration6$ \
-source-path=. \
-agent-binary-path=cmd/agent/agent \
-binary-path=cmd/server/server \
-server-port=$SERVER_PORT \
-database-dsn='postgres://postgres:postgres@postgres:5432/praktikum?sslmode=disable' \
-file-storage-path=$TEMP_FILE
# VII. Задание к седьмому инкременту.
# Доработать код, что бы он умел принимать аргументы с использованием флагов.
# * Аргументы Сервера
# ADDRESS, через флаг "-a=<ЗНАЧЕНИЕ>"
# RESTORE, через флаг "-r=<ЗНАЧЕНИЕ>"
# STORE_INTERVAL, через флаг "-i=<ЗНАЧЕНИЕ>"
# STORE_FILE, через флаг "-f=<ЗНАЧЕНИЕ>"
# * Аргументы Агента
# ADDRESS, через флаг: "-a=<ЗНАЧЕНИЕ>"
# REPORT_INTERVAL, через флаг: "-r=<ЗНАЧЕНИЕ>"
# POLL_INTERVAL, через флаг: "-p=<ЗНАЧЕНИЕ>"
# Во всех случаях иметь значения по умолчанию и реализовать приоритет значений полученных через ENV, перед значениями задаваемые посредством флагов.
- name: "Code increment #7"
if: always()
run: |
SERVER_PORT=$(random unused-port)
ADDRESS="localhost:${SERVER_PORT}"
TEMP_FILE=$(random tempfile)
devopstest -test.v -test.run=^TestIteration7$ \
-source-path=. \
-agent-binary-path=cmd/agent/agent \
-binary-path=cmd/server/server \
-server-port=$SERVER_PORT \
-database-dsn='postgres://postgres:postgres@postgres:5432/praktikum?sslmode=disable' \
-file-storage-path=$TEMP_FILE
# VIII. Задание к восьмому инкременту.
# Доработать код сервера, для реализации механизма cжатия данных сервером в формате gzip
# для контента с типом: application/json и text/html
- name: "Code increment #8"
if: always()
run: |
SERVER_PORT=$(random unused-port)
ADDRESS="localhost:${SERVER_PORT}"
TEMP_FILE=$(random tempfile)
devopstest -test.v -test.run=^TestIteration8 \
-source-path=. \
-agent-binary-path=cmd/agent/agent \
-binary-path=cmd/server/server \
-server-port=$SERVER_PORT \
-database-dsn='postgres://postgres:postgres@postgres:5432/praktikum?sslmode=disable' \
-file-storage-path=$TEMP_FILE
# IX. Задание к девятому инкременту.
# Внимание: это учебный пример, в котором сделан акцент на закреплении пройденной темы,
# а не на безопасности. В реальной жизни использовать подпись таким образом не следует.
# Например остается возможность передать серверу перехваченные ранее данные с корректным хешом.
# (старое значение счетчика)
# Реализовать механизм подписывания передаваемых данных по алгоритму sha256
# Для этого расширим структуру
# type Metrics struct {
# ID string `json:"id"` // Имя метрики
# MType string `json:"type"` // Параметр принимающий значение gauge или counter
# Delta *int64 `json:"delta,omitempty"` // Значение метрики в случае передачи counter
# Value *float64 `json:"value,omitempty"` // Значение метрики в случае передачи gauge
# Hash string `json:"hash,omitempty"` // Значение hash-функции
# }
# Хеш необходимо считать от строки, с учетом ключа, который предан агенту/серверу на старте.
# ** для counter - hash(fmt.Sprintf("%s:counter:%d", id, delta), key)
# ** для gauge - hash(fmt.Sprintf("%s:gauge:%f", id, value), key)
# Агент:
# * добавить поддержку аргумента через флаг "-k=<КЛЮЧ>"
# * добавить поддержку аргумента через переменную окружения "KEY=<КЛЮЧ>"
# * при наличии ключа, агент должен вычислять хеш и передавать в поле hash запроса.
# Сервер:
# * добавить поддержку аргумента через флаг "-k=<КЛЮЧ>"
# * добавить поддержку аргумента через переменную окружения "KEY=<КЛЮЧ>"
# * при наличии ключа, во время обработки запроса, сервер должен проверять соответствие полученного и вычисленного хеша.
# при не совпадении отбрасывать полученные данные и возвращать http.StatusBadRequest
# * при наличии ключа, на этапе формирования ответа, сервер должен
# вычислять хеш и передавать его в соответствующем поле hash ответа.
- name: "Code increment #9"
if: always()
run: |
SERVER_PORT=$(random unused-port)
ADDRESS="localhost:${SERVER_PORT}"
TEMP_FILE=$(random tempfile)
devopstest -test.v -test.run=^TestIteration9$ \
-source-path=. \
-agent-binary-path=cmd/agent/agent \
-binary-path=cmd/server/server \
-server-port=$SERVER_PORT \
-file-storage-path=$TEMP_FILE \
-database-dsn='postgres://postgres:postgres@postgres:5432/praktikum?sslmode=disable' \
-key="${TEMP_FILE}"
# X. Задание к десятому инкременту.
# Сервер:
# * Добавьте функциональность подключения к базе данных. В качестве СУБД используйте PostgreSQL версии не ниже 10.
# * Добавьте хендлер GET /ping, который при запросе проверяет соединение с базой данных.
# При успешной проверке хендлер должен вернуть HTTP-статус 200 OK, при неуспешной — 500 Internal Server Error.
# * Строка с адресом подключения к БД должна получаться из переменной окружения DATABASE_DSN или флага командной строки -d.
# Использование этого параметра имеет приоритет над параметром -file-storage-path и автоматически задействует функциональность сервера БД
# NOTE: Для хранения значений gauge рекомендуется использовать тип: double precision
- name: "Code increment #10"
if: always()
run: |
SERVER_PORT=$(random unused-port)
ADDRESS="localhost:${SERVER_PORT}"
TEMP_FILE=$(random tempfile)
devopstest -test.v -test.run=^TestIteration10[b]*$ \
-source-path=. \
-agent-binary-path=cmd/agent/agent \
-binary-path=cmd/server/server \
-server-port=$SERVER_PORT \
-database-dsn='postgres://postgres:postgres@postgres:5432/praktikum?sslmode=disable' \
-key="${TEMP_FILE}"
# XI. Задание к одиннадцатому инкременту.
# Сервер:
# * Перепишите сервер так, чтобы СУБД PostgresSQL стала хранилищем метрик вместо текущей реализации.
# Сервису необходимо самостоятельно создать все необходимые таблицы в базе данных,
# схема и формат хранения остаются на ваше усмотрение.
- name: "Code increment #11"
if: always()
run: |
SERVER_PORT=$(random unused-port)
ADDRESS="localhost:${SERVER_PORT}"
TEMP_FILE=$(random tempfile)
devopstest -test.v -test.run=^TestIteration11$ \
-source-path=. \
-agent-binary-path=cmd/agent/agent \
-binary-path=cmd/server/server \
-server-port=$SERVER_PORT \
-database-dsn='postgres://postgres:postgres@postgres:5432/praktikum?sslmode=disable' \
-key="${TEMP_FILE}"
# XII. Задание к двенадцатому инкременту.
# Сервер:
# * Добавьте новый хендлер POST /updates/ принимающий в теле запроса множество метрик в формате: []Metrics (списка метрик)
# Агент:
# * Научите агента работать с использованием нового API (отправлять метрики батчами)
# Стоит помнить:
# * Необходимо соблюдать обратную совместимость
# * Отправлять пустые батчи не нужно
# * Мы умеем сжимать контент по алгоритму gzip
# * Изменение в базе можно выполнять в рамках одной транзакции/одного запроса
- name: "Code increment #12"
if: always()
run: |
SERVER_PORT=$(random unused-port)
ADDRESS="localhost:${SERVER_PORT}"
TEMP_FILE=$(random tempfile)
devopstest -test.v -test.run=^TestIteration12$ \
-source-path=. \
-agent-binary-path=cmd/agent/agent \
-binary-path=cmd/server/server \
-server-port=$SERVER_PORT \
-database-dsn='postgres://postgres:postgres@postgres:5432/praktikum?sslmode=disable' \
-key="${TEMP_FILE}"
# XIII. Задание к тринадцатому инкременту.
# Измените весь свой код в соответствии со знаниями, полученными в данной главе.
# * Добавьте механизмы обработки ошибок (там где это уместно)
# * Для формирования отладочных сообщений, используйте стандартный логгер или одну из популярных библиотек логгирования.
# * Не используйте функции fmt.Print* для вывода отладочной информации в коде сервера и агента
- name: "Code increment #13"
if: always()
run: |
devopstest -test.v -test.run=^TestIteration13$ \
-source-path=.
# XIV. Задание к четыринадцатому инкременту.
# Агент:
# Перепланируйте архитектуру агента таким образом,
# что бы сбор метрик (опрос runtime) и их отправка осуществлялись в разных горутинах.
# Добавьте еще одну горутину которая бы собирала дополнительные метрики
# (с использованием пакета https://github.com/shirou/gopsutil)
# * Имя метрики: "TotalMemory", тип: gauge - общее количество памяти
# * Имя метрики: "FreeMemory", тип: gauge - общее количество свободной памяти
# * Имя метрики: "CPUutilization1", тип: gauge - загрузка ядра в процентах за 10 секунд (точное количество - по числу CPU определяемое во время исполнения)
- name: "Code increment #14"
if: always()
run: |
SERVER_PORT=$(random unused-port)
ADDRESS="localhost:${SERVER_PORT}"
TEMP_FILE=$(random tempfile)
devopstest -test.v -test.run=^TestIteration14$ \
-source-path=. \
-agent-binary-path=cmd/agent/agent \
-binary-path=cmd/server/server \
-server-port=$SERVER_PORT \
-file-storage-path=$TEMP_FILE \
-database-dsn='postgres://postgres:postgres@postgres:5432/praktikum?sslmode=disable' \
-key="${TEMP_FILE}"