CLI - Command Line Interface
CLI - сиэлай, кли, сли, слай, слаи, консоль, терминал, командная строка. Этому механизму уже лет 60. И он никуда не делся. Он живее всех живых - где-то для отладки, где-то для эксплуатации, зачастую для конфигурации и даже для ежедневной работы.
На компьютерах, серверах, виртуальных машинах, коммутаторах, маршрутизаторах, фаерволах, АТС, базовых станциях. Трудно найти такое оборудование, где нет CLI, пусть даже хорошо спрятанного.
И в этом его сила - 100% функциональности на 100% сетевых устройств можно настроить через CLI. Ладно 99,9% - придётся выкинуть некоторое альтернативное оборудование.
Это породило миллионы строк кода на Perl, PHP, Python, Go, Ruby, развесистые джинджа-шаблоны и по 300 экспектов в каждом скрипте.
И дало работу тысячам кодеров, выросших из сетевиков и админов.
Вот уже лет 30, а то и больше мы старательно пишем скрипты, которые с той или иной степенью успеха прикидываются человеком перед сетевой коробкой.
И ещё долго мы не останемся без дела - выпускают всё новые версии софта, ещё более другие модели железа, постоянно меняется CLI, и там, где вчера был string, завтра будет integer. И там, где вчера было no some shitty service enable
, завтра будет some shitty service disable
. И там, где вчера на вопрос интерфейса надо было ответить yes
, завтра вылезет ошибка.
Клянусь, это увлекательное путешествие продлится ещё десятилетия.
А чем же оно увлекательно?
- Модели конфигурации не формализованы
- Модель и поведение не зафиксированы
- CLI интерактивен
- Формат данных не структурированный
- Нет явного признака успешности операции
- Сложно вычислять разницу между целевой и текущей конфигурацией
- Сложно считать конфигурационный патч
- Транзакционность не всегда доступна
- Поддержание целевого состояния – задача инженера
Выше 9 смертных грехов CLI, которые обусловили рождение моделей данных конфигурации, языков их описания, протоколов, как SNMP, NETCONF и gNMI.
Если всё по каждому из них понятно, просто пропускайте следующую секцию.
9 грехов CLI
1. Модели конфигурации не формализованы
Есть такое? Есть такое.
Как мы узнаём, какие команды с какими аргументами в каком порядке надо дать?
Правильно - идём в Command reference guide на сайте производителя и дальше методом проб и ошибок разбираемся в терминале. Или в обратном порядке. Но эти два способа (и ещё помощь друга) - это то, как мы узнаём модель данных конфигурации.
И скажем так: она наверняка есть - ведь каждый раз одна и та же команда приводит к одному и тому же результату (правда ведь? Правда?)
Знаем как настраивать интерфейсы, знаем как они должны называться, где будет IPv4, а где IPv6 адреса? Если мы введём что-то неправильно, CLI ругнётся, но мы не отправим OS в kernel panic или ASIC в рестарт?
Просто эта модель не формализована. Или по крайней мере нам об этом не говорят.
И да, своим естественным интеллектом мы рано или поздно такую модель в своей голове выстраиваем и научаемся ею пользоваться.
Но для того, чтобы написать код, нам придётся её хорошо или плохо самим формализовать - иерархия, порядок ввода команд, последовательность аргументов, типы значений. И скорее плохо, конечно.
2. Модель и поведение не зафиксированы
Всё, что мы изучили на предыдущем этапе, может поменяться в новой версии - и мы сначала переобучаем себя, потом переписываем код.
3. CLI интерактивен
expect("Вы точно хотите выключить bgp-сессию, mpls на всей коробке [Y/n]?"] Yes!
expect("Вы точно хотите выключить электричество в серверной [Y/n]?"] No!
4. Формат данных не структурированный
Мы засылаем туда неструктурированный текст.
Мы получаем оттуда неструктурированный текст.
Мы его крафтим, мы его парсим. Мы пишем jinja-шаблоны и regexp’ы. Мы прожигаем свою жизнь.
Лучше json’ы перекладывать.
Строго говоря, будь-то json или вывод show version
, в итоге это всё равно поток байтов и по сути текст. Только в одном случае в нём есть структура, а в другом - это просто набор символов.
5. Нет явного признака успешности операции
Вывод CLI не означает ни успех, ни провал.
Warning ещё не означает, что что-то пошло не так.
Отсутствие вывода - ещё не признак успешности.
6. Сложно вычислять разницу между целевой и текущей конфигурацией
Казалось бы нужно просто подифать два текста.
Вот только в этих текстах имеет значение, порядок строк.
Одна и та же конфигурация может быть (и будет) разной для разных версий ПО.
Различающийся же регистр, напротив, может ничего не значить в одном месте, а в другом значить.
Одна и та же команда, в разных контекстах может означать разное (выключите MPLS на интерфейсе или в глобальном режиме - посмотрите на последствия).
Даже IPv6-адреса могут быть записаны в сокращённом или полном виде.
7. Сложно считать конфигурационный патч
Как следствие предыдущего пункта - выяснить, какие команды нужно применить - тоже нетривиально.
Но не только это.
Дело в том, что нужно уметь не только правильно добавлять, но и правильно удалять - а способов - не один и не два. Обратная команда не всегда формируется как отрицание прямой. Часто нужны не все её параметры.
В каком порядке отменять - и не поломает ли это чего-то ещё?
Даже не всегда команды после применения выглядят так же, как их применяли.
8. Транзакционность не всегда доступна
В целом мы уже избалованы коммитами - многие вендоры его поддерживают. Но многие ещё нет. А те, кто поддерживает, может это делать тоже собственным уникальным способом, как например валидация ввода только при коммите, или коммит заключается в последовательном применении всех команд без вычисления дельты.
9. Поддержание целевого состояния – задача инженера
Ооо, это самое интересное - а как собственно привести конфигурацию к тому состоянию, которое мы желаем увидеть, а не просто применить новую конфигу?
Кто и как должен посчитать конфигурационный патч, применить только его и проверить за собой, что рантайм соответствует эталону?
Но тут стоит быть чуть более честным - не всегда CLI настолько плох. Некоторые вендоры генерируют CLI-интерфейс из YANG-модели, что гарантирует чёткое соответствие между тем, что и как конфигурируется через CLI или любые другие интерфейсы.
Например, в Nokia SR Linux интерфейс командной строки, а так же gNMI, JSON-RPC и внутренние приложения работают с единым API - mgmt_srv - поэтому не только формализованы из одной и той же YANG-модели, но и имеют одинаковые возможности по чтению/записи конфигурации.
Дифы, коммиты, датасторы и прочее, тоже могут быть сделаны с умом - как у той же Nokia или у Juniper.
Но это всё, конечно, не отменяет факта работы с неструктурированным текстом.
Этого всего, как мне кажется, достаточно для того, чтобы даже не приступать к написанию полноценной системы автоматизации, основанной на CLI.
Далее был опыт с SNMP и всеми связанными протоколами (приглашаю пройти в
пятую часть книги).
Признаем его удачным лишь по той простой причине, что он позволил сформулировать требования к новым интерфейсам и протоколам.
Не исчерпывающий список можно сформулировать так:
- Представление данных в структурированном виде,
- Разделение конфигурационных и операционных данных,
- Читаемость для человека исходных данных и самой конфигурации,
- Воспроизводимость - задачу на исходных данных можно запустить повторно - проиграть,
- Механизм основан на формальных моделях,
- Транзакционность изменений и их откат,
- Поддержание целевого состояния.
Не все они появились сразу. Не все они появились. Но это понятная и приятная цель.
И на замену SNMP, в подмогу CLI зародился NETCONF, эксплуатирующий идею RPC - Remote Procedure Call.
Что за RPC, какое у него отношение с API вы так же можете узнать из пятой части.
Ну, только если коротко.