Документація
Потоки й автоматизація
Потік — це креслення, яке виконується. Ви ставите вузли на полотні, тягнете дроти між ними, і платформа проходить це креслення щоразу, коли настає обраний вами момент. Ця сторінка каже, що вміє потік, що означає кожен вузол і де саме проходять його межі.
Що таке потік
Потік — це орієнтований граф: вузли, зʼєднані дротами, які проходять від однієї точки початку. Це навмисне не сценарій із циклом. Форму задають чотири правила, і редактор відмовляється публікувати креслення, яке порушує бодай одне з них, називаючи хибний вузол.
- Рівно один тригер. Вузол тригера — єдиний вхід, і саме він вирішує, які змінні існують у решті креслення.
- Жодних циклів. Дріт, який веде назад до вузла, звідки він вийшов, відхиляється, бо потік не вміє чекати: цикл просто ніколи б не завершився.
- Кожен вузол має бути досяжним від тригера. Вузол, що завис окремо, — це помилка, якої не видно на знімку екрана, тож це помилка під час публікації.
- Гілки проходять одна за одною, ніколи поруч. Дві гілки водночас писали б у state одночасно, і результат залежав би від випадковості годинника.
Полотно
Редактор — це полотно, і другого немає. Новий потік відкривається просто на ньому, а потік, який був прямим списком кроків, відкривається як прямий ланцюг вузлів.
- Палітра містить дванадцять видів вузлів. Клацніть на одному, щоб покласти його на полотно, або перетягніть у потрібне місце.
- Вузол пересувається перетягуванням за його заголовок. Усе інше на вузлі — це елемент керування, тож перетягування воно не починає.
- Дріт іде від точки виходу до точки входу. Перетягніть від однієї до іншої або клацніть спершу вихід, а потім вхід. Обидва способи роблять те саме, і другий — це шлях із клавіатури.
- Якщо відпустити дріт у порожнечі, нічого не станеться. Щоб прибрати дріт, виберіть його й натисніть Delete або скористайтеся хрестиком на ньому.
- Масштаб від 50 до 200 відсотків, Вмістити показує все креслення, а перетягування тла зміщує огляд. Мінікарти немає.
Вузли
Дванадцять видів, і цей перелік навмисне короткий. Кожен вид — це панель, девʼять перекладів, гілка у виконавці та рядок у таблиці істинності, тож вид, який виправдовує своє місце, вартий більше за той, що майже виправдовує.
| Вузол | Виходи | Що робить і де зупиняється |
|---|---|---|
trigger | out | Єдиний вхід. Його подія вирішує, які змінні існують. Ручний тригер несе ще й JSON, який ви вводите: щонайбільше 2048 символів, 40 ключів і 512 символів на значення. |
script | ok · error | Відтворює шаблон скрипта для цілі. Виходить через ok або через error, коли відтворення не вдається. Позначте продовження після помилки — і невдача піде далі попри все. |
switch | rule-0 … · otherwise | Дивиться на одне значення й бере перше правило, яке пасує; усе інше виходить через otherwise. Щонайбільше дванадцять правил і значення для порівняння завдовжки щонайбільше 512 символів. |
if | true · false | Одна умова, два виходи. Ті самі оператори й те саме обчислення, що й у правила switch, намальовані як вибір так або ні, яким вони насправді і є. |
set | out | Пише у state, звідки пізніший вузол або скрипт читає це назад. Щонайбільше дванадцять присвоєнь на вузол і 4096 символів на значення. Назви обирає той, хто малює; http зарезервовано. |
http | ok · error | Викликає URL і кладе відповідь у state.http. GET або POST, щонайбільше вісім заголовків, межа часу від 0,5 до 10 секунд і межа відповіді від 256 байтів до 256 КіБ, 64 КіБ типово. Щонайбільше три перенаправлення, кожне перевіряється наново. |
notify | out | Пише сповіщення в панелі цього облікового запису, на рівні відомості або застереження. Заголовок щонайбільше 120 символів, текст щонайбільше 1000. Позначте Також надсилати електронною поштою, і воно піде ще й поштою до всіх, хто має доступ до скриптів і не вимкнув Сповіщення потоків у розділі Сповіщення електронною поштою. Тестовий запуск пошти ніколи не надсилає. |
action | ok · error | Запускає, спиняє, вимикає, призупиняє або відновлює сервер цього виконання й чекає до 300 секунд на завершення команди. Нуль означає не чекати: прийнято — це не те саме, що працює. |
delay | out | Ставить запуск на паузу. До 30 секунд усередині запиту, який його розпочав; довше — і запуск відкладають та продовжують пізніше, щонайбільше 30 днів. |
approval | approved · rejected | Зупиняє запуск, доки людина не погодить або не відхилить, із терміном і обраним підсумком, якщо ніхто не відповість. |
foreach | loop · done | Проходить вихід циклу один раз на елемент списку, прочитаного як JSON, по одному в рядку або через коми. |
repeat | loop · done | Проходить вихід циклу, доки виконується умова, і перечитує цю умову перед кожним обертом. |
break | — | Виходить із циклу, у якому стоїть; запуск продовжується на виході Готово цього циклу. |
subflow | ok · error | Виконує інший потік цього облікового запису й чекає на його результат. Дочірній потік отримує свої вхідні дані як input.*. |
log | out | Пише один рядок у виконання, так само як вузол налагодження в Node-RED. Поле вміщує 1000 символів; у виконання потрапляють перші 200. |
note | — | Текст на полотні. Він не має портів і ніколи не проходиться, тож і у виконанні ніколи не зʼявляється. |
end | — | Завершує цю гілку й каже, чим скінчилося виконання: успіхом, невдачею або пропуском для сервера, до якого цей потік не звертався. Його супроводжує повідомлення щонайбільше на 280 символів. |
Тригери
Пʼять моментів, і обраний каже не лише, коли потік виконується. Він каже також, які змінні існують, які пропонує вибирач і які платформа відмовляється зберігати. Шлях, який у той момент існувати не може, — це помилка під час збереження, а не порожній рядок посеред виконання.
| Тригер | Коли виконується | Що є, а чого немає |
|---|---|---|
server.provisioned | Один раз, одразу після того, як замовлення дало машину. | Усе. Це єдиний момент, коли існує кожна група. |
server.reinstalled | Після того, як перевстановлення наявної машини вдалося. | Та сама машина, інший образ. Адреса не змінюється, а дата створення лишається початковою. Сьогодні спрацьовує лише для контейнерів; перевстановлення віртуальної машини завершує складова, яка не вміє відтворювати. |
server.deleted | Щойно вилучення прийнято, поки рядок ще можна прочитати. | Усе, крім образу. Не лишилося нічого, звідки прочитати образ, і платформа його не вигадує: os просто відсутній. |
manual | Ніколи сам собою. Ви запускаєте його з редактора через Inject. | Наявна машина, яку ви вказуєте, плюс власний JSON як input. Тут також немає образу: що саме встановлено на машині, платформа згодом дізнатися не може. |
webhook | Щойно хтось чужий надсилає запит на власну URL. | Жодної машини, тож ані тарифу, ані адреси, ані зʼєднання, ані агента. Лишаються обліковий запис, потік, надіслане тіло як input і сам запит як webhook. |
Змінні
Кожне значення, яке потік може прочитати, походить із однієї з цих груп. Вибирач у редакторі показує групи, що існують для обраного тригера, і більше нічого. Читати невідомий шлях — це помилка, а не порожнє значення: хибне припущення має бути гучним.
| Група | Існує з | Що містить |
|---|---|---|
org.* | Будь-яким тригером | Обліковий запис: id, назва й коротка назва. |
user.* | Чотирма серверними | Особа, за яку діє виконання: id, імʼя й поштова адреса. |
flow.* | Будь-яким тригером | Цей потік і це виконання: назва, id виконання, номер і кількість кроків, тригер і час початку. |
server.* | Чотирма серверними | Машина: назва, імʼя вузла мережі, вид, стан, зовнішній id, вузол, ядра, памʼять, диск і дата створення. |
server.compute.* | Чотирма серверними | Якого роду це гість і що той рід справді вміє: рід, шаблон, unprivileged, сховище, точки монтування, capabilities та unsupported. Усі сім необовʼязкові, а відсутність означає невстановлено, а не ні. |
plan.* | Чотирма серверними | Тариф за замовленням: назва, ядра, памʼять, диск і міст. |
os.* | Створення й перевстановлення | Образ: назва, коротка назва й категорія. Родини й версії немає, бо в каталозі таких стовпців нема, а вгадувати їх означає обрати не той менеджер пакунків. |
ip.* | Чотирма серверними | Видана адреса й те, чи вона версії 4 чи 6. |
network.* | Чотирма серверними | Усе довкола тієї адреси: cidr, шлюз, маска, мережа, широкомовна адреса й розвʼязувачі. |
prefix.* | Чотирма серверними | Набір адрес, звідки вона походить, з його діапазоном і батьківським набором. |
integration.* | Чотирма серверними | Зʼєднання, що несе машину: назва, вид, вузол, сховище, міст і діапазон vmid. |
agent.* | Чотирма серверними | Агент, який виконав роботу: назва, стан, версія, імʼя вузла мережі, операційна система, ядро й ядра процесора. |
input.* | Ручний і вебхук | Те, що ви ввели, або те, що надіслав вебхук. Ключі ваші, і вибирач іде за ними. |
webhook.* | Лише вебхук | Сам запит: яка точка входу, коли він надійшов і з якої адреси. |
state.* | Після вузла set | Те, що записав вузол set цього потоку. Назви ваші, і вони існують лише нижче від вузла, який їх пише. |
state.http.<node>.* | Після вузла http | Для кожного вузла http: status, ok, body, json, error і url. Усі шість існують завжди, і на доброму шляху, і на поганому. |
device.* | Поки що ніде | Задумано для мережевого обладнання. Немає постачальника, який міг би її наповнити, тож сьогодні жоден потік нею скористатися не може. |
Вирази
Вузол set пише у state. Його значення — дослівний текст, якщо тільки ви не позначите поле виразу; тоді воно читається як шаблон, зі вже підставленими змінними цього виконання.
- Ця позначка — свідомий вибір. Значення, у якому випадково стоять дві фігурні дужки, шматок Ansible або уривок Helm, і далі означає те, що там написано. Ніщо не змінює сенсу через зміну, якої ніхто не просив.
- Мова — це лише вивід. Дві дужки й шлях, і більше нічого: жодного assign, жодного capture, жодного циклу, жодного include. Що стоїть на полотні, те й виходить, із підставленими значеннями.
- Є 46 фільтрів: текст, числа, дати, ті кілька спискових фільтрів, що дають текст, і власні quote, ini та ipoctet. Вибирач у редакторі їх перелічує. Двох родин навмисне немає — тих, що кидають жереб, і тих, що повертають обʼєкт там, де ви хотіли слово.
- Таємниці тут недоступні, як і повторно вживані уривки. Те, що пише вузол set, потрапляє до запису виконання, а таємниці там робити нічого.
Погодження та цикли
Потік може зупинитися й чекати на людину, а також може проходити ті самі вузли не один раз. Ані те, ані інше не було можливе, доки запуск не можна було відкласти й пізніше розбудити; ця черга тепер є.
- Вузол погодження зупиняє запуск, створює запит і сповіщає обліковий запис. Відповідь потребує окремого права, тож той, хто написав потік, не є автоматично тим, хто його затверджує.
- Кожен запит несе термін і те, що станеться без відповіді: продовжити як погоджено, продовжити як відхилено або завершити запуск як такий, що не стосується. Четвертого варіанта немає, бо запуск, який чекає вічно, це запуск, про який більше ніхто не почує.
- Для кожного проходить свій вихід циклу один раз на елемент списку. У циклі state.loop містить поточний елемент, його позицію та загальну кількість.
- Ніщо ззовні циклу не може приєднуватися до вузлів усередині нього. Ці вузли виконуються щообертом, і сповіщення, приєднане до обох, писало б по одному повідомленню на оберт.
- Крок погодження може також надсилати пошту. Вона надходить лише учасникам, які можуть вирішувати щодо погоджень, а не всім, хто бачить потоки; сповіщення в панелі записується в будь-якому разі.
Очікування та потоки, що викликають потоки
Запуск, що стоїть, — це не запуск, який зазнав невдачі. Відкласти його можуть три речі, і всі три користуються однією чергою: погодження, довга пауза та підпотік, дочірній запуск якого сам чекає.
- Пауза до півхвилини просто чекає всередині запиту, який її розпочав, і саме цього ви хочете, коли даєте агентові трохи часу. Усе довше відкладає запуск, тож замовлення, яке його розпочало, завершується одразу, а решта потоку йде пізніше.
- Підпотік виконує інший потік цього облікового запису як один крок. Його результат визначає вихід: дочірній запуск, який удався або не знайшов роботи, продовжує через OK, а невдалий — через «Помилка». Стан, запуск і назва потоку є в state.subflow.
- Потік ніколи не має досягати сам себе — ні напряму, ні через інший потік. Це перевіряють під час розгортання, і повідомлення називає знайдений ланцюг.
- Потоки можуть викликати один одного щонайбільше на три рівні. Оскільки потоки редагують окремо, цю межу перевіряють двічі: під час розгортання і поки запуск справді триває.
Вебхуки
Точка входу вебхука дає зовнішній системі власну URL. Та система надсилає JSON, потік за URL виконується, а відповідь — голий код стану. Точки входу живуть у розділі Скрипти, на вкладці вебхуків, і є окремими обʼєктами: та сама точка входу може вказувати на інший потік, а відправник цього й не помітить.
- Створіть точку входу й дайте їй назву, яку впізнаєте згодом. URL створюється сама й вибору не підлягає: 32 випадкові символи, тобто 160 бітів, тож вгадування — не стратегія.
- Оберіть, як відправник підтверджує себе, і скопіюйте таємницю. Її показують один раз і більше ніколи; якщо вона загубилася, ви створюєте нову, а разом із нею отримуєте й нову URL.
- Спрямуйте точку входу на потік, тригером якого є вебхук. Точка входу може існувати раніше за потік, і доти запит приймається й отримує 202, який нічого не запускає. Саме в такому порядку люди це й будують насправді, тож помилкою це не вважають.
| Схема | Що вона робить |
|---|---|
none | Жодного доказу: хто знає URL, той може запустити потік. Захисне рішення поруч зі списком адрес і важко захисне без нього. |
hmac_sha256 | Відправник підписує неопрацьоване тіло разом із позначкою часу. Саме це варто обрати: воно привʼязує запит до власного тіла, тож перехоплений запит не вийде змінити й надіслати далі. |
bearer | Відправник кладе спільний ключ у заголовок Authorization. Просто, і про тіло, з яким він прийшов, це нічого не каже. |
Підпис — це слово sha256, знак рівності й HMAC-SHA256 саме над байтами позначки часу, крапки й тіла, малими шістнадцятковими цифрами. Він іде в X-Provibr-Signature, а сама позначка часу йде в X-Provibr-Timestamp, цілими секундами від епохи.
Запит, чия позначка часу старша за 300 секунд або лежить у майбутньому, відхиляється з 401. Це вікно — справжнє правило, а не оздоба, бо позначка часу міститься всередині підписаного матеріалу: перехоплений запит не вийде надіслати завтра, наліпивши поверх свіжу позначку.
Підписати запит — це один рядок openssl. Цей приклад надсилає невеликий обʼєкт; текст для термінала навмисне лишається англійським, щоб збігатися з тим, що показує ваш термінал.
# Sign the raw body together with the timestamp, then post it.
SECRET="$PROVIBR_WEBHOOK_SECRET"
BODY='{"reason":"maintenance","attempt":1}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d' ' -f1)
curl -sS -X POST 'https://app.provibr.com/api/hooks/flows/<your-slug>' \
-H 'Content-Type: application/json' \
-H "X-Provibr-Timestamp: $TS" \
-H "X-Provibr-Signature: sha256=$SIG" \
--data "$BODY"| Межа | Подробиці |
|---|---|
body | 64 КіБ типово, налаштовується від 1 КіБ до 256 КіБ. Більший запит обрізається, поки ще надходить, а не читається повністю й лише потім відхиляється. |
rate | 60 запитів на хвилину типово, налаштовується від 1 до 600. Лік ведеться на точку входу, а не на відправника, бо справжнє джерело має одну адресу, а нападник — тисячу. |
payload | Обʼєкт JSON одного рівня. Кожен ключ стає input із тим ключем; вкладений обʼєкт відхиляється, а не сплощується. |
allowlist | Щонайбільше 20 адрес або діапазонів, у v4 чи v6. Порожньо означає жодного обмеження. |
endpoints | Щонайбільше 50 точок входу на обліковий запис. |
| Код | Значення |
|---|---|
202 | Прийнято. Або виконання почалося, або запускати не було чого: потік ще не привʼязаний, потік вимкнений чи саме виконання впало. У всіх чотирьох випадках відправник нічого поганого не зробив, а квитанція каже, який саме з чотирьох це був. |
401 | Підпису чи ключа немає або він не збігається, чи підпис збігається, а його позначка часу випадає з вікна. |
403 | Точка входу вимкнена, або адреса джерела не значиться у списку. |
404 | Точки входу з цим позначенням немає. |
410 | Точку входу відкликано. Позначення лишається зайнятим назавжди, і ця відповідь каже чесному джерелу, що йому потрібна нова URL, чого 404 не зробив би. |
413 | Тіло більше, ніж приймає ця точка входу. |
422 | Тіло не є обʼєктом JSON одного рівня. |
429 | Понад дозволений потік запитів для цієї точки входу. |
Кожен запит лишає квитанцію, прийнятий він чи ні: наслідок, повернутий стан, адресу джерела повністю й скільки байтів справді прочитано. Тіло не зберігається ніколи. Квитанції зникають за 90 днів, раніше за самі виконання, бо адреса джерела — це персональні дані того, хто нашим клієнтом не є.
Редакції та виконання
Два схожі питання мають тут дві різні відповіді. Хто що і коли змінив — це редакція. Що саме пройшло це конкретне виконання — це копія, збережена на самому виконанні. Знімок не може відповісти на перше питання, а редакція — на друге, тож існують обидва.
- Кожна публікація пише редакцію, зокрема й публікація, яка нічого не змінила. Номер зростає для кожного потоку й ніколи не використовується вдруге.
- Різниця між двома редакціями — це читабельний список, а не сирий JSON: доданий, прибраний або змінений вузол із названими полями, доданий чи прибраний дріт. Те, де вузол стоїть на полотні, зміною не є.
- Відновлення нічого не відмотує. Воно записує старе креслення як нову редакцію поверх історії, з приміткою, звідки воно взялося.
- Кожне виконання зберігає креслення, яке воно пройшло. Зміна потоку згодом ніколи не переписує того, що зробило давніше виконання.
- Виконання містить рядок на кожен відвіданий вузол, із наслідком і виходом, через який воно пішло, і рядок на кожен невідвіданий вузол із причиною. Невідвіданий — це факт, який варто записати, а не порожнє місце.
- Список виконань фільтрується за тригером, станом і редакцією та вивантажується у CSV. Вивантаження спиняється на 5000 рядках і каже про це всередині файлу, а не обривається мовчки.
Шаблони скриптів тримають поряд власну історію: кожну збережену версію вмісту й порядкову різницю між будь-якими двома з них.