# Модель архитектуры в нотации ArchiMate Модель технологического слоя типового контура платформы. **Все данные, зависящие от конкретной инсталляции — имя кластера, узлы, домены, реестр — заменены на примеры.** Реальные значения в репозиторий не попадают: они задаются профилем контура, который держится отдельно. Прикладной слой представлен потребителями технологических сервисов и межсервисными вызовами. Бизнес-слой будет добавлен отдельно. ## Файлы | Файл | Формат | Чем открывать | |---|---|---| | `example-technology.archimate` | нативный формат [Archi](https://www.archimatetool.com/) | десктопный Archi: File → Open | | `example-technology.xml` | The Open Group ArchiMate Model Exchange File Format 3.1 | любой инструмент с импортом Open Exchange, в том числе archi-online.com: **Import, save, and create models** → Open Exchange | | `preview.html` | SVG-рендер всех представлений | любой браузер, без установки чего-либо | | `matrix.example.json` | снимок матрицы «приложение → технологический сервис» | вход для сборки | | `calls.example.json` | снимок графа межсервисных вызовов | вход для сборки | | `app-summaries.md` | короткие описания компонентов прикладного слоя (1–3 предложения) | вход для сборки; попадает в поле `Documentation` модели | | `app-docs.md` | развёрнутые описания тех же компонентов | справочник; в модель по умолчанию не идёт | 91 элемент, 369 отношений, 40 представлений. | Представление | Что показывает | |---|---| | L1 | Легенда нотации: что означает каждый тип элемента и каждый тип линии. Собрана из настоящих элементов модели — заодно разобранный пример | | T1 | Кластер, ПО внутри него, внешние узлы, технологические сервисы. Без приложений — обзорная схема | | T2 | Развёртывание по узлам: какая группа узлов какие компоненты несёт | | T3 | Внешние интеграции: чем контур связан с инфраструктурой заказчика — каталог предприятия, брокер идентификации, служба федерации, почтовый релей | | T4–T13 | По одному представлению на технологический сервис: кто им пользуется | | A0 | Карта прикладного слоя: все компоненты по смысловым группам, без связей | | A1 | Ядро прикладного слоя: восемь самых связанных сервисов и вызовы между ними | | A2–A12 | По представлению на сервис с тремя и более потребителями: кто от него зависит | | P1–P13 | Паспорт сервиса — зеркало к A2–A12: не «кто сломается без него», а «без чего не работает он сам» | Направление связи — как принято в ArchiMate: стрелка идёт от вызываемого к вызывающему (serving). Читается как «кого лишишься — тот и сломается». Тот же вопрос с другой стороны — представления P: что нужно самому сервису, чтобы работать. Разбиение по сервисам сделано осознанно: 152 связи «технологический сервис → приложение» и 86 межсервисных вызовов на одной схеме нечитаемы. В модели они лежат одним набором, представления — это срезы. Метамодель намеренно урезана. Технологический слой: `Node`, `SystemSoftware`, `TechnologyService`, `Artifact`. Прикладной: `ApplicationComponent`. Смысловая группировка: `Grouping`. Отношения: `Composition`, `Aggregation`, `Realization`, `Serving`, `Assignment`. Не используются `Device`, `Path`, `CommunicationNetwork`, `TechnologyFunction` — они не несут информации на этом уровне. ## Как собрать модель для реального контура 1. Снять с нужного кластера матрицу использования технологических сервисов и граф межсервисных вызовов: ``` py scan_contour.py <имя-кластера> matrix.json py scan_calls.py <имя-кластера> calls.json ``` 2. Скопировать `contour-profile.example.json`, подставить настоящие имена кластера, узлов, доменов и реестра. **Копию хранить вне репозитория.** 3. Собрать модель и производные форматы: ``` py build_archimate.py <профиль.json> matrix.json out.archimate calls.json app-summaries.md py to_open_exchange.py out.archimate out.xml py render_preview.py out.archimate out.html ``` Аргументы после имени выходного файла необязательны и распознаются по расширению: `.json` — граф вызовов (без него собирается только технологический слой), `.md` — описания компонентов (без них у компонентов остаётся путь к манифестам). Файлов с описаниями можно передать несколько, каждый следующий переопределяет предыдущий по совпадающим заголовкам: `app-docs.md app-summaries.md` даст короткие описания там, где они есть, и развёрнутые для остальных. Результат шага 3 в репозиторий не коммитить — он содержит данные контура. ## Откуда взяты связи Не нарисованы от руки, а выведены из манифестов, поэтому проверяемы. | Связь | Источник | |---|---| | Состав кластера, версии чартов | `clusters/<контур>/kustomization.yaml`, `infrastructure//base/helmrelease.yaml` | | Приложение → PostgreSQL | env `POSTGRES_*`, `DB__HOST` или путь Vault `secrets/data/apps//postgres` | | Приложение → RabbitMQ | env `RABBITMQ*`, `AMQP__*` | | Приложение → Kafka | env `KAFKA*`, `BOOTSTRAP_SERVERS` | | Приложение → S3 | env `S3__*`, `S3_ENDPOINT`, `S3_ACCESS`, `S3_BUCKET` | | Приложение → Redis | env `REDIS_HOST`, `REDIS__*` | | Приложение → Vault | аннотации `vault.hashicorp.com/agent-inject*` | | Приложение → Zitadel | env `ZITADEL*`, `JWKS`, `OIDC`, секрет `jwt-public` | | Приложение → почтовый релей | env `SMTP_*_HOST`, `SMTP__HOST`, `FROM_EMAIL`, `EMAIL_FROM` | | Приложение → Istio | `service:` в маршрутах `infrastructure/istio-config/<контур>/istio-config.yaml` (закомментированные не считаются) | | Приложение → приложение | адрес `<сервис>.` в манифестах вызывающего; либо переменная `_URL` / `_HOST` / `_BASE_URL` / `_ENDPOINT` | Сканируются `*.yaml` в `apps//base/` и `apps//<контур>/`. Для матрицы технологических сервисов документация `*.md` служит вторым источником, для графа вызовов — `*ENDPOINTS.md` и `*CONFIGURATION.md`. Две поправки, без которых граф вызовов врёт: - **суффикс контура в namespace.** Адреса встречаются в формах `documentations`, `documentations-prod`, `bim-api`; без нормализации связь теряется, а короткая форма `<сервис>.` без `.svc.cluster.local` не распознаётся вовсе. - **инфраструктурный сегмент в имени переменной.** `DJANGO_POSTGRES_HOST` и `ISSUES_DB_HOST` адресуют базу данных чужого сервиса, а не сам сервис. Это связь другого рода, и как вызов её показывать нельзя. `matrix.example.json` и `calls.example.json` — снимки. В них только имена приложений и флаги связей; идентификаторов контура нет. **Внешние интеграции — исключение: они из манифестов не выводятся.** В репозитории нет ни каталога предприятия, ни службы федерации, ни центра выдачи билетов — это инфраструктура заказчика, и в модель они попадают из профиля контура, блок `external`. Проверять их надо не грепом, а у того, кто разворачивает контур. Схем подключения каталога четыре, и в конкретной инсталляции работает одна: | Схема | Цепочка | Когда нужна | |---|---|---| | прямая | каталог → провайдер идентификации | каталог доступен по LDAPS и источник пользователей один | | с брокером | каталог → Keycloak → провайдер идентификации | источников несколько либо каталог опубликован по SAML | | с доменным входом | каталог + центр выдачи билетов → Keycloak → провайдер идентификации | нужен вход без повторного пароля для рабочих станций домена; проверку билета по SPNEGO умеет только брокер | | через федерацию | каталог → AD FS → провайдер идентификации | у заказчика уже есть федеративная служба как штатная точка входа | В представлении T3 показаны все четыре сразу — при сборке модели для конкретного контура лишние узлы из профиля убираются. Keycloak поставляется и чартом платформы (`infrastructure/keycloak`), поэтому брокер может стоять как у заказчика, так и внутри контура. **Группировка прикладного слоя по доменам — тоже не из манифестов.** В репозитории нет ничего, что относило бы приложение к «контролю качества» или «полевым данным»: это смысл, а не конфигурация. Группы заданы в профиле, блок `domains`, и сверены с доменной группировкой в [../apps/README.md](../apps/README.md). От контура к контуру они не меняются — в отличие от остального в профиле, это свойство продукта. Последняя группа с `"apps": "*"` собирает всё, что не попало в предыдущие: так новое приложение не исчезает с карты молча, а всплывает в группе «Не отнесено». Если группа пуста, в модель она не попадает. Описания компонентов в `app-docs.md` и `app-summaries.md` выведены не из этого репозитория, а из исходного кода компонентных репозиториев, и потому проверяются иначе — чтением кода, а не грепом по манифестам. Там, где доказательств не хватило, это сказано в самом описании; такие места стоит подтверждать у команды платформы, а не считать фактом. ## Про формат файлов Нативный `.archimate` нигде не стандартизирован, и его словарь неочевиден: объекты схем сериализуются как ``, соединения — через атрибут `relationship`. Имена EClass из метамодели (`DiagramModelArchimateObject`, `archimateRelationship`) в XML **не используются** — на них легко попасться, модель тогда открывается с пустыми представлениями. Эталон для сверки — любая модель из [archimatetool/ArchiModels](https://github.com/archimatetool/ArchiModels), созданная самим Archi. Пояснительные надписи на легенде — объекты `archimate:Note`: они принадлежат схеме, а не модели, поэтому в счёт элементов не идут и в других инструментах ничего не ломают. В обменном формате им соответствуют узлы `xsi:type="Label"`. `example-technology.xml` проверен на соответствие официальной схеме `archimate3_Diagram.xsd`. Если сторонний инструмент не берёт нативный формат, используйте его. Отличие обменной версии: вложенность узлов развёрнута в плоский список с абсолютными координатами (в обменном формате трактовка координат вложенного узла неоднозначна между реализациями). Визуально раскладка та же, но компоненты внутри кластера не будут его дочерними элементами. ## Скрипты Требуется Python 3, внешних зависимостей нет. На Windows запускать через `py`, а не `python`. | Скрипт | Назначение | |---|---| | `scan_contour.py` | матрица «приложение → технологический сервис» по кластеру | | `scan_calls.py` | граф межсервисных вызовов прикладного слоя | | `build_archimate.py` | сборка модели из профиля и матрицы | | `to_open_exchange.py` | конвертация в обменный формат | | `render_preview.py` | рендер представлений в HTML со встроенным SVG | **Внимание:** после ручной правки модели в Archi источником истины становится `.archimate`, а повторный запуск `build_archimate.py` затрёт расстановку элементов. Производные форматы (`to_open_exchange.py`, `render_preview.py`) пересобирать после каждой правки, иначе они разъедутся с моделью.