# Настройка переноса конфигураций между контурами GlobalERP

Документ описывает настройку автоматического переноса конфигураций между контурами GlobalERP через GitLab. Процесс включает действия в двух системах: в GlobalERP и в GitLab. Репозиторий в GitLab выступает в роли пайплайна: после выгрузки конфигурации из исходного контура запускается автоматическая валидация и установка на целевой контур.

## Настройка в системе GlobalERP

Для работы механизма выполните подготовительные действия на исходном и целевом контурах.

### Создание технических пользователей

На каждом контуре создайте отдельную техническую учётную запись для операций выгрузки и загрузки конфигураций.

1. Откройте приложение `Администратор > Доступ > Пользователи`.
2. Создайте пользователя с типом **Технический пользователь**.
3. Назначьте пользователю роль с доступом к функционалу менеджера конфигураций.

Для корректной работы в роли настройте права:

4. Перейдите в карточку роли → закладка **Права роли**.
5. В списке бизнес-объектов найдите `Btk_ConfigManagerAvi`. Чтобы объект отобразился, отключите фильтр **Только объекты, на которые у роли имеются права**.
6. Назначьте права:
   - **Чтение**, **Редактирование**, **Добавление**;
   - все доступные **объектные права**.
7. На закладке **Серверные полномочия** той же роли предоставьте полный доступ к REST-пакету `Btk_ConfigManagerRestPkg`.

### Конфигурация исходного контура (отправителя)

На контуре-отправителе настройте подключение к целевому контуру.

1. Откройте приложение `Настройки системы > Настройки и сервисы > Управление конфигурацией > Настройки удалённых контуров`.
2. Создайте новую запись с параметрами:

| Параметр | Рекомендуемое значение | Примечание |
|----------|------------------------|------------|
| Код | `to-<наименование целевого контура>` | Уникальный идентификатор |
| Наименование | `Отправка на <наименование целевого контура>` | Произвольное, но понятное |
| Url | Адрес Git-репозитория, заканчивающийся на `.git` | Создание репозитория описано далее |
| База данных | Наименование текущей БД | Обычно совпадает с именем контура |
| Пользователь | Логин технического пользователя в GitLab | Используется для аутентификации |
| Пароль | Зашифрованное значение пароля | См. ниже |
| Тип передачи | `Система контроля версий` | Обязательное значение |

```{note}
**Как зашифровать пароль**: используйте функцию `Сервис > Настройки и сервисы > Дополнительно > Шифрование данных`. Полученное значение вставьте в поле **Пароль**.
```
Заполните дополнительные характеристики:

3. **URL контура** — базовый адрес целевого контура GlobalERP.
4. **Git Email** — электронный адрес пользователя Git с доступом к репозиторию.
5. **Наименование целевого контура** — должно в точности совпадать с кодом аналогичной настройки `Настройки удалённых контуров`, созданной на целевом контуре.

### Конфигурация целевого контура (получателя)

Настройте целевой контур через раздел `Настройки удалённых контуров`. Создайте запись с отличиями:

| Параметр | Рекомендуемое значение |
|----------|------------------------|
| Код | `from-<наименование исходного контура>` |
| Наименование | `Получение из <наименование исходного контура>` |
| Url | Тот же Git-репозиторий, что и на исходном контуре |
| Пользователь / Пароль / Тип передачи | Настроены идентично |

Дополнительные характеристики:

6. **URL контура** — базовый адрес исходного контура.
7. **Git Email** — тот же email, что и на исходном контуре.
8. **Наименование целевого контура** — должно совпадать с кодом настройки на исходном контуре (например, `to-prod`).

```{important}
Значения **Наименование целевого контура** на обоих контурах должны быть согласованы — это обеспечивает корректную маршрутизацию в пайплайне.
```

## Настройка среды GitLab

Оркестрация переноса осуществляется средствами CI/CD в GitLab. Настройте раннер, репозиторий, токен и переменные.

### Настройка раннера

1. Разверните и зарегистрируйте **instance runner** в вашем инстансе GitLab.
2. Убедитесь, что раннер поддерживает Python 3.9+.
3. Установите необходимые библиотеки Python:

<!-- Начало кода -->
```bash
pip3 install pyyaml requests
```
<!-- Конец кода -->

4. Назначьте раннеру уникальный тег, например: `config_manager`, для привязки задач CI/CD в репозиториях оркестрации.

### Подготовка репозитория

1. Создайте новый пустой проект в GitLab.
2. В корне репозитория разместите:
   - файл конфигурации CI/CD (`.gitlab-ci.yml`);
   - файл с исполняемым Python-скриптом (`config_manager.py`);
   - набор служебных директорий.

Основной файл пайплайна — `.gitlab-ci.yml`. Его содержимое задаёт последовательность стадий и операций. В разделе `tags` каждого **job** укажите тег, соответствующий настройкам раннера (`config_manager`).

#### Файл .gitlab-ci.yml

<!-- Начало кода -->
```yaml
stages:
  - deploy

variables:
  # Авторизационные данные от целевого контура
  TARGET_USERNAME: $TARGET_USERNAME
  TARGET_PASSWORD: $TARGET_PASSWORD
  # Авторизационные данные от исходного контура
  ORIGINAL_USERNAME: $ORIGINAL_USERNAME
  ORIGINAL_PASSWORD: $ORIGINAL_PASSWORD

# Валидация метаданных на целевом контуре
validate_meta_data:
  tags:
    - config_manager
  stage: deploy
  only:
    changes:
      # Обрабатываем коммиты только в папке с информацией о метаданных
      - "validationMetaData/**/*"
  script:
    - rm -rf ${REPO_NAME}
    - git clone https://oauth2:${PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git ${REPO_NAME}
    - git config --global user.email "config-manager-bot@email.com"
    - git config --global user.name "**Config Manager Bot**"
    - cd ${REPO_NAME}
    - python3 config_manager.py "validationMetaData/${CI_COMMIT_TITLE}.yaml" "${TARGET_USERNAME}" "${TARGET_PASSWORD}"
    - cd ..
    - rm -rf ${REPO_NAME}
  variables:
    REPO_NAME: "validate_meta_data_repo"

# Отправка отчёта об валидации метаданных на исходный контур
send_meta_data_report:
  tags:
    - config_manager
  stage: deploy
  only:
    changes:
      - "sendMetaDataReport/**/*"
  script:
    - rm -rf ${REPO_NAME}
    - git clone https://oauth2:${PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git ${REPO_NAME}
    - git config --global user.email "config-manager-bot@email.com"
    - git config --global user.name "**Config Manager Bot**"
    - cd ${REPO_NAME}
    - python3 config_manager.py "sendMetaDataReport/${CI_COMMIT_TITLE}.yaml" "${ORIGINAL_USERNAME}" "${ORIGINAL_PASSWORD}"
    - cd ..
    - rm -rf ${REPO_NAME}
  variables:
    REPO_NAME: "install_config_repo"

# Установка конфигурации на целевой контур
install_config:
  tags:
    - config_manager
  stage: deploy
  only:
    changes:
      - "installConfig/**/*"
  script:
    - rm -rf ${REPO_NAME}
    - git clone https://oauth2:${PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git ${REPO_NAME}
    - git config --global user.email "config-manager-bot@email.com"
    - git config --global user.name "**Config Manager Bot**"
    - cd ${REPO_NAME}
    - python3 config_manager.py "installConfig/${CI_COMMIT_TITLE}.yaml" "${TARGET_USERNAME}" "${TARGET_PASSWORD}"
    - cd ..
    - rm -rf ${REPO_NAME}
  variables:
    REPO_NAME: "install_config_repo"

# Отправка отчёта на исходный контур об установке конфигурации
send_install_report:
  tags:
    - config_manager
  stage: deploy
  only:
    changes:
      - "sendInstallReport/**/*"
  script:
    - rm -rf ${REPO_NAME}
    - git clone https://oauth2:${PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git ${REPO_NAME}
    - git config --global user.email "config-manager-bot@email.com"
    - git config --global user.name "**Config Manager Bot**"
    - cd ${REPO_NAME}
    - python3 config_manager.py "sendInstallReport/${CI_COMMIT_TITLE}.yaml" "${ORIGINAL_USERNAME}" "${ORIGINAL_PASSWORD}"
    - cd ..
    - rm -rf ${REPO_NAME}
  variables:
    REPO_NAME: "send_install_report_repo"
```
<!-- Конец кода -->

#### Скрипт config_manager.py

<!-- Начало кода -->
```python
import yaml
import sys
import requests
from requests.auth import HTTPBasicAuth

def main():
    if len(sys.argv) != 4:
        print("Error: Переданы не все параметры, убедитесь в правильности .gitlab-ci.yml")
        sys.exit(1)
    
    file_path = sys.argv[1]
    username = sys.argv[2]
    password = sys.argv[3]
    
    try:
        # Читаем YAML файл
        with open(file_path, 'r') as file:
            yaml_data = yaml.safe_load(file)
        
        # Параметры
        link_circuit = yaml_data.get('linkCircuit')
        name_base_circuit = yaml_data.get('nameBaseCircuit')
        file_name = yaml_data.get('fileName')
        uuid = yaml_data.get("sUUID")
        id_user = yaml_data.get("idUser")
        
        # POST запрос на контур
        response = requests.post(
            link_circuit,
            data={
                'sFileName': file_name,
                'sBaseCircuit': name_base_circuit,
                'sUUID': uuid,
                'idUser': id_user
            },
            auth=HTTPBasicAuth(username, password)
        )
        
        print(f"Response status code: {response.status_code}")
        print(f"Response text: {response.text}")
        
        if response.status_code != 200:
            sys.exit(1)
            
    except Exception as e:
        print(f"Error: {str(e)}")
        sys.exit(1)

if __name__ == "__main__":
    main()
```
<!-- Конец кода -->

### Служебные директории

Создайте в корне репозитория папки:

- `validationMetaData`;
- `sendMetaDataReport`;
- `installConfig`;
- `sendInstallReport`.

Поскольку Git не отслеживает пустые каталоги, поместите в каждую из них пустой файл `.gitkeep`.

### Создание токена доступа

Для взаимодействия пайплайна с репозиторием создайте токен доступа:

1. Перейдите в настройки проекта: `Settings > Access Tokens > Add new token`.
2. Укажите имя, например: `config_manager_token`.
3. Выберите срок действия и область видимости (scope).
4. Назначьте минимально необходимые права:
   - `read_repository`;
   - `write_repository`;
   - `api`.
5. Сохраните токен — он понадобится на следующем шаге.

### Настройка переменных CI/CD

Для безопасной передачи учётных данных в задания пайплайна используйте защищённые переменные. Добавьте их в разделе `Settings > CI/CD > Variables`. Для каждой переменной:

- установите **Visibility** в значение **Masked**;
- в **Flags** выберите только **Expand variable reference**.

Создайте переменные:

| Переменная | Описание |
|------------|----------|
| `ORIGINAL_USERNAME` | Логин технического пользователя на исходном контуре |
| `ORIGINAL_PASSWORD` | Пароль технического пользователя на исходном контуре |
| `TARGET_USERNAME` | Логин технического пользователя на целевом контуре |
| `TARGET_PASSWORD` | Пароль технического пользователя на целевом контуре |
| `PUSH_TOKEN` | Токен для работы с репозиторием |

## Завершение настройки

После завершения настройки пользователь инициирует перенос конфигурации в интерфейсе GlobalERP. Система автоматически взаимодействует с GitLab-репозиторием, который последовательно выполняет этапы валидации и установки на удалённых контурах.