Перейти до вмісту

Документація

Потоки й автоматизація

Потік — це креслення, яке виконується. Ви ставите вузли на полотні, тягнете дроти між ними, і платформа проходить це креслення щоразу, коли настає обраний вами момент. Ця сторінка каже, що вміє потік, що означає кожен вузол і де саме проходять його межі.

Що таке потік

Потік — це орієнтований граф: вузли, зʼєднані дротами, які проходять від однієї точки початку. Це навмисне не сценарій із циклом. Форму задають чотири правила, і редактор відмовляється публікувати креслення, яке порушує бодай одне з них, називаючи хибний вузол.

  • Рівно один тригер. Вузол тригера — єдиний вхід, і саме він вирішує, які змінні існують у решті креслення.
  • Жодних циклів. Дріт, який веде назад до вузла, звідки він вийшов, відхиляється, бо потік не вміє чекати: цикл просто ніколи б не завершився.
  • Кожен вузол має бути досяжним від тригера. Вузол, що завис окремо, — це помилка, якої не видно на знімку екрана, тож це помилка під час публікації.
  • Гілки проходять одна за одною, ніколи поруч. Дві гілки водночас писали б у state одночасно, і результат залежав би від випадковості годинника.
Креслення вміщує щонайбільше 80 вузлів і 160 дротів, з яких щонайбільше 25 справді щось роблять. Це останнє число те саме, що мали давні списки кроків; малювати замість перелічувати його не підвищує.

Полотно

Редактор — це полотно, і другого немає. Новий потік відкривається просто на ньому, а потік, який був прямим списком кроків, відкривається як прямий ланцюг вузлів.

  • Палітра містить дванадцять видів вузлів. Клацніть на одному, щоб покласти його на полотно, або перетягніть у потрібне місце.
  • Вузол пересувається перетягуванням за його заголовок. Усе інше на вузлі — це елемент керування, тож перетягування воно не починає.
  • Дріт іде від точки виходу до точки входу. Перетягніть від однієї до іншої або клацніть спершу вихід, а потім вхід. Обидва способи роблять те саме, і другий — це шлях із клавіатури.
  • Якщо відпустити дріт у порожнечі, нічого не станеться. Щоб прибрати дріт, виберіть його й натисніть Delete або скористайтеся хрестиком на ньому.
  • Масштаб від 50 до 200 відсотків, Вмістити показує все креслення, а перетягування тла зміщує огляд. Мінікарти немає.
Вигляд списком — це той самий граф у вигляді тексту, з тією ж панеллю властивостей поруч. Це повноцінна заміна, а не стислий виклад: кожен вузол, кожен дріт і кожне налаштування доступні там без миші.

Вузли

Дванадцять видів, і цей перелік навмисне короткий. Кожен вид — це панель, девʼять перекладів, гілка у виконавці та рядок у таблиці істинності, тож вид, який виправдовує своє місце, вартий більше за той, що майже виправдовує.

Види вузлів, їхні виходи та їхні межі
ВузолВиходиЩо робить і де зупиняється
triggeroutЄдиний вхід. Його подія вирішує, які змінні існують. Ручний тригер несе ще й JSON, який ви вводите: щонайбільше 2048 символів, 40 ключів і 512 символів на значення.
scriptok · errorВідтворює шаблон скрипта для цілі. Виходить через ok або через error, коли відтворення не вдається. Позначте продовження після помилки — і невдача піде далі попри все.
switchrule-0 … · otherwiseДивиться на одне значення й бере перше правило, яке пасує; усе інше виходить через otherwise. Щонайбільше дванадцять правил і значення для порівняння завдовжки щонайбільше 512 символів.
iftrue · falseОдна умова, два виходи. Ті самі оператори й те саме обчислення, що й у правила switch, намальовані як вибір так або ні, яким вони насправді і є.
setoutПише у state, звідки пізніший вузол або скрипт читає це назад. Щонайбільше дванадцять присвоєнь на вузол і 4096 символів на значення. Назви обирає той, хто малює; http зарезервовано.
httpok · errorВикликає URL і кладе відповідь у state.http. GET або POST, щонайбільше вісім заголовків, межа часу від 0,5 до 10 секунд і межа відповіді від 256 байтів до 256 КіБ, 64 КіБ типово. Щонайбільше три перенаправлення, кожне перевіряється наново.
notifyoutПише сповіщення в панелі цього облікового запису, на рівні відомості або застереження. Заголовок щонайбільше 120 символів, текст щонайбільше 1000. Позначте Також надсилати електронною поштою, і воно піде ще й поштою до всіх, хто має доступ до скриптів і не вимкнув Сповіщення потоків у розділі Сповіщення електронною поштою. Тестовий запуск пошти ніколи не надсилає.
actionok · errorЗапускає, спиняє, вимикає, призупиняє або відновлює сервер цього виконання й чекає до 300 секунд на завершення команди. Нуль означає не чекати: прийнято — це не те саме, що працює.
delayoutСтавить запуск на паузу. До 30 секунд усередині запиту, який його розпочав; довше — і запуск відкладають та продовжують пізніше, щонайбільше 30 днів.
approvalapproved · rejectedЗупиняє запуск, доки людина не погодить або не відхилить, із терміном і обраним підсумком, якщо ніхто не відповість.
foreachloop · doneПроходить вихід циклу один раз на елемент списку, прочитаного як JSON, по одному в рядку або через коми.
repeatloop · doneПроходить вихід циклу, доки виконується умова, і перечитує цю умову перед кожним обертом.
break—Виходить із циклу, у якому стоїть; запуск продовжується на виході Готово цього циклу.
subflowok · errorВиконує інший потік цього облікового запису й чекає на його результат. Дочірній потік отримує свої вхідні дані як input.*.
logoutПише один рядок у виконання, так само як вузол налагодження в Node-RED. Поле вміщує 1000 символів; у виконання потрапляють перші 200.
note—Текст на полотні. Він не має портів і ніколи не проходиться, тож і у виконанні ніколи не зʼявляється.
end—Завершує цю гілку й каже, чим скінчилося виконання: успіхом, невдачею або пропуском для сервера, до якого цей потік не звертався. Його супроводжує повідомлення щонайбільше на 280 символів.
Вузол action і вузол http мають вихід error з тієї самої причини: вони стосуються когось іншого, агента або чужого сервера, і лише той, хто малював потік, знає, чи невдача там є бідою.

Тригери

Пʼять моментів, і обраний каже не лише, коли потік виконується. Він каже також, які змінні існують, які пропонує вибирач і які платформа відмовляється зберігати. Шлях, який у той момент існувати не може, — це помилка під час збереження, а не порожній рядок посеред виконання.

Пʼять тригерів і те, що має кожен із них
ТригерКоли виконуєтьсяЩо є, а чого немає
server.provisionedОдин раз, одразу після того, як замовлення дало машину.Усе. Це єдиний момент, коли існує кожна група.
server.reinstalledПісля того, як перевстановлення наявної машини вдалося.Та сама машина, інший образ. Адреса не змінюється, а дата створення лишається початковою. Сьогодні спрацьовує лише для контейнерів; перевстановлення віртуальної машини завершує складова, яка не вміє відтворювати.
server.deletedЩойно вилучення прийнято, поки рядок ще можна прочитати.Усе, крім образу. Не лишилося нічого, звідки прочитати образ, і платформа його не вигадує: os просто відсутній.
manualНіколи сам собою. Ви запускаєте його з редактора через Inject.Наявна машина, яку ви вказуєте, плюс власний JSON як input. Тут також немає образу: що саме встановлено на машині, платформа згодом дізнатися не може.
webhookЩойно хтось чужий надсилає запит на власну URL.Жодної машини, тож ані тарифу, ані адреси, ані зʼєднання, ані агента. Лишаються обліковий запис, потік, надіслане тіло як input і сам запит як webhook.
Тариф підвішує до кожного з трьох серверних моментів щонайбільше один потік, тож provisioned, reinstalled і deleted несуть по одному й ніколи не список. Ручний або вебхуковий потік підвісити до тарифу взагалі не можна: жоден із двох не запускається замовленням, і саме для цього ці два й існують.

Змінні

Кожне значення, яке потік може прочитати, походить із однієї з цих груп. Вибирач у редакторі показує групи, що існують для обраного тригера, і більше нічого. Читати невідомий шлях — це помилка, а не порожнє значення: хибне припущення має бути гучним.

Групи змінних, коли вони існують і що містять
ГрупаІснує зЩо містить
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, потрапляє до запису виконання, а таємниці там робити нічого.
Заголовок і текст вузла notify завжди читаються як шаблон, без позначки. Це проза, і підставити в неї імʼя — увесь її сенс.

Погодження та цикли

Потік може зупинитися й чекати на людину, а також може проходити ті самі вузли не один раз. Ані те, ані інше не було можливе, доки запуск не можна було відкласти й пізніше розбудити; ця черга тепер є.

  • Вузол погодження зупиняє запуск, створює запит і сповіщає обліковий запис. Відповідь потребує окремого права, тож той, хто написав потік, не є автоматично тим, хто його затверджує.
  • Кожен запит несе термін і те, що станеться без відповіді: продовжити як погоджено, продовжити як відхилено або завершити запуск як такий, що не стосується. Четвертого варіанта немає, бо запуск, який чекає вічно, це запуск, про який більше ніхто не почує.
  • Для кожного проходить свій вихід циклу один раз на елемент списку. У циклі state.loop містить поточний елемент, його позицію та загальну кількість.
  • Ніщо ззовні циклу не може приєднуватися до вузлів усередині нього. Ці вузли виконуються щообертом, і сповіщення, приєднане до обох, писало б по одному повідомленню на оберт.
  • Крок погодження може також надсилати пошту. Вона надходить лише учасникам, які можуть вирішувати щодо погоджень, а не всім, хто бачить потоки; сповіщення в панелі записується в будь-якому разі.
Кожен цикл несе жорстку межу кількості обертів, а запуск межу кількості кроків. Понад межу запуск зупиняється з помилкою замість того, щоб мовчки зробити частину роботи: потік, який пройшов сто з тисячі елементів і нічого не сказав, гірший за той, що зазнав невдачі.

Очікування та потоки, що викликають потоки

Запуск, що стоїть, — це не запуск, який зазнав невдачі. Відкласти його можуть три речі, і всі три користуються однією чергою: погодження, довга пауза та підпотік, дочірній запуск якого сам чекає.

  • Пауза до півхвилини просто чекає всередині запиту, який її розпочав, і саме цього ви хочете, коли даєте агентові трохи часу. Усе довше відкладає запуск, тож замовлення, яке його розпочало, завершується одразу, а решта потоку йде пізніше.
  • Підпотік виконує інший потік цього облікового запису як один крок. Його результат визначає вихід: дочірній запуск, який удався або не знайшов роботи, продовжує через OK, а невдалий — через «Помилка». Стан, запуск і назва потоку є в state.subflow.
  • Потік ніколи не має досягати сам себе — ні напряму, ні через інший потік. Це перевіряють під час розгортання, і повідомлення називає знайдений ланцюг.
  • Потоки можуть викликати один одного щонайбільше на три рівні. Оскільки потоки редагують окремо, цю межу перевіряють двічі: під час розгортання і поки запуск справді триває.
Дочірній запуск, що спинився на погодженні, спиняє й батьківський, а сторінка кожного з них посилається на інший. Поки запуск чекає, нічого не втрачається: половину обходу збережено, і він продовжується саме з тим графом, з якого починався.

Вебхуки

Точка входу вебхука дає зовнішній системі власну URL. Та система надсилає JSON, потік за URL виконується, а відповідь — голий код стану. Точки входу живуть у розділі Скрипти, на вкладці вебхуків, і є окремими обʼєктами: та сама точка входу може вказувати на інший потік, а відправник цього й не помітить.

  1. Створіть точку входу й дайте їй назву, яку впізнаєте згодом. URL створюється сама й вибору не підлягає: 32 випадкові символи, тобто 160 бітів, тож вгадування — не стратегія.
  2. Оберіть, як відправник підтверджує себе, і скопіюйте таємницю. Її показують один раз і більше ніколи; якщо вона загубилася, ви створюєте нову, а разом із нею отримуєте й нову URL.
  3. Спрямуйте точку входу на потік, тригером якого є вебхук. Точка входу може існувати раніше за потік, і доти запит приймається й отримує 202, який нічого не запускає. Саме в такому порядку люди це й будують насправді, тож помилкою це не вважають.
Три способи для відправника підтвердити себе
СхемаЩо вона робить
noneЖодного доказу: хто знає URL, той може запустити потік. Захисне рішення поруч зі списком адрес і важко захисне без нього.
hmac_sha256Відправник підписує неопрацьоване тіло разом із позначкою часу. Саме це варто обрати: воно привʼязує запит до власного тіла, тож перехоплений запит не вийде змінити й надіслати далі.
bearerВідправник кладе спільний ключ у заголовок Authorization. Просто, і про тіло, з яким він прийшов, це нічого не каже.

Підпис — це слово sha256, знак рівності й HMAC-SHA256 саме над байтами позначки часу, крапки й тіла, малими шістнадцятковими цифрами. Він іде в X-Provibr-Signature, а сама позначка часу йде в X-Provibr-Timestamp, цілими секундами від епохи.

Запит, чия позначка часу старша за 300 секунд або лежить у майбутньому, відхиляється з 401. Це вікно — справжнє правило, а не оздоба, бо позначка часу міститься всередині підписаного матеріалу: перехоплений запит не вийде надіслати завтра, наліпивши поверх свіжу позначку.

Підписати запит — це один рядок openssl. Цей приклад надсилає невеликий обʼєкт; текст для термінала навмисне лишається англійським, щоб збігатися з тим, що показує ваш термінал.

shell
# 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"
Що приймає точка входу
МежаПодробиці
body64 КіБ типово, налаштовується від 1 КіБ до 256 КіБ. Більший запит обрізається, поки ще надходить, а не читається повністю й лише потім відхиляється.
rate60 запитів на хвилину типово, налаштовується від 1 до 600. Лік ведеться на точку входу, а не на відправника, бо справжнє джерело має одну адресу, а нападник — тисячу.
payloadОбʼєкт JSON одного рівня. Кожен ключ стає input із тим ключем; вкладений обʼєкт відхиляється, а не сплощується.
allowlistЩонайбільше 20 адрес або діапазонів, у v4 чи v6. Порожньо означає жодного обмеження.
endpointsЩонайбільше 50 точок входу на обліковий запис.
Що означає кожна відповідь
КодЗначення
202Прийнято. Або виконання почалося, або запускати не було чого: потік ще не привʼязаний, потік вимкнений чи саме виконання впало. У всіх чотирьох випадках відправник нічого поганого не зробив, а квитанція каже, який саме з чотирьох це був.
401Підпису чи ключа немає або він не збігається, чи підпис збігається, а його позначка часу випадає з вікна.
403Точка входу вимкнена, або адреса джерела не значиться у списку.
404Точки входу з цим позначенням немає.
410Точку входу відкликано. Позначення лишається зайнятим назавжди, і ця відповідь каже чесному джерелу, що йому потрібна нова URL, чого 404 не зробив би.
413Тіло більше, ніж приймає ця точка входу.
422Тіло не є обʼєктом JSON одного рівня.
429Понад дозволений потік запитів для цієї точки входу.

Кожен запит лишає квитанцію, прийнятий він чи ні: наслідок, повернутий стан, адресу джерела повністю й скільки байтів справді прочитано. Тіло не зберігається ніколи. Квитанції зникають за 90 днів, раніше за самі виконання, бо адреса джерела — це персональні дані того, хто нашим клієнтом не є.

Вимкнути точку входу — не те саме, що відкликати її. Вимкнена відповідає 403 і її можна ввімкнути знову; відкликана відповідає 410 назавжди, і URL більше ніколи не видається.

Редакції та виконання

Два схожі питання мають тут дві різні відповіді. Хто що і коли змінив — це редакція. Що саме пройшло це конкретне виконання — це копія, збережена на самому виконанні. Знімок не може відповісти на перше питання, а редакція — на друге, тож існують обидва.

  • Кожна публікація пише редакцію, зокрема й публікація, яка нічого не змінила. Номер зростає для кожного потоку й ніколи не використовується вдруге.
  • Різниця між двома редакціями — це читабельний список, а не сирий JSON: доданий, прибраний або змінений вузол із названими полями, доданий чи прибраний дріт. Те, де вузол стоїть на полотні, зміною не є.
  • Відновлення нічого не відмотує. Воно записує старе креслення як нову редакцію поверх історії, з приміткою, звідки воно взялося.
  • Кожне виконання зберігає креслення, яке воно пройшло. Зміна потоку згодом ніколи не переписує того, що зробило давніше виконання.
  • Виконання містить рядок на кожен відвіданий вузол, із наслідком і виходом, через який воно пішло, і рядок на кожен невідвіданий вузол із причиною. Невідвіданий — це факт, який варто записати, а не порожнє місце.
  • Список виконань фільтрується за тригером, станом і редакцією та вивантажується у CSV. Вивантаження спиняється на 5000 рядках і каже про це всередині файлу, а не обривається мовчки.

Шаблони скриптів тримають поряд власну історію: кожну збережену версію вмісту й порядкову різницю між будь-якими двома з них.

Запуск, що доходить до погодження, відкладається: обхід зберігається, запуск переходить в очікування, а робітник продовжує його, щойно хтось вирішить або завершиться термін. Решта, як і раніше, проходиться в межах запиту, що його розпочав, і тому пауза сягає пʼяти хвилин.